diff -u --recursive --new-file v2.4.1/linux/CREDITS linux/CREDITS
--- v2.4.1/linux/CREDITS	Sat Feb  3 19:51:21 2001
+++ linux/CREDITS	Fri Feb 16 17:15:23 2001
@@ -62,6 +62,15 @@
 S: B-2610 Wilrijk-Antwerpen
 S: Belgium
 
+N: Anton Altaparmakov
+E: aia21@cus.cam.ac.uk
+W: http://www-stu.christs.cam.ac.uk/~aia21/
+D: NTFS driver maintainer. NTFS fixes and cleanup.
+D: Tiny fixes in linear md device and emu10k1 driver.
+S: Christ's College
+S: Cambridge CB2 3BU
+S: United Kingdom
+
 N: C. Scott Ananian
 E: cananian@alumni.princeton.edu
 W: http://www.pdos.lcs.mit.edu/~cananian
@@ -83,6 +92,14 @@
 S: Salt Lake City, Utah 84120
 S: USA
 
+N: Michael Ang
+E: mang@subcarrier.org
+W: http://www.subcarrier.org/mang
+D: Linux/PA-RISC hacker
+S: 85 Frank St.
+S: Ottawa, Ontario
+S: Canada K2P 0X3
+
 N: H. Peter Anvin
 E: hpa@zytor.com
 W: http://www.zytor.com/~hpa/
@@ -161,6 +178,17 @@
 S: Milano
 S: Italy
 
+N: Paul Bame
+E: bame@debian.org
+E: bame@puffin.external.hp.com
+E: paul_bame@hp.com
+W: http://www.parisc-linux.org
+D: PA-RISC 32 and 64-bit early boot, firmware interface, interrupts, misc
+S: MS42
+S: Hewlett-Packard
+S: 3404 E Harmony Rd
+S: Fort Collins, CO 80525
+
 N: Arindam Banerji
 E: axb@cse.nd.edu
 D: Contributed ESDI driver routines needed to port LINUX to the PS/2 MCA.
@@ -375,6 +403,12 @@
 S: Pittsburgh, Pennsylvania 15213
 S: USA
 
+N: Ryan Bradetich
+E: rbradetich@uswest.net
+D: Linux/PA-RISC hacker
+S: 1200 Goldenrod Dr.
+S: Nampa, Idaho 83686
+
 N: Derrick J. Brashear
 E: shadow@dementia.org
 W: http://www.dementia.org/~shadow
@@ -606,6 +640,14 @@
 D: AX25-HOWTO, HAM-HOWTO, IPX-HOWTO, NET-2-HOWTO
 D: ax25-utils maintainer.
 
+N: Helge Deller
+E: deller@gmx.de
+E: hdeller@redhat.de
+D: PA-RISC Linux hacker, LASI-, ASP-, WAX-, LCD/LED-driver
+S: Schimmelsrain 1
+S: D-69231 Rauenberg
+S: Germany
+
 N: Peter Denison
 E: peterd@pnd-pc.demon.co.uk
 W: http://www.pnd-pc.demon.co.uk/promise/
@@ -957,11 +999,22 @@
 N: Hans Grobler
 E: grobh@sun.ac.za
 D: Various AX.25/ROSE/NETROM + hamradio driver patches
+D: Various X.25/LABP + driver patches
+D: Misc kernel fixes and updates
 S: Department of Electronic Engineering
 S: University of Stellenbosch
 S: Stellenbosch, Western Cape
 S: South Africa
 
+N: Grant Grundler
+E: grundler@puffin.external.hp.com
+W: http://www.grundler.net/
+W: http://obmouse.sourceforge.net/
+D: obmouse - rewrote Olivier Florent's Omnibook 600 "pop-up" mouse driver
+D: PA-RISC - IO Interrupt/PCI HBA/IO MMU author and architect
+S: Mountain View, California
+S: USA
+
 N: Grant Guenther
 E: grant@torque.net
 W: http://www.torque.net/linux-pp.html
@@ -1051,11 +1104,12 @@
 N: Jochen Hein
 E: jochen@jochen.org
 P: 1024/4A27F015 25 72 FB E3 85 9F DE 3B  CB 0A DA DA 40 77 05 6C
+P: 1024D/77D4FC9B F5C5 1C20 1DFC DEC3 3107  54A4 2332 ADFC 77D4 FC9B
 D: National Language Support
 D: Linux Internationalization Project
 D: German Localization for Linux and GNU software
-S: Frankenstraße 33
-S: 34131 Kassel
+S: Helenenstrasse 18
+S: 65183 Wiesbaden
 S: Germany
 
 N: Christoph Hellwig
@@ -1106,6 +1160,15 @@
 S: D - 72072 Tuebingen
 S: Germany
 
+N: Richard Hirst
+E: richard@sleepie.demon.co.uk
+E: rhirst@linuxcare.com
+W: http://www.sleepie.demon.co.uk/
+D: linux-m68k VME support
+D: PA-RISC port, scsi and network drivers
+D: 53c700/53c710 driver author, 82596 driver maintainer
+S: United Kingdom
+
 N: Jauder Ho
 E: jauderho@carumba.com
 W: http://www.carumba.com/
@@ -1182,6 +1245,19 @@
 S: Tabor 390 03
 S: Czech Republic
 
+N: David Huggins-Daines
+E: dhd@debian.org
+E: dhd@eradicator.org
+E: dhd@cepstral.com
+D: PA-RISC port
+D: Nubus subsystem
+D: Generic 68k Macintosh framebuffer driver
+D: STI framebuffer tweaks
+D: LTPC driver tweaks
+S: 110 S. 12th St., Apt. A
+S: Pittsburgh, PA 15203-1250
+S: USA
+
 N: Gareth Hughes
 E: gareth@valinux.com
 E: gareth@precisioninsight.com
@@ -1250,11 +1326,7 @@
 N: Niels Kristian Bech Jensen
 E: nkbj@image.dk
 W: http://www.image.dk/~nkbj
-D: 4.4BSD and NeXTstep filesystem support in the old ufs.
-D: Openstep filesystem and NeXTstep CDROM support in the new ufs.
-D: Replace CPU==[3-6]86 and __i386__ submodel flags by configuration options.
-D: Replace __SMP__ by CONFIG_SMP.
-D: Danish HOWTO, Linux+FreeBSD mini-HOWTO.
+D: Miscellaneous kernel updates and fixes.
 S: Dr. Holsts Vej 34, lejl. 164
 S: DK-8230 Åbyhøj
 S: Denmark
@@ -1736,6 +1808,14 @@
 D: XF86_8514
 D: cfdisk (curses based disk partitioning program)
 
+N: John S. Marvin
+E: jsm@fc.hp.com
+D: PA-RISC port
+S: Hewlett Packard
+S: MS 42
+S: 3404 E. Harmony Road
+S: Fort Collins, CO 80528
+
 N: Torben Mathiasen
 E: torben.mathiasen@compaq.com
 E: torben@kernel.dk
@@ -2086,6 +2166,16 @@
 D: implemented kmod
 D: modularized BSD Unix domain sockets
 
+N: Martin Kasper Petersen
+E: mkp@linuxcare.com
+E: mkp@mkp.net
+D: PA-RISC port
+D: XFS file system
+D: kiobuf based block I/O work
+S: 314 Frank St.
+S: Ottawa, Ontario
+S: Canada K2P 0X8
+
 N: Mikael Pettersson
 E: mikpe@csd.uu.se
 W: http://www.csd.uu.se/~mikpe/
@@ -2270,6 +2360,13 @@
 S: D-68789 St.Leon-Rot
 S: Germany
 
+N: Thiago Berlitz Rondon
+E: maluco@mileniumnet.com.br
+D: Miscellaneous kernel hacker
+S: R. Anhanguera, 1487 - Ipiranga
+S: 79080-740 - Campo Grande - Mato Grosso do Sul
+S: Brazil
+
 N: Stephen Rothwell
 E: sfr@linuxcare.com.au
 W: http://linuxcare.com.au/sfr
@@ -2597,7 +2694,7 @@
 S: Austria
 
 N: Jeff Tranter
-E: Jeff_Tranter@Mitel.COM
+E: tranter@pobox.com
 D: Enhancements to Joystick driver
 D: Author of Sound HOWTO and CD-ROM HOWTO
 D: Author of several small utilities
@@ -2871,6 +2968,12 @@
 S: 2135 CN Hoofddorp
 S: The Netherlands
 
+N: Matthew Wilcox
+E: matthew@wil.cx
+W: ftp://ftp.uk.linux.org/pub/linux/people/willy/
+D: Linux/PARISC hacker.  Filesystem hacker.  Random other hacking.  Custom
+D: PPC port hacking.
+
 N: G\"unter Windau
 E: gunter@mbfys.kun.nl
 D: Some bug fixes in the polling printer driver (lp.c)
@@ -2931,9 +3034,10 @@
 D: some Alpha platform porting from 2.0, Memory Technology Devices,
 D: Acquire watchdog timer, PC speaker driver maintenance,
 D: various other stuff that annoyed me by not working.
-S: c/o Red Hat UK Limited
-S: 35-36 Cambridge Place
-S: Cambridge. CB2 1NS
+S: c/o Red Hat Engineering
+S: Rustat House
+S: 60 Clifton Road
+S: Cambridge. CB1 7EG
 S: England
 
 N: Frank Xia
@@ -2955,8 +3059,8 @@
 W: http://www.andante.org
 D: General kernel hacker
 D: SCSI iso9660 and ELF
-S: 17 Canterbury Square #101
-S: Alexandria, Virginia 22304
+S: 6389 Hawk View Lane
+S: Alexandria, Virginia 22312
 S: USA
 
 N: Niibe Yutaka
diff -u --recursive --new-file v2.4.1/linux/Documentation/00-INDEX linux/Documentation/00-INDEX
--- v2.4.1/linux/Documentation/00-INDEX	Tue Nov 14 10:54:07 2000
+++ linux/Documentation/00-INDEX	Thu Feb  8 16:32:44 2001
@@ -1,8 +1,8 @@
+
 This is a brief list of all the files in ./linux/Documentation and what
 they contain. If you add a documentation file, please list it here in 
 alphabetical order as well, or risk being hunted down like a rabid dog. 
-Note that subdirectories have their own index files too. Please try and
-keep the descriptions small enough to fit on one line.
+Please try and keep the descriptions small enough to fit on one line.
 							 Thanks -- Paul G.
 
 00-INDEX
@@ -15,28 +15,40 @@
 	- how the boss likes the C code in the kernel to look.
 Configure.help
 	- text file that is used for help when you run "make config"
-IO-APIC.txt
-	- info on using the enhanced interrupt hardware on SMP boards.
+DMA-mapping.txt
+	- info for PCI drivers using DMA portably across all platforms.
+DocBook/
+	- directory with DocBook templates etc. for kernel documentation.
 IO-mapping.txt
 	- how to access I/O mapped memory from within device drivers.
+IRQ-affinity.txt
+	- how to select which CPU(s) handle which interrupt events on SMP.
+LVM-HOWTO
+	- info on setting up logical volume management (virtual disks etc.)
 README.DAC960
 	- info on Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
+README.moxa
+	- release notes for Moxa mutiport serial card.
+SubmittingDrivers
+	- procedure to get a new driver source included into the kernel tree.
+SubmittingPatches
+	- procedure to get a source patch included into the kernel tree.
 VGA-softcursor.txt
 	- how to change your VGA cursor from a blinking underscore.
 arm/
 	- directory with info about Linux on the ARM architecture.
-atm.txt
-	- info on Linux ATM support
 binfmt_misc.txt
 	- info on the kernel support for extra binary formats.
+cachetlb.txt
+	- describes the cache/TLB flushing interfaces Linux uses.
+cciss.txt
+	- info, major/minor #'s for Compaq's SMART Array Controllers.
 cdrom/
 	- directory with information on the CD-ROM drivers that Linux has.
 computone.txt
 	- info on Computone Intelliport II/Plus Multiport Serial Driver
 cpqarray.txt
 	- info on using Compaq's SMART2 Intelligent Disk Array Controllers.
-devices.tex
-	- LaTeX source listing of all the nodes in /dev/ with major minor #'s
 devices.txt
 	- plain ASCII listing of all the nodes in /dev/ with major minor #'s
 digiboard.txt
@@ -51,12 +63,20 @@
 	- directory with info on the frame buffer graphics abstraction layer.
 filesystems/
 	- directory with info on the various filesystems that Linux supports.
+floppy.txt
+	- notes and driver options for the floppy disk driver.
 ftape.txt
 	- notes about the floppy tape device driver
 hayes-esp.txt
 	- info on using the Hayes ESP serial driver.
+highuid.txt
+	- notes on the change from 16 bit to 32 bit user/group IDs.
+i2c/
+	- directory with info about the I2C bus/protocol (2 wire, kHz speed)
 i386/
-	- directory with info about Linux on the intel ix86 architecture.
+	- directory with info about Linux on intel 32 bit architecture.
+ia64/
+	- directory with info about Linux on intel 64 bit architecture.
 ide.txt
 	- important info for users of ATA devices (IDE/EIDE disks and CD-ROMS)
 initrd.txt
@@ -77,6 +97,8 @@
 	- info on using joystick devices (and driver) with Linux.
 kbuild/
 	- directory with info about the kernel build process
+kernel-doc-nano-HOWTO.txt
+	- mini HowTo on generation and location of kernel documentation files.
 kernel-docs.txt
 	- listing of various WWW + books that document kernel internals.
 kernel-parameters.txt
@@ -101,10 +123,14 @@
 	- info on boot arguments for the multiple devices driver
 memory.txt
 	- info on typical Linux memory problems.
+mkdev.cciss
+	- script to make /dev entries for SMART controllers (see cciss.txt)
 mkdev.ida
 	- script to make /dev entries for Intelligent Disk Array Controllers.
 modules.txt
 	- short guide on how to make kernel parts into loadable modules
+moxa-smartio
+	- info on installing/using Moxa multiport serial driver.
 mtrr.txt
 	- how to use PPro Memory Type Range Registers to increase performance
 nbd.txt
@@ -119,8 +145,12 @@
 	- how to decode those nasty internal kernel error dump messages.
 paride.txt
 	- information about the parallel port IDE subsystem.
+parisc/
+	- directory with info on using Linux on PA-RISC architecture.
 parport.txt
 	- how to use the parallel-port driver.
+parport-lowlevel.txt
+	- description and usage of the low level parallel port functions.
 pci.txt
 	- info on the PCI subsystem for device driver authors
 pcwd-watchdog.txt
@@ -129,14 +159,14 @@
 	- info on Linux power management support
 powerpc/
 	- directory with info on using Linux with the PowerPC.
-proc_usb_info.txt
-	- info on /proc/bus/usb direcory generated for USB devices
 ramdisk.txt
 	- short guide on how to set up and use the RAM disk.
 riscom8.txt
 	- notes on using the RISCom/8 multi-port serial driver.
 rtc.txt
 	- notes on how to use the Real Time Clock (aka CMOS clock) driver.
+s390/
+	- directory with info on using Linux on the IBM S390.
 scsi-generic.txt
 	- info on the sg driver for generic (non-disk/CD/tape) SCSI devices.
 scsi.txt
@@ -153,6 +183,8 @@
 	- a few more notes on symmetric multi-processing
 sound/
 	- directory with info on sound card support
+sparc/
+	- directory with info on using Linux on Sparc architecture.
 specialix.txt
 	- info on hardware/driver for specialix IO8+ multiport serial card.
 spinlocks.txt
@@ -167,8 +199,12 @@
 	- directory with info on the /proc/sys/* files
 sysrq.txt
 	- info on the magic SysRq key
+telephony/
+	- directory with info on telephony (e.g. voice over IP) support.
 unicode.txt
 	- info on the Unicode character/font mapping used in Linux.
+usb/
+	- directory with info regarding the Universal Serial Bus.
 video4linux/
 	- directory with info regarding video/TV/radio cards and linux.
 vm/
@@ -177,4 +213,6 @@
 	- how to auto-reboot Linux if it has "fallen and can't get up". ;-)
 xterm-linux.xpm
 	- XPM image of penguin logo (see logo.txt) sitting on an xterm.
+zorro.txt
+	- info on writing drivers for Zorro bus devices found on Amigas.
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/Changes linux/Documentation/Changes
--- v2.4.1/linux/Documentation/Changes	Sat Feb  3 19:51:21 2001
+++ linux/Documentation/Changes	Fri Feb 16 15:53:08 2001
@@ -31,7 +31,7 @@
 Eine deutsche Version dieser Datei finden Sie unter
 <http://www.stefan-winter.de/Changes-2.4.0.txt>.
 
-Last updated: December 11, 2000
+Last updated: January 11, 2001
 
 Chris Ricker (kaboom@gatech.edu or chris.ricker@genetics.utah.edu).
 
@@ -52,8 +52,9 @@
 o  Gnu make               3.77                    # make --version
 o  binutils               2.9.1.0.25              # ld -v
 o  util-linux             2.10o                   # fdformat --version
-o  modutils               2.4.0                   # insmod -V
-o  e2fsprogs              1.19                    # tune2fs --version
+o  modutils               2.4.2                   # insmod -V
+o  e2fsprogs              1.19                    # tune2fs
+o  reiserfsprogs          3.x.0b                  # reiserfsck 2>&1|grep reiserfsprogs
 o  pcmcia-cs              3.1.21                  # cardmgr -V
 o  PPP                    2.4.0                   # pppd --version
 o  isdn4k-utils           3.1pre1                 # isdnctrl 2>&1|grep version
@@ -99,11 +100,11 @@
 your kernel.  This change does, however, mean that you need a recent
 release of binutils.
 
-If you can, upgrade to the latest 2.9.5 binutils release.  Older
+If you can, upgrade to the latest 2.9.5 or 2.10 binutils release.  Older
 releases such as 2.8, 2.8.xx, and the FSF's 2.9.1 should be avoided if
 at all possible.  The later releases of 2.9.1.0.x (anything where x >= 22)
-can and do compile the kernel properly, but there are many benefits
-to upgrading to 2.9.5 if you're up to it.
+can and do compile the kernel properly, but there are many benefits in
+upgrading to 2.9.5 or 2.10 if you're up to it.
 
 System utils
 ============
@@ -114,20 +115,6 @@
 DevFS is now in the kernel.  See Documentation/filesystems/devfs/* in
 the kernel source tree for all the gory details.
 
-System V shared memory is now implemented via a virtual filesystem.
-You do not have to mount it to use it. SYSV shared memory limits are
-set via /proc/sys/kernel/shm{max,all,mni}.  You should mount the
-filesystem under /dev/shm to be able to use POSIX shared
-memory. Adding the following line to /etc/fstab should take care of
-things:
-
-none		/dev/shm	shm		defaults	0 0
-
-Remember to create the directory that you intend to mount shm on if
-necessary (The entry is automagically created if you use devfs). You
-can set limits for the number of blocks and inodes used by the
-filesystem with the mount options nr_blocks and nr_inodes.
-
 The Logical Volume Manager (LVM) is now in the kernel.  If you want to
 use this, you'll need to install the necessary LVM toolset.
 
@@ -178,6 +165,14 @@
 The latest version of e2fsprogs fixes several bugs in fsck and
 debugfs.  Obviously, it's a good idea to upgrade.
 
+Reiserfsprogs
+-------------
+
+The reiserfsprogs package should be used for reiserfs-3.6.x
+(Linux kernels 2.4.x). It is a combined package and contains working
+versions of mkreiserfs, resize_reiserfs, debugreiserfs and
+reiserfsck. These utils work on both i386 and alpha platforms.
+
 Pcmcia-cs
 ---------
 
@@ -206,6 +201,14 @@
 
 to your /etc/modules.conf file.
 
+Powertweak
+----------
+
+If you are running v0.1.17 or earlier, you should upgrade to
+version v0.99.0 or higher. Running old versions may cause problems
+with programs using shared memory.
+
+
 Networking
 ==========
 
@@ -262,10 +265,19 @@
 *********
 
 egcs 1.1.2 (gcc 2.91.66)
----------
-o  <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-glibc.x86.tar.bz2>
-o  <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-libc5.x86.tar.bz2>
-o  <ftp://ftp.valinux.com/pub/support/hjl/gcc/egcs-1.1.2/egcs-1.1.2-alpha.tar.bz2>
+------------------------
+o  <ftp://sourceware.cygnus.com/pub/gcc/releases/egcs-1.1.2/egcs-1.1.2.tar.bz2>
+
+gcc 2.95.2
+----------
+o  <ftp://ftp.gnu.org/pub/gnu/gcc/gcc-2.95.2.tar.gz>
+
+Gnu Make
+********
+
+Make 3.77
+--------
+o  <ftp://ftp.gnu.org/gnu/make/make-3.77.tar.gz>
 
 Binutils
 ********
@@ -274,20 +286,20 @@
 ------------
 o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/2.9.1/binutils-2.9.1.0.25.tar.gz>
 
-2.10 series
-------------
-o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/binutils-2.10.0.24.tar.bz2>
+2.9.5 and 2.10 series
+---------------------
+o  <ftp://ftp.valinux.com/pub/support/hjl/binutils/>
 
 System utilities
 ****************
 
 Util-linux
 ----------
-o  <ftp://ftp.win.tue.nl/pub/linux-local/utils/util-linux/util-linux-2.10o.tar.gz>
+o  <ftp://ftp.kernel.org/pub/linux/utils/util-linux/util-linux-2.10o.tar.gz>
 
 Ksymoops
 --------
-o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4>
+o  <ftp://ftp.kernel.org/pub/linux/utils/kernel/ksymoops/v2.4/>
 
 Modutils
 --------
@@ -295,13 +307,17 @@
 
 Mkinitrd
 --------
-o  <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/mkinitrd-2.5-1.src.rpm>
+o  <ftp://rawhide.redhat.com/pub/rawhide/SRPMS/SRPMS/mkinitrd-2.9-1.src.rpm>
 
 E2fsprogs
 ---------
 o  <ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/e2fsprogs-1.19.tar.gz>
 o  <ftp://download.sourceforge.net/pub/sourceforge/e2fsprogs/e2fsprogs-1.19.src.rpm>
 
+Reiserfsprogs
+-------------
+o  <ftp://ftp.namesys.com/pub/reiserfsprogs/reiserfs_utils-3.6.25-fsck-3.x.0b.tar.gz>
+
 LVM toolset
 -----------
 o  <http://linux.msede.com/lvm/>
@@ -322,6 +338,10 @@
 ------------------
 o  <http://www.urbanmyth.org/microcode/>
 
+Powertweak
+----------
+o  <http://powertweak.sourceforge.net>
+
 Network
 *******
 
@@ -331,7 +351,7 @@
 
 Isdn4k-utils
 ------------
-o  <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/testing/isdn4k-utils.v3.1beta7.tar.gz>
+o  <ftp://ftp.isdn4linux.de/pub/isdn4linux/utils/isdn4k-utils.v3.1pre1.tar.gz>
 
 Netfilter
 ---------
diff -u --recursive --new-file v2.4.1/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.4.1/linux/Documentation/Configure.help	Sat Feb  3 19:51:21 2001
+++ linux/Documentation/Configure.help	Mon Feb 19 10:18:18 2001
@@ -1,7 +1,7 @@
 # Maintained by Axel Boldt (axel@uni-paderborn.de)
 #
 # This version of the Linux kernel configuration help texts
-# corresponds to the kernel versions 2.3.x.
+# corresponds to the kernel versions 2.4.x.
 #
 # Translations of this file available on the WWW:
 #
@@ -1575,16 +1575,6 @@
   more details about the Baget see the Linux/MIPS FAQ on 
   http://oss.sgi.com/mips .
 
-Support for Cobalt Microserver
-CONFIG_COBALT_MICRO_SERVER
-  This enables support for the Cobalt Microserver.  For more information
-  see the Linux/MIPS FAQ on http://oss.sgi.com/mips .
-
-Support for 2800
-CONFIG_COBALT_28
-  This adds support for the Cobalt Microserver 2800.  A kernel with this
-  option selected will only work on the 2800.
-
 Support for DECstations
 CONFIG_DECSTATION
   This enables support for DEC's MIPS based workstations.  For details
@@ -2572,7 +2562,7 @@
   inserted in and removed from the running kernel whenever you want).
   If you want to compile it as a module, say M here and read
   Documentation/modules.txt. You will get modules called i2o_core.o
-  and i20_config.o. 
+  and i2o_config.o. 
 
   If unsure, say N.
 
@@ -3104,7 +3094,7 @@
 
 nVidia Riva support (EXPERIMENTAL)
 CONFIG_FB_RIVA
-  This driver supports graphics boards with the nVidia Riva (aka TNTx)
+  This driver supports graphics boards with the nVidia Riva/Geforce
   chips.
   Say Y if you have such a graphics board.
 
@@ -5119,7 +5109,7 @@
 
 Compaq Smart Array support
 CONFIG_BLK_CPQ_CISS_DA
-   This is the driver for Compaq Smart Array controllers.
+   This is the driver for Compaq Smart Array 5xxx controllers.
    Everyone using these boards should say Y here.
    See Documentation/cciss.txt for the current list of
    boards supported by this driver, and for further information
@@ -10361,14 +10351,12 @@
 USB Serial converter support
 CONFIG_USB_SERIAL
   Say Y here if you have a USB device that provides normal serial
-  ports, and you want to connect it to your USB bus. Supported devices
-  are the Tech WhiteHEAT multi-port USB to serial converter, and the
-  FTDI or Keyspan single port USB to serial converter Handspring
-  Visor. In addition to saying Y here, you need to say Y to the driver
-  for your specific hardware below. Some other devices may also be
-  used if you say Y to "USB Generic Serial Driver", below.
+  ports, or acts like a serial device, and you want to connect it to
+  your USB bus.
 
-  Please read Documentation/usb/usb-serial.txt for more information.
+  Please read Documentation/usb/usb-serial.txt for more information
+  on the specifics of the different devices that are supported, and
+  on how to use them.
   
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -10474,6 +10462,10 @@
 CONFIG_USB_SERIAL_KEYSPAN_USA19W
   Say Y here to include firmware for the USA-19W converter.
 
+USB Keyspan USA-49W Firmware
+CONFIG_USB_SERIAL_KEYSPAN_USA49W
+  Say Y here to include firmware for the USA-49W converter.
+
 USB ZyXEL omni.net LCD Plus Driver
 CONFIG_USB_SERIAL_OMNINET
   Say Y here if you want to use a ZyXEL omni.net LCD ISDN TA.
@@ -10514,6 +10506,9 @@
 CONFIG_USB_SERIAL_MCT_U232
   Say Y here if you want to use a USB Serial single port adapter from
   Magic Control Technology Corp. (U232 is one of the model numbers).
+  
+  This driver also works with Sitecom U232-P25 and D-Link DU-H3SP USB
+  BAY devices.
 
   This code is also available as a module ( = code which can be
   inserted in and removed from the running kernel whenever you want).
@@ -10523,7 +10518,7 @@
 USB Serial Converter verbose debug
 CONFIG_USB_SERIAL_DEBUG
   Say Y here if you want verbose debug messages from the USB Serial
-  Converter. 
+  Drivers sent to the kernel debug log.
 
 USB Printer support
 CONFIG_USB_PRINTER
@@ -10798,11 +10793,10 @@
   Balanced trees are more efficient than traditional
   filesystem architectural foundations.
 
-  You can use reiserfs in all cases where you use the ext2fs file
-  system, and you will gain in speed and disk space.  It has fewer
-  worst case performance situations than other file systems
-  because balanced trees are hardier creatures than other algorithms
-  are (if that is not technical enough, read www.namesys.com....:-) )
+  In general, ReiserFS is as fast as ext2, but is very efficient
+  with large directories and small files.  Additional patches are
+  needed for NFS and quotas, please see www.reiserfs.org for
+  links.
 
   It is more easily extended to have features currently found in
   database and keyword search systems than block allocation based
@@ -10810,7 +10804,7 @@
   support plugins consistent with our motto ``It takes more than a
   license to make source code open.''
 
-  Read www.namesys.com to learn more about reiserfs.
+  Read www.reiserfs.org to learn more about reiserfs.
 
   Sponsored by Threshold Networks, Emusic.com, and Bigstorage.com.
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/DocBook/Makefile linux/Documentation/DocBook/Makefile
--- v2.4.1/linux/Documentation/DocBook/Makefile	Sat Dec 30 18:16:13 2000
+++ linux/Documentation/DocBook/Makefile	Sat Feb  3 12:43:55 2001
@@ -81,6 +81,7 @@
 		$(TOPDIR)/fs/devfs/base.c \
 		$(TOPDIR)/kernel/pm.c \
 		$(TOPDIR)/kernel/ksyms.c \
+		$(TOPDIR)/kernel/kmod.c \
 		$(TOPDIR)/net/netsyms.c
  
 kernel-api.sgml: kernel-api.tmpl $(APISOURCES)
diff -u --recursive --new-file v2.4.1/linux/Documentation/DocBook/kernel-hacking.tmpl linux/Documentation/DocBook/kernel-hacking.tmpl
--- v2.4.1/linux/Documentation/DocBook/kernel-hacking.tmpl	Mon Nov 27 17:47:38 2000
+++ linux/Documentation/DocBook/kernel-hacking.tmpl	Thu Feb  8 16:32:44 2001
@@ -1179,7 +1179,7 @@
      You may well want to make your CONFIG option only visible if
      <symbol>CONFIG_EXPERIMENTAL</symbol> is enabled: this serves as a
      warning to users.  There many other fancy things you can do: see
-     the the various <filename>Config.in</filename> files for ideas.
+     the various <filename>Config.in</filename> files for ideas.
     </para>
    </listitem>
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/DocBook/kernel-locking.tmpl linux/Documentation/DocBook/kernel-locking.tmpl
--- v2.4.1/linux/Documentation/DocBook/kernel-locking.tmpl	Fri Dec 29 14:07:19 2000
+++ linux/Documentation/DocBook/kernel-locking.tmpl	Fri Feb 16 15:53:08 2001
@@ -386,7 +386,7 @@
        <function>spin_lock()</function> and
        <function>spin_unlock()</function> calls.  
        <function>spin_lock_bh()</function> is
-       unnecessary here, as you are already in a a tasklet, and
+       unnecessary here, as you are already in a tasklet, and
        none will be run on the same CPU.
      </para>
     </sect2>
@@ -720,7 +720,8 @@
       halves without a lock.  Depending on their exact timing, they
       would either see the new element in the list with a valid 
       <structfield>next</structfield> pointer, or it would not be in the 
-      list yet.
+      list yet.  A lock is still required against other CPUs inserting
+      or deleting from the list, of course.
     </para>
 
     <para>
diff -u --recursive --new-file v2.4.1/linux/Documentation/SubmittingDrivers linux/Documentation/SubmittingDrivers
--- v2.4.1/linux/Documentation/SubmittingDrivers	Sun Dec  3 17:48:18 2000
+++ linux/Documentation/SubmittingDrivers	Thu Feb  8 16:32:44 2001
@@ -45,7 +45,7 @@
 What Criteria Determine Acceptance
 ----------------------------------
 
-Licensing:	The code must be released to us under the GNU public license. 
+Licensing:	The code must be released to us under the GNU General Public License. 
 		We don't insist on any kind of exclusively GPL licensing,
 		and if you wish the driver to be useful to other communities
 		such as BSD you may well wish to release under multiple
diff -u --recursive --new-file v2.4.1/linux/Documentation/cciss.txt linux/Documentation/cciss.txt
--- v2.4.1/linux/Documentation/cciss.txt	Fri Sep 22 17:11:37 2000
+++ linux/Documentation/cciss.txt	Sat Feb  3 12:13:19 2001
@@ -6,6 +6,8 @@
 This driver is known to work with the following cards:
 
 	* SA 5300
+	* SA 5i 
+	* SA 532
 
 If notes are not already created in the /dev/cciss directory
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/cris/README linux/Documentation/cris/README
--- v2.4.1/linux/Documentation/cris/README	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/cris/README	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,174 @@
+Linux 2.4 on the CRIS architecture
+==================================
+$Id: README,v 1.5 2001/01/10 17:20:55 bjornw Exp $
+
+This is a port of Linux 2.4 to Axis Communications ETRAX 100LX embedded network CPU. For
+more information about CRIS and ETRAX please see further below.
+
+<... to come: instructions on how to grab the right gcc, compiling and booting ...>
+
+
+What is CRIS ?
+--------------
+
+CRIS is an acronym for 'Code Reduced Instruction Set'. It is the CPU architecture in Axis
+Communication AB's range of embedded network CPU's, called ETRAX. The latest CPU is called
+ETRAX 100LX, where LX stands for 'Linux' because the chip was designed to be a good host for
+the Linux operating system.
+
+The ETRAX 100LX chip
+--------------------
+
+For reference, plase see the press-release:
+
+http://www.axis.com/news/us/001101_etrax.htm
+
+The ETRAX 100LX is a 100 MIPS processor with 8kB cache, MMU, and a very broad range of 
+built-in interfaces, all with modern scatter/gather DMA.
+
+Memory interfaces:
+
+	* SRAM
+	* NOR-flash/ROM
+	* EDO or page-mode DRAM
+	* SDRAM
+
+I/O interfaces:
+
+	* one 10/100 Mbit/s ethernet controller
+	* four serial-ports (up to 6 Mbit/s)
+	* two synchronous serial-ports for multimedia codec's etc.
+	* USB host controller and USB slave
+	* ATA
+	* SCSI
+	* two parallel-ports
+	* two generic 8-bit ports
+	
+	(not all interfaces are available at the same time due to chip pin multiplexing)
+
+The previous version of the ETRAX, the ETRAX 100, sits in almost all of Axis shipping 
+thin-servers like the Axis 2100 web camera or the developer-board. It lacks an MMU so the
+Linux we run on that is a version of uClinux (Linux 2.0 without MM-support) ported to the CRIS
+architecture. The new Linux 2.4 port has full MM and needs a CPU with an MMU, so it will not
+run on the ETRAX 100. 
+
+A version of the Axis developer-board with ETRAX 100LX will be available as soon as the chip 
+is ramped up (please see http://developer.axis.com for further information on that).
+
+
+
+Bootlog
+-------
+
+Just as an example, this is the debug-output from a boot of Linux 2.4 on an Axis
+developer-board with ETRAX 100LX. The displayed BogoMIPS value is 5 times too small :)
+At the end you see some user-mode programs booting like telnet and ftp daemons.
+
+Linux version 2.4.0-test11 (bjornw@godzilla.axis.se) (gcc version 2.96 20000427 (experimental)) #358 Wed Nov 22 19:29:15 CET 2000
+ROM fs in RAM, size 368640 bytes
+Setting up paging and the MMU.
+On node 0 totalpages: 1024
+zone(0): 1024 pages.
+zone(1): 0 pages.
+zone(2): 0 pages.
+Linux/CRIS port (c) 2000 Axis Communications AB
+Kernel command line: 
+Calibrating delay loop... 19.92 BogoMIPS
+Memory: 6864k/8192k available (531k kernel code, 1328k reserved, 85k data, 24k init)
+kmem_create: Forcing size word alignment - vm_area_struct
+kmem_create: Forcing size word alignment - filp
+Dentry-cache hash table entries: 1024 (order: 0, 8192 bytes)
+Buffer-cache hash table entries: 2048 (order: 0, 8192 bytes)
+Page-cache hash table entries: 2048 (order: 0, 8192 bytes)
+kmem_create: Forcing size word alignment - kiobuf
+kmem_create: Forcing size word alignment - bdev_cache
+Inode-cache hash table entries: 1024 (order: 0, 8192 bytes)
+kmem_create: Forcing size word alignment - inode_cache
+POSIX conformance testing by UNIFIX
+Linux NET4.0 for Linux 2.4
+Based upon Swansea University Computer Society NET3.039
+kmem_create: Forcing size word alignment - skbuff_head_cache
+Starting kswapd v1.8
+kmem_create: Forcing size word alignment - file lock cache
+kmem_create: Forcing size word alignment - blkdev_requests
+ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000 Axis Communications AB
+eth0 initialized
+eth0: changed MAC to 00:40:8C:CD:00:00
+ETRAX 100LX serial-driver $Revision: 1.5 $, (c) 2000 Axis Communications AB
+ttyS0 at 0xb0000060 is a builtin UART with DMA
+ttyS1 at 0xb0000068 is a builtin UART with DMA
+ttyS2 at 0xb0000070 is a builtin UART with DMA
+ttyS3 at 0xb0000078 is a builtin UART with DMA
+NET4: Linux TCP/IP 1.0 for NET4.0
+IP Protocols: ICMP, UDP, TCP
+kmem_create: Forcing size word alignment - ip_dst_cache
+IP: routing cache hash table of 1024 buckets, 8Kbytes
+TCP: Hash tables configured (established 1024 bind 1024)
+NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
+VFS: Mounted root (cramfs filesystem) readonly.
+Init starts up...
+Setting up eth0 with ip 10.13.9.116 and mac 00:40:8c:18:04:60
+eth0: changed MAC to 00:40:8C:18:04:60
+Setting up lo with ip 127.0.0.1
+Default gateway is 10.13.9.1
+Hostname is bbox1
+Telnetd starting, using port 23.
+  using /bin/sh as shell.
+sftpd[14]: sftpd $Revision: 1.5 $ starting up
+
+
+And here is how some /proc entries look:
+
+17# cd /proc
+17# cat cpuinfo
+cpu             : ETRAX
+cpu revision    : 10
+cpu model       : ETRAX 100LX
+cache size      : 8 kB
+fpu             : no
+mmu             : yes
+ethernet        : 10/100 Mbps
+token ring      : no
+scsi            : yes
+ata             : yes
+usb             : yes
+bogomips        : 99.84
+17# cat meminfo
+        total:    used:    free:  shared: buffers:  cached:
+Mem:   7028736   925696  6103040   114688        0   229376
+Swap:        0        0        0
+MemTotal:         6864 kB
+MemFree:          5960 kB
+MemShared:         112 kB
+Buffers:             0 kB
+Cached:            224 kB
+Active:            224 kB
+Inact_dirty:         0 kB
+Inact_clean:         0 kB
+Inact_target:        0 kB
+HighTotal:           0 kB
+HighFree:            0 kB
+LowTotal:         6864 kB
+LowFree:          5960 kB
+SwapTotal:           0 kB
+SwapFree:            0 kB
+17# ls -l /bin
+-rwxr-xr-x  1 342      100         10356  Jan 01 00:00 ifconfig
+-rwxr-xr-x  1 342      100         17548  Jan 01 00:00 init
+-rwxr-xr-x  1 342      100          9488  Jan 01 00:00 route
+-rwxr-xr-x  1 342      100         46036  Jan 01 00:00 sftpd
+-rwxr-xr-x  1 342      100         48104  Jan 01 00:00 sh
+-rwxr-xr-x  1 342      100         16252  Jan 01 00:00 telnetd
+
+
+(All programs are statically linked to the libc at this point - we have not ported the
+ shared libraries yet)
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/Documentation/filesystems/00-INDEX linux/Documentation/filesystems/00-INDEX
--- v2.4.1/linux/Documentation/filesystems/00-INDEX	Wed Feb 16 15:42:05 2000
+++ linux/Documentation/filesystems/00-INDEX	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,7 @@
 00-INDEX
 	- this file (info on some of the filesystems supported by linux).
+Locking
+	- info on locking rules as they pertain to Linux VFS.
 adfs.txt
 	- info and mount options for the Acorn Advanced Disc Filing System.
 affs.txt
@@ -8,8 +10,12 @@
 	- info for the SCO UnixWare Boot Filesystem (BFS).
 coda.txt
 	- description of the CODA filesystem.
-devfs
+cramfs.txt
+	- info on the cram filesystem for small storage (ROMs etc)
+devfs/
 	- directory containing devfs documentation.
+ext2.txt
+	- info, mount options and specifications for the Ext2 filesystem.
 fat_cvf.txt
 	- info on the Compressed Volume Files extension to the FAT filesystem
 hpfs.txt
diff -u --recursive --new-file v2.4.1/linux/Documentation/filesystems/Locking linux/Documentation/filesystems/Locking
--- v2.4.1/linux/Documentation/filesystems/Locking	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/filesystems/Locking	Fri Feb 16 15:53:08 2001
@@ -117,7 +117,7 @@
 
 --------------------------- address_space_operations --------------------------
 prototypes:
-	int (*writepage)(struct file *, struct page *);
+	int (*writepage)(struct page *);
 	int (*readpage)(struct file *, struct page *);
 	int (*sync_page)(struct page *);
 	int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
@@ -126,8 +126,8 @@
 locking rules:
 	All may block
 		BKL	PageLocked(page)
-writepage:	no	yes
-readpage:	no	yes
+writepage:	no	yes, unlocks
+readpage:	no	yes, unlocks
 sync_page:	no	maybe
 prepare_write:	no	yes
 commit_write:	no	yes
@@ -135,6 +135,7 @@
 
 	->prepare_write(), ->commit_write(), ->sync_page() and ->readpage()
 may be called from the request handler (/dev/loop).
+	->readpage() and ->writepage() unlock the page.
 	->sync_page() locking rules are not well-defined - usually it is called
 with lock on page, but that is not guaranteed. Considering the currently
 existing instances of this method ->sync_page() itself doesn't look
@@ -285,26 +286,13 @@
 prototypes:
 	void (*open)(struct vm_area_struct*);
 	void (*close)(struct vm_area_struct*);
-	void (*unmap)(struct vm_area_struct*, unsigned long, size_t);
-	void (*protect)(struct vm_area_struct*, unsigned long, size_t, unsigned);
-	int (*sync)(struct vm_area_struct*, unsigned long, size_t, unsigned);
 	struct page *(*nopage)(struct vm_area_struct*, unsigned long, int);
-	struct page *(*wppage)(struct vm_area_struct*, unsigned long, struct page*);
-	int (*swapout)(struct page *, struct file *);
 
 locking rules:
 		BKL	mmap_sem
 open:		no	yes
 close:		no	yes
-sync:		no	yes
-unmap:		no	yes
 nopage:		no	yes
-swapout:	yes	yes
-wpppage:				(see below)
-protect:				(see below)
-
-->wppage() and ->protect() have no instances and nothing calls them; looks like
-they must die...
 
 ================================================================================
 			Dubious stuff
diff -u --recursive --new-file v2.4.1/linux/Documentation/filesystems/ntfs.txt linux/Documentation/filesystems/ntfs.txt
--- v2.4.1/linux/Documentation/filesystems/ntfs.txt	Tue May  2 13:46:53 2000
+++ linux/Documentation/filesystems/ntfs.txt	Fri Feb 16 15:53:08 2001
@@ -2,18 +2,25 @@
 =============
 
 To mount an NTFS volume, use the filesystem type 'ntfs'. The driver
-currently works only in read-only mode, with no fault-tolerance
-supported.  If you enable the experimental write support, make sure
-you can recover from a complete loss of data and also always run
-chkdsk from within Microsoft Windows NT after performing a write to
-a NTFS partition from Linux to detect any problems as early as 
-possible. For ftdisk support, limited success was reported with 
-volume sets on top of the md driver, although mirror and stripe 
-sets should work as well - if the md driver can be talked into 
-using the same layout as Windows NT.
+currently works only in read-only mode, with no fault-tolerance supported.
+
+If you enable the dangerous(!) write support, make sure you can recover
+from a complete loss of data. Also, download the Linux-NTFS project
+distribution from Sourceforge at http://sourceforge.net/projects/linux-ntfs/
+and always run the included ntfsfix utility after performing a write to an
+NTFS partition from Linux to fix some of the damage done by the Linux NTFS
+driver. You should run ntfsfix _after_ unmounting the partition in Linux but
+_before_ rebooting into Windows. During the next reboot into Windows, chkdsk
+will be run automatically to fix the remaining damage.
+
+For ftdisk support, limited success was reported with volume sets on top of
+the md driver, although mirror and stripe sets should work as well - if the
+md driver can be talked into using the same layout as Windows NT. However,
+using the md driver will fail if any of your NTFS partitions have an odd
+number of sectors.
 
 Please note that the experimental write support is limited to
-Windows NT4 and earlier versions.
+Windows NT4 and earlier versions at the moment.
 
 The ntfs driver supports the following mount options:
 iocharset=name      Character set to use when returning file names.
diff -u --recursive --new-file v2.4.1/linux/Documentation/i2c/smbus-protocol linux/Documentation/i2c/smbus-protocol
--- v2.4.1/linux/Documentation/i2c/smbus-protocol	Thu Dec 16 13:59:38 1999
+++ linux/Documentation/i2c/smbus-protocol	Fri Feb 16 15:53:08 2001
@@ -31,7 +31,7 @@
 SMBus Write Quick
 =================
 
-This sends a single byte to the device, at the place of the Rd/Wr bit.
+This sends a single bit to the device, at the place of the Rd/Wr bit.
 There is no equivalent Read Quick command.
 
 A Addr Rd/Wr [A] P
diff -u --recursive --new-file v2.4.1/linux/Documentation/ia64/efirtc.txt linux/Documentation/ia64/efirtc.txt
--- v2.4.1/linux/Documentation/ia64/efirtc.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/ia64/efirtc.txt	Thu Feb  8 16:32:44 2001
@@ -13,7 +13,7 @@
 
 EFI provides 4 calls one can make once the OS is booted: GetTime(),
 SetTime(), GetWakeupTime(), SetWakeupTime() which are all supported by this driver.
-We describes those calls as well the the design of the driver in the following
+We describe those calls as well the design of the driver in the following
 sections.
 
 II/ Design Decisions
diff -u --recursive --new-file v2.4.1/linux/Documentation/ioctl-number.txt linux/Documentation/ioctl-number.txt
--- v2.4.1/linux/Documentation/ioctl-number.txt	Mon Dec 11 13:42:08 2000
+++ linux/Documentation/ioctl-number.txt	Tue Feb 13 14:13:42 2001
@@ -82,6 +82,7 @@
 'B'	C0-FF				advanced bbus
 					<mailto:maassen@uni-freiburg.de>
 'C'	all	linux/soundcard.h
+'D'	all	asm-s390/dasd.h
 'F'	all	linux/fb.h
 'I'	all	linux/isdn.h
 'J'	00-1F	drivers/scsi/gdth_ioctl.h
diff -u --recursive --new-file v2.4.1/linux/Documentation/isdn/INTERFACE linux/Documentation/isdn/INTERFACE
--- v2.4.1/linux/Documentation/isdn/INTERFACE	Wed Aug 25 15:18:07 1999
+++ linux/Documentation/isdn/INTERFACE	Tue Feb 13 14:13:42 2001
@@ -480,7 +480,7 @@
     Parameter:
       driver      = driver-Id
       command     = ISDN_CMD_PROT_IO
-      arg         = The lower 8 Bits define the adressed protocol as defined
+      arg         = The lower 8 Bits define the addressed protocol as defined
                     in ISDN_PTYPE..., the upper bits are used to differenciate
                     the protocol specific CMD.  
       
@@ -734,7 +734,7 @@
     Parameter:
       driver      = driver-Id
       command     = ISDN_STAT_PROT
-      arg         = The lower 8 Bits define the adressed protocol as defined
+      arg         = The lower 8 Bits define the addressed protocol as defined
                     in ISDN_PTYPE..., the upper bits are used to differenciate
                     the protocol specific STAT.  
       
@@ -748,7 +748,7 @@
     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
+    The LL returns a nonzero code if the operation was not successful or the
     selected channel is actually regarded as busy.
 
     Parameter:
diff -u --recursive --new-file v2.4.1/linux/Documentation/isdn/README.HiSax linux/Documentation/isdn/README.HiSax
--- v2.4.1/linux/Documentation/isdn/README.HiSax	Tue Nov 28 21:43:13 2000
+++ linux/Documentation/isdn/README.HiSax	Thu Feb  8 10:40:25 2001
@@ -442,6 +442,7 @@
 	Enrik Berkhan (enrik@starfleet.inka.de) for S0BOX specific stuff
 	Ton van Rosmalen for Teles PCI
 	Petr Novak <petr.novak@i.cz> for Winbond W6692 support
+	Werner Cornelius <werner@isdn4linux.de> for HFC-PCI, HFC-S(+/P) and supplementary services support
         and more people who are hunting bugs. (If I forgot somebody, please
 	send me a mail).
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/isdn/README.diversion linux/Documentation/isdn/README.diversion
--- v2.4.1/linux/Documentation/isdn/README.diversion	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/isdn/README.diversion	Thu Feb  8 16:32:44 2001
@@ -6,7 +6,7 @@
 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.
+GNU General 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
diff -u --recursive --new-file v2.4.1/linux/Documentation/isdn/README.hfc-pci linux/Documentation/isdn/README.hfc-pci
--- v2.4.1/linux/Documentation/isdn/README.hfc-pci	Sun Nov  7 16:34:00 1999
+++ linux/Documentation/isdn/README.hfc-pci	Thu Feb  8 10:40:25 2001
@@ -35,7 +35,7 @@
 supplied else the parameter is assumed 0 and a auto search for a free card is
 invoked which may not give the wanted result. 
 
-Comments and reports to werner@isdn4linux.de or werner@titro.de .
+Comments and reports to werner@isdn4linux.de or werner@isdn-development.de
 
 
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/isdn/README.hysdn linux/Documentation/isdn/README.hysdn
--- v2.4.1/linux/Documentation/isdn/README.hysdn	Mon Aug 21 07:49:02 2000
+++ linux/Documentation/isdn/README.hysdn	Thu Feb  8 16:32:44 2001
@@ -2,7 +2,7 @@
 The hysdn driver has been written by
 by Werner Cornelius (werner@isdn4linux.de or werner@titro.de) 
 for Hypercope GmbH Aachen Germany. Hypercope agreed to publish this driver
-under the GNU Public License.
+under the GNU General Public License.
 
 The CAPI 2.0-support was added by Ulrich Albrecht (ualbrecht@hypercope.de)
 for Hypercope GmbH Aachen, Germany.
diff -u --recursive --new-file v2.4.1/linux/Documentation/kbuild/makefiles.txt linux/Documentation/kbuild/makefiles.txt
--- v2.4.1/linux/Documentation/kbuild/makefiles.txt	Mon Dec 11 13:19:35 2000
+++ linux/Documentation/kbuild/makefiles.txt	Tue Feb 13 14:13:42 2001
@@ -1206,7 +1206,7 @@
 
     mod-subdirs
 
-	$(mod-subdirs) is a list of all the the subdirectories that should
+	$(mod-subdirs) is a list of all the subdirectories that should
 	be added to $(subdir-m), too if they appear in $(subdir-y)
 
 	Example:
diff -u --recursive --new-file v2.4.1/linux/Documentation/magic-number.txt linux/Documentation/magic-number.txt
--- v2.4.1/linux/Documentation/magic-number.txt	Sun Feb 20 20:37:09 2000
+++ linux/Documentation/magic-number.txt	Tue Feb 13 14:13:42 2001
@@ -65,7 +65,6 @@
 TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
 TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
 TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
-SCC_MAGIC             0x8530      scc_channel       include/linux/scc.h
 SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
 CG_MAGIC	      0x090255    ufs_cylinder_group include/linux/ufs_fs.h
 RPORT_MAGIC           0x525001    r_port            drivers/char/rocket_int.h
diff -u --recursive --new-file v2.4.1/linux/Documentation/mca.txt linux/Documentation/mca.txt
--- v2.4.1/linux/Documentation/mca.txt	Wed Aug 18 11:37:51 1999
+++ linux/Documentation/mca.txt	Tue Feb 13 14:13:42 2001
@@ -25,7 +25,7 @@
 	if( MCA_bus ) {
 		slot = mca_find_adapter( ADAPTER_ID, 0 );
 		if( slot == MCA_NOTFOUND ) {
-			return ENODEV;
+			return -ENODEV;
 		}
 		/* optional - see below */
 		mca_set_adapter_name( slot, "adapter name & description" );
@@ -37,7 +37,7 @@
 		pos4 = mca_read_stored_pos( slot, 4 );
 		pos5 = mca_read_stored_pos( slot, 5 );
 	} else {
-		return ENODEV;
+		return -ENODEV;
 	}
 
 	/* extract configuration from pos[2345] and set everything up */
diff -u --recursive --new-file v2.4.1/linux/Documentation/modules.txt linux/Documentation/modules.txt
--- v2.4.1/linux/Documentation/modules.txt	Fri Dec 29 14:35:47 2000
+++ linux/Documentation/modules.txt	Fri Feb 16 15:53:08 2001
@@ -137,6 +137,39 @@
 since umsdos runs piggyback on msdos.
 
 
+Using modinfo:
+--------------
+
+Sometimes you need to know what parameters are accepted by a
+module or you've found a bug and want to contact the maintainer.
+Then modinfo comes in very handy.
+
+Every module (normally) contains the author/maintainer,
+a description and a list of parameters.
+
+For example "modinfo -a eepro100" will return:
+
+	Maintainer: Andrey V. Savochkin <saw@saw.sw.com.sg>
+
+and "modinfo -d eepro100" will return a description:
+
+	Intel i82557/i82558 PCI EtherExpressPro driver
+
+and more important "modinfo -p eepro100" will return this list:
+
+	debug int
+	options int array (min = 1, max = 8)
+	full_duplex int array (min = 1, max = 8)
+	congenb int
+	txfifo int
+	rxfifo int
+	txdmacount int
+	rxdmacount int
+	rx_copybreak int
+	max_interrupt_work int
+	multicast_filter_limit int
+
+
 The "ultimate" utility:
 -----------------------
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/networking/00-INDEX linux/Documentation/networking/00-INDEX
--- v2.4.1/linux/Documentation/networking/00-INDEX	Sat Nov 27 15:27:48 1999
+++ linux/Documentation/networking/00-INDEX	Thu Feb  8 16:32:44 2001
@@ -4,32 +4,46 @@
 	- information on the 3Com EtherLink Plus (3c505) driver.
 6pack.txt
 	- info on the 6pack protocol, an alternative to KISS for AX.25
+8139too.txt
+	- info on the 8139too driver for RTL-8139 based network cards.
 Configurable
 	- info on some of the configurable network parameters
 DLINK.txt
 	- info on the D-Link DE-600/DE-620 parallel port pocket adapters
 PLIP.txt
 	- PLIP: The Parallel Line Internet Protocol device driver
+README.sb1000
+	- info on General Instrument/NextLevel SURFboard1000 cable modem.
 alias.txt
 	- info on using alias network devices 
 arcnet-hardware.txt
 	- tons of info on ARCnet, hubs, jumper settings for ARCnet cards, etc.
 arcnet.txt
 	- info on the using the ARCnet driver itself.
+atm.txt
+	- info on where to get ATM programs and support for Linux.
 ax25.txt
 	- info on using AX.25 and NET/ROM code for Linux
 baycom.txt
 	- info on the driver for Baycom style amateur radio modems
+bridge.txt
+	- where to get user space programs for ethernet bridging with Linux.
+comx.txt
+	- info on drivers for COMX line of synchronous serial adapters.
 cops.txt
 	- info on the COPS LocalTalk Linux driver
 cs89x0.txt
 	- the Crystal LAN (CS8900/20-based) Ethernet ISA adapter driver
 de4x5.txt
 	- the Digital EtherWORKS DE4?? and DE5?? PCI Ethernet driver
+decnet.txt
+	- info on using the DECnet networking layer in Linux.
 depca.txt
 	- the Digital DEPCA/EtherWORKS DE1?? and DE2?? LANCE Ethernet driver
 dgrs.txt
 	- the Digi International RightSwitch SE-X Ethernet driver
+dmfe.txt
+	- info on the Davicom DM9102(A)/DM9132/DM9801 fast ethernet driver.
 eql.txt
 	- serial IP load balancing
 ethertap.txt
@@ -38,6 +52,8 @@
 	- the Digital EtherWORKS 3 DE203/4/5 Ethernet driver
 filter.txt
 	- Linux Socket Filtering
+fore200e.txt
+	- FORE Systems PCA-200E/SBA-200E ATM NIC driver info.
 framerelay.txt
 	- info on using Frame Relay/Data Link Connection Identifier (DLCI).
 ip-sysctl.txt
@@ -46,6 +62,10 @@
 	- IP dynamic address hack e.g. for auto-dialup links
 ipddp.txt
 	- AppleTalk-IP Decapsulation and AppleTalk-IP Encapsulation
+iphase.txt
+	- Interphase PCI ATM (i)Chip IA Linux driver info.
+irda.txt
+	- where to get IrDA (infrared) utilities and info for Linux.
 lapb-module.txt
 	- programming information of the LAPB module.
 ltpc.txt
@@ -56,22 +76,42 @@
 	- notes on how NCSA telnet (DOS) breaks with MTU discovery enabled.
 net-modules.txt
 	- info and "insmod" parameters for all network driver modules.
+netdevices.txt
+	- info on network device driver functions exported to the kernel.
+olympic.txt
+	- IBM PCI Pit/Pit-Phy/Olympic Token Ring driver info.
 policy-routing.txt
 	- IP policy-based routing
 pt.txt
 	- the Gracilis Packetwin AX.25 device driver
+ray_cs.txt
+	- Raylink Wireless LAN card driver info.
 routing.txt
 	- the new routing mechanism
 shaper.txt
 	- info on the module that can shape/limit transmitted traffic.
+sis900.txt
+	- SiS 900/7016 Fast Ethernet device driver info.
+sk98lin.txt
+	- SysKonnect SK-NET (SK-98xx) Gigabit Ethernet driver info.
+skfp.txt
+	- SysKonnect FDDI (SK-5xxx, Compaq Netelligent) driver info.
 smc9.txt
 	- the driver for SMC's 9000 series of Ethernet cards
+smctr.txt
+	- SMC TokenCard TokenRing Linux driver info.
 soundmodem.txt
 	- Linux driver for sound cards as AX.25 modems
 tcp.txt
 	- short blurb on how TCP output takes place.
+tlan.txt
+	- ThunderLAN (Compaq Netelligent 10/100, Olicom OC-2xxx) driver info.
+tms380tr.txt
+	- SysKonnect Token Ring ISA/PCI adapter driver info.
 tulip.txt
 	- info on using DEC 21040/21041/21140 based PCI Ethernet cards.
+tuntap.txt
+	- TUN/TAP device driver, allowing user space Rx/Tx of packets.
 vortex.txt
 	- info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards.
 wan-router.txt
diff -u --recursive --new-file v2.4.1/linux/Documentation/networking/decnet.txt linux/Documentation/networking/decnet.txt
--- v2.4.1/linux/Documentation/networking/decnet.txt	Fri Jul 28 12:50:51 2000
+++ linux/Documentation/networking/decnet.txt	Fri Feb 16 15:53:08 2001
@@ -145,7 +145,7 @@
  - What is in the /proc/decnet* files and /proc/sys/net/decnet/* files ?
  - Which services are you running ?
  - Which client caused the problem ?
- - How much data was being transfered ?
+ - How much data was being transferred ?
  - Was the network congested ?
  - If there was a kernel panic, please run the output through ksymoops
    before sending it to me, otherwise its _useless_.
diff -u --recursive --new-file v2.4.1/linux/Documentation/networking/smc9.txt linux/Documentation/networking/smc9.txt
--- v2.4.1/linux/Documentation/networking/smc9.txt	Sat Nov 29 10:33:18 1997
+++ linux/Documentation/networking/smc9.txt	Thu Feb  8 16:32:44 2001
@@ -3,7 +3,7 @@
 Revision 0.12 
 3/5/96
 Copyright 1996  Erik Stahlman 
-Released under terms of the GNU public license. 
+Released under terms of the GNU General Public License. 
 
 This file contains the instructions and caveats for my SMC9xxx driver.  You
 should not be using the driver without reading this file.  
diff -u --recursive --new-file v2.4.1/linux/Documentation/s390/TAPE linux/Documentation/s390/TAPE
--- v2.4.1/linux/Documentation/s390/TAPE	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/TAPE	Fri Feb 16 15:53:08 2001
@@ -0,0 +1,125 @@
+Channel attached Tape device driver 
+
+-----------------------------WARNING-----------------------------------------
+This driver is considered to be EXPERIMENTAL. Do NOT use it in 
+production environments. Feel free to test it and report problems back to us. 
+-----------------------------------------------------------------------------
+
+The LINUX for zSeries tape device driver manages channel attached tape drives 
+which are compatible to IBM 3480 or IBM 3490 magnetic tape subsystems. This 
+includes various models of these devices (for example the 3490E). 
+
+
+Tape driver features 
+
+The device driver supports a maximum of 128 tape devices. 
+No official LINUX device major number is assigned to the zSeries tape device 
+driver. It allocates major numbers dynamically and reports them on system 
+startup. 
+Typically it will get major number 254 for both the character device front-end 
+and the block device front-end. 
+
+The tape device driver needs no kernel parameters. All supported devices 
+present are detected on driver initialization at system startup or module load.
+The devices detected are ordered by their subchannel numbers. The device with 
+the lowest subchannel number becomes device 0, the next one will be device 1 
+and so on. 
+
+
+Tape character device front-end 
+
+The usual way to read or write to the tape device is through the character 
+device front-end. The zSeries tape device driver provides two character devices
+for each physical device -- the first of these will rewind automatically when 
+it is closed, the second will not rewind automatically. 
+
+The character device nodes are named /dev/rtibm0 (rewinding) and /dev/ntibm0 
+(non-rewinding) for the first device, /dev/rtibm1 and /dev/ntibm1 for the 
+second, and so on. 
+
+The character device front-end can be used as any other LINUX tape device. You 
+can write to it and read from it using LINUX facilities such as GNU tar. The 
+tool mt can be used to perform control operations, such as rewinding the tape 
+or skipping a file. 
+
+Most LINUX tape software should work with either tape character device. 
+
+
+Tape block device front-end 
+
+The tape device may also be accessed as a block device in read-only mode. 
+This could be used for software installation in the same way as it is used with 
+other operation systems on the zSeries platform (and most LINUX 
+distributions are shipped on compact disk using ISO9660 filesystems). 
+
+One block device node is provided for each physical device. These are named 
+/dev/btibm0 for the first device, /dev/btibm1 for the second and so on. 
+You should only use the ISO9660 filesystem on LINUX for zSeries tapes because 
+the physical tape devices cannot perform fast seeks and the ISO9660 system is 
+optimized for this situation. 
+
+
+Tape block device example 
+
+In this example a tape with an ISO9660 filesystem is created using the first 
+tape device. ISO9660 filesystem support must be built into your system kernel
+for this. 
+The mt command is used to issue tape commands and the mkisofs command to 
+create an ISO9660 filesystem: 
+
+- create a LINUX directory (somedir) with the contents of the filesystem 
+     mkdir somedir
+     cp contents somedir 
+
+- insert a tape 
+
+- ensure the tape is at the beginning 
+     mt -f /dev/ntibm0 rewind 
+
+- set the blocksize of the character driver. The blocksizes 512, 1024
+  and 2048 bytes are supported by ISO9660. 1024 is the default, u
+  which will be used here. 
+     mt -f /dev/ntibm0 setblk 1024 
+
+- write the filesystem to the character device driver 
+     mkisofs -o /dev/ntibm0 somedir 
+
+- rewind the tape again 
+     mt -f /dev/ntibm0 rewind 
+
+- Now you can mount your new filesystem as a block device: 
+     mount -t iso9660 -o ro,block=1024 /dev/btibm0 /mnt 
+
+TODO List 
+
+- The backend code has to be enhanced to support error-recovery actions. 
+
+- The seeking algorithm of the block device has to be improved to speed 
+  things up 
+
+BUGS 
+
+There are lots of weaknesses still in the code. This is why it is EXPERIMENTAL.
+If an error occurs which cannot be handled by the code you will get a 
+sense-data dump.In that case please do the following: 
+
+1. set the tape driver debug level to maximum: 
+     echo 6 >/proc/s390dbf/tape/level 
+
+2. re-perform the actions which produced the bug. (Hopefully the bug will 
+   reappear.) 
+
+3. get a snapshot from the debug-feature: 
+     cat /proc/s390dbf/tape/hex_ascii >somefile 
+
+4. Now put the snapshot together with a detailed description of the situation 
+   that led to the bug: 
+ - Which tool did you use? 
+ - Which hardware do you have? 
+ - Was your tape unit online? 
+ - Is it a shared tape unit? 
+
+5. Send an email with your bug report to: 
+     mailto:Linux390@de.ibm.com 
+
+
diff -u --recursive --new-file v2.4.1/linux/Documentation/s390/cds.txt linux/Documentation/s390/cds.txt
--- v2.4.1/linux/Documentation/s390/cds.txt	Thu Oct 12 14:19:31 2000
+++ linux/Documentation/s390/cds.txt	Fri Feb 16 15:53:08 2001
@@ -539,7 +539,7 @@
 
 Possible flag values are :
 
-DOIO_EARLY_NOTIFICATION  - allow for early interupt notification
+DOIO_EARLY_NOTIFICATION  - allow for early interrupt notification
 DOIO_VALID_LPM           - LPM input parameter is valid (see usage
                            notes below for details)
 DOIO_WAIT_FOR_INTERRUPT  - wait synchronously for final status
@@ -549,7 +549,7 @@
 
 typedef struct {
    char            cmd_code; /* command code */
-   char            flags;    /* flags, like IDA adressing, etc. */
+   char            flags;    /* flags, like IDA addressing, etc. */
    unsigned short  count;    /* byte count */
    void           *cda;      /* data address */
 } ccw1_t __attribute__ ((aligned(8)));
diff -u --recursive --new-file v2.4.1/linux/Documentation/s390/chandev.8 linux/Documentation/s390/chandev.8
--- v2.4.1/linux/Documentation/s390/chandev.8	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/s390/chandev.8	Fri Feb 16 15:53:08 2001
@@ -0,0 +1,306 @@
+.TH chandev 8
+.SH NAME
+channel device layer
+.Dd December 6, 2000
+.Os Linux for Zseries
+
+.SH SYNOPSIS
+The channel device layer is a layer to provide a consistent interface for
+configuration & default machine check (devices appearing & disappearing )
+handling Linux for zSeries channel devices.
+
+These include among others
+
+.Bl -item
+.It
+lcs ( the most common ethernet/token ring/fddi standard on zSeries )
+.It
+ctc/escon hi speed like serial link standard on zSeries.
+.It
+claw used to talk to cisco routers.
+.It
+qeth gigabit ethernet.
+.El
+
+These devices use two channels one read & one write for configuration &
+or communication.
+The motivation behind producing this layer was that there is a lot of
+duplicate code among the drivers for configuration so the lcs & ctc drivers
+tended to fight over 3088/08's & 3088/1F's which could be either 2216/3172
+lcs compatible devices or escons/ctc's & to resolve this fight
+both device drivers had to be reconfigured rather than doing the
+configuration in a single place.
+
+.SH DESCRIPTION
+The current setup can be read from /proc/chandev
+arguments can be entered by...
+.Bl -enum
+.It
+Piping to /proc/chandev.
+.It
+Entering them into /etc/chandev.conf comments are prefixed #.
+.It
+Or from the boot command line using the 'chandev=' keyword
+.El
+Multiple options can be passed separated by semicolons but no spaces are allowed between parameters. The script /bin/chandev will be called automatically on startup or a machine check of a device as follows.
+/bin/chandev <start starting_devnames> <machine_check (devnames pre_recovery_action_status) (post_recovery_action_status)>.
+
+e.g. if tr0 & ctc0 were starting up & eth0 & eth1 didn't recover from a gone machine check at the same instant the  parameters would be.
+
+
+/bin/chandev start tr0 ctc0 machine_check eth0 gone gone eth1 gone gone
+
+
+This can be used for example to call /etc/rc.d/init.d/network start when a device appears & make the ipldelay kernel boot parameter obselete on native machines or recover from bad machine checks where the default machine check handling isn't adequete. The machine checks that can be presented as parameters are good not_operational no_path revalidate device_gone.
+
+valid chandev arguments are <> indicate optional parameters, | indicate a choice.
+
+.B glossary
+.Bl -item
+.It
+devno: is a 16 bit unsigned number used to uniquely identify a subchannel to a device.
+.It
+force list: is a term specific to channel device layer describing a range of devno's to be forced to configure in a particular manner as opposed to autodetect
+.El
+
+.B commonly used options
+
+.Bl -item
+.It
+
+.Bl -item
+
+.It
+.B (ctc|escon|lcs|osad|qeth|claw)<devif_num>, 
+read_devno, write_devno, <port_no/protocol_no>, <checksum_received_ip_pkts>, <use_hw_stats>
+.It
+e.g. ctc0,0x7c00,0x7c01,0,0,0
+.It
+Tells the channel layer to force ctc0 if detected to use cuu's 7c00 & 7c01 port,port_no is the relative adapter no on lcs, on ctc/escon this field is the ctc/escon protocol number ( normally 0 ), don't do checksumming on received ip packets & as ctc doesn't have hardware stats so it ignores this parameter.
+.El
+.It
+
+.Bl -item
+.It
+.B add_parms
+,chan_type,<string>
+.It
+chan_type bitfield 
+.It
+ctc=0x1, escon=0x2, lcs=0x4, osad=0x8, qeth=0x10, claw=0x20.
+.It
+This is for device driver specific options passed as a string to the driver
+not dealt with by the channel device layer it can't contain spaces.
+.El
+.It
+
+.Bl -item
+.It
+.B del_parms
+<,chan_type,exact_match>
+.It
+This deletes some or all device driver specific options not specifying chan_type causes it to delete all the strings. exact_match=1 specifies only to remove driver parms where chan_type is exactly equal exact_match=0 specifies to remove parms where any bit matches chan_type.
+.El
+.It
+
+.Bl -item
+.It
+.B noauto
+,<lo_devno>-<hi_devno>
+.It
+Don't probe a range of device numbers for channel devices.
+.El
+.It
+
+.Bl -item
+.It
+.B use_devno_names
+.It
+Tells the channel layer to assign device names based on the read channel cuu number.
+.It
+e.g. a token ring read channel 0x7c00 would have an interface called tr0x7c00 this avoids name collisions on devices.
+.El
+.El
+
+
+.B power user options
+
+
+.Bl -item
+
+.It
+.Bl -item
+.It
+.B del_noauto
+,<devno>
+.It
+ Delete a range or all noauto ranges when devno is within a range.
+.El
+
+.It
+.Bl -item
+.It
+.B del_force
+,read_devno
+.It
+Delete a forced channel device from force list.
+.El
+
+.It
+.Bl -item
+.It
+.B dont_use_devno_names
+.It
+Opposite to use_devno_names described above.
+.El
+
+
+.It
+.Bl -item
+.It
+.B add_model
+,chan_type, cu_type, cu_model, dev_type, dev_model, max_port_no, automatic_machine_check_handling
+
+.It
+Tells the channel layer to probe for the device described, -1 for any of the parameters other than chan_type & automatic_machine_check_handling is a wildcard.
+Set max_port_no to 0 for non lcs devices.
+.It
+auto machine check recovery bitfield
+.It
+not_operational=0x1, no_path=0x2, revalidate=0x4, gone=0x8
+.It
+chan_type bitfield
+.It
+ctc=0x1, escon=0x2, lcs=0x4, osad=0x8, qeth=0x10, claw=0x20
+
+.It
+.Bl -item
+.It
+.B del_model
+,cu_type,cu_model,dev_type,dev_model
+.It
+-1 for any parameter is a wildcard,
+.El
+.It
+.B del_all_models
+.It
+.Bl -item
+.It
+.B auto_msck
+<,lo_devno>,<hi_devno>,auto_msck_recovery
+.It
+This is used to specify the kind of machine check recovery that occurs over a device range.
+.El
+.It
+.Bl -item
+.It
+.B del_auto_msck
+<,devno>
+.It
+Delete a range or all machine check recovery ranges when devno is within a range.
+.El
+.It
+.Bl -item
+.It
+.B reset_clean
+.It
+Resets all model info, forced devices & noauto lists to null.
+.El
+.It
+.Bl -item
+.It
+.B reset_conf
+.It
+Resets all model info, forced devices & noauto lists back to default settings.
+.El
+.It
+.Bl -item
+.It
+.B reset_conf_clean
+.It
+Resets all model info, forced devices & noauto lists to empty.
+.El
+.It
+.Bl -item
+.It
+.B shutdown
+<device name|read devno>
+.It
+Shuts down a particular device by device name or read devno,
+deregisters it & releases its interrupts
+or shuts down all devices if no parameter is used.
+.El
+.It
+.Bl -item
+.It
+.B reprobe
+.It
+Calls probe method for channels whose interrupts are not owned.
+.El
+.It
+.Bl -item
+.It
+.B read_conf
+.It
+Read instructions from /etc/chandev.conf.
+.El
+.It
+.Bl -item
+.It
+.B dont_read_conf
+.It
+Don't automatically read /etc/chandev.conf on boot.
+.El
+.It
+e.g the following sequence of commands should be roughly equivalent
+to rebooting for channel devices.
+.Bl -item
+.It
+shutdown
+.It
+reset_conf
+.It
+read_conf
+.It
+reprobe
+.El
+.El
+
+.SH SEE ALSO
+.Bl -item
+.It
+If you wish to write a driver channel device layer compatible
+.It
+/linux/include/asm-s390/chandev.h for the apis which are commented.
+.It
+/linux/drivers/s390/misc/chandev.c for the code.
+.El
+
+.SH FILES
+.Bl -item
+.It
+.B /proc/chandev
+.It
+cat /proc/chandev to see current options chosen.
+.Iy
+echo <command> >proc/chandev to enter a new command
+.It
+.B /etc/chandev.conf 
+.It
+A file which can be used to configure the channel 
+device layer.
+.It
+kernel parameters with the 
+.B 'chandev=' 
+keyword.
+.It
+.B /bin/chandev
+.It 
+A user script/executable which is run when devices come online "appear"
+or go offline "disappear".
+.El
+
+
+.SH AUTHORS
+DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+
diff -u --recursive --new-file v2.4.1/linux/Documentation/scsi-generic.txt linux/Documentation/scsi-generic.txt
--- v2.4.1/linux/Documentation/scsi-generic.txt	Mon Aug 21 08:57:35 2000
+++ linux/Documentation/scsi-generic.txt	Thu Feb  8 16:32:44 2001
@@ -314,7 +314,7 @@
 (limit is SG_MAX_QUEUE (16) outstanding packets per file descriptor).
 However, for backward compatibility, command queuing is turned off
 by default (#define SG_DEF_COMMAND_Q 0 in sg.h). This can be changed
-via the the SG_SET_COMMAND_Q ioctl() [or by recompiling after changing
+via the SG_SET_COMMAND_Q ioctl() [or by recompiling after changing
 the above define to 1].
 
 In this sg driver a write() should return more or less immediately.
diff -u --recursive --new-file v2.4.1/linux/Documentation/sound/AWE32 linux/Documentation/sound/AWE32
--- v2.4.1/linux/Documentation/sound/AWE32	Tue Apr 11 19:13:15 2000
+++ linux/Documentation/sound/AWE32	Fri Feb 16 15:53:08 2001
@@ -3,103 +3,74 @@
 This documentation is devoted to the Creative Sound Blaster AWE32, AWE64 and 
 SB32.
 
-1) Make sure you have an ORIGINAL Creative SB32, AWE32 or AWE64 card. This is 
-important, because the driver works only with real Creative cards.
+1) Make sure you have an ORIGINAL Creative SB32, AWE32 or AWE64 card. This
+   is important, because the driver works only with real Creative cards.
 
-2) If your card is NOT "Plug-n-Play" then go to 5th step now. In the other case
-proceed to step 3.
+2) The first thing you need to do is re-compile your kernel with support for
+   your sound card. Run your favourite tool to configure the kernel and when
+   you get to the "Sound" menu you should enable support for the following:
 
-3) You should compile in kernel ISAPnP support or you should obtain isapnptools.
-If you choose kernel level ISAPnP skip to step 5. I looked through other PnP 
-packages for Linux, but all they are either in deep unstable beta/alpha releases
-or they are much worse than isapnptools. In my case isapnptools were included in
-a Linux distribution (Red Hat 5.x). If you also already have them then go to 
-step 4.
+   Sound card support,
+   OSS sound modules,
+   100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support,
+   AWE32 synth
 
-The latest copy of isapnptools-1.17 is available from 
-ftp://sunsite.unc.edu/pub/Linux/system/hardware/isapnptools-1.17.tgz
-You should gunzip/untar it to something like /usr/local/ 
-(cp isapnptools-1.17.tgz /usr/local/; cd /usr/local/;
-tar -xzf isapnptools-1.17.tgz). 
+   If your card is "Plug and Play" you will also need to enable these two
+   options, found under the "Plug and Play configuration" menu:
 
-Compile the package (make) and install it (make install).
-If something goes wrong check the INSTALL file in isapnptools-1.15 directory.
+   Plug and Play support
+   ISA Plug and Play support
 
-4) Now do a "pnpdump > /etc/isapnp.conf". File /etc/isapnp.conf will contain 
-info about PnP devices you may have. If you want you can read the manual page
-about isapnp.conf file (man isapnp.conf). Most lines of your isapnp.conf file are 
-commented. You should uncomment lines which don't conflict with your 
-configuration.
+   Now compile and install the kernel in normal fashion. If you don't know
+   how to do this you can find instructions for this in the README file
+   located in the root directory of the kernel source.
 
-ATTENTION! Device Audio should have 1 IRQ, 2 DMA and 3 base I/O resources.
-If you don't have such a configuration you should manually add the resources to
-the isapnp.conf file. After editing I got these lines in the Audio device
-section (I ripped out all the comments):
+3) Before you can start playing midi files you will have to load a sound
+   bank file. The utility needed for doing this is called "sfxload", and it
+   is one of the utilities found in a package called "awesfx". If this
+   package is not available in your distribution you can download the AWE
+   snapshot from Creative Labs Open Source website:
 
-"(CONFIGURE CTL0044/1132685 (LD 0 (INT 0 (IRQ 5 (MODE +E))) (DMA 0 (CHANNEL 1))
- (DMA 1 (CHANNEL 5)) (IO 0 (BASE 0x220)) (IO 1 (BASE 0x330)) (IO 2 (BASE 0x388))
- (ACT Y)))"
+   http://www.opensource.creative.com/snapshot.html
 
-(In your case CTL044/1132685 numbers may be other)
+   Once you have unpacked the AWE snapshot you will see a "awesfx"
+   directory. Follow the instructions in awesfx/docs/INSTALL to install the
+   utilities in this package. After doing this, sfxload should be installed
+   as:
 
-Don't forget to uncomment (ACT Y)!
+   /usr/local/bin/sfxload
 
-The next device is the on-board IDE controller. You may enable it if you wish,
-but it will not effect sound.
+   To enable AWE general midi synthesis you should also get the sound bank
+   file for general midi from:
 
-Then WaveTable goes. For some reason Plug-n-Play detects only one I/O port,
-but the wavetable needs THREE! My working string is:
+   http://members.xoom.com/yar/synthgm.sbk.gz
 
-"(CONFIGURE CTL044/1132685 (LD 2 (IO 0 (BASE 0x0620)) (IO 1 (BASE 0x0A20)) 
-(IO 2 (BASE 0x0E20)) (ACT Y) ))"
+   Copy it to a directory of your choice, and unpack it there.
 
-Resources 0x0620, 0x0A20 and 0x0E20 should work. Other on-board devices: 
-Gameport and StereoEnhance are not required to be initialized.
+4) Edit /etc/modules.conf, and insert the following lines at the end of the
+   file:
 
-Now you can execute "isapnp /etc/isapnp.conf". No errors should be reported.
-If you correctly installed isapnptools, then isapnp will run every boot time.
+  alias sound-slot-0 sb
+  alias sound-service-0-1 awe_wave
+  post-install awe_wave /usr/local/bin/sfxload PATH_TO_SOUND_BANK_FILE
 
-5) Now you should recompile the kernel.
+  You will of course have to change "PATH_TO_SOUND_BANK_FILE" to the full
+  path of of the sound bank file. That will enable the Sound Blaster and AWE
+  wave synthesis. To play midi files you should get one of these programs if
+  you don't already have them:
 
-In "make (x,menu)config" select in "Sound":
-"Sound card support", "100% Sound Blaster compatibles (SB16/32/64, ESS, Jazz16) support",
-"Generic OPL2/OPL3 FM synthesizer support" and "FM synthesizer (YM3812/OPL-3) 
-support" as <M> (module).
+  Playmidi:			http://playmidi.openprojects.net
 
-In "make (x,menu)config" select in "Sound":
-select "OSS sound modules" as <M> (module)
-select "AWE32 Synth" as <M> (module)
+  AWEMidi Player (drvmidi)  	Included in the previously mentioned AWE
+  				snapshot.
 
-Now recompile the kernel (make dep; make (b)zImage, b(z)lilo, etc...;
-make modules; make modules_install), update your boot loader (if required) and
-boot new kernel.
+  You will probably have to pass the "-e" switch to playmidi to have it use
+  your midi device. drvmidi should work without switches.
 
-6) If awesfx program is not included in your distribution, then download it 
-from http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/index.html#Latest.
-Compile it. Copy sfxload program to /usr/bin. To enable AWE general midi
-synthesis you should also get the sound bank file for general midi from
-http://members.xoom.com/yar/synthgm.sbk.gz. Copy it to /usr and gunzip it there.
+  If something goes wrong please e-mail me. All comments and suggestions are
+  welcome.
 
-7) Edit /etc/modules.conf, inserting at the end of the file:
+		    Yaroslav Rosomakho (alons55@dialup.ptt.ru)
+			    http://www.yar.opennet.ru
 
-alias midi awe_wave
-post-install awe_wave /usr/bin/sfxload /usr/synthfm.sbk
-
-That will enable the Sound Blaster and AWE wave synthesis.
-
-To play midi files you should get one of these programs:
-
-Playmidi 2.4 or higher: http://playmidi.openprojects.net
-Drvmidi: http://bahamut.mm.t.u-tokyo.ac.jp/~iwai/awedrv/index.html#Latest
-
-(These are available at all major Linux FTP sites and may already be
- in your distribution)
-Remember to use -a switch if you have playmidi as a compiled binary (ex. RPM)
-
-If something goes wrong please e-mail me. All comments and suggestions are
-welcome.
-
-			    Yaroslav Rosomakho (alons55@dialup.ptt.ru)
-				    http://www.yar.opennet.ru
-
-Last Updated: 10Apr2000
+Last Updated: Feb 3 2001
diff -u --recursive --new-file v2.4.1/linux/Documentation/sound/Introduction linux/Documentation/sound/Introduction
--- v2.4.1/linux/Documentation/sound/Introduction	Wed Sep 27 13:53:52 2000
+++ linux/Documentation/sound/Introduction	Fri Feb 16 15:53:08 2001
@@ -1,15 +1,19 @@
 Introduction	Notes on Modular Sound Drivers and Soundcore
 Wade Hampton 
-6/30/1999
+2/14/2001
 
 Purpose:  
 ========
 This document provides some general notes on the modular 
 sound drivers and their configuration, along with the 
-support modules sound.o, soundlow.o and soundcore.o.
+support modules sound.o and soundcore.o.
 
 Note, some of this probably should be added to the Sound-HOWTO!
 
+Note, soundlow.o was present with 2.2 kernels but is not 
+required for 2.4.x kernels.  References have been removed
+to this.
+
 
 Copying:
 ========
@@ -28,6 +32,8 @@
 1.1.1  19991031	   Added notes on sound-slot- and sound-service.
 			(Alan Cox)
 1.1.2  20000920    Modified for Kernel 2.4 (Christoph Hellwig)
+1.1.3  20010214    Minor notes and corrections (Wade Hampton)
+                   Added examples of sound-slot-0, etc.
 
 
 Modular Sound Drivers:
@@ -69,8 +75,9 @@
 
 1.  There is a new OpenSource sound driver called ALSA which is
     currently under development:  http://www.alsa-project.org/
-    I have not tried it nor am I aware of its status, but it is
-    currently under development.
+    The ALSA drivers support some newer hardware that may not 
+    be supported by this sound driver and also provide some 
+    additional features.
 
 2.  The commercial OSS driver may be obtained from the site:
     http://www/opensound.com.  This may be used for cards that
@@ -82,7 +89,8 @@
     some of the requirements for multiple sound card systems.  For
     more information, see:  http://www.tux.org/~ricdude/EsounD.html  
     The "esd" program may be used with the real-player and mpeg 
-    players like mpg123 and x11amp.
+    players like mpg123 and x11amp.  The newer real-player 
+    and some games even include built-in support for ESD!
 
 
 Building the Modules:
@@ -104,13 +112,31 @@
 
 4.  Select your sound driver(s) as a module.  For ProAudio, Sound
     Blaster, etc., select M (module) for OSS sound modules.
-    [thanks to marvin stodolsky <stodolsk@erols.com>]A
+    [thanks to Marvin Stodolsky <stodolsk@erols.com>]A
 
 5.  Make the kernel (e.g., make dep ; make bzImage), and install
     the kernel.
 
 6.  Make the modules and install them (make modules; make modules_install).
 
+Note, for 2.4.x kernels, make sure you have the newer modutils 
+loaded or modules will not be loaded properly.  2.4.x changed the 
+layout of /lib/modules/2.4.x and requires an updated modutils.
+
+
+Plug and Play (PnP:
+===================
+
+If the sound card is an ISA PnP card, isapnp may be used
+to configure the card.  See the file isapnp.txt in the 
+directory one level up (e.g., /usr/src/linux/Documentation).
+
+Also the 2.4.x kernels provide PnP capabilities, see the 
+file NEWS in this directory.
+
+PCI sound cards are highly recommended, as they are far 
+easier to configure and from what I have read, they use
+less resources and are more CPU efficient.
 
 
 INSMOD:
@@ -129,7 +155,6 @@
 #
 echo Starting sound
 /sbin/insmod soundcore
-/sbin/insmod soundlow
 /sbin/insmod sound  
 #
 echo Starting sound blaster....
@@ -160,6 +185,10 @@
 The status of sound may be read/checked by:
         cat (anyfile).au >/dev/audio
 
+[WWH:  This may not work properly for SoundBlaster PCI 128 cards
+such as the es1370/1 (see the es1370/1 files in this directory) 
+as they do not automatically support uLaw on /dev/audio.]
+
 The status of the modules and which modules depend on 
 which other modules may be checked by:
 	/sbin/lsmod
@@ -168,7 +197,6 @@
 	sb                     26280   0 
 	uart401                 5640   0  [sb]
 	sound                  57112   0  [sb uart401]
-	soundlow                 208   0  [sound]
 	soundcore               1968   8  [sb sound]
 
 
@@ -186,7 +214,6 @@
 /sbin/rmmod sb
 /sbin/rmmod uart401
 /sbin/rmmod sound
-/sbin/rmmod soundlow
 /sbin/rmmod soundcore
 
 When using sound as a module, I typically put these commands
@@ -217,7 +244,8 @@
 Typically, you need two sound cards of different types.  Note, this
 uses more precious interrupts and DMA channels and sometimes 
 can be a configuration nightmare.  I have heard reports of 3-4
-sound cards (typically I only use 2).
+sound cards (typically I only use 2).  You can sometimes use
+multiple PCI sound cards of the same type.
 
 On my machine I have two sound cards (cs4232 and Soundblaster Vibra
 16).  By loading sound as modules, I can control which is the first
@@ -236,7 +264,7 @@
 
 1.  Copy the sound modules to a new name.  For example
     sb.o could be copied (or symlinked) to sb1.o for the
-    second SoundBlasster.
+    second SoundBlaster.
 
 2.  Make a second entry in /etc/modules.conf, for example,
     sound1 or sb1.  This second entry should refer to the
@@ -257,6 +285,7 @@
 supports multiple cards with one module by default.
 Read the file 'Soundblaster' in this directory for details.
 
+
 Sound Problems:
 ===============
 
@@ -314,7 +343,6 @@
     esddsp <program> may be used to play files via a non-esd
     aware program.
 
-
 6)  Ask for help on the sound list or send E-MAIL to the
     sound driver author/maintainer.
 
@@ -327,6 +355,9 @@
 
     This makes the sound system allocate its buffers and hang onto them.
 
+    You may also set persistent DMA when building a 2.4.x kernel.
+
+
 Configuring Sound:
 ==================
 
@@ -354,10 +385,11 @@
 
 Anyone want to write a linuxconf module for configuring sound?
 
+
 Module Loading:
 ===============
 
-When a sound card is first referenced and sound is modular the sound system
+When a sound card is first referenced and sound is modular, the sound system
 will ask for the sound devices to be loaded. Initially it requests that
 the driver for the sound system is loaded. It then will ask for 
 sound-slot-0, where 0 is the first sound card. (sound-slot-1 the second and
@@ -370,11 +402,32 @@
 a midi synth in all cases then it will request "sound-service-0-n" where n
 is
 
-0	Mixer
+  0	Mixer
+
+  2  	MIDI
+
+  3, 4	DSP audio
+
 
-2  	MIDI
+For example, I use the following to load my Soundblaster PCI 128
+(ES 1371) card first, followed by my SoundBlaster Vibra 16 card,
+then by my TV card:
 
-3, 4	DSP audio
+# Load the Soundblaster PCI 128 as /dev/dsp, /dev/dsp1, /dev/mixer
+alias sound-slot-0 es1371
+
+# Load the Soundblaster Vibra 16 as /dev/dsp2, /dev/mixer1
+alias sound-slot-1 sb
+options sb io=0x240 irq=5 dma=1 dma16=5 mpu_io=0x330
+
+# Load the BTTV (TV card) as /dev/mixer2
+alias sound-slot-2 bttv
+alias sound-service-2-0 tvmixer
+
+pre-install bttv  modprobe tuner ; modprobe tvmixer
+pre-install tvmixer modprobe msp3400; modprobe tvaudio 
+options tuner debug=0 type=8 
+options bttv  card=0 radio=0 pll=0
 
 
 For More Information (RTFM):
@@ -405,3 +458,4 @@
 Contact Information:
 ====================
 Wade Hampton:  (whampton@staffnet.com)
+
diff -u --recursive --new-file v2.4.1/linux/Documentation/sound/Maestro3 linux/Documentation/sound/Maestro3
--- v2.4.1/linux/Documentation/sound/Maestro3	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sound/Maestro3	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,84 @@
+	An OSS/Lite Driver for the ESS Maestro3 family of sound chips
+
+			Zach Brown, January 2001
+
+Driver Status and Availability
+------------------------------
+
+The most recent version of this driver will hopefully always be available at
+	http://www.zabbo.net/maestro3/
+
+I will try and maintain the most recent stable version of the driver
+in both the stable and development kernel lines.
+
+Historically I've sucked pretty hard at actually doing that, however.
+
+ESS Maestro3 Chip Family
+-----------------------
+
+The 'Maestro3' is much like the Maestro2 chip.  The noted improvement
+is the removal of the silicon in the '2' that did PCM mixing.  All that
+work is now done through a custom DSP called the ASSP, the Asynchronus
+Specific Signal Processor.
+
+The 'Allegro' is a baby version of the Maestro3.  I'm not entirely clear
+on the extent of the differences, but the driver supports them both :)
+
+The 'Allegro' shows up as PCI ID 0x1988 and the Maestro3 as 0x1998,
+both under ESS's vendor ID of 0x125D.  The Maestro3 can also show up as
+0x199a when hardware strapping is used.
+
+The chip can also act as a multi function device.  The modem IDs follow
+the audio multimedia device IDs.  (so the modem part of an Allegro shows
+up as 0x1989)
+
+Driver OSS Behavior
+--------------------
+
+This OSS driver exports /dev/mixer and /dev/dsp to applications, which
+mostly adhere to the OSS spec.   This driver doesn't register itself
+with /dev/sndstat, so don't expect information to appear there.
+
+The /dev/dsp device exported behaves as expected.  Playback is
+supported in all the various lovely formats.  8/16bit stereo/mono from
+8khz to 48khz, with both read()/write(), and mmap().
+
+/dev/mixer is an interface to the AC'97 codec on the Maestro3.  It is
+worth noting that there are a variety of AC'97s that can be wired to
+the Maestro3.  Which is used is entirely up to the hardware implementor.
+This should only be visible to the user by the presence, or lack, of
+'Bass' and 'Treble' sliders in the mixer.  Not all AC'97s have them.
+The Allegro has an onchip AC'97.
+
+The driver doesn't support MIDI or FM playback at the moment.
+
+Compiling and Installing
+------------------------
+
+With the drivers inclusion into the kernel, compiling and installing
+is the same as most OSS/Lite modular sound drivers.  Compilation
+of the driver is enabled through the CONFIG_SOUND_MAESTRO3 variable
+in the config system.  
+
+It may be modular or statically linked.  If it is modular it should be
+installed with the rest of the modules for the kernel on the system.
+Typically this will be in /lib/modules/ somewhere.  'alias sound-slot-0
+maestro3' should also be added to your module configs (typically
+/etc/modules.conf) if you're using modular OSS/Lite sound and want to
+default to using a maestro3 chip.
+
+There are very few options to the driver.  One is 'debug' which will 
+tell the driver to print minimal debugging information as it runs.  This
+can be collected with 'dmesg' or through the klogd daemon.
+
+The other is 'external_amp', which tells the driver to attempt to enable
+an external amplifier.  This defaults to '1', you can tell the driver
+not to bother enabling such an amplifier by setting it to '0'.
+
+Power Management
+----------------
+
+This driver has a minimal understanding of PCI Power Management.  It will
+try and power down the chip when the system is suspended, and power
+it up with it is resumed.  It will also try and power down the chip
+when the machine is shut down.
diff -u --recursive --new-file v2.4.1/linux/Documentation/sound/NM256 linux/Documentation/sound/NM256
--- v2.4.1/linux/Documentation/sound/NM256	Mon Oct 25 08:26:52 1999
+++ linux/Documentation/sound/NM256	Sun Feb  4 10:05:29 2001
@@ -53,7 +53,7 @@
 compatible OSS driver with these chipsets.  I cannot provide any
 assistance with machines using the SB16, AD1848 or CS4232 compatible
 versions.  (The driver now attempts to detect the mixer version, and
-will refuse to load if it believes the hardware is not not
+will refuse to load if it believes the hardware is not
 AC97-compatible.)
 
 The sound support is very basic, but it does include simultaneous
diff -u --recursive --new-file v2.4.1/linux/Documentation/sound/OPL3-SA2 linux/Documentation/sound/OPL3-SA2
--- v2.4.1/linux/Documentation/sound/OPL3-SA2	Wed May 24 19:28:05 2000
+++ linux/Documentation/sound/OPL3-SA2	Sun Feb  4 10:05:29 2001
@@ -2,22 +2,26 @@
 ---------------------------------------------------------------
 
 Scott Murray, scott@spiteful.org
-January 5, 1999
+January 7, 2001
 
 NOTE: All trade-marked terms mentioned below are properties of their
       respective owners.
 
+
+Supported Devices
+-----------------
+
 This driver is for PnP soundcards based on the following Yamaha audio
 controller chipsets:
 
 YMF711 aka OPL3-SA2
-YMF715 aka OPL3-SA3
-YMF719 aka OPL3-SAx (?)
+YMF715 and YMF719 aka OPL3-SA3
 
-I'm a little fuzzy on what exactly is classified a SAx, as I've seen
-the label used to refer to the whole 7xx family and as a specific
-identifier for the 719 on my no-name soundcard.  To make matters
-worse, there seem to be several revisions of the 715 chipset.
+Up until recently (December 2000), I'd thought the 719 to be a
+different chipset, the OPL3-SAx.  After an email exhange with
+Yamaha, however, it turns out that the 719 is just a re-badged
+715, and the chipsets are identical.  The chipset detection code
+has been updated to refkect this.
 
 Anyways, all of these chipsets implement the following devices:
 
@@ -31,75 +35,142 @@
 device and the MSS device.  Since the MSS device has better
 capabilities, I have implemented the driver to use it.
 
-Being PnP cards, some configuration is required.  There are two ways
-of doing this.  The most common is to use the isapnptools package to
-initialize the card, and use the kernel module form of the sound
-subsystem and sound drivers.  Alternatively, some BIOS's allow manual
-configuration of installed PnP devices in a BIOS menu, which should
-allow using the non-modular sound drivers, i.e. built into the kernel.
+
+Mixer Channels
+--------------
+
+Older versions of this driver (pre-December 2000) had two mixers,
+an OPL3-SA2 or SA3 mixer and a MSS mixer.  The OPL3-SA[23] mixer
+device contained a superset of mixer channels consisting of its own
+channels and all of the MSS mixer channels.  To simplify the driver
+considerably, and to partition functionality better, the OPL3-SA[23]
+mixer device now contains has its own specific mixer channels.  They
+are:
+
+Volume     - Hardware master volume control
+Bass       - SA3 only, now supports left and right channels
+Treble     - SA3 only, now supports left and right channels
+Microphone - Hardware microphone input volume control
+Digital1   - Yamaha 3D enhancement "Wide" mixer
+
+All other mixer channels (e.g. "PCM", "CD", etc.) now have to be
+controlled via the "MS Sound System (CS4231)" mixer.  To facilitate
+this, the mixer device creation order has been switched so that
+the MSS mixer is created first.  This allows accessing the majority
+of the useful mixer channels even via single mixer-aware tools
+such as "aumix".
+
+
+Plug 'n Play
+------------
+
+In previous kernels (2.2.x), some configuration was required to
+get the driver to talk to the card.  Being the new millenium and
+all, the 2.4.x kernels now support auto-configuration if ISA PnP
+support is configured in.  Theoretically, the driver even supports
+having more than one card in this case.
+
+With the addition of PnP support to the driver, two new parameters
+have been added to control it:
+
+isapnp   - set to 0 to disable ISA PnP card detection
+
+multiple - set to 0 to disable multiple PnP card detection
+
+
+Optional Parameters
+-------------------
+
+Recent (December 2000) additions to the driver (based on a patch
+provided by Peter Englmaier) are two new parameters:
+
+ymode -    Set Yamaha 3D enhancement mode:
+           0 = Desktop/Normal  5-12 cm speakers
+           1 = Notebook PC (1) 3 cm speakers
+           2 = Notebook PC (2) 1.5 cm speakers
+           3 = Hi-Fi           16-38 cm speakers
+
+loopback - Set A/D input source. Useful for echo cancellation:
+           0 = Mic Right channel (default)
+           1 = Mono output loopback
+
+The ymode parameter has been tested and does work.  The loopback
+parameter, however, is untested.  Any feedback on its usefulness
+would be appreciated.
+
+
+Manual Configuration
+--------------------
+
+If for some reason you decide not to compile ISA PnP support into
+your kernel, or disabled the driver's usage of it by setting the
+isapnp parameter as discussed above, then you will need to do some
+manual configuration.  There are two ways of doing this.  The most
+common is to use the isapnptools package to initialize the card, and
+use the kernel module form of the sound subsystem and sound drivers.
+Alternatively, some BIOS's allow manual configuration of installed
+PnP devices in a BIOS menu, which should allow using the non-modular
+sound drivers, i.e. built into the kernel.
 
 I personally use isapnp and modules, and do not have access to a PnP
-BIOS machine to test.  If you have such a beast, try building both the
-MSS driver and this driver into the kernel (appropriately configured,
-of course).  I have received reports of this working, so it should be
-possible for most people with PnP BIOS.  If it does not work for you,
-then email me if you are willing to experiment in an effort to make it
-work.
-
-************************************************************************
-* I have now had two such machines, and I have fixed this to work
-* properly when built into the kernel.  The Toshiba Libretto series, or
-* at least models 70CT and 110CT which I have owned, use a Yamaha
-* OPL3-SAx (OPL3-SA3 according to documentation) sound chip, IRQ 5,
-* IO addresses 220/530/388/330/370 and DMA 1,0 (_not_ 0,1).  All these
-* configuration settings can be gathered by booting another OS which
-* recognizes the card already.
-*
-* I have made things 'just work' for the non-modular case on such
-* machines when configured properly.
-*
-* David Luyer <luyer@ucs.uwa.edu.au>
-************************************************************************
-
-If you are using isapnp, follow the directions in its documentation to
-produce a configuration file.  Here is the relevant excerpt I use for
-my SAx card from my isapnp.conf:
+BIOS machine to test.  If you have such a beast, configuring the
+driver to be built into the kernel should just work (thanks to work
+done by David Luyer <luyer@ucs.uwa.edu.au>).  You will still need
+to specify settings, which can be done by adding:
+
+opl3sa2=<io>,<irq>,<dma>,<dma2>,<mssio>,<mpuio>
+
+to the kernel command line.  For example:
+
+opl3sa2=0x370,5,0,1,0x530,0x330
+
+If you are instead using the isapnp tools (as most people have been
+before Linux 2.4.x), follow the directions in their documentation to
+produce a configuration file.  Here is the relevant excerpt I used to
+use for my SA3 card from my isapnp.conf:
 
 (CONFIGURE YMH0800/-1 (LD 0
 
-# Instead of (IO 0 (BASE 0x0220)), disable SB:
-(IO 0 (BASE 0x0000))
+# NOTE: IO 0 is for the unused SoundBlaster part of the chipset.
+(IO 0 (BASE 0x0220))
 (IO 1 (BASE 0x0530))
 (IO 2 (BASE 0x0388))
 (IO 3 (BASE 0x0330))
 (IO 4 (BASE 0x0370))
-(INT 0 (IRQ 7 (MODE +E)))
+(INT 0 (IRQ 5 (MODE +E)))
 (DMA 0 (CHANNEL 0))
-(DMA 1 (CHANNEL 3))
+(DMA 1 (CHANNEL 1))
 
 Here, note that:
 
 Port  Acceptable Range  Purpose
 ----  ----------------  -------
-IO 0  0x0220 - 0x0280   SB base address, I set to 0 just to be safe.
+IO 0  0x0220 - 0x0280   SB base address, unused.
 IO 1  0x0530 - 0x0F48   MSS base address
 IO 2  0x0388 - 0x03F8   OPL3 base address
 IO 3  0x0300 - 0x0334   MPU base address
 IO 4  0x0100 - 0x0FFE   card's own base address for its control I/O ports
 
-The IRQ and DMA values can be any that considered acceptable for a
+The IRQ and DMA values can be any that are considered acceptable for a
 MSS.  Assuming you've got isapnp all happy, then you should be able to
 do something like the following (which matches up with the isapnp
 configuration above):
 
-insmod mpu401
-insmod ad1848
-insmod opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
-insmod opl3 io=0x388
-
-Remember that the opl3sa2 module's io argument is for it's own control
-port, which handles the card's master mixer for volume (on all cards),
-and bass and treble (on SA3 and SAx cards).
+modprobe mpu401
+modprobe ad1848
+modprobe opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=5 dma=0 dma2=1
+modprobe opl3 io=0x388
+
+See the section "Automatic Module Loading" below for how to set up
+/etc/modules.conf to automate this.
+
+An important thing to remember that the opl3sa2 module's io argument is
+for it's own control port, which handles the card's master mixer for
+volume (on all cards), and bass and treble (on SA3 cards).
+
+
+Troubleshooting
+---------------
 
 If all goes well and you see no error messages, you should be able to
 start using the sound capabilities of your system.  If you get an
@@ -112,29 +183,27 @@
 
 If you still cannot get the module to load, look at the contents of
 your system log file, usually /var/log/messages.  If you see the
-message "Unknown Yamaha audio controller version", then you have a
-different chipset than I've encountered so far.  Look for a line in
-the log file that says "opl3sa2.c: chipset version = <some number>".
-If you want me to add support for your card, send me the number from
-this line and any information you have on the make and chipset of your
-sound card, and I should be able to work up a permanent fix.
-
-If you do not see the chipset version message, and none of the other
-messages present in the system log are helpful, email me some details
-and I'll try my best to help.
+message "opl3sa2: Unknown Yamaha audio controller version", then you
+have a different chipset version than I've encountered so far.  Look
+for all messages in the log file that start with "opl3sa2: " and see
+if they provide any clues.  If you do not see the chipset version
+message, and none of the other messages present in the system log are
+helpful, email me some details and I'll try my best to help.
+
+
+Automatic Module Loading
+------------------------
 
 Lastly, if you're using modules and want to set up automatic module
 loading with kmod, the kernel module loader, here is the section I
 currently use in my modules.conf file:
 
 # Sound
-alias char-major-14 opl3sa2
-pre-install opl3sa2 modprobe "-k" "ad1848"
-post-install opl3sa2 modprobe "-k" "opl3"
+alias sound-slot-0 opl3sa2
 options opl3sa2 io=0x370 mss_io=0x530 mpu_io=0x330 irq=7 dma=0 dma2=3
 options opl3 io=0x388
 
-That's all it currently takes to get an OPL3-SAx card working on my
+That's all it currently takes to get an OPL3-SA3 card working on my
 system.  Once again, if you have any other problems, email me at the
 address listed above.
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/sound/via82cxxx.txt linux/Documentation/sound/via82cxxx.txt
--- v2.4.1/linux/Documentation/sound/via82cxxx.txt	Tue Jun 20 07:52:36 2000
+++ linux/Documentation/sound/via82cxxx.txt	Wed Dec 31 16:00:00 1969
@@ -1,176 +0,0 @@
-			Via motherboard audio driver
-	Copyright 1999,2000 Jeff Garzik <jgarzik@mandrakesoft.com>
-
-Driver software and documentation distributed under the GNU GENERAL
-PUBLIC LICENSE (GPL) Version 2. See the "COPYING" file distributed with
-this software for more info.
-
-
-
-Introduction
-------------------------------------------------------------------------
-The via82cxxx audio driver found in the drivers/sound directory
-of the kernel source tree is a PCI audio driver for audio chips
-found on Via-based motherboards, such as the MVP4.
-
-Currently the driver exports the following features:
-
-	* /dev/dsp and /dev/audio support
-	* 16-bit stereo PCM output channel
-	* AC97 mixer
-
-Please send bug reports to the mailing list linux-via@gtf.org.
-To subscribe, e-mail majordomo@gtf.org with "subscribe linux-via" in the
-body of the message.
-
-
-Thanks
-------------------------------------------------------------------------
-Via for providing e-mail support, specs, and NDA'd source code.
-
-MandrakeSoft for providing hacking time.
-
-AC97 mixer interface fixes and debugging by Ron Cemer <roncemer@gte.net>
-
-
-
-Installation
-------------------------------------------------------------------------
-If the driver is being statically compiled into the kernel, no
-configuration should be necessary.
-
-If the driver is being compiled as a module, generally one line must
-be added to your /etc/conf.modules (or /etc/modules.conf) file:
-
-	alias sound via82cxxx_audio
-
-
-
-Driver notes
-------------------------------------------------------------------------
-Two /proc pseudo-files provide diagnostic information.  This is generally
-not useful to most users.  Power users can disable VIA_PROC_FS macro in the 
-driver source code, and remove the /proc support code.  In any case, once
-version 2.0.0 is released, the /proc support code will be disabled by
-default.  Available /proc pseudo-files:
-
-	/proc/driver/via/0/info
-	/proc/driver/via/0/ac97
-
-This driver by default supports all PCI audio devices which report
-a vendor id of 0x1106, and a device id of 0x3058.  Subsystem vendor
-and device ids are not examined.
-
-Only supports a single sound chip, as this is a motherboard chipset.
-Some architecture remains for multiple cards, feel free to submit
-a patch to clean some of that up.  Ideally, 
-
-No consideration for SMP, this chipset is not known to be found on
-any SMP motherboards.  However, spin_locks must be used anyway in order
-to handle interrupts correctly.
-
-GNU indent formatting options:  -kr -i8 -pcs
-
-
-
-Tested Hardware
-------------------------------------------------------------------------
-The following is an _incomplete_ list of motherboards supported by this
-audio driver.  If your motherboard (or notebook) is not listed here,
-please e-mail the maintainer with details.
-
-	AOpen MX59 Pro
-	Compaq Presario 1247
-
-
-
-Random Developer Notes / Comments
-------------------------------------------------------------------------
-Via has graciously donated e-mail support and source code to help further
-the development of this driver.  Their assistance has been invaluable
-in the design and coding of the next major version of this driver.
-
-The Via audio chip apparently provides a second PCM scatter-gather
-DMA channel just for FM data, but does not have a full hardware MIDI
-processor.  I haven't put much thought towards a solution here, but it
-might involve using SoftOSS midi wave table, or simply disabling MIDI
-support altogether and using the FM PCM channel as a second (input? output?)
-
-
-
-General To-do List (patches/suggestions welcome)
-------------------------------------------------------------------------
-Recording support
-
-mmap support
-
-Other advanced ioctls
-
-Better docs
-
-Code review
-
-Native MIDI driver, as described above
-
-
-
-Known bugs (patches/suggestions welcome)
-------------------------------------------------------------------------
-1) Volume too low on many systems.  Workaround:  use mixer program
-such as xmixer to increase volume.
-
-2) RealPlayer output very scratchy.  Workaround:  use esd, and
-configure RealPlayer to output to esd.
-
-3) Applications which attempt to open the sound device in read/write
-mode (O_RDWR) will fail.  This is incorrect OSS behavior, but since
-this driver will eventually support recording as well as playback,
-we will be able to (in the future) support even broken programs which
-unconditionally use O_RDWR.
-
-
-
-Submitting a bug report
-------------------------------------------------------------------------
-Describe the application you were using to play/record sound, and how
-to reproduce the problem.
-
-Obtain the via-audio-diag diagnostics program from
-http://gtf.org/garzik/drivers/via82cxxx/ and provide a dump of the
-audio chip's registers while the problem is occurring.  Sample command line:
-	./via-audio-diag -aps > diag-output.txt
-
-Define "VIA_DEBUG" at the beginning of the driver, then capture and email
-the kernel log output.  This can be viewed in the system kernel log (if
-enabled), or via the 'dmesg' program.
-
-If you wish to increase the size of the buffer displayed by 'dmesg', then
-change the LOG_BUF_LEN macro at the top of linux/kernel/printk.c, recompile
-your kernel, and pass the "-s <size>" option to 'dmesg'.
-
-
-
-Change history
-------------------------------------------------------------------------
-Version 1.1.7:
-* Fix module unload bug where mixer device left registered
-  after driver exit
-
-Version 1.1.6:
-* Rewrite via_set_rate to mimic ALSA basic AC97 rate setting
-* Remove much dead code
-* Complete spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
-* Fix build problem in via_dsp_ioctl
-* Optimize included headers to eliminate headers found in linux/drivers/sound
-
-Version 1.1.5:
-* Disable some overly-verbose debugging code
-* Remove unnecessary sound locks
-* Fix some ioctls for better time resolution
-* Begin spin_lock_irqsave -> spin_lock_irq conversion in via_dsp_ioctl
-
-Version 1.1.4:
-* Completed rewrite of driver.  Eliminated SoundBlaster compatibility
-  completely, and now uses the much-faster scatter-gather DMA engine.
-
-
diff -u --recursive --new-file v2.4.1/linux/Documentation/usb/uhci.txt linux/Documentation/usb/uhci.txt
--- v2.4.1/linux/Documentation/usb/uhci.txt	Fri Jul 28 12:50:52 2000
+++ linux/Documentation/usb/uhci.txt	Tue Feb 13 14:13:43 2001
@@ -33,7 +33,7 @@
 great USB-October-Revolution started by GA, DF, and TS ;-)
 
 Since the concept is in no way UHCI dependent, we hope that it will also be 
-transfered to the OHCI-driver, so both drivers share a common API.
+transferred to the OHCI-driver, so both drivers share a common API.
 
 1.2. Advantages and disadvantages
 
diff -u --recursive --new-file v2.4.1/linux/Documentation/usb/usb-serial.txt linux/Documentation/usb/usb-serial.txt
--- v2.4.1/linux/Documentation/usb/usb-serial.txt	Sat Feb  3 19:51:21 2001
+++ linux/Documentation/usb/usb-serial.txt	Thu Feb  8 16:30:40 2001
@@ -73,6 +73,11 @@
   the port to use for the HotSync transfer. The "Generic" port can be used
   for other device communication, such as a PPP link.
 
+  If after pressing the sync button, nothing shows up in the system log,
+  try resetting the Visor, first a hot reset, and then a cold reset if
+  necessary.  Some Visors need this before they can talk to the USB port
+  properly.
+  
   There is a webpage and mailing lists for this portion of the driver at: 
   http://usbvisor.sourceforge.net/
 
@@ -103,22 +108,22 @@
 
 Keyspan USA-series Serial Adapters
 
-  Single and Dual port adapters - driver uses Keyspan supplied 
+  Single, Dual and Quad port adapters - driver uses Keyspan supplied 
   firmware and is being developed with their support.
   
-  Driver isn't as far advanced as Keyspan PDA driver mentioned above.
-  
 Current status:
- Things that work:
-   Firmware upload for USA-18X, USA-28, USA-28X, USA-19 and USA-19W 
-   Simple character I/O fixed at 9600 baud on USA-19 only
-   
- Things that don't:
-   Everything else. (for now...)
+  The USA-18X, USA-28X, USA-19, USA-19W and USA-49W are supported and
+  have been pretty throughly tested at various baud rates with 8-N-1
+  character settings.  Other character lengths and parity setups are
+  presently untested.
+
+  The USA-28 isn't yet supported though doing so should be pretty
+  straightforward.  Contact the maintainer if you require this
+  functionality.
+  
+  More information is available at:
+        http://www.linuxcare.com.au/hugh/keyspan.html
    
- Big Things on the todo list:
-   Driver is in infancy, much functionality remains to be added
-
 
 FTDI Single Port Serial Driver
 
@@ -157,6 +162,7 @@
 Belkin USB Serial Adapter F5U103
 
   Single port DB-9/PS-2 serial adapter from Belkin with firmware by eTEK Labs.
+  The Peracom single port serial adapter also works with this driver.
 
 Current status:
   The following have been tested and work:
@@ -210,6 +216,11 @@
  The driver is generally working, though it still needs some more
  testing. It is derived from the Belkin USB Serial Adapter F5U103
  driver and its TODO list is valid for this driver as well.
+
+ This driver has also been found to work for other products, which have 
+ the same Vendor ID but different Product IDs. Sitecom's U232-P25 
+ serial converter uses Product ID 0x230 and Vendor ID 0x711 and works with 
+ this driver. Also, D-Link's DU-H3SP USB BAY also works with this driver.
 
 
 Generic Serial driver
diff -u --recursive --new-file v2.4.1/linux/Documentation/video4linux/bttv/CARDLIST linux/Documentation/video4linux/bttv/CARDLIST
--- v2.4.1/linux/Documentation/video4linux/bttv/CARDLIST	Sun Nov 12 20:47:19 2000
+++ linux/Documentation/video4linux/bttv/CARDLIST	Mon Feb 19 14:43:36 2001
@@ -38,36 +38,50 @@
   card=36 - Typhoon TView TV/FM Tuner
   card=37 - PixelView PlayTV pro
   card=38 - TView99 CPH063
-  card=39 - Pinnacle PCTV Rave
+  card=39 - Pinnacle PCTV Studio/Rave
   card=40 - STB2
   card=41 - AVerMedia TVPhone 98
   card=42 - ProVideo PV951
   card=43 - Little OnAir TV
   card=44 - Sigma TVII-FM
   card=45 - MATRIX-Vision MV-Delta 2
-  card=46 - Zoltrix Genie TV
+  card=46 - Zoltrix Genie TV/FM
   card=47 - Terratec TV/Radio+
   card=48 - Dynalink Magic TView 
   card=49 - GV-BCTV3
   card=50 - Prolink PV-BT878P+4E (PixelView PlayTV PAK)
   card=51 - Eagle Wireless Capricorn2 (bt878A)
-  card=52 - Pinnacle Studio PCTV Pro
-  card=53 - Typhoon TView RDS
+  card=52 - Pinnacle PCTV Studio Pro
+  card=53 - Typhoon TView RDS / FM Stereo
+  card=54 - Livetec 9415 TV
+  card=55 - BESTBUY Easy TV
+  card=56 - FlyVideo '98/FM
+  card=57 - GrandTec 'Grand Video Capture'
+  card=58 - Phoebe TV Master Only (No FM)
 
 tuner.o
-  type=0 - Temic PAL
+  type=0 - Temic PAL (4002 FH5)
   type=1 - Philips PAL_I
   type=2 - Philips NTSC
   type=3 - Philips SECAM
   type=4 - NoTuner
   type=5 - Philips PAL
-  type=6 - Temic NTSC
-  type=7 - Temic PAL_I
-  type=8 - Temic 4036 FY5 NTSC
+  type=6 - Temic NTSC (4032 FY5)
+  type=7 - Temic PAL_I (4062 FY5)
+  type=8 - Temic NTSC (4036 FY5)
   type=9 - Alps HSBH1
   type=10 - Alps TSBE1
   type=11 - Alps TSBB5
   type=12 - Alps TSBE5
   type=13 - Alps TSBC5
-  type=14 - Temic 4006FH5
+  type=14 - Temic PAL_I (4006FH5)
   type=15 - Alps TSCH6
+  type=16 - Temic PAL_DK (4016 FY5)
+  type=17 - Philips NTSC_M (MK2)
+  type=18 - Temic PAL_I (4066 FY5)
+  type=19 - Temic PAL* auto (4006 FN5)
+  type=20 - Temic PAL (4009 FR5)
+  type=21 - Temic NTSC (4039 FR5)
+  type=22 - Temic PAL/SECAM multi (4046 FM5)
+  type=23 - Philips PAL_DK
+  type=24 - Philips PAL/SECAM multi (FQ1216ME)
diff -u --recursive --new-file v2.4.1/linux/Documentation/video4linux/bttv/Insmod-options linux/Documentation/video4linux/bttv/Insmod-options
--- v2.4.1/linux/Documentation/video4linux/bttv/Insmod-options	Sat Dec 30 11:23:13 2000
+++ linux/Documentation/video4linux/bttv/Insmod-options	Mon Feb 19 14:43:36 2001
@@ -30,6 +30,12 @@
 				default is 2.
 		gbufsize=	size of capture buffers. default and
 				maximum value is 0x208000 (~2MB)
+		no_overlay=0	Enable overlay on broken hardware.  There
+				are some chipsets (SIS for example) which
+				are known to have problems with the PCI DMA
+				push used by bttv.  bttv will disable overlay
+				by default on this hardware to avoid crashes.
+				With this insmod option you can override this.
 
 		bttv_gpio=0/1
 		gpiomask=
@@ -48,6 +54,8 @@
 		debug=1		print some debug info to the syslog
 		type=n		type of the tuner chip. n as follows:
 				see CARDLIST for a complete list.
+		pal=[bdgil]	select PAL variant (used for some tuners
+				only, important for the audio carrier).
 
 tvmixer.o
 	registers a mixer device for the TV card's volume/bass/treble
diff -u --recursive --new-file v2.4.1/linux/Documentation/video4linux/bttv/README linux/Documentation/video4linux/bttv/README
--- v2.4.1/linux/Documentation/video4linux/bttv/README	Sat Dec 30 11:23:13 2000
+++ linux/Documentation/video4linux/bttv/README	Mon Feb 19 14:43:36 2001
@@ -16,9 +16,10 @@
 kernel, download it from:
 	http://www2.lm-sensors.nu/~lm78/download.html
 
-You'll need at least these i2c config options for bttv:
+You'll need at least these config options for bttv:
 CONFIG_I2C=m
 CONFIG_I2C_ALGOBIT=m
+CONFIG_VIDEO_DEV=m
 
 The latest bttv version is available here:
 	http://www.strusel007.de/linux/bttv/
@@ -50,12 +51,8 @@
 Make bttv work with your card
 -----------------------------
 
-Of course you have to load the modules as very first thing.  The
-separate bttv bundle comes with a script called "update".  I use this
-one to load a new version while doing driver hacking.  You can use it
-too, but check the module arguments first.  They work for my setup,
-and probably do *not* for yours.  Another way is to setup your
-/etc/modules.conf file and let kmod load the modules.  See also:
+Setup your /etc/modules.conf file and let kmod load the modules.
+See also:
 
 Modules.conf:	some sample entries for /etc/modules.conf
 Insmod-options:	list of all insmod options available for bttv and
@@ -68,15 +65,45 @@
 to load them automagically by calling request_module() now, but this
 obviously works only with kmod enabled.
 
+If bttv takes very long to load (happens sometimes with the cheap
+cards which have no tuner), try adding this to your modules.conf:
+	options i2c-algo-bit bit_test=1
+
 The most important insmod option for bttv is "card=n" to select the
-correct card type.  If you get video but no sound you've very likely
-specified the wrong (or no) card type.  A list of supported cards is
-in CARDLIST.
+correct card type in case the autodetection does'nt work. If you get
+video but no sound you've very likely specified the wrong (or no)
+card type.  A list of supported cards is in CARDLIST.
 
 If your card isn't listed in CARDLIST or if you have trouble making
 audio work, you should read the Sound-FAQ.
 
 
+Autodetecting cards
+-------------------
+
+bttv uses the PCI Subsystem ID to autodetect the card type.  lspci lists
+the Subsystem ID in the second line, looks like this:
+
+00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02)
+        Subsystem: Hauppauge computer works Inc. WinTV/GO
+        Flags: bus master, medium devsel, latency 32, IRQ 5
+        Memory at e2000000 (32-bit, prefetchable) [size=4K]
+
+only bt878-based cards can have a subsystem ID (which does not mean
+that every card really has one).  bt848 cards can't have a Subsystem
+ID and therefore can't be autodetected.  There is a list with the ID's
+in bttv-cards.c (in case you are intrested or want to mail patches
+with updates).
+
+Old driver versions used to have a heuristic which could identify some
+bt848-based cards.  It worked for Hauppauge and Miro cards in most
+cases (simply because these where the first cards available on the
+market), but misdetected other bt848 cards.  That code is gone now for
+exactly this reason, the misdetection confused lots of people.  If you
+have a old Hauppauge or Miro card, you'll have to load the driver with
+card=1 or card=2 these days.
+
+
 Still doesn't work?
 -------------------
 
@@ -87,10 +114,12 @@
 yourself (patches very welcome of course...)  You know: The linux
 slogan is "Do it yourself".
 
-There is a mailing list: video4linux-list@redhat.com.  If you have
-trouble with some specific TV card, try to ask there instead of
-mailing me directly.  The chance that someone with the same card
-listens there is much higher...
+There is a mailing list: video4linux-list@redhat.com.
+https://listman.redhat.com/mailman/listinfo/video4linux-list
+
+If you have trouble with some specific TV card, try to ask there
+instead of mailing me directly.  The chance that someone with the
+same card listens there is much higher...
 
 For problems with sound:  There are alot of different systems used
 for TV sound all over the world.  And there are also different chips
diff -u --recursive --new-file v2.4.1/linux/Documentation/video4linux/bttv/Sound-FAQ linux/Documentation/video4linux/bttv/Sound-FAQ
--- v2.4.1/linux/Documentation/video4linux/bttv/Sound-FAQ	Sun Nov 12 20:47:19 2000
+++ linux/Documentation/video4linux/bttv/Sound-FAQ	Mon Feb 19 14:43:36 2001
@@ -79,10 +79,12 @@
 What you have to do is figure out the correct values for gpiomask and
 the audiomux array.  If you have Windows and the drivers four your
 card installed, you might to check out if you can read these registers
-values used by the windows driver.  A tool to do this is available
-from ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil (doesn't
-work with bt878 boards according to some reports I received).  You
-might also dig around in the *.ini files of the Windows applications.
+values used by the windows driver.  A tool to do this is available from
+ftp://telepresence.dmem.strath.ac.uk/pub/bt848/winutil, but it does'nt
+work with bt878 boards according to some reports I received.  Another
+one is available from http://www.kki.net.pl/~borgx/bTV.html.
+
+You might also dig around in the *.ini files of the Windows applications.
 You can have a look at the board to see which of the gpio pins are
 connected at all and then start trial-and-error ...
 
diff -u --recursive --new-file v2.4.1/linux/MAINTAINERS linux/MAINTAINERS
--- v2.4.1/linux/MAINTAINERS	Sat Feb  3 19:51:21 2001
+++ linux/MAINTAINERS	Mon Feb 19 10:18:18 2001
@@ -857,6 +857,14 @@
 M:	pavel@atrey.karlin.mff.cuni.cz
 S:	Maintained
 
+NETWORK DEVICE DRIVERS
+P:	Andrew Morton
+M:	andrewm@uow.edu.au
+P:	Jeff Garzik
+M:	jgarzik@mandrakesoft.com
+L:	linux-net@vger.kernel.org
+S:	Maintained
+
 NETWORKING [GENERAL]
 P:	Networking Team
 M:	netdev@oss.sgi.com
diff -u --recursive --new-file v2.4.1/linux/Makefile linux/Makefile
--- v2.4.1/linux/Makefile	Sat Feb  3 19:51:21 2001
+++ linux/Makefile	Wed Feb 21 16:54:15 2001
@@ -1,6 +1,6 @@
 VERSION = 2
 PATCHLEVEL = 4
-SUBLEVEL = 1
+SUBLEVEL = 2
 EXTRAVERSION =
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
@@ -110,7 +110,7 @@
 export SVGA_MODE = -DSVGA_MODE=NORMAL_VGA
 
 #
-# if you want the RAM disk device, define this to be the size in blocks.
+# If you want the RAM disk device, define this to be the size in blocks.
 # This is i386 specific.
 #
 
@@ -138,9 +138,9 @@
 DRIVERS-$(CONFIG_ISDN) += drivers/isdn/isdn.a
 DRIVERS-$(CONFIG_NET_FC) += drivers/net/fc/fc.o
 DRIVERS-$(CONFIG_APPLETALK) += drivers/net/appletalk/appletalk.o
-DRIVERS-$(CONFIG_TR) += drivers/net/tokenring/tr.a
+DRIVERS-$(CONFIG_TR) += drivers/net/tokenring/tr.o
 DRIVERS-$(CONFIG_WAN) += drivers/net/wan/wan.o
-DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnet.a
+DRIVERS-$(CONFIG_ARCNET) += drivers/net/arcnet/arcnetdrv.o
 DRIVERS-$(CONFIG_ATM) += drivers/atm/atm.o
 DRIVERS-$(CONFIG_IDE) += drivers/ide/idedriver.o
 DRIVERS-$(CONFIG_SCSI) += drivers/scsi/scsidrv.o
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/Makefile linux/arch/alpha/kernel/Makefile
--- v2.4.1/linux/arch/alpha/kernel/Makefile	Sat Feb  3 19:51:21 2001
+++ linux/arch/alpha/kernel/Makefile	Fri Feb  9 11:38:01 2001
@@ -30,9 +30,7 @@
 obj-y	 += console.o
 endif
 
-
 obj-$(CONFIG_SMP)    += smp.o irq_smp.o
-
 obj-$(CONFIG_PCI)    += pci.o pci_iommu.o
 
 ifdef CONFIG_ALPHA_GENERIC
@@ -76,7 +74,7 @@
 endif
 
 obj-$(CONFIG_ALPHA_EIGER) += sys_eiger.o
-obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o
+obj-$(CONFIG_ALPHA_JENSEN) += sys_jensen.o pci-noop.o
 obj-$(CONFIG_ALPHA_MIATA) += sys_miata.o
 obj-$(CONFIG_ALPHA_MIKASA) += sys_mikasa.o
 obj-$(CONFIG_ALPHA_NAUTILUS) += sys_nautilus.o
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/alpha_ksyms.c linux/arch/alpha/kernel/alpha_ksyms.c
--- v2.4.1/linux/arch/alpha/kernel/alpha_ksyms.c	Sun Nov 12 19:27:11 2000
+++ linux/arch/alpha/kernel/alpha_ksyms.c	Tue Feb 13 14:56:41 2001
@@ -98,9 +98,13 @@
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(__memsetw);
 EXPORT_SYMBOL(__constant_c_memset);
+EXPORT_SYMBOL(copy_page);
+EXPORT_SYMBOL(clear_page);
 
 EXPORT_SYMBOL(__direct_map_base);
 EXPORT_SYMBOL(__direct_map_size);
+
+#ifdef CONFIG_PCI
 EXPORT_SYMBOL(pci_alloc_consistent);
 EXPORT_SYMBOL(pci_free_consistent);
 EXPORT_SYMBOL(pci_map_single);
@@ -108,6 +112,7 @@
 EXPORT_SYMBOL(pci_map_sg);
 EXPORT_SYMBOL(pci_unmap_sg);
 EXPORT_SYMBOL(pci_dma_supported);
+#endif
 
 EXPORT_SYMBOL(dump_thread);
 EXPORT_SYMBOL(dump_fpu);
@@ -166,6 +171,7 @@
 EXPORT_SYMBOL(__up_wakeup);
 EXPORT_SYMBOL(down);
 EXPORT_SYMBOL(down_interruptible);
+EXPORT_SYMBOL(down_trylock);
 EXPORT_SYMBOL(up);
 EXPORT_SYMBOL(__down_read_failed);
 EXPORT_SYMBOL(__down_write_failed);
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/irq.c linux/arch/alpha/kernel/irq.c
--- v2.4.1/linux/arch/alpha/kernel/irq.c	Fri Nov 17 08:47:05 2000
+++ linux/arch/alpha/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/irq.h>
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/irq_alpha.c linux/arch/alpha/kernel/irq_alpha.c
--- v2.4.1/linux/arch/alpha/kernel/irq_alpha.c	Fri Aug  4 16:15:38 2000
+++ linux/arch/alpha/kernel/irq_alpha.c	Tue Feb 13 14:13:43 2001
@@ -18,7 +18,7 @@
 unsigned long __irq_attempt[NR_IRQS];
 #endif
 
-/* Hack minimum IPL during interupt processing for broken hardware.  */
+/* Hack minimum IPL during interrupt processing for broken hardware.  */
 #ifdef CONFIG_ALPHA_BROKEN_IRQ_MASK
 int __min_ipl;
 #endif
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.4.1/linux/arch/alpha/kernel/osf_sys.c	Sat Feb  3 19:51:21 2001
+++ linux/arch/alpha/kernel/osf_sys.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/utsname.h>
@@ -74,8 +74,10 @@
 	mm = current->mm;
 	mm->end_code = bss_start + bss_len;
 	mm->brk = bss_start + bss_len;
+#if 0
 	printk("set_program_attributes(%lx %lx %lx %lx)\n",
 		text_start, text_len, bss_start, bss_len);
+#endif
 	unlock_kernel();
 	return 0;
 }
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/pci-noop.c linux/arch/alpha/kernel/pci-noop.c
--- v2.4.1/linux/arch/alpha/kernel/pci-noop.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/kernel/pci-noop.c	Fri Feb  9 11:38:01 2001
@@ -0,0 +1,104 @@
+/*
+ *	linux/arch/alpha/kernel/pci-noop.c
+ *
+ * Stub PCI interfaces for Jensen-specific kernels.
+ */
+
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+
+#include "proto.h"
+
+
+/*
+ * The PCI controler list.
+ */
+
+struct pci_controler *hose_head, **hose_tail = &hose_head;
+struct pci_controler *pci_isa_hose;
+
+
+struct pci_controler * __init
+alloc_pci_controler(void)
+{
+	struct pci_controler *hose;
+
+	hose = alloc_bootmem(sizeof(*hose));
+
+	*hose_tail = hose;
+	hose_tail = &hose->next;
+
+	return hose;
+}
+
+struct resource * __init
+alloc_resource(void)
+{
+	struct resource *res;
+
+	res = alloc_bootmem(sizeof(*res));
+
+	return res;
+}
+
+asmlinkage long
+sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
+{
+	struct pci_controler *hose;
+	struct pci_dev *dev;
+
+	/* from hose or from bus.devfn */
+	if (which & IOBASE_FROM_HOSE) {
+		for (hose = hose_head; hose; hose = hose->next) 
+			if (hose->index == bus)
+				break;
+		if (!hose)
+			return -ENODEV;
+	} else {
+		/* Special hook for ISA access.  */
+		if (bus == 0 && dfn == 0)
+			hose = pci_isa_hose;
+		else
+			return -ENODEV;
+	}
+
+	switch (which & ~IOBASE_FROM_HOSE) {
+	case IOBASE_HOSE:
+		return hose->index;
+	case IOBASE_SPARSE_MEM:
+		return hose->sparse_mem_base;
+	case IOBASE_DENSE_MEM:
+		return hose->dense_mem_base;
+	case IOBASE_SPARSE_IO:
+		return hose->sparse_io_base;
+	case IOBASE_DENSE_IO:
+		return hose->dense_io_base;
+	case IOBASE_ROOT_BUS:
+		return hose->bus->number;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+asmlinkage long
+sys_pciconfig_read(unsigned long bus, unsigned long dfn,
+		   unsigned long off, unsigned long len, void *buf)
+{
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	else
+		return -ENODEV;
+}
+
+asmlinkage long
+sys_pciconfig_write(unsigned long bus, unsigned long dfn,
+		    unsigned long off, unsigned long len, void *buf)
+{
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+	else
+		return -ENODEV;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.4.1/linux/arch/alpha/kernel/process.c	Tue Sep  5 13:50:02 2000
+++ linux/arch/alpha/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/utsname.h>
@@ -416,22 +416,20 @@
  * Don't do this at home.
  */
 asmlinkage int
-sys_execve(unsigned long a0, unsigned long a1, unsigned long a2,
-	unsigned long a3, unsigned long a4, unsigned long a5,
-	struct pt_regs regs)
+sys_execve(char *ufilename, char **argv, char **envp,
+	   unsigned long a3, unsigned long a4, unsigned long a5,
+	   struct pt_regs regs)
 {
 	int error;
-	char * filename;
+	char *filename;
 
-	lock_kernel();
-	filename = getname((char *) a0);
+	filename = getname(ufilename);
 	error = PTR_ERR(filename);
 	if (IS_ERR(filename))
 		goto out;
-	error = do_execve(filename, (char **) a1, (char **) a2, &regs);
+	error = do_execve(filename, argv, envp, &regs);
 	putname(filename);
 out:
-	unlock_kernel();
 	return error;
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/ptrace.c linux/arch/alpha/kernel/ptrace.c
--- v2.4.1/linux/arch/alpha/kernel/ptrace.c	Mon Jun 19 17:59:32 2000
+++ linux/arch/alpha/kernel/ptrace.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/errno.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/setup.c linux/arch/alpha/kernel/setup.c
--- v2.4.1/linux/arch/alpha/kernel/setup.c	Tue Jan  2 16:45:37 2001
+++ linux/arch/alpha/kernel/setup.c	Fri Feb  9 11:29:44 2001
@@ -16,7 +16,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/smc37c669.c linux/arch/alpha/kernel/smc37c669.c
--- v2.4.1/linux/arch/alpha/kernel/smc37c669.c	Mon Jun 19 17:59:32 2000
+++ linux/arch/alpha/kernel/smc37c669.c	Fri Feb  9 11:29:44 2001
@@ -3,7 +3,7 @@
  */
 #include <linux/kernel.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/smc37c93x.c linux/arch/alpha/kernel/smc37c93x.c
--- v2.4.1/linux/arch/alpha/kernel/smc37c93x.c	Sat Nov 27 15:42:54 1999
+++ linux/arch/alpha/kernel/smc37c93x.c	Fri Feb  9 11:29:44 2001
@@ -5,7 +5,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/smp.c linux/arch/alpha/kernel/smp.c
--- v2.4.1/linux/arch/alpha/kernel/smp.c	Tue Jan  2 16:45:37 2001
+++ linux/arch/alpha/kernel/smp.c	Tue Feb 13 14:13:43 2001
@@ -837,7 +837,7 @@
 	atomic_set(&data.unstarted_count, smp_num_cpus - 1);
 	atomic_set(&data.unfinished_count, smp_num_cpus - 1);
 
-	/* Aquire the smp_call_function_data mutex.  */
+	/* Acquire the smp_call_function_data mutex.  */
 	if (pointer_lock(&smp_call_function_data, &data, retry))
 		return -EBUSY;
 
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/sys_ruffian.c linux/arch/alpha/kernel/sys_ruffian.c
--- v2.4.1/linux/arch/alpha/kernel/sys_ruffian.c	Mon Nov 27 17:50:12 2000
+++ linux/arch/alpha/kernel/sys_ruffian.c	Thu Feb  8 12:56:29 2001
@@ -92,14 +92,80 @@
 #endif
 }
 
+/*
+ *  Interrupt routing:
+ *
+ *		Primary bus
+ *	  IdSel		INTA	INTB	INTC	INTD
+ * 21052   13		  -	  -	  -	  -
+ * SIO	   14		 23	  -	  -	  -
+ * 21143   15		 44	  -	  -	  -
+ * Slot 0  17		 43	 42	 41	 40
+ *
+ *		Secondary bus
+ *	  IdSel		INTA	INTB	INTC	INTD
+ * Slot 0   8 (18)	 19	 18	 17	 16
+ * Slot 1   9 (19)	 31	 30	 29	 28
+ * Slot 2  10 (20)	 27	 26	 25	 24
+ * Slot 3  11 (21)	 39	 38	 37	 36
+ * Slot 4  12 (22)	 35	 34	 33	 32
+ * 53c875  13 (23)	 20	  -	  -	  -
+ *
+ */
+
 static int __init
 ruffian_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
-	/* We don't know anything about the PCI routing, so leave
-	   the IRQ unchanged.  */
-	return dev->irq;
+        static char irq_tab[11][5] __initdata = {
+	      /*INT  INTA INTB INTC INTD */
+		{-1,  -1,  -1,  -1,  -1},  /* IdSel 13,  21052	     */
+		{-1,  -1,  -1,  -1,  -1},  /* IdSel 14,  SIO	     */
+		{44,  44,  44,  44,  44},  /* IdSel 15,  21143	     */
+		{-1,  -1,  -1,  -1,  -1},  /* IdSel 16,  none	     */
+		{43,  43,  42,  41,  40},  /* IdSel 17,  64-bit slot */
+		/* the next 6 are actually on PCI bus 1, across the bridge */
+		{19,  19,  18,  17,  16},  /* IdSel  8,  slot 0	     */
+		{31,  31,  30,  29,  28},  /* IdSel  9,  slot 1	     */
+		{27,  27,  26,  25,  24},  /* IdSel 10,  slot 2	     */
+		{39,  39,  38,  37,  36},  /* IdSel 11,  slot 3	     */
+		{35,  35,  34,  33,  32},  /* IdSel 12,  slot 4	     */
+		{20,  20,  20,  20,  20},  /* IdSel 13,  53c875	     */
+        };
+	const long min_idsel = 13, max_idsel = 23, irqs_per_slot = 5;
+	return COMMON_TABLE_LOOKUP;
 }
 
+static u8 __init
+ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+	int slot, pin = *pinp;
+
+	if (dev->bus->number == 0) {
+		slot = PCI_SLOT(dev->devfn);
+	}		
+	/* Check for the built-in bridge.  */
+	else if (PCI_SLOT(dev->bus->self->devfn) == 13) {
+		slot = PCI_SLOT(dev->devfn) + 10;
+	}
+	else 
+	{
+		/* Must be a card-based bridge.  */
+		do {
+			if (PCI_SLOT(dev->bus->self->devfn) == 13) {
+				slot = PCI_SLOT(dev->devfn) + 10;
+				break;
+			}
+			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+
+			/* Move up the chain of bridges.  */
+			dev = dev->bus->self;
+			/* Slot of the next bridge.  */
+			slot = PCI_SLOT(dev->devfn);
+		} while (dev->bus->self);
+	}
+	*pinp = pin;
+	return slot;
+}
 
 #ifdef BUILDING_FOR_MILO
 /*
@@ -164,6 +230,6 @@
 	init_pci:		cia_init_pci,
 	kill_arch:		ruffian_kill_arch,
 	pci_map_irq:		ruffian_map_irq,
-	pci_swizzle:		common_swizzle,
+	pci_swizzle:		ruffian_swizzle,
 };
 ALIAS_MV(ruffian)
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/kernel/traps.c linux/arch/alpha/kernel/traps.c
--- v2.4.1/linux/arch/alpha/kernel/traps.c	Mon Jun 19 17:59:33 2000
+++ linux/arch/alpha/kernel/traps.c	Thu Feb  8 12:56:29 2001
@@ -1093,7 +1093,9 @@
 {
 	/* We only get here for OSF system calls, minus #112;
 	   the rest go to sys_ni_syscall.  */
+#if 0
 	printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
+#endif
 	return -ENOSYS;
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/lib/Makefile linux/arch/alpha/lib/Makefile
--- v2.4.1/linux/arch/alpha/lib/Makefile	Sat Dec 30 11:13:36 2000
+++ linux/arch/alpha/lib/Makefile	Thu Feb  8 12:56:29 2001
@@ -42,6 +42,8 @@
 	$(ev6)strncpy_from_user.o \
 	$(ev67)strlen_user.o \
 	$(ev6)csum_ipv6_magic.o \
+	$(ev6)clear_page.o \
+	$(ev6)copy_page.o \
 	strcasecmp.o \
 	fpreg.o \
 	callback_srm.o srm_puts.o srm_printk.o
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/lib/clear_page.S linux/arch/alpha/lib/clear_page.S
--- v2.4.1/linux/arch/alpha/lib/clear_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/lib/clear_page.S	Thu Feb  8 12:56:29 2001
@@ -0,0 +1,39 @@
+/*
+ * arch/alpha/lib/clear_page.S
+ *
+ * Zero an entire page.
+ */
+
+	.text
+	.align 4
+	.global clear_page
+	.ent clear_page
+clear_page:
+	.prologue 0
+
+	lda	$0,128
+	nop
+	unop
+	nop
+
+1:	stq	$31,0($16)
+	stq	$31,8($16)
+	stq	$31,16($16)
+	stq	$31,24($16)
+
+	stq	$31,32($16)
+	stq	$31,40($16)
+	stq	$31,48($16)
+	subq	$0,1,$0
+
+	stq	$31,56($16)
+	addq	$16,64,$16
+	unop
+	bne	$0,1b
+
+	ret
+	nop
+	unop
+	nop
+
+	.end clear_page
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/lib/copy_page.S linux/arch/alpha/lib/copy_page.S
--- v2.4.1/linux/arch/alpha/lib/copy_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/lib/copy_page.S	Thu Feb  8 12:56:29 2001
@@ -0,0 +1,49 @@
+/*
+ * arch/alpha/lib/copy_page.S
+ *
+ * Copy an entire page.
+ */
+
+	.text
+	.align 4
+	.global copy_page
+	.ent copy_page
+copy_page:
+	.prologue 0
+
+	lda	$18,128
+	nop
+	unop
+	nop
+
+1:	ldq	$0,0($17)
+	ldq	$1,8($17)
+	ldq	$2,16($17)
+	ldq	$3,24($17)
+
+	ldq	$4,32($17)
+	ldq	$5,40($17)
+	ldq	$6,48($17)
+	ldq	$7,56($17)
+
+	stq	$0,0($16)
+	subq	$18,1,$18
+	stq	$1,8($16)
+	addq	$17,64,$17
+
+	stq	$2,16($16)
+	stq	$3,24($16)
+	stq	$4,32($16)
+	stq	$5,40($16)
+
+	stq	$6,48($16)
+	stq	$7,56($16)
+	addq	$16,64,$16
+	bne	$18, 1b
+
+	ret
+	nop
+	unop
+	nop
+
+	.end copy_page
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/lib/ev6-clear_page.S linux/arch/alpha/lib/ev6-clear_page.S
--- v2.4.1/linux/arch/alpha/lib/ev6-clear_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/lib/ev6-clear_page.S	Thu Feb  8 12:56:29 2001
@@ -0,0 +1,54 @@
+/*
+ * arch/alpha/lib/ev6-clear_page.S
+ *
+ * Zero an entire page.
+ */
+
+        .text
+        .align 4
+        .global clear_page
+        .ent clear_page
+clear_page:
+        .prologue 0
+
+	lda	$0,128
+	lda	$1,125
+	addq	$16,64,$2
+	addq	$16,128,$3
+
+	addq	$16,192,$17
+	wh64	($16)
+	wh64	($2)
+	wh64	($3)
+
+1:	wh64	($17)
+	stq	$31,0($16)
+	subq	$0,1,$0
+	subq	$1,1,$1
+
+	stq	$31,8($16)
+	stq	$31,16($16)
+	addq	$17,64,$2
+	nop
+
+	stq	$31,24($16)
+	stq	$31,32($16)
+	cmovgt	$1,$2,$17
+	nop
+
+	stq	$31,40($16)
+	stq	$31,48($16)
+	nop
+	nop
+
+	stq	$31,56($16)
+	addq	$16,64,$16
+	nop
+	bne	$0,1b
+
+	ret
+	nop
+	nop
+	nop
+
+	.end clear_page
diff -u --recursive --new-file v2.4.1/linux/arch/alpha/lib/ev6-copy_page.S linux/arch/alpha/lib/ev6-copy_page.S
--- v2.4.1/linux/arch/alpha/lib/ev6-copy_page.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/alpha/lib/ev6-copy_page.S	Thu Feb  8 12:56:29 2001
@@ -0,0 +1,203 @@
+/*
+ * arch/alpha/lib/ev6-copy_page.S
+ *
+ * Copy an entire page.
+ */
+
+/* The following comparison of this routine vs the normal copy_page.S
+   was written by an unnamed ev6 hardware designer and forwarded to me
+   via Steven Hobbs <hobbs@steven.zko.dec.com>.
+ 
+   First Problem: STQ overflows.
+   -----------------------------
+
+	It would be nice if EV6 handled every resource overflow efficiently,
+	but for some it doesn't.  Including store queue overflows.  It causes
+	a trap and a restart of the pipe.
+
+	To get around this we sometimes use (to borrow a term from a VSSAD
+	researcher) "aeration".  The idea is to slow the rate at which the
+	processor receives valid instructions by inserting nops in the fetch
+	path.  In doing so, you can prevent the overflow and actually make
+	the code run faster.  You can, of course, take advantage of the fact
+	that the processor can fetch at most 4 aligned instructions per cycle.
+
+	I inserted enough nops to force it to take 10 cycles to fetch the
+	loop code.  In theory, EV6 should be able to execute this loop in
+	9 cycles but I was not able to get it to run that fast -- the initial
+	conditions were such that I could not reach this optimum rate on
+	(chaotic) EV6.  I wrote the code such that everything would issue
+	in order. 
+
+   Second Problem: Dcache index matches.
+   -------------------------------------
+
+	If you are going to use this routine on random aligned pages, there
+	is a 25% chance that the pages will be at the same dcache indices.
+	This results in many nasty memory traps without care.
+
+	The solution is to schedule the prefetches to avoid the memory
+	conflicts.  I schedule the wh64 prefetches farther ahead of the
+	read prefetches to avoid this problem.
+
+   Third Problem: Needs more prefetching.
+   --------------------------------------
+
+	In order to improve the code I added deeper prefetching to take the
+	most advantage of EV6's bandwidth.
+
+	I also prefetched the read stream. Note that adding the read prefetch
+	forced me to add another cycle to the inner-most kernel - up to 11
+	from the original 8 cycles per iteration.  We could improve performance
+	further by unrolling the loop and doing multiple prefetches per cycle.
+
+   I think that the code below will be very robust and fast code for the
+   purposes of copying aligned pages.  It is slower when both source and
+   destination pages are in the dcache, but it is my guess that this is
+   less important than the dcache miss case.  */
+
+
+	.text
+	.align 4
+	.global copy_page
+	.ent copy_page
+copy_page:
+	.prologue 0
+
+	/* Prefetch 5 read cachelines; write-hint 10 cache lines.  */
+	wh64	($16)
+	ldl	$31,0($17)
+	ldl	$31,64($17)
+	lda	$1,1*64($16)
+
+	wh64	($1)
+	ldl	$31,128($17)
+	ldl	$31,192($17)
+	lda	$1,2*64($16)
+
+	wh64	($1)
+	ldl	$31,256($17)
+	lda	$18,118
+	lda	$1,3*64($16)
+
+	wh64	($1)
+	nop
+	lda	$1,4*64($16)
+	lda	$2,5*64($16)
+
+	wh64	($1)
+	wh64	($2)
+	lda	$1,6*64($16)
+	lda	$2,7*64($16)
+
+	wh64	($1)
+	wh64	($2)
+	lda	$1,8*64($16)
+	lda	$2,9*64($16)
+
+	wh64	($1)
+	wh64	($2)
+	lda	$19,10*64($16)
+	nop
+
+	/* Main prefetching/write-hinting loop.  */
+1:	ldq	$0,0($17)
+	ldq	$1,8($17)
+	unop
+	unop
+
+	unop
+	unop
+	ldq	$2,16($17)
+	ldq	$3,24($17)
+
+	ldq	$4,32($17)
+	ldq	$5,40($17)
+	unop
+	unop
+
+	unop
+	unop
+	ldq	$6,48($17)
+	ldq	$7,56($17)
+
+	ldl	$31,320($17)
+	unop
+	unop
+	unop
+
+	/* This gives the extra cycle of aeration above the minimum.  */
+	unop			
+	unop
+	unop
+	unop
+
+	wh64	($19)
+	unop
+	unop
+	unop
+
+	stq	$0,0($16)
+	subq	$18,1,$18
+	stq	$1,8($16)
+	unop
+
+	unop
+	stq	$2,16($16)
+	addq	$17,64,$17
+	stq	$3,24($16)
+
+	stq	$4,32($16)
+	stq	$5,40($16)
+	addq	$19,64,$19
+	unop
+
+	stq	$6,48($16)
+	stq	$7,56($16)
+	addq	$16,64,$16
+	bne	$18, 1b
+
+	/* Prefetch the final 5 cache lines of the read stream.  */
+	lda	$18,10
+	ldl	$31,320($17)
+	ldl	$31,384($17)
+	ldl	$31,448($17)
+
+	ldl	$31,512($17)
+	ldl	$31,576($17)
+	nop
+	nop
+
+	/* Non-prefetching, non-write-hinting cleanup loop for the
+	   final 10 cache lines.  */
+2:	ldq	$0,0($17)
+	ldq	$1,8($17)
+	ldq	$2,16($17)
+	ldq	$3,24($17)
+
+	ldq	$4,32($17)
+	ldq	$5,40($17)
+	ldq	$6,48($17)
+	ldq	$7,56($17)
+
+	stq	$0,0($16)
+	subq	$18,1,$18
+	stq	$1,8($16)
+	addq	$17,64,$17
+
+	stq	$2,16($16)
+	stq	$3,24($16)
+	stq	$4,32($16)
+	stq	$5,40($16)
+
+	stq	$6,48($16)
+	stq	$7,56($16)
+	addq	$16,64,$16
+	bne	$18, 2b
+
+	ret
+	nop
+	unop
+	nop
+
+	.end copy_page
diff -u --recursive --new-file v2.4.1/linux/arch/arm/Makefile linux/arch/arm/Makefile
--- v2.4.1/linux/arch/arm/Makefile	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/Makefile	Thu Feb  8 16:32:44 2001
@@ -12,25 +12,18 @@
 #
 # Copyright (C) 1995-2000 by Russell King
 
-OBJCOPY		:= $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
-CPP		:= $(CC) -E
-LINKFLAGS	:= -p -X -T arch/arm/vmlinux.lds
-ARCHCC		:= $(word 1,$(CC))
-
-AFLAGS		+= -mno-fpu
-CFLAGS_PIPE	:= -pipe
-CFLAGS		:= $(CFLAGS) $(CFLAGS_PIPE) -msoft-float
+LINKFLAGS	:=-p -X -T arch/arm/vmlinux.lds
+GZFLAGS		:=-9
+CFLAGS		+=-fno-common -pipe
 
 ifdef CONFIG_FRAME_POINTER
-CFLAGS		:= $(CFLAGS:-fomit-frame-pointer=)
+CFLAGS		:=$(CFLAGS:-fomit-frame-pointer=)
 endif
 
 ifdef CONFIG_DEBUG_INFO
-CFLAGS		+= -g
+CFLAGS		+=-g
 endif
 
-GZFLAGS		= -9
-
 # Ensure this is ld "2.9.4" or later
 NEW_LINKER	:= $(shell $(LD) --gc-sections --version >/dev/null 2>&1; echo $$?)
 
@@ -40,61 +33,42 @@
 		@false
 endif
 
-# GCC 2.7 uses different options to later compilers; sort out which we have
-NEW_GCC		:= $(shell $(CC) --version 2>&1 | grep '^2\.7' > /dev/null; echo $$?)
-
-#
-# select flags depending on the compiler
+# Select CPU dependent flags.  Note that order of declaration is important;
+# the options further down the list override previous items.
 #
-ifneq ($(NEW_GCC),0)
-CFLAGS			+= -mshort-load-bytes
-CFLAGS_PROC_CPU_26	:= -mcpu=arm3 -mapcs-26 -Os
-CFLAGS_PROC_CPU_32v3	:= -march=armv3
-CFLAGS_PROC_CPU_32v4	:= -march=armv4
-else
-CFLAGS			+= -DNO_TEXT_SECTIONS
-CFLAGS_PROC_CPU_26	:= -m3
-CFLAGS_PROC_CPU_32v3	:= -m6
-CFLAGS_PROC_CPU_32v4	:= -m6
-endif
+apcs-$(CONFIG_CPU_26)		:=-mapcs-26 -mcpu=arm3 -Os
+apcs-$(CONFIG_CPU_32)		:=-mapcs-32
+
+arch-$(CONFIG_CPU_32v3)		:=-march=armv3
+arch-$(CONFIG_CPU_32v4)		:=-march=armv4
+arch-$(CONFIG_CPU_32v5)		:=-march=armv5
+
+proc-$(CONFIG_CPU_32v3)		:=-marmv3m
+proc-$(CONFIG_CPU_32v4)		:=-marmv4
+proc-$(CONFIG_CPU_32v5)		:=-marmv5
+
+tune-$(CONFIG_CPU_ARM610)	:=-mtune=arm610
+tune-$(CONFIG_CPU_ARM710)	:=-mtune=arm710
+tune-$(CONFIG_CPU_ARM720T)	:=-mtune=arm7tdmi
+tune-$(CONFIG_CPU_ARM920T)	:=-mtune=arm9tdmi
+tune-$(CONFIG_CPU_SA110)	:=-mtune=strongarm110
+tune-$(CONFIG_CPU_SA1100)	:=-mtune=strongarm1100
+
+CFLAGS		+= $(apcs-y) $(arch-y) $(tune-y) -mshort-load-bytes -msoft-float
+AFLAGS		+= $(apcs-y) $(proc-y) -mno-fpu
+
+LIBGCC		:= $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
 
-#
-# Select CPU dependent flags
-#
 ifeq ($(CONFIG_CPU_26),y)
- PROCESSOR	 = armo
- TEXTADDR	 = 0x02080000
- CFLAGS		+= $(CFLAGS_PROC_CPU_26)
- AFLAGS		+= -mapcs-26
+PROCESSOR	 = armo
+TEXTADDR	 = 0x02080000
 endif
 
 ifeq ($(CONFIG_CPU_32),y)
- PROCESSOR	 = armv
- TEXTADDR	 = 0xC0008000
- ifeq ($(CONFIG_CPU_32v4),y)
-  CFLAGS	+= $(CFLAGS_PROC_CPU_32v4)
-  AFLAGS	+= -mapcs-32 -marmv4
- else
-  CFLAGS	+= $(CFLAGS_PROC_CPU_32v3)
-  AFLAGS	+= -mapcs-32 -marmv3m
- endif
-
- opt-$(CONFIG_CPU_ARM6)		:= -mtune=arm6
- opt-$(CONFIG_CPU_ARM7)		:= -mtune=arm7
- opt-$(CONFIG_CPU_ARM720)	:= -mtune=arm7tdmi
- opt-$(CONFIG_CPU_ARM920)	:= -mtune=arm9tdmi
- opt-$(CONFIG_CPU_SA110)	:= -mtune=strongarm110
- opt-$(CONFIG_CPU_SA1100)	:= -mtune=strongarm110
-
- ifneq ($(NEW_GCC),0)
- CFLAGS	+= $(opt-y)
- endif
+PROCESSOR	 = armv
+TEXTADDR	 = 0xC0008000
 endif
 
-LIBGCC		:= $(shell $(CC) $(CFLAGS) --print-libgcc-file-name)
-
-export	LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS
-
 ifeq ($(CONFIG_ARCH_ARCA5K),y)
 MACHINE		 = arc
 endif
@@ -132,6 +106,10 @@
 endif
 
 ifeq ($(CONFIG_ARCH_SA1100),y)
+ifeq ($(CONFIG_SA1111),y)
+# SA1111 DMA bug: we don't want the kernel to live in precious DMA-able memory
+TEXTADDR	 = 0xc0208000
+endif
 MACHINE		 = sa1100
 endif
 
@@ -143,6 +121,13 @@
 MACHINE		 = integrator
 endif
 
+ifeq ($(CONFIG_ARCH_CLPS711X),y)
+TEXTADDR	 = 0xc0018000
+MACHINE		 = clps711x
+endif
+
+export	LIBGCC MACHINE PROCESSOR TEXTADDR GZFLAGS
+
 # Only set INCDIR if its not already defined above
 # Grr, ?= doesn't work as all the other assignment operators do.  Make bug?
 ifeq ($(origin INCDIR), undefined)
@@ -158,8 +143,7 @@
 
 HEAD		:= arch/arm/kernel/head-$(PROCESSOR).o \
 		   arch/arm/kernel/init_task.o
-SUBDIRS		+= arch/arm/kernel arch/arm/mm arch/arm/lib \
-		   arch/arm/nwfpe
+SUBDIRS		+= arch/arm/kernel arch/arm/mm arch/arm/lib arch/arm/nwfpe
 CORE_FILES	:= arch/arm/kernel/kernel.o arch/arm/mm/mm.o $(CORE_FILES)
 LIBS		:= arch/arm/lib/lib.o arch/arm/lib/lib.a $(LIBS) $(LIBGCC)
 
@@ -167,14 +151,6 @@
 LIBS		:= arch/arm/nwfpe/math-emu.o $(LIBS)
 endif
 
-ifeq ($(CONFIG_ARCH_ACORN),y)
-SUBDIRS		+= drivers/acorn
-DRIVERS		+= drivers/acorn/block/acorn-block.a
-DRIVERS		+= drivers/acorn/char/acorn-char.o
-DRIVERS		+= drivers/acorn/net/acorn-net.o
-DRIVERS		+= drivers/acorn/scsi/acorn-scsi.a
-endif
-
 ifeq ($(CONFIG_ARCH_CLPS7500),y)
 SUBDIRS		+= drivers/acorn/char
 DRIVERS		+= drivers/acorn/char/acorn-char.o
@@ -230,6 +206,7 @@
 Img:;	@$(MAKEBOOT) Image
 i:;	@$(MAKEBOOT) install
 zi:;	@$(MAKEBOOT) zinstall
+bp:;	@$(MAKEBOOT) bootpImage
 
 #
 # Configuration targets.  Use these to select a
@@ -237,9 +214,10 @@
 CFGS=	a5k_config		ebsa110_config		\
 	footbridge_config	rpc_config		\
 	brutus_config		victor_config		\
-	empeg_config		thinclient_config	\
+	empeg_config		graphicsclient_config	\
 	assabet_config		lart_config		\
-	cerf_config		lusl7200_config 
+	cerf_config		lusl7200_config 	\
+	sherman_config		pangolin_config
 
 $(CFGS):
 	@( \
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/Makefile linux/arch/arm/boot/Makefile
--- v2.4.1/linux/arch/arm/boot/Makefile	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/boot/Makefile	Thu Feb  8 16:32:44 2001
@@ -83,15 +83,18 @@
 ZRELADDR	 = 0xc0008000
 ifeq ($(CONFIG_SA1100_VICTOR),y)
   ZTEXTADDR	 = 0x00002000
-  ZBSSADDR	 = 0xc0100000
+  ZBSSADDR	 = 0xc0200000
 endif
 ifeq ($(CONFIG_SA1100_SHERMAN),y)
   ZTEXTADDR      = 0x00050000   
-  ZBSSADDR       = 0xc0100000
+  ZBSSADDR       = 0xc0200000
 endif
 ifeq ($(CONFIG_SA1100_GRAPHICSCLIENT),y)
   ZTEXTADDR	 = 0xC0200000
 endif
+ifeq ($(CONFIG_SA1111),y)
+  ZRELADDR	 = 0xc0208000
+endif
 endif
 
 #
@@ -105,15 +108,15 @@
 export	SYSTEM ZTEXTADDR ZBSSADDR ZRELADDR INITRD_PHYS INITRD_VIRT PARAMS_PHYS
 
 Image:	$(CONFIGURE) $(SYSTEM)
-	$(OBJCOPY) $(SYSTEM) $@
+	$(OBJCOPY) -O binary -R .note -R .comment -S $(SYSTEM) $@
 
 bzImage: zImage
 
 zImage:	$(CONFIGURE) compressed/vmlinux
-	$(OBJCOPY) compressed/vmlinux $@
+	$(OBJCOPY) -O binary -R .note -R .comment -S compressed/vmlinux $@
 
 bootpImage: bootp/bootp
-	$(OBJCOPY) bootp/bootp $@
+	$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@
 
 compressed/vmlinux: $(TOPDIR)/vmlinux dep
 	@$(MAKE) -C compressed vmlinux
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/bootp/Makefile linux/arch/arm/boot/bootp/Makefile
--- v2.4.1/linux/arch/arm/boot/bootp/Makefile	Sun Sep  3 11:19:11 2000
+++ linux/arch/arm/boot/bootp/Makefile	Thu Feb  8 16:32:44 2001
@@ -7,7 +7,8 @@
 ZLDFLAGS	=-p -X -T bootp.lds \
 		 --defsym initrd_addr=$(INITRD_PHYS) \
 		 --defsym initrd_virt=$(INITRD_VIRT) \
-		 --defsym params=$(PARAMS_PHYS)
+		 --defsym params=$(PARAMS_PHYS) \
+		 --defsym kernel_addr=$(ZTEXTADDR)
 
 all:		bootp
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/bootp/init.S linux/arch/arm/boot/bootp/init.S
--- v2.4.1/linux/arch/arm/boot/bootp/init.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/boot/bootp/init.S	Thu Feb  8 16:32:44 2001
@@ -12,33 +12,59 @@
  */
 		.section .start,#alloc,#execinstr
 		.type	_entry, #function
-_entry:
-kernel_addr:	adr	r10, initdata
-		ldmia	r10, {r11, r12}
+_entry:		adr	r10, initdata
+		ldr	r11, initdata
 		sub	r11, r10, r11		@ work out exec offset
-		add	r12, r12, r11		@ correct "splitify"
-		mov	pc, r12			@ jump to splitify
+		b	splitify
 		.size	_entry,. - _entry
 
 		.type	initdata, #object
 initdata:	.word	initdata		@ compiled address of this
-		.word	splitify
 		.size	initdata,. - initdata
 
 		.text
 splitify:	adr	r13, data
-		ldmia	r13!, {r4-r6}		@ move the kernel
+		ldmia	r13!, {r4-r6}		@ move the initrd
 		add	r4, r4, r11		@ correction
-		mov	r12, r5
 		bl	move
 
-		ldmia	r13!, {r4-r6}		@ then the initrd
+		ldmia	r13!, {r4-r6}		@ then the kernel
+		mov	r12, r5
 		add	r4, r4, r11		@ correction
 		bl	move
 
-		ldmib	r13, {r5,r6,r7}		@ get size and addr of initrd
-		add	r7, r7, #16*4		@ offset of initrd_start in param_struct
-		stmia	r7, {r5,r6}		@ save in param_struct
+/*
+ * Setup the initrd parameters to pass to the kernel.  This can either be
+ * passed in via a param_struct or a tag list.  We spot the param_struct
+ * method by looking at the first word; this should either indicate a page
+ * size of 4K, 16K or 32K.
+ */
+		ldmia	r13, {r5-r8}		@ get size and addr of initrd
+						@ r5 = ATAG_INITRD
+						@ r6 = initrd start
+						@ r7 = initrd end
+						@ r8 = param_struct address
+		ldr	r9, [r8, #0]		@ no param struct?
+		teq	r9, #0x1000		@ 4K?
+		teqne	r9, #0x4000		@ 16K?
+		teqne	r9, #0x8000		@ 32K?
+		beq	no_taglist
+
+/*
+ * find the end of the tag list, and then add an INITRD tag on the end.
+ */
+taglist:	ldr	r9, [r8, #0]		@ tag length
+		teq	r9, #0			@ last tag?
+		addne	r8, r8, r9
+		bne	taglist
+
+		mov	r4, #16			@ length of initrd tag
+		mov	r9, #0			@ end of tag list terminator
+		stmia	r8, {r4, r5, r6, r7, r9}
+		mov	pc, r12			@ call kernel
+
+no_taglist:	add	r8, r8, #16*4
+		stmia	r8, {r6,r7}		@ save in param_struct
 		mov	pc, r12			@ call kernel
 
 move:		ldmia	r4!, {r7 - r10}		@ move 32-bytes at a time
@@ -49,17 +75,18 @@
 		bcs	move
 		mov	pc, lr
 
-data:		.word	kernel_start
-		.word	kernel_addr
-		.word	kernel_len
-
-		.word	initrd_start
+data:		.word	initrd_start
 		.word	initrd_addr
 		.word	initrd_len
 
-		.word	initrd_virt
-		.word	initrd_len
-		.word	params
+		.word	kernel_start
+		.word	kernel_addr
+		.word	kernel_len
+
+		.word	0x54410005		@ r5 = ATAG_INITRD
+		.word	initrd_virt		@ r6
+		.word	initrd_len		@ r7
+		.word	params			@ r8
 
 		.type	kernel_start,#object
 		.type	initrd_start,#object
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/Makefile linux/arch/arm/boot/compressed/Makefile
--- v2.4.1/linux/arch/arm/boot/compressed/Makefile	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/boot/compressed/Makefile	Thu Feb  8 16:32:44 2001
@@ -66,7 +66,7 @@
 		$(CC) $(AFLAGS) -traditional -c $(HEAD:.o=.S)
 
 piggy.o:	$(SYSTEM)
-		$(OBJCOPY) $(SYSTEM) piggy
+		$(OBJCOPY) -O binary -R .note -R .comment -S $(SYSTEM) piggy
 		gzip $(GZFLAGS) < piggy > piggy.gz
 		$(LD) -r -o $@ -b binary piggy.gz
 		rm -f piggy piggy.gz
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/head-ftvpci.S linux/arch/arm/boot/compressed/head-ftvpci.S
--- v2.4.1/linux/arch/arm/boot/compressed/head-ftvpci.S	Sun Sep  3 11:19:11 2000
+++ linux/arch/arm/boot/compressed/head-ftvpci.S	Thu Feb  8 16:32:44 2001
@@ -6,6 +6,13 @@
  * Special startup code for FTV PCI board.
  */
 
+/*
+ * 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.
+ */
+
 	.section        ".start", #alloc, #execinstr
 ftv_start:
 	mcr	p15, 0, r0, c7, c5, 0		@ flush I cache
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/head-l7200.S linux/arch/arm/boot/compressed/head-l7200.S
--- v2.4.1/linux/arch/arm/boot/compressed/head-l7200.S	Sun Aug 13 09:54:15 2000
+++ linux/arch/arm/boot/compressed/head-l7200.S	Thu Feb  8 16:32:44 2001
@@ -3,7 +3,7 @@
  * 
  * Copyright (C) 2000 Steve Hill <sjhill@cotw.com>
  * 
- * Some code borrowed from Nicola Pitre's 'head-sa1100.S' file. This
+ * Some code borrowed from Nicolas Pitre's 'head-sa1100.S' file. This
  * is merged with head.S by the linker.
  */
 
@@ -16,15 +16,14 @@
 		.section        ".start", #alloc, #execinstr
 
 __L7200_start:
-
 		mov	r0, #0x00100000		@ FLASH address of initrd
 		mov	r2, #0xf1000000		@ RAM address of initrd
-		add	r1, r2, #0x00700000	@ Size of initrd 
+		add	r3, r2, #0x00700000	@ Size of initrd 
 1:
-		ldmia   r0!, {r3, r4, r5, r6}
-		stmia   r2!, {r3, r4, r5, r6}
-		cmp	r2, r1
+		ldmia   r0!, {r4, r5, r6, r7}
+		stmia   r2!, {r4, r5, r6, r7}
+		cmp	r2, r3
 		ble	1b
-		
+
 		mov	r8, #0			@ Zero it out
 		mov	r7, #19			@ Set architecture ID
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/head-sa1100.S linux/arch/arm/boot/compressed/head-sa1100.S
--- v2.4.1/linux/arch/arm/boot/compressed/head-sa1100.S	Sun Aug 13 09:54:15 2000
+++ linux/arch/arm/boot/compressed/head-sa1100.S	Thu Feb  8 16:32:44 2001
@@ -11,10 +11,6 @@
 #include <linux/linkage.h>
 #include <asm/mach-types.h>
 
-#ifndef CONFIG_ARCH_SA1100
-#error What am I doing here...
-#endif
-
 		.section        ".start", #alloc, #execinstr
 
 __SA1100_start:
@@ -54,6 +50,8 @@
 		bic	r0, r0, #0x0d		@ clear WB, DC, MMU
 		bic	r0, r0, #0x1000		@ clear Icache
 		mcr	p15, 0, r0, c1, c0, 0
+
+#ifdef CONFIG_ANGELBOOT
 /*
  * Pause for a short time so that we give enough time
  * for the host to start a terminal up.
@@ -61,3 +59,5 @@
 		mov	r0, #0x00200000
 1:		subs	r0, r0, #1
 		bne	1b
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/head-shark.S linux/arch/arm/boot/compressed/head-shark.S
--- v2.4.1/linux/arch/arm/boot/compressed/head-shark.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/boot/compressed/head-shark.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,121 @@
+/* The head-file for the Shark
+ * by Alexander.Schulz@stud.uni-karlsruhe.de
+ *
+ * Does the following:
+ * - get the memory layout from firmware. This can only be done as long as the mmu
+ *   is still on.
+ * - switch the mmu off, so we have physical addresses
+ * - copy the kernel to 0x08508000. This is done to have a fixed address where the
+ *   C-parts (misc.c) are executed. This address must be known at compile-time,
+ *   but the load-address of the kernel depends on how much memory is installed.
+ * - Jump to this location.
+ * - Set r8 with 0, r7 with the architecture ID for head.S
+ */
+
+#include <linux/linkage.h>
+
+#include <asm/assembler.h>
+	
+		.section	".start", #alloc, #execinstr
+
+		b	__beginning
+	
+__serial_addr:	.long	0xf7eff3f8
+		.long	0				@ space
+__ofw_data:	.long	0				@ the number of memory blocks
+		.space  128				@ (startaddr,size) ...
+		.space  128				@ bootargs
+		.align
+
+__beginning:	mov	r4, r0				@ save the entry to the firmware
+
+		mov	r0, #0xC0			@ disable irq and fiq
+		mov	r1, r0
+		mrs	r3, cpsr_all
+		bic	r2, r3, r0
+		eor	r2, r2, r1
+		msr	cpsr_all, r2
+
+		ldr	r0, __serial_addr		@ disable serial interrupt
+		mov	r1, #0				@ hangs the machine, I don t know why.
+		strb	r1, [r0, #0x01]
+
+		mov	r0, r4				@ get the Memory layout from firmware
+		adr	r1, __ofw_data
+		add	r2, r1, #4
+		mov	lr, pc
+		b	SYMBOL_NAME(ofw_init)
+		mov	r1, #0
+
+		adr	r2, __mmu_off			@ calculate physical address
+		sub	r2, r2, #0xf0000000		@ openprom maps us at f000 virt, 0e50 phys
+		adr	r0, __ofw_data
+		ldr	r0, [r0, #4]
+		add	r2, r2, r0
+		add	r2, r2, #0x00500000
+
+		mrc	p15, 0, r3, c1, c0
+		bic	r3, r3, #0xC			@ Write Buffer and DCache
+		bic	r3, r3, #0x1000			@ ICache
+		mcr	p15, 0, r3, c1, c0		@ disabled
+
+		mov	r0, #0
+		mcr	p15, 0, r0, c7, c7		@ flush I,D caches on v4
+		mcr	p15, 0, r0, c7, c10, 4		@ drain write buffer on v4
+		mcr	p15, 0, r0, c8, c7		@ flush I,D TLBs on v4
+
+		bic	r3, r3, #0x1			@ MMU
+		mcr	p15, 0, r3, c1, c0		@ disabled
+
+		mov	pc, r2
+
+__copy_target:	.long	0x08508000
+__copy_end:	.long	0x08608000
+		
+		.word	_start
+		.word	__bss_start
+
+		.align
+__temp_stack:	.space 128
+
+__mmu_off:
+		adr	r0, __ofw_data
+		ldr	r0, [r0, #4]
+		orr	r0, r0, #0x00600000
+	
+		ldr	r1, __copy_end
+		ldr	r3, __copy_target
+
+/* r0 = 0x0e600000 (current end of kernelcode)
+ * r3 = 0x08508000 (where it should begin)
+ * r1 = 0x08608000 (end of copying area, 1MB)
+ * The kernel is compressed, so 1 MB should be enough.
+ * copy the kernel to the beginning of physical memory
+ * We start from the highest address, so we can copy
+ * from 0x08500000 to 0x08508000 if we have only 8MB
+ */
+
+	
+__Copy:		ldr	r2, [r0], #-4
+		str	r2, [r1], #-4
+		teq	r1, r3
+		bne	__Copy
+		/* and jump to it */
+		adr	r2, __go_on
+		adr	r0, __ofw_data
+		ldr	r0, [r0, #4]
+		sub	r2, r2, r0
+		sub	r2, r2, #0x00500000
+		ldr	r0, __copy_target
+		add	r2, r2, r0
+		mov	pc, r2
+
+__go_on:
+		adr	sp, __temp_stack
+		add	sp, sp, #128
+		adr	r0, __ofw_data
+		mov	lr, pc
+		b	SYMBOL_NAME(create_params)
+	
+		mov	r8, #0
+		mov	r7, #15
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/head.S linux/arch/arm/boot/compressed/head.S
--- v2.4.1/linux/arch/arm/boot/compressed/head.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/boot/compressed/head.S	Thu Feb  8 16:32:44 2001
@@ -112,8 +112,7 @@
 		 */
 
 		.text
-1:		mrc	p15, 0, r6, c0, c0	@ get processor ID
-		adr	r2, LC0
+1:		adr	r2, LC0
 		ldmia	r2, {r2, r3, r4, r5, sp}
 
 		mov	r0, #0
@@ -124,14 +123,15 @@
 		cmp	r2, r3
 		blt	1b
 
+		mrc	p15, 0, r6, c0, c0	@ get processor ID
 		bl	cache_on
 
 		mov	r1, sp			@ malloc space above stack
 		add	r2, sp, #0x10000	@ 64k max
 
 		teq	r4, r5			@ will we overwrite ourselves?
-		moveq	r5, r2
-		movne	r5, r4
+		moveq	r5, r2			@ decompress after image
+		movne	r5, r4			@ decompress to final location
 
 		mov	r0, r5
 		mov	r3, r7
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/ofw-shark.c linux/arch/arm/boot/compressed/ofw-shark.c
--- v2.4.1/linux/arch/arm/boot/compressed/ofw-shark.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/boot/compressed/ofw-shark.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,216 @@
+/*
+ * linux/arch/arm/boot/compressed/ofw-shark.c
+ *
+ * by Alexander.Schulz@stud.uni-karlsruhe.de
+ *
+ * This file is used to get some basic information
+ * about the memory layout of the shark we are running
+ * on. Memory is usually divided in blocks a 8 MB.
+ * And bootargs are copied from OpenFirmware.
+ */
+
+
+#include <linux/kernel.h>
+#include <asm/setup.h>
+#include <asm/page.h>
+
+
+asmlinkage void
+create_params (unsigned long *buffer)
+{
+	/* Is there a better address? Also change in kernel/arch.c */
+	struct param_struct *params = (struct param_struct *) 0x08003000;
+	int j,i,m,k,nr_banks,size;
+
+	for (j=0;j<256;j++) params->u1.unused[j]=0;
+
+	size=0;
+	nr_banks=(unsigned int) buffer[0];
+	if (nr_banks > NR_BANKS) nr_banks = NR_BANKS;
+	for (j=0;j<nr_banks;j++){
+		/* search the lowest address and put it into the next entry   */
+		/* not a fast sort algorithm, but there are at most 8 entries */
+		/* and this is used only once anyway                          */
+		m=0xffffffff;
+		for (i=0;i<(unsigned int) buffer[0];i++){
+			if (buffer[2*i+1]<m) {
+				m=buffer[2*i+1];
+				k=i;
+			}
+		}
+	  
+		/* using pages_in_bank for startaddress and size               */
+		/* start is in bytes, size in pages and not bigger than 0x2000 */
+		/* This is decoded in fixup_shark in arch/arm/kernel/arch.c    */
+		params->u1.s.pages_in_bank[j]=buffer[2*k+1]|(buffer[2*k+2]/PAGE_SIZE);
+		size += buffer[2*k+2];
+
+		buffer[2*k+1]=0xffffffff;                    /* mark as copied             */
+	}
+	
+	params->u1.s.page_size = PAGE_SIZE;
+	params->u1.s.nr_pages  = size/PAGE_SIZE;
+	params->u1.s.flags     = FLAG_READONLY;
+	
+	/* Copy over the bootargs */
+	for (j=0;j<128/4;j++) {
+		((unsigned long *) params->commandline)[j]=buffer[33+j];
+	}
+}
+
+
+typedef int (*ofw_handle_t)(void *);
+
+/* Everything below is called with a wrong MMU setting.
+ * This means: no string constants, no initialization of
+ * arrays, no global variables! This is ugly but I didn't
+ * want to write this in assembler :-)
+ */
+
+int
+of_decode_int(const unsigned char *p)
+{
+	unsigned int i = *p++ << 8;
+	i = (i + *p++) << 8;
+	i = (i + *p++) << 8;
+	return (i + *p);
+}
+  
+int
+OF_finddevice(ofw_handle_t openfirmware, char *name)
+{
+	unsigned int args[8];
+	char service[12];
+
+	service[0]='f';
+	service[1]='i';
+	service[2]='n';
+	service[3]='d';
+	service[4]='d';
+	service[5]='e';
+	service[6]='v';
+	service[7]='i';
+	service[8]='c';
+	service[9]='e';
+	service[10]='\0';
+
+	args[0]=(unsigned int)service;
+	args[1]=1;
+	args[2]=1;
+	args[3]=(unsigned int)name;
+
+	if (openfirmware(args) == -1)
+		return -1;
+	return args[4];
+}
+
+int
+OF_getproplen(ofw_handle_t openfirmware, int handle, char *prop)
+{
+	unsigned int args[8];
+	char service[12];
+
+	service[0]='g';
+	service[1]='e';
+	service[2]='t';
+	service[3]='p';
+	service[4]='r';
+	service[5]='o';
+	service[6]='p';
+	service[7]='l';
+	service[8]='e';
+	service[9]='n';
+	service[10]='\0';
+
+	args[0] = (unsigned int)service;
+	args[1] = 2;
+	args[2] = 1;
+	args[3] = (unsigned int)handle;
+	args[4] = (unsigned int)prop;
+
+	if (openfirmware(args) == -1)
+		return -1;
+	return args[5];
+}
+  
+int
+OF_getprop(ofw_handle_t openfirmware, int handle, char *prop, void *buf, unsigned int buflen)
+{
+	unsigned int args[8];
+	char service[8];
+
+	service[0]='g';
+	service[1]='e';
+	service[2]='t';
+	service[3]='p';
+	service[4]='r';
+	service[5]='o';
+	service[6]='p';
+	service[7]='\0';
+
+	args[0] = (unsigned int)service;
+	args[1] = 4;
+	args[2] = 1;
+	args[3] = (unsigned int)handle;
+	args[4] = (unsigned int)prop;
+	args[5] = (unsigned int)buf;
+	args[6] = buflen;
+
+	if (openfirmware(args) == -1)
+		return -1;
+	return args[7];
+}
+  
+asmlinkage void ofw_init(ofw_handle_t o, int *nomr, int *pointer)
+{
+	int phandle,i,mem_len,buffer[32];
+	char temp[12];
+  
+	temp[0]='/';
+	temp[1]='m';
+	temp[2]='e';
+	temp[3]='m';
+	temp[4]='o';
+	temp[5]='r';
+	temp[6]='y';
+	temp[7]='\0';
+
+	phandle=OF_finddevice(o,temp);
+
+	temp[0]='r';
+	temp[1]='e';
+	temp[2]='g';
+	temp[3]='\0';
+
+	mem_len = OF_getproplen(o,phandle, temp);
+	OF_getprop(o,phandle, temp, buffer, mem_len);
+	*nomr=mem_len >> 3;
+
+	for (i=0; i<=mem_len/4; i++) pointer[i]=of_decode_int((const unsigned char *)&buffer[i]);
+
+	temp[0]='/';
+	temp[1]='c';
+	temp[2]='h';
+	temp[3]='o';
+	temp[4]='s';
+	temp[5]='e';
+	temp[6]='n';
+	temp[7]='\0';
+
+	phandle=OF_finddevice(o,temp);
+
+	temp[0]='b';
+	temp[1]='o';
+	temp[2]='o';
+	temp[3]='t';
+	temp[4]='a';
+	temp[5]='r';
+	temp[6]='g';
+	temp[7]='s';
+	temp[8]='\0';
+
+	mem_len = OF_getproplen(o,phandle, temp);
+	OF_getprop(o,phandle, temp, buffer, mem_len);
+	for (i=0; i<=mem_len/4; i++) pointer[i+32]=buffer[i];
+  
+}
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/setup-sa1100.S linux/arch/arm/boot/compressed/setup-sa1100.S
--- v2.4.1/linux/arch/arm/boot/compressed/setup-sa1100.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/boot/compressed/setup-sa1100.S	Thu Feb  8 16:32:44 2001
@@ -33,13 +33,11 @@
 #define UTSR0           0x1c
 #define UTSR1           0x20
 
-#define BAUD_DIV_230400	0x000
-#define BAUD_DIV_115200	0x001
-#define BAUD_DIV_57600	0x003
-#define BAUD_DIV_38400	0x005
-#define BAUD_DIV_19200	0x00b
-#define BAUD_DIV_9600	0x017
-#define BAUD_DIV	BAUD_DIV_9600
+#ifndef CONFIG_SA1100_DEFAULT_BAUDRATE
+#define CONFIG_SA1100_DEFAULT_BAUDRATE	9600
+#endif
+
+#define BAUD_DIV	((230400/CONFIG_SA1100_DEFAULT_BAUDRATE)-1)
 
 SCR_loc:	.long	SYMBOL_NAME(SCR_value)
 #define GPIO_2_9	0x3fc
@@ -92,7 +90,7 @@
 		bne	skip_uart
 
 		@ UART3 if Assabet is used with Neponset
-		teq	r3, #25			@ if Assabet 
+		teq	r3, #MACH_TYPE_ASSABET	@ if Assabet 
 		tsteq	r2, #(1 << 9)		@ ... and Neponset present
 		ldreq	r0, UART3_BASE
 		beq	uart_init
diff -u --recursive --new-file v2.4.1/linux/arch/arm/boot/compressed/vmlinux.lds.in linux/arch/arm/boot/compressed/vmlinux.lds.in
--- v2.4.1/linux/arch/arm/boot/compressed/vmlinux.lds.in	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/boot/compressed/vmlinux.lds.in	Thu Feb  8 16:32:44 2001
@@ -19,12 +19,13 @@
 
   .text : {
     _start = .;
-    head.o(.start)
     *(.start)
-    head.o(.text)
     *(.text)
     *(.fixup)
     *(.gnu.warning)
+    *(.rodata)
+    *(.glue_7)
+    *(.glue_7t)
     input_data = .;
     piggy.o
     input_data_end = .;
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/Makefile linux/arch/arm/kernel/Makefile
--- v2.4.1/linux/arch/arm/kernel/Makefile	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/Makefile	Thu Feb  8 16:32:44 2001
@@ -10,16 +10,14 @@
 HEAD_OBJ  = head-$(PROCESSOR).o
 ENTRY_OBJ = entry-$(PROCESSOR).o
 
-AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR) -traditional
-AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR) -traditional
+AFLAGS_head-armv.o := -DTEXTADDR=$(TEXTADDR)
+AFLAGS_head-armo.o := -DTEXTADDR=$(TEXTADDR)
 
 O_OBJS_arc        = dma-arc.o oldlatches.o
 O_OBJS_rpc        = dma-rpc.o
 O_OBJS_footbridge = dma-footbridge.o isa.o
 O_OBJS_l7200      = fiq.o
 
-leds-ebsa110	  = leds-ebsa110.o
-
 pci-nexuspci	  = plx90x0.o
 pci-footbridge	  = dec21285.o
 pci-shark	  = via82c505.o
@@ -31,36 +29,28 @@
 
 # Object file lists.
 
-obj-y			:= arch.o dma.o $(ENTRY_OBJ) irq.o process.o ptrace.o \
-			   semaphore.o setup.o signal.o sys_arm.o time.o \
-			   traps.o $(O_OBJS_$(MACHINE))
-obj-m			:=
-obj-n			:=
-obj-			:=
-
-export-objs		:= armksyms.o dma.o ecard.o \
-			   $(leds-$(MACHINE)) oldlatches.o \
-			   time.o
+obj-y		:= arch.o dma.o $(ENTRY_OBJ) irq.o process.o ptrace.o    \
+		   semaphore.o setup.o signal.o sys_arm.o time.o traps.o \
+		   $(O_OBJS_$(MACHINE))
+obj-m		:=
+obj-n		:=
+obj-		:=
+
+export-objs	:= armksyms.o dma.o ecard.o fiq.o oldlatches.o time.o
+
+no-irq-arch	:= $(CONFIG_ARCH_INTEGRATOR) $(CONFIG_ARCH_CLPS711X) \
+		   $(CONFIG_ARCH_FOOTBRIDGE) $(CONFIG_ARCH_EBSA110)
+
+ifneq ($(findstring y,$(no-irq-arch)),y)
+  obj-y		+= irq-arch.o
+endif
 
 obj-$(CONFIG_ARCH_ACORN) += ecard.o fiq.o time-acorn.o
 obj-$(CONFIG_DEBUG_LL)	+= debug-$(PROCESSOR).o
 obj-$(CONFIG_MODULES)	+= armksyms.o
-obj-$(CONFIG_LEDS)	+= $(leds-$(MACHINE))
 obj-$(CONFIG_ARTHUR)	+= arthur.o
 obj-$(CONFIG_ISA_DMA)	+= dma-isa.o
-
 obj-$(CONFIG_PCI)	+= bios32.o $(pci-$(MACHINE)) $(pci-y)
-
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-
-# Translate to Rules.make lists.
-
-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)))
 
 all: kernel.o $(HEAD_OBJ) init_task.o
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/bios32.c linux/arch/arm/kernel/bios32.c
--- v2.4.1/linux/arch/arm/kernel/bios32.c	Mon Nov 27 17:51:34 2000
+++ linux/arch/arm/kernel/bios32.c	Thu Feb  8 16:32:44 2001
@@ -257,11 +257,30 @@
 			(struct arm_pci_sysdata *)bus->sysdata;
 	struct arm_bus_sysdata *busdata;
 
-	if (bus->number < MAX_NR_BUS)
-		busdata = sysdata->bus + bus->number;
-	else
+	if (bus->number >= MAX_NR_BUS)
 		BUG();
 
+	if (bus->self) {
+		struct pci_dev *dev = bus->self;
+		int i;
+
+		for (i = 0; i < 3; i++) {
+			bus->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES + i];
+			bus->resource[i]->name = bus->name;
+		}
+		bus->resource[0]->start = ioport_resource.start;
+		bus->resource[0]->end   = ioport_resource.end;
+		bus->resource[0]->flags |= pci_bridge_check_io(dev);
+		bus->resource[1]->start = iomem_resource.start;
+		bus->resource[1]->end   = iomem_resource.end;
+		bus->resource[1]->flags |= IORESOURCE_MEM;
+
+		/* Turn off downsteam prefetchable memory address range */
+		bus->resource[2]->start = 1024*1024;
+		bus->resource[2]->end   = bus->resource[2]->start - 1;
+	}
+
+	busdata = sysdata->bus + bus->number;
 	busdata->max_lat = 255;
 
 	/*
@@ -363,10 +382,6 @@
 void __init
 pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
 {
-	ranges->io_start -= bus->resource[0]->start;
-	ranges->io_end -= bus->resource[0]->start;
-	ranges->mem_start -= bus->resource[1]->start;
-	ranges->mem_end -= bus->resource[1]->start;
 }
 
 u8 __init no_swizzle(struct pci_dev *dev, u8 *pin)
@@ -442,7 +457,8 @@
 	hw_pci->init(&sysdata);
 
 	/*
-	 * Other architectures don't seem to do this... should we?
+	 * Claim the currently allocated resources.  This ensures
+	 * that we will not allocate an already inuse region.
 	 */
 	pcibios_claim_resources();
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/dma-arc.c linux/arch/arm/kernel/dma-arc.c
--- v2.4.1/linux/arch/arm/kernel/dma-arc.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/kernel/dma-arc.c	Thu Feb  8 16:32:44 2001
@@ -40,7 +40,7 @@
 		memcpy ((void *)0x1c, (void *)&fdc1772_dma_read,
 			&fdc1772_dma_read_end - &fdc1772_dma_read);
 		fdc1772_setupdma(dma->buf.length, dma->buf.address); /* Sets data pointer up */
-		enable_irq (64);
+		enable_fiq(FIQ_FLOPPYDATA);
 		restore_flags(flags);
 	   }
 	   break;
@@ -55,7 +55,7 @@
 		memcpy ((void *)0x1c, (void *)&fdc1772_dma_write,
 			&fdc1772_dma_write_end - &fdc1772_dma_write);
 		fdc1772_setupdma(dma->buf.length, dma->buf.address); /* Sets data pointer up */
-		enable_irq (64);
+		enable_fiq(FIQ_FLOPPYDATA;
 
 		restore_flags(flags);
 	    }
@@ -102,7 +102,7 @@
 
 static void arc_disable_dma(dmach_t channel, dma_t *dma)
 {
-	disable_irq(dma->dma_irq);
+	disable_fiq(dma->dma_irq);
 }
 
 static struct dma_ops arc_floppy_data_dma_ops = {
@@ -158,12 +158,12 @@
 	regs.ARM_r10 = dma->buf.address;
 	regs.ARM_fp = FLOPPYDMA_BASE;
 	set_fiq_regs(&regs);
-	enable_irq(dma->dma_irq);
+	enable_fiq(dma->dma_irq);
 }
 
 static void a5k_floppy_disable_dma(dmach_t channel, dma_t *dma)
 {
-	disable_irq(dma->dma_irq);
+	disable_fiq(dma->dma_irq);
 	release_fiq(&fh);
 }
 
@@ -192,15 +192,15 @@
 {
 #if defined(CONFIG_BLK_DEV_FD1772) || defined(CONFIG_BLK_DEV_FD1772_MODULE)
 	if (machine_is_archimedes()) {
-		dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
+		dma[DMA_VIRTUAL_FLOPPY0].dma_irq = FIQ_FLOPPYDATA;
 		dma[DMA_VIRTUAL_FLOPPY0].d_ops   = &arc_floppy_data_dma_ops;
-		dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 65;
+		dma[DMA_VIRTUAL_FLOPPY1].dma_irq = 1;
 		dma[DMA_VIRTUAL_FLOPPY1].d_ops   = &arc_floppy_cmdend_dma_ops;
 	}
 #endif
 #ifdef CONFIG_ARCH_A5K
 	if (machine_is_a5k()) {
-		dma[DMA_VIRTUAL_FLOPPY0].dma_irq = 64;
+		dma[DMA_VIRTUAL_FLOPPY0].dma_irq = FIQ_FLOPPYDATA;
 		dma[DMA_VIRTUAL_FLOPPY0].d_ops   = &a5k_floppy_dma_ops;
 	}
 #endif
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/dma-rpc.c linux/arch/arm/kernel/dma-rpc.c
--- v2.4.1/linux/arch/arm/kernel/dma-rpc.c	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/dma-rpc.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
  *  DMA functions specific to RiscPC architecture
  */
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -42,11 +42,11 @@
 #define TRANSFER_SIZE	2
 
 #define CURA	(0)
-#define ENDA	((IOMD_IO0ENDA - IOMD_IO0CURA) << 2)
-#define CURB	((IOMD_IO0CURB - IOMD_IO0CURA) << 2)
-#define ENDB	((IOMD_IO0ENDB - IOMD_IO0CURA) << 2)
-#define CR	((IOMD_IO0CR - IOMD_IO0CURA) << 2)
-#define ST	((IOMD_IO0ST - IOMD_IO0CURA) << 2)
+#define ENDA	(IOMD_IO0ENDA - IOMD_IO0CURA)
+#define CURB	(IOMD_IO0CURB - IOMD_IO0CURA)
+#define ENDB	(IOMD_IO0ENDB - IOMD_IO0CURA)
+#define CR	(IOMD_IO0CR - IOMD_IO0CURA)
+#define ST	(IOMD_IO0ST - IOMD_IO0CURA)
 
 #define state_prog_a	0
 #define state_wait_a	1
@@ -93,14 +93,14 @@
 
 static inline void iomd_setup_dma_a(struct scatterlist *sg, dma_t *dma)
 {
-	outl_t(sg->dma_address, dma->dma_base + CURA);
-	outl_t(sg->length, dma->dma_base + ENDA);
+	iomd_writel(sg->dma_address, dma->dma_base + CURA);
+	iomd_writel(sg->length, dma->dma_base + ENDA);
 }
 
 static inline void iomd_setup_dma_b(struct scatterlist *sg, dma_t *dma)
 {
-	outl_t(sg->dma_address, dma->dma_base + CURB);
-	outl_t(sg->length, dma->dma_base + ENDB);
+	iomd_writel(sg->dma_address, dma->dma_base + CURB);
+	iomd_writel(sg->length, dma->dma_base + ENDB);
 }
 
 static void iomd_dma_handle(int irq, void *dev_id, struct pt_regs *regs)
@@ -116,7 +116,7 @@
 			dma->state = state_wait_a;
 
 		case state_wait_a:
-			status = inb_t(dma->dma_base + ST);
+			status = iomd_readb(dma->dma_base + ST);
 			switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
 			case DMA_ST_OFL|DMA_ST_INT:
 				iomd_get_next_sg(&dma->cur_sg, dma);
@@ -137,7 +137,7 @@
 			break;
 
 		case state_wait_b:
-			status = inb_t(dma->dma_base + ST);
+			status = iomd_readb(dma->dma_base + ST);
 			switch (status & (DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB)) {
 			case DMA_ST_OFL|DMA_ST_INT|DMA_ST_AB:
 				iomd_get_next_sg(&dma->cur_sg, dma);
@@ -193,14 +193,14 @@
 				PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
 		}
 
-		outb_t(DMA_CR_C, dma_base + CR);
+		iomd_writeb(DMA_CR_C, dma_base + CR);
 		dma->state = state_prog_a;
 	}
 		
 	if (dma->dma_mode == DMA_MODE_READ)
 		ctrl |= DMA_CR_D;
 
-	outb_t(ctrl, dma_base + CR);
+	iomd_writeb(ctrl, dma_base + CR);
 	enable_irq(dma->dma_irq);
 }
 
@@ -210,8 +210,8 @@
 	unsigned int ctrl;
 
 	disable_irq(dma->dma_irq);
-	ctrl = inb_t(dma_base + CR);
-	outb_t(ctrl & ~DMA_CR_E, dma_base + CR);
+	ctrl = iomd_readb(dma_base + CR);
+	iomd_writeb(ctrl & ~DMA_CR_E, dma_base + CR);
 }
 
 static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
@@ -227,7 +227,7 @@
 	else
 		speed = 0;
 
-	tcr = inb(IOMD_DMATCR);
+	tcr = iomd_readb(IOMD_DMATCR);
 	speed &= 3;
 
 	switch (channel) {
@@ -251,7 +251,7 @@
 		break;
 	}
 
-	outb(tcr, IOMD_DMATCR);
+	iomd_writeb(tcr, IOMD_DMATCR);
 
 	return speed;
 }
@@ -287,7 +287,7 @@
 
 	regs.ARM_r9  = dma->buf.length;
 	regs.ARM_r10 = (unsigned long)dma->buf.address;
-	regs.ARM_fp  = (unsigned long)PCIO_FLOPPYDMABASE;
+	regs.ARM_fp  = FLOPPYDMA_BASE;
 
 	if (claim_fiq(&fh)) {
 		printk("floppydma: couldn't claim FIQ.\n");
@@ -296,12 +296,12 @@
 
 	set_fiq_handler(fiqhandler_start, fiqhandler_length);
 	set_fiq_regs(&regs);
-	enable_irq(dma->dma_irq);
+	enable_fiq(dma->dma_irq);
 }
 
 static void floppy_disable_dma(dmach_t channel, dma_t *dma)
 {
-	disable_irq(dma->dma_irq);
+	disable_fiq(dma->dma_irq);
 	release_fiq(&fh);
 }
 
@@ -334,32 +334,32 @@
 
 void __init arch_dma_init(dma_t *dma)
 {
-	outb(0, IOMD_IO0CR);
-	outb(0, IOMD_IO1CR);
-	outb(0, IOMD_IO2CR);
-	outb(0, IOMD_IO3CR);
+	iomd_writeb(0, IOMD_IO0CR);
+	iomd_writeb(0, IOMD_IO1CR);
+	iomd_writeb(0, IOMD_IO2CR);
+	iomd_writeb(0, IOMD_IO3CR);
 
-	outb(0xa0, IOMD_DMATCR);
+	iomd_writeb(0xa0, IOMD_DMATCR);
 
-	dma[DMA_0].dma_base		= ioaddr(IOMD_IO0CURA);
+	dma[DMA_0].dma_base		= IOMD_IO0CURA;
 	dma[DMA_0].dma_irq		= IRQ_DMA0;
 	dma[DMA_0].d_ops		= &iomd_dma_ops;
-	dma[DMA_1].dma_base		= ioaddr(IOMD_IO1CURA);
+	dma[DMA_1].dma_base		= IOMD_IO1CURA;
 	dma[DMA_1].dma_irq		= IRQ_DMA1;
 	dma[DMA_1].d_ops		= &iomd_dma_ops;
-	dma[DMA_2].dma_base		= ioaddr(IOMD_IO2CURA);
+	dma[DMA_2].dma_base		= IOMD_IO2CURA;
 	dma[DMA_2].dma_irq		= IRQ_DMA2;
 	dma[DMA_2].d_ops		= &iomd_dma_ops;
-	dma[DMA_3].dma_base		= ioaddr(IOMD_IO3CURA);
+	dma[DMA_3].dma_base		= IOMD_IO3CURA;
 	dma[DMA_3].dma_irq		= IRQ_DMA3;
 	dma[DMA_3].d_ops		= &iomd_dma_ops;
-	dma[DMA_S0].dma_base		= ioaddr(IOMD_SD0CURA);
+	dma[DMA_S0].dma_base		= IOMD_SD0CURA;
 	dma[DMA_S0].dma_irq		= IRQ_DMAS0;
 	dma[DMA_S0].d_ops		= &iomd_dma_ops;
-	dma[DMA_S1].dma_base		= ioaddr(IOMD_SD1CURA);
+	dma[DMA_S1].dma_base		= IOMD_SD1CURA;
 	dma[DMA_S1].dma_irq		= IRQ_DMAS1;
 	dma[DMA_S1].d_ops		= &iomd_dma_ops;
-	dma[DMA_VIRTUAL_FLOPPY].dma_irq	= 64;
+	dma[DMA_VIRTUAL_FLOPPY].dma_irq	= FIQ_FLOPPYDATA;
 	dma[DMA_VIRTUAL_FLOPPY].d_ops	= &floppy_dma_ops;
 	dma[DMA_VIRTUAL_SOUND].d_ops	= &sound_dma_ops;
 
@@ -367,5 +367,5 @@
 	 * Setup DMA channels 2,3 to be for podules
 	 * and channels 0,1 for internal devices
 	 */
-	outb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
+	iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
 }
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/dma.c linux/arch/arm/kernel/dma.c
--- v2.4.1/linux/arch/arm/kernel/dma.c	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/dma.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
  *  DMA facilities.
  */
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/mman.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/ecard.c linux/arch/arm/kernel/ecard.c
--- v2.4.1/linux/arch/arm/kernel/ecard.c	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/ecard.c	Fri Feb  9 11:29:44 2001
@@ -35,7 +35,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/entry-armo.S linux/arch/arm/kernel/entry-armo.S
--- v2.4.1/linux/arch/arm/kernel/entry-armo.S	Mon Sep 18 15:15:24 2000
+++ linux/arch/arm/kernel/entry-armo.S	Thu Feb  8 16:32:44 2001
@@ -197,8 +197,7 @@
 #endif
 #define FAULT_CODE_PREFETCH	0x04
 #define FAULT_CODE_WRITE	0x02
-#define FAULT_CODE_USER		0x01
-
+#define FAULT_CODE_FORCECOW	0x01
 
 #define SVC_SAVE_ALL				\
 		str	sp, [sp, #-16]!		;\
@@ -487,7 +486,6 @@
 		save_user_regs
 		teqp	pc, #0x00000003		@ NOT a problem - doesnt change mode
 		mask_pc	r0, lr
-		mov	r2, #FAULT_CODE_USER
 		bl	Ldata_do
 		b	ret_from_exception
 
@@ -499,7 +497,6 @@
 		tst	lr, #0x08000000
 		teqeqp	pc, #0x00000003		@ NOT a problem - doesnt change mode
 		mask_pc	r0, lr
-		mov	r2, #0
 		bl	Ldata_do
 		SVC_RESTORE_ALL
 
@@ -510,6 +507,7 @@
 
 Ldata_do:	mov	r3, sp
 		ldr	r4, [r0]		@ Get instruction
+		mov	r2, #0
 		tst	r4, #1 << 20		@ Check to see if it is a write instruction
 		orreq	r2, r2, #FAULT_CODE_WRITE @ Indicate write instruction
 		mov	r1, r4, lsr #22		@ Now branch to the relevent processing routine
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/fiq.c linux/arch/arm/kernel/fiq.c
--- v2.4.1/linux/arch/arm/kernel/fiq.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/kernel/fiq.c	Thu Feb  8 16:32:44 2001
@@ -36,12 +36,14 @@
  *  6. Goto 3
  */
 #include <linux/config.h>
+#include <linux/module.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/init.h>
 
 #include <asm/fiq.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -71,7 +73,7 @@
  * - we always relinquish FIQ control
  * - we always reacquire FIQ control
  */
-int fiq_def_op(void *ref, int relinquish)
+static int fiq_def_op(void *ref, int relinquish)
 {
 	if (!relinquish) {
 		unprotect_page_0();
@@ -213,6 +215,24 @@
 		current_fiq = current_fiq->next;
 	while (current_fiq->fiq_op(current_fiq->dev_id, 0));
 }
+
+void enable_fiq(int fiq)
+{
+	enable_irq(fiq + FIQ_START);
+}
+
+void disable_fiq(int fiq)
+{
+	disable_irq(fiq + FIQ_START);
+}
+
+EXPORT_SYMBOL(set_fiq_handler);
+EXPORT_SYMBOL(set_fiq_regs);
+EXPORT_SYMBOL(get_fiq_regs);
+EXPORT_SYMBOL(claim_fiq);
+EXPORT_SYMBOL(release_fiq);
+EXPORT_SYMBOL(enable_fiq);
+EXPORT_SYMBOL(disable_fiq);
 
 void __init init_FIQ(void)
 {
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/irq.c linux/arch/arm/kernel/irq.c
--- v2.4.1/linux/arch/arm/kernel/irq.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/sched.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c
--- v2.4.1/linux/arch/arm/kernel/process.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
@@ -92,8 +92,10 @@
 		void (*idle)(void) = pm_idle;
 		if (!idle)
 			idle = arch_idle;
+		leds_event(led_idle_start);
 		while (!current->need_resched)
 			idle();
+		leds_event(led_idle_end);
 		schedule();
 #ifndef CONFIG_NO_PGT_CACHE
 		check_pgt_cache();
@@ -364,20 +366,23 @@
  */
 pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 {
-	extern long sys_exit(int) __attribute__((noreturn));
 	pid_t __ret;
 
 	__asm__ __volatile__(
-	"mov	r0, %1		@ kernel_thread sys_clone
+	"orr	r0, %1, %2	@ kernel_thread sys_clone
 	mov	r1, #0
 	"__syscall(clone)"
-	teq	r0, #0		@ if we are the child
-	moveq	fp, #0		@ ensure that fp is zero
-	mov	%0, r0"
+	movs	%0, r0		@ if we are the child
+	bne	1f
+	mov	fp, #0		@ ensure that fp is zero
+	mov	r0, %4
+	mov	lr, pc
+	mov	pc, %3
+	b	sys_exit
+1:	"
         : "=r" (__ret)
-        : "Ir" (flags | CLONE_VM) : "r0", "r1");
-	if (__ret == 0)
-		sys_exit((fn)(arg));
+        : "Ir" (flags), "I" (CLONE_VM), "r" (fn), "r" (arg)
+	: "r0", "r1", "lr");
 	return __ret;
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/sys_arm.c linux/arch/arm/kernel/sys_arm.c
--- v2.4.1/linux/arch/arm/kernel/sys_arm.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/sys_arm.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
  */
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/sem.h>
 #include <linux/msg.h>
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.4.1/linux/arch/arm/kernel/time.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/kernel/time.c	Thu Feb  8 16:32:44 2001
@@ -134,32 +134,17 @@
 #ifdef CONFIG_MODULES
 EXPORT_SYMBOL(leds_event);
 #endif
+#endif
 
+#ifdef CONFIG_LEDS_TIMER
 static void do_leds(void)
 {
-#ifdef CONFIG_LEDS_CPU
-	{
-		static int last_pid;
+	static unsigned int count = 50;
 
-		if (current->pid != last_pid) {
-			last_pid = current->pid;
-			if (last_pid)
-				leds_event(led_idle_end);
-			else
-				leds_event(led_idle_start);
-		}
+	if (--count == 0) {
+		count = 50;
+		leds_event(led_timer);
 	}
-#endif
-#ifdef CONFIG_LEDS_TIMER
-	{
-		static unsigned int count = 50;
-
-		if (--count == 0) {
-			count = 50;
-			leds_event(led_timer);
-		}
-	}
-#endif
 }
 #else
 #define do_leds()
diff -u --recursive --new-file v2.4.1/linux/arch/arm/kernel/traps.c linux/arch/arm/kernel/traps.c
--- v2.4.1/linux/arch/arm/kernel/traps.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/arm/kernel/traps.c	Thu Feb  8 16:32:44 2001
@@ -107,7 +107,7 @@
 			bad = __get_user(val, &((u32 *)addr)[i]);
 
 		if (!bad)
-			printk(i == 0 ? "(%0*x) " : "%0*x", width, val);
+			printk(i == 0 ? "(%0*x) " : "%0*x ", width, val);
 		else {
 			printk("bad PC value.");
 			break;
@@ -133,7 +133,7 @@
 		printk("no frame pointer");
 		ok = 0;
 	} else if (verify_stack(fp)) {
-		printk("invalid frame pointer %08lx", fp);
+		printk("invalid frame pointer 0x%08x", fp);
 		ok = 0;
 	} else if (fp < 4096+(unsigned long)tsk)
 		printk("frame pointer underflow");
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/Makefile linux/arch/arm/lib/Makefile
--- v2.4.1/linux/arch/arm/lib/Makefile	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/Makefile	Thu Feb  8 16:32:44 2001
@@ -1,57 +1,57 @@
 #
 # linux/arch/arm/lib/Makefile
 #
-# Copyright (C) 1995-1999 Russell King
+# Copyright (C) 1995-2000 Russell King
 #
 
 USE_STANDARD_AS_RULE := true
 
-L_TARGET := lib.a
-L_OBJS   := changebit.o csumipv6.o csumpartial.o csumpartialcopy.o \
-	    csumpartialcopyuser.o clearbit.o copy_page.o findbit.o \
-	    memchr.o memcpy.o memset.o memzero.o setbit.o          \
-	    strncpy_from_user.o strnlen_user.o strchr.o strrchr.o  \
-	    testchangebit.o testclearbit.o testsetbit.o uaccess.o
-
-l-obj-y	:=
-l-obj-n	:=
-
-O_TARGET := lib.o
-O_OBJS   := backtrace.o delay.o
-
-ifeq ($(CONFIG_ARCH_ACORN),y)
-  half := n
-  full := y
+L_TARGET	:= lib.a
+
+obj-y		:= backtrace.o changebit.o csumipv6.o csumpartial.o   \
+		   csumpartialcopy.o csumpartialcopyuser.o clearbit.o \
+		   copy_page.o delay.o findbit.o memchr.o memcpy.o    \
+		   memset.o memzero.o setbit.o strncpy_from_user.o    \
+		   strnlen_user.o strchr.o strrchr.o testchangebit.o  \
+		   testclearbit.o testsetbit.o uaccess.o
+obj-m		:=
+obj-n		:=
+
+export-objs	:= io.o
+
+obj-arc		:= ecard.o io-acorn.o floppydma.o
+obj-rpc		:= ecard.o io-acorn.o floppydma.o
+obj-clps7500	:= io-acorn.o
+obj-footbridge	:= io-pcio.o
+obj-l7200     	:= io-acorn.o
+obj-nexuspci	:= io-pcio.o
+obj-sa1100	:= io-pcio.o
+obj-shark	:= io-shark.o
+obj-integrator	:= io-pcio.o
+obj-clps711x	:= io-shark.o
+
+obj-y		+= $(obj-$(MACHINE))
+
+ifeq ($(CONFIG_CPU_32v4),y)
+  v3		:= n
+  v4		:= y
 else
-  half := y
-  full := n
+  v3		:= y
+  v4		:= n
 endif
 
-L_OBJS_arc		:= ecard.o io-acorn.o floppydma.o
-L_OBJS_rpc		:= ecard.o io-acorn.o floppydma.o
-L_OBJS_clps7500		:= io-acorn.o
-L_OBJS_footbridge	:= io-pcio.o
-L_OBJS_l7200     	:= io-acorn.o
-L_OBJS_nexuspci		:= io-pcio.o
-L_OBJS_sa1100		:= io-pcio.o
-L_OBJS_shark		:= io-shark.o
-L_OBJS_integrator	:= io-pcio.o
-L_OBJS_clps711x		:= io-shark.o
-
-l-obj-y			+= io-readsb.o io-writesb.o
-l-obj-$(full)		+= io-readsw-armv3.o io-writesw-armv3.o
-l-obj-$(half)		+= io-readsw-armv4.o io-writesw-armv4.o
-l-obj-y			+= io-readsl.o io-writesl.o
+obj-y		+= io-readsb.o io-writesb.o
+obj-$(v3)	+= io-readsw-armv3.o io-writesw-armv3.o io-readsl-armv3.o
+obj-$(v4)	+= io-readsw-armv4.o io-writesw-armv4.o io-readsl-armv4.o
+obj-y		+= io-writesl.o
 
 ifeq ($(PROCESSOR),armo)
-  L_OBJS += uaccess-armo.o
+  obj-y		+= uaccess-armo.o
 endif
 
 ifneq ($(MACHINE),ebsa110)
-  OX_OBJS += io.o
+  obj-y		+= io.o
 endif
-
-L_OBJS	+= $(L_OBJS_$(MACHINE)) $(l-obj-y)
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-acorn.S linux/arch/arm/lib/io-acorn.S
--- v2.4.1/linux/arch/arm/lib/io-acorn.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-acorn.S	Thu Feb  8 16:32:44 2001
@@ -60,32 +60,32 @@
  */
 
 ENTRY(insw)
-		teq	r2, #0
-		RETINSTR(moveq, pc, lr)
 		addr	r0
-		b	__arch_readsw
+		teq	r2, #0
+		bne	__arch_readsw
+		RETINSTR(mov, pc, lr)
 
 ENTRY(insb)
-		teq	r2, #0
-		RETINSTR(moveq, pc, lr)
 		addr	r0
-		b	__arch_readsb
+		teq	r2, #0
+		bne	__arch_readsb
+		RETINSTR(mov, pc, lr)
 
 @ Purpose: write a block of data from memory to a hardware register.
 @ Proto  : outsw(int to_reg, void *from, int len_in_words);
 @ Notes  : increments from
 
 ENTRY(outsw)
-		teq	r2, #0
-		RETINSTR(moveq, pc, lr)
 		addr	r0
-		b	__arch_writesw
+		teq	r2, #0
+		bne	__arch_writesw
+		RETINSTR(mov, pc, lr)
 
 ENTRY(outsb)
-		teq	r2, #0
-		RETINSTR(moveq, pc, lr)
 		addr	r0
-		b	__arch_writesb
+		teq	r2, #0
+		bne	__arch_writesb
+		RETINSTR(mov, pc, lr)
 
 @ Purpose: write a memc register
 @ Proto  : void memc_write(int register, int value);
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-pcio.S linux/arch/arm/lib/io-pcio.S
--- v2.4.1/linux/arch/arm/lib/io-pcio.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-pcio.S	Thu Feb  8 16:32:44 2001
@@ -1,4 +1,5 @@
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/hardware.h>
 
 		.equ	pcio_high, PCIO_BASE & 0xff000000
@@ -13,26 +14,37 @@
 
 ENTRY(insl)
 		ioaddr	r0, r0
-		b	__arch_readsl
+		teq	r2, #0
+		bne	__arch_readsl
+		RETINSTR(mov, pc, lr)
 
 ENTRY(outsl)
 		ioaddr	r0, r0
-		b	__arch_writesl
-
-		/* Nobody could say these are optimal, but not to worry. */
+		teq	r2, #0
+		bne	__arch_writesl
+		RETINSTR(mov, pc, lr)
 
 ENTRY(outsw)
 		ioaddr	r0, r0
-		b	__arch_writesw
+		teq	r2, #0
+		bne	__arch_writesw
+		RETINSTR(mov, pc, lr)
 
 ENTRY(insw)
 		ioaddr	r0, r0
-		b	__arch_readsw
+		teq	r2, #0
+		bne	__arch_readsw
+		RETINSTR(mov, pc, lr)
 
 ENTRY(insb)
 		ioaddr	r0, r0
-		b	__arch_readsb
+		teq	r2, #0
+		bne	__arch_readsb
+		RETINSTR(mov, pc, lr)
 
 ENTRY(outsb)
 		ioaddr	r0, r0
-		b	__arch_writesb
+		teq	r2, #0
+		bne	__arch_writesb
+		RETINSTR(mov, pc, lr)
+
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-readsb.S linux/arch/arm/lib/io-readsb.S
--- v2.4.1/linux/arch/arm/lib/io-readsb.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-readsb.S	Thu Feb  8 16:32:44 2001
@@ -62,6 +62,7 @@
 		ldrb	ip, [r0]
 		orr	r6, r6, ip, lsl #24
 		stmia	r1!, {r3 - r6}
+
 		subs	r2, r2, #16
 		bpl	.insb_16_lp
 
@@ -88,7 +89,7 @@
 		stmia	r1!, {r3, r4}
 
 .insb_no_8:	tst	r2, #4
-		bne	.insb_no_4
+		beq	.insb_no_4
 
 		ldrb	r3, [r0]
 		ldrb	r4, [r0]
@@ -101,6 +102,7 @@
 
 .insb_no_4:	ands	r2, r2, #3
 		LOADREGS(eqfd, sp!, {r4 - r6, pc})
+
 		cmp	r2, #2
 		ldrb	r3, [r0]
 		strb	r3, [r1], #1
@@ -108,4 +110,5 @@
 		strgeb	r3, [r1], #1
 		ldrgtb	r3, [r0]
 		strgtb	r3, [r1]
+
 		LOADREGS(fd, sp!, {r4 - r6, pc})
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-readsl-armv3.S linux/arch/arm/lib/io-readsl-armv3.S
--- v2.4.1/linux/arch/arm/lib/io-readsl-armv3.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/io-readsl-armv3.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,76 @@
+/*
+ *  linux/arch/arm/lib/io-readsl-armv3.S
+ *
+ *  Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+/*
+ * Note that some reads can be aligned on half-word boundaries.
+ */
+ENTRY(__arch_readsl)
+		ands	ip, r1, #3
+		bne	2f
+
+1:		ldr	r3, [r0]
+		str	r3, [r1], #4
+		subs	r2, r2, #1
+		bne	1b
+		mov	pc, lr
+
+2:		cmp	ip, #2
+		ldr	ip, [r0]
+		blt	4f
+		bgt	6f
+
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+3:		subs	r2, r2, #1
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, lsl #16
+		strne	ip, [r1], #4
+		movne	ip, r3, lsr #16
+		bne	3b
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1
+		mov	pc, lr
+
+4:		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+5:		subs	r2, r2, #1
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, lsl #8
+		strne	ip, [r1], #4
+		movne	ip, r3, lsr #24
+		bne	5b
+		strb	ip, [r1], #1
+		mov	pc, lr
+
+6:		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+7:		subs	r2, r2, #1
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, lsl #24
+		strne	ip, [r1], #4
+		movne	ip, r3, lsr #8
+		bne	7b
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strb	ip, [r1], #1
+		mov	pc, lr
+
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-readsl-armv4.S linux/arch/arm/lib/io-readsl-armv4.S
--- v2.4.1/linux/arch/arm/lib/io-readsl-armv4.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/arm/lib/io-readsl-armv4.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,68 @@
+/*
+ *  linux/arch/arm/lib/io-readsl-armv4.S
+ *
+ *  Copyright (C) 1995-2000 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hardware.h>
+
+/*
+ * Note that some reads can be aligned on half-word boundaries.
+ */
+ENTRY(__arch_readsl)
+		ands	ip, r1, #3
+		bne	2f
+
+1:		ldr	r3, [r0]
+		str	r3, [r1], #4
+		subs	r2, r2, #1
+		bne	1b
+		mov	pc, lr
+
+2:		cmp	ip, #2
+		ldr	ip, [r0]
+		blt	4f
+		bgt	6f
+
+		strh	ip, [r1], #2
+		mov	ip, ip, lsr #16
+3:		subs	r2, r2, #1
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, lsl #16
+		strne	ip, [r1], #4
+		movne	ip, r3, lsr #16
+		bne	3b
+		strh	ip, [r1], #2
+		mov	pc, lr
+
+4:		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strh	ip, [r1], #2
+		mov	ip, ip, lsr #16
+5:		subs	r2, r2, #1
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, lsl #8
+		strne	ip, [r1], #4
+		movne	ip, r3, lsr #24
+		bne	5b
+		strb	ip, [r1], #1
+		mov	pc, lr
+
+6:		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+7:		subs	r2, r2, #1
+		ldrne	r3, [r0]
+		orrne	ip, ip, r3, lsl #24
+		strne	ip, [r1], #4
+		movne	ip, r3, lsr #8
+		bne	7b
+		strb	ip, [r1], #1
+		mov	ip, ip, lsr #8
+		strh	ip, [r1], #2
+		mov	pc, lr
+
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-readsl.S linux/arch/arm/lib/io-readsl.S
--- v2.4.1/linux/arch/arm/lib/io-readsl.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-readsl.S	Wed Dec 31 16:00:00 1969
@@ -1,65 +0,0 @@
-/*
- *  linux/arch/arm/lib/io-readsb.S
- *
- *  Copyright (C) 1995-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/linkage.h>
-#include <asm/assembler.h>
-#include <asm/hardware.h>
-
-ENTRY(__arch_readsl)
-		ands	ip, r1, #3
-		bne	2f
-
-1:		ldr	r3, [r0]
-		str	r3, [r1], #4
-		subs	r2, r2, #1
-		bne	1b
-		mov	pc, lr
-
-2:		cmp	ip, #2
-		ldr	ip, [r0]
-		blt	4f
-		bgt	6f
-
-		strh	ip, [r1], #2
-		mov	ip, ip, lsr #16
-3:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #16
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #16
-		bne	3b
-		strh	ip, [r1], #2
-		mov	pc, lr
-
-4:		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strh	ip, [r1], #2
-		mov	ip, ip, lsr #16
-5:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #8
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #24
-		bne	5b
-		strb	ip, [r1], #1
-		mov	pc, lr
-
-6:		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-7:		subs	r2, r2, #1
-		ldrne	r3, [r0]
-		orrne	ip, ip, r3, lsl #24
-		strne	ip, [r1], #4
-		movne	ip, r3, lsr #8
-		bne	7b
-		strb	ip, [r1], #1
-		mov	ip, ip, lsr #8
-		strh	ip, [r1], #2
-		mov	pc, lr
-
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-readsw-armv3.S linux/arch/arm/lib/io-readsw-armv3.S
--- v2.4.1/linux/arch/arm/lib/io-readsw-armv3.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-readsw-armv3.S	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/lib/io-readsb.S
+ *  linux/arch/arm/lib/io-readsw-armv3.S
  *
  *  Copyright (C) 1995-2000 Russell King
  *
@@ -62,8 +62,10 @@
 		orr	r6, r6, lr, lsl #16
 
 		stmia	r1!, {r3 - r6}
+
 		subs	r2, r2, #8
 		bpl	.insw_8_lp
+
 		tst	r2, #7
 		LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
 
@@ -97,6 +99,7 @@
 		strneb	r3, [r1], #1
 		movne	r3, r3, lsr #8
 		strneb	r3, [r1]
+
 		LOADREGS(fd, sp!, {r4, r5, r6, pc})
 
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-readsw-armv4.S linux/arch/arm/lib/io-readsw-armv4.S
--- v2.4.1/linux/arch/arm/lib/io-readsw-armv4.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-readsw-armv4.S	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/lib/io-readsb.S
+ *  linux/arch/arm/lib/io-readsw-armv4.S
  *
  *  Copyright (C) 1995-2000 Russell King
  *
@@ -46,16 +46,18 @@
 		orr	r4, r4, r5, lsl #16
 
 		ldrh	r5, [r0]
-		ldrh	r6, [r0]
-		orr	r5, r5, r6, lsl #16
+		ldrh	ip, [r0]
+		orr	r5, r5, ip, lsl #16
 
 		ldrh	ip, [r0]
 		ldrh	lr, [r0]
 		orr	ip, ip, lr, lsl #16
 
 		stmia	r1!, {r3 - r5, ip}
+
 		subs	r2, r2, #8
 		bpl	.insw_8_lp
+
 		tst	r2, #7
 		LOADREGS(eqfd, sp!, {r4, r5, pc})
 
@@ -84,4 +86,5 @@
 .no_insw_2:	tst	r2, #1
 		ldrneh	r3, [r0]
 		strneh	r3, [r1]
+
 		LOADREGS(fd, sp!, {r4, r5, pc})
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-writesb.S linux/arch/arm/lib/io-writesb.S
--- v2.4.1/linux/arch/arm/lib/io-writesb.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-writesb.S	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/lib/io-readsb.S
+ *  linux/arch/arm/lib/io-writesb.S
  *
  *  Copyright (C) 1995-2000 Russell King
  *
@@ -13,7 +13,7 @@
 
 .outsb_align:	rsb	ip, ip, #4
 		cmp	ip, r2
-		mov	ip, r2
+		movgt	ip, r2
 		cmp	ip, #2
 		ldrb	r3, [r1], #1
 		strb	r3, [r0]
@@ -34,6 +34,7 @@
 		bmi	.outsb_no_16
 
 .outsb_16_lp:	ldmia	r1!, {r3 - r6}
+
 		strb	r3, [r0]
 		mov	r3, r3, lsr #8
 		strb	r3, [r0]
@@ -65,6 +66,7 @@
 		strb	r6, [r0]
 		mov	r6, r6, lsr #8
 		strb	r6, [r0]
+
 		subs	r2, r2, #16
 		bpl	.outsb_16_lp
 
@@ -74,7 +76,8 @@
 .outsb_no_16:	tst	r2, #8
 		beq	.outsb_no_8
 
-		ldmia	r1, {r3, r4}
+		ldmia	r1!, {r3, r4}
+
 		strb	r3, [r0]
 		mov	r3, r3, lsr #8
 		strb	r3, [r0]
@@ -92,7 +95,7 @@
 		strb	r4, [r0]
 
 .outsb_no_8:	tst	r2, #4
-		bne	.outsb_no_4
+		beq	.outsb_no_4
 
 		ldr	r3, [r1], #4
 		strb	r3, [r0]
@@ -105,6 +108,7 @@
 
 .outsb_no_4:	ands	r2, r2, #3
 		LOADREGS(eqfd, sp!, {r4 - r6, pc})
+
 		cmp	r2, #2
 		ldrb	r3, [r1], #1
 		strb	r3, [r0]
@@ -112,4 +116,5 @@
 		strgeb	r3, [r0]
 		ldrgtb	r3, [r1]
 		strgtb	r3, [r0]
+
 		LOADREGS(fd, sp!, {r4 - r6, pc})
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-writesl.S linux/arch/arm/lib/io-writesl.S
--- v2.4.1/linux/arch/arm/lib/io-writesl.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-writesl.S	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/lib/io-readsb.S
+ *  linux/arch/arm/lib/io-writesl.S
  *
  *  Copyright (C) 1995-2000 Russell King
  *
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-writesw-armv3.S linux/arch/arm/lib/io-writesw-armv3.S
--- v2.4.1/linux/arch/arm/lib/io-writesw-armv3.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-writesw-armv3.S	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/lib/io-readsb.S
+ *  linux/arch/arm/lib/io-writesw-armv3.S
  *
  *  Copyright (C) 1995-2000 Russell King
  *
@@ -39,6 +39,7 @@
 
 		subs	r2, r2, #8
 		bmi	.no_outsw_8
+
 .outsw_8_lp:	ldmia	r1!, {r3, r4, r5, r6}
 
 		mov	ip, r3, lsl #16
@@ -75,6 +76,7 @@
 
 		subs	r2, r2, #8
 		bpl	.outsw_8_lp
+
 		tst	r2, #7
 		LOADREGS(eqfd, sp!, {r4, r5, r6, pc})
 
@@ -121,5 +123,3 @@
 		strne	ip, [r0]
 
 		LOADREGS(fd, sp!, {r4, r5, r6, pc})
-
-
diff -u --recursive --new-file v2.4.1/linux/arch/arm/lib/io-writesw-armv4.S linux/arch/arm/lib/io-writesw-armv4.S
--- v2.4.1/linux/arch/arm/lib/io-writesw-armv4.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/lib/io-writesw-armv4.S	Thu Feb  8 16:32:44 2001
@@ -1,5 +1,5 @@
 /*
- *  linux/arch/arm/lib/io-readsb.S
+ *  linux/arch/arm/lib/io-writesw-armv4.S
  *
  *  Copyright (C) 1995-2000 Russell King
  *
@@ -32,11 +32,11 @@
 		tst	r1, #3
 		bne	.outsw_align
 
+		stmfd	sp!, {r4, r5, lr}
+
 		subs	r2, r2, #8
 		bmi	.no_outsw_8
 
-		stmfd	sp!, {r4, r5, lr}
-
 .outsw_8_lp:	ldmia	r1!, {r3, r4, r5, ip}
 
 		strh	r3, [r0]
@@ -54,26 +54,31 @@
 
 		subs	r2, r2, #8
 		bpl	.outsw_8_lp
-		ldmfd	sp!, {r4, r5, lr}
+
 		tst	r2, #7
-		RETINSTR(moveq, pc, lr)
+		LOADREGS(eqfd, sp!, {r4, r5, pc})
 
 .no_outsw_8:	tst	r2, #4
-		ldmneia	r1!, {r3, ip}
-		strneh	r3, [r0]
-		movne	r3, r3, lsr #16
-		strneh	r3, [r0]
-		strneh	ip, [r0]
-		movne	ip, ip, lsr #16
-		strneh	ip, [r0]
-		tst	r2, #2
-		ldrne	r3, [r1], #4
-		strneh	r3, [r0]
-		movne	r3, r3, lsr #16
-		strneh	r3, [r0]
-		tst	r2, #1
+		beq	.no_outsw_4
+
+		ldmia	r1!, {r3, ip}
+		strh	r3, [r0]
+		mov	r3, r3, lsr #16
+		strh	r3, [r0]
+		strh	ip, [r0]
+		mov	ip, ip, lsr #16
+		strh	ip, [r0]
+
+.no_outsw_4:	tst	r2, #2
+		beq	.no_outsw_2
+
+		ldr	r3, [r1], #4
+		strh	r3, [r0]
+		mov	r3, r3, lsr #16
+		strh	r3, [r0]
+
+.no_outsw_2:	tst	r2, #1
 		ldrneh	r3, [r1]
 		strneh	r3, [r0]
-		RETINSTR(mov, pc, lr)
-
 
+		LOADREGS(fd, sp!, {r4, r5, pc})
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mach-sa1100/Makefile linux/arch/arm/mach-sa1100/Makefile
--- v2.4.1/linux/arch/arm/mach-sa1100/Makefile	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-sa1100/Makefile	Thu Feb  8 16:32:44 2001
@@ -20,15 +20,4 @@
 
 obj-$(CONFIG_LEDS)	+= leds.o
 
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-
-# Translate to Rules.make lists.
-
-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)))
-
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mach-sa1100/hw.c linux/arch/arm/mach-sa1100/hw.c
--- v2.4.1/linux/arch/arm/mach-sa1100/hw.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-sa1100/hw.c	Thu Feb  8 16:32:44 2001
@@ -90,12 +90,12 @@
 void clr_bitsy_egpio(unsigned long x) 
 {
   bitsy_egpio &= ~x;
-  *(volatile int *)0xdc000000 = bitsy_egpio;
+  BITSY_EGPIO = bitsy_egpio;
 }
 void set_bitsy_egpio(unsigned long x) 
 {
   bitsy_egpio |= x;
-  *(volatile int *)0xdc000000 = bitsy_egpio;
+  BITSY_EGPIO = bitsy_egpio;
 }
 EXPORT_SYMBOL(clr_bitsy_egpio);
 EXPORT_SYMBOL(set_bitsy_egpio);
@@ -119,8 +119,8 @@
   /* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
    * (SA-1110 Developer's Manual, section 9.1.2.1)
    */
-  GAFR |= GPIO_GPIO27;
-  GPDR |= GPIO_GPIO27;
+  GAFR |= GPIO_32_768kHz;
+  GPDR |= GPIO_32_768kHz;
   TUCR = TUCR_3_6864MHz;
 
   /* Now, set up the PLL and RCLK in the SA-1111: */
@@ -133,32 +133,32 @@
    * using the SKPCR.
    */
 
-  {
-  /*
-   * SA1111 DMA bus master setup 
+  /* If the system is going to use the SA-1111 DMA engines, set up
+   * the memory bus request/grant pins. Also configure the shared
+   * memory controller on the SA-1111 (SA-1111 Developer's Manual,
+   * section 3.2.3) and power up the DMA bus clock:
    */
-	int cas;
+  if(machine_is_assabet()){
 
-	/* SA1111 side */
-	switch ( (MDCNFG>>12) & 0x03 ) {
-	case 0x02:
-		cas = 0; break;
-	case 0x03:
-		cas = 1; break;
-	default:
-		cas = 1; break;
-	}
-	SMCR = 1		/* 1: memory is SDRAM */
-		| ( 1 << 1 )	/* 1:MBGNT is enable */
-		| ( ((MDCNFG >> 4) & 0x07) << 2 )	/* row address lines */
-		| ( cas << 5 );	/* CAS latency */
-
-	/* SA1110 side */
-	GPDR |= 1<<21;
-	GPDR &= ~(1<<22);
-	GAFR |= ( (1<<21) | (1<<22) );
+    GAFR |= (GPIO_MBGNT | GPIO_MBREQ);
+    GPDR |= GPIO_MBGNT;
+    GPDR &= ~GPIO_MBREQ;
+    TUCR |= TUCR_MR;
+
+    /* Assabet is populated by default with two Samsung KM416S8030T-G8
+     * 128Mb SDRAMs, which are organized as 12-bit (row addr) x 9-bit
+     * (column addr), according to the data sheet. Apparently, the 
+     * bank selects factor into the row address, as Angel sets up the
+     * SA-1110 to use 14x9 addresses. The SDRAM datasheet specifies
+     * that when running at 100-125MHz, the CAS latency for -8 parts
+     * is 3 cycles, which is consistent with Angel.
+     */
+
+    SMCR = (SMCR_DTIM | SMCR_MBGE | 
+	    FInsrt(FExtr(MDCNFG, MDCNFG_SA1110_DRAC0), SMCR_DRAC) |
+	    ((FExtr(MDCNFG, MDCNFG_SA1110_TDL0)==3) ? SMCR_CLAT : 0));
 
-	TUCR |= (1<<10);
+    SKPCR |= SKPCR_DCLKEN;
   }
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mach-shark/Makefile linux/arch/arm/mach-shark/Makefile
--- v2.4.1/linux/arch/arm/mach-shark/Makefile	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mach-shark/Makefile	Thu Feb  8 16:32:44 2001
@@ -5,6 +5,8 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (ie not a .c file).
 
+USE_STANDARD_AS_RULE := true
+
 O_TARGET		:= shark.o
 
 # Object file lists.
@@ -17,16 +19,5 @@
 export-objs		:= 
 
 #obj-$(CONFIG_LEDS)	+= leds.o
-
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-
-# Translate to Rules.make lists.
-
-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)))
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/Makefile linux/arch/arm/mm/Makefile
--- v2.4.1/linux/arch/arm/mm/Makefile	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/Makefile	Thu Feb  8 16:32:44 2001
@@ -9,12 +9,11 @@
 
 USE_STANDARD_AS_RULE := true
 
-EXTRA_AFLAGS	:= -traditional
 O_TARGET	:= mm.o
 
 # Object file lists.
 
-obj-y		:= extable.o fault-$(PROCESSOR).o init.o \
+obj-y		:= extable.o fault-common.o fault-$(PROCESSOR).o init.o \
 		   mm-$(PROCESSOR).o small_page.o
 obj-m		:=
 obj-n		:=
@@ -22,10 +21,10 @@
 export-objs	:= proc-syms.o
 
 p-$(CONFIG_CPU_26)	+= proc-arm2,3.o
-p-$(CONFIG_CPU_ARM6)	+= proc-arm6,7.o
-p-$(CONFIG_CPU_ARM7)	+= proc-arm6,7.o
-p-$(CONFIG_CPU_ARM720)	+= proc-arm720.o
-p-$(CONFIG_CPU_ARM920)	+= proc-arm920.o
+p-$(CONFIG_CPU_ARM610)	+= proc-arm6,7.o
+p-$(CONFIG_CPU_ARM710)	+= proc-arm6,7.o
+p-$(CONFIG_CPU_ARM720T)	+= proc-arm720.o
+p-$(CONFIG_CPU_ARM920T)	+= proc-arm920.o
 p-$(CONFIG_CPU_ARM10)	+= proc-arm10.o
 p-$(CONFIG_CPU_SA110)	+= proc-sa110.o
 p-$(CONFIG_CPU_SA1100)	+= proc-sa110.o
@@ -37,29 +36,16 @@
 
 # Integrator follows "new style"
 # Soon, others will do too, and we can get rid of this
-MMMACH		:= mm-$(MACHINE).o
+MMMACH		:= mm-$(MACHINE).c
 ifeq ($(MMMACH),$(wildcard $(MMMACH)))
-obj-$(CONFIG_CPU_32)	+= $(MMMACH)
+obj-$(CONFIG_CPU_32)	+= $(MMMACH:.c=.o)
 endif
 
 obj-y		+= $(sort $(p-y))
 
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-
-# Translate to Rules.make lists.
-
-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)))
-
 include $(TOPDIR)/Rules.make
 
 # Special dependencies
-fault-armv.o:   fault-common.c
-fault-armo.o:   fault-common.c
 proc-arm2,3.o:	../lib/constants.h
 proc-arm6,7.o:	../lib/constants.h
 proc-arm720.o:	../lib/constants.h
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/fault-armo.c linux/arch/arm/mm/fault-armo.c
--- v2.4.1/linux/arch/arm/mm/fault-armo.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/fault-armo.c	Thu Feb  8 16:32:44 2001
@@ -23,14 +23,20 @@
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
 
-#define FAULT_CODE_FORCECOW	0x80
+#define FAULT_CODE_LDRSTRPOST	0x80
+#define FAULT_CODE_LDRSTRPRE	0x40
+#define FAULT_CODE_LDRSTRREG	0x20
+#define FAULT_CODE_LDMSTM	0x10
+#define FAULT_CODE_LDCSTC	0x08
 #define FAULT_CODE_PREFETCH	0x04
 #define FAULT_CODE_WRITE	0x02
+#define FAULT_CODE_FORCECOW	0x01
 
 #define DO_COW(m)		((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
 #define READ_FAULT(m)		(!((m) & FAULT_CODE_WRITE))
 
-#include "fault-common.c"
+extern int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs);
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
 
 /*
  * Handle a data abort.  Note that we have to handle a range of addresses
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/fault-armv.c linux/arch/arm/mm/fault-armv.c
--- v2.4.1/linux/arch/arm/mm/fault-armv.c	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/fault-armv.c	Thu Feb  8 16:32:44 2001
@@ -27,27 +27,9 @@
 #include <asm/pgtable.h>
 #include <asm/unaligned.h>
 
-#define FAULT_CODE_READ		0x02
-
-#define DO_COW(m)		(!((m) & FAULT_CODE_READ))
-#define READ_FAULT(m)		((m) & FAULT_CODE_READ)
-
 extern void die_if_kernel(const char *str, struct pt_regs *regs, int err);
-
-#include "fault-common.c"
-
-#ifdef DEBUG
-static int sp_valid(unsigned long *sp)
-{
-	unsigned long addr = (unsigned long) sp;
-
-	if (addr >= 0xb0000000 && addr < 0xd0000000)
-		return 1;
-	if (addr >= 0x03ff0000 && addr < 0x04000000)
-		return 1;
-	return 0;
-}
-#endif
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+extern int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs);
 
 #ifdef CONFIG_ALIGNMENT_TRAP
 /*
@@ -178,6 +160,15 @@
 					eaddr -= offset.un;
 			}
 
+			/*
+			 * This is a "hint" - we already have eaddr worked out by the
+			 * processor for us.
+			 */
+			if (addr != eaddr)
+				printk(KERN_ERR "LDRHSTRH: PC = %08lx, instr = %08x, "
+					"addr = %08lx, eaddr = %08lx\n",
+					 instruction_pointer(regs), instr, addr, eaddr);
+
 			if (LDST_L_BIT(instr))
 				regs->uregs[rd] = get_unaligned((unsigned short *)eaddr);
 			else
@@ -253,8 +244,15 @@
 			}
 		}
 
-if (addr != eaddr)
-printk("PC = %08lx, instr = %08x, addr = %08lx, eaddr = %08lx\n", instruction_pointer(regs), instr, addr, eaddr);
+		/*
+		 * This is a "hint" - we already have eaddr worked out by the
+		 * processor for us.
+		 */
+		if (addr != eaddr)
+			printk(KERN_ERR "LDRSTR: PC = %08lx, instr = %08x, "
+				"addr = %08lx, eaddr = %08lx\n",
+				 instruction_pointer(regs), instr, addr, eaddr);
+
 		if (LDST_L_BIT(instr)) {
 			regs->uregs[rd] = get_unaligned((unsigned long *)eaddr);
 			if (rd == 15)
@@ -284,6 +282,15 @@
 		if  (!LDST_U_BIT(instr))
 			eaddr -= nr_regs;
 
+		/*
+		 * This is a "hint" - we already have eaddr worked out by the
+		 * processor for us.
+		 */
+		if (addr != eaddr)
+			printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08x, "
+				"addr = %08lx, eaddr = %08lx\n",
+				 instruction_pointer(regs), instr, addr, eaddr);
+
 		if ((LDST_U_BIT(instr) == 0 && LDST_P_BIT(instr) == 0) ||
 		    (LDST_U_BIT(instr)      && LDST_P_BIT(instr)))
 			eaddr += 4;
@@ -322,39 +329,39 @@
 
 #endif
 
-#ifdef CONFIG_DEBUG_USER
-
+/*
+ * Some section permission faults need to be handled gracefully, for
+ * instance, when they happen due to a __{get,put}_user during an oops).
+ * In this case, we should return an error to the __{get,put}_user caller
+ * instead of causing another oops.  We should also fixup this fault as
+ * the user could pass a pointer to a section to the kernel.
+ */
 static int
 do_sect_fault(unsigned long addr, int error_code, struct pt_regs *regs)
 {
+	unsigned long fixup;
+
 	if (user_mode(regs)) {
+#ifdef CONFIG_DEBUG_USER
 		printk("%s: permission fault on section, "
 		       "address=0x%08lx, code %d\n",
 		       current->comm, addr, error_code);
+#endif
+		goto fail;
+	}
+
+	fixup = search_exception_table(instruction_pointer(regs));
+	if (fixup != 0) {
 #ifdef DEBUG
-		{
-			unsigned int i, j;
-			unsigned long *sp;
-
-			sp = (unsigned long *) (regs->ARM_sp - 128);
-			for (j = 0; j < 20 && sp_valid(sp); j++) {
-				printk("%p: ", sp);
-				for (i = 0; i < 8 && sp_valid(sp); i += 1, sp++)
-					printk("%08lx ", *sp);
-				printk("\n");
-			}
-			show_regs(regs);
-			c_backtrace(regs->ARM_fp, regs->ARM_cpsr);
-		}
+		printk(KERN_DEBUG "%s: Exception at [<%lx>] addr=%lx (fixup: %lx)\n",
+			tsk->comm, regs->ARM_pc, addr, fixup);
 #endif
+		regs->ARM_pc = fixup;
+		return 0;
 	}
+fail:
 	return 1;	/* not fixed up */
 }
-#else
-
-#define do_sect_fault NULL
-
-#endif
 
 static const struct fsr_info {
 	int	(*fn)(unsigned long addr, int error_code, struct pt_regs *regs);
@@ -382,18 +389,19 @@
 /*
  * Currently dropped down to debug level
  */
-#define BUG_PROC_MSG \
-  KERN_DEBUG "Weird data abort (%08X).\n" \
-  KERN_DEBUG "Please see http://www.arm.linux.org.uk/state.html for " \
-	"more information\n"
-
 asmlinkage void
 do_DataAbort(unsigned long addr, int error_code, struct pt_regs *regs, int fsr)
 {
 	const struct fsr_info *inf = fsr_info + (fsr & 15);
 
+#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
 	if (addr == regs->ARM_pc)
-		goto weirdness;
+		goto sa1_weirdness;
+#endif
+#if defined(CONFIG_CPU_ARM720T) && defined(CONFIG_ALIGNMENT_TRAP)
+	if (addr & 3 && (fsr & 13) != 1)
+		goto arm720_weirdness;
+#endif
 
 	if (!inf->fn)
 		goto bad;
@@ -409,26 +417,51 @@
 	die_if_kernel("Oops", regs, 0);
 	return;
 
-weirdness:
+#if defined(CONFIG_CPU_SA110) || defined(CONFIG_CPU_SA1100)
+sa1_weirdness:
 	if (user_mode(regs)) {
 		static int first = 1;
 		if (first)
-			/*
-			 * I want statistical information on this problem,
-			 * but we don't want to hastle the users too much.
-			 */
-			printk(BUG_PROC_MSG, fsr);
+			printk(KERN_DEBUG "Weird data abort detected\n");
 		first = 0;
 		return;
 	}
 
 	if (!inf->fn || inf->fn(addr, error_code, regs))
 		goto bad;
+	return;
+#endif
+#if defined(CONFIG_CPU_ARM720T) && defined(CONFIG_ALIGNMENT_TRAP)
+arm720_weirdness:
+	if (!user_mode(regs)) {
+		unsigned long instr;
+
+		instr = *(unsigned long *)instruction_pointer(regs);
+
+		if ((instr & 0x04400000) != 0x04400000) {
+			static int first = 1;
+			if (first)
+				printk("Mis-reported alignment fault at "
+					"0x%08lx, fsr 0x%02x, code 0x%02x, "
+					"PC = 0x%08lx, instr = 0x%08lx\n",
+					addr, fsr, error_code, regs->ARM_pc,
+					instr);
+			first = 0;
+			cpu_tlb_invalidate_all();
+			cpu_cache_clean_invalidate_all();
+			return;
+		}
+	}
+
+	if (!inf->fn || inf->fn(addr, error_code, regs))
+		goto bad;
+	return;
+#endif
 }
 
 asmlinkage int
 do_PrefetchAbort(unsigned long addr, struct pt_regs *regs)
 {
-	do_page_fault(addr, FAULT_CODE_READ, regs);
+	do_page_fault(addr, 0, regs);
 	return 1;
 }
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/fault-common.c linux/arch/arm/mm/fault-common.c
--- v2.4.1/linux/arch/arm/mm/fault-common.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/mm/fault-common.c	Thu Feb  8 16:32:44 2001
@@ -9,8 +9,41 @@
  * published by the Free Software Foundation.
  */
 #include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/unaligned.h>
+
+#ifdef CONFIG_CPU_26
+#define FAULT_CODE_WRITE	0x02
+#define FAULT_CODE_FORCECOW	0x01
+#define DO_COW(m)		((m) & (FAULT_CODE_WRITE|FAULT_CODE_FORCECOW))
+#define READ_FAULT(m)		(!((m) & FAULT_CODE_WRITE))
+#else
+/*
+ * On 32-bit processors, we define "mode" to be zero when reading,
+ * non-zero when writing.  This now ties up nicely with the polarity
+ * of the 26-bit machines, and also means that we avoid the horrible
+ * gcc code for "int val = !other_val;".
+ */
+#define DO_COW(m)		(m)
+#define READ_FAULT(m)		(!(m))
+#endif
 
-extern void die(const char *msg, struct pt_regs *regs, int err);
+NORET_TYPE void die(const char *msg, struct pt_regs *regs, int err) ATTRIB_NORET;
 
 /*
  * This is useful to dump out the page tables associated with
@@ -60,7 +93,9 @@
 	printk("\n");
 }
 
-static int __do_page_fault(struct mm_struct *mm, unsigned long addr, int mode, struct task_struct *tsk)
+static int
+__do_page_fault(struct mm_struct *mm, unsigned long addr, int mode,
+		struct task_struct *tsk)
 {
 	struct vm_area_struct *vma;
 	int fault, mask;
@@ -159,7 +194,7 @@
 	return -2;
 }
 
-static int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
+int do_page_fault(unsigned long addr, int mode, struct pt_regs *regs)
 {
 	struct task_struct *tsk;
 	struct mm_struct *mm;
@@ -278,8 +313,10 @@
 	 * Oops. The kernel tried to access some bad page. We'll have to
 	 * terminate things with extreme prejudice.
 	 */
-	printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n",
-		(addr < PAGE_SIZE) ? "NULL pointer dereference" : "paging request", addr);
+	printk(KERN_ALERT
+		"Unable to handle kernel %s at virtual address %08lx\n",
+		(addr < PAGE_SIZE) ? "NULL pointer dereference" :
+		"paging request", addr);
 
 	show_pte(mm, addr);
 	die("Oops", regs, mode);
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/init.c linux/arch/arm/mm/init.c
--- v2.4.1/linux/arch/arm/mm/init.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/mm/init.c	Thu Feb  8 16:32:44 2001
@@ -49,7 +49,7 @@
 #define TABLE_SIZE	((TABLE_OFFSET + PTRS_PER_PTE) * sizeof(void *))
 
 static unsigned long totalram_pages;
-pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
 extern char _stext, _text, _etext, _end, __init_begin, __init_end;
 
 /*
@@ -418,7 +418,7 @@
 	if (machine_is_archimedes() || machine_is_a5k())
 		reserve_bootmem_node(pgdat, 0x02000000, 0x00080000);
 	if (machine_is_p720t())
-		reserve_bootmem_node(pgdat, 0xc0000000, 0x00014000);
+		reserve_bootmem_node(pgdat, PAGE_OFFSET, 0x00014000);
 }
 
 /*
@@ -450,8 +450,28 @@
 	initrd_node   = check_initrd(mi);
 
 	map_pg = bootmap_pfn;
-	
-	for (node = 0; node < numnodes; node++, np++) {
+
+	/*
+	 * Initialise the bootmem nodes.
+	 *
+	 * What we really want to do is:
+	 *
+	 *   unmap_all_regions_except_kernel();
+	 *   for_each_node_in_reverse_order(node) {
+	 *     map_node(node);
+	 *     allocate_bootmem_map(node);
+	 *     init_bootmem_node(node);
+	 *     free_bootmem_node(node);
+	 *   }
+	 *
+	 * but this is a 2.5-type change.  For now, we just set
+	 * the nodes up in reverse order.
+	 *
+	 * (we could also do with rolling bootmem_init and paging_init
+	 * into one generic "memory_init" type function).
+	 */
+	np += numnodes - 1;
+	for (node = numnodes - 1; node >= 0; node--, np--) {
 		/*
 		 * If there are no pages in this node, ignore it.
 		 * Note that node 0 must always have some pages.
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/mm-armv.c linux/arch/arm/mm/mm-armv.c
--- v2.4.1/linux/arch/arm/mm/mm-armv.c	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/mm/mm-armv.c	Thu Feb  8 16:32:44 2001
@@ -275,7 +275,7 @@
 	off    = md->physical - virt;
 	length = md->length;
 
-	while ((virt & 1048575 || (virt + off) & 1048575) && length >= PAGE_SIZE) {
+	while ((virt & 0xfffff || (virt + off) & 0xfffff) && length >= PAGE_SIZE) {
 		alloc_init_page(virt, virt + off, md->domain, prot_pte);
 
 		virt   += PAGE_SIZE;
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/proc-arm6,7.S linux/arch/arm/mm/proc-arm6,7.S
--- v2.4.1/linux/arch/arm/mm/proc-arm6,7.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/proc-arm6,7.S	Thu Feb  8 16:32:44 2001
@@ -7,10 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- *  MMU functions for ARM6
- *
  *  These are the low level assembler for performing cache and TLB
- *  functions on the ARM6 & ARM7.
+ *  functions on the ARM610 & ARM710.
  */
 #include <linux/linkage.h>
 #include <asm/assembler.h>
@@ -105,9 +103,9 @@
 
 ENTRY(cpu_arm6_data_abort)
 		ldr	r4, [r0]			@ read instruction causing problem
-		mov	r1, r4, lsr #19			@ r1 b1 = L
+		tst	r4, r4, lsr #21			@ C = bit 20
+		sbc	r1, r1, r1			@ r1 = C - 1
 		and	r2, r4, #14 << 24
-		and	r1, r1, #2			@ check read/write bit
 		teq	r2, #8 << 24			@ was it ldm/stm
 		bne	Ldata_simple
 
@@ -138,9 +136,9 @@
 
 ENTRY(cpu_arm7_data_abort)
 		ldr	r4, [r0]			@ read instruction causing problem
-		mov	r1, r4, lsr #19			@ r1 b1 = L
+		tst	r4, r4, lsr #21			@ C = bit 20
+		sbc	r1, r1, r1			@ r1 = C - 1
 		and	r2, r4, #15 << 24
-		and	r1, r1, #2			@ check read/write bit
 		add	pc, pc, r2, lsr #22		@ Now branch to the relevent processing routine
 		movs	pc, lr
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/proc-arm720.S linux/arch/arm/mm/proc-arm720.S
--- v2.4.1/linux/arch/arm/mm/proc-arm720.S	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/mm/proc-arm720.S	Thu Feb  8 16:32:44 2001
@@ -144,9 +144,9 @@
 
 ENTRY(cpu_arm720_data_abort)
 		ldr	r4, [r0]			@ read instruction causing problem
-		mov	r1, r4, lsr #19			@ r1 b1 = L
+		tst	r4, r4, lsr #21			@ C = bit 20
+		sbc	r1, r1, r1			@ r1 = C - 1
 		and	r2, r4, #15 << 24
-		and	r1, r1, #2			@ check read/write bit
 		add	pc, pc, r2, lsr #22		@ Now branch to the relevent processing routine
 		movs	pc, lr
 
@@ -283,23 +283,11 @@
 		ldmfd	sp!, {pc}
 
 /*
- * Function: arm720_proc_do_idle (void)
- *
- * Params  : r0 = call type:
- *           0 = slow idle
- *           1 = fast idle
- *           2 = switch to slow processor clock
- *           3 = switch to fast processor clock
- *
+ * Function: arm720_proc_do_idle(void)
+ * Params  : r0 = unused
  * Purpose : put the processer in proper idle mode
  */
 ENTRY(cpu_arm720_do_idle)
-#if 0 /* FIXME: is this part of the processor? */
-		ldr	r2, =IO_BASE			@ Virt addr of IO
-		add	r2, r2, #0x00050000		@ Start of PMU regs
-		mov	r1, #0x01			@ Idle mode
-		str	r1, [r2, #4]
-#endif
 		mov	pc, lr
 
 /*
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/proc-arm920.S linux/arch/arm/mm/proc-arm920.S
--- v2.4.1/linux/arch/arm/mm/proc-arm920.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/proc-arm920.S	Thu Feb  8 16:32:44 2001
@@ -68,9 +68,9 @@
 ENTRY(cpu_arm920_data_abort)
 	ldr	r1, [r0]			@ read aborted instruction
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	mov	r1, r1, lsr #19			@ b1 = L
+	tst	r1, r1, lsr #21			@ C = bit 20
 	mrc	p15, 0, r3, c5, c0, 0		@ get FSR
-	and	r1, r1, #2
+	sbc	r1, r1, r1			@ r1 = C - 1
 	and	r3, r3, #255
 	mov	pc, lr
 
@@ -330,7 +330,7 @@
 	mov	r0, #0
 	mcr	p15, 0, r0, c7, c10, 4		@ drain WB
 ENTRY(cpu_arm920_icache_invalidate_page)
-	/* why no invalidate I cache --rmk */
+	mcr	p15, 0, r0, c7, c5, 0		@ invalidate I cache
 	mov	pc, lr
 
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/mm/proc-sa110.S linux/arch/arm/mm/proc-sa110.S
--- v2.4.1/linux/arch/arm/mm/proc-sa110.S	Mon Sep 18 15:15:25 2000
+++ linux/arch/arm/mm/proc-sa110.S	Thu Feb  8 16:32:44 2001
@@ -83,9 +83,9 @@
 ENTRY(cpu_sa1100_data_abort)
 	ldr	r1, [r0]			@ read aborted instruction
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
-	mov	r1, r1, lsr #19			@ b1 = L
+	tst	r1, r1, lsr #21			@ C = bit 20
 	mrc	p15, 0, r3, c5, c0, 0		@ get FSR
-	and	r1, r1, #2
+	sbc	r1, r1, r1			@ r1 = C - 1
 	and	r3, r3, #255
 	mov	pc, lr
 
diff -u --recursive --new-file v2.4.1/linux/arch/arm/nwfpe/Makefile linux/arch/arm/nwfpe/Makefile
--- v2.4.1/linux/arch/arm/nwfpe/Makefile	Sun Aug 13 09:54:15 2000
+++ linux/arch/arm/nwfpe/Makefile	Thu Feb  8 16:32:44 2001
@@ -6,27 +6,27 @@
 
 USE_STANDARD_AS_RULE := true
 
-NWFPE_OBJS := fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \
-	      fpmodule.o fpopcode.o softfloat.o \
-	      single_cpdo.o double_cpdo.o extended_cpdo.o
+O_TARGET		:= math-emu.o
 
-ifeq ($(CONFIG_CPU_26),y)
-NWFPE_OBJS += entry26.o
-else
-NWFPE_OBJS += entry.o
-endif
+obj-y			:=
+obj-m			:=
+obj-n			:=
+
+list-multi		:= nwfpe.o
 
-ifeq ($(CONFIG_NWFPE),y)
-O_TARGET := math-emu.o
-O_OBJS = $(NWFPE_OBJS)
+obj-$(CONFIG_NWFPE)	+= nwfpe.o
+
+nwfpe-objs		:= fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o \
+			   fpmodule.o fpopcode.o softfloat.o \
+			   single_cpdo.o double_cpdo.o extended_cpdo.o
+
+ifeq ($(CONFIG_CPU_26),y)
+nwfpe-objs		+= entry26.o
 else
-  ifeq ($(CONFIG_NWFPE),m)
-    M_OBJS = nwfpe.o
-    MI_OBJS = $(NWFPE_OBJS)
-  endif
+nwfpe-objs		+= entry.o
 endif
 
 include $(TOPDIR)/Rules.make
 
-nwfpe.o: $(MI_OBJS) $(MIX_OBJS)
-	 $(LD) $(LD_RFLAG) -r -o $@ $(MI_OBJS) $(MIX_OBJS)
+nwfpe.o: $(nwfpe-objs)
+	$(LD) -r -o $@ $(nwfpe-objs)
diff -u --recursive --new-file v2.4.1/linux/arch/arm/vmlinux-armo.lds.in linux/arch/arm/vmlinux-armo.lds.in
--- v2.4.1/linux/arch/arm/vmlinux-armo.lds.in	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/vmlinux-armo.lds.in	Thu Feb  8 16:32:44 2001
@@ -47,6 +47,8 @@
 			*(.gnu.warning)
 			*(.text.lock)	/* out-of-line lock text */
 			*(.rodata)
+			*(.glue_7)
+			*(.glue_7t)
 			*(.kstrtab)
 		. = ALIGN(16);		/* Exception table		*/
 		__start___ex_table = .;
diff -u --recursive --new-file v2.4.1/linux/arch/arm/vmlinux-armv.lds.in linux/arch/arm/vmlinux-armv.lds.in
--- v2.4.1/linux/arch/arm/vmlinux-armv.lds.in	Mon Nov 27 17:07:59 2000
+++ linux/arch/arm/vmlinux-armv.lds.in	Thu Feb  8 16:32:44 2001
@@ -42,6 +42,8 @@
 			*(.gnu.warning)
 			*(.text.lock)	/* out-of-line lock text */
 			*(.rodata)
+			*(.glue_7)
+			*(.glue_7t)
 			*(.kstrtab)
 		. = ALIGN(16);
 		__start___ex_table = .;	/* Exception table		*/
diff -u --recursive --new-file v2.4.1/linux/arch/cris/Makefile linux/arch/cris/Makefile
--- v2.4.1/linux/arch/cris/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,96 @@
+# $Id: Makefile,v 1.11 2000/11/27 17:58:30 bjornw Exp $
+# cris/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# 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.
+
+LD_SCRIPT=$(TOPDIR)/arch/cris/cris.ld
+
+# A bug in ld prevents us from having a (constant-value) symbol in a
+# "ORIGIN =" or "LENGTH =" expression.  We fix that by generating a
+# linker file with the symbolic part of those expressions evaluated.
+#  Unfortunately, there is trouble making vmlinux depend on anything we
+# generate here, so we *always* regenerate the final linker script and
+# replace the LD macro to get what we want.  Thankfully(?) vmlinux is
+# always rebuilt (due to calling make recursively and not knowing if
+# anything was rebuilt).
+#  The shell script to build in some kind of dependency is really not
+# necessary for reasons of speed.  It's there because always
+# regenerating stuff (even for incremental linking of subsystems!) is
+# even more nauseating.
+LD = if [ ! -e $(LD_SCRIPT).tmp -o $(LD_SCRIPT) -nt $(LD_SCRIPT).tmp ]; then \
+          sed -e s/@ETRAX_DRAM_BASE@/0x$(ETRAX_DRAM_BASE)/ \
+              -e s/@ETRAX_DRAM_SIZE_M@/$(ETRAX_DRAM_SIZE)/ \
+              < $(LD_SCRIPT) > $(LD_SCRIPT).tmp; \
+     else true; \
+     fi && $(CROSS_COMPILE)ld -mcriself
+
+LINKFLAGS =-qmagic -mcriself -T $(LD_SCRIPT).tmp
+
+# objcopy is used to make binary images from the resulting linked file
+
+OBJCOPY := $(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+
+# normally, gcc on a linux box adds __linux__ but we do it "manually"
+# gcc-cris defaults to a.out, we need ELF, so -melf
+
+CFLAGS := $(CFLAGS) -march=v10 -fno-strict-aliasing -pipe -D__linux__
+
+ifdef CONFIG_KGDB
+CFLAGS := $(subst -fomit-frame-pointer,,$(CFLAGS)) -g
+CFLAGS += -fno-omit-frame-pointer
+endif
+
+HEAD := arch/cris/kernel/head.o
+
+SUBDIRS += arch/cris/kernel arch/cris/mm arch/cris/lib arch/cris/drivers
+CORE_FILES += arch/cris/kernel/kernel.o arch/cris/mm/mm.o arch/cris/drivers/drivers.o
+LIBGCC = $(shell $(CC) $(CFLAGS) -print-file-name=libgcc.a)
+LIBS := $(TOPDIR)/arch/cris/lib/lib.a $(LIBS) $(TOPDIR)/arch/cris/lib/lib.a $(LIBGCC)
+
+arch/cris/kernel: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/cris/kernel
+
+arch/cris/mm: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/cris/mm
+
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+vmlinux.bin: vmlinux
+	$(OBJCOPY) vmlinux vmlinux.bin
+
+timage: vmlinux.bin
+	cat vmlinux.bin cramfs.img >timage
+
+simimage: timage
+	cp vmlinux.bin simvmlinux.bin
+
+# the following will remake timage without compiling the kernel
+# it does of course require that all object files exist...
+
+cramfs:
+## cramfs      - Creates a cramfs image
+	mkcramfs -p 8192 root cramfs.img
+	cat vmlinux.bin cramfs.img >timage
+
+zImage: vmlinux
+## zImage     - Compressed kernel (gzip)
+	@$(MAKEBOOT) zImage
+
+compressed: zImage
+
+archclean:
+	@$(MAKEBOOT) clean
+	rm -f timage vmlinux.bin cramfs.img
+	rm -rf $(LD_SCRIPT).tmp
+
+archmrproper:
+
+archdep:
+	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.4.1/linux/arch/cris/README.mm linux/arch/cris/README.mm
--- v2.4.1/linux/arch/cris/README.mm	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/README.mm	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,241 @@
+Memory management for CRIS/MMU
+------------------------------
+HISTORY:
+
+$Log: README.mm,v $
+Revision 1.1  2000/07/10 16:25:21  bjornw
+Initial revision
+
+Revision 1.4  2000/01/17 02:31:59  bjornw
+Added discussion of paging and VM.
+
+Revision 1.3  1999/12/03 16:43:23  hp
+Blurb about that the 3.5G-limitation is not a MMU limitation
+
+Revision 1.2  1999/12/03 16:04:21  hp
+Picky comment about not mapping the first page
+
+Revision 1.1  1999/12/03 15:41:30  bjornw
+First version of CRIS/MMU memory layout specification.
+
+
+
+
+
+------------------------------
+
+See the ETRAX-NG HSDD for reference.
+
+We use the page-size of 8 kbytes, as opposed to the i386 page-size of 4 kbytes.
+
+The MMU can, apart from the normal mapping of pages, also do a top-level
+segmentation of the kernel memory space. We use this feature to avoid having
+to use page-tables to map the physical memory into the kernel's address
+space. We also use it to keep the user-mode virtual mapping in the same
+map during kernel-mode, so that the kernel easily can access the corresponding
+user-mode process' data.
+
+As a comparision, the Linux/i386 2.0 puts the kernel and physical RAM at
+address 0, overlapping with the user-mode virtual space, so that descriptor
+registers are needed for each memory access to specify which MMU space to
+map through. That changed in 2.2, putting the kernel/physical RAM at 
+0xc0000000, to co-exist with the user-mode mapping. We will do something
+quite similar, but with the additional complexity of having to map the
+internal chip I/O registers and the flash memory area (including SRAM
+and peripherial chip-selets).
+
+The kernel-mode segmentation map:
+
+        ------------------------                ------------------------
+FFFFFFFF|                      | => cached      |                      | 
+        |    kernel seg_f      |    flash       |                      |
+F0000000|______________________|                |                      |
+EFFFFFFF|                      | => uncached    |                      | 
+        |    kernel seg_e      |    flash       |                      |
+E0000000|______________________|                |        DRAM          |
+DFFFFFFF|                      |  paged to any  |      Un-cached       | 
+        |    kernel seg_d      |    =======>    |                      |
+D0000000|______________________|                |                      |
+CFFFFFFF|                      |                |                      | 
+        |    kernel seg_c      |==\             |                      |
+C0000000|______________________|   \            |______________________|
+BFFFFFFF|                      |  uncached      |                      |
+        |    kernel seg_b      |=====\=========>|       Registers      |
+B0000000|______________________|      \c        |______________________|
+AFFFFFFF|                      |       \a       |                      |
+        |                      |        \c      | FLASH/SRAM/Peripheral|
+        |                      |         \h     |______________________|
+        |                      |          \e    |                      |
+        |                      |           \d   |                      |
+        | kernel seg_0 - seg_a |            \==>|         DRAM         | 
+        |                      |                |        Cached        |
+        |                      |  paged to any  |                      |
+        |                      |    =======>    |______________________| 
+        |                      |                |                      |
+        |                      |                |        Illegal       |
+        |                      |                |______________________|
+        |                      |                |                      |      
+        |                      |                | FLASH/SRAM/Peripheral|
+00000000|______________________|                |______________________|
+
+In user-mode it looks the same except that only the space 0-AFFFFFFF is
+available. Therefore, in this model, the virtual address space per process
+is limited to 0xb0000000 bytes (minus 8192 bytes, since the first page,
+0..8191, is never mapped, in order to trap NULL references).
+
+It also means that the total physical RAM that can be mapped is 256 MB
+(kseg_c above). More RAM can be mapped by choosing a different segmentation
+and shrinking the user-mode memory space.
+
+The MMU can map all 4 GB in user mode, but doing that would mean that a
+few extra instructions would be needed for each access to user mode
+memory.
+
+The kernel needs access to both cached and uncached flash. Uncached is
+necessary because of the special write/erase sequences. Also, the 
+peripherial chip-selects are decoded from that region.
+
+The kernel also needs its own virtual memory space. That is kseg_d. It
+is used by the vmalloc() kernel function to allocate virtual contiguous
+chunks of memory not possible using the normal kmalloc physical RAM 
+allocator.
+
+The setting of the actual MMU control registers to use this layout would
+be something like this:
+
+R_MMU_KSEG = ( ( seg_f, seg     ) |   // Flash cached
+               ( seg_e, seg     ) |   // Flash uncached
+               ( seg_d, page    ) |   // kernel vmalloc area    
+               ( seg_c, seg     ) |   // kernel linear segment
+               ( seg_b, seg     ) |   // kernel linear segment
+               ( seg_a, page    ) |
+               ( seg_9, page    ) |
+               ( seg_8, page    ) |
+               ( seg_7, page    ) |
+               ( seg_6, page    ) |
+               ( seg_5, page    ) |
+               ( seg_4, page    ) |
+               ( seg_3, page    ) |
+               ( seg_2, page    ) |
+               ( seg_1, page    ) |
+               ( seg_0, page    ) );
+
+R_MMU_KBASE_HI = ( ( base_f, 0x0 ) |   // flash/sram/periph cached
+                   ( base_e, 0x8 ) |   // flash/sram/periph uncached
+                   ( base_d, 0x0 ) |   // don't care
+                   ( base_c, 0x4 ) |   // physical RAM cached area
+                   ( base_b, 0xb ) |   // uncached on-chip registers
+                   ( base_a, 0x0 ) |   // don't care
+                   ( base_9, 0x0 ) |   // don't care
+                   ( base_8, 0x0 ) );  // don't care
+
+R_MMU_KBASE_LO = ( ( base_7, 0x0 ) |   // don't care
+                   ( base_6, 0x0 ) |   // don't care
+                   ( base_5, 0x0 ) |   // don't care
+                   ( base_4, 0x0 ) |   // don't care
+                   ( base_3, 0x0 ) |   // don't care
+                   ( base_2, 0x0 ) |   // don't care
+                   ( base_1, 0x0 ) |   // don't care
+                   ( base_0, 0x0 ) );  // don't care
+
+NOTE: while setting up the MMU, we run in a non-mapped mode in the DRAM (0x40
+segment) and need to setup the seg_4 to a unity mapping, so that we don't get
+a fault before we have had time to jump into the real kernel segment (0xc0). This
+is done in head.S temporarily, but fixed by the kernel later in paging_init.
+
+
+Paging - PTE's, PMD's and PGD's
+-------------------------------
+
+[ References: asm/pgtable.h, asm/page.h, asm/mmu.h ]
+
+The paging mechanism uses virtual addresses to split a process memory-space into
+pages, a page being the smallest unit that can be freely remapped in memory. On
+Linux/CRIS, a page is 8192 bytes (for technical reasons not equal to 4096 as in 
+most other 32-bit architectures). It would be inefficient to let a virtual memory
+mapping be controlled by a long table of page mappings, so it is broken down into
+a 2-level structure with a Page Directory containing pointers to Page Tables which
+each have maps of up to 2048 pages (8192 / sizeof(void *)). Linux can actually
+handle 3-level structures as well, with a Page Middle Directory in between, but
+in many cases, this is folded into a two-level structure by excluding the Middle
+Directory.
+
+We'll take a look at how an address is translated while we discuss how it's handled
+in the Linux kernel.
+
+The example address is 0xd004000c; in binary this is:
+
+31       23       15       7      0
+11010000 00000100 00000000 00001100
+
+|______| |__________||____________|
+  PGD        PTE       page offset
+
+Given the top-level Page Directory, the offset in that directory is calculated
+using the upper 8 bits:
+
+extern inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+	return mm->pgd + (address >> PGDIR_SHIFT);
+}
+
+PGDIR_SHIFT is the log2 of the amount of memory an entry in the PGD can map; in our
+case it is 24, corresponding to 16 MB. This means that each entry in the PGD 
+corresponds to 16 MB of virtual memory.
+
+The pgd_t from our example will therefore be the 208'th (0xd0) entry in mm->pgd.
+
+Since the Middle Directory does not exist, it is a unity mapping:
+
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+	return (pmd_t *) dir;
+}
+
+The Page Table provides the final lookup by using bits 13 to 23 as index:
+
+extern inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+	return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) &
+					   (PTRS_PER_PTE - 1));
+}
+
+PAGE_SHIFT is the log2 of the size of a page; 13 in our case. PTRS_PER_PTE is
+the number of pointers that fit in a Page Table and is used to mask off the 
+PGD-part of the address.
+
+The so-far unused bits 0 to 12 are used to index inside a page linearily.
+
+The VM system
+-------------
+
+The kernels own page-directory is the swapper_pg_dir, cleared in paging_init, 
+and contains the kernels virtual mappings (the kernel itself is not paged - it
+is mapped linearily using kseg_c as described above). Architectures without
+kernel segments like the i386, need to setup swapper_pg_dir directly in head.S
+to map the kernel itself. swapper_pg_dir is pointed to by init_mm.pgd as the
+init-task's PGD.
+
+To see what support functions are used to setup a page-table, let's look at the
+kernel's internal paged memory system, vmalloc/vfree.
+
+void * vmalloc(unsigned long size)
+
+The vmalloc-system keeps a paged segment in kernel-space at 0xd0000000. What
+happens first is that a virtual address chunk is allocated to the request using
+get_vm_area(size). After that, physical RAM pages are allocated and put into
+the kernel's page-table using alloc_area_pages(addr, size). 
+
+static int alloc_area_pages(unsigned long address, unsigned long size)
+
+First the PGD entry is found using init_mm.pgd. This is passed to
+alloc_area_pmd (remember the 3->2 folding). It uses pte_alloc_kernel to
+check if the PGD entry points anywhere - if not, a page table page is
+allocated and the PGD entry updated. Then the alloc_area_pte function is
+used just like alloc_area_pmd to check which page table entry is desired, 
+and a physical page is allocated and the table entry updated. All of this
+is repeated at the top-level until the entire address range specified has 
+been mapped.
+
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/cris/boot/Makefile linux/arch/cris/boot/Makefile
--- v2.4.1/linux/arch/cris/boot/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,14 @@
+#
+# arch/cris/boot/Makefile
+#
+
+zImage: compressed/vmlinuz
+
+compressed/vmlinuz: $(TOPDIR)/vmlinux
+	@$(MAKE) -C compressed vmlinuz
+
+dep:
+
+clean:
+	rm -f zImage tools/build compressed/vmlinux.out
+	@$(MAKE) -C compressed clean
diff -u --recursive --new-file v2.4.1/linux/arch/cris/boot/compressed/Makefile linux/arch/cris/boot/compressed/Makefile
--- v2.4.1/linux/arch/cris/boot/compressed/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/compressed/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,37 @@
+#
+# linux/arch/etrax100/boot/compressed/Makefile
+#
+# create a compressed vmlinux image from the original vmlinux files and romfs
+#
+
+CC = gcc-cris -melf -I $(TOPDIR)/include
+CFLAGS = -O2
+LD = ld-cris
+OBJCOPY = objcopy-cris
+
+OBJECTS = head.o misc.o
+
+# files to compress
+SYSTEM = $(TOPDIR)/vmlinux.bin
+
+all: vmlinuz
+
+vmlinuz: piggy.img $(OBJECTS)
+	$(LD) -mcriself -T decompress.ld -o decompress.o $(OBJECTS)
+	$(OBJCOPY) -O binary --remove-section=.bss decompress.o decompress.bin
+# save it for mkprod in the topdir.
+	cp decompress.bin $(TOPDIR)
+	cat decompress.bin piggy.img $(TOPDIR)/cramfs.img > vmlinuz
+	rm -f piggy.img
+
+head.o: head.S
+	$(CC) -D__ASSEMBLY__ -traditional -c head.S -o head.o
+
+# gzip the kernel image
+
+piggy.img: $(SYSTEM)
+	cat $(SYSTEM) | gzip -f -9 > piggy.img
+
+clean:
+	rm -f piggy.img vmlinuz vmlinuz.o
+
diff -u --recursive --new-file v2.4.1/linux/arch/cris/boot/compressed/README linux/arch/cris/boot/compressed/README
--- v2.4.1/linux/arch/cris/boot/compressed/README	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/compressed/README	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,25 @@
+Creation of the self-extracting compressed kernel image (vmlinuz)
+-----------------------------------------------------------------
+$Id: README,v 1.1 2000/11/22 17:20:46 bjornw Exp $
+
+This can be slightly confusing because it's a process with many steps.
+
+The kernel object built by the arch/etrax100/Makefile, vmlinux, is split
+by that makefile into text and data binary files, vmlinux.text and 
+vmlinux.data.
+
+Those files together with a ROM filesystem can be catted together and
+burned into a flash or executed directly at the DRAM origin.
+
+They can also be catted together and compressed with gzip, which is what
+happens in this makefile. Together they make up piggy.img. 
+
+The decompressor is built into the file decompress.o. It is turned into
+the binary file decompress.bin, which is catted together with piggy.img
+into the file vmlinuz. It can be executed in an arbitrary place in flash.
+
+Be careful - it assumes some things about free locations in DRAM. It
+assumes the DRAM starts at 0x40000000 and that it is at least 8 MB,
+so it puts its code at 0x40700000, and initial stack at 0x40800000.
+
+-Bjorn
diff -u --recursive --new-file v2.4.1/linux/arch/cris/boot/compressed/decompress.ld linux/arch/cris/boot/compressed/decompress.ld
--- v2.4.1/linux/arch/cris/boot/compressed/decompress.ld	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/compressed/decompress.ld	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,26 @@
+MEMORY 
+	{
+	dram : ORIGIN = 0x40700000,
+	       LENGTH = 0x00100000
+	}
+
+SECTIONS
+{
+	.text :
+	{
+		_stext = . ;
+		*(.text)
+		*(.rodata)
+		_etext = . ;
+	} > dram
+	.data :
+	{
+		*(.data)
+		_edata = . ;
+	} > dram
+	.bss :
+	{
+		*(.bss)
+		_end = ALIGN( 0x10 ) ;
+	} > dram
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/boot/compressed/head.S linux/arch/cris/boot/compressed/head.S
--- v2.4.1/linux/arch/cris/boot/compressed/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/compressed/head.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,100 @@
+/*
+ *  arch/etrax100/boot/compressed/head.S
+ *
+ *  Copyright (C) 1999 Axis Communications AB
+ *
+ *  Code that sets up the DRAM registers, calls the
+ *  decompressor to unpack the piggybacked kernel, and jumps.
+ *
+ */
+
+#include <linux/config.h>
+#define ASSEMBLER_MACROS_ONLY
+#include <asm/sv_addr_ag.h>
+
+	;; Exported symbols
+	
+	.globl	_input_data
+
+	
+	.text
+
+	nop
+	di
+
+#ifndef CONFIG_SVINTO_SIM	
+
+	;; We need to setup the bus registers before we start using the DRAM
+
+	move.d   DEF_R_WAITSTATES, r0
+	move.d   r0, [R_WAITSTATES]
+
+	move.d   DEF_R_BUS_CONFIG, r0
+	move.d   r0, [R_BUS_CONFIG]
+  
+	move.d   DEF_R_DRAM_CONFIG, r0
+	move.d   r0, [R_DRAM_CONFIG]
+
+	move.d   DEF_R_DRAM_TIMING, r0
+	move.d   r0, [R_DRAM_TIMING]
+
+#endif
+
+	;; Setup the stack to a suitably high address.
+	;; We assume 8 MB is the minimum DRAM in an eLinux
+	;; product and put the sp at the top for now.
+
+	move.d	0x40800000, sp
+
+	;; Figure out where the compressed piggyback image is
+	;; in the flash (since we wont try to copy it to DRAM
+	;; before unpacking). It is at _edata, but in flash.
+	;; Use (_edata - basse) as offset to the current PC.
+	
+basse:	move.d	pc, r5
+	and.d	0x7fffffff, r5	; strip any non-cache bit
+	subq	2, r5		; compensate for the move.d pc instr
+	move.d	r5, r0		; save for later - flash address of 'basse'
+	add.d	_edata, r5
+	sub.d	basse, r5	; r5 = flash address of '_edata'
+	
+	;; Copy text+data to DRAM
+	
+	move.d	basse, r1	; destination
+	move.d	_edata, r2	; end destination
+1:	move.w	[r0+], r3
+	move.w	r3, [r1+]
+	cmp.d	r2, r1
+	bcs	1b
+	nop
+
+	move.d	r5, [_input_data] ; for the decompressor
+
+	;; Clear the decompressors BSS (between _edata and _end)
+	
+	moveq	0, r0
+	move.d	_edata, r1
+	move.d	_end, r2
+1:	move.w	r0, [r1+]
+	cmp.d	r2, r1
+	bcs	1b
+	nop
+	
+	;; Do the decompression and save compressed size in _inptr
+	
+	jsr	_decompress_kernel
+
+	;; Put start address of cramfs in r9 so the kernel can use it
+	;; when mounting from flash
+
+	move.d	[_input_data], r9	; flash address of compressed kernel
+	add.d	[_inptr], r9		; size of compressed kernel
+
+	;; Enter the decompressed kernel
+		
+	jump	0x40004000	; kernel is linked to this address
+	
+	.data
+
+_input_data:
+	.dword	0		; used by the decompressor
diff -u --recursive --new-file v2.4.1/linux/arch/cris/boot/compressed/misc.c linux/arch/cris/boot/compressed/misc.c
--- v2.4.1/linux/arch/cris/boot/compressed/misc.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/boot/compressed/misc.c	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,260 @@
+/*
+ * misc.c
+ *
+ * $Id: misc.c,v 1.3 2001/01/17 15:54:18 jonashg Exp $
+ * 
+ * This is a collection of several routines from gzip-1.0.3 
+ * adapted for Linux.
+ *
+ * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994
+ * puts by Nick Holloway 1993, better puts by Martin Mares 1995
+ * adoptation for Linux/CRIS Axis Communications AB, 1999
+ * 
+ */
+
+/* where the piggybacked kernel image expects itself to live.
+ * it is the same address we use when we network load an uncompressed
+ * image into DRAM, and it is the address the kernel is linked to live
+ * at by etrax100.ld.
+ */
+
+#define KERNEL_LOAD_ADR 0x40004000
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <asm/svinto.h>
+
+/*
+ * gzip declarations
+ */
+
+#define OF(args)  args
+#define STATIC static
+
+void* memset(void* s, int c, size_t n);
+void* memcpy(void* __dest, __const void* __src,
+	     size_t __n);
+
+#define memzero(s, n)     memset ((s), 0, (n))
+
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+#define WSIZE 0x8000		/* Window size must be at least 32k, */
+				/* and a power of two */
+
+static uch *inbuf;	     /* input buffer */
+static uch window[WSIZE];    /* Sliding window buffer */
+
+unsigned inptr = 0;	/* index of next byte to be processed in inbuf
+			 * After decompression it will contain the
+			 * compressed size, and head.S will read it.
+			 */
+
+static unsigned outcnt = 0;  /* bytes in output buffer */
+
+/* gzip flag byte */
+#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
+#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
+#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
+#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
+#define COMMENT      0x10 /* bit 4 set: file comment present */
+#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */
+#define RESERVED     0xC0 /* bit 6,7:   reserved */
+
+#define get_byte() inbuf[inptr++]	
+	
+/* Diagnostic functions */
+#ifdef DEBUG
+#  define Assert(cond,msg) {if(!(cond)) error(msg);}
+#  define Trace(x) fprintf x
+#  define Tracev(x) {if (verbose) fprintf x ;}
+#  define Tracevv(x) {if (verbose>1) fprintf x ;}
+#  define Tracec(c,x) {if (verbose && (c)) fprintf x ;}
+#  define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+static int  fill_inbuf(void);
+static void flush_window(void);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+
+extern char *input_data;  /* lives in head.S */
+
+static long bytes_out = 0;
+static uch *output_data;
+static unsigned long output_ptr = 0;
+ 
+static void *malloc(int size);
+static void free(void *where);
+static void error(char *m);
+static void gzip_mark(void **);
+static void gzip_release(void **);
+ 
+static void puts(const char *);
+
+/* the "heap" is put directly after the BSS ends, at end */
+  
+extern int end;
+static long free_mem_ptr = (long)&end;
+ 
+#include "../../../../lib/inflate.c"
+
+static void *malloc(int size)
+{
+	void *p;
+
+	if (size <0) error("Malloc error\n");
+
+	free_mem_ptr = (free_mem_ptr + 3) & ~3;	/* Align */
+
+	p = (void *)free_mem_ptr;
+	free_mem_ptr += size;
+
+	return p;
+}
+
+static void free(void *where)
+{	/* Don't care */
+}
+
+static void gzip_mark(void **ptr)
+{
+	*ptr = (void *) free_mem_ptr;
+}
+
+static void gzip_release(void **ptr)
+{
+	free_mem_ptr = (long) *ptr;
+}
+
+/* decompressor info and error messages to serial console */
+
+static void
+puts(const char *s)
+{
+#ifndef CONFIG_DEBUG_PORT_NULL
+	while(*s) {
+#ifdef CONFIG_DEBUG_PORT0
+		while(!(*R_SERIAL0_STATUS & (1 << 5))) ;
+		*R_SERIAL0_TR_DATA = *s++;
+#endif
+#ifdef CONFIG_DEBUG_PORT1
+		while(!(*R_SERIAL1_STATUS & (1 << 5))) ;
+		*R_SERIAL1_TR_DATA = *s++;
+#endif
+#ifdef CONFIG_DEBUG_PORT2
+		while(!(*R_SERIAL2_STATUS & (1 << 5))) ;
+		*R_SERIAL2_TR_DATA = *s++;
+#endif
+#ifdef CONFIG_DEBUG_PORT3
+		while(!(*R_SERIAL3_STATUS & (1 << 5))) ;
+		*R_SERIAL3_TR_DATA = *s++;
+#endif
+	}
+#endif
+}
+
+void*
+memset(void* s, int c, size_t n)
+{
+	int i;
+	char *ss = (char*)s;
+
+	for (i=0;i<n;i++) ss[i] = c;
+}
+
+void*
+memcpy(void* __dest, __const void* __src,
+			    size_t __n)
+{
+	int i;
+	char *d = (char *)__dest, *s = (char *)__src;
+
+	for (i=0;i<__n;i++) d[i] = s[i];
+}
+
+/* ===========================================================================
+ * Write the output window window[0..outcnt-1] and update crc and bytes_out.
+ * (Used for the decompressed data only.)
+ */
+
+static void
+flush_window()
+{
+    ulg c = crc;         /* temporary variable */
+    unsigned n;
+    uch *in, *out, ch;
+    
+    in = window;
+    out = &output_data[output_ptr]; 
+    for (n = 0; n < outcnt; n++) {
+	    ch = *out++ = *in++;
+	    c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8);
+    }
+    crc = c;
+    bytes_out += (ulg)outcnt;
+    output_ptr += (ulg)outcnt;
+    outcnt = 0;
+}
+
+static void
+error(char *x)
+{
+	puts("\n\n");
+	puts(x);
+	puts("\n\n -- System halted\n");
+
+	while(1);	/* Halt */
+}
+
+void
+setup_normal_output_buffer()
+{
+	output_data = (char *)KERNEL_LOAD_ADR;
+}
+
+void
+decompress_kernel()
+{
+	/* input_data is set in head.S */
+	inbuf = input_data;
+
+#ifdef CONFIG_DEBUG_PORT0
+	*R_SERIAL0_XOFF = 0;
+	*R_SERIAL0_BAUD = 0x99;
+	*R_SERIAL0_TR_CTRL = 0x40;
+#endif
+#ifdef CONFIG_DEBUG_PORT1
+	*R_SERIAL1_XOFF = 0;
+	*R_SERIAL1_BAUD = 0x99;
+	*R_SERIAL1_TR_CTRL = 0x40;
+#endif
+#ifdef CONFIG_DEBUG_PORT2
+	*R_SERIAL2_XOFF = 0;
+	*R_SERIAL2_BAUD = 0x99;
+	*R_SERIAL2_TR_CTRL = 0x40;
+#endif
+#ifdef CONFIG_DEBUG_PORT3
+	*R_SERIAL3_XOFF = 0;
+	*R_SERIAL3_BAUD = 0x99;
+	*R_SERIAL3_TR_CTRL = 0x40;
+#endif
+       
+	setup_normal_output_buffer();
+
+	makecrc();
+	puts("Uncompressing Linux...\n");
+	gunzip();
+	puts("Done. Now booting the kernel.\n");
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/config.in linux/arch/cris/config.in
--- v2.4.1/linux/arch/cris/config.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/config.in	Fri Feb 16 15:53:08 2001
@@ -0,0 +1,223 @@
+#
+# For a description of the syntax of this configuration file,
+# see the Configure script.
+#
+mainmenu_name "Linux/CRIS Kernel Configuration"
+
+define_bool CONFIG_UID16 y
+
+mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
+
+bool 'Networking support' CONFIG_NET
+bool 'System V IPC' CONFIG_SYSVIPC
+
+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+  tristate 'Kernel support for JAVA binaries' CONFIG_BINFMT_JAVA
+fi
+
+bool 'Use kernel gdb debugger' CONFIG_KGDB
+
+bool 'Enable Etrax100 watchdog' CONFIG_ETRAX_WATCHDOG
+
+bool 'Use serial console (on the debug port)' CONFIG_USE_SERIAL_CONSOLE
+
+bool 'Use in-kernel ifconfig/route setup' CONFIG_KERNEL_IFCONFIG
+
+endmenu
+
+mainmenu_option next_comment
+comment 'Hardware setup'
+
+choice 'Processor type' \
+	"Etrax-100-LX	CONFIG_ETRAX100LX	\
+	 Etrax-100-LX-for-xsim-simulator   CONFIG_SVINTO_SIM" Etrax-100-LX
+
+# For both LX version 1 and the current simulator we enable the low VM mapping
+# Later when LX version 2 and above exist, this should be done with an if
+
+define_bool CONFIG_CRIS_LOW_MAP y
+
+hex 'DRAM base (hex)' ETRAX_DRAM_BASE 40000000
+int 'DRAM size (dec, in MB)' ETRAX_DRAM_SIZE 8
+
+int 'Max possible flash size (dec, in MB)' CONFIG_ETRAX_FLASH_LENGTH 2
+int 'Buswidth of flash in bytes' CONFIG_ETRAX_FLASH_BUSWIDTH 2
+
+choice 'Product LED port' \
+	"Port-PA-LEDs	CONFIG_ETRAX_PA_LEDS	\
+	 Port-PB-LEDs	CONFIG_ETRAX_PB_LEDS	\
+	 Mem-0x90000000-LEDs	CONFIG_ETRAX_90000000_LEDS  \
+	 None	CONFIG_ETRAX_NO_LEDS" Port-PA-LEDs
+
+if [ "$CONFIG_ETRAX_NO_LEDS" != "y" ]; then
+  int '  First green LED bit' CONFIG_ETRAX_LED1G 2
+  int '  First red LED bit' CONFIG_ETRAX_LED1R 3
+  int '  Second green LED bit' CONFIG_ETRAX_LED2G 4
+  int '  Second red LED bit' CONFIG_ETRAX_LED2R 5
+  int '  Third green LED bit' CONFIG_ETRAX_LED3R 2
+  int '  Third red LED bit' CONFIG_ETRAX_LED3G 2
+fi
+
+choice 'Product debug-port' \
+	"Serial-0	CONFIG_DEBUG_PORT0	\
+	 Serial-1	CONFIG_DEBUG_PORT1	\
+	 Serial-2	CONFIG_DEBUG_PORT2	\
+	 Serial-3	CONFIG_DEBUG_PORT3" Serial-0
+
+hex 'R_WAITSTATES' DEF_R_WAITSTATES 95a6
+hex 'R_BUS_CONFIG' DEF_R_BUS_CONFIG 104
+hex 'R_DRAM_CONFIG' DEF_R_DRAM_CONFIG 1a200040
+hex 'R_DRAM_TIMING' DEF_R_DRAM_TIMING 5611
+hex 'R_PORT_PA_DIR' DEF_R_PORT_PA_DIR 1c
+hex 'R_PORT_PA_DATA' DEF_R_PORT_PA_DATA 00
+hex 'R_PORT_PB_CONFIG' DEF_R_PORT_PB_CONFIG 00
+hex 'R_PORT_PB_DIR' DEF_R_PORT_PB_DIR 00
+hex 'R_PORT_PB_DATA' DEF_R_PORT_PB_DATA ff
+
+endmenu
+
+# only configure IP numbers if the kernel ifconfig/route setup is enabled
+
+if [ "$CONFIG_KERNEL_IFCONFIG" = "y" ]; then
+  mainmenu_option next_comment	
+  comment 'IP address selection'
+
+  comment 'All addresses are in hexadecimal form without 0x prefix'
+
+  hex 'IP address' ELTEST_IPADR ab1005af
+  hex 'Network' ELTEST_NETWORK ab100000
+  hex 'Netmask' ELTEST_NETMASK ffff0000
+  hex 'Broadcast' ELTEST_BROADCAST ab10ffff
+  hex 'Gateway' ELTEST_GATEWAY ab100101
+  hwaddr 'Ethernet address' ELTEST_ETHADR 00408ccd0000
+
+  endmenu
+fi
+
+# bring in Etrax built-in drivers
+
+source arch/cris/drivers/Config.in
+
+# standard linux drivers
+
+source drivers/mtd/Config.in
+
+source drivers/parport/Config.in
+
+source drivers/pnp/Config.in
+
+source drivers/block/Config.in
+
+source drivers/md/Config.in
+
+if [ "$CONFIG_NET" = "y" ]; then
+  source net/Config.in
+fi
+
+source drivers/telephony/Config.in
+
+mainmenu_option next_comment
+comment 'ATA/IDE/MFM/RLL support'
+
+tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+
+if [ "$CONFIG_IDE" != "n" ]; then
+  source drivers/ide/Config.in
+else
+  define_bool CONFIG_BLK_DEV_IDE_MODES n
+  define_bool CONFIG_BLK_DEV_HD n
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'SCSI support'
+
+tristate 'SCSI support' CONFIG_SCSI
+
+if [ "$CONFIG_SCSI" != "n" ]; then
+  source drivers/scsi/Config.in
+fi
+endmenu
+
+source drivers/ieee1394/Config.in
+
+source drivers/i2o/Config.in
+
+if [ "$CONFIG_NET" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Network device support'
+
+  bool 'Network device support' CONFIG_NETDEVICES
+  if [ "$CONFIG_NETDEVICES" = "y" ]; then
+    source drivers/net/Config.in
+      if [ "$CONFIG_ATM" = "y" ]; then
+         source drivers/atm/Config.in
+      fi
+  fi
+  endmenu
+fi
+
+source net/ax25/Config.in
+
+source net/irda/Config.in
+
+mainmenu_option next_comment
+comment 'ISDN subsystem'
+if [ "$CONFIG_NET" != "n" ]; then
+   tristate 'ISDN support' CONFIG_ISDN
+   if [ "$CONFIG_ISDN" != "n" ]; then
+      source drivers/isdn/Config.in
+   fi
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+
+bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
+if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+   source drivers/cdrom/Config.in
+fi
+endmenu
+
+#
+# input before char - char/joystick depends on it. As does USB.
+#
+source drivers/input/Config.in
+source drivers/char/Config.in
+
+#source drivers/misc/Config.in
+
+source drivers/media/Config.in
+
+source fs/Config.in
+
+source drivers/char/Config.in
+
+mainmenu_option next_comment
+comment 'Sound'
+
+tristate 'Sound card support' CONFIG_SOUND
+if [ "$CONFIG_SOUND" != "n" ]; then
+  source drivers/sound/Config.in
+fi
+endmenu
+
+source drivers/usb/Config.in
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+bool 'Kernel profiling support' CONFIG_PROFILE
+if [ "$CONFIG_PROFILE" = "y" ]; then
+  int ' Profile shift count' CONFIG_PROFILE_SHIFT 2
+fi
+endmenu
diff -u --recursive --new-file v2.4.1/linux/arch/cris/cris.ld linux/arch/cris/cris.ld
--- v2.4.1/linux/arch/cris/cris.ld	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/cris.ld	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,81 @@
+/* ld script to make the Linux/CRIS kernel
+ * Authors: Bjorn Wesen (bjornw@axis.com)
+ *
+ * For now, on Etrax-100 LX, the DRAM starts virtually at 0x6. Normally
+ * it should be at 0xc.
+ */	
+
+SECTIONS
+{
+	. = 0x60000000;               /* DRAM starts virtually at 0x60000000 */
+	_dram_start = .;
+	_ibr_start = .;
+	. = . + 0x4000; /* see head.S and pages reserved at the start */
+
+	_text = .;                    /* Text and read-only data */
+	_text_start = .;              /* lots of aliases */
+	_stext = .;
+	__stext = .;
+	.text : {
+		*(.text)
+		*(.fixup)
+		*(.text.__*)
+		*(.rodata)
+	}
+
+	. = ALIGN(4);                /* Exception table */
+  	__start___ex_table = .;
+  	__ex_table : { *(__ex_table) }
+  	__stop___ex_table = .;
+
+	_etext = . ;                  /* End of text section */ 
+	__etext = .;
+
+	. = ALIGN (4);
+	___data_rom_start = . ;
+	___data_start = . ;
+	__Sdata = . ;
+	.data : {                     /* Data */
+		*(.data)
+	}
+	__edata = . ;                 /* End of data section */
+	_edata = . ;
+
+	. = ALIGN(8192);              /* init_task and stack, must be aligned */
+  	.data.init_task : { *(.data.init_task) }
+
+  	. = ALIGN(8192);              /* 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 = .;
+	__vmlinux_end = .;            /* last address of the physical file */
+  	. = ALIGN(8192);
+  	___init_end = .;
+
+	__data_end = . ;              /* Move to _edata ? */
+	__bss_start = .;              /* BSS */
+	.bss : {
+		*(COMMON)
+		*(.bss)
+	}
+
+	. =  ALIGN (0x20);
+	_end = .;
+	__end = .;
+
+	/* Sections to be discarded */
+  	/DISCARD/ : {
+        	*(.text.exit)
+        	*(.data.exit)
+		*(.exitcall.exit)
+        }
+
+	_dram_end = 0x60000000 + @ETRAX_DRAM_SIZE_M@*1024*1024;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/defconfig linux/arch/cris/defconfig
--- v2.4.1/linux/arch/cris/defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/defconfig	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,319 @@
+#
+# Automatically generated make config: don't edit
+#
+CONFIG_UID16=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# General setup
+#
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_JAVA is not set
+# CONFIG_KGDB is not set
+# CONFIG_ETRAX_WATCHDOG is not set
+CONFIG_USE_SERIAL_CONSOLE=y
+# CONFIG_KERNEL_IFCONFIG is not set
+
+#
+# Hardware setup
+#
+CONFIG_ETRAX100LX=y
+# CONFIG_SVINTO_SIM is not set
+CONFIG_CRIS_LOW_MAP=y
+ETRAX_DRAM_BASE=40000000
+ETRAX_DRAM_SIZE=8
+CONFIG_ETRAX_PA_LEDS=y
+# CONFIG_ETRAX_PB_LEDS is not set
+# CONFIG_ETRAX_90000000_LEDS is not set
+# CONFIG_ETRAX_NO_LEDS is not set
+CONFIG_ETRAX_LED1G=2
+CONFIG_ETRAX_LED1R=2
+CONFIG_ETRAX_LED2G=2
+CONFIG_ETRAX_LED2R=2
+CONFIG_DEBUG_PORT0=y
+# CONFIG_DEBUG_PORT1 is not set
+# CONFIG_DEBUG_PORT2 is not set
+# CONFIG_DEBUG_PORT3 is not set
+DEF_R_WAITSTATES=95a6
+DEF_R_BUS_CONFIG=104
+DEF_R_DRAM_CONFIG=1a200040
+DEF_R_DRAM_TIMING=5611
+DEF_R_PORT_PA_DIR=1d
+DEF_R_PORT_PA_DATA=f0
+DEF_R_PORT_PB_CONFIG=00
+DEF_R_PORT_PB_DIR=1e
+DEF_R_PORT_PB_DATA=f3
+
+#
+# Drivers for Etrax built-in interfaces
+#
+CONFIG_ETRAX_ETHERNET=y
+CONFIG_NET_ETHERNET=y
+CONFIG_ETRAX_SERIAL=y
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_XD is not set
+# CONFIG_PARIDE is not set
+# CONFIG_BLK_CPQ_DA is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_LOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_BLK_DEV_INITRD is not set
+
+#
+# Networking options
+#
+# CONFIG_PACKET is not set
+# CONFIG_NETLINK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+
+#
+#  
+#
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# SCSI support
+#
+# CONFIG_SCSI is not set
+
+#
+# Network device support
+#
+CONFIG_NETDEVICES=y
+
+#
+# ARCnet devices
+#
+# CONFIG_ARCNET is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_NET_SB1000 is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_LANCE is not set
+# CONFIG_NET_VENDOR_SMC is not set
+# CONFIG_NET_VENDOR_RACAL is not set
+# CONFIG_AT1700 is not set
+# CONFIG_DEPCA is not set
+# CONFIG_NET_ISA is not set
+# CONFIG_NET_PCI is not set
+# CONFIG_NET_POCKET is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+# CONFIG_ACENIC is not set
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+# CONFIG_SK98LIN is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_PLIP is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Token Ring devices
+#
+# CONFIG_TR is not set
+# CONFIG_NET_FC is not set
+# CONFIG_RCPCI is not set
+# CONFIG_SHAPER is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# CD-ROM drivers (not for SCSI or IDE/ATAPI drives)
+#
+# CONFIG_CD_NO_IDESCSI is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_CRAMFS=y
+CONFIG_RAMFS=y
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_EXT2_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+# CONFIG_NFS_FS is not set
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+# CONFIG_SUNRPC is not set
+# CONFIG_LOCKD is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_NLS is not set
+
+#
+# Character devices
+#
+# CONFIG_VT is not set
+# CONFIG_SERIAL is not set
+# CONFIG_SERIAL_EXTENDED is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_PRINTER is not set
+# CONFIG_PPDEV is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+
+#
+# Mice
+#
+# CONFIG_BUSMOUSE is not set
+# CONFIG_MOUSE is not set
+
+#
+# Joysticks
+#
+# CONFIG_JOYSTICK is not set
+
+#
+# Input core support is needed for joysticks
+#
+# CONFIG_QIC02_TAPE is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_INTEL_RNG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
+
+#
+# Sound
+#
+# CONFIG_SOUND is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PROFILE is not set
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/Config.in linux/arch/cris/drivers/Config.in
--- v2.4.1/linux/arch/cris/drivers/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/Config.in	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,49 @@
+mainmenu_option next_comment
+comment 'Drivers for Etrax built-in interfaces'
+
+bool 'Ethernet support' CONFIG_ETRAX_ETHERNET y
+if [ "$CONFIG_ETRAX_ETHERNET" = "y" ]; then
+# this is just so that the user does not have to go into the
+# normal ethernet driver section just to enable ethernetworking
+  define_bool CONFIG_NET_ETHERNET y
+fi
+
+bool 'Serial-port support' CONFIG_ETRAX_SERIAL y
+
+bool 'ATA/IDE support' CONFIG_ETRAX_IDE n
+
+if [ "$CONFIG_ETRAX_IDE" = "y" ]; then
+# here we should add the CONFIG_'s necessary to enable the basic
+# general ide drivers so the common case does not need to go
+# into that config submenu. enable disk and CD support. others
+# need to go fiddle in the submenu..
+	define_bool CONFIG_IDE y
+
+	define_bool CONFIG_BLK_DEV_IDE y
+	define_bool CONFIG_BLK_DEV_IDEDISK y
+	define_bool CONFIG_BLK_DEV_IDECD y
+
+	define_bool CONFIG_BLK_DEV_IDEDMA y
+	define_bool CONFIG_DMA_NONPCI y
+ 
+	choice 'IDE reset pin' \
+  	"Port_PB_Bit_7  CONFIG_ETRAX_IDE_PB7_RESET\
+   	 Port_G_Bit_27  CONFIG_ETRAX_IDE_G27_RESET\
+   	 Port_CSE1_Bit_16  CONFIG_ETRAX_IDE_CSE1_16_RESET" Port_PB_Bit_7 
+fi
+
+bool 'Axis flash-map support' CONFIG_ETRAX_AXISFLASHMAP n
+
+if [ "$CONFIG_ETRAX_AXISFLASHMAP" = "y" ]; then
+# here we define the CONFIG_'s necessary to enable MTD support
+# for the flash
+	define_bool CONFIG_MTD y
+
+	define_bool CONFIG_MTD_CFI y
+	define_bool CONFIG_MTD_CFI_INTELEXT n
+	define_bool CONFIG_MTD_CFI_AMDSTD y
+
+	define_bool CONFIG_MTD_CHAR y
+fi
+
+endmenu
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/Makefile linux/arch/cris/drivers/Makefile
--- v2.4.1/linux/arch/cris/drivers/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,14 @@
+#
+# Makefile for Etrax-specific drivers
+#
+
+O_TARGET := drivers.o
+
+obj-y :=
+
+obj-$(CONFIG_ETRAX_ETHERNET)     += ethernet.o
+obj-$(CONFIG_ETRAX_SERIAL)       += serial.o
+obj-$(CONFIG_ETRAX_IDE)          += ide.o
+obj-$(CONFIG_ETRAX_AXISFLASHMAP) += axisflashmap.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/axisflashmap.c linux/arch/cris/drivers/axisflashmap.c
--- v2.4.1/linux/arch/cris/drivers/axisflashmap.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/axisflashmap.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,311 @@
+/*
+ * Physical mapping layer for MTD using the Axis partitiontable format
+ *
+ * Copyright (c) 2001 Axis Communications AB
+ *
+ * This file is under the GPL.
+ *
+ * First partition is always sector 0 regardless of if we find a partitiontable
+ * or not. In the start of the next sector, there can be a partitiontable that
+ * tells us what other partitions to define. If there isn't, we use a default
+ * partition split defined below.
+ *
+ * $Log: axisflashmap.c,v $
+ * Revision 1.1  2001/01/12 17:01:18  bjornw
+ * * Added axisflashmap.c, a physical mapping for MTD that reads and understands
+ *   Axis partition-table format.
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/config.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+
+#include <asm/axisflashmap.h>
+#include <asm/mmu.h>
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define FLASH_UNCACHED_ADDR  KSEG_E
+#define FLASH_CACHED_ADDR    KSEG_5
+#else
+#define FLASH_UNCACHED_ADDR  KSEG_E
+#define FLASH_CACHED_ADDR    KSEG_F
+#endif
+
+/*
+ * WINDOW_SIZE is the total size where the flash chips are mapped,
+ * my guess is that this can be the total memory area even if there
+ * are many flash chips inside the area or if they are not all mounted.
+ * So possibly we can get rid of the CONFIG_ here and just write something
+ * like 32 MB always.
+ */
+
+#define WINDOW_SIZE  (CONFIG_ETRAX_FLASH_LENGTH * 1024 * 1024)
+
+/* Byte-offset where the partition-table is placed in the first chip
+ */
+
+#define PTABLE_SECTOR 65536
+
+/* 
+ * Map driver
+ *
+ * Ok this is the scoop - we need to access the flash both with and without
+ * the cache - without when doing all the fancy flash interfacing, and with
+ * when we do actual copying because otherwise it will be slow like molasses.
+ * I hope this works the way it's intended, so that there won't be any cases
+ * of non-synchronicity because of the different access modes below...
+ */
+
+static __u8 flash_read8(struct map_info *map, unsigned long ofs)
+{
+	return *(__u8 *)(FLASH_UNCACHED_ADDR + ofs);
+}
+
+static __u16 flash_read16(struct map_info *map, unsigned long ofs)
+{
+	return *(__u16 *)(FLASH_UNCACHED_ADDR + ofs);
+}
+
+static __u32 flash_read32(struct map_info *map, unsigned long ofs)
+{
+	return *(volatile unsigned int *)(FLASH_UNCACHED_ADDR + ofs);
+}
+
+static void flash_copy_from(struct map_info *map, void *to,
+			    unsigned long from, ssize_t len)
+{
+	memcpy(to, (void *)(FLASH_CACHED_ADDR + from), len);
+}
+
+static void flash_write8(struct map_info *map, __u8 d, unsigned long adr)
+{
+	*(__u8 *)(FLASH_UNCACHED_ADDR + adr) = d;
+}
+
+static void flash_write16(struct map_info *map, __u16 d, unsigned long adr)
+{
+	*(__u16 *)(FLASH_UNCACHED_ADDR + adr) = d;
+}
+
+static void flash_write32(struct map_info *map, __u32 d, unsigned long adr)
+{
+	*(__u32 *)(FLASH_UNCACHED_ADDR + adr) = d;
+}
+
+static void flash_copy_to(struct map_info *map, unsigned long to,
+			  const void *from, ssize_t len)
+{
+	memcpy((void *)(FLASH_CACHED_ADDR + to), from, len);
+}
+
+static struct map_info axis_map = {
+	name: "Axis flash",
+	size: WINDOW_SIZE,
+	buswidth: CONFIG_ETRAX_FLASH_BUSWIDTH,
+	read8: flash_read8,
+	read16: flash_read16,
+	read32: flash_read32,
+	copy_from: flash_copy_from,
+	write8: flash_write8,
+	write16: flash_write16,
+	write32: flash_write32,
+	copy_to: flash_copy_to
+};
+
+/* If no partition-table was found, we use this default-set.
+ */
+
+#define MAX_PARTITIONS         7  
+#define NUM_DEFAULT_PARTITIONS 3
+
+static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = {
+	{
+		name: "boot firmware",
+		size: PTABLE_SECTOR,
+		offset: 0
+	},
+	{
+		name: "kernel",
+		size: 0x1a0000,
+		offset: PTABLE_SECTOR
+	},
+	{
+		name: "filesystem",
+		size: 0x50000,
+		offset: (0x1a0000 + PTABLE_SECTOR)
+	}
+};
+
+static struct mtd_partition axis_partitions[MAX_PARTITIONS] = {
+	{
+		name: "part0",
+		size: 0,
+		offset: 0
+	},
+	{
+		name: "part1",
+		size: 0,
+		offset: 0
+	},
+	{
+		name: "part2",
+		size: 0,
+		offset: 0
+	},
+	{
+		name: "part3",
+		size: 0,
+		offset: 0
+	},
+	{
+		name: "part4",
+		size: 0,
+		offset: 0
+	},
+	{
+		name: "part5",
+		size: 0,
+		offset: 0
+	},
+	{
+		name: "part6",
+		size: 0,
+		offset: 0
+	},
+};
+
+/* 
+ * This is the master MTD device for which all the others are just
+ * auto-relocating aliases.
+ */
+static struct mtd_info *mymtd;
+
+/* CFI-scan the flash, and if there was a chip, read the partition-table
+ * and register the partitions with MTD.
+ */
+
+static int __init
+init_axis_flash(void)
+{
+	int pidx = 0;
+	struct partitiontable_head *ptable_head;
+	struct partitiontable_entry *ptable;
+	int use_default_ptable = 1; /* Until proven otherwise */
+	const char *pmsg = "  /dev/flash%d at 0x%x, size 0x%x\n";
+
+	printk(KERN_NOTICE "Axis flash mapping: %x at %x\n",
+	       WINDOW_SIZE, FLASH_CACHED_ADDR);
+
+	mymtd = do_cfi_probe(&axis_map);
+
+	if(!mymtd) {
+		printk("cfi_probe erred %d\n", mymtd);
+		return -ENXIO;
+	}
+
+	mymtd->module = THIS_MODULE;
+
+	/* The partition-table is at an offset within the second 
+	 * sector of the flash. We _define_ this to be at offset 64k
+	 * even if the actual sector-size in the flash changes.. for
+	 * now at least.
+	 */
+
+	ptable_head = FLASH_CACHED_ADDR + PTABLE_SECTOR + PARTITION_TABLE_OFFSET;
+	pidx++;  /* first partition is always set to the default */
+
+	if ((ptable_head->magic == PARTITION_TABLE_MAGIC)
+	    && (ptable_head->size
+		< (MAX_PARTITIONS
+		   * sizeof(struct partitiontable_entry) + 4))
+	    && (*(unsigned long*)
+		((void*)ptable_head
+		 + sizeof(*ptable_head)
+		 + ptable_head->size - 4)
+		==  PARTITIONTABLE_END_MARKER)) {
+		/* Looks like a start, sane length and end of a
+		 * partition table, lets check csum etc.
+		 */
+		int ptable_ok = 0;
+		struct partitiontable_entry *max_addr =
+			(struct partitiontable_entry *)
+			((unsigned long)ptable_head + sizeof(*ptable_head) +
+			 ptable_head->size);
+		unsigned long offset = PTABLE_SECTOR;
+		unsigned char *p;
+		unsigned long csum = 0;
+		
+		ptable = (struct partitiontable_entry *)
+			((unsigned long)ptable_head + sizeof(*ptable_head));
+
+		/* Lets be PARANOID, and check the checksum. */
+		p = (unsigned char*) ptable;
+
+		while (p <= (unsigned char*)max_addr) {
+			csum += *p++;
+			csum += *p++;
+			csum += *p++;
+			csum += *p++;
+		}
+		/* printk("  total csum: 0x%08X 0x%08X\n",
+		   csum, ptable_head->checksum); */
+		ptable_ok = (csum == ptable_head->checksum);
+
+		/* Read the entries and use/show the info.  */
+		ptable = (struct partitiontable_entry *)
+			((unsigned long)ptable_head + sizeof(*ptable_head));
+		
+		printk(" Found %s partition table at 0x%08lX-0x%08lX.\n",
+		       (ptable_ok ? "valid" : "invalid"),
+		       (unsigned long)ptable_head,
+		       (unsigned long)max_addr);
+
+		/* We have found a working bootblock.  Now read the
+		   partition table.  Scan the table.  It ends when
+		   there is 0xffffffff, that is, empty flash.  */
+		
+		while (ptable_ok
+		       && ptable->offset != 0xffffffff
+		       && ptable < max_addr
+		       && pidx < MAX_PARTITIONS) {
+#if 0
+			/* wait with multi-chip support until we know
+			 * how mtd detects multiple chips
+			 */
+			if ((offset + ptable->offset) >= chips[0].size) {
+				partitions[pidx].start
+					= offset + chips[1].start
+					+ ptable->offset - chips[0].size;
+			}
+#endif
+			axis_partitions[pidx].offset = offset + ptable->offset;
+			axis_partitions[pidx].size = ptable->size;
+
+			printk(pmsg, pidx, axis_partitions[pidx].offset,
+			       axis_partitions[pidx].size);
+			pidx++;
+			ptable++;
+		}
+		use_default_ptable = !ptable_ok;
+	}
+
+	if(use_default_ptable) {
+		printk(" Using default partition table\n");
+		return add_mtd_partitions(mymtd, axis_default_partitions,
+					  NUM_DEFAULT_PARTITIONS);
+	} else {
+		return add_mtd_partitions(mymtd, axis_partitions, pidx);
+	}		
+}
+
+/* This adds the above to the kernels init-call chain */
+
+module_init(init_axis_flash);
+
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/ethernet.c linux/arch/cris/drivers/ethernet.c
--- v2.4.1/linux/arch/cris/drivers/ethernet.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/ethernet.c	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,1041 @@
+/* $Id: ethernet.c,v 1.5 2000/11/29 17:22:22 bjornw Exp $
+ *
+ * e100net.c: A network driver for the ETRAX 100LX network controller.
+ *
+ * Copyright (c) 1998-2000 Axis Communications AB.
+ *
+ * The outline of this driver comes from skeleton.c.
+ *
+ * $Log: ethernet.c,v $
+ * Revision 1.5  2000/11/29 17:22:22  bjornw
+ * Get rid of the udword types legacy stuff
+ *
+ * Revision 1.4  2000/11/22 16:36:09  bjornw
+ * Please marketing by using the correct case when spelling Etrax.
+ *
+ * Revision 1.3  2000/11/21 16:43:04  bjornw
+ * Minor short->int change
+ *
+ * Revision 1.2  2000/11/08 14:27:57  bjornw
+ * 2.4 port
+ *
+ * Revision 1.1  2000/11/06 13:56:00  bjornw
+ * Verbatim copy of the 1.24 version of e100net.c from elinux
+ *
+ * Revision 1.24  2000/10/04 15:55:23  bjornw
+ * * Use virt_to_phys etc. for DMA addresses
+ * * Removed bogus CHECKSUM_UNNECESSARY
+ *
+ *
+ */
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+
+#include <asm/svinto.h>
+
+//#define ETHDEBUG
+
+#define D(x)
+
+/*
+ * The name of the card. Is used for messages and in the requests for
+ * io regions, irqs and dma channels
+ */
+
+static const char* cardname = "ETRAX 100LX built-in ethernet controller";
+
+/* A default ethernet address. Highlevel SW will set the real one later */
+
+static struct sockaddr default_mac = {
+	0,
+        { 0x00, 0x40, 0x8C, 0xCD, 0x00, 0x00 }
+};
+
+/* Information that need to be kept for each board. */
+struct net_local {
+	struct net_device_stats stats;
+
+	/* Tx control lock.  This protects the transmit buffer ring
+	 * state along with the "tx full" state of the driver.  This
+	 * means all netif_queue flow control actions are protected
+	 * by this lock as well.
+	 */
+	spinlock_t lock;
+};
+
+#define NETWORK_DMARX_IRQ 17  /* irq 17 is the DMA1 irq */
+#define NETWORK_DMATX_IRQ 16  /* irq 16 is the DMA0 irq */
+#define NETWORK_STATUS_IRQ 6  /* irq 6 is the network irq */
+
+/* Dma descriptors etc. */
+
+#define RX_BUF_SIZE 32768
+
+#define MAX_MEDIA_DATA_SIZE 1518
+
+#define MIN_PACKET_LEN      46
+#define ETHER_HEAD_LEN      14
+
+/* 
+** MDIO constants.
+*/
+#define MDIO_BASE_STATUS_REG   0x1
+#define MDIO_BASE_CONTROL_REG  0x0
+#define MDIO_LINK_UP_MASK      0x4
+#define MDIO_START                          0x1
+#define MDIO_READ                           0x2
+#define MDIO_WRITE                          0x1
+#define MDIO_PREAMBLE              0xfffffffful
+
+/* Broadcom specific */
+#define MDIO_AUX_CTRL_STATUS_REG           0x18
+#define MDIO_SPEED                          0x2
+#define MDIO_PHYS_ADDR                      0x0
+
+/* Network flash constants */
+#define NET_FLASH_TIME                        2 /* 20 ms */
+#define NET_LINK_UP_CHECK_INTERVAL          200 /* 2 s   */
+
+/* RX_DESC_BUF_SIZE should be a multiple of four to avoid the buffer
+ * alignment bug in Etrax 100 release 1
+ */
+
+#define RX_DESC_BUF_SIZE   256
+#define NBR_OF_RX_DESC     (RX_BUF_SIZE / \
+			    RX_DESC_BUF_SIZE)
+
+#define GET_BIT(bit,val)   (((val) >> (bit)) & 0x01)
+
+static etrax_dma_descr *myNextRxDesc;  /* Points to the next descriptor to
+					  to be processed */
+static etrax_dma_descr *myLastRxDesc;  /* The last processed descriptor */
+static etrax_dma_descr *myPrevRxDesc;  /* The descriptor right before myNextRxDesc */
+
+static unsigned char RxBuf[RX_BUF_SIZE];
+
+static etrax_dma_descr RxDescList[NBR_OF_RX_DESC];
+static etrax_dma_descr TxDesc;
+
+static struct sk_buff *tx_skb;
+
+/* Network speed indication. */
+static struct timer_list speed_timer;
+static struct timer_list clear_led_timer;
+static int current_speed;
+static int led_clear_time;
+static int nolink;
+
+/* Index to functions, as function prototypes. */
+
+static int etrax_ethernet_init(struct net_device *dev);
+
+static int e100_open(struct net_device *dev);
+static int e100_set_mac_address(struct net_device *dev, void *addr);
+static int e100_send_packet(struct sk_buff *skb, struct net_device *dev);
+static void e100rx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void e100tx_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void e100nw_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void e100_rx(struct net_device *dev);
+static int e100_close(struct net_device *dev);
+static struct net_device_stats *e100_get_stats(struct net_device *dev);
+static void set_multicast_list(struct net_device *dev);
+static void e100_hardware_send_packet(char *buf, int length);
+static void update_rx_stats(struct net_device_stats *);
+static void update_tx_stats(struct net_device_stats *);
+
+static void e100_check_speed(unsigned long dummy);
+static unsigned short e100_get_mdio_reg(unsigned char reg_num);
+static void e100_send_mdio_cmd(unsigned short cmd, int write_cmd);
+static void e100_send_mdio_bit(unsigned char bit);
+static unsigned char e100_receive_mdio_bit(void);
+static void e100_reset_tranceiver(void);
+
+static void e100_clear_network_leds(unsigned long dummy);
+
+#define tx_done(dev) (*R_DMA_CH0_CMD == 0)
+
+/*
+ * Check for a network adaptor of this type, and return '0' if one exists.
+ * If dev->base_addr == 0, probe all likely locations.
+ * If dev->base_addr == 1, always return failure.
+ * If dev->base_addr == 2, allocate space for the device and return success
+ * (detachable devices only).
+ */
+
+static int __init
+etrax_ethernet_init(struct net_device *dev)
+{
+	int i;
+	int anOffset = 0;
+
+	printk("ETRAX 100LX 10/100MBit ethernet v2.0 (c) 2000 Axis Communications AB\n");
+
+	dev->base_addr = (unsigned int)R_NETWORK_SA_0; /* just to have something to show */
+
+	printk("%s initialized\n", dev->name);
+
+	/* make Linux aware of the new hardware  */
+
+	if (!dev) {
+		printk("dev == NULL. Should this happen?\n");
+		dev = init_etherdev(dev, sizeof(struct net_local));
+	}
+
+	/* setup generic handlers and stuff in the dev struct */
+
+	ether_setup(dev);
+
+	/* make room for the local structure containing stats etc */
+
+	dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+	if (dev->priv == NULL)
+		return -ENOMEM;
+	memset(dev->priv, 0, sizeof(struct net_local));
+
+	/* now setup our etrax specific stuff */
+
+	dev->irq = NETWORK_DMARX_IRQ; /* we really use DMATX as well... */
+	dev->dma = 1;
+
+	/* fill in our handlers so the network layer can talk to us in the future */
+
+	dev->open               = e100_open;
+	dev->hard_start_xmit    = e100_send_packet;
+	dev->stop               = e100_close;
+	dev->get_stats          = e100_get_stats;
+	dev->set_multicast_list = set_multicast_list;
+	dev->set_mac_address    = e100_set_mac_address;
+
+	/* set the default MAC address */
+
+	e100_set_mac_address(dev, &default_mac);
+
+	/* Initialise the list of Etrax DMA-descriptors */
+
+	/* Initialise receive descriptors */
+
+	for(i = 0; i < (NBR_OF_RX_DESC - 1); i++) {
+		RxDescList[i].ctrl   = 0;
+		RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
+		RxDescList[i].next   = virt_to_phys(&RxDescList[i + 1]);
+		RxDescList[i].buf    = virt_to_phys(RxBuf + anOffset);
+		RxDescList[i].status = 0;
+		RxDescList[i].hw_len = 0;
+		anOffset += RX_DESC_BUF_SIZE;
+	}
+
+	RxDescList[i].ctrl   = d_eol;
+	RxDescList[i].sw_len = RX_DESC_BUF_SIZE;
+	RxDescList[i].next   = virt_to_phys(&RxDescList[0]);
+	RxDescList[i].buf    = virt_to_phys(RxBuf + anOffset);
+	RxDescList[i].status = 0;
+	RxDescList[i].hw_len = 0;
+
+	/* Initialise initial pointers */
+
+	myNextRxDesc = &RxDescList[0];
+	myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+	myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1];
+
+	/* Initialize speed indicator stuff. */
+
+	nolink = 0;
+	current_speed = 10;
+	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
+	speed_timer.function = e100_check_speed;
+	add_timer(&speed_timer);
+	clear_led_timer.function = e100_clear_network_leds;
+	clear_led_timer.expires = jiffies + 10;
+	add_timer(&clear_led_timer);
+
+	return 0;
+}
+
+/* set MAC address of the interface. called from the core after a
+ * SIOCSIFADDR ioctl, and from the bootup above.
+ */
+
+static int
+e100_set_mac_address(struct net_device *dev, void *p)
+{
+	struct sockaddr *addr = p;
+	int i;
+
+	/* remember it */
+
+        memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+
+	/* Write it to the hardware.
+	 * Note the way the address is wrapped:
+	 * *R_NETWORK_SA_0 = a0_0 | (a0_1 << 8) | (a0_2 << 16) | (a0_3 << 24);
+	 * *R_NETWORK_SA_1 = a0_4 | (a0_5 << 8);
+	 */
+	
+	*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |
+		(dev->dev_addr[2] << 16) | (dev->dev_addr[3] << 24);
+	*R_NETWORK_SA_1 = dev->dev_addr[4] | (dev->dev_addr[5] << 8);
+	*R_NETWORK_SA_2 = 0;
+
+	/* show it in the log as well */
+
+	printk("%s: changed MAC to ", dev->name);
+
+	for (i = 0; i < 5; i++)
+		printk("%02X:", dev->dev_addr[i]);
+
+	printk("%02X\n", dev->dev_addr[i]);
+
+	return 0;
+}
+
+/*
+ * Open/initialize the board. This is called (in the current kernel)
+ * sometime after booting when the 'ifconfig' program is run.
+ *
+ * This routine should set everything up anew at each open, even
+ * 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
+e100_open(struct net_device *dev)
+{
+	unsigned long flags;
+
+	/* disable the ethernet interface while we configure it */
+
+	*R_NETWORK_GEN_CONFIG =
+		IO_STATE(R_NETWORK_GEN_CONFIG, phy,    mii_clk) |
+		IO_STATE(R_NETWORK_GEN_CONFIG, enable, off);
+
+	/* enable the MDIO output pin */
+
+	*R_NETWORK_MGM_CTRL = IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable);
+
+	*R_IRQ_MASK0_CLR = 0xe0000; /* clear excessive_col, over/underrun irq mask */
+	*R_IRQ_MASK2_CLR = 0xf; /* clear dma0 and 1 eop and descr irq masks */
+
+	/* Reset and wait for the DMA channels */
+
+	RESET_DMA(0);
+	RESET_DMA(1);
+	WAIT_DMA(0);
+	WAIT_DMA(1);
+
+	/* Initialise the etrax network controller */
+
+	/* allocate the irq corresponding to the receiving DMA */
+
+	if (request_irq(NETWORK_DMARX_IRQ, e100rx_interrupt, 0,
+			cardname, (void *)dev)) {
+		goto grace_exit;
+	}
+
+	/* allocate the irq corresponding to the transmitting DMA */
+
+	if (request_irq(NETWORK_DMATX_IRQ, e100tx_interrupt, 0,
+			cardname, (void *)dev)) {
+		goto grace_exit;
+	}
+
+	/* allocate the irq corresponding to the network errors etc */
+
+	if (request_irq(NETWORK_STATUS_IRQ, e100nw_interrupt, 0,
+			cardname, (void *)dev)) {
+		goto grace_exit;
+	}
+
+	/*
+	 * Always allocate the DMA channels after the IRQ,
+	 * and clean up on failure.
+	 */
+
+	if(request_dma(0, cardname)) {
+		goto grace_exit;
+	}
+
+	if(request_dma(1, cardname)) {
+	grace_exit:
+		/* this will cause some 'trying to free free irq' but what the heck... */
+		free_dma(0);
+		free_irq(NETWORK_DMARX_IRQ, NULL);
+		free_irq(NETWORK_DMATX_IRQ, NULL);
+		free_irq(NETWORK_STATUS_IRQ, NULL);
+		return -EAGAIN;
+	}
+
+	/* give the HW an idea of what MAC address we want */
+
+	*R_NETWORK_SA_0 = dev->dev_addr[0] | (dev->dev_addr[1] << 8) |
+		(dev->dev_addr[2] << 16) | (dev->dev_addr[3] << 24);
+	*R_NETWORK_SA_1 = dev->dev_addr[4] | (dev->dev_addr[5] << 8);
+	*R_NETWORK_SA_2 = 0;
+
+#if 0
+	/* use promiscuous mode for testing */
+	*R_NETWORK_GA_0 = 0xffffffff;
+	*R_NETWORK_GA_1 = 0xffffffff;
+
+	*R_NETWORK_REC_CONFIG = 0xd; /* broadcast rec, individ. rec, ma0 enabled */
+#else
+	*R_NETWORK_REC_CONFIG =
+		IO_STATE(R_NETWORK_REC_CONFIG, broadcast, receive) |
+		IO_STATE(R_NETWORK_REC_CONFIG, ma0,       enable);
+#endif
+
+	*R_NETWORK_GEN_CONFIG =
+		IO_STATE(R_NETWORK_GEN_CONFIG, phy,    mii_clk) |
+		IO_STATE(R_NETWORK_GEN_CONFIG, enable, on);
+
+	save_flags(flags);
+	cli();
+
+	/* enable the irq's for ethernet DMA */
+
+	*R_IRQ_MASK2_SET =
+		IO_STATE(R_IRQ_MASK2_SET, dma0_eop, set) |
+		IO_STATE(R_IRQ_MASK2_SET, dma1_eop, set);
+
+	*R_IRQ_MASK0_SET =
+		IO_STATE(R_IRQ_MASK0_SET, overrun,       set) |
+		IO_STATE(R_IRQ_MASK0_SET, underrun,      set) |
+		IO_STATE(R_IRQ_MASK0_SET, excessive_col, set);
+
+	tx_skb = 0;
+
+	/* make sure the irqs are cleared */
+
+	*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
+	*R_DMA_CH1_CLR_INTR = IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do);
+
+	/* make sure the rec and transmit error counters are cleared */
+
+	(void)*R_REC_COUNTERS;  /* dummy read */
+	(void)*R_TR_COUNTERS;   /* dummy read */
+
+	/* start the receiving DMA channel so we can receive packets from now on */
+
+	*R_DMA_CH1_FIRST = virt_to_phys(myNextRxDesc);
+	*R_DMA_CH1_CMD = IO_STATE(R_DMA_CH1_CMD, cmd, start);
+
+	restore_flags(flags);
+	
+	/* We are now ready to accept transmit requeusts from
+	 * the queueing layer of the networking.
+	 */
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+
+static void
+e100_check_speed(unsigned long dummy)
+{
+	unsigned long data;
+	data = e100_get_mdio_reg(MDIO_BASE_STATUS_REG);
+	if (!(data & MDIO_LINK_UP_MASK)) {
+		nolink = 1;
+		LED_NETWORK_TX_SET(1); /* Make it red, link is down. */
+	} else {
+		nolink = 0;
+		LED_NETWORK_TX_SET(0); /* Link is up again, clear red LED. */
+		data = e100_get_mdio_reg(MDIO_AUX_CTRL_STATUS_REG);
+		if (data & MDIO_SPEED) {
+			current_speed = 100;
+		} else {
+			current_speed = 10;
+		}
+	}
+	
+	/* Reinitialize the timer. */
+	speed_timer.expires = jiffies + NET_LINK_UP_CHECK_INTERVAL;
+	add_timer(&speed_timer);
+}
+
+static unsigned short
+e100_get_mdio_reg(unsigned char reg_num)
+{
+	unsigned long flags;
+	unsigned short cmd;    /* Data to be sent on MDIO port */
+	unsigned short data;   /* Data read from MDIO */
+	int bitCounter;
+	
+	save_flags(flags);
+	cli();
+	
+	/* Start of frame, OP Code, Physical Address, Register Address */
+	cmd = (MDIO_START << 14) | (MDIO_READ << 12) | (MDIO_PHYS_ADDR << 7) |
+		(reg_num << 2);
+	
+	e100_send_mdio_cmd(cmd, 0);
+	
+	data = 0;
+	
+	/* Data... */
+	for(bitCounter=15; bitCounter>=0 ; bitCounter--) {
+		data |= (e100_receive_mdio_bit() << bitCounter);
+	}
+	
+	restore_flags(flags);
+	return data;
+}
+
+static void
+e100_send_mdio_cmd(unsigned short cmd, int write_cmd)
+{
+	int bitCounter;
+	unsigned char data = 0x2;
+	
+	/* Preamble */
+	for(bitCounter = 31; bitCounter>= 0; bitCounter--)
+		e100_send_mdio_bit(GET_BIT(bitCounter, MDIO_PREAMBLE));
+
+	for(bitCounter = 15; bitCounter >= 2; bitCounter--)
+		e100_send_mdio_bit(GET_BIT(bitCounter, cmd));
+
+	/* Turnaround */
+	for(bitCounter = 1; bitCounter >= 0 ; bitCounter--)
+		if (write_cmd)
+			e100_send_mdio_bit(GET_BIT(bitCounter, data));
+		else
+			e100_receive_mdio_bit();
+}
+
+static void
+e100_send_mdio_bit(unsigned char bit)
+{
+	volatile int i;
+	*R_NETWORK_MGM_CTRL = 2 | bit&1;
+	for (i=40; i; i--);
+	*R_NETWORK_MGM_CTRL = 6 | bit&1;
+	for (i=40; i; i--);
+}
+
+static unsigned char
+e100_receive_mdio_bit()
+{
+	unsigned char bit;
+	volatile int i;
+	*R_NETWORK_MGM_CTRL = 0;
+	bit = *R_NETWORK_STAT & 1;
+	for (i=40; i; i--);
+	*R_NETWORK_MGM_CTRL = 4;
+	for (i=40; i; i--);
+	return bit;
+}
+
+static void 
+e100_reset_tranceiver(void)
+{
+	unsigned long flags;
+	unsigned short cmd;
+	unsigned short data;
+	int bitCounter;
+
+	save_flags(flags);
+	cli();
+
+	data = e100_get_mdio_reg(MDIO_BASE_CONTROL_REG);
+
+	cmd = (MDIO_START << 14) | (MDIO_WRITE << 12) | (MDIO_PHYS_ADDR << 7) | (MDIO_BASE_CONTROL_REG << 2);
+
+	e100_send_mdio_cmd(cmd, 0);
+	
+	data |= 0x8000;
+	
+	for(bitCounter = 15; bitCounter >= 0 ; bitCounter--) {
+		e100_send_mdio_bit(GET_BIT(bitCounter, data));
+	}
+	
+	restore_flags(flags);
+}
+
+/* Called by upper layers if they decide it took too long to complete
+ * sending a packet - we need to reset and stuff.
+ */
+
+static void
+e100_tx_timeout(struct net_device *dev)
+{
+	struct net_local *np = (struct net_local *)dev->priv;
+
+	printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
+	       tx_done(dev) ? "IRQ problem" : "network cable problem");
+	
+	/* remember we got an error */
+	
+	np->stats.tx_errors++; 
+	
+	/* reset the TX DMA in case it has hung on something */
+	
+	RESET_DMA(0);
+	WAIT_DMA(0);
+	
+	/* Reset the tranceiver. */
+	
+	e100_reset_tranceiver();
+	
+	/* and get rid of the packet that never got an interrupt */
+	
+	dev_kfree_skb(tx_skb);
+	tx_skb = 0;
+	
+	/* tell the upper layers we're ok again */
+	
+	netif_wake_queue(dev);
+}
+
+
+/* This will only be invoked if the driver is _not_ in XOFF state.
+ * What this means is that we need not check it, and that this
+ * invariant will hold if we make sure that the netif_*_queue()
+ * calls are done at the proper times.
+ */
+
+static int
+e100_send_packet(struct sk_buff *skb, struct net_device *dev)
+{
+	struct net_local *np = (struct net_local *)dev->priv;
+	int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
+	unsigned char *buf = skb->data;
+	
+#ifdef ETHDEBUG
+	printk("send packet len %d\n", length);
+#endif
+	spin_lock_irq(&np->lock);  /* protect from tx_interrupt */
+
+	tx_skb = skb; /* remember it so we can free it in the tx irq handler later */
+	dev->trans_start = jiffies;
+	
+	e100_hardware_send_packet(buf, length);
+
+	/* this simple TX driver has only one send-descriptor so we're full
+	 * directly. If this had a send-ring instead, we would only do this if
+	 * the ring got full.
+	 */
+
+	netif_stop_queue(dev);
+
+	spin_unlock_irq(&np->lock);
+
+	return 0;
+}
+
+/*
+ * The typical workload of the driver:
+ *   Handle the network interface interrupts.
+ */
+
+static void
+e100rx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	unsigned long irqbits = *R_IRQ_MASK2_RD;
+
+	if(irqbits & (1U << 3)) {
+
+		/* acknowledge the eop interrupt */
+
+		*R_DMA_CH1_CLR_INTR = IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do);
+
+		/* check if one or more complete packets were indeed received */
+
+		while(*R_DMA_CH1_FIRST != virt_to_phys(myNextRxDesc)) {
+			/* Take out the buffer and give it to the OS, then
+			 * allocate a new buffer to put a packet in.
+			 */
+			e100_rx(dev);
+			((struct net_local *)dev->priv)->stats.rx_packets++;
+			*R_DMA_CH1_CMD = 3; /* restart/continue on the channel, for safety */
+			*R_DMA_CH1_CLR_INTR = 3; /* clear dma channel 1 eop/descr irq bits */
+			/* now, we might have gotten another packet so we have to loop back
+			   and check if so */
+		}
+	}
+}
+
+/* the transmit dma channel interrupt
+ *
+ * this is supposed to free the skbuff which was pending during transmission,
+ * and inform the kernel that we can send one more buffer
+ */
+
+static void
+e100tx_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	unsigned long irqbits = *R_IRQ_MASK2_RD;
+	struct net_local *np = (struct net_local *)dev->priv;
+
+	if(irqbits & 2) { /* check for a dma0_eop interrupt */
+
+		/* This protects us from concurrent execution of
+		 * our dev->hard_start_xmit function above.
+		 */
+
+		spin_lock(&np->lock);
+		
+		/* acknowledge the eop interrupt */
+
+		*R_DMA_CH0_CLR_INTR = IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do);
+
+		if(*R_DMA_CH0_FIRST == 0 && tx_skb) {
+			np->stats.tx_bytes += tx_skb->len;
+			np->stats.tx_packets++;
+			/* dma is ready with the transmission of the data in tx_skb, so now
+			   we can release the skb memory */
+			dev_kfree_skb_irq(tx_skb);
+			tx_skb = 0;
+			netif_wake_queue(dev);
+		} else {
+			printk("tx weird interrupt\n");
+		}
+
+		spin_unlock(&np->lock);
+	}
+}
+
+static void
+e100nw_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct net_local *np = (struct net_local *)dev->priv;
+	unsigned long irqbits = *R_IRQ_MASK0_RD;
+
+	if(irqbits & (1 << 19)) { /* check for overrun irq */
+		update_rx_stats(&np->stats); /* this will ack the irq */
+		D(printk("ethernet receiver overrun!\n"));
+	}
+	if(irqbits & (1 << 17)) { /* check for excessive collision irq */
+		*R_NETWORK_TR_CTRL = 1 << 8; /* clear the interrupt */
+		np->stats.tx_errors++;
+		D(printk("ethernet excessive collisions!\n"));
+	}
+
+}
+
+/* We have a good packet(s), get it/them out of the buffers. */
+static void
+e100_rx(struct net_device *dev)
+{
+	struct sk_buff *skb;
+	int length=0;
+	int i;
+	struct etrax_dma_descr *mySaveRxDesc = myNextRxDesc;
+	unsigned char *skb_data_ptr;
+
+	/* light the network rx packet depending on the current speed.
+	** But only if link has been detected.
+	*/
+	if (!nolink)
+		if (current_speed == 10) {
+			LED_NETWORK_TX_SET(1);
+			LED_NETWORK_RX_SET(1);
+		} else
+			LED_NETWORK_RX_SET(1);
+  
+	/* Set the earliest time we may clear the LED */
+
+	led_clear_time = jiffies + NET_FLASH_TIME;
+  
+	/* If the packet is broken down in many small packages then merge
+	 * count how much space we will need to alloc with skb_alloc() for
+	 * it to fit.
+	 */
+
+	while (!(myNextRxDesc->status & d_eop)) {
+		length += myNextRxDesc->sw_len; /* use sw_len for the first descs */
+		myNextRxDesc->status = 0;
+		myNextRxDesc = phys_to_virt(myNextRxDesc->next);
+	}
+
+	length += myNextRxDesc->hw_len; /* use hw_len for the last descr */
+
+#ifdef ETHDEBUG
+	printk("Got a packet of length %d:\n", length);
+	/* dump the first bytes in the packet */
+	skb_data_ptr = (unsigned char *)phys_to_virt(mySaveRxDesc->buf);
+	for(i = 0; i < 8; i++) {
+		printk("%d: %.2x %.2x %.2x %.2x %.2x %.2x %.2x %.2x\n", i * 8,
+		       skb_data_ptr[0],skb_data_ptr[1],skb_data_ptr[2],skb_data_ptr[3],
+		       skb_data_ptr[4],skb_data_ptr[5],skb_data_ptr[6],skb_data_ptr[7]);
+		skb_data_ptr += 8;
+	}
+#endif
+
+	skb = dev_alloc_skb(length - ETHER_HEAD_LEN);
+	if (!skb) {
+		printk(KERN_NOTICE "%s: Memory squeeze, dropping packet.\n",
+		       dev->name);
+		return;
+	}
+
+	skb_put(skb, length - ETHER_HEAD_LEN);        /* allocate room for the packet body */
+	skb_data_ptr = skb_push(skb, ETHER_HEAD_LEN); /* allocate room for the header */
+
+#if 0
+	printk("head = 0x%x, data = 0x%x, tail = 0x%x, end = 0x%x\n",
+	       skb->head, skb->data, skb->tail, skb->end);
+	printk("copying packet to 0x%x.\n", skb_data_ptr);
+#endif
+
+	/* this loop can be made using max two memcpy's if optimized */
+
+	while(mySaveRxDesc != myNextRxDesc) {
+		memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),
+		       mySaveRxDesc->sw_len);
+		skb_data_ptr += mySaveRxDesc->sw_len;
+		mySaveRxDesc = phys_to_virt(mySaveRxDesc->next);
+	}
+
+	memcpy(skb_data_ptr, phys_to_virt(mySaveRxDesc->buf),
+	       mySaveRxDesc->hw_len);
+
+	skb->dev = dev;
+	skb->protocol = eth_type_trans(skb, dev);
+
+	/* Send the packet to the upper layers */
+
+	netif_rx(skb);
+
+	/* Prepare for next packet */
+
+	myNextRxDesc->status = 0;
+	myPrevRxDesc = myNextRxDesc;
+	myNextRxDesc = phys_to_virt(myNextRxDesc->next);
+
+	myPrevRxDesc->ctrl |= d_eol;
+	myLastRxDesc->ctrl &= ~d_eol;
+	myLastRxDesc = myPrevRxDesc;
+
+	return;
+}
+
+/* The inverse routine to net_open(). */
+static int
+e100_close(struct net_device *dev)
+{
+	struct net_local *np = (struct net_local *)dev->priv;
+
+	printk("Closing %s.\n", dev->name);
+
+	netif_stop_queue(dev);
+
+	*R_NETWORK_GEN_CONFIG =
+		IO_STATE(R_NETWORK_GEN_CONFIG, phy,    mii_clk) |
+		IO_STATE(R_NETWORK_GEN_CONFIG, enable, off);
+
+	*R_IRQ_MASK0_CLR = 0xe0000; /* clear excessive_col, over/underrun irq mask */
+	*R_IRQ_MASK2_CLR = 0xf; /* clear dma0 and 1 eop and descr irq masks */
+
+	/* Stop the receiver and the transmitter */
+
+	RESET_DMA(0);
+	RESET_DMA(1);
+
+	/* Flush the Tx and disable Rx here. */
+
+	free_irq(NETWORK_DMARX_IRQ, NULL);
+	free_irq(NETWORK_DMATX_IRQ, NULL);
+	free_irq(NETWORK_STATUS_IRQ, NULL);
+
+	free_dma(0);
+	free_dma(1);
+
+	/* Update the statistics here. */
+
+	update_rx_stats(&np->stats);
+	update_tx_stats(&np->stats);
+
+	return 0;
+}
+
+static void
+update_rx_stats(struct net_device_stats *es)
+{
+	unsigned long r = *R_REC_COUNTERS;
+	/* update stats relevant to reception errors */
+	es->rx_fifo_errors += r >> 24;            /* fifo overrun */
+	es->rx_crc_errors += r & 0xff;            /* crc error */
+	es->rx_frame_errors += (r >> 8) & 0xff;   /* alignment error */
+	es->rx_length_errors += (r >> 16) & 0xff; /* oversized frames */
+}
+
+static void
+update_tx_stats(struct net_device_stats *es)
+{
+	unsigned long r = *R_TR_COUNTERS;
+	/* update stats relevant to transmission errors */
+	es->collisions += (r & 0xff) + ((r >> 8) & 0xff); /* single_col + multiple_col */
+	es->tx_errors += (r >> 24) & 0xff; /* deferred transmit frames */
+}
+
+/*
+ * Get the current statistics.
+ * This may be called with the card open or closed.
+ */
+static struct net_device_stats *
+e100_get_stats(struct net_device *dev)
+{
+	struct net_local *lp = (struct net_local *)dev->priv;
+
+	update_rx_stats(&lp->stats);
+	update_tx_stats(&lp->stats);
+
+	return &lp->stats;
+}
+
+/*
+ * Set or clear the multicast filter for this adaptor.
+ * num_addrs == -1	Promiscuous mode, receive all packets
+ * num_addrs == 0	Normal mode, clear multicast list
+ * num_addrs > 0	Multicast mode, receive normal and MC packets,
+ *			and do best-effort filtering.
+ */
+static void
+set_multicast_list(struct net_device *dev)
+{
+	int num_addr = dev->mc_count;
+	unsigned long int lo_bits;
+	unsigned long int hi_bits;
+	if (num_addr == -1)
+	{
+		/* promiscuous mode */
+		lo_bits = 0xfffffffful;
+		hi_bits = 0xfffffffful;
+	} else if (num_addr == 0) {
+		/* Normal, clear the mc list */
+		lo_bits = 0x00000000ul;
+		hi_bits = 0x00000000ul;
+	} else {
+		/* MC mode, receive normal and MC packets */
+		char hash_ix;
+		struct dev_mc_list *dmi = dev->mc_list;
+		int i;
+		char *baddr;
+		lo_bits = 0x00000000ul;
+		hi_bits = 0x00000000ul;
+		for (i=0; i<num_addr; i++) {
+			/* Calculate the hash index for the GA registers */
+			
+			hash_ix = 0;
+			baddr = dmi->dmi_addr;
+			hash_ix ^= (*baddr) & 0x3f;
+			hash_ix ^= ((*baddr) >> 6) & 0x03;
+			++baddr;
+			hash_ix ^= ((*baddr) << 2) & 0x03c;
+			hash_ix ^= ((*baddr) >> 4) & 0xf;
+			++baddr;
+			hash_ix ^= ((*baddr) << 4) & 0x30;
+			hash_ix ^= ((*baddr) >> 2) & 0x3f;
+			++baddr;
+			hash_ix ^= (*baddr) & 0x3f;
+			hash_ix ^= ((*baddr) >> 6) & 0x03;
+			++baddr;
+			hash_ix ^= ((*baddr) << 2) & 0x03c;
+			hash_ix ^= ((*baddr) >> 4) & 0xf;
+			++baddr;
+			hash_ix ^= ((*baddr) << 4) & 0x30;
+			hash_ix ^= ((*baddr) >> 2) & 0x3f;
+			
+			hash_ix &= 0x3f;
+			
+			if (hash_ix > 32) {
+				hi_bits |= (1 << (hash_ix-32));
+			}
+			else {
+				lo_bits |= (1 << hash_ix);
+			}
+			dmi = dmi->next;
+		}
+	}
+	*R_NETWORK_GA_0 = lo_bits;
+	*R_NETWORK_GA_1 = hi_bits;
+}
+
+void
+e100_hardware_send_packet(char *buf, int length)
+{
+	D(printk("e100 send pack, buf 0x%x len %d\n", buf, length));
+	/* light the network leds depending on the current speed.
+	** But only if link has been detected.
+	*/
+	if (!nolink) {
+		if (current_speed == 10) {
+			LED_NETWORK_TX_SET(1);
+			LED_NETWORK_RX_SET(1);
+		} else {
+			LED_NETWORK_RX_SET(1);
+		}
+	}
+
+	/* Set the earliest time we may clear the LED */
+
+	led_clear_time = jiffies + NET_FLASH_TIME;
+	
+	/* configure the tx dma descriptor */
+
+	TxDesc.sw_len = length;
+	TxDesc.ctrl = d_eop | d_eol | d_wait;
+	TxDesc.buf = virt_to_phys(buf);
+
+	/* setup the dma channel and start it */
+
+	*R_DMA_CH0_FIRST = virt_to_phys(&TxDesc);
+	*R_DMA_CH0_CMD = IO_STATE(R_DMA_CH0_CMD, cmd, start);
+}
+
+static void
+e100_clear_network_leds(unsigned long dummy)
+{
+	if (jiffies > led_clear_time) {
+		if (nolink)
+			LED_NETWORK_TX_SET(1);
+		else
+			LED_NETWORK_TX_SET(0);
+		LED_NETWORK_RX_SET(0); 
+	}
+	
+	clear_led_timer.expires = jiffies + 10;
+	add_timer(&clear_led_timer);
+}
+
+static struct net_device dev_etrax_ethernet;  /* only got one */
+
+static int
+etrax_init_module(void)
+{
+	struct net_device *d = &dev_etrax_ethernet;
+
+	d->init = etrax_ethernet_init;
+
+	if(register_netdev(d) == 0)
+		return 0;
+	else
+		return -ENODEV;
+}
+
+module_init(etrax_init_module);
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/ide.c linux/arch/cris/drivers/ide.c
--- v2.4.1/linux/arch/cris/drivers/ide.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/ide.c	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,818 @@
+/* $Id: ide.c,v 1.4 2001/01/10 21:14:32 bjornw Exp $
+ *
+ * Etrax specific IDE functions, like init and PIO-mode setting etc.
+ * Almost the entire ide.c is used for the rest of the Etrax ATA driver.
+ * Copyright (c) 2000, 2001 Axis Communications AB 
+ *
+ * Authors:    Bjorn Wesen        (initial version)
+ *             Mikael Starvik     (pio setup stuff)
+ *
+ * $Log: ide.c,v $
+ * Revision 1.4  2001/01/10 21:14:32  bjornw
+ * Initialize hwif->ideproc, for the new way of handling ide_xxx_data
+ *
+ * Revision 1.3  2000/12/01 17:48:18  bjornw
+ * - atapi_output_bytes now uses DMA
+ * - dma_active check removed - the kernel does proper serializing and it had
+ *   a race-condition anyway
+ * - ide_build_dmatable had a nameclash
+ * - re-added the RESET_DMA thingys because sometimes the interface can get
+ *   stuck apparently
+ * - added ide_release_dma
+ *
+ * Revision 1.2  2000/11/29 17:31:29  bjornw
+ * 2.4 port
+ *
+ * - The "register addresses" stored in the hwif are now 32-bit fields that
+ *   don't need to be shifted into correct positions in R_ATA_CTRL_DATA
+ * - PIO-mode detection temporarily disabled since ide-modes.c is not compiled
+ * - All DMA uses virt_to_phys conversions for DMA buffers and descriptor ptrs
+ * - Probably correct ide_dma_begin semantics in dmaproc now for ATAPI devices
+ * - Removed RESET_DMA when starting a new transfer - why was this necessary ?
+ * - Indentation fix
+ *
+ *
+ */
+
+/* Regarding DMA: 
+ *
+ * There are two forms of DMA - "DMA handshaking" between the interface and the drive,
+ * and DMA between the memory and the interface. We can ALWAYS use the latter, since it's
+ * something built-in in the Etrax. However only some drives support the DMA-mode handshaking
+ * on the ATA-bus. The normal PC driver and Triton interface disables memory-if DMA when the
+ * device can't do DMA handshaking for some stupid reason. We don't need to do that.
+ */ 
+
+#undef REALLY_SLOW_IO           /* most systems can safely undef this */
+
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/svinto.h>
+
+/* number of Etrax DMA descriptors */
+#define MAX_DMA_DESCRS 64
+
+#define LOWDB(x)
+#define D(x)
+
+void OUT_BYTE(unsigned char data, ide_ioreg_t reg) {
+	LOWDB(printk("ob: data 0x%x, reg 0x%x\n", data, reg));
+	while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */
+	*R_ATA_CTRL_DATA = reg | data; /* write data to the drive's register */
+	while(!(*R_ATA_STATUS_DATA &
+		IO_MASK(R_ATA_STATUS_DATA, tr_rdy))); /* wait for transmitter ready */
+}
+
+unsigned char IN_BYTE(ide_ioreg_t reg) {
+	int status;
+	while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */
+	*R_ATA_CTRL_DATA = reg | IO_STATE(R_ATA_CTRL_DATA, rw, read); /* read data */ 
+	while(!((status = *R_ATA_STATUS_DATA) &
+		IO_MASK(R_ATA_STATUS_DATA, dav))); /* wait for available */
+	LOWDB(printk("inb: 0x%x from reg 0x%x\n", status & 0xff, reg));
+	return (unsigned char)status; /* data was in the lower 16 bits in the status reg */
+}
+
+/* PIO timing (in R_ATA_CONFIG)
+ *
+ *                        _____________________________
+ * ADDRESS :     ________/
+ *
+ *                            _______________
+ * DIOR    :     ____________/               \__________
+ *
+ *                               _______________
+ * DATA    :     XXXXXXXXXXXXXXXX_______________XXXXXXXX
+ *
+ *
+ * DIOR is unbuffered while address and data is buffered.
+ * This creates two problems:
+ * 1. The DIOR pulse is to early (because it is unbuffered)
+ * 2. The rise time of DIOR is long
+ *
+ * There are at least three different plausible solutions
+ * 1. Use a pad capable of larger currents in Etrax
+ * 2. Use an external buffer
+ * 3. Make the strobe pulse longer
+ *
+ * Some of the strobe timings below are modified to compensate
+ * for this. This implies a slight performance decrease.
+ *
+ * THIS SHOULD NEVER BE CHANGED!
+ *
+ * TODO: Is this true for the latest LX boards still ?
+ */
+
+#define ATA_DMA2_STROBE  4 
+#define ATA_DMA2_HOLD    0
+#define ATA_DMA1_STROBE  4 
+#define ATA_DMA1_HOLD    1
+#define ATA_DMA0_STROBE 12 
+#define ATA_DMA0_HOLD    9
+#define ATA_PIO4_SETUP   1
+#define ATA_PIO4_STROBE  5
+#define ATA_PIO4_HOLD    0
+#define ATA_PIO3_SETUP   1
+#define ATA_PIO3_STROBE  5
+#define ATA_PIO3_HOLD    1
+#define ATA_PIO2_SETUP   1
+#define ATA_PIO2_STROBE  6
+#define ATA_PIO2_HOLD    2
+#define ATA_PIO1_SETUP   2
+#define ATA_PIO1_STROBE 11
+#define ATA_PIO1_HOLD    4
+#define ATA_PIO0_SETUP   4
+#define ATA_PIO0_STROBE 19
+#define ATA_PIO0_HOLD    4
+
+/*
+ * good_dma_drives() lists the model names (from "hdparm -i")
+ * of drives which do not support mword2 DMA but which are
+ * known to work fine with this interface under Linux.
+ */
+
+const char *good_dma_drives[] = {"Micropolis 2112A",
+				 "CONNER CTMA 4000",
+				 "CONNER CTT8000-A",
+				 NULL};
+
+static void tune_e100_ide(ide_drive_t *drive, byte pio)
+{
+	unsigned long flags;
+	
+	pio = 4;
+	//pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
+	
+	save_flags(flags);
+	cli();
+
+	/* set pio mode! */
+  	 
+	switch(pio) {
+		case 0:
+			*R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_hold,   ATA_DMA2_HOLD ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_setup,  ATA_PIO0_SETUP ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO0_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_hold,   ATA_PIO0_HOLD ) );
+			break;
+		case 1:
+			*R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_hold,   ATA_DMA2_HOLD ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_setup,  ATA_PIO1_SETUP ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO1_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_hold,   ATA_PIO1_HOLD ) );
+			break;
+		case 2:
+			*R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_hold,   ATA_DMA2_HOLD ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_setup,  ATA_PIO2_SETUP ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO2_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_hold,   ATA_PIO2_HOLD ) );
+			break;
+		case 3:
+			*R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_hold,   ATA_DMA2_HOLD ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_setup,  ATA_PIO3_SETUP ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO3_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_hold,   ATA_PIO3_HOLD ) );
+			break;
+		case 4:
+			*R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, dma_hold,   ATA_DMA2_HOLD ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_setup,  ATA_PIO4_SETUP ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO4_STROBE ) |
+					  IO_FIELD( R_ATA_CONFIG, pio_hold,   ATA_PIO4_HOLD ) );
+			break;
+	}
+	restore_flags(flags);
+}
+
+static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive); /* defined below */
+static void e100_ideproc (ide_ide_action_t func, ide_drive_t *drive,
+			  void *buffer, unsigned int length);        /* defined below */
+
+void __init init_e100_ide (void)
+{
+	volatile unsigned int dummy;
+	int h;
+
+	printk("ide: ETRAX 100LX built-in ATA DMA controller\n");
+
+	/* first fill in some stuff in the ide_hwifs fields */
+	
+	for(h = 0; h < MAX_HWIFS; h++) {
+		ide_hwif_t *hwif = &ide_hwifs[h];
+		hwif->chipset = ide_etrax100;
+		hwif->tuneproc = &tune_e100_ide;
+		hwif->dmaproc = &e100_dmaproc;
+		hwif->ideproc = &e100_ideproc;
+	}
+	/* actually reset and configure the etrax100 ide/ata interface */
+
+	/* de-assert bus-reset */
+#ifdef CONFIG_ETRAX_IDE_PB7_RESET  
+	port_pb_dir_shadow = port_pb_dir_shadow | 
+		IO_STATE(R_PORT_PB_DIR, dir7, output);
+	*R_PORT_PB_DIR = port_pb_dir_shadow;
+	REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, 7, 1);
+#endif
+#ifdef CONFIG_ETRAX_IDE_G27_RESET
+	*R_PORT_G_DATA = 0;
+#endif 
+
+	*R_ATA_CTRL_DATA = 0;
+	*R_ATA_TRANSFER_CNT = 0;
+	*R_ATA_CONFIG = 0;
+
+	genconfig_shadow = (genconfig_shadow & 
+			    ~IO_MASK(R_GEN_CONFIG, dma2) &
+			    ~IO_MASK(R_GEN_CONFIG, dma3) &
+			    ~IO_MASK(R_GEN_CONFIG, ata)) | 
+		( IO_STATE( R_GEN_CONFIG, dma3, ata    ) |
+		  IO_STATE( R_GEN_CONFIG, dma2, ata    ) |
+		  IO_STATE( R_GEN_CONFIG, ata,  select ) );
+
+	*R_GEN_CONFIG = genconfig_shadow;
+
+#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
+	*(volatile long *)(MEM_CSE1_START | MEM_NON_CACHEABLE) = 0;
+#endif
+
+	/* wait some */
+
+	dummy = 1;
+	dummy = 2;
+	dummy = 3;
+
+#ifdef CONFIG_ETRAX_IDE_CSE1_16_RESET
+	*(volatile long *)(MEM_CSE1_START | MEM_NON_CACHEABLE) = 1 << 16;
+	*R_PORT_G_DATA = 0;  /* de-assert bus-reset */
+#endif
+
+	/* make a dummy read to set the ata controller in a proper state */
+	dummy = *R_ATA_STATUS_DATA;
+  
+	*R_ATA_CONFIG = ( IO_FIELD( R_ATA_CONFIG, enable,     1 ) |
+			  IO_FIELD( R_ATA_CONFIG, dma_strobe, ATA_DMA2_STROBE ) |
+			  IO_FIELD( R_ATA_CONFIG, dma_hold,   ATA_DMA2_HOLD ) |
+			  IO_FIELD( R_ATA_CONFIG, pio_setup,  ATA_PIO4_SETUP ) |
+			  IO_FIELD( R_ATA_CONFIG, pio_strobe, ATA_PIO4_STROBE ) |
+			  IO_FIELD( R_ATA_CONFIG, pio_hold,   ATA_PIO4_HOLD ) );
+
+	*R_ATA_CTRL_DATA = ( IO_STATE( R_ATA_CTRL_DATA, rw,   read) |
+			     IO_FIELD( R_ATA_CTRL_DATA, addr, 1   ) );
+
+	while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag*/
+
+	*R_IRQ_MASK0_SET = ( IO_STATE( R_IRQ_MASK0_SET, ata_irq0, set ) |
+			     IO_STATE( R_IRQ_MASK0_SET, ata_irq1, set ) |
+			     IO_STATE( R_IRQ_MASK0_SET, ata_irq2, set ) |
+			     IO_STATE( R_IRQ_MASK0_SET, ata_irq3, set ) );
+
+	printk("ide: waiting 10 seconds for drives to regain consciousness\n");
+
+	h = jiffies + 1000;
+	while(jiffies < h) ;
+
+  /* reset the dma channels we will use */
+
+	RESET_DMA(2);
+	RESET_DMA(3);
+	WAIT_DMA(2);
+	WAIT_DMA(3);
+
+}
+
+static etrax_dma_descr mydescr;
+
+/*
+ * The following routines are mainly used by the ATAPI drivers.
+ *
+ * These routines will round up any request for an odd number of bytes,
+ * so if an odd bytecount is specified, be sure that there's at least one
+ * extra byte allocated for the buffer.
+ */
+static void 
+e100_atapi_input_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
+{
+	ide_ioreg_t data_reg = IDE_DATA_REG;
+	unsigned long status;
+
+	D(printk("atapi_input_bytes, dreg 0x%x, buffer 0x%x, count %d\n",
+		 data_reg, buffer, bytecount));
+	
+	if(bytecount & 1) {
+		printk("warning, odd bytecount in cdrom_in_bytes = %d.\n", bytecount);
+		bytecount++; /* to round off */
+	}
+	
+	/* make sure the DMA channel is available */
+	RESET_DMA(3);
+	WAIT_DMA(3); 
+	
+	/* setup DMA descriptor */
+	
+	mydescr.sw_len = bytecount;
+	mydescr.ctrl   = d_eol;
+	mydescr.buf    = virt_to_phys(buffer);
+	
+	/* start the dma channel */
+	
+	*R_DMA_CH3_FIRST = virt_to_phys(&mydescr);
+	*R_DMA_CH3_CMD   = IO_STATE(R_DMA_CH3_CMD, cmd, start);
+	
+	/* initiate a multi word dma read using PIO handshaking */
+	
+	*R_ATA_TRANSFER_CNT = bytecount >> 1;
+	
+	*R_ATA_CTRL_DATA = data_reg |
+		IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
+		IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma) |
+		IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
+		IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+	
+	/* wait for completion */
+	
+	LED_DISK_READ(1);
+	WAIT_DMA(3);
+	LED_DISK_READ(0);
+	
+#if 0
+	/* old polled transfer code */
+	
+	/* initiate a multi word read */
+	
+	*R_ATA_TRANSFER_CNT = wcount << 1;
+	
+	*R_ATA_CTRL_DATA = data_reg |
+		IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
+		IO_STATE(R_ATA_CTRL_DATA, src_dst,  register) |
+		IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
+		IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+	
+	/* svinto has a latency until the busy bit actually is set */
+	
+	nop(); nop();
+	nop(); nop();
+	nop(); nop();
+	nop(); nop();
+	nop(); nop();
+	
+	/* unit should be busy during multi transfer */
+	while((status = *R_ATA_STATUS_DATA) & IO_MASK(R_ATA_STATUS_DATA, busy)) {
+		while(!(status & IO_MASK(R_ATA_STATUS_DATA, dav)))
+			status = *R_ATA_STATUS_DATA;
+		*ptr++ = (unsigned short)(status & 0xffff);
+	}
+#endif
+}
+
+static void 
+e100_atapi_output_bytes (ide_drive_t *drive, void *buffer, unsigned int bytecount)
+{
+	ide_ioreg_t data_reg = IDE_DATA_REG;
+	unsigned short *ptr = (unsigned short *)buffer;
+	unsigned long ctrl;
+	
+	D(printk("atapi_output_bytes, dreg 0x%x, buffer 0x%x, count %d\n",
+		 data_reg, buffer, bytecount));
+
+	if(bytecount & 1) {
+		printk("odd bytecount %d in atapi_out_bytes!\n", bytecount);
+		bytecount++;
+	}
+
+	/* make sure the DMA channel is available */
+	RESET_DMA(2);
+	WAIT_DMA(2); 
+	
+	/* setup DMA descriptor */
+	
+	mydescr.sw_len = bytecount;
+	mydescr.ctrl   = d_eol;
+	mydescr.buf    = virt_to_phys(buffer);
+
+	/* start the dma channel */
+	
+	*R_DMA_CH2_FIRST = virt_to_phys(&mydescr);
+	*R_DMA_CH2_CMD   = IO_STATE(R_DMA_CH2_CMD, cmd, start);
+	
+	/* initiate a multi word dma write using PIO handshaking */
+	
+	*R_ATA_TRANSFER_CNT = bytecount >> 1;
+	
+	*R_ATA_CTRL_DATA = data_reg |
+		IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
+		IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma) |
+		IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
+		IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+	
+	/* wait for completion */
+	
+	LED_DISK_WRITE(1);
+	WAIT_DMA(2);
+	LED_DISK_WRITE(0);
+
+#if 0
+	/* old polled write code */
+
+	while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)); /* wait for busy flag */
+
+	/* initiate a multi word write */
+
+	*R_ATA_TRANSFER_CNT = bytecount >> 1;
+
+	ctrl = data_reg |
+		IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
+		IO_STATE(R_ATA_CTRL_DATA, src_dst,  register) |
+		IO_STATE(R_ATA_CTRL_DATA, handsh,   pio) |
+		IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+		IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+	
+	LED_DISK_WRITE(1);
+	
+	/* Etrax will set busy = 1 until the multi pio transfer has finished
+	 * and tr_rdy = 1 after each succesful word transfer. 
+	 * When the last byte has been transferred Etrax will first set tr_tdy = 1 
+	 * and then busy = 0 (not in the same cycle). If we read busy before it
+	 * has been set to 0 we will think that we should transfer more bytes 
+	 * and then tr_rdy would be 0 forever. This is solved by checking busy
+	 * in the inner loop.
+	 */
+	
+	do {
+		*R_ATA_CTRL_DATA = ctrl | *ptr++;
+		while(!(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, tr_rdy)) &&
+		      (*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy)));
+	} while(*R_ATA_STATUS_DATA & IO_MASK(R_ATA_STATUS_DATA, busy));
+
+	LED_DISK_WRITE(0);
+#endif	
+}
+
+/*
+ * This is used for most PIO data transfers *from* the IDE interface
+ */
+static void 
+e100_ide_input_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+{
+	e100_atapi_input_bytes(drive, buffer, wcount << 2);
+}
+
+/*
+ * This is used for most PIO data transfers *to* the IDE interface
+ */
+static void
+e100_ide_output_data (ide_drive_t *drive, void *buffer, unsigned int wcount)
+{
+	e100_atapi_output_bytes(drive, buffer, wcount << 2);
+}
+
+/*
+ * The multiplexor for ide_xxxput_data and atapi calls
+ */
+static void 
+e100_ideproc (ide_ide_action_t func, ide_drive_t *drive,
+	      void *buffer, unsigned int length)
+{
+	switch (func) {
+		case ideproc_ide_input_data:
+			e100_ide_input_data(drive, buffer, length);
+			break;
+		case ideproc_ide_output_data:
+			e100_ide_input_data(drive, buffer, length);
+			break;
+		case ideproc_atapi_input_bytes:
+			e100_atapi_input_bytes(drive, buffer, length);
+			break;
+		case ideproc_atapi_output_bytes:
+			e100_atapi_output_bytes(drive, buffer, length);
+			break;
+		default:
+			printk("e100_ideproc: unsupported func %d!\n", func);
+			break;
+	}
+}
+
+/* we only have one DMA channel on the chip for ATA, so we can keep these statically */
+static etrax_dma_descr ata_descrs[MAX_DMA_DESCRS];
+static unsigned int ata_tot_size;
+
+/*
+ * e100_ide_build_dmatable() prepares a dma request.
+ * Returns 0 if all went okay, returns 1 otherwise.
+ */
+static int e100_ide_build_dmatable (ide_drive_t *drive)
+{
+	struct request *rq = HWGROUP(drive)->rq;
+	struct buffer_head *bh = rq->bh;
+	unsigned long size, addr;
+	unsigned int count = 0;
+
+	ata_tot_size = 0;
+
+	do {
+		/*
+		 * Determine addr and size of next buffer area.  We assume that
+		 * individual virtual buffers are always composed linearly in
+		 * physical memory.  For example, we assume that any 8kB buffer
+		 * is always composed of two adjacent physical 4kB pages rather
+		 * than two possibly non-adjacent physical 4kB pages.
+		 */
+		if (bh == NULL) {  /* paging and tape requests have (rq->bh == NULL) */
+			addr = virt_to_phys (rq->buffer);
+			size = rq->nr_sectors << 9;
+		} else {
+			/* group sequential buffers into one large buffer */
+			addr = virt_to_phys (bh->b_data);
+			size = bh->b_size;
+			while ((bh = bh->b_reqnext) != NULL) {
+				if ((addr + size) != virt_to_phys (bh->b_data))
+					break;
+				size += bh->b_size;
+			}
+		}
+
+		/* did we run out of descriptors? */
+
+		if(count >= MAX_DMA_DESCRS) {
+			printk("%s: too few DMA descriptors\n", drive->name);
+			return 1;
+		}
+
+		/* uh.. I'm lazy.. if size >= 65536, it should loop below and split it in
+		   more than one descriptor */
+
+		if(size >= 65536) {
+			printk("too large ATA DMA request block, size = %d!\n", size);
+			return 1;
+		}
+
+		/* however, this case is more difficult - R_ATA_TRANSFER_CNT cannot be more
+		   than 65536 words per transfer, so in that case we need to either 
+		   1) use a DMA interrupt to re-trigger R_ATA_TRANSFER_CNT and continue with
+		      the descriptors, or
+		   2) simply do the request here, and get dma_intr to only ide_end_request on 
+		      those blocks that were actually set-up for transfer.
+		*/
+
+		if(ata_tot_size + size >= 131072) {
+			printk("too large total ATA DMA request, %d + %d!\n", ata_tot_size, size);
+			return 1;
+		}
+
+		/* ok we want to do IO at addr, size bytes. set up a new descriptor entry */
+
+		ata_descrs[count].sw_len = size;
+		ata_descrs[count].ctrl = 0;
+		ata_descrs[count].buf = addr;
+		ata_descrs[count].next = virt_to_phys(&ata_descrs[count + 1]);
+		count++;
+		ata_tot_size += size;
+
+	} while (bh != NULL);
+
+	if (count) {
+		/* set the end-of-list flag on the last descriptor */
+		ata_descrs[count - 1].ctrl |= d_eol;
+		/* return and say all is ok */
+		return 0;
+	}
+
+	printk("%s: empty DMA table?\n", drive->name);
+	return 1;	/* let the PIO routines handle this weirdness */
+}
+
+static int config_drive_for_dma (ide_drive_t *drive)
+{
+        const char **list;
+        struct hd_driveid *id = drive->id;
+
+        if (id && (id->capability & 1)) {
+                /* Enable DMA on any drive that supports mword2 DMA */
+                if ((id->field_valid & 2) && (id->dma_mword & 0x404) == 0x404) {
+                        drive->using_dma = 1;
+                        return 0;               /* DMA enabled */
+                }
+
+                /* Consult the list of known "good" drives */
+                list = good_dma_drives;
+                while (*list) {
+                        if (!strcmp(*list++,id->model)) {
+                                drive->using_dma = 1;
+                                return 0;       /* DMA enabled */
+                        }
+                }
+        }
+        return 1;       /* DMA not enabled */
+}
+
+/*
+ * etrax_dma_intr() is the handler for disk read/write DMA interrupts
+ */
+static ide_startstop_t etrax_dma_intr (ide_drive_t *drive)
+{
+	int i, dma_stat;
+	byte stat;
+
+	LED_DISK_READ(0);
+	LED_DISK_WRITE(0);
+
+	dma_stat = HWIF(drive)->dmaproc(ide_dma_end, drive);
+	stat = GET_STAT();			/* get drive status */
+	if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) {
+		if (!dma_stat) {
+			struct request *rq;
+			rq = HWGROUP(drive)->rq;
+			for (i = rq->nr_sectors; i > 0;) {
+				i -= rq->current_nr_sectors;
+				ide_end_request(1, HWGROUP(drive));
+			}
+			return ide_stopped;
+		}
+		printk("%s: bad DMA status\n", drive->name);
+	}
+	return ide_error(drive, "dma_intr", stat);
+}
+
+/*
+ * e100_dmaproc() initiates/aborts DMA read/write operations on a drive.
+ *
+ * The caller is assumed to have selected the drive and programmed the drive's
+ * sector address using CHS or LBA.  All that remains is to prepare for DMA
+ * and then issue the actual read/write DMA/PIO command to the drive.
+ *
+ * For ATAPI devices, we just prepare for DMA and return. The caller should
+ * then issue the packet command to the drive and call us again with
+ * ide_dma_begin afterwards.
+ *
+ * Returns 0 if all went well.
+ * Returns 1 if DMA read/write could not be started, in which case
+ * the caller should revert to PIO for the current request.
+ */
+
+static int e100_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
+{
+        static unsigned int reading; /* static to support ide_dma_begin semantics */
+	int atapi = 0;
+
+	D(printk("e100_dmaproc func %d\n", func));
+
+        switch (func) {
+		case ide_dma_verbose:
+			return 0;
+                case ide_dma_check:
+                        return config_drive_for_dma (drive);
+		case ide_dma_off:
+		case ide_dma_off_quietly:
+			/* ok.. we don't really need to do anything I think. */
+			return 0;
+                case ide_dma_write:
+                        reading = 0;
+			break;
+                case ide_dma_read:
+			reading = 1;
+                        break;
+                case ide_dma_begin:
+			/* begin DMA, used by ATAPI devices which want to issue the 
+			 * appropriate IDE command themselves.
+			 *
+			 * they have already called ide_dma_read/write to set the
+			 * static reading flag, now they call ide_dma_begin to do
+			 * the real stuff. we tell our code below not to issue
+			 * any IDE commands itself and jump into it. 
+			 */
+			atapi++;
+			goto dma_begin;
+		case ide_dma_end: /* returns 1 on error, 0 otherwise */
+			/* TODO: check if something went wrong with the DMA */
+			return 0;
+
+                default:
+                        printk("e100_dmaproc: unsupported func %d\n", func);
+                        return 1;
+        }
+
+	/* ATAPI-devices (not disks) first call ide_dma_read/write to set the direction
+	 * then they call ide_dma_begin after they have issued the appropriate drive command
+	 * themselves to actually start the chipset DMA. so we just return here if we're
+	 * not a diskdrive.
+	 */
+
+        if (drive->media != ide_disk)
+                return 0;
+
+ dma_begin:
+
+	if(reading) {
+
+		RESET_DMA(3); /* sometimes the DMA channel get stuck so we need to do this */
+		WAIT_DMA(3);
+
+		/* set up the Etrax DMA descriptors */
+		
+		if(e100_ide_build_dmatable (drive))
+			return 1;
+
+		if(!atapi) {
+			/* set the irq handler which will finish the request when DMA is done */
+		
+			ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
+			
+			/* issue cmd to drive */
+			
+			OUT_BYTE(WIN_READDMA, IDE_COMMAND_REG);
+		}
+
+		/* begin DMA */
+	      
+		*R_DMA_CH3_FIRST = virt_to_phys(ata_descrs);
+		*R_DMA_CH3_CMD   = IO_STATE(R_DMA_CH3_CMD, cmd, start);
+		
+		/* initiate a multi word dma read using DMA handshaking */
+		
+		*R_ATA_TRANSFER_CNT = ata_tot_size >> 1;
+		
+		*R_ATA_CTRL_DATA = IDE_DATA_REG  |
+			IO_STATE(R_ATA_CTRL_DATA, rw,       read) |
+			IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma)  |
+			IO_STATE(R_ATA_CTRL_DATA, handsh,   dma)  |
+			IO_STATE(R_ATA_CTRL_DATA, multi,    on)   |
+			IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+
+		LED_DISK_READ(1);
+
+		D(printk("dma read of %d bytes.\n", ata_tot_size));
+ 
+	} else {
+		/* writing */
+
+		RESET_DMA(2); /* sometimes the DMA channel get stuck so we need to do this */
+		WAIT_DMA(2);
+
+		/* set up the Etrax DMA descriptors */
+
+		if(e100_ide_build_dmatable (drive))
+			return 1;
+
+		if(!atapi) {
+			/* set the irq handler which will finish the request when DMA is done */
+				
+			ide_set_handler(drive, &etrax_dma_intr, WAIT_CMD, NULL);
+			
+			/* issue cmd to drive */
+			
+			OUT_BYTE(WIN_WRITEDMA, IDE_COMMAND_REG);
+		}
+
+		/* begin DMA */
+		
+		*R_DMA_CH2_FIRST = virt_to_phys(ata_descrs);
+		*R_DMA_CH2_CMD   = IO_STATE(R_DMA_CH2_CMD, cmd, start);
+		
+		/* initiate a multi word dma write using DMA handshaking */
+		
+		*R_ATA_TRANSFER_CNT = ata_tot_size >> 1;
+		
+		*R_ATA_CTRL_DATA = IDE_DATA_REG |
+			IO_STATE(R_ATA_CTRL_DATA, rw,       write) |
+			IO_STATE(R_ATA_CTRL_DATA, src_dst,  dma) |
+			IO_STATE(R_ATA_CTRL_DATA, handsh,   dma) |
+			IO_STATE(R_ATA_CTRL_DATA, multi,    on) |
+			IO_STATE(R_ATA_CTRL_DATA, dma_size, word);
+
+		LED_DISK_WRITE(1);
+
+		D(printk("dma write of %d bytes.\n", ata_tot_size));
+	}
+
+	/* DMA started successfully */
+	return 0;
+}
+
+/* ide.c calls this, but we don't need to do anything particular */
+
+int ide_release_dma (ide_hwif_t *hwif)
+{
+	return 1;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/serial.c linux/arch/cris/drivers/serial.c
--- v2.4.1/linux/arch/cris/drivers/serial.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/serial.c	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,3039 @@
+/* $Id: serial.c,v 1.6 2000/11/22 16:36:09 bjornw Exp $
+ *
+ * Serial port driver for the ETRAX 100LX chip
+ *
+ *      Copyright (C) 1998, 1999, 2000  Axis Communications AB
+ *
+ *      Many, many authors. Based once upon a time on serial.c for 16x50.
+ *
+ * $Log: serial.c,v $
+ * Revision 1.6  2000/11/22 16:36:09  bjornw
+ * Please marketing by using the correct case when spelling Etrax.
+ *
+ * Revision 1.5  2000/11/21 16:43:37  bjornw
+ * Fixed so it compiles under CONFIG_SVINTO_SIM
+ *
+ * Revision 1.4  2000/11/15 17:34:12  bjornw
+ * Added a timeout timer for flushing input channels. The interrupt-based
+ * fast flush system should be easy to merge with this later (works the same
+ * way, only with an irq instead of a system timer_list)
+ *
+ * Revision 1.3  2000/11/13 17:19:57  bjornw
+ * * Incredibly, this almost complete rewrite of serial.c worked (at least
+ *   for output) the first time.
+ *
+ *   Items worth noticing:
+ *
+ *      No Etrax100 port 1 workarounds (does only compile on 2.4 anyway now)
+ *      RS485 is not ported (why cant it be done in userspace as on x86 ?)
+ *      Statistics done through async_icount - if any more stats are needed,
+ *      that's the place to put them or in an arch-dep version of it.
+ *      timeout_interrupt and the other fast timeout stuff not ported yet
+ *      There be dragons in this 3k+ line driver
+ *
+ * Revision 1.2  2000/11/10 16:50:28  bjornw
+ * First shot at a 2.4 port, does not compile totally yet
+ *
+ * Revision 1.1  2000/11/10 16:47:32  bjornw
+ * Added verbatim copy of rev 1.49 etrax100ser.c from elinux
+ *
+ * Revision 1.49  2000/10/30 15:47:14  tobiasa
+ * Changed version number.
+ *
+ * Revision 1.48  2000/10/25 11:02:43  johana
+ * Changed %ul to %lu in printf's
+ *
+ * Revision 1.47  2000/10/18 15:06:53  pkj
+ * Compile correctly with CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST and
+ * CONFIG_SERIAL_PROC_ENTRY together.
+ * Some clean-up of the /proc/serial file.
+ *
+ * Revision 1.46  2000/10/16 12:59:40  johana
+ * Added CONFIG_SERIAL_PROC_ENTRY for statistics and debug info.
+ *
+ * Revision 1.45  2000/10/13 17:10:59  pkj
+ * Do not flush DMAs while flipping TTY buffers.
+ *
+ * Revision 1.44  2000/10/13 16:34:29  pkj
+ * Added a delay in ser_interrupt() for 2.3ms when an error is detected.
+ * We do not know why this delay is required yet, but without it the
+ * irmaflash program does not work (this was the program that needed
+ * the ser_interrupt() to be needed in the first place). This should not
+ * affect normal use of the serial ports.
+ *
+ * Revision 1.43  2000/10/13 16:30:44  pkj
+ * New version of the fast flush of serial buffers code. This time
+ * it is localized to the serial driver and uses a fast timer to
+ * do the work.
+ *
+ * Revision 1.42  2000/10/13 14:54:26  bennyo
+ * Fix for switching RTS when using rs485
+ *
+ * Revision 1.41  2000/10/12 11:43:44  pkj
+ * Cleaned up a number of comments.
+ *
+ * Revision 1.40  2000/10/10 11:58:39  johana
+ * Made RS485 support generic for all ports.
+ * Toggle rts in interrupt if no delay wanted.
+ * WARNING: No true transmitter empty check??
+ * Set d_wait bit when sending data so interrupt is delayed until
+ * fifo flushed. (Fix tcdrain() problem)
+ *
+ * Revision 1.39  2000/10/04 16:08:02  bjornw
+ * * Use virt_to_phys etc. for DMA addresses
+ * * Removed CONFIG_FLUSH_DMA_FAST hacks
+ * * Indentation fix
+ *
+ * Revision 1.38  2000/10/02 12:27:10  mattias
+ * * added variable used when using fast flush on serial dma.
+ *   (CONFIG_FLUSH_DMA_FAST)
+ *
+ * Revision 1.37  2000/09/27 09:44:24  pkj
+ * Uncomment definition of SERIAL_HANDLE_EARLY_ERRORS.
+ *
+ * Revision 1.36  2000/09/20 13:12:52  johana
+ * Support for CONFIG_ETRAX100_SERIAL_RX_TIMEOUT_TICKS:
+ *   Number of timer ticks between flush of receive fifo (1 tick = 10ms).
+ *   Try 0-3 for low latency applications. Approx 5 for high load
+ *   applications (e.g. PPP). Maybe this should be more adaptive some day...
+ *
+ * Revision 1.35  2000/09/20 10:36:08  johana
+ * Typo in get_lsr_info()
+ *
+ * Revision 1.34  2000/09/20 10:29:59  johana
+ * Let rs_chars_in_buffer() check fifo content as well.
+ * get_lsr_info() might work now (not tested).
+ * Easier to change the port to debug.
+ *
+ * Revision 1.33  2000/09/13 07:52:11  torbjore
+ * Support RS485
+ *
+ * Revision 1.32  2000/08/31 14:45:37  bjornw
+ * After sending a break we need to reset the transmit DMA channel
+ *
+ * Revision 1.31  2000/06/21 12:13:29  johana
+ * Fixed wait for all chars sent when closing port.
+ * (Used to always take 1 second!)
+ * Added shadows for directions of status/ctrl signals.
+ *
+ * Revision 1.30  2000/05/29 16:27:55  bjornw
+ * Simulator ifdef moved a bit
+ *
+ * Revision 1.29  2000/05/09 09:40:30  mattias
+ * * Added description of dma registers used in timeout_interrupt
+ * * Removed old code
+ *
+ * Revision 1.28  2000/05/08 16:38:58  mattias
+ * * Bugfix for flushing fifo in timeout_interrupt
+ *   Problem occurs when bluetooth stack waits for a small number of bytes
+ *   containing an event acknowledging free buffers in bluetooth HW
+ *   As before, data was stuck in fifo until more data came on uart and
+ *   flushed it up to the stack.
+ *
+ * Revision 1.27  2000/05/02 09:52:28  jonasd
+ * Added fix for peculiar etrax behaviour when eop is forced on an empty
+ * fifo. This is used when flashing the IRMA chip. Disabled by default.
+ *
+ * Revision 1.26  2000/03/29 15:32:02  bjornw
+ * 2.0.34 updates
+ *
+ * Revision 1.25  2000/02/16 16:59:36  bjornw
+ * * Receive DMA directly into the flip-buffer, eliminating an intermediary
+ *   receive buffer and a memcpy. Will avoid some overruns.
+ * * Error message on debug port if an overrun or flip buffer overrun occurs.
+ * * Just use the first byte in the flag flip buffer for errors.
+ * * Check for timeout on the serial ports only each 5/100 s, not 1/100.
+ *
+ * Revision 1.24  2000/02/09 18:02:28  bjornw
+ * * Clear serial errors (overrun, framing, parity) correctly. Before, the
+ *   receiver would get stuck if an error occured and we did not restart
+ *   the input DMA.
+ * * Cosmetics (indentation, some code made into inlines)
+ * * Some more debug options
+ * * Actually shut down the serial port (DMA irq, DMA reset, receiver stop)
+ *   when the last open is closed. Corresponding fixes in startup().
+ * * rs_close() "tx FIFO wait" code moved into right place, bug & -> && fixed
+ *   and make a special case out of port 1 (R_DMA_CHx_STATUS is broken for that)
+ * * e100_disable_rx/enable_rx just disables/enables the receiver, not RTS
+ *
+ * Revision 1.23  2000/01/24 17:46:19  johana
+ * Wait for flush of DMA/FIFO when closing port.
+ *
+ * Revision 1.22  2000/01/20 18:10:23  johana
+ * Added TIOCMGET ioctl to return modem status.
+ * Implemented modem status/control that works with the extra signals
+ * (DTR, DSR, RI,CD) as well.
+ * 3 different modes supported:
+ * ser0 on PB (Bundy), ser1 on PB (Lisa) and ser2 on PA (Bundy)
+ * Fixed DEF_TX value that caused the serial transmitter pin (txd) to go to 0 when
+ * closing the last filehandle, NASTY!.
+ * Added break generation, not tested though!
+ * Use SA_SHIRQ when request_irq() for ser2 and ser3 (shared with) par0 and par1.
+ * You can't use them at the same time (yet..), but you can hopefully switch
+ * between ser2/par0, ser3/par1 with the same kernel config.
+ * Replaced some magic constants with defines
+ *
+ *
+ */
+
+static char *serial_version = "$Revision: 1.6 $";
+
+#include <linux/config.h>
+#include <linux/version.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/major.h>
+#include <linux/string.h>
+#include <linux/fcntl.h>
+#include <linux/mm.h>
+#if (LINUX_VERSION_CODE >= 131343)
+#include <linux/init.h>
+#endif
+#if (LINUX_VERSION_CODE >= 131336)
+#include <asm/uaccess.h>
+#endif
+#include <linux/kernel.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/bitops.h>
+#include <asm/delay.h>
+
+#include <asm/svinto.h>
+
+/* non-arch dependant serial structures are in linux/serial.h */
+#include <linux/serial.h>
+/* while we keep our own stuff (struct e100_serial) in a local .h file */
+#include "serial.h"
+
+/*
+ * All of the compatibilty code so we can compile serial.c against
+ * older kernels is hidden in serial_compat.h
+ */
+#if defined(LOCAL_HEADERS) || (LINUX_VERSION_CODE < 0x020317) /* 2.3.23 */
+#include "serial_compat.h"
+#endif
+
+static DECLARE_TASK_QUEUE(tq_serial);
+
+struct tty_driver serial_driver, callout_driver;
+static int serial_refcount;
+
+/* serial subtype definitions */
+#ifndef SERIAL_TYPE_NORMAL
+#define SERIAL_TYPE_NORMAL	1
+#define SERIAL_TYPE_CALLOUT	2
+#endif
+
+/* number of characters left in xmit buffer before we ask for more */
+#define WAKEUP_CHARS 256
+
+//#define SERIAL_DEBUG_INTR
+//#define SERIAL_DEBUG_OPEN 
+//#define SERIAL_DEBUG_FLOW
+//#define SERIAL_DEBUG_DATA
+//#define SERIAL_DEBUG_THROTTLE
+//#define SERIAL_DEBUG_IO  /* Debug for Extra control and status pins */
+#define SERIAL_DEBUG_LINE 0 /* What serport we want to debug */
+
+/* Enable this to use serial interrupts to handle when you
+   expect the first received event on the serial port to
+   be an error, break or similar. Used to be able to flash IRMA
+   from eLinux */
+//#define SERIAL_HANDLE_EARLY_ERRORS
+
+
+#ifndef CONFIG_ETRAX100_SERIAL_RX_TIMEOUT_TICKS
+/* Default number of timer ticks before flushing rx fifo 
+ * When using "little data, low latency applications: use 0
+ * When using "much data applications (PPP)" use ~5
+ */
+#define CONFIG_ETRAX100_SERIAL_RX_TIMEOUT_TICKS 5 
+#endif
+
+#define MAX_FLUSH_TIME 8
+
+#define _INLINE_ inline
+
+static void change_speed(struct e100_serial *info);
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
+static int rs_write(struct tty_struct * tty, int from_user,
+                    const unsigned char *buf, int count);
+
+#define DEF_BAUD 0x99   /* 115.2 kbit/s */
+#define STD_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST )
+#define DEF_RX 0x20  /* or SERIAL_CTRL_W >> 8 */
+/* Default value of tx_ctrl register: has txd(bit 7)=1 (idle) as default */
+#define DEF_TX 0x80  /* or SERIAL_CTRL_B */
+
+/* offsets from R_SERIALx_CTRL */
+
+#define REG_DATA 0
+#define REG_TR_DATA 0
+#define REG_STATUS 1
+#define REG_TR_CTRL 1
+#define REG_REC_CTRL 2
+#define REG_BAUD 3
+#define REG_XOFF 4  /* this is a 32 bit register */
+
+/* this is the data for the four serial ports in the etrax100 */
+/*  DMA2(ser2), DMA4(ser3), DMA6(ser0) or DMA8(ser1) */
+/* R_DMA_CHx_CLR_INTR, R_DMA_CHx_FIRST, R_DMA_CHx_CMD */
+
+static struct e100_serial rs_table[] = {
+	{ DEF_BAUD, (unsigned char *)R_SERIAL0_CTRL, 1U << 12, /* uses DMA 6 and 7 */
+	  R_DMA_CH6_CLR_INTR, R_DMA_CH6_FIRST, R_DMA_CH6_CMD,
+	  R_DMA_CH6_STATUS, R_DMA_CH6_HWSW,
+	  R_DMA_CH7_CLR_INTR, R_DMA_CH7_FIRST, R_DMA_CH7_CMD,
+	  R_DMA_CH7_STATUS, R_DMA_CH7_HWSW,
+	  STD_FLAGS, DEF_RX, DEF_TX, 2 },  /* ttyS0 */
+#ifndef CONFIG_SVINTO_SIM
+	{ DEF_BAUD, (unsigned char *)R_SERIAL1_CTRL, 1U << 16, /* uses DMA 8 and 9 */
+	  R_DMA_CH8_CLR_INTR, R_DMA_CH8_FIRST, R_DMA_CH8_CMD,
+	  R_DMA_CH8_STATUS, R_DMA_CH8_HWSW,
+	  R_DMA_CH9_CLR_INTR, R_DMA_CH9_FIRST, R_DMA_CH9_CMD,
+	  R_DMA_CH9_STATUS, R_DMA_CH9_HWSW,
+	  STD_FLAGS, DEF_RX, DEF_TX, 3 },  /* ttyS1 */
+
+	{ DEF_BAUD, (unsigned char *)R_SERIAL2_CTRL, 1U << 4,  /* uses DMA 2 and 3 */
+	  R_DMA_CH2_CLR_INTR, R_DMA_CH2_FIRST, R_DMA_CH2_CMD,
+	  R_DMA_CH2_STATUS, R_DMA_CH2_HWSW,
+	  R_DMA_CH3_CLR_INTR, R_DMA_CH3_FIRST, R_DMA_CH3_CMD,
+	  R_DMA_CH3_STATUS, R_DMA_CH3_HWSW,
+	  STD_FLAGS, DEF_RX, DEF_TX, 0 },  /* ttyS2 */
+
+	{ DEF_BAUD, (unsigned char *)R_SERIAL3_CTRL, 1U << 8,  /* uses DMA 4 and 5 */
+	  R_DMA_CH4_CLR_INTR, R_DMA_CH4_FIRST, R_DMA_CH4_CMD,
+	  R_DMA_CH4_STATUS, R_DMA_CH4_HWSW,
+	  R_DMA_CH5_CLR_INTR, R_DMA_CH5_FIRST, R_DMA_CH5_CMD,
+	  R_DMA_CH5_STATUS, R_DMA_CH5_HWSW,
+	  STD_FLAGS, DEF_RX, DEF_TX, 1 }   /* ttyS3 */
+#endif
+};
+
+
+#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
+  
+static struct tty_struct *serial_table[NR_PORTS]; 
+static struct termios *serial_termios[NR_PORTS];
+static struct termios *serial_termios_locked[NR_PORTS];
+
+
+/* RS-485 */
+#if defined(CONFIG_RS485)
+#if defined(CONFIG_RS485_ON_PA)
+static int rs485_pa_bit = CONFIG_RS485_ON_PA_BIT;
+#endif
+#endif
+  
+
+/* For now we assume that all bits are on the same port for each serial port */
+
+/* Dummy shadow variables */
+static unsigned char dummy_ser0 = 0x00;
+static unsigned char dummy_ser1 = 0x00;
+static unsigned char dummy_ser2 = 0x00;
+static unsigned char dummy_ser3 = 0x00;
+
+static unsigned char dummy_dir_ser0 = 0x00;
+static unsigned char dummy_dir_ser1 = 0x00;
+static unsigned char dummy_dir_ser2 = 0x00;
+static unsigned char dummy_dir_ser3 = 0x00;
+
+/* Info needed for each ports extra control/status signals.
+   We only supports that all pins uses same register for each port */
+struct control_pins
+{
+	volatile unsigned char *port;
+	volatile unsigned char *shadow;
+	volatile unsigned char *dir_shadow;
+	
+	unsigned char dtr_bit;
+	unsigned char ri_bit;
+	unsigned char dsr_bit;
+	unsigned char cd_bit;
+};
+
+static const struct control_pins e100_modem_pins[NR_PORTS] = 
+{
+/* Ser 0 */
+  {
+#if defined(CONFIG_ETRAX100_SER0_DTR_RI_DSR_CD_ON_PB)
+    R_PORT_PB_DATA,  &port_pb_data_shadow,  &port_pb_dir_shadow,
+    CONFIG_ETRAX100_SER0_DTR_ON_PB_BIT,
+	  CONFIG_ETRAX100_SER0_RI_ON_PB_BIT, 
+	  CONFIG_ETRAX100_SER0_DSR_ON_PB_BIT, 
+	  CONFIG_ETRAX100_SER0_CD_ON_PB_BIT
+#else
+    &dummy_ser0, &dummy_ser0, &dummy_dir_ser0, 0, 1, 2, 3
+#endif   
+  },
+/* Ser 1 */
+  {
+#if defined(CONFIG_ETRAX100_SER1_DTR_RI_DSR_CD_ON_PB)
+    R_PORT_PB_DATA,  &port_pb_data_shadow,  &port_pb_dir_shadow,
+    CONFIG_ETRAX100_SER1_DTR_ON_PB_BIT,
+	  CONFIG_ETRAX100_SER1_RI_ON_PB_BIT, 
+	  CONFIG_ETRAX100_SER1_DSR_ON_PB_BIT, 
+	  CONFIG_ETRAX100_SER1_CD_ON_PB_BIT
+#else
+    &dummy_ser1, &dummy_ser1, &dummy_dir_ser1, 0, 1, 2, 3
+#endif   
+  },  
+/* Ser 2 */
+  {
+#if defined(CONFIG_ETRAX100_SER2_DTR_RI_DSR_CD_ON_PA)
+    R_PORT_PA_DATA,  &port_pa_data_shadow,  &port_pa_dir_shadow,
+    CONFIG_ETRAX100_SER2_DTR_ON_PA_BIT,
+	  CONFIG_ETRAX100_SER2_RI_ON_PA_BIT, 
+	  CONFIG_ETRAX100_SER2_DSR_ON_PA_BIT, 
+	  CONFIG_ETRAX100_SER2_CD_ON_PA_BIT
+#else
+    &dummy_ser2, &dummy_ser2, &dummy_dir_ser2, 0, 1, 2, 3
+#endif   
+  },
+/* Ser 3 */
+  {
+    &dummy_ser3, &dummy_ser3, &dummy_dir_ser3, 0, 1, 2, 3
+  }
+};
+
+#if defined(CONFIG_RS485) && defined(CONFIG_RS485_ON_PA)
+unsigned char rs485_pa_port = CONFIG_RS485_ON_PA_BIT;
+#endif
+
+#define E100_RTS_MASK 0x20
+#define E100_CTS_MASK 0x40
+
+
+/* All serial port signals are active low:
+ * active   = 0 -> 3.3V to RS-232 driver -> -12V on RS-232 level
+ * inactive = 1 -> 0V   to RS-232 driver -> +12V on RS-232 level
+ *
+ * These macros returns the pin value: 0=0V, >=1 = 3.3V on ETRAX chip
+ */
+
+/* Output */
+#define E100_RTS_GET(info) ((info)->rx_ctrl & E100_RTS_MASK)
+/* Input */
+#define E100_CTS_GET(info) ((info)->port[REG_STATUS] & E100_CTS_MASK)
+
+/* These are typically PA or PB and 0 means 0V, 1 means 3.3V */
+/* Is an output */
+#define E100_DTR_GET(info) ((*e100_modem_pins[(info)->line].shadow) & (1 << e100_modem_pins[(info)->line].dtr_bit))
+
+/* Normally inputs */
+#define E100_RI_GET(info) ((*e100_modem_pins[(info)->line].port) & (1 << e100_modem_pins[(info)->line].ri_bit))
+#define E100_CD_GET(info) ((*e100_modem_pins[(info)->line].port) & (1 << e100_modem_pins[(info)->line].cd_bit))
+
+/* Input */
+#define E100_DSR_GET(info) ((*e100_modem_pins[(info)->line].port) & (1 << e100_modem_pins[(info)->line].dsr_bit))
+
+
+#ifndef MIN
+#define MIN(a,b)	((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * tmp_buf is used as a temporary buffer by serial_write.  We need to
+ * lock it in case the memcpy_fromfs blocks while swapping in a page,
+ * and some other program tries to do a serial write at the same time.
+ * Since the lock will only come under contention when the system is
+ * swapping and available memory is low, it makes sense to share one
+ * buffer across all the serial ports, since it significantly saves
+ * memory if large numbers of serial ports are open.
+ */
+static unsigned char *tmp_buf;
+#ifdef DECLARE_MUTEX
+static DECLARE_MUTEX(tmp_buf_sem);
+#else
+static struct semaphore tmp_buf_sem = MUTEX;
+#endif
+
+#ifdef CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST
+#define TIMER1_IRQ_NBR 3
+
+/* clock select 10 for timer 1 gives 230400 Hz */
+#define FASTTIMER_SELECT (10)
+/* we use a source of 230400 Hz and a divider of 15 => 15360 Hz */
+#define FASTTIMER_DIV (15)
+
+/* fast flush timer stuff */
+static int fast_timer_started = 0;
+static unsigned long int fast_timer_ints = 0;
+
+static void _INLINE_ start_flush_timer(void)
+{
+	if (fast_timer_started)
+		return;
+
+	*R_TIMER_CTRL = r_timer_ctrl_shadow = 
+		(r_timer_ctrl_shadow &
+		 ~IO_MASK(R_TIMER_CTRL, timerdiv1) &
+		 ~IO_MASK(R_TIMER_CTRL, tm1) &
+		 ~IO_MASK(R_TIMER_CTRL, clksel1)) | 
+		IO_FIELD(R_TIMER_CTRL, timerdiv1, FASTTIMER_DIV) |
+		IO_STATE(R_TIMER_CTRL, tm1, stop_ld) | 
+		IO_FIELD(R_TIMER_CTRL, clksel1, FASTTIMER_SELECT);
+
+	*R_TIMER_CTRL = r_timer_ctrl_shadow = 
+		(r_timer_ctrl_shadow & ~IO_MASK(R_TIMER_CTRL, tm1)) |
+		IO_STATE(R_TIMER_CTRL, tm1, run);
+
+	/* enable timer1 irq */
+
+	*R_IRQ_MASK0_SET = IO_STATE(R_IRQ_MASK0_SET, timer1, set);
+	fast_timer_started = 1;
+}
+#endif /* CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST */
+
+/*
+ * This function maps from the Bxxxx defines in asm/termbits.h into real
+ * baud rates.
+ */
+
+static int 
+cflag_to_baud(unsigned int cflag)
+{
+	static int baud_table[] = {
+		0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
+		4800, 9600, 19200, 38400 };
+	
+	static int ext_baud_table[] = {
+		0, 57600, 115200, 230400, 460800, 921600, 1843200, 6250000 };
+	
+	if(cflag & CBAUDEX)
+		return ext_baud_table[(cflag & CBAUD) & ~CBAUDEX];
+	else 
+		return baud_table[cflag & CBAUD];
+}
+
+/* and this maps to an etrax100 hardware baud constant */
+
+static unsigned char 
+cflag_to_etrax_baud(unsigned int cflag)
+{
+	char retval;
+	
+	static char baud_table[] = {
+		-1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, 3, 4, 5, 6, 7 };
+	
+	static char ext_baud_table[] = {
+		-1, 8, 9, 10, 11, 12, 13, 14 };
+	
+	if(cflag & CBAUDEX)
+		retval = ext_baud_table[(cflag & CBAUD) & ~CBAUDEX];
+	else 
+		retval = baud_table[cflag & CBAUD];
+	
+	if(retval < 0) {
+		printk("serdriver tried setting invalid baud rate, flags %x.\n", cflag);
+		retval = 5; /* choose default 9600 instead */
+	}
+
+	return retval | (retval << 4); /* choose same for both TX and RX */
+}
+
+
+/* Various static support functions */
+
+/* Functions to set or clear DTR/RTS on the requested line */
+/* It is complicated by the fact that RTS is a serial port register, while
+ * DTR might not be implemented in the HW at all, and if it is, it can be on
+ * any general port.
+ */
+
+static inline void 
+e100_dtr(struct e100_serial *info, int set)
+{
+#ifndef CONFIG_SVINTO_SIM
+	unsigned char mask  = ( 1 << e100_modem_pins[info->line].dtr_bit);
+#ifdef SERIAL_DEBUG_IO  
+	printk("ser%i dtr %i mask: 0x%02X\n", info->line, set, mask);
+	printk("ser%i shadow before 0x%02X get: %i\n", 
+	       info->line, *e100_modem_pins[info->line].shadow,
+	       E100_DTR_GET(info));
+#endif
+	/* DTR is active low */
+	{
+		unsigned long flags;	
+		save_flags(flags);
+		cli();
+		*e100_modem_pins[info->line].shadow &= ~mask;
+		*e100_modem_pins[info->line].shadow |= (set ? 0 : mask); 
+		*e100_modem_pins[info->line].port = *e100_modem_pins[info->line].shadow;
+		restore_flags(flags);
+	}
+	
+#if 0
+	REG_SHADOW_SET(e100_modem_pins[info->line].port,
+		       *e100_modem_pins[info->line].shadow,
+		       e100_modem_pins[info->line].dtr_bit, !set);
+#endif
+#ifdef SERIAL_DEBUG_IO
+	printk("ser%i shadow after 0x%02X get: %i\n", 
+	       info->line, *e100_modem_pins[info->line].shadow, 
+	       E100_DTR_GET(info));
+#endif
+#endif
+}
+
+/* set = 0 means 3.3V on the pin, bitvalue: 0=active, 1=inactive  
+ *                                          0=0V    , 1=3.3V
+ */
+static inline void 
+e100_rts(struct e100_serial *info, int set)
+{
+#ifndef CONFIG_SVINTO_SIM
+#ifdef SERIAL_DEBUG_IO  
+	printk("ser%i rts %i\n", info->line, set);
+#endif
+	info->rx_ctrl &= ~E100_RTS_MASK;
+	info->rx_ctrl |= (set ? 0 : E100_RTS_MASK);  /* RTS is active low */
+	info->port[REG_REC_CTRL] = info->rx_ctrl;
+#endif
+}
+
+/* If this behaves as a modem, RI and CD is an output */
+static inline void 
+e100_ri_out(struct e100_serial *info, int set)
+{
+#ifndef CONFIG_SVINTO_SIM
+	/* RI is active low */
+	{
+		unsigned char mask  = ( 1 << e100_modem_pins[info->line].ri_bit);
+		unsigned long flags;	
+		save_flags(flags);
+		cli();
+		*e100_modem_pins[info->line].shadow &= ~mask;
+		*e100_modem_pins[info->line].shadow |= (set ? 0 : mask); 
+		*e100_modem_pins[info->line].port = *e100_modem_pins[info->line].shadow;
+		restore_flags(flags);
+	}
+#if 0
+	REG_SHADOW_SET(e100_modem_pins[info->line].port,
+		       *e100_modem_pins[info->line].shadow,
+		       e100_modem_pins[info->line].ri_bit, !set);
+#endif
+#endif
+}
+static inline void 
+e100_cd_out(struct e100_serial *info, int set)
+{
+#ifndef CONFIG_SVINTO_SIM
+	/* CD is active low */
+	{
+		unsigned char mask  = ( 1 << e100_modem_pins[info->line].cd_bit);
+		unsigned long flags;	
+		save_flags(flags);
+		cli();
+		*e100_modem_pins[info->line].shadow &= ~mask;
+		*e100_modem_pins[info->line].shadow |= (set ? 0 : mask); 
+		*e100_modem_pins[info->line].port = *e100_modem_pins[info->line].shadow;
+		restore_flags(flags);
+	}
+#if 0
+	REG_SHADOW_SET(e100_modem_pins[info->line].port,
+		       *e100_modem_pins[info->line].shadow,
+		       e100_modem_pins[info->line].cd_bit, !set);
+#endif
+#endif
+}
+
+static inline void
+e100_disable_rx(struct e100_serial *info)
+{
+#ifndef CONFIG_SVINTO_SIM
+	/* disable the receiver */
+	info->port[REG_REC_CTRL] = (info->rx_ctrl &= ~0x40);
+#endif
+}
+
+static inline void 
+e100_enable_rx(struct e100_serial *info)
+{
+#ifndef CONFIG_SVINTO_SIM
+	/* enable the receiver */
+	info->port[REG_REC_CTRL] = (info->rx_ctrl |= 0x40);
+#endif
+}
+
+/* the rx DMA uses both the dma_descr and the dma_eop interrupts */
+
+static inline void
+e100_disable_rxdma_irq(struct e100_serial *info) 
+{
+#ifdef SERIAL_DEBUG_INTR
+	printk("rxdma_irq(%d): 0\n",info->line);
+#endif
+	*R_IRQ_MASK2_CLR = (info->irq << 2) | (info->irq << 3);
+}
+
+static inline void
+e100_enable_rxdma_irq(struct e100_serial *info) 
+{
+#ifdef SERIAL_DEBUG_INTR
+	printk("rxdma_irq(%d): 1\n",info->line);
+#endif
+	*R_IRQ_MASK2_SET = (info->irq << 2) | (info->irq << 3);
+}
+
+/* the tx DMA uses only dma_descr interrupt */
+
+static inline void
+e100_disable_txdma_irq(struct e100_serial *info) 
+{
+#ifdef SERIAL_DEBUG_INTR
+	printk("txdma_irq(%d): 0\n",info->line);
+#endif
+	*R_IRQ_MASK2_CLR = info->irq;
+}
+
+static inline void
+e100_enable_txdma_irq(struct e100_serial *info) 
+{
+#ifdef SERIAL_DEBUG_INTR
+	printk("txdma_irq(%d): 1\n",info->line);
+#endif
+	*R_IRQ_MASK2_SET = info->irq;
+}
+
+#ifdef SERIAL_HANDLE_EARLY_ERRORS
+/* in order to detect and fix errors on the first byte
+ we have to use the serial interrupts as well. */
+
+static inline void
+e100_disable_serial_data_irq(struct e100_serial *info) 
+{
+#ifdef SERIAL_DEBUG_INTR
+	printk("ser_irq(%d): 0\n",info->line);
+#endif
+	*R_IRQ_MASK1_CLR = (1U << (8+2*info->line));
+}
+
+static inline void
+e100_enable_serial_data_irq(struct e100_serial *info) 
+{
+#ifdef SERIAL_DEBUG_INTR
+	printk("ser_irq(%d): 1\n",info->line);
+	printk("**** %d = %d\n",
+	       (8+2*info->line),
+	       (1U << (8+2*info->line)));
+#endif
+	*R_IRQ_MASK1_SET = (1U << (8+2*info->line));
+}
+#endif
+
+#if defined(CONFIG_RS485)
+/* Enable RS-485 mode on selected port. This is UGLY. */
+static int
+e100_enable_rs485(struct tty_struct *tty,struct rs485_control *r)
+{
+	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+
+#if defined(CONFIG_RS485_ON_PA)	
+	*R_PORT_PA_DATA = port_pa_data_shadow |= (1 << rs485_pa_bit);
+#endif
+
+	info->rs485.rts_on_send = 0x01 & r->rts_on_send;
+	info->rs485.rts_after_sent = 0x01 & r->rts_after_sent;
+	info->rs485.delay_rts_before_send = r->delay_rts_before_send;
+	info->rs485.enabled = r->enabled;
+	
+	return 0;
+}
+
+/* Enable RS-485 mode on selected port. This is UGLY. */
+static int
+e100_write_rs485(struct tty_struct *tty,struct rs485_write *r)
+{
+	int stop_delay;
+	int total, i;
+	int max_j, delay_ms, bits;
+	tcflag_t cflags;
+	int size = (*r).outc_size;
+	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+	struct wait_queue wait = { current, NULL };
+
+	/* If we are in RS-485 mode, we need to toggle RTS and disable
+	 * the receiver before initiating a DMA transfer
+	 */
+	e100_rts(info, info->rs485.rts_on_send);
+#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+	e100_disable_rx(info);
+	e100_disable_rxdma_irq(info);
+#endif
+
+	if (info->rs485.delay_rts_before_send > 0){
+		current->timeout = jiffies + (info->rs485.delay_rts_before_send * HZ)/1000;
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		current->timeout = 0;
+	}
+	total = rs_write(tty, 1, (*r).outc, (*r).outc_size);
+
+	/* If we are in RS-485 mode the following things has to be done:
+	 * wait until DMA is ready
+	 * wait on transmit shift register
+	 * wait to toggle RTS
+	 * enable the receiver
+	 */	
+
+	/* wait on transmit shift register */
+	/* All is sent, check if we should wait more before toggling rts */
+	
+	/* calc. number of bits / data byte */
+	cflags = info->tty->termios->c_cflag;
+	/* databits + startbit and 1 stopbit */
+	if((cflags & CSIZE) == CS7) 
+	  bits = 9;
+	else
+	  bits = 10;  
+
+	if(cflags & CSTOPB)     /* 2 stopbits ? */
+	  bits++;
+
+	if(cflags & PARENB)     /* parity bit ? */
+	  bits++;
+	
+	/* calc timeout */
+	delay_ms = ((bits * size * 1000) / info->baud) + 1;
+	max_j = jiffies + (delay_ms * HZ)/1000 + 10;
+
+	while (jiffies < max_j ) {
+	  if (info->port[REG_STATUS] & 0x20) {
+	    for( i=0 ; i<100; i++ ) {};
+	    if (info->port[REG_STATUS] & 0x20) {
+	      /* ~25 for loops per usec */
+	      stop_delay = 25 * (1000000 / info->baud);
+	      if(cflags & CSTOPB) 
+		stop_delay *= 2;
+	      for( i=0 ; i<stop_delay; i++ ) {};
+	      break;
+	    }
+	  }
+	}
+
+	e100_rts(info, info->rs485.rts_after_sent);
+	
+#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+	e100_enable_rx(info);
+	e100_enable_rxdma_irq(info);
+#endif
+
+	return total;
+}
+#endif
+
+/*
+ * ------------------------------------------------------------
+ * rs_stop() and rs_start()
+ *
+ * This routines are called before setting or resetting tty->stopped.
+ * They enable or disable transmitter interrupts, as necessary.
+ * ------------------------------------------------------------
+ */
+
+/* FIXME - when are these used and what is the purpose ? 
+ * In rs_stop we probably just can block the transmit DMA ready irq
+ * and in rs_start we re-enable it (and then the old one will come).
+ */
+
+static void 
+rs_stop(struct tty_struct *tty)
+{
+}
+
+static void 
+rs_start(struct tty_struct *tty)
+{
+}
+
+/*
+ * ----------------------------------------------------------------------
+ *
+ * Here starts the interrupt handling routines.  All of the following
+ * subroutines are declared as inline and are folded into
+ * rs_interrupt().  They were separated out for readability's sake.
+ *
+ * Note: rs_interrupt() is a "fast" interrupt, which means that it
+ * runs with interrupts turned off.  People who may want to modify
+ * rs_interrupt() should try to keep the interrupt handler as fast as
+ * possible.  After you are done making modifications, it is not a bad
+ * idea to do:
+ * 
+ * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
+ *
+ * and look at the resulting assemble code in serial.s.
+ *
+ * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
+ * -----------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used by the interrupt handler to schedule
+ * processing in the software interrupt portion of the driver.
+ */
+static _INLINE_ void 
+rs_sched_event(struct e100_serial *info,
+				    int event)
+{
+	info->event |= 1 << event;
+	queue_task(&info->tqueue, &tq_serial);
+	mark_bh(SERIAL_BH);
+}
+
+/* The output DMA channel is free - use it to send as many chars as possible
+ * NOTES:
+ *   We don't pay attention to info->x_char, which means if the TTY wants to
+ *   use XON/XOFF it will set info->x_char but we won't send any X char!
+ * 
+ *   To implement this, we'd just start a DMA send of 1 byte pointing at a
+ *   buffer containing the X char, and skip updating xmit. We'd also have to
+ *   check if the last sent char was the X char when we enter this function
+ *   the next time, to avoid updating xmit with the sent X value.
+ */
+
+static void 
+transmit_chars(struct e100_serial *info)
+{
+	unsigned int c, sentl;
+	struct etrax_dma_descr *descr;
+
+#ifdef CONFIG_SVINTO_SIM
+	/* This will output too little if tail is not 0 always since
+	 * we don't reloop to send the other part. Anyway this SHOULD be a
+	 * no-op - transmit_chars would never really be called during sim
+	 * since rs_write does not write into the xmit buffer then.
+	 */
+	if(info->xmit.tail)
+		printk("Error in serial.c:transmit_chars(), tail!=0\n");
+	if(info->xmit.head != info->xmit.tail) {
+		SIMCOUT(info->xmit.buf + info->xmit.tail,
+			CIRC_CNT(info->xmit.head,
+				 info->xmit.tail,
+				 SERIAL_XMIT_SIZE));
+		info->xmit.head = info->xmit.tail;  /* move back head */
+		info->tr_running = 0;
+	}
+	return;
+#endif
+	/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
+	*info->oclrintradr = 3;
+
+#ifdef SERIAL_DEBUG_INTR
+	if(info->line == SERIAL_DEBUG_LINE)
+		printk("tc\n");
+#endif
+	if(!info->tr_running) {
+		/* weirdo... we shouldn't get here! */
+		printk("Achtung: transmit_chars with !tr_running\n");
+		return;
+	}
+
+	descr = &info->tr_descr;
+
+	/* first get the amount of bytes sent during the last DMA transfer,
+	   and update xmit accordingly */
+
+	/* if the stop bit was not set, all data has been sent */
+	if(!(descr->status & d_stop)) {
+		sentl = descr->sw_len;
+	} else 
+		/* otherwise we find the amount of data sent here */
+		sentl = descr->hw_len;
+
+	/* update stats */
+	info->icount.tx += sentl;
+
+	/* update xmit buffer */
+	info->xmit.tail = (info->xmit.tail + sentl) & (SERIAL_XMIT_SIZE - 1);
+
+	/* if there is only a few chars left in the buf, wake up the blocked
+	   write if any */
+	if (CIRC_CNT(info->xmit.head,
+		     info->xmit.tail,
+		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
+		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
+
+	/* find out the largest amount of consecutive bytes we want to send now */
+
+	c = CIRC_CNT_TO_END(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+
+	if(c <= 0) {
+		/* our job here is done, don't schedule any new DMA transfer */
+		info->tr_running = 0;
+
+#if defined(CONFIG_RS485)
+		/* Check if we should toggle RTS now */
+		if (info->rs485.enabled)
+		{
+			/* Make sure fifo is empty */
+			int in_fifo = 0 ;
+			do{
+				in_fifo = (*info->ostatusadr) & 0x007F ;
+			}  while (in_fifo > 0) ;
+			/* Any way to really check transmitter empty? (TEMT) */
+			/* Control RTS to set to RX mode */
+			e100_rts(info, info->rs485.rts_after_sent); 
+#if defined(CONFIG_RS485_DISABLE_RECEIVER)
+			e100_enable_rx(info);
+			e100_enable_rxdma_irq(info);
+#endif
+		}
+#endif /* RS485 */
+
+		return;
+	}
+
+	/* ok we can schedule a dma send of c chars starting at info->xmit.tail */
+	/* set up the descriptor correctly for output */
+
+	descr->ctrl = d_int | d_eol | d_wait; /* Wait needed for tty_wait_until_sent() */
+	descr->sw_len = c;
+	descr->buf = virt_to_phys(info->xmit.buf + info->xmit.tail);
+	descr->status = 0;
+
+	*info->ofirstadr = virt_to_phys(descr); /* write to R_DMAx_FIRST */
+	*info->ocmdadr = 1;       /* dma command start -> R_DMAx_CMD */
+	
+	/* DMA is now running (hopefully) */
+
+}
+
+static void 
+start_transmit(struct e100_serial *info)
+{
+#if 0
+	if(info->line == SERIAL_DEBUG_LINE)
+		printk("x\n");
+#endif
+
+	info->tr_descr.sw_len = 0;
+	info->tr_descr.hw_len = 0;
+	info->tr_descr.status = 0;
+	info->tr_running = 1;
+
+	transmit_chars(info);
+}
+
+
+static _INLINE_ void 
+receive_chars(struct e100_serial *info)
+{
+	struct tty_struct *tty;
+	unsigned char rstat;
+	unsigned int recvl;
+	struct etrax_dma_descr *descr;
+
+#ifdef CONFIG_SVINTO_SIM
+	/* No receive in the simulator.  Will probably be when the rest of
+	 * the serial interface works, and this piece will just be removed.
+	 */
+	return;
+#endif
+
+	tty = info->tty;
+
+	/* acknowledge both a dma_descr and dma_eop irq in R_DMAx_CLRINTR */
+
+	*info->iclrintradr = 3;
+
+	if(!tty) /* something wrong... */
+		return;
+
+	descr = &info->rec_descr;
+  
+	/* find out how many bytes were read */
+
+	/* if the eop bit was not set, all data has been received */
+	if(!(descr->status & d_eop)) {
+		recvl = descr->sw_len;
+	} else {
+		/* otherwise we find the amount of data received here */
+		recvl = descr->hw_len;
+	}
+	if(recvl) {
+		unsigned char *buf;
+		struct async_icount *icount;
+
+		icount = &info->icount;
+
+		/* update stats */
+		icount->rx += recvl;
+
+		/* read the status register so we can detect errors */
+		rstat = info->port[REG_STATUS];
+
+		if(rstat & 0xe) {
+			/* if we got an error, we must reset it by reading the
+			 * data_in field
+			 */
+			(void)info->port[REG_DATA];
+		}
+		
+		/* we only ever write errors into the first byte in the flip 
+		 * flag buffer, so we dont have to clear it all every time
+		 */
+
+		if(rstat & 0x04) {
+			icount->parity++;
+			*tty->flip.flag_buf_ptr = TTY_PARITY;
+		} else if(rstat & 0x08) {
+			icount->overrun++;
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+		} else if(rstat & 0x02) {
+			icount->frame++;
+			*tty->flip.flag_buf_ptr = TTY_FRAME;
+		} else
+			*tty->flip.flag_buf_ptr = 0;
+
+		/* use the flip buffer next in turn to restart DMA into */
+		
+		if (tty->flip.buf_num) {
+			buf = tty->flip.char_buf;
+		} else {
+			buf = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
+		}
+
+		if(buf == phys_to_virt(descr->buf)) {
+			printk("ttyS%d flip-buffer overrun!\n", info->line);
+			icount->overrun++;
+			*tty->flip.flag_buf_ptr = TTY_OVERRUN;
+			/* restart old buffer */
+		} else {
+			descr->buf = virt_to_phys(buf);
+			
+			/* schedule or push a flip of the buffer */
+			
+			info->tty->flip.count = recvl;
+
+#if (LINUX_VERSION_CODE > 131394) /* 2.1.66 */
+			/* this includes a check for low-latency */
+			tty_flip_buffer_push(tty);
+#else
+			queue_task_irq_off(&tty->flip.tqueue, &tq_timer);
+#endif	
+		}
+	}
+	
+	/* restart the receiving dma */
+	
+	descr->sw_len = TTY_FLIPBUF_SIZE;
+	descr->ctrl = d_int | d_eol | d_eop;
+	descr->hw_len = 0;
+	descr->status = 0;
+
+	*info->ifirstadr = virt_to_phys(descr);
+	*info->icmdadr = 1; /* start */
+
+#ifdef SERIAL_HANDLE_EARLY_ERRORS
+	e100_enable_serial_data_irq(info);
+#endif	
+	/* input dma should be running now */
+}
+
+static void 
+start_receive(struct e100_serial *info)
+{
+	struct etrax_dma_descr *descr;
+	
+#ifdef CONFIG_SVINTO_SIM
+	/* No receive in the simulator.  Will probably be when the rest of
+	 * the serial interface works, and this piece will just be removed.
+	 */
+	return;
+#endif
+
+	/* reset the input dma channel to be sure it works */
+	
+	*info->icmdadr = 4;
+	while((*info->icmdadr & 7) == 4);
+
+	descr = &info->rec_descr;
+	
+	/* start the receiving dma into the flip buffer */
+	
+	descr->ctrl = d_int | d_eol | d_eop;
+	descr->sw_len = TTY_FLIPBUF_SIZE;
+	descr->buf = virt_to_phys(info->tty->flip.char_buf_ptr);
+	descr->hw_len = 0;
+	descr->status = 0;
+	
+	info->tty->flip.count = 0;
+
+	*info->ifirstadr = virt_to_phys(descr);
+	*info->icmdadr = 1; /* start */
+}
+
+
+static _INLINE_ void 
+status_handle(struct e100_serial *info, unsigned short status)
+{
+}
+
+/* the bits in the MASK2 register are laid out like this:
+   DMAI_EOP DMAI_DESCR DMAO_EOP DMAO_DESCR
+   where I is the input channel and O is the output channel for the port.
+   info->irq is the bit number for the DMAO_DESCR so to check the others we
+   shift info->irq to the left.
+*/
+
+/* dma output channel interrupt handler
+   this interrupt is called from DMA2(ser2), DMA4(ser3), DMA6(ser0) or
+   DMA8(ser1) when they have finished a descriptor with the intr flag set.
+*/
+
+static void 
+tr_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct e100_serial *info;
+	unsigned long ireg;
+	int i;
+	
+#ifdef CONFIG_SVINTO_SIM
+	/* No receive in the simulator.  Will probably be when the rest of
+	 * the serial interface works, and this piece will just be removed.
+	 */
+	{
+		const char *s = "What? tr_interrupt in simulator??\n";
+		SIMCOUT(s,strlen(s));
+	}
+	return;
+#endif
+	
+	/* find out the line that caused this irq and get it from rs_table */
+	
+	ireg = *R_IRQ_MASK2_RD;  /* get the active irq bits for the dma channels */
+	
+	for(i = 0; i < NR_PORTS; i++) {
+		info = rs_table + i;
+		/* check for dma_descr (dont need to check for dma_eop in output dma for serial */
+		if(ireg & info->irq) {  
+			/* we can send a new dma bunch. make it so. */
+			transmit_chars(info);
+		}
+		
+		/* FIXME: here we should really check for a change in the
+		   status lines and if so call status_handle(info) */
+	}
+}
+
+/* dma input channel interrupt handler */
+
+static void 
+rec_interrupt(int irq, void *dev_id, struct pt_regs * regs)
+{
+	struct e100_serial *info;
+	unsigned long ireg;
+	int i;
+
+#ifdef CONFIG_SVINTO_SIM
+	/* No receive in the simulator.  Will probably be when the rest of
+	 * the serial interface works, and this piece will just be removed.
+	 */
+	{
+		const char *s = "What? rec_interrupt in simulator??\n";
+		SIMCOUT(s,strlen(s));
+	}
+	return;
+#endif
+	
+	/* find out the line that caused this irq and get it from rs_table */
+	
+	ireg = *R_IRQ_MASK2_RD;  /* get the active irq bits for the dma channels */
+	
+	for(i = 0; i < NR_PORTS; i++) {
+		info = rs_table + i;
+		/* check for both dma_eop and dma_descr for the input dma channel */
+		if(ireg & ((info->irq << 2) | (info->irq << 3))) {
+			/* we have received something */
+			receive_chars(info);
+		}
+		
+		/* FIXME: here we should really check for a change in the
+		   status lines and if so call status_handle(info) */
+	}
+}
+
+/* dma fifo/buffer timeout handler
+   forces an end-of-packet for the dma input channel if no chars 
+   have been received for CONFIG_ETRAX100_RX_TIMEOUT_TICKS/100 s.
+   If CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST is configured then this
+   handler is instead run at 15360 Hz.
+*/
+
+#ifndef CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST
+static int timeout_divider = 0;
+#endif
+
+static struct timer_list flush_timer;
+
+static void 
+timed_flush_handler(void)
+{
+	struct e100_serial *info;
+	int i;
+	unsigned int magic;
+
+#ifdef CONFIG_SVINTO_SIM
+	return;
+#endif
+	
+	for(i = 0; i < NR_PORTS; i++) {
+		info = rs_table + i;
+		if(!(info->flags & ASYNC_INITIALIZED))
+			continue;
+
+		/* istatusadr (bit 6-0) hold number of bytes in fifo 
+		 * ihwswadr (bit 31-16) holds number of bytes in dma buffer
+		 * ihwswadr (bit 15-0) specifies size of dma buffer
+		 */
+
+		magic = (*info->istatusadr & 0x3f);
+		magic += ((*info->ihwswadr&0xffff ) - (*info->ihwswadr >> 16));
+
+		/* if magic is equal to fifo_magic (magic in previous
+		 * timeout_interrupt) then no new data has arrived since last
+		 * interrupt and we'll force eop to flush fifo+dma buffers
+		 */
+
+		if(magic != info->fifo_magic) {
+			info->fifo_magic = magic;
+			info->fifo_didmagic = 0;
+		} else {
+			/* hit the timeout, force an EOP for the input
+			 * dma channel if we haven't already
+			 */
+			if(!info->fifo_didmagic && magic) {
+				info->fifo_didmagic = 1;
+				info->fifo_magic = 0;
+				*R_SET_EOP = 1U << info->iseteop;
+			}
+		}
+	}
+
+	/* restart flush timer */
+
+	mod_timer(&flush_timer, jiffies + MAX_FLUSH_TIME);
+}
+
+
+#ifdef SERIAL_HANDLE_EARLY_ERRORS
+
+/* If there is an error (ie break) when the DMA is running and
+ * there are no bytes in the fifo the DMA is stopped and we get no
+ * eop interrupt. Thus we have to monitor the first bytes on a DMA
+ * transfer, and if it is without error we can turn the serial
+ * interrupts off.
+ */
+
+static void 
+ser_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct e100_serial *info;
+	int i;
+	unsigned char rstat;
+
+	for(i = 0; i < NR_PORTS; i++) {
+
+		info = rs_table + i;
+		rstat = info->port[REG_STATUS];
+		
+		if(*R_IRQ_MASK1_RD & (1U << (8+2*info->line))) { /* This line caused the irq */
+#ifdef SERIAL_DEBUG_INTR
+			printk("Interrupt from serport %d\n", i);
+#endif
+			if(rstat & 0x0e) {
+				/* FIXME: This is weird, but if this delay is
+				 * not present then irmaflash does not work...
+				 */
+				udelay(2300);
+
+				/* if we got an error, we must reset it by
+				 * reading the data_in field
+				 */
+				(void)info->port[REG_DATA];
+				
+				PROCSTAT(early_errors_cnt[info->line]++);
+
+				/* restart the DMA */
+				*info->icmdadr = 3;
+			} 
+			else { /* it was a valid byte, now let the dma do the rest */
+#ifdef SERIAL_DEBUG_INTR
+				printk("** OK, disabling ser_interupts\n");
+#endif
+				e100_disable_serial_data_irq(info);
+			}
+		}
+	}
+}
+#endif
+
+/*
+ * -------------------------------------------------------------------
+ * Here ends the serial interrupt routines.
+ * -------------------------------------------------------------------
+ */
+
+/*
+ * This routine is used to handle the "bottom half" processing for the
+ * serial driver, known also the "software interrupt" processing.
+ * This processing is done at the kernel interrupt level, after the
+ * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
+ * is where time-consuming activities which can not be done in the
+ * interrupt driver proper are done; the interrupt driver schedules
+ * them using rs_sched_event(), and they get done here.
+ */
+static void 
+do_serial_bh(void)
+{
+	run_task_queue(&tq_serial);
+}
+
+static void 
+do_softint(void *private_)
+{
+	struct e100_serial	*info = (struct e100_serial *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+	
+	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event)) {
+		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+		    tty->ldisc.write_wakeup)
+			(tty->ldisc.write_wakeup)(tty);
+		wake_up_interruptible(&tty->write_wait);
+	}
+}
+
+/*
+ * This routine is called from the scheduler tqueue when the interrupt
+ * routine has signalled that a hangup has occurred.  The path of
+ * hangup processing is:
+ *
+ * 	serial interrupt routine -> (scheduler tqueue) ->
+ * 	do_serial_hangup() -> tty->hangup() -> rs_hangup()
+ * 
+ */
+static void 
+do_serial_hangup(void *private_)
+{
+	struct e100_serial	*info = (struct e100_serial *) private_;
+	struct tty_struct	*tty;
+	
+	tty = info->tty;
+	if (!tty)
+		return;
+	
+	tty_hangup(tty);
+}
+
+static int 
+startup(struct e100_serial * info)
+{
+	unsigned long flags;
+	unsigned long page;
+
+	page = get_zeroed_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	save_flags(flags); cli();
+
+	/* if it was already initialized, skip this */
+	
+	if (info->flags & ASYNC_INITIALIZED) {
+		free_page(page);
+		restore_flags(flags);
+		return -EBUSY;
+	}
+	
+	if (info->xmit.buf)
+		free_page(page);
+	else
+		info->xmit.buf = (unsigned char *) page;
+		
+#ifdef SERIAL_DEBUG_OPEN
+	printk("starting up ttyS%d (xmit_buf 0x%x)...\n", info->line, info->xmit_buf);
+#endif
+
+	if(info->tty) {
+
+		/* clear the tty flip flag buffer since we will not
+		 * be using it (we only use the first byte..)
+		 */
+
+		memset(info->tty->flip.flag_buf, 0, TTY_FLIPBUF_SIZE * 2);
+	}
+
+	save_flags(flags);
+	cli();
+	
+#ifdef CONFIG_SVINTO_SIM
+	/* Bits and pieces collected from below.  Better to have them
+	   in one ifdef:ed clause than to mix in a lot of ifdefs,
+	   right? */
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+	info->xmit.head = info->xmit.tail = 0;
+	
+	/* No real action in the simulator, but may set info important
+	   to ioctl. */
+	change_speed(info);
+#else
+
+	/*
+	 * Clear the FIFO buffers and disable them
+	 * (they will be reenabled in change_speed())
+	 */
+	
+	/*
+	 * Reset the DMA channels and make sure their interrupts are cleared
+	 */
+	
+	*info->icmdadr = 4; /* reset command */
+	*info->ocmdadr = 4; /* reset command */
+	
+	while((*info->icmdadr & 7) == 4); /* wait until reset cycle is complete */
+	while((*info->ocmdadr & 7) == 4);
+	
+	*info->iclrintradr = 3; /* make sure the irqs are cleared */
+	*info->oclrintradr = 3;
+	
+	if (info->tty)
+		clear_bit(TTY_IO_ERROR, &info->tty->flags);
+
+        info->xmit.head = info->xmit.tail = 0;
+	
+	/*
+	 * and set the speed and other flags of the serial port
+	 * this will start the rx/tx as well
+	 */
+#ifdef SERIAL_HANDLE_EARLY_ERRORS
+	e100_enable_serial_data_irq(info);
+#endif	
+	change_speed(info);
+
+	/* dummy read to reset any serial errors */
+
+	(void)info->port[REG_DATA];
+
+	/* enable the interrupts */
+
+	e100_enable_txdma_irq(info);
+	e100_enable_rxdma_irq(info);
+
+	info->tr_running = 0;  /* to be sure we dont lock up the transmitter */
+
+	/* setup the dma input descriptor and start dma */
+	
+	start_receive(info);
+	
+	/* for safety, make sure the descriptors last result is 0 bytes written */
+	
+	info->tr_descr.sw_len = 0;
+	info->tr_descr.hw_len = 0;
+	info->tr_descr.status = 0;
+
+	/* enable RTS/DTR last */
+
+	e100_rts(info, 1);
+	e100_dtr(info, 1);
+		
+#endif /* CONFIG_SVINTO_SIM */
+	
+	info->flags |= ASYNC_INITIALIZED;
+	
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * This routine will shutdown a serial port; interrupts are disabled, and
+ * DTR is dropped if the hangup on close termio flag is on.
+ */
+static void 
+shutdown(struct e100_serial * info)
+{
+	unsigned long flags;
+
+#ifndef CONFIG_SVINTO_SIM	
+	/* shut down the transmitter and receiver  */
+
+	e100_disable_rx(info);
+	info->port[REG_TR_CTRL] = (info->tx_ctrl &= ~0x40);
+
+	e100_disable_rxdma_irq(info);
+	e100_disable_txdma_irq(info);
+
+	info->tr_running = 0;
+
+	/* reset both dma channels */
+
+	*info->icmdadr = 4;
+	*info->ocmdadr = 4;
+
+#endif /* CONFIG_SVINTO_SIM */
+
+	if (!(info->flags & ASYNC_INITIALIZED))
+		return;
+	
+#ifdef SERIAL_DEBUG_OPEN
+	printk("Shutting down serial port %d (irq %d)....\n", info->line,
+	       info->irq);
+#endif
+	
+	save_flags(flags);
+	cli(); /* Disable interrupts */
+	
+	if (info->xmit.buf) {
+		unsigned long pg = (unsigned long) info->xmit.buf;
+		info->xmit.buf = 0;
+		free_page(pg);
+	}
+
+	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
+		/* hang up DTR and RTS if HUPCL is enabled */
+		e100_dtr(info, 0);
+		e100_rts(info, 0); /* could check CRTSCTS before doing this */
+	}
+
+	if (info->tty)
+		set_bit(TTY_IO_ERROR, &info->tty->flags);
+	
+	info->flags &= ~ASYNC_INITIALIZED;
+	restore_flags(flags);
+}
+
+
+/* change baud rate and other assorted parameters */
+
+static void 
+change_speed(struct e100_serial *info)
+{
+	unsigned int cflag;
+
+	/* first some safety checks */
+	
+	if(!info->tty || !info->tty->termios)
+		return;
+	if (!info->port)
+		return;
+	
+	cflag = info->tty->termios->c_cflag;
+	
+	/* possibly, the tx/rx should be disabled first to do this safely */
+	
+	/* change baud-rate and write it to the hardware */
+	
+	info->baud = cflag_to_baud(cflag);
+	
+#ifndef CONFIG_SVINTO_SIM
+	info->port[REG_BAUD] = cflag_to_etrax_baud(cflag);
+	/* start with default settings and then fill in changes */
+	
+	info->rx_ctrl &= ~(0x07); /* 8 bit, no/even parity */
+	info->tx_ctrl &= ~(0x37); /* 8 bit, no/even parity, 1 stop bit, no cts */
+	
+	if ((cflag & CSIZE) == CS7) {
+		/* set 7 bit mode */
+		info->tx_ctrl |= 0x01;
+		info->rx_ctrl |= 0x01;
+	}
+	
+	if (cflag & CSTOPB) {
+		/* set 2 stop bit mode */
+		info->tx_ctrl |= 0x10;
+	}	  
+	
+	if (cflag & PARENB) {
+		/* enable parity */
+		info->tx_ctrl |= 0x02;
+		info->rx_ctrl |= 0x02;
+	}
+	
+	if (cflag & PARODD) {
+		/* set odd parity */
+		info->tx_ctrl |= 0x04;
+		info->rx_ctrl |= 0x04;
+	}
+	
+	if (cflag & CRTSCTS) {
+		/* enable automatic CTS handling */
+		info->tx_ctrl |= 0x20;
+	}
+	
+	/* make sure the tx and rx are enabled */
+	
+	info->tx_ctrl |= 0x40;
+	info->rx_ctrl |= 0x40;
+
+	/* actually write the control regs to the hardware */
+	
+	info->port[REG_TR_CTRL] = info->tx_ctrl;
+	info->port[REG_REC_CTRL] = info->rx_ctrl;
+	*((unsigned long *)&info->port[REG_XOFF]) = 0;
+
+#endif /* CONFIG_SVINTO_SIM */
+}
+
+/* start transmitting chars NOW */
+
+static void 
+rs_flush_chars(struct tty_struct *tty)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (info->tr_running
+	    || info->xmit.head == info->xmit.tail
+	    || tty->stopped
+	    || tty->hw_stopped
+	    || !info->xmit.buf)
+		return;
+
+#ifdef SERIAL_DEBUG_FLOW
+	printk("rs_flush_chars\n");
+#endif
+	
+	/* this protection might not exactly be necessary here */
+	
+	save_flags(flags);
+	cli();
+	start_transmit(info);
+	restore_flags(flags);
+}
+
+static int 
+rs_write(struct tty_struct * tty, int from_user,
+	 const unsigned char *buf, int count)
+{
+	int	c, ret = 0;
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+	
+	/* first some sanity checks */
+	
+	if (!tty || !info->xmit.buf || !tmp_buf)
+		return 0;
+	
+#ifdef SERIAL_DEBUG_DATA
+	if(info->line == SERIAL_DEBUG_LINE)
+		printk("rs_write (%d), status %d\n", 
+		       count, info->port[REG_STATUS]);
+#endif
+
+#ifdef CONFIG_SVINTO_SIM
+	/* Really simple.  The output is here and now. */
+	SIMCOUT(buf, count);
+	return;
+#endif
+	save_flags(flags);
+	
+	/* the cli/restore_flags pairs below are needed because the
+	 * DMA interrupt handler moves the info->xmit values. the memcpy
+	 * needs to be in the critical region unfortunately, because we
+	 * need to read xmit values, memcpy, write xmit values in one
+	 * atomic operation... this could perhaps be avoided by more clever
+	 * design.
+	 */
+	if(from_user) {
+		down(&tmp_buf_sem);
+		while (1) {
+			int c1;
+			c = CIRC_SPACE_TO_END(info->xmit.head,
+					      info->xmit.tail,
+					      SERIAL_XMIT_SIZE);
+			if (count < c)
+				c = count;
+			if (c <= 0)
+				break;
+
+			c -= copy_from_user(tmp_buf, buf, c);
+			if (!c) {
+				if (!ret)
+					ret = -EFAULT;
+				break;
+			}
+			cli();
+			c1 = CIRC_SPACE_TO_END(info->xmit.head,
+					       info->xmit.tail,
+					       SERIAL_XMIT_SIZE);
+			if (c1 < c)
+				c = c1;
+			memcpy(info->xmit.buf + info->xmit.head, tmp_buf, c);
+			info->xmit.head = ((info->xmit.head + c) &
+					   (SERIAL_XMIT_SIZE-1));
+			restore_flags(flags);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		up(&tmp_buf_sem);
+	} else {
+		cli();	
+		while(1) {
+			c = CIRC_SPACE_TO_END(info->xmit.head,
+					      info->xmit.tail,
+					      SERIAL_XMIT_SIZE);
+
+			if (count < c)
+				c = count;
+			if (c <= 0)
+				break;
+		
+			memcpy(info->xmit.buf + info->xmit.head, buf, c);
+			info->xmit.head = (info->xmit.head + c) &
+				(SERIAL_XMIT_SIZE-1);
+			buf += c;
+			count -= c;
+			ret += c;
+		}
+		restore_flags(flags);
+	}
+	
+	/* enable transmitter if not running, unless the tty is stopped
+	 * this does not need IRQ protection since if tr_running == 0
+	 * the IRQ's are not running anyway for this port.
+	 */
+	
+	if(info->xmit.head != info->xmit.tail
+	   && !tty->stopped &&
+	   !tty->hw_stopped &&
+	   !info->tr_running) {
+		start_transmit(info);
+	}
+ 	
+	return ret;
+}
+
+/* how much space is available in the xmit buffer? */
+
+static int 
+rs_write_room(struct tty_struct *tty)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+	
+	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+/* How many chars are in the xmit buffer?
+ * This does not include any chars in the transmitter FIFO.
+ * Use wait_until_sent for waiting for FIFO drain.
+ */
+
+static int 
+rs_chars_in_buffer(struct tty_struct *tty)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+
+	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
+}
+
+/* discard everything in the xmit buffer */
+
+static void 
+rs_flush_buffer(struct tty_struct *tty)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	info->xmit.head = info->xmit.tail = 0;
+	restore_flags(flags);
+
+	wake_up_interruptible(&tty->write_wait);
+
+	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    tty->ldisc.write_wakeup)
+		(tty->ldisc.write_wakeup)(tty);
+}
+
+/*
+ * This function is used to send a high-priority XON/XOFF character to
+ * the device
+ *
+ * Since we don't bother to check for info->x_char in transmit_chars yet,
+ * we don't really implement this function yet.
+ */
+static void rs_send_xchar(struct tty_struct *tty, char ch)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+
+	printk("serial.c:rs_send_xchar not implemented!\n");
+
+	info->x_char = ch;
+	if (ch) {
+		/* Make sure transmit interrupts are on */
+		/* TODO. */
+	}
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_throttle()
+ * 
+ * This routine is called by the upper-layer tty layer to signal that
+ * incoming characters should be throttled.
+ * ------------------------------------------------------------
+ */
+static void 
+rs_throttle(struct tty_struct * tty)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("throttle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+	
+	if (I_IXOFF(tty))
+		info->x_char = STOP_CHAR(tty);
+	
+	/* Turn off RTS line (do this atomic) should here be an else ?? */
+	
+	save_flags(flags); 
+	cli();
+	e100_rts(info, 0);
+	restore_flags(flags);
+}
+
+static void 
+rs_unthrottle(struct tty_struct * tty)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+#ifdef SERIAL_DEBUG_THROTTLE
+	char	buf[64];
+	
+	printk("unthrottle %s: %d....\n", _tty_name(tty, buf),
+	       tty->ldisc.chars_in_buffer(tty));
+#endif
+	
+	if (I_IXOFF(tty)) {
+		if (info->x_char)
+			info->x_char = 0;
+		else
+			info->x_char = START_CHAR(tty);
+	}
+	
+	/* Assert RTS line (do this atomic) */
+	
+	save_flags(flags); 
+	cli();
+	e100_rts(info, 1);
+	restore_flags(flags);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_ioctl() and friends
+ * ------------------------------------------------------------
+ */
+
+static int 
+get_serial_info(struct e100_serial * info,
+		struct serial_struct * retinfo)
+{
+	struct serial_struct tmp;
+	
+	/* this is all probably wrong, there are a lot of fields
+	 * here that we don't have in e100_serial and maybe we
+	 * should set them to something else than 0.
+	 */
+
+	if (!retinfo)
+		return -EFAULT;
+	memset(&tmp, 0, sizeof(tmp));
+	tmp.type = info->type;
+	tmp.line = info->line;
+	tmp.port = (int)info->port;
+	tmp.irq = info->irq;
+	tmp.flags = info->flags;
+	tmp.close_delay = info->close_delay;
+	tmp.closing_wait = info->closing_wait;
+	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
+		return -EFAULT;
+	return 0;
+}
+
+static int
+set_serial_info(struct e100_serial * info,
+		struct serial_struct * new_info)
+{
+	struct serial_struct new_serial;
+	struct e100_serial old_info;
+	int 			retval = 0;
+
+	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
+		return -EFAULT;
+
+	old_info = *info;
+	
+	if(!capable(CAP_SYS_ADMIN)) {
+		if((new_serial.type != info->type) ||
+		   (new_serial.close_delay != info->close_delay) ||
+		   ((new_serial.flags & ~ASYNC_USR_MASK) !=
+		    (info->flags & ~ASYNC_USR_MASK)))
+			return -EPERM;
+		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
+			       (new_serial.flags & ASYNC_USR_MASK));
+		goto check_and_exit;
+	}
+	
+	if (info->count > 1)
+		return -EBUSY;
+	
+	/*
+	 * OK, past this point, all the error checking has been done.
+	 * At this point, we start making changes.....
+	 */
+	
+	info->flags = ((info->flags & ~ASYNC_FLAGS) |
+		       (new_serial.flags & ASYNC_FLAGS));
+	info->type = new_serial.type;
+	info->close_delay = new_serial.close_delay;
+	info->closing_wait = new_serial.closing_wait;
+#if (LINUX_VERSION_CODE > 0x20100)
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+#endif
+
+ check_and_exit:
+	if(info->flags & ASYNC_INITIALIZED) {
+		change_speed(info);
+	} else
+		retval = startup(info);
+	return retval;
+}
+
+/*
+ * get_lsr_info - get line status register info
+ *
+ * Purpose: Let user call ioctl() to get info when the UART physically
+ * 	    is emptied.  On bus types like RS485, the transmitter must
+ * 	    release the bus after transmitting. This must be done when
+ * 	    the transmit shift register is empty, not be done when the
+ * 	    transmit holding register is empty.  This functionality
+ * 	    allows an RS485 driver to be written in user space. 
+ */
+static int 
+get_lsr_info(struct e100_serial * info, unsigned int *value)
+{
+	unsigned int result;
+
+#ifdef CONFIG_SVINTO_SIM
+	/* Always open. */
+	result = TIOCSER_TEMT;
+#else
+	if (*info->ostatusadr & 0x007F)  /* something in fifo */
+		result = 0;
+	else
+		result = TIOCSER_TEMT;
+#endif
+
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+#ifdef SERIAL_DEBUG_IO 
+struct state_str
+{
+  int state;
+  const char *str;
+  
+};
+
+const struct state_str control_state_str[]={
+	{TIOCM_DTR, "DTR" },
+	{TIOCM_RTS, "RTS"},
+	{TIOCM_ST, "ST?" },
+	{TIOCM_SR, "SR?" },
+	{TIOCM_CTS, "CTS" },
+	{TIOCM_CD, "CD" },
+	{TIOCM_RI, "RI" },
+	{TIOCM_DSR, "DSR" },
+	{0, NULL }
+};
+
+char *get_control_state_str(int MLines, char *s)
+{
+	int i = 0;
+	s[0]='\0';
+	while (control_state_str[i].str != NULL) {
+		if (MLines & control_state_str[i].state) {
+			if (s[0] != '\0') {
+				strcat(s, ", ");
+			}
+			strcat(s, control_state_str[i].str);
+		}
+		i++;
+	}
+	return s;
+}
+#endif
+
+static int 
+get_modem_info(struct e100_serial * info, unsigned int *value)
+{
+	unsigned int result;
+	/* Polarity isn't verified */
+#if 0 /*def SERIAL_DEBUG_IO  */
+
+	printk("get_modem_info: RTS: %i DTR: %i CD: %i RI: %i DSR: %i CTS: %i\n",
+	       E100_RTS_GET(info),
+	       E100_DTR_GET(info),
+	       E100_CD_GET(info),
+	       E100_RI_GET(info),
+	       E100_DSR_GET(info),
+	       E100_CTS_GET(info));
+#endif
+	result =  
+		(!E100_RTS_GET(info) ? TIOCM_RTS : 0)
+		| (!E100_DTR_GET(info) ? TIOCM_DTR : 0)
+		| (!E100_CD_GET(info) ? TIOCM_CAR : 0)
+		| (!E100_RI_GET(info) ? TIOCM_RNG : 0)
+		| (!E100_DSR_GET(info) ? TIOCM_DSR : 0)
+		| (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
+	
+#ifdef SERIAL_DEBUG_IO 
+	printk("e100ser: modem state: %i 0x%08X\n", result, result);
+	{
+		char s[100];
+		
+		get_control_state_str(result, s);
+		printk("state: %s\n", s);
+	}
+#endif  
+	if (copy_to_user(value, &result, sizeof(int)))
+		return -EFAULT;
+	return 0;
+}
+
+
+static int
+set_modem_info(struct e100_serial * info, unsigned int cmd,
+	       unsigned int *value)
+{
+	unsigned int arg;
+
+	if (copy_from_user(&arg, value, sizeof(int)))
+		return -EFAULT;
+
+	switch (cmd) {
+	case TIOCMBIS: 
+		if (arg & TIOCM_RTS) {
+			e100_rts(info, 1);
+		}
+		if (arg & TIOCM_DTR) {
+			e100_dtr(info, 1);
+		}
+		/* Handle FEMALE behaviour */
+		if (arg & TIOCM_RI) {
+			e100_ri_out(info, 1);
+		}
+		if (arg & TIOCM_CD) {
+			e100_cd_out(info, 1);
+		}
+		break;
+	case TIOCMBIC:
+		if (arg & TIOCM_RTS) {
+			e100_rts(info, 0);
+		}
+		if (arg & TIOCM_DTR) {
+			e100_dtr(info, 0);
+		}
+		/* Handle FEMALE behaviour */
+		if (arg & TIOCM_RI) {
+			e100_ri_out(info, 0);
+		}
+		if (arg & TIOCM_CD) {
+			e100_cd_out(info, 0);
+		}
+		break;
+	case TIOCMSET:
+		e100_rts(info, arg & TIOCM_RTS);
+		e100_dtr(info, arg & TIOCM_DTR);
+		/* Handle FEMALE behaviour */
+		e100_ri_out(info, arg & TIOCM_RI);
+		e100_cd_out(info, arg & TIOCM_CD);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * This routine sends a break character out the serial port.
+ */
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+static void 
+send_break(struct e100_serial * info, int duration)
+{
+	unsigned long flags;	
+
+	if (!info->port)
+		return;
+
+	current->state = TASK_INTERRUPTIBLE;
+	current->timeout = jiffies + duration;
+
+	save_flags(flags);
+	cli();
+
+	/* Go to manual mode and set the txd pin to 0 */
+
+	info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */
+	info->port[REG_TR_CTRL] = info->tx_ctrl;
+
+	/* wait for "duration" jiffies */
+
+	schedule();
+
+	info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */
+	info->port[REG_TR_CTRL] = info->tx_ctrl;
+
+	/* the DMA gets awfully confused if we toggle the tranceiver like this 
+	 * so we need to reset it 
+	 */
+	*info->ocmdadr = 4;
+
+	restore_flags(flags);
+}
+#else
+static void 
+rs_break(struct tty_struct *tty, int break_state)
+{
+	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (!info->port)
+		return;
+	
+	save_flags(flags);
+	cli();
+	if (break_state == -1) {
+		/* Go to manual mode and set the txd pin to 0 */
+		info->tx_ctrl &= 0x3F; /* Clear bit 7 (txd) and 6 (tr_enable) */
+	} else {
+		info->tx_ctrl |= (0x80 | 0x40); /* Set bit 7 (txd) and 6 (tr_enable) */
+	}
+	info->port[REG_TR_CTRL] = info->tx_ctrl;
+	restore_flags(flags);
+}
+#endif
+
+static int 
+rs_ioctl(struct tty_struct *tty, struct file * file,
+	 unsigned int cmd, unsigned long arg)
+{
+	int error;
+	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+	int retval;
+	
+	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
+	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGWILD)  &&
+	    (cmd != TIOCSERSWILD) && (cmd != TIOCSERGSTRUCT)) {
+		if (tty->flags & (1 << TTY_IO_ERROR))
+			return -EIO;
+	}
+	
+	switch (cmd) {
+#if (LINUX_VERSION_CODE < 131394) /* Linux 2.1.66 */
+	        case TCSBRK:	/* SVID version: non-zero arg --> no break */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			if (!arg) {
+				send_break(info, HZ/4);	/* 1/4 second */
+				if (signal_pending(current))
+					return -EINTR;
+			}
+			return 0;
+		case TCSBRKP:	/* support for POSIX tcsendbreak() */
+			retval = tty_check_change(tty);
+			if (retval)
+				return retval;
+			tty_wait_until_sent(tty, 0);
+			if (signal_pending(current))
+				return -EINTR;
+			send_break(info, arg ? arg*(HZ/10) : HZ/4);
+			if (signal_pending(current))
+				return -EINTR;
+			return 0;
+		case TIOCGSOFTCAR:
+			error = verify_area(VERIFY_WRITE, (void *) arg,sizeof(long));
+			if (error)
+				return error;
+			put_fs_long(C_CLOCAL(tty) ? 1 : 0,
+				    (unsigned long *) arg);
+			return 0;
+		case TIOCSSOFTCAR:
+			arg = get_fs_long((unsigned long *) arg);
+			tty->termios->c_cflag =
+				((tty->termios->c_cflag & ~CLOCAL) |
+				 (arg ? CLOCAL : 0));
+			return 0;
+#endif
+		case TIOCMGET:
+			return get_modem_info(info, (unsigned int *) arg);
+		case TIOCMBIS:
+		case TIOCMBIC:
+		case TIOCMSET:
+			return set_modem_info(info, cmd, (unsigned int *) arg);
+		case TIOCGSERIAL:
+			return get_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSSERIAL:
+			return set_serial_info(info,
+					       (struct serial_struct *) arg);
+		case TIOCSERGETLSR: /* Get line status register */
+			return get_lsr_info(info, (unsigned int *) arg);
+
+		case TIOCSERGSTRUCT:
+			if (copy_to_user((struct e100_serial *) arg,
+					 info, sizeof(struct e100_serial)))
+				return -EFAULT;
+			return 0;
+
+#if defined(CONFIG_RS485)
+		case TIOCSERSETRS485:
+			error = verify_area(VERIFY_WRITE, (void *) arg,
+					sizeof(struct rs485_control));
+			
+			if (error)
+				return error;
+			
+			return e100_enable_rs485(tty, (struct rs485_control *) arg);
+
+		case TIOCSERWRRS485:
+			error = verify_area(VERIFY_WRITE, (void *) arg,
+					sizeof(struct rs485_write));
+			
+			if (error)
+				return error;
+			
+			return e100_write_rs485(tty, (struct rs485_write *) arg);
+#endif
+			
+		default:
+			return -ENOIOCTLCMD;
+	}
+	return 0;
+}
+
+static void 
+rs_set_termios(struct tty_struct *tty, struct termios *old_termios)
+{
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+
+	if (tty->termios->c_cflag == old_termios->c_cflag)
+		return;
+
+	change_speed(info);
+
+	if ((old_termios->c_cflag & CRTSCTS) &&
+	    !(tty->termios->c_cflag & CRTSCTS)) {
+		tty->hw_stopped = 0;
+		rs_start(tty);
+	}
+	
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_close()
+ * 
+ * This routine is called when the serial port gets closed.  First, we
+ * wait for the last remaining data to be sent.  Then, we unlink its
+ * S structure from the interrupt chain if necessary, and we free
+ * that IRQ if nothing is left in the chain.
+ * ------------------------------------------------------------
+ */
+static void 
+rs_close(struct tty_struct *tty, struct file * filp)
+{
+	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+	unsigned long flags;
+
+	if (!info)
+		return;
+  
+	/* interrupts are disabled for this entire function */
+  
+	save_flags(flags); 
+	cli();
+  
+	if (tty_hung_up_p(filp)) {
+		restore_flags(flags);
+		return;
+	}
+  
+#ifdef SERIAL_DEBUG_OPEN
+	printk("[%d] rs_close ttyS%d, count = %d\n", current->pid, 
+	       info->line, info->count);
+#endif
+	if ((tty->count == 1) && (info->count != 1)) {
+		/*
+		 * Uh, oh.  tty->count is 1, which means that the tty
+		 * structure will be freed.  Info->count should always
+		 * be one in these conditions.  If it's greater than
+		 * one, we've got real problems, since it means the
+		 * serial port won't be shutdown.
+		 */
+		printk("rs_close: bad serial port count; tty->count is 1, "
+		       "info->count is %d\n", info->count);
+		info->count = 1;
+	}
+	if (--info->count < 0) {
+		printk("rs_close: bad serial port count for ttyS%d: %d\n",
+		       info->line, info->count);
+		info->count = 0;
+	}
+	if (info->count) {
+		restore_flags(flags);
+		return;
+	}
+	info->flags |= ASYNC_CLOSING;
+	/*
+	 * Save the termios structure, since this port may have
+	 * separate termios for callout and dialin.
+	 */
+	if (info->flags & ASYNC_NORMAL_ACTIVE)
+		info->normal_termios = *tty->termios;
+	if (info->flags & ASYNC_CALLOUT_ACTIVE)
+		info->callout_termios = *tty->termios;
+	/*
+	 * Now we wait for the transmit buffer to clear; and we notify 
+	 * the line discipline to only process XON/XOFF characters.
+	 */
+	tty->closing = 1;
+	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, info->closing_wait);
+	/*
+	 * At this point we stop accepting input.  To do this, we
+	 * disable the serial receiver and the DMA receive interrupt.
+	 */
+#ifdef SERIAL_HANDLE_EARLY_ERRORS 
+	e100_disable_serial_data_irq(info);
+#endif
+
+#ifndef CONFIG_SVINTO_SIM
+	e100_disable_rx(info);
+	e100_disable_rxdma_irq(info);
+
+	if (info->flags & ASYNC_INITIALIZED) {
+		/*
+		 * Before we drop DTR, make sure the UART transmitter
+		 * has completely drained; this is especially
+		 * important as we have a transmit FIFO!
+		 */
+		rs_wait_until_sent(tty, HZ);
+	}
+#endif
+
+	shutdown(info);
+	if (tty->driver.flush_buffer)
+		tty->driver.flush_buffer(tty);
+	if (tty->ldisc.flush_buffer)
+		tty->ldisc.flush_buffer(tty);
+	tty->closing = 0;
+	info->event = 0;
+	info->tty = 0;
+	if (info->blocked_open) {
+		if (info->close_delay) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			schedule_timeout(info->close_delay);
+		}
+		wake_up_interruptible(&info->open_wait);
+	}
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
+			 ASYNC_CLOSING);
+	wake_up_interruptible(&info->close_wait);
+	restore_flags(flags);
+
+	/* port closed */
+
+#if defined(CONFIG_RS485)
+	if (info->rs485.enabled) {
+		info->rs485.enabled = 0;
+#if defined(CONFIG_RS485_ON_PA)
+		*R_PORT_PA_DATA = port_pa_data_shadow &= ~(1 << rs485_pa_bit);
+#endif
+	}
+#endif
+}
+
+/*
+ * rs_wait_until_sent() --- wait until the transmitter is empty
+ */
+static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
+{
+	unsigned long orig_jiffies;
+	struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+
+	/*
+	 * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
+	 * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
+	 */
+	orig_jiffies = jiffies;
+	while(info->xmit.head != info->xmit.tail || /* More in send queue */
+	      (*info->ostatusadr & 0x007f)) { /* more in FIFO */
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(1);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+	set_current_state(TASK_RUNNING);
+}
+
+/*
+ * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
+ */
+void 
+rs_hangup(struct tty_struct *tty)
+{
+	struct e100_serial * info = (struct e100_serial *)tty->driver_data;
+	
+	rs_flush_buffer(tty);
+	shutdown(info);
+	info->event = 0;
+	info->count = 0;
+	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+	info->tty = 0;
+	wake_up_interruptible(&info->open_wait);
+}
+
+/*
+ * ------------------------------------------------------------
+ * rs_open() and friends
+ * ------------------------------------------------------------
+ */
+static int 
+block_til_ready(struct tty_struct *tty, struct file * filp,
+		struct e100_serial *info)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long   flags;
+	int		retval;
+	int		do_clocal = 0, extra_count = 0;
+	
+	/*
+	 * If the device is in the middle of being closed, then block
+	 * until it's done, and then try again.
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		if (info->flags & ASYNC_HUP_NOTIFY)
+			return -EAGAIN;
+		else
+			return -ERESTARTSYS;
+#else
+		return -EAGAIN;
+#endif
+	}
+  
+	/*
+	 * If this is a callout device, then just make sure the normal
+	 * device isn't being used.
+	 */
+	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
+		if (info->flags & ASYNC_NORMAL_ACTIVE)
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_SESSION_LOCKOUT) &&
+		    (info->session != current->session))
+			return -EBUSY;
+		if ((info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    (info->flags & ASYNC_PGRP_LOCKOUT) &&
+		    (info->pgrp != current->pgrp))
+			return -EBUSY;
+		info->flags |= ASYNC_CALLOUT_ACTIVE;
+		return 0;
+	}
+	
+	/*
+	 * If non-blocking mode is set, or the port is not enabled,
+	 * then make the check up front and then exit.
+	 */
+	if ((filp->f_flags & O_NONBLOCK) ||
+	    (tty->flags & (1 << TTY_IO_ERROR))) {
+		if (info->flags & ASYNC_CALLOUT_ACTIVE)
+			return -EBUSY;
+		info->flags |= ASYNC_NORMAL_ACTIVE;
+		return 0;
+	}
+	
+	if (info->flags & ASYNC_CALLOUT_ACTIVE) {
+		if (info->normal_termios.c_cflag & CLOCAL)
+			do_clocal = 1;
+	} else {
+		if (tty->termios->c_cflag & CLOCAL)
+			do_clocal = 1;
+	}
+	
+	/*
+	 * Block waiting for the carrier detect and the line to become
+	 * free (i.e., not in use by the callout).  While we are in
+	 * this loop, info->count is dropped by one, so that
+	 * rs_close() knows when to free things.  We restore it upon
+	 * exit, either normal or abnormal.
+	 */
+	retval = 0;
+	add_wait_queue(&info->open_wait, &wait);
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready before block: ttyS%d, count = %d\n",
+	       info->line, info->count);
+#endif
+	save_flags(flags); 
+	cli();
+	if (!tty_hung_up_p(filp)) {
+		extra_count++;
+		info->count--;
+	}
+	restore_flags(flags);
+	info->blocked_open++;
+	while (1) {
+		save_flags(flags);
+		cli();
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE)) {
+			/* assert RTS and DTR */
+			e100_rts(info, 1);
+			e100_dtr(info, 1);
+		}
+		restore_flags(flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		if (tty_hung_up_p(filp) ||
+		    !(info->flags & ASYNC_INITIALIZED)) {
+#ifdef SERIAL_DO_RESTART
+			if (info->flags & ASYNC_HUP_NOTIFY)
+				retval = -EAGAIN;
+			else
+				retval = -ERESTARTSYS;	
+#else
+			retval = -EAGAIN;
+#endif
+			break;
+		}
+		if (!(info->flags & ASYNC_CALLOUT_ACTIVE) &&
+		    !(info->flags & ASYNC_CLOSING) && do_clocal)
+			/* && (do_clocal || DCD_IS_ASSERTED) */
+			break;
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			break;
+		}
+#ifdef SERIAL_DEBUG_OPEN
+		printk("block_til_ready blocking: ttyS%d, count = %d\n",
+		       info->line, info->count);
+#endif
+		schedule();
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&info->open_wait, &wait);
+	if (extra_count)
+		info->count++;
+	info->blocked_open--;
+#ifdef SERIAL_DEBUG_OPEN
+	printk("block_til_ready after blocking: ttyS%d, count = %d\n",
+	       info->line, info->count);
+#endif
+	if (retval)
+		return retval;
+	info->flags |= ASYNC_NORMAL_ACTIVE;
+	return 0;
+}	
+
+/*
+ * This routine is called whenever a serial port is opened. 
+ * It performs the serial-specific initialization for the tty structure.
+ */
+static int 
+rs_open(struct tty_struct *tty, struct file * filp)
+{
+	struct e100_serial	*info;
+	int 			retval, line;
+	unsigned long           page;
+
+	/* find which port we want to open */
+
+	line = MINOR(tty->device) - tty->driver.minor_start;
+  
+	if (line < 0 || line >= NR_PORTS)
+		return -ENODEV;
+
+	/* dont allow opening ports that are not enabled in the HW config */
+
+#ifndef CONFIG_ETRAX100_SERIAL_PORT2
+	if (line == 2)
+		return -ENODEV;
+#endif
+#ifndef CONFIG_ETRAX100_SERIAL_PORT3
+	if (line == 3)
+		return -ENODEV;
+#endif
+
+	/* find the corresponding e100_serial struct in the table */
+
+	info = rs_table + line;
+  
+#ifdef SERIAL_DEBUG_OPEN
+	printk("[%d] rs_open %s%d, count = %d\n", current->pid,
+	       tty->driver.name, info->line,
+	       info->count);
+#endif
+
+	info->count++;
+	tty->driver_data = info;
+	info->tty = tty;
+
+#if (LINUX_VERSION_CODE > 0x20100)
+	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+#endif
+
+	if (!tmp_buf) {
+		page = get_zeroed_page(GFP_KERNEL);
+		if (!page) {
+			return -ENOMEM;
+		}
+		if (tmp_buf)
+			free_page(page);
+		else
+			tmp_buf = (unsigned char *) page;
+	}
+
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (info->flags & ASYNC_CLOSING)) {
+		if (info->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&info->close_wait);
+#ifdef SERIAL_DO_RESTART
+		return ((info->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
+	/*
+	 * Start up the serial port
+	 */
+
+	retval = startup(info);
+	if (retval)
+		return retval;
+  
+	retval = block_til_ready(tty, filp, info);
+	if (retval) {
+#ifdef SERIAL_DEBUG_OPEN
+		printk("rs_open returning after block_til_ready with %d\n",
+		       retval);
+#endif
+		return retval;
+	}
+
+	if ((info->count == 1) && (info->flags & ASYNC_SPLIT_TERMIOS)) {
+		if (tty->driver.subtype == SERIAL_TYPE_NORMAL)
+			*tty->termios = info->normal_termios;
+		else 
+			*tty->termios = info->callout_termios;
+		change_speed(info);
+	}
+
+	info->session = current->session;
+	info->pgrp = current->pgrp;
+  
+#ifdef SERIAL_DEBUG_OPEN
+	printk("rs_open ttyS%d successful...\n", info->line);
+#endif
+	return 0;
+}
+
+/*
+ * /proc fs routines....
+ */
+
+static inline int line_info(char *buf, struct e100_serial *info)
+{
+	char	stat_buf[30], control, status;
+	int	ret;
+	unsigned long flags;
+
+	ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d",
+		      info->line, info->port, info->irq);
+
+	if (!info->port || (info->type == PORT_UNKNOWN)) {
+		ret += sprintf(buf+ret, "\n");
+		return ret;
+	}
+
+	stat_buf[0] = 0;
+	stat_buf[1] = 0;
+	if (E100_RTS_GET(info))
+		strcat(stat_buf, "|RTS");
+	if (E100_CTS_GET(info))
+		strcat(stat_buf, "|CTS");
+	if (E100_DTR_GET(info))
+		strcat(stat_buf, "|DTR");
+	if (E100_DSR_GET(info))
+		strcat(stat_buf, "|DSR");
+	if (E100_CD_GET(info))
+		strcat(stat_buf, "|CD");
+	if (E100_RI_GET(info))
+		strcat(stat_buf, "|RI");
+
+	ret += sprintf(buf+ret, " baud:%d", info->baud);
+
+	ret += sprintf(buf+ret, " tx:%d rx:%d",
+		      info->icount.tx, info->icount.rx);
+
+	if (info->icount.frame)
+		ret += sprintf(buf+ret, " fe:%d", info->icount.frame);
+	
+	if (info->icount.parity)
+		ret += sprintf(buf+ret, " pe:%d", info->icount.parity);
+	
+	if (info->icount.brk)
+		ret += sprintf(buf+ret, " brk:%d", info->icount.brk);	
+
+	if (info->icount.overrun)
+		ret += sprintf(buf+ret, " oe:%d", info->icount.overrun);
+
+	/*
+	 * Last thing is the RS-232 status lines
+	 */
+	ret += sprintf(buf+ret, " %s\n", stat_buf+1);
+	return ret;
+}
+
+int rs_read_proc(char *page, char **start, off_t off, int count,
+		 int *eof, void *data)
+{
+	int i, len = 0, l;
+	off_t	begin = 0;
+
+	len += sprintf(page, "serinfo:1.0 driver:%s\n",
+		       serial_version);
+	for (i = 0; i < NR_PORTS && len < 4000; i++) {
+		l = line_info(page + len, &rs_table[i]);
+		len += l;
+		if (len+begin > off+count)
+			goto done;
+		if (len+begin < off) {
+			begin += len;
+			len = 0;
+		}
+	}
+	*eof = 1;
+done:
+	if (off >= len+begin)
+		return 0;
+	*start = page + (off-begin);
+	return ((count < begin+len-off) ? count : begin+len-off);
+}
+
+/* Finally, routines used to initialize the serial driver. */
+
+static void 
+show_serial_version(void)
+{
+	printk("ETRAX 100LX serial-driver %s, (c) 2000 Axis Communications AB\r\n",
+	       serial_version);
+}
+
+/* rs_init inits the driver at boot (using the module_init chain) */
+
+static int __init
+rs_init(void)
+{
+	int i;
+	struct e100_serial *info;
+
+	show_serial_version();
+        
+	init_bh(SERIAL_BH, do_serial_bh);
+
+	/* Setup the timed flush handler system */
+
+	init_timer(&flush_timer);
+	flush_timer.function = timed_flush_handler;
+	mod_timer(&flush_timer, jiffies + MAX_FLUSH_TIME);
+
+	/* Initialize the tty_driver structure */
+  
+	memset(&serial_driver, 0, sizeof(struct tty_driver));
+	serial_driver.magic = TTY_DRIVER_MAGIC;
+#if (LINUX_VERSION_CODE > 0x20100)
+	serial_driver.driver_name = "serial";
+#endif
+	serial_driver.name = "ttyS";
+	serial_driver.major = TTY_MAJOR;
+	serial_driver.minor_start = 64;
+	serial_driver.num = NR_PORTS;       /* etrax100 has 4 serial ports */
+	serial_driver.type = TTY_DRIVER_TYPE_SERIAL;
+	serial_driver.subtype = SERIAL_TYPE_NORMAL;
+	serial_driver.init_termios = tty_std_termios;
+	serial_driver.init_termios.c_cflag =
+		B115200 | CS8 | CREAD | HUPCL | CLOCAL; /* is normally B9600 default... */
+	serial_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS;
+	serial_driver.refcount = &serial_refcount;
+	serial_driver.table = serial_table;
+	serial_driver.termios = serial_termios;
+	serial_driver.termios_locked = serial_termios_locked;
+  
+	serial_driver.open = rs_open;
+	serial_driver.close = rs_close;
+	serial_driver.write = rs_write;
+	/* should we have an rs_put_char as well here ? */
+	serial_driver.flush_chars = rs_flush_chars;
+	serial_driver.write_room = rs_write_room;
+	serial_driver.chars_in_buffer = rs_chars_in_buffer;
+	serial_driver.flush_buffer = rs_flush_buffer;
+	serial_driver.ioctl = rs_ioctl;
+	serial_driver.throttle = rs_throttle;
+	serial_driver.unthrottle = rs_unthrottle;
+	serial_driver.set_termios = rs_set_termios;
+	serial_driver.stop = rs_stop;
+	serial_driver.start = rs_start;
+	serial_driver.hangup = rs_hangup;
+#if (LINUX_VERSION_CODE >= 131394) /* Linux 2.1.66 */
+	serial_driver.break_ctl = rs_break;
+#endif
+#if (LINUX_VERSION_CODE >= 131343)
+	serial_driver.send_xchar = rs_send_xchar;
+	serial_driver.wait_until_sent = rs_wait_until_sent;
+	serial_driver.read_proc = rs_read_proc;
+#endif
+	  
+	/*
+	 * The callout device is just like normal device except for
+	 * major number and the subtype code.
+	 */
+	callout_driver = serial_driver;
+	callout_driver.name = "cua";
+	callout_driver.major = TTYAUX_MAJOR;
+	callout_driver.subtype = SERIAL_TYPE_CALLOUT;
+#if (LINUX_VERSION_CODE >= 131343)
+	callout_driver.read_proc = 0;
+	callout_driver.proc_entry = 0;
+#endif
+  
+	if (tty_register_driver(&serial_driver))
+		panic("Couldn't register serial driver\n");
+	if (tty_register_driver(&callout_driver))
+		panic("Couldn't register callout driver\n");
+  
+	/* do some initializing for the separate ports */
+  
+	for (i = 0, info = rs_table; i < NR_PORTS; i++,info++) {
+		info->line = i;
+		info->tty = 0;
+		info->type = PORT_ETRAX100;
+		info->tr_running = 0;
+		info->fifo_magic = 0;
+		info->fifo_didmagic = 0;
+		info->flags = 0;
+		info->close_delay = 5*HZ/10;
+		info->closing_wait = 30*HZ;
+		info->x_char = 0;
+		info->event = 0;
+		info->count = 0;
+		info->blocked_open = 0;
+		info->tqueue.routine = do_softint;
+		info->tqueue.data = info;
+		info->callout_termios = callout_driver.init_termios;
+		info->normal_termios = serial_driver.init_termios;
+		init_waitqueue_head(&info->open_wait);
+		init_waitqueue_head(&info->close_wait);
+		info->xmit.buf = 0;
+		info->xmit.tail = info->xmit.head = 0;
+
+		printk(KERN_INFO "%s%d at 0x%x is a builtin UART with DMA\n",
+		       serial_driver.name, info->line, (unsigned int)info->port);
+	}
+
+#ifndef CONFIG_SVINTO_SIM
+	/* Not needed in simulator.  May only complicate stuff. */
+	/* hook the irq's for DMA channel 6 and 7, serial output and input, and some more... */
+	if(request_irq(22, tr_interrupt, SA_INTERRUPT, "serial 0 dma tr", NULL))
+		panic("irq22");
+	if(request_irq(23, rec_interrupt, SA_INTERRUPT, "serial 0 dma rec", NULL))
+		panic("irq23");
+#ifdef SERIAL_HANDLE_EARLY_ERRORS
+	if(request_irq(8, ser_interrupt, SA_INTERRUPT, "serial ", NULL))
+		panic("irq8");
+#endif
+	if(request_irq(24, tr_interrupt, SA_INTERRUPT, "serial 1 dma tr", NULL))
+		panic("irq24");
+	if(request_irq(25, rec_interrupt, SA_INTERRUPT, "serial 1 dma rec", NULL))
+		panic("irq25");
+#ifdef CONFIG_ETRAX100_SERIAL_PORT2
+	/* DMA Shared with par0 (and SCSI0 and ATA) */
+	if(request_irq(18, tr_interrupt, SA_SHIRQ, "serial 2 dma tr", NULL))
+		panic("irq18");
+	if(request_irq(19, rec_interrupt, SA_SHIRQ, "serial 2 dma rec", NULL))
+		panic("irq19");
+#endif
+#ifdef CONFIG_ETRAX100_SERIAL_PORT3
+	/* DMA Shared with par1 (and SCSI1 and Extern DMA 0) */
+	if(request_irq(20, tr_interrupt, SA_SHIRQ, "serial 3 dma tr", NULL))
+		panic("irq20");
+	if(request_irq(21, rec_interrupt, SA_SHIRQ, "serial 3 dma rec", NULL))
+		panic("irq21");
+#endif
+#ifdef CONFIG_ETRAX100_SERIAL_FLUSH_DMA_FAST
+	/* TODO: a timeout_interrupt needs to be written that calls timeout_handler */
+	if(request_irq(TIMER1_IRQ_NBR, timeout_interrupt, SA_SHIRQ,
+		       "fast serial dma timeout", NULL)) {
+		printk("err: timer1 irq\n");
+	}
+#endif
+#endif /* CONFIG_SVINTO_SIM */
+
+	return 0;
+}
+
+/* this makes sure that rs_init is called during kernel boot */
+
+module_init(rs_init);
+
+/*
+ * register_serial and unregister_serial allows for serial ports to be
+ * configured at run-time, to support PCMCIA modems.
+ */
+int 
+register_serial(struct serial_struct *req)
+{
+	return -1;
+}
+
+void unregister_serial(int line)
+{
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/drivers/serial.h linux/arch/cris/drivers/serial.h
--- v2.4.1/linux/arch/cris/drivers/serial.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/drivers/serial.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,106 @@
+/*
+ * serial.h: Arch-dep definitions for the Etrax100 serial driver.
+ *
+ * Copyright (C) 1998, 1999, 2000 Axis Communications AB
+ */
+
+#ifndef _ETRAX100_SERIAL_H
+#define _ETRAX100_SERIAL_H
+
+#include <linux/config.h>
+#include <linux/circ_buf.h>
+#include <asm/termios.h>
+
+/* Software state per channel */
+
+#ifdef __KERNEL__
+/*
+ * This is our internal structure for each serial port's state.
+ * 
+ * Many fields are paralleled by the structure used by the serial_struct
+ * structure.
+ *
+ * For definitions of the flags field, see tty.h
+ */
+
+struct e100_serial {
+	int                   baud;
+	volatile unsigned char *	port; /* R_SERIALx_CTRL */
+	unsigned long	        irq;  /* bitnr in R_IRQ_MASK2 for dmaX_descr */
+
+	volatile char *oclrintradr; /* adr to R_DMA_CHx_CLR_INTR, output */
+	volatile unsigned long *ofirstadr;   /* adr to R_DMA_CHx_FIRST, output */
+	volatile char *ocmdadr;     /* adr to R_DMA_CHx_CMD, output */
+	const volatile unsigned short *ostatusadr;  /* adr to R_DMA_CHx_STATUS, output */
+	volatile unsigned long  *ohwswadr;    /* adr to R_DMA_CHx_HWSW, output */
+
+	volatile char *iclrintradr; /* adr to R_DMA_CHx_CLR_INTR, input */
+	volatile unsigned long *ifirstadr;   /* adr to R_DMA_CHx_FIRST, input */
+	volatile char *icmdadr;     /* adr to R_DMA_CHx_CMD, input */
+	const volatile unsigned short *istatusadr;  /* adr to R_DMA_CHx_STATUS, input */
+	volatile unsigned long  *ihwswadr;    /* adr to R_DMA_CHx_HWSW, input */
+
+	int			flags; 		/* defined in tty.h */
+
+	unsigned char           rx_ctrl; /* shadow for R_SERIALx_REC_CTRL */
+	unsigned char           tx_ctrl; /* shadow for R_SERIALx_TR_CTRL */
+	unsigned char           iseteop; /* bit number for R_SET_EOP for the input dma */
+/* end of fields defined in rs_table[] in .c-file */
+	unsigned char           fifo_didmagic; /* a fifo eop has been forced */
+
+	struct etrax_dma_descr tr_descr, rec_descr;
+
+	int                     fifo_magic; /* fifo amount - bytes left in dma buffer */
+
+	volatile int            tr_running; /* 1 if output is running */
+
+	struct tty_struct 	*tty;
+	int			read_status_mask;
+	int			ignore_status_mask;
+	int			x_char;	/* xon/xoff character */
+	int			close_delay;
+	unsigned short	        closing_wait;
+	unsigned short	        closing_wait2;
+	unsigned long		event;
+	unsigned long		last_active;
+	int			line;
+	int                     type;  /* PORT_ETRAX100 */
+	int			count;	    /* # of fd on device */
+	int			blocked_open; /* # of blocked opens */
+	long			session; /* Session of opening process */
+	long			pgrp; /* pgrp of opening process */
+	struct circ_buf         xmit;
+
+	struct tq_struct	tqueue;
+	struct async_icount     icount;   /* error-statistics etc.*/
+	struct termios	        normal_termios;
+	struct termios	        callout_termios;
+#ifdef DECLARE_WAITQUEUE
+	wait_queue_head_t       open_wait;
+        wait_queue_head_t       close_wait;
+#else   
+        struct wait_queue       *open_wait;
+        struct wait_queue       *close_wait;
+#endif  
+
+#ifdef CONFIG_RS485
+	struct rs485_control    rs485;  /* RS-485 support */
+#endif
+};
+
+/* this PORT is not in the standard serial.h. it's not actually used for
+ * anything since we only have one type of async serial-port anyway in this
+ * system.
+ */
+
+#define PORT_ETRAX100 1
+
+/*
+ * Events are used to schedule things to happen at timer-interrupt
+ * time, instead of at rs interrupt time.
+ */
+#define RS_EVENT_WRITE_WAKEUP	0
+
+#endif /* __KERNEL__ */
+
+#endif /* !(_ETRAX100_SERIAL_H) */
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/Makefile linux/arch/cris/kernel/Makefile
--- v2.4.1/linux/arch/cris/kernel/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,25 @@
+# $Id: Makefile,v 1.3 2001/01/10 21:11:07 bjornw Exp $
+#
+# 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) $(AFLAGS) -traditional -c $< -o $*.o
+
+all: kernel.o head.o
+
+O_TARGET := kernel.o
+obj-y   := process.o signal.o entry.o traps.o irq.o \
+           ptrace.o setup.o time.o sys_cris.o shadows.o \
+	   debugport.o semaphore.o
+
+obj-$(CONFIG_KGDB) += kgdb.o
+
+clean:
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/debugport.c linux/arch/cris/kernel/debugport.c
--- v2.4.1/linux/arch/cris/kernel/debugport.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/debugport.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,242 @@
+/* Serialport functions for debugging
+ *
+ * Copyright (c) 2000 Axis Communications AB
+ *
+ * Authors:  Bjorn Wesen
+ *
+ * Exports:
+ *    console_print_etrax(char *buf)
+ *    int getDebugChar()
+ *    putDebugChar(int)
+ *    enableDebugIRQ()
+ *    init_etrax_debug()
+ *
+ * $Log: debugport.c,v $
+ * Revision 1.4  2000/10/06 12:37:26  bjornw
+ * Use physical addresses when talking to DMA
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/major.h>
+
+#include <asm/system.h>
+#include <asm/svinto.h>
+#include <asm/io.h>             /* Get SIMCOUT. */
+
+/* Which serial-port is our debug port ? */
+
+#if defined(CONFIG_DEBUG_PORT0) || defined(CONFIG_DEBUG_PORT_NULL)
+#define DEBUG_PORT_IDX 0
+#define DEBUG_OCMD R_DMA_CH6_CMD
+#define DEBUG_FIRST R_DMA_CH6_FIRST
+#define DEBUG_OCLRINT R_DMA_CH6_CLR_INTR
+#define DEBUG_STATUS R_DMA_CH6_STATUS
+#define DEBUG_READ R_SERIAL0_READ
+#define DEBUG_WRITE R_SERIAL0_TR_DATA
+#define DEBUG_TR_CTRL R_SERIAL0_TR_CTRL
+#define DEBUG_REC_CTRL R_SERIAL0_REC_CTRL
+#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser0_data, set)
+#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma6_descr, clr)
+#endif
+
+#ifdef CONFIG_DEBUG_PORT1
+#define DEBUG_PORT_IDX 1
+#define DEBUG_OCMD R_DMA_CH8_CMD
+#define DEBUG_FIRST R_DMA_CH8_FIRST
+#define DEBUG_OCLRINT R_DMA_CH8_CLR_INTR
+#define DEBUG_STATUS R_DMA_CH8_STATUS
+#define DEBUG_READ R_SERIAL1_READ
+#define DEBUG_WRITE R_SERIAL1_TR_DATA
+#define DEBUG_TR_CTRL R_SERIAL1_TR_CTRL
+#define DEBUG_REC_CTRL R_SERIAL1_REC_CTRL
+#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser1_data, set)
+#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma8_descr, clr)
+#endif
+
+#ifdef CONFIG_DEBUG_PORT2
+#define DEBUG_PORT_IDX 2
+#define DEBUG_OCMD R_DMA_CH2_CMD
+#define DEBUG_FIRST R_DMA_CH2_FIRST
+#define DEBUG_OCLRINT R_DMA_CH2_CLR_INTR
+#define DEBUG_STATUS R_DMA_CH2_STATUS
+#define DEBUG_READ R_SERIAL2_READ
+#define DEBUG_WRITE R_SERIAL2_TR_DATA
+#define DEBUG_TR_CTRL R_SERIAL2_TR_CTRL
+#define DEBUG_REC_CTRL R_SERIAL2_REC_CTRL
+#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser2_data, set)
+#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma2_descr, clr)
+#endif
+
+#ifdef CONFIG_DEBUG_PORT3
+#define DEBUG_PORT_IDX 3
+#define DEBUG_OCMD R_DMA_CH4_CMD
+#define DEBUG_FIRST R_DMA_CH4_FIRST
+#define DEBUG_OCLRINT R_DMA_CH4_CLR_INTR
+#define DEBUG_STATUS R_DMA_CH4_STATUS
+#define DEBUG_READ R_SERIAL3_READ
+#define DEBUG_WRITE R_SERIAL3_TR_DATA
+#define DEBUG_TR_CTRL R_SERIAL3_TR_CTRL
+#define DEBUG_REC_CTRL R_SERIAL3_REC_CTRL
+#define DEBUG_IRQ IO_STATE(R_IRQ_MASK1_SET, ser3_data, set)
+#define DEBUG_DMA_IRQ_CLR IO_STATE(R_IRQ_MASK2_CLR, dma4_descr, clr)
+#endif
+
+/* Write a string of count length to the console (debug port) using DMA, polled
+ * for completion. Interrupts are disabled during the whole process. Some
+ * caution needs to be taken to not interfere with ttyS business on this port.
+ */
+
+static void 
+console_write(struct console *co, const char *buf, unsigned int len)
+{
+	static struct etrax_dma_descr descr;
+	unsigned long flags; 
+	int in_progress;
+	
+#ifdef CONFIG_DEBUG_PORT_NULL
+        /* no debug printout at all */
+        return;
+#endif
+
+#ifdef CONFIG_SVINTO_SIM
+	/* no use to simulate the serial debug output */
+	SIMCOUT(buf,len);
+	return;
+#endif
+	
+	save_flags(flags);
+	cli();
+
+#ifdef CONFIG_KGDB
+	/* kgdb needs to output debug info using the gdb protocol */
+	putDebugString(buf, len);
+	restore_flags(flags);
+	return;
+#endif
+
+	/* make sure the transmitter is enabled. 
+	 * NOTE: this overrides any setting done in ttySx, to 8N1, no auto-CTS.
+	 * in the future, move the tr/rec_ctrl shadows from etrax100ser.c to
+	 * shadows.c and use it here as well...
+	 */
+
+	*DEBUG_TR_CTRL = 0x40;
+
+	/* if the tty has some ongoing business, remember it */
+
+	in_progress = *DEBUG_OCMD & 7;
+
+	if(in_progress) {
+		/* wait until the output dma channel is ready */
+		
+		while(*DEBUG_OCMD & 7) /* nothing */ ;
+	}
+
+	descr.ctrl = d_eol;
+	descr.sw_len = len;
+	descr.buf = __pa(buf);
+
+	*DEBUG_FIRST = __pa(&descr); /* write to R_DMAx_FIRST */
+	*DEBUG_OCMD = 1;       /* dma command start -> R_DMAx_CMD */
+
+	/* wait until the output dma channel is ready again */
+
+	while(*DEBUG_OCMD & 7) /* nothing */;
+
+	/* clear pending interrupts so we don't get a surprise below */
+
+	if(in_progress)
+		*DEBUG_OCLRINT = 2;  /* only clear EOP, leave DESCR for the tty */
+	else
+		*DEBUG_OCLRINT = 3;  /* clear both EOP and DESCR */
+
+	while(*DEBUG_STATUS & 0x7f); /* wait until output FIFO is empty as well */
+
+	restore_flags(flags);
+}
+
+/* legacy function */
+
+void
+console_print_etrax(const char *buf)
+{
+	console_write(NULL, buf, strlen(buf));
+}
+
+/* Use polling to get a single character FROM the debug port */
+
+int
+getDebugChar(void)
+{
+	unsigned long readval;
+	
+	do {
+		readval = *DEBUG_READ;
+	} while(!(readval & IO_MASK(R_SERIAL0_READ, data_avail)));
+
+	return (readval & IO_MASK(R_SERIAL0_READ, data_in));
+}
+
+/* Use polling to put a single character to the debug port */
+
+void
+putDebugChar(int val)
+{
+	while(!(*DEBUG_READ & IO_MASK(R_SERIAL0_READ, tr_ready))) ;
+;
+	*DEBUG_WRITE = val;
+}
+
+/* Enable irq for receiving chars on the debug port, used by kgdb */
+
+void
+enableDebugIRQ(void)
+{
+	*R_IRQ_MASK1_SET = DEBUG_IRQ;
+	/* use R_VECT_MASK directly, since we really bypass Linux normal
+	 * IRQ handling in kgdb anyway, we don't need to use enable_irq
+	 */
+	*R_VECT_MASK_SET = IO_STATE(R_VECT_MASK_SET, serial, set);
+
+	*DEBUG_REC_CTRL = IO_STATE(R_SERIAL0_REC_CTRL, rec_enable, enable);
+}
+
+static kdev_t 
+console_device(struct console *c)
+{
+         return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int __init 
+console_setup(struct console *co, char *options)
+{
+        return 0;
+}
+
+static struct console sercons = {
+        "ttyS",
+        console_write,
+        NULL,
+        console_device,
+        NULL,
+	NULL,
+	console_setup,
+	CON_PRINTBUFFER,
+	DEBUG_PORT_IDX,
+	0,
+	NULL
+};
+
+/*
+ *      Register console (for printk's etc)
+ */
+
+void __init 
+init_etrax_debug(void)
+{
+	register_console(&sercons);
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/entry.S linux/arch/cris/kernel/entry.S
--- v2.4.1/linux/arch/cris/kernel/entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/entry.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,738 @@
+/* $Id: entry.S,v 1.11 2001/01/10 21:13:29 bjornw Exp $
+ *
+ *  linux/arch/cris/entry.S
+ *
+ *  Copyright (C) 2000 Axis Communications AB
+ *
+ *  Authors:	Bjorn Wesen (bjornw@axis.com)
+ *
+ *  $Log: entry.S,v $
+ *  Revision 1.11  2001/01/10 21:13:29  bjornw
+ *  SYMBOL_NAME is defined incorrectly for the compiler options we currently use
+ *
+ *  Revision 1.10  2000/12/18 23:47:56  bjornw
+ *  * Added syscall trace support (ptrace), completely untested of course
+ *  * Removed redundant check for NULL entries in syscall_table
+ *
+ *  Revision 1.9  2000/11/21 16:40:51  bjornw
+ *  * New frame type used when an SBFS frame needs to be popped without
+ *    actually restarting the instruction
+ *  * Enable interrupts in signal_return (they did so in x86, I hope it's a good
+ *    idea)
+ *
+ *  Revision 1.8  2000/11/17 16:53:35  bjornw
+ *  Added detection of frame-type in Rexit, so that mmu_bus_fault can
+ *  use ret_from_intr in the return-path to check for signals (like SEGV)
+ *  and other foul things that might have occured during the fault.
+ *
+ *  Revision 1.7  2000/10/06 15:04:28  bjornw
+ *  Include mof in register savings
+ *
+ *  Revision 1.6  2000/09/12 16:02:44  bjornw
+ *  Linux-2.4.0-test7 derived updates
+ *
+ *  Revision 1.5  2000/08/17 15:35:15  bjornw
+ *  2.4.0-test6 changed local_irq_count and friends API
+ *
+ *  Revision 1.4  2000/08/02 13:59:30  bjornw
+ *  Removed olduname and uname from the syscall list
+ *
+ *  Revision 1.3  2000/07/31 13:32:58  bjornw
+ *  * Export ret_from_intr
+ *  * _resume updated (prev/last tjohejsan)
+ *  * timer_interrupt obsolete
+ *  * SIGSEGV detection in mmu_bus_fault temporarily disabled
+ *
+ *
+ */
+
+/*
+ * entry.S contains the system-call and fault low-level handling routines.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ * Stack layout in 'ret_from_system_call':
+ * 	ptrace needs to have all regs on the stack.
+ *	if the order here is changed, it needs to be 
+ *	updated in fork.c:copy_process, signal.c:do_signal,
+ *	ptrace.c and ptrace.h
+ *
+ */
+
+#include <linux/linkage.h>
+#include <linux/sys.h>
+			
+	;; functions exported from this file
+	
+	.globl _system_call
+	.globl _ret_from_intr
+	.globl _ret_from_sys_call
+	.globl _resume
+	.globl _multiple_interrupt
+	.globl _hwbreakpoint
+	.globl _IRQ1_interrupt
+	.globl _timer_interrupt
+	.globl _timer_shortcut
+	.globl _spurious_interrupt
+	.globl _hw_bp_trigs
+	.globl _mmu_bus_fault
+				
+	.globl _sys_call_table
+		
+	;; syscall error codes
+	
+LENOSYS = 38
+
+	;; offsets into the task_struct (found at sp aligned to THREAD_SIZE, 8192)
+	;; linux/sched.h
+	
+LTASK_SIGPENDING  =  8
+LTASK_NEEDRESCHED = 20
+LTASK_PTRACE      = 24
+
+	;; some pt_regs offsets (from ptrace.h)
+	
+LORIG_R10	= 4
+LR13		= 8
+LR12		= 12
+LR11		= 16
+LR10		= 20
+LR1		= 56
+LR0		= 60	
+LDCCR		= 68
+LSRP		= 72
+LIRP		= 76
+
+	;; below are various parts of system_call which are not in the fast-path
+	
+	;; handle software irqs
+				
+handle_softirq:
+	push	r9
+	jsr	_do_softirq		; call the C routine for softirq handling
+	pop	r9
+
+	;; fall-through
+	
+_ret_from_intr:
+	;; check for resched only if we're going back to user-mode
+
+	move	ccr, r0
+	btstq	8, r0		; U-flag
+	bpl	Rexit		; go back directly
+	nop
+	ba	ret_with_reschedule  ; go back but check schedule and signals first 
+	nop
+		
+reschedule:
+	;; keep r9 intact
+	push	r9
+	jsr	_schedule
+	pop	r9
+	ba	_ret_from_sys_call
+	nop
+
+	;; return but call do_signal first
+signal_return:
+	ei			; we can get here from an interrupt
+	move.d	r9,r10		; do_signals syscall/irq param
+	moveq	0,r11		; oldset param - 0 in this case
+	move.d	sp,r12		; another argument to do_signal (the regs param)
+	jsr	_do_signal	; arch/cris/kernel/signal.c
+	ba	Rexit
+	nop
+	
+	;; The system_call is called by a BREAK instruction, which works like
+	;; an interrupt call but it stores the return PC in BRP instead of IRP.
+	;; Since we dont really want to have two epilogues (one for system calls
+	;; and one for interrupts) we push the contents of BRP instead of IRP in the
+	;; system call prologue, to make it look like an ordinary interrupt on the
+	;; stackframe.
+	;;
+	;; Since we can't have system calls inside interrupts, it should not matter
+	;; that we don't stack IRP.
+	;; 
+	;; In r1 we have the wanted syscall number. Arguments come in r10,r11,r12,r13,r0
+	;;
+	;; This function looks on the _surface_ like spaghetti programming, but it's
+	;; really designed so that the fast-path does not force cache-loading of non-used
+	;; instructions. Only the non-common cases cause the outlined code to run..
+
+_system_call:
+	;; stack-frame similar to the irq heads, which is reversed in ret_from_sys_call
+	push	brp		; this is normally push irp
+	push	srp
+	push	dccr
+	push	mof
+	subq	14*4,sp		; make room for r0-r13
+	movem	r13,[sp]	; push r0-r13
+	push	r10		; push orig_r10
+	clear.d [sp=sp-4]	; frametype == 0, normal stackframe
+	
+	move.d	r10,r2		; save for later
+	
+	movs.w	-LENOSYS,r10
+	move.d	r10,[sp+LR10]	; put the default return value in r10 in the frame
+	
+	move.d	sp,r10
+	jsr	_set_esp0	; save top of frame (clobbers r9...)
+
+	;; check if this process is syscall-traced
+
+	move.d	sp, r10
+	and.d	-8192, r10		; THREAD_SIZE == 8192
+	move.d	[r10+LTASK_PTRACE],r10
+	btstq	2, r10	                ; PT_TRACESYS
+	bmi	tracesys
+	nop	
+
+	;; check for sanity in the requested syscall number
+	
+	cmpu.w	NR_syscalls,r1	
+	bcc	_ret_from_sys_call
+	lslq	2,r1		;  multiply by 4, in the delay slot
+
+	;; read the system call vector into r1
+	
+	move.d	[r1+_sys_call_table],r1	
+
+	;; the parameter carrying registers r11, r12 and 13 are intact - restore r10.
+	;; the fifth parameter (if any) was in r0, and we need to put it on the stack
+
+	push	r0
+	move.d	r2,r10
+	
+	jsr	r1		; actually call the corresponding system call
+	addq	4,sp		; pop the r0 parameter
+	move.d	r10,[sp+LR10]	; save the return value
+
+	moveq	1,r9		; "parameter" to ret_from_sys_call to show it was a sys call
+	
+	;; fall through into ret_from_sys_call to return
+	
+_ret_from_sys_call:
+	;; r9 is a parameter - if 1, we came from a syscall, if 0, from an irq
+		
+	;; check if any bottom halves need service
+	
+	move.d	[_irq_stat],r0	       ; softirq_active
+	and.d	[_irq_stat+4],r0       ; softirq_mask
+	bne	handle_softirq
+	nop
+
+ret_with_reschedule:
+	;; first get the current task-struct pointer (see top for defs)
+
+	move.d	sp, r0
+	and.d	-8192, r0	; THREAD_SIZE == 8192
+	
+	;; see if we want to reschedule into another process
+	
+	test.d	[r0+LTASK_NEEDRESCHED]
+	bne	reschedule
+	nop
+
+	;; see if we need to run signal checks (important that r9 is intact here)
+
+	test.d	[r0+LTASK_SIGPENDING]
+	bne	signal_return
+	nop
+	
+Rexit:
+	;; this epilogue MUST match the prologues in multiple_interrupt, irq.h and ptregs.h
+	pop	r10		; frametype
+	bne	RBFexit		; was not CRIS_FRAME_NORMAL, handle otherwise
+	addq	4,sp		; skip orig_r10, in delayslot
+	movem	[sp+],r13	; registers r0-r13
+	pop	mof		; multiply overflow register 
+	pop	dccr		; condition codes
+	pop	srp		; subroutine return pointer
+	jmpu	[sp+]		; return by popping irp and jumping there
+	;; jmpu takes the U-flag into account to see if we return to
+	;; user-mode or kernel mode.
+
+RBFexit:
+	cmpq	2, r10		; was it CRIS_FRAME_FIXUP ?
+	beq	2f
+	movem	[sp+],r13	; registers r0-r13, in delay slot
+	pop	mof		; multiply overflow register 
+	pop	dccr		; condition codes
+	pop	srp		; subroutine return pointer
+	rbf	[sp+]		; return by popping the CPU status
+
+2:	pop	mof		; multiply overflow register
+	pop	dccr		; condition codes
+	pop	srp		; subroutine return pointer
+	;; now we have a 4-word SBFS frame which we do not want to restore
+	;; using RBF since we have made a fixup. instead we would like to
+	;; just get the PC value to restart it with, and skip the rest of
+	;; the frame.
+	pop	irp		; fixup location will be here
+	pop	p8		; null pop
+	pop	p8		; null pop
+	reti			; return to IRP, taking U-flag into account
+	pop	p8		; null pop in delayslot
+
+
+tracesys:
+	;; this first invocation of syscall_trace _requires_ that
+	;; LR10 in the frame contains -LENOSYS (as is set in the beginning
+	;; of system_call
+
+	jsr	_syscall_trace
+
+	;; now we should more or less do the same things as in the system_call
+	;; but since our argument regs got clobbered during syscall_trace and
+	;; because syscall_trace might want to alter them, we need to reload them
+	;; from the stack-frame as we use them.
+
+	;; check for sanity in the requested syscall number
+
+	move.d	[sp+LR1], r1
+	movs.w	-LENOSYS, r10
+	cmpu.w	NR_syscalls,r1	
+	bcc	1f
+	lslq	2,r1		;  multiply by 4, in the delay slot
+
+	;; read the system call vector entry into r1
+	
+	move.d	[r1+_sys_call_table],r1
+
+	;; restore r10, r11, r12, r13 and r0 into the needed registers
+
+	move.d	[sp+LORIG_R10], r10  ; LR10 is already filled with -LENOSYS
+	move.d	[sp+LR11],      r11
+	move.d	[sp+LR12],      r12
+	move.d	[sp+LR13],      r13
+	move.d	[sp+LR0],       r0
+
+	;; the fifth parameter needs to be put on the stack for the system
+	;; call to find it
+
+	push	r0
+	jsr	r1		; actually call the system-call
+	addq	4,sp		; pop the r0 parameter
+
+1:	move.d	r10,[sp+LR10]	; save the return value
+
+	;; second call of syscall_trace, to let it grab the results
+		
+	jsr	_syscall_trace
+
+	moveq	1,r9		; "parameter" to ret_from_sys_call to show it was a sys call
+	ba	_ret_from_sys_call
+	nop
+		
+	;; from asm/processor.h, the thread_struct
+	
+LTHREAD_KSP	= 0
+LTHREAD_USP	= 4
+LTHREAD_ESP0	= 8
+LTHREAD_DCCR	= 12
+	
+	;; _resume performs the actual task-switching, by switching stack pointers
+	;; input arguments: r10 = prev, r11 = next, r12 = thread offset in task struct
+	;; returns old current in r10
+	;;
+	;; TODO:  see the i386 version. The switch_to which calls resume in our version
+	;;        could really be an inline asm of this.
+
+_resume:	
+	push	srp		         ; we keep the old/new PC on the stack 
+	add.d	r12, r10		 ; r10 = current tasks tss
+	move	dccr, [r10+LTHREAD_DCCR] ; save irq enable state
+	di
+
+	move	usp, [r10+LTHREAD_USP]	 ; save user-mode stackpointer
+	
+	subq	10*4, sp
+	movem	r9, [sp]		 ; save non-scratch registers
+	
+	move.d	sp, [r10+LTHREAD_KSP]	 ; save the kernel stack pointer for the old task
+	move.d	sp, r10			 ; return last running task in r10
+	and.d   -8192, r10	         ; get task ptr from stackpointer
+	add.d	r12, r11		 ; find the new tasks tss
+	move.d	[r11+LTHREAD_KSP], sp	 ; switch into the new stackframe by restoring kernel sp
+
+	movem	[sp+], r9		 ; restore non-scratch registers
+
+	move	[r11+LTHREAD_USP], usp	 ; restore user-mode stackpointer
+	
+	move	[r11+LTHREAD_DCCR], dccr ; restore irq enable status
+	jump	[sp+]		         ; restore PC
+
+	;; This is the MMU bus fault handler.
+	;; It needs to stack the CPU status and overall is different
+	;; from the other interrupt handlers.
+
+_mmu_bus_fault:	
+	sbfs	[sp=sp-16]	; push the internal CPU status
+	;; the first longword in the sbfs frame was the interrupted PC
+	;; which fits nicely with the "IRP" slot in pt_regs normally used to
+	;; contain the return address. used by Oops to print kernel errors..
+	push	srp		; make a stackframe similar to pt_regs
+	push	dccr
+	push	mof
+	di
+	subq	14*4, sp
+	movem	r13, [sp]
+	push	r10		; dummy orig_r10
+	moveq	1, r10
+	push	r10		; frametype == 1, BUSFAULT frame type
+
+	moveq	0, r9		; busfault is equivalent to an irq
+		
+	move.d	sp, r10		; pt_regs argument to handle_mmu_bus_fault
+		
+	jsr	_handle_mmu_bus_fault  ; in arch/cris/mm/fault.c
+
+	;; now we need to return through the normal path, we cannot just
+	;; do the RBFexit since we might have killed off the running
+	;; process due to a SEGV, scheduled due to a page blocking or
+	;; whatever.
+
+	ba	_ret_from_intr
+	nop
+		
+	;; special handlers for breakpoint and NMI
+#if 0			
+_hwbreakpoint:
+	push	dccr
+	di
+	push	r10
+	push	r11
+	push	r12
+	push	r13
+	clearf	b
+	move	brp,r11
+	move.d	[_hw_bp_msg],r10
+	jsr	_printk
+	setf	b
+	pop	r13
+	pop	r12
+	pop	r11
+	pop	r10
+	pop	dccr
+	retb
+	nop
+#else
+_hwbreakpoint:
+	push	dccr
+	di
+#if 1
+	push	r10
+	push	r11
+	move.d	[_hw_bp_trig_ptr],r10
+	move.d	[r10],r11
+	cmp.d	42,r11
+	beq	nobp
+	nop
+	move	brp,r11
+	move.d	r11,[r10+]
+	move.d	r10,[_hw_bp_trig_ptr]
+nobp:	pop	r11
+	pop	r10
+#endif
+	pop	dccr
+	retb
+	nop
+#endif
+	
+_IRQ1_interrupt:
+_spurious_interrupt:	
+	di
+	move.b	4,r0
+	move.b	r0,[0xb0000030]
+basse2:	ba	basse2
+	nop
+
+	;; this handles the case when multiple interrupts arrive at the same time
+	;; we jump to the first set interrupt bit in a priority fashion
+	;; the hardware will call the unserved interrupts after the handler finishes
+	
+_multiple_interrupt:
+	;; this prologue MUST match the one in irq.h and the struct in ptregs.h!!!
+	push	irp
+	push	srp
+	push	dccr
+	push	mof
+	di
+	subq	14*4,sp
+	movem	r13,[sp]
+	push	r10		; push orig_r10
+	clear.d [sp=sp-4]	; frametype == 0, normal frame
+	
+	move.d	_irq_shortcuts + 8,r1
+	moveq	2,r2		; first bit we care about is the timer0 irq
+	move.d	[0xb00000d8],r0	; read the irq bits that triggered the multiple irq
+multloop:	
+	btst	r2,r0		; check for the irq given by bit r2
+	bmi	do_shortcut	; actually do the shortcut
+	nop
+	addq	1,r2		; next vector bit - remember this is in the delay slot!
+	addq	4,r1		; next vector
+	cmpq	26,r2
+	bne	multloop	; process all irq's up to and including number 25
+	nop
+	
+	;; strange, we didn't get any set vector bits.. oh well, just return
+	
+	ba	Rexit
+	nop
+
+do_shortcut:
+	test.d	[r1]
+	beq	Rexit
+	nop
+	jump	[r1]		; jump to the irq handlers shortcut
+
+	
+	.data
+
+_hw_bp_trigs:
+	.space 64*4
+_hw_bp_trig_ptr:
+	.dword _hw_bp_trigs
+
+/* linux/linkage.h got it wrong for this compiler currently */
+	
+#undef SYMBOL_NAME
+#define SYMBOL_NAME(X) _/**/X
+		
+_sys_call_table:	
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 0  -  old "setup()" system call*/
+	.long SYMBOL_NAME(sys_exit)
+	.long SYMBOL_NAME(sys_fork)
+	.long SYMBOL_NAME(sys_read)
+	.long SYMBOL_NAME(sys_write)
+	.long SYMBOL_NAME(sys_open)		/* 5 */
+	.long SYMBOL_NAME(sys_close)
+	.long SYMBOL_NAME(sys_waitpid)
+	.long SYMBOL_NAME(sys_creat)
+	.long SYMBOL_NAME(sys_link)
+	.long SYMBOL_NAME(sys_unlink)		/* 10 */
+	.long SYMBOL_NAME(sys_execve)
+	.long SYMBOL_NAME(sys_chdir)
+	.long SYMBOL_NAME(sys_time)
+	.long SYMBOL_NAME(sys_mknod)
+	.long SYMBOL_NAME(sys_chmod)		/* 15 */
+	.long SYMBOL_NAME(sys_lchown16)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old break syscall holder */
+	.long SYMBOL_NAME(sys_stat)
+	.long SYMBOL_NAME(sys_lseek)
+	.long SYMBOL_NAME(sys_getpid)		/* 20 */
+	.long SYMBOL_NAME(sys_mount)
+	.long SYMBOL_NAME(sys_oldumount)
+	.long SYMBOL_NAME(sys_setuid16)
+	.long SYMBOL_NAME(sys_getuid16)
+	.long SYMBOL_NAME(sys_stime)		/* 25 */
+	.long SYMBOL_NAME(sys_ptrace)
+	.long SYMBOL_NAME(sys_alarm)
+	.long SYMBOL_NAME(sys_fstat)
+	.long SYMBOL_NAME(sys_pause)
+	.long SYMBOL_NAME(sys_utime)		/* 30 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old stty syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old gtty syscall holder */
+	.long SYMBOL_NAME(sys_access)
+	.long SYMBOL_NAME(sys_nice)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* 35  old ftime syscall holder */
+	.long SYMBOL_NAME(sys_sync)
+	.long SYMBOL_NAME(sys_kill)
+	.long SYMBOL_NAME(sys_rename)
+	.long SYMBOL_NAME(sys_mkdir)
+	.long SYMBOL_NAME(sys_rmdir)		/* 40 */
+	.long SYMBOL_NAME(sys_dup)
+	.long SYMBOL_NAME(sys_pipe)
+	.long SYMBOL_NAME(sys_times)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old prof syscall holder */
+	.long SYMBOL_NAME(sys_brk)		/* 45 */
+	.long SYMBOL_NAME(sys_setgid16)
+	.long SYMBOL_NAME(sys_getgid16)
+	.long SYMBOL_NAME(sys_signal)
+	.long SYMBOL_NAME(sys_geteuid16)
+	.long SYMBOL_NAME(sys_getegid16)	/* 50 */
+	.long SYMBOL_NAME(sys_acct)
+	.long SYMBOL_NAME(sys_umount)		/* recycled never used phys() */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old lock syscall holder */
+	.long SYMBOL_NAME(sys_ioctl)
+	.long SYMBOL_NAME(sys_fcntl)		/* 55 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old mpx syscall holder */
+	.long SYMBOL_NAME(sys_setpgid)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old ulimit syscall holder */
+	.long SYMBOL_NAME(sys_ni_syscall)       /* old sys_olduname holder */
+	.long SYMBOL_NAME(sys_umask)		/* 60 */
+	.long SYMBOL_NAME(sys_chroot)
+	.long SYMBOL_NAME(sys_ustat)
+	.long SYMBOL_NAME(sys_dup2)
+	.long SYMBOL_NAME(sys_getppid)
+	.long SYMBOL_NAME(sys_getpgrp)		/* 65 */
+	.long SYMBOL_NAME(sys_setsid)
+	.long SYMBOL_NAME(sys_sigaction)
+	.long SYMBOL_NAME(sys_sgetmask)
+	.long SYMBOL_NAME(sys_ssetmask)
+	.long SYMBOL_NAME(sys_setreuid16)	/* 70 */
+	.long SYMBOL_NAME(sys_setregid16)
+	.long SYMBOL_NAME(sys_sigsuspend)
+	.long SYMBOL_NAME(sys_sigpending)
+	.long SYMBOL_NAME(sys_sethostname)
+	.long SYMBOL_NAME(sys_setrlimit)	/* 75 */
+	.long SYMBOL_NAME(sys_old_getrlimit)
+	.long SYMBOL_NAME(sys_getrusage)
+	.long SYMBOL_NAME(sys_gettimeofday)
+	.long SYMBOL_NAME(sys_settimeofday)
+	.long SYMBOL_NAME(sys_getgroups16)	/* 80 */
+	.long SYMBOL_NAME(sys_setgroups16)
+	.long SYMBOL_NAME(sys_select)           /* was old_select in Linux/E100 */
+	.long SYMBOL_NAME(sys_symlink)
+	.long SYMBOL_NAME(sys_lstat)
+	.long SYMBOL_NAME(sys_readlink)		/* 85 */
+	.long SYMBOL_NAME(sys_uselib)
+	.long SYMBOL_NAME(sys_swapon)
+	.long SYMBOL_NAME(sys_reboot)
+	.long SYMBOL_NAME(old_readdir)
+	.long SYMBOL_NAME(old_mmap)		/* 90 */
+	.long SYMBOL_NAME(sys_munmap)
+	.long SYMBOL_NAME(sys_truncate)
+	.long SYMBOL_NAME(sys_ftruncate)
+	.long SYMBOL_NAME(sys_fchmod)
+	.long SYMBOL_NAME(sys_fchown16)		/* 95 */
+	.long SYMBOL_NAME(sys_getpriority)
+	.long SYMBOL_NAME(sys_setpriority)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old profil syscall holder */
+	.long SYMBOL_NAME(sys_statfs)
+	.long SYMBOL_NAME(sys_fstatfs)		/* 100 */
+	.long SYMBOL_NAME(sys_ni_syscall)       /* sys_ioperm in i386 */
+	.long SYMBOL_NAME(sys_socketcall)
+	.long SYMBOL_NAME(sys_syslog)
+	.long SYMBOL_NAME(sys_setitimer)
+	.long SYMBOL_NAME(sys_getitimer)	/* 105 */
+	.long SYMBOL_NAME(sys_newstat)
+	.long SYMBOL_NAME(sys_newlstat)
+	.long SYMBOL_NAME(sys_newfstat)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old sys_uname holder */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_iopl in i386 */
+	.long SYMBOL_NAME(sys_vhangup)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* old "idle" system call */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* vm86old in i386 */
+	.long SYMBOL_NAME(sys_wait4)
+	.long SYMBOL_NAME(sys_swapoff)		/* 115 */
+	.long SYMBOL_NAME(sys_sysinfo)
+	.long SYMBOL_NAME(sys_ipc)
+	.long SYMBOL_NAME(sys_fsync)
+	.long SYMBOL_NAME(sys_sigreturn)
+	.long SYMBOL_NAME(sys_clone)		/* 120 */
+	.long SYMBOL_NAME(sys_setdomainname)
+	.long SYMBOL_NAME(sys_newuname)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* TODO sys_modify_ldt - do something ?*/
+	.long SYMBOL_NAME(sys_adjtimex)
+	.long SYMBOL_NAME(sys_mprotect)		/* 125 */
+	.long SYMBOL_NAME(sys_sigprocmask)
+	.long SYMBOL_NAME(sys_create_module)
+	.long SYMBOL_NAME(sys_init_module)
+	.long SYMBOL_NAME(sys_delete_module)
+	.long SYMBOL_NAME(sys_get_kernel_syms)	/* 130 */
+	.long SYMBOL_NAME(sys_quotactl)
+	.long SYMBOL_NAME(sys_getpgid)
+	.long SYMBOL_NAME(sys_fchdir)
+	.long SYMBOL_NAME(sys_bdflush)
+	.long SYMBOL_NAME(sys_sysfs)		/* 135 */
+	.long SYMBOL_NAME(sys_personality)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* for afs_syscall */
+	.long SYMBOL_NAME(sys_setfsuid16)
+	.long SYMBOL_NAME(sys_setfsgid16)
+	.long SYMBOL_NAME(sys_llseek)		/* 140 */
+	.long SYMBOL_NAME(sys_getdents)
+	.long SYMBOL_NAME(sys_select)
+	.long SYMBOL_NAME(sys_flock)
+	.long SYMBOL_NAME(sys_msync)
+	.long SYMBOL_NAME(sys_readv)		/* 145 */
+	.long SYMBOL_NAME(sys_writev)
+	.long SYMBOL_NAME(sys_getsid)
+	.long SYMBOL_NAME(sys_fdatasync)
+	.long SYMBOL_NAME(sys_sysctl)
+	.long SYMBOL_NAME(sys_mlock)		/* 150 */
+	.long SYMBOL_NAME(sys_munlock)
+	.long SYMBOL_NAME(sys_mlockall)
+	.long SYMBOL_NAME(sys_munlockall)
+	.long SYMBOL_NAME(sys_sched_setparam)
+	.long SYMBOL_NAME(sys_sched_getparam)   /* 155 */
+	.long SYMBOL_NAME(sys_sched_setscheduler)
+	.long SYMBOL_NAME(sys_sched_getscheduler)
+	.long SYMBOL_NAME(sys_sched_yield)
+	.long SYMBOL_NAME(sys_sched_get_priority_max)
+	.long SYMBOL_NAME(sys_sched_get_priority_min)  /* 160 */
+	.long SYMBOL_NAME(sys_sched_rr_get_interval)
+	.long SYMBOL_NAME(sys_nanosleep)
+	.long SYMBOL_NAME(sys_mremap)
+	.long SYMBOL_NAME(sys_setresuid16)
+	.long SYMBOL_NAME(sys_getresuid16)	/* 165 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* sys_vm86 */
+	.long SYMBOL_NAME(sys_query_module)
+	.long SYMBOL_NAME(sys_poll)
+	.long SYMBOL_NAME(sys_nfsservctl)
+	.long SYMBOL_NAME(sys_setresgid16)	/* 170 */
+	.long SYMBOL_NAME(sys_getresgid16)
+	.long SYMBOL_NAME(sys_prctl)
+	.long SYMBOL_NAME(sys_rt_sigreturn)
+	.long SYMBOL_NAME(sys_rt_sigaction)
+	.long SYMBOL_NAME(sys_rt_sigprocmask)	/* 175 */
+	.long SYMBOL_NAME(sys_rt_sigpending)
+	.long SYMBOL_NAME(sys_rt_sigtimedwait)
+	.long SYMBOL_NAME(sys_rt_sigqueueinfo)
+	.long SYMBOL_NAME(sys_rt_sigsuspend)
+	.long SYMBOL_NAME(sys_pread)		/* 180 */
+	.long SYMBOL_NAME(sys_pwrite)
+	.long SYMBOL_NAME(sys_chown16)
+	.long SYMBOL_NAME(sys_getcwd)
+	.long SYMBOL_NAME(sys_capget)
+	.long SYMBOL_NAME(sys_capset)           /* 185 */
+	.long SYMBOL_NAME(sys_sigaltstack)
+	.long SYMBOL_NAME(sys_sendfile)
+	.long SYMBOL_NAME(sys_ni_syscall)	/* streams1 */
+	.long SYMBOL_NAME(sys_ni_syscall)	/* streams2 */
+	.long SYMBOL_NAME(sys_vfork)            /* 190 */
+	.long SYMBOL_NAME(sys_getrlimit)
+	.long SYMBOL_NAME(sys_mmap2)
+	.long SYMBOL_NAME(sys_truncate64)
+	.long SYMBOL_NAME(sys_ftruncate64)
+	.long SYMBOL_NAME(sys_stat64)		/* 195 */
+	.long SYMBOL_NAME(sys_lstat64)
+	.long SYMBOL_NAME(sys_fstat64)
+	.long SYMBOL_NAME(sys_lchown)
+	.long SYMBOL_NAME(sys_getuid)
+	.long SYMBOL_NAME(sys_getgid)		/* 200 */
+	.long SYMBOL_NAME(sys_geteuid)
+	.long SYMBOL_NAME(sys_getegid)
+	.long SYMBOL_NAME(sys_setreuid)
+	.long SYMBOL_NAME(sys_setregid)
+	.long SYMBOL_NAME(sys_getgroups)	/* 205 */
+	.long SYMBOL_NAME(sys_setgroups)
+	.long SYMBOL_NAME(sys_fchown)
+	.long SYMBOL_NAME(sys_setresuid)
+	.long SYMBOL_NAME(sys_getresuid)
+	.long SYMBOL_NAME(sys_setresgid)	/* 210 */
+	.long SYMBOL_NAME(sys_getresgid)
+	.long SYMBOL_NAME(sys_chown)
+	.long SYMBOL_NAME(sys_setuid)
+	.long SYMBOL_NAME(sys_setgid)
+	.long SYMBOL_NAME(sys_setfsuid)		/* 215 */
+	.long SYMBOL_NAME(sys_setfsgid)
+	.long SYMBOL_NAME(sys_pivot_root)
+	.long SYMBOL_NAME(sys_mincore)
+	.long SYMBOL_NAME(sys_madvise)
+	.long SYMBOL_NAME(sys_getdents64)       /* 220 */
+
+        /*
+         * NOTE!! This doesn't have to be exact - we just have
+         * to make sure we have _enough_ of the "sys_ni_syscall"
+         * entries. Don't panic if you notice that this hasn't
+         * been shrunk every time we add a new system call.
+         */
+
+	;; TODO: this needs to actually generate sys_ni_syscall entires
+	;; since we now have removed the check for NULL entries in this
+	;; table in system_call!
+	
+	.space (NR_syscalls-220)*4
+	
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/head.S linux/arch/cris/kernel/head.S
--- v2.4.1/linux/arch/cris/kernel/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/head.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,519 @@
+	;; $Id: head.S,v 1.11 2001/01/16 16:31:38 bjornw Exp $
+	;; 
+	;; Head of the kernel - alter with care
+	;;
+	;; Copyright (C) 2000, 2001 Axis Communications AB
+	;;
+	;; Authors:	Bjorn Wesen (bjornw@axis.com)
+	;; 
+	;; $Log: head.S,v $
+	;; Revision 1.11  2001/01/16 16:31:38  bjornw
+	;; * Changed name and semantics of running_from_flash to romfs_in_flash,
+	;;   set by head.S to indicate to setup.c whether there is a cramfs image
+	;;   after the kernels BSS or not. Should work for all three boot-cases
+	;;   (DRAM with cramfs in DRAM, DRAM with cramfs in flash (compressed boot),
+	;;    and flash with cramfs in flash)
+	;;
+	;; Revision 1.10  2001/01/16 14:12:21  bjornw
+	;; * Check for cramfs start passed in r9 from the decompressor, if all other
+	;;   cramfs options fail (if we boot from DRAM but don't find a cramfs image
+	;;   after the kernel in DRAM, it is probably still in the flash)
+	;; * Check magic in cramfs detection when booting from flash directly
+	;;
+	;; Revision 1.9  2001/01/15 17:17:02  bjornw
+	;; * Corrected the code that detects the cramfs lengths
+	;; * Added a comment saying that the above does not work due to other
+	;;   reasons..
+	;;
+	;; Revision 1.8  2001/01/15 16:27:51  jonashg
+	;; Made boot after flashing work.
+	;; * end destination is __vmlinux_end in RAM.
+	;; * _romfs_start moved because of virtual memory.
+	;;
+	;; Revision 1.7  2000/11/21 13:55:29  bjornw
+	;; Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
+	;;
+	;; Revision 1.6  2000/10/06 12:36:55  bjornw
+	;; Forgot swapper_pg_dir when changing memory map..
+	;;
+	;; Revision 1.5  2000/10/04 16:49:30  bjornw
+	;; * Fixed memory mapping in LX
+	;; * Check for cramfs instead of romfs
+	;;
+	;;
+	
+#include <linux/config.h>
+#define ASSEMBLER_MACROS_ONLY
+#include <asm/sv_addr_ag.h>
+
+#define CRAMFS_MAGIC 0x28cd3d45
+	
+	;; exported symbols
+		
+	.globl	_etrax_irv
+	.globl	_romfs_start
+	.globl	_romfs_length
+	.globl	_romfs_in_flash
+	.globl  _swapper_pg_dir
+					
+	.text
+
+	;; This is the entry point of the kernel. We are in supervisor mode.
+	;; 0x00000000 if Flash, 0x40004000 if DRAM
+	;; since etrax actually starts at address 2 when booting from flash, we
+	;; put a nop (2 bytes) here first so we dont accidentally skip the di
+	;;
+	;; NOTICE! The register r9 is used as a parameter carrying register from
+	;; the decompressor (if the kernel was compressed). It should not be
+	;; used in the code below until it is read.
+	
+	nop	
+	di
+
+	;; First setup the kseg_c mapping from where the kernel is linked
+	;; to 0x40000000 (where the actual DRAM resides) otherwise
+	;; we cannot do very much! See arch/cris/README.mm
+	;;
+	;; Notice that since we're potentially running at 0x00 or 0x40 right now,
+	;; we will get a fault as soon as we enable the MMU if we dont
+	;; temporarily map those segments linearily.
+	;;
+	;; Due to a bug in Etrax-100 LX version 1 we need to map the memory
+	;; slightly different. We also let the simulator get this mapping for now.
+
+#ifdef CONFIG_CRIS_LOW_MAP
+	move.d	0x0800b000, r0	; kseg mappings
+	move.d	r0, [R_MMU_KBASE_HI]
+
+	move.d	0x04040000, r0	; temporary map of 0x40->0x40 and 0x00->0x00 
+	move.d	r0, [R_MMU_KBASE_LO]
+
+	move.d	0x80074871, r0	; mmu enable, segs e,b,6,5,4,0 segment mapped
+	move.d	r0, [R_MMU_CONFIG]
+#else
+	move.d	0x0804b000, r0	; kseg mappings
+	move.d	r0, [R_MMU_KBASE_HI]
+
+	move.d	0x00040000, r0	; temporary map of 0x40->0x40 and 0x00->0x00 
+	move.d	r0, [R_MMU_KBASE_LO]
+
+	move.d	0x8007d811, r0	; mmu enable, segs f,e,c,b,4,0 segment mapped
+	move.d	r0, [R_MMU_CONFIG]
+#endif
+
+	;; Now we need to sort out the segments and their locations in RAM or
+	;; Flash. The image in the Flash (or in DRAM) consists of 3 pieces:
+	;; 1) kernel text, 2) kernel data, 3) ROM filesystem image
+	;; But the linker has linked the kernel to expect this layout in
+	;; DRAM memory:
+	;; 1) kernel text, 2) kernel data, 3) kernel BSS
+	;; (the location of the ROM filesystem is determined by the krom driver)
+	;; If we boot this from Flash, we want to keep the ROM filesystem in
+	;; the flash, we want to copy the text and need to copy the data to DRAM.
+	;; But if we boot from DRAM, we need to move the ROMFS image
+	;; from its position after kernel data, to after kernel BSS, BEFORE the
+	;; kernel starts using the BSS area (since its "overlayed" with the ROMFS)
+	;;
+	;; In both cases, we start in un-cached mode, and need to jump into a
+	;; cached PC after we're done fiddling around with the segments.
+	;; 
+	;; arch/etrax100/etrax100.ld sets some symbols that define the start
+	;; and end of each segment.
+	
+	;; Check if we start from DRAM or FLASH by testing PC
+	
+	move.d	pc,r0
+	and.d	0x7fffffff,r0	; get rid of the non-cache bit
+	cmp.d	0x10000,r0	; arbitrary... just something above this code
+	bcs	inflash
+	nop
+
+	jump	inram		; enter cached ram
+	
+inflash:
+
+#ifndef CONFIG_SVINTO_SIM	
+
+	;; We need to setup the bus registers before we start using the DRAM
+
+	move.d   DEF_R_WAITSTATES, r0
+	move.d   r0, [R_WAITSTATES]
+
+	move.d   DEF_R_BUS_CONFIG, r0
+	move.d   r0, [R_BUS_CONFIG]
+  
+	move.d   DEF_R_DRAM_CONFIG, r0
+	move.d   r0, [R_DRAM_CONFIG]
+
+	move.d   DEF_R_DRAM_TIMING, r0
+	move.d   r0, [R_DRAM_TIMING]
+
+#endif
+	;; Copy text+data to DRAM
+	;; This is fragile - the calculation of r4 as the image size depends
+	;; on that the labels below actually are the first and last positions
+	;; in the linker-script.
+	;;
+	;; Then the locating of the cramfs image depends on the aforementioned
+	;; image being located in the flash at 0. This is most often not true,
+	;; thus the following does not work (normally there is a rescue-block
+	;; between the physical start of the flash and the flash-image start,
+	;; and when run with compression, the kernel is actually unpacked to
+	;; DRAM and we never get here in the first place :))
+	
+	moveq	0, r0			; source
+	move.d	_text_start, r1		; destination
+	move.d	__vmlinux_end, r2	; end destination
+	move.d	r2, r4
+	sub.d	r1, r4			; r4=__vmlinux_end in flash, used below
+1:	move.w	[r0+], r3
+	move.w	r3, [r1+]
+	cmp.d	r2, r1
+	bcs	1b
+	nop
+
+	;; We keep the cramfs in the flash.
+	;; There might be none, but that does not matter because
+	;; we don't do anything than read some bytes here.
+
+	moveq	0, r0
+	move.d	r0, [_romfs_length] ; default if there is no cramfs
+
+	move.d  [r4], r0	; cramfs_super.magic
+	cmp.d	CRAMFS_MAGIC, r0
+	bne	1f
+	nop
+	move.d	[r4 + 4], r0	; cramfs_super.size
+	move.d	r0, [_romfs_length]
+#ifdef CONFIG_CRIS_LOW_MAP
+	add.d   0x50000000, r4	; add flash start in virtual memory (cached)
+#else
+	add.d   0xf0000000, r4	; add flash start in virtual memory (cached)
+#endif
+	move.d	r4, [_romfs_start]
+1:	
+	moveq	1, r0
+	move.d	r0, [_romfs_in_flash]
+		
+	jump	start_it	; enter code, cached this time
+
+inram:
+	;; Move the ROM fs to after BSS end. This assumes that the cramfs
+	;; second longword contains the length of the cramfs
+	
+	moveq	0, r0
+	move.d	r0, [_romfs_length] ; default if there is no cramfs
+	
+	;; First check if there is a cramfs (magic value)
+	;; Notice that we check for cramfs magic value - which is
+	;; the "rom fs" we'll possibly use in 2.4 if not JFFS (which does
+	;; not need this mechanism anyway)
+	
+	move.d	__vmlinux_end, r0 ; the image will be after the vmlinux end address
+	move.d	[r0], r1	; cramfs assumes same endian on host/target
+	cmp.d	CRAMFS_MAGIC, r1; magic value in cramfs superblock
+	bne	no_romfs_in_ram
+	nop
+
+	;; Ok. What is its size ? 
+	
+	move.d	[r0 + 4], r2	; cramfs_super.size (again, no need to swapwb)
+
+	;; We want to copy it to the end of the BSS
+
+	move.d	_end, r1
+
+	;; Remember values so cramfs and setup can find this info
+
+	move.d	r1, [_romfs_start]	; new romfs location
+	move.d	r2, [_romfs_length]
+
+	;; We need to copy it backwards, since they can be overlapping
+
+	add.d	r2, r0
+	add.d	r2, r1
+		
+	;; Go ahead. Make my loop.
+
+	lsrq	1, r2		; size is in bytes, we copy words
+
+1:	move.w	[r0=r0-2],r3
+	move.w	r3,[r1=r1-2]
+	subq	1, r2
+	bne	1b
+	nop
+	
+	;; Dont worry that the BSS is tainted. It will be cleared later.
+
+	moveq	0, r0
+	move.d	r0, [_romfs_in_flash]
+
+	jump	start_it	; better skip the additional cramfs check below
+			
+no_romfs_in_ram:
+
+	;; We have still one other possibility at this point - the kernel
+	;; could have been unpacked to DRAM by the loader, but the cramfs
+	;; image was still in the Flash directly after the compressed kernel
+	;; image. The loader passes the address of the byte succeeding the
+	;; last compressed byte in the flash in the register r9 when starting
+	;; the kernel. Check if r9 points to a decent cramfs image!
+	;; (Notice that if this is not booted from the loader, r9 will be
+	;;  garbage but we do sanity checks on it, the chance that it points
+	;;  to a cramfs magic is small.. )
+	
+	cmp.d	0x0ffffff8, r9
+	bcc	1f		; r9 points outside the flash area
+	nop
+	move.d	[r9], r0	; cramfs_super.magic
+	cmp.d	CRAMFS_MAGIC, r0
+	bne	1f
+	nop
+	move.d	[r9+4], r0	; cramfs_super.length
+	move.d	r0, [_romfs_length]
+#ifdef CONFIG_CRIS_LOW_MAP
+	add.d   0x50000000, r9	; add flash start in virtual memory (cached)
+#else
+	add.d   0xf0000000, r9	; add flash start in virtual memory (cached)
+#endif
+	move.d	r9, [_romfs_start]
+
+	moveq	1, r0
+	move.d	r0, [_romfs_in_flash]
+1:	
+	
+	jump	start_it	; enter code, cached this time
+	
+start_it:
+	;; the kernel stack is overlayed with the task structure for each
+	;; task. thus the initial kernel stack is in the same page as the
+	;; init_task (but starts in the top of the page, size 8192)
+	move.d	_init_task_union + 8192,sp
+	move.d	_ibr_start,r0	; this symbol is set by the linker script 
+	move	r0,ibr
+	move.d	r0,[_etrax_irv]	; set the interrupt base register and pointer
+
+	;; Clear BSS region, from _bss_start to _end
+
+	move.d	__bss_start, r0
+	move.d	_end, r1
+1:	clear.d	[r0+]
+	cmp.d	r1, r0
+	bcs	1b
+	nop
+	
+#ifdef CONFIG_BLK_DEV_ETRAXIDE
+	;; disable ATA before enabling it in genconfig below
+	moveq	0,r0
+	move.d	r0,[R_ATA_CTRL_DATA]
+	move.d	r0,[R_ATA_TRANSFER_CNT]
+	move.d	r0,[R_ATA_CONFIG]
+#if 0
+	move.d	R_PORT_G_DATA,r1
+	move.d	r0,[r1]; assert ATA bus-reset
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	move.d	0x08000000,r0
+	move.d	r0,[r1]
+#endif
+#endif
+
+#ifdef CONFIG_JULIETTE
+	;; configure external DMA channel 0 before enabling it in genconfig
+	
+	moveq	0,r0
+	move.d	r0,[R_EXT_DMA_0_ADDR]
+	move.d	0x860000,r0	; cnt enable, word size, output, stop, size 0
+	move.d	r0,[R_EXT_DMA_0_CMD]
+
+	;; reset dma4 and wait for completion
+	
+	moveq	4,r0
+	move.b	r0,[R_DMA_CH4_CMD]
+w4u:	move.b	[R_DMA_CH4_CMD],r0
+	and.b	7,r0
+	cmp.b	4,r0
+	beq	w4u
+	nop
+
+	;; reset dma5 and wait for completion
+	
+	moveq	4,r0
+	move.b	r0,[R_DMA_CH5_CMD]
+w5u:	move.b	[R_DMA_CH5_CMD],r0
+	and.b	7,r0
+	cmp.b	4,r0
+	beq	w5u
+	nop
+#endif	
+			
+	;; Etrax product HW genconfig setup
+
+	moveq	0,r0
+#if !defined(CONFIG_KGDB) && !defined(CONFIG_DMA_MEMCPY)
+	or.d	0x140000,r0	; DMA channels 6 and 7 to ser0, kgdb doesnt want DMA
+#endif
+#if !defined(CONFIG_KGDB) || !defined(CONFIG_DEBUG_PORT1)
+	or.d	0xc00000,r0	; DMA channels 8 and 9 to ser1, kgdb doesnt want DMA
+#endif
+#ifdef CONFIG_DMA_MEMCPY
+	or.d	0x003c0000,r0	; 6/7 memory-memory DMA
+#endif
+#ifdef CONFIG_ETRAX100_SERIAL_PORT2
+	or.d	0x2808,r0	; DMA channels 2 and 3 to serport 2, port 2 enabled
+#endif
+#ifdef CONFIG_ETRAX100_SERIAL_PORT3
+	or.d	0x28100,r0	; DMA channels 4 and 5 to serport 3, port 3 enabled
+#endif
+#if defined(CONFIG_ETRAX100_PARALLEL_PORT0) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
+	or.w	0x4,r0	; parport 0 enabled using DMA 2/3
+#endif
+#if defined(CONFIG_ETRAX100_PARALLEL_PORT1) || defined(CONFIG_ETRAX_ETHERNET_LPSLAVE)
+	or.w	0x80,r0	; parport 1 enabled using DMA 4/5
+#endif
+#ifdef CONFIG_BLK_DEV_ETRAXIDE
+	or.d	0x3c02,r0	; DMA channels 2 and 3 to ATA, ATA enabled
+#endif
+#ifdef CONFIG_JULIETTE
+	or.d	0x3c000,r0	; DMA channels 4 and 5 to EXTDMA0, for Juliette
+#ifndef CONFIG_BLK_DEV_ETRAXIDE
+	or.d	0x41,r0		; HACK for now! To make G27 connected for the RTC
+#endif
+#endif
+	move.d	r0,[_genconfig_shadow] ; init a shadow register of R_GEN_CONFIG
+
+#ifndef CONFIG_SVINTO_SIM
+	move.d	r0,[R_GEN_CONFIG]
+
+#if 0
+	moveq	4,r0
+	move.b	r0,[R_DMA_CH6_CMD]	; reset (ser0 dma out)
+	move.b	r0,[R_DMA_CH7_CMD]	; reset (ser0 dma in)
+w61:	move.b	[R_DMA_CH6_CMD],r0	; wait for reset cycle to finish
+	and.b	7,r0
+	cmp.b	4,r0
+	beq	w61
+	nop
+w71:	move.b	[R_DMA_CH7_CMD],r0	; wait for reset cycle to finish
+	and.b	7,r0
+	cmp.b	4,r0
+	beq	w71
+	nop
+#endif
+	
+	moveq	4,r0
+	move.b	r0,[R_DMA_CH8_CMD]	; reset (ser1 dma out)
+	move.b	r0,[R_DMA_CH9_CMD]	; reset (ser1 dma in)
+w81:	move.b	[R_DMA_CH8_CMD],r0	; wait for reset cycle to finish
+	and.b	7,r0
+	cmp.b	4,r0
+	beq	w81
+	nop
+w91:	move.b	[R_DMA_CH9_CMD],r0	; wait for reset cycle to finish
+	and.b	7,r0
+	cmp.b	4,r0
+	beq	w91
+	nop
+
+	;; setup port PA and PB default initial directions and data
+	;; including their shadow registers
+		
+	move.b	DEF_R_PORT_PA_DIR,r0
+	move.b	r0,[_port_pa_dir_shadow]
+	move.b	r0,[R_PORT_PA_DIR]
+	move.b	DEF_R_PORT_PA_DATA,r0
+	move.b	r0,[_port_pa_data_shadow]
+	move.b	r0,[R_PORT_PA_DATA]
+	
+	move.b	DEF_R_PORT_PB_CONFIG,r0
+	move.b	r0,[_port_pb_config_shadow]
+	move.b	r0,[R_PORT_PB_CONFIG]
+	move.b	DEF_R_PORT_PB_DIR,r0
+	move.b	r0,[_port_pb_dir_shadow]
+	move.b	r0,[R_PORT_PB_DIR]
+	move.b	DEF_R_PORT_PB_DATA,r0
+	move.b	r0,[_port_pb_data_shadow]
+	move.b	r0,[R_PORT_PB_DATA]
+
+	moveq	0,r0
+	move.d	r0,[_port_g_data_shadow]
+	move.d	r0,[R_PORT_G_DATA]
+	
+	;; setup the serial port 0 at 115200 baud for debug purposes
+	
+	moveq	0,r0
+	move.d	r0,[R_SERIAL0_XOFF] 
+
+	move.b	0x99,r0
+	move.b	r0,[R_SERIAL0_BAUD]	; 115.2kbaud for both transmit and receive
+
+	move.b	0x40,r0			; rec enable
+	move.b	r0,[R_SERIAL0_REC_CTRL] 
+	
+	move.b	0x40,r0			; tr enable
+	move.b	r0,[R_SERIAL0_TR_CTRL]
+
+	;; setup the serial port 1 at 115200 baud for debug purposes
+	
+	moveq	0,r0
+	move.d	r0,[R_SERIAL1_XOFF] 
+
+	move.b	0x99,r0
+	move.b	r0,[R_SERIAL1_BAUD]	; 115.2kbaud for both transmit and receive
+
+	move.b	0x40,r0			; rec enable
+	move.b	r0,[R_SERIAL1_REC_CTRL] 
+	
+	move.b	0x40,r0			; tr enable
+	move.b	r0,[R_SERIAL1_TR_CTRL]
+
+#ifdef CONFIG_ETRAX_90000000_LEDS
+	;; clear LED's on Stallone and Olga boards
+	moveq	-1,r0
+	move.d	r0,[_port_90000000_shadow]
+	move.d	r0,[0x90000000]
+#endif
+	
+#ifdef CONFIG_ETRAX100_SERIAL_PORT3	
+	;; setup the serial port 3 at 115200 baud for debug purposes
+	
+	moveq	0,r0
+	move.d	r0,[R_SERIAL3_XOFF] 
+
+	move.b	0x99,r0
+	move.b	r0,[R_SERIAL3_BAUD]	; 115.2kbaud for both transmit and receive
+
+	move.b	0x40,r0			; rec enable
+	move.b	r0,[R_SERIAL3_REC_CTRL] 
+	
+	move.b	0x40,r0			; tr enable
+	move.b	r0,[R_SERIAL3_TR_CTRL]
+#endif
+	
+#endif /* CONFIG_SVINTO_SIM */
+
+	jump	_start_kernel	; jump into the C-function _start_kernel in init/main.c
+
+	
+	.data
+_etrax_irv:	
+	.dword	0
+_romfs_start:
+	.dword	0
+_romfs_length:
+	.dword	0
+_romfs_in_flash:
+	.dword	0
+
+	;; put some special pages at the beginning of the kernel aligned
+	;; to page boundaries - the kernel cannot start until after this
+
+#ifdef CONFIG_CRIS_LOW_MAP
+_swapper_pg_dir = 0x60002000
+#else	
+_swapper_pg_dir = 0xc0002000
+#endif
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/hexify.c linux/arch/cris/kernel/hexify.c
--- v2.4.1/linux/arch/cris/kernel/hexify.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/hexify.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,31 @@
+#include <stdio.h>
+
+
+void main()
+{
+	int c;
+	int comma=0;
+	int count=0;
+	while((c=getchar())!=EOF)
+	{
+		unsigned char x=c;
+		if(comma)
+			printf(",");
+		else
+			comma=1;
+		if(count==8)
+		{
+			count=0;
+			printf("\n");
+		}
+		if(count==0)
+			printf("\t");
+		printf("0x%02X",c);
+		count++;
+	}
+	if(count)
+		printf("\n");
+	exit(0);
+}
+
+		
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/irq.c linux/arch/cris/kernel/irq.c
--- v2.4.1/linux/arch/cris/kernel/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/irq.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,467 @@
+/* $Id: irq.c,v 1.5 2000/08/17 15:35:15 bjornw Exp $
+ *
+ *	linux/arch/cris/kernel/irq.c
+ *
+ *      Copyright (c) 2000 Axis Communications AB
+ *
+ *      Authors: Bjorn Wesen (bjornw@axis.com)
+ *
+ * This file contains the code used by various IRQ handling routines:
+ * asking for different IRQ's should be done through these routines
+ * instead of just grabbing them. Thus setups with different IRQ numbers
+ * shouldn't result in any weird surprises, and installing new handlers
+ * should be easier.
+ *
+ * Notice Linux/CRIS: these routines do not care about SMP
+ *
+ */
+
+/*
+ * IRQ's are in fact implemented a bit like signal handlers for the kernel.
+ * Naturally it's not a 1:1 relation, but there are similarities.
+ */
+
+#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 <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+
+#include <asm/svinto.h>
+
+char *hw_bp_msg = "BP 0x%x\n";
+
+static inline void
+mask_irq(unsigned int irq_nr)
+{
+	*R_VECT_MASK_CLR = 1 << irq_nr;
+}
+
+static inline void
+unmask_irq(unsigned int irq_nr)
+{
+	*R_VECT_MASK_SET = 1 << irq_nr;
+}
+
+void
+disable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	
+	save_flags(flags);
+	cli();
+	mask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+void
+enable_irq(unsigned int irq_nr)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	unmask_irq(irq_nr);
+	restore_flags(flags);
+}
+
+unsigned long
+probe_irq_on()
+{
+	return 0;
+}
+
+int
+probe_irq_off(unsigned long x)
+{
+	return 0;
+}
+
+irqvectptr irq_shortcuts[NR_IRQS]; /* vector of shortcut jumps after the irq prologue */
+
+/* don't use set_int_vector, it bypasses the linux interrupt handlers. it is
+ * global just so that the kernel gdb can use it.
+ */
+
+void
+set_int_vector(int n, irqvectptr addr, irqvectptr saddr)
+{
+	/* remember the shortcut entry point, after the prologue */
+
+	irq_shortcuts[n] = saddr;
+
+	etrax_irv->v[n + 0x20] = (irqvectptr)addr;
+}
+
+/* the breakpoint vector is obviously not made just like the normal irq handlers
+ * but needs to contain _code_ to jump to addr.
+ *
+ * the BREAK n instruction jumps to IBR + n * 8
+ */
+
+void
+set_break_vector(int n, irqvectptr addr)
+{
+	unsigned short *jinstr = (unsigned short *)&etrax_irv->v[n*2];
+	unsigned long *jaddr = (unsigned long *)(jinstr + 1);
+
+	/* if you don't know what this does, do not touch it! */
+	
+	*jinstr = 0x0d3f;
+	*jaddr = (unsigned long)addr;
+
+	/* 00000026 <clrlop+1a> 3f0d82000000     jump  0x82 */
+}
+
+
+/*
+ * This builds up the IRQ handler stubs using some ugly macros in irq.h
+ *
+ * These macros create the low-level assembly IRQ routines that do all
+ * the operations that are needed. They are also written to be fast - and to
+ * disable interrupts as little as humanly possible.
+ *
+ */
+
+/* IRQ0 and 1 are special traps */
+void hwbreakpoint(void);
+void IRQ1_interrupt(void);
+BUILD_IRQ(2, 0x04)             /* the timer interrupt */
+BUILD_IRQ(3, 0x08)
+BUILD_IRQ(4, 0x10)
+BUILD_IRQ(5, 0x20)
+BUILD_IRQ(6, 0x40)
+BUILD_IRQ(7, 0x80)
+BUILD_IRQ(8, 0x100)
+BUILD_IRQ(9, 0x200)
+BUILD_IRQ(10, 0x400)
+BUILD_IRQ(11, 0x800)
+BUILD_IRQ(12, 0x1000)
+BUILD_IRQ(13, 0x2000)
+void mmu_bus_fault(void);      /* IRQ 14 is the bus fault interrupt */
+void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
+BUILD_IRQ(16, 0x10000)
+BUILD_IRQ(17, 0x20000)
+BUILD_IRQ(18, 0x40000)
+BUILD_IRQ(19, 0x80000)
+BUILD_IRQ(20, 0x100000)
+BUILD_IRQ(21, 0x200000)
+BUILD_IRQ(22, 0x400000)
+BUILD_IRQ(23, 0x800000)
+BUILD_IRQ(24, 0x1000000)
+BUILD_IRQ(25, 0x2000000)
+ 
+/*
+ * Pointers to the low-level handlers 
+ */
+
+static void (*interrupt[NR_IRQS])(void) = {
+	NULL, NULL, IRQ2_interrupt, IRQ3_interrupt,
+	IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
+	IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
+	IRQ12_interrupt, IRQ13_interrupt, NULL, NULL,	
+	IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,	
+	IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,	
+	IRQ24_interrupt, IRQ25_interrupt
+};
+
+static void (*sinterrupt[NR_IRQS])(void) = {
+	NULL, NULL, sIRQ2_interrupt, sIRQ3_interrupt,
+	sIRQ4_interrupt, sIRQ5_interrupt, sIRQ6_interrupt, sIRQ7_interrupt,
+	sIRQ8_interrupt, sIRQ9_interrupt, sIRQ10_interrupt, sIRQ11_interrupt,
+	sIRQ12_interrupt, sIRQ13_interrupt, NULL, NULL,	
+	sIRQ16_interrupt, sIRQ17_interrupt, sIRQ18_interrupt, sIRQ19_interrupt,	
+	sIRQ20_interrupt, sIRQ21_interrupt, sIRQ22_interrupt, sIRQ23_interrupt,	
+	sIRQ24_interrupt, sIRQ25_interrupt
+};
+
+static void (*bad_interrupt[NR_IRQS])(void) = {
+        NULL, NULL,
+	NULL, bad_IRQ3_interrupt,
+	bad_IRQ4_interrupt, bad_IRQ5_interrupt,
+	bad_IRQ6_interrupt, bad_IRQ7_interrupt,
+	bad_IRQ8_interrupt, bad_IRQ9_interrupt,
+	bad_IRQ10_interrupt, bad_IRQ11_interrupt,
+	bad_IRQ12_interrupt, bad_IRQ13_interrupt,
+	NULL, NULL,
+	bad_IRQ16_interrupt, bad_IRQ17_interrupt,
+	bad_IRQ18_interrupt, bad_IRQ19_interrupt,
+	bad_IRQ20_interrupt, bad_IRQ21_interrupt,
+	bad_IRQ22_interrupt, bad_IRQ23_interrupt,
+	bad_IRQ24_interrupt, bad_IRQ25_interrupt
+};
+
+/*
+ * Initial irq handlers.
+ */
+
+static struct irqaction *irq_action[NR_IRQS] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL
+};
+
+int get_irq_list(char *buf)
+{
+	int i, len = 0;
+	struct irqaction * action;
+
+	for (i = 0; i < NR_IRQS; i++) {
+		action = irq_action[i];
+		if (!action) 
+			continue;
+		len += sprintf(buf+len, "%2d: %10u %c %s",
+			i, kstat.irqs[0][i],
+			(action->flags & SA_INTERRUPT) ? '+' : ' ',
+			action->name);
+		for (action = action->next; action; action = action->next) {
+			len += sprintf(buf+len, ",%s %s",
+				(action->flags & SA_INTERRUPT) ? " +" : "",
+				action->name);
+		}
+		len += sprintf(buf+len, "\n");
+	}
+	return len;
+}
+
+/* called by the assembler IRQ entry functions defined in irq.h
+ * to dispatch the interrupts to registred handlers
+ * interrupts are disabled upon entry - depending on if the
+ * interrupt was registred with SA_INTERRUPT or not, interrupts
+ * are re-enabled or not.
+ */
+
+asmlinkage void do_IRQ(int irq, struct pt_regs * regs)
+{
+	struct irqaction *action;
+	int do_random, cpu;
+
+        cpu = smp_processor_id();
+        irq_enter(cpu);
+	kstat.irqs[cpu][irq]++;
+
+	action = *(irq + irq_action);
+        if (action) {
+                if (!(action->flags & SA_INTERRUPT))
+                        __sti();
+                action = *(irq + irq_action);
+                do_random = 0;
+                do {
+                        do_random |= action->flags;
+                        action->handler(irq, action->dev_id, regs);
+                        action = action->next;
+                } while (action);
+                if (do_random & SA_SAMPLE_RANDOM)
+                        add_interrupt_randomness(irq);
+                __cli();
+        }
+        irq_exit(cpu);
+
+	if (softirq_active(cpu) & softirq_mask(cpu))
+                do_softirq();
+
+        /* unmasking and bottom half handling is done magically for us. */
+}
+
+/* this function links in a handler into the chain of handlers for the
+   given irq, and if the irq has never been registred, the appropriate
+   handler is entered into the interrupt vector
+*/
+
+int setup_etrax_irq(int irq, struct irqaction * new)
+{
+	int shared = 0;
+	struct irqaction *old, **p;
+	unsigned long flags;
+
+	p = irq_action + irq;
+	if ((old = *p) != NULL) {
+		/* Can't share interrupts unless both agree to */
+		if (!(old->flags & new->flags & SA_SHIRQ))
+			return -EBUSY;
+
+		/* Can't share interrupts unless both are same type */
+		if ((old->flags ^ new->flags) & SA_INTERRUPT)
+			return -EBUSY;
+
+		/* add new interrupt at end of irq queue */
+		do {
+			p = &old->next;
+			old = *p;
+		} while (old);
+		shared = 1;
+	}
+
+	if (new->flags & SA_SAMPLE_RANDOM)
+		rand_initialize_irq(irq);
+
+	save_flags(flags);
+	cli();
+	*p = new;
+
+	if (!shared) {
+		/* if the irq wasn't registred before, enter it into the vector table
+		   and unmask it physically 
+		*/
+		set_int_vector(irq, interrupt[irq], sinterrupt[irq]);
+		unmask_irq(irq);
+	}
+	
+	restore_flags(flags);
+	return 0;
+}
+
+/* this function is called by a driver to register an irq handler
+   Valid flags:
+   SA_INTERRUPT -> it's a fast interrupt, handler called with irq disabled and
+                   no signal checking etc is performed upon exit
+   SA_SHIRQ -> the interrupt can be shared between different handlers, the handler
+                is required to check if the irq was "aimed" at it explicitely
+   SA_RANDOM -> the interrupt will add to the random generators entropy
+*/
+
+int request_irq(unsigned int irq, 
+		void (*handler)(int, void *, struct pt_regs *),
+		unsigned long irqflags, 
+		const char * devname,
+		void *dev_id)
+{
+	int retval;
+	struct irqaction * action;
+
+	/* interrupts 0 and 1 are hardware breakpoint and NMI and we can't support
+	   these yet. interrupt 15 is the multiple irq, it's special. */
+
+	if(irq < 2 || irq == 15 || irq >= NR_IRQS)
+		return -EINVAL;
+
+	if(!handler)
+		return -EINVAL;
+
+	/* allocate and fill in a handler structure and setup the irq */
+
+	action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);
+	if (!action)
+		return -ENOMEM;
+
+	action->handler = handler;
+	action->flags = irqflags;
+	action->mask = 0;
+	action->name = devname;
+	action->next = NULL;
+	action->dev_id = dev_id;
+
+	retval = setup_etrax_irq(irq, action);
+
+	if (retval)
+		kfree(action);
+	return retval;
+}
+		
+void free_irq(unsigned int irq, void *dev_id)
+{
+	struct irqaction * action, **p;
+	unsigned long flags;
+
+	if (irq >= NR_IRQS) {
+		printk("Trying to free IRQ%d\n",irq);
+		return;
+	}
+	for (p = irq + irq_action; (action = *p) != NULL; p = &action->next) {
+		if (action->dev_id != dev_id)
+			continue;
+
+		/* Found it - now free it */
+		save_flags(flags);
+		cli();
+		*p = action->next;
+		if (!irq[irq_action]) {
+			mask_irq(irq);
+			set_int_vector(irq, bad_interrupt[irq], 0);
+		}
+		restore_flags(flags);
+		kfree(action);
+		return;
+	}
+	printk("Trying to free free IRQ%d\n",irq);
+}
+
+void weird_irq(void)
+{
+	__asm__("di");
+	printk("weird irq\n");
+	while(1);
+}
+
+/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
+   setting the irq vector table to point to bad_interrupt ptrs.
+*/
+
+void system_call(void);  /* from entry.S */
+
+void init_IRQ(void)
+{
+	int i;
+
+	/* clear all interrupt masks */
+
+#ifndef CONFIG_SVINTO_SIM
+	*R_IRQ_MASK0_CLR = 0xffffffff;
+	*R_IRQ_MASK1_CLR = 0xffffffff;
+	*R_IRQ_MASK2_CLR = 0xffffffff;
+#endif
+
+	*R_VECT_MASK_CLR = 0xffffffff;
+
+	/* clear the shortcut entry points */
+
+	for(i = 0; i < NR_IRQS; i++)
+		irq_shortcuts[i] = NULL;
+	
+	for (i = 0; i < 256; i++)
+		etrax_irv->v[i] = weird_irq;
+      
+	/* set all etrax irq's to the bad handlers */
+	for (i = 2; i < NR_IRQS; i++)
+		set_int_vector(i, bad_interrupt[i], 0);
+
+	/* except IRQ 15 which is the multiple-IRQ handler on Etrax100 */
+
+	set_int_vector(15, multiple_interrupt, 0);
+	
+	/* 0 and 1 which are special breakpoint/NMI traps */
+
+	set_int_vector(0, hwbreakpoint, 0);
+	set_int_vector(1, IRQ1_interrupt, 0);
+
+	/* and irq 14 which is the mmu bus fault handler */
+
+	set_int_vector(14, mmu_bus_fault, 0);
+
+	/* setup the system-call trap, which is reached by BREAK 13 */
+
+	set_break_vector(13, system_call);
+
+#ifdef CONFIG_KGDB
+	/* setup kgdb if its enabled, and break into the debugger */
+
+	kgdb_init();
+
+	breakpoint();
+#endif
+
+} 
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/kgdb.c linux/arch/cris/kernel/kgdb.c
--- v2.4.1/linux/arch/cris/kernel/kgdb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/kgdb.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,1540 @@
+/*!**************************************************************************
+*!
+*! FILE NAME  : kgdb.c
+*!
+*! DESCRIPTION: Implementation of the gdb stub with respect to ETRAX 100.
+*!              It is a mix of arch/m68k/kernel/kgdb.c and cris_stub.c.
+*!
+*!---------------------------------------------------------------------------
+*! HISTORY
+*!
+*! DATE         NAME            CHANGES
+*! ----         ----            -------
+*! Apr 26 1999  Hendrik Ruijter Initial version.
+*! May  6 1999  Hendrik Ruijter Removed call to strlen in libc and removed
+*!                              struct assignment as it generates calls to
+*!                              memcpy in libc.
+*! Jun 17 1999  Hendrik Ruijter Added gdb 4.18 support. 'X', 'qC' and 'qL'.
+*! Jul 21 1999  Bjorn Wesen     eLinux port
+*!
+*! $Log: kgdb.c,v $
+*! Revision 1.2  2001/01/12 14:22:25  orjanf
+*! Updated kernel debugging support to work with ETRAX 100LX.
+*!
+*! Revision 1.1  2000/07/10 16:25:21  bjornw
+*! Initial revision
+*!
+*! Revision 1.1.1.1  1999/12/03 14:57:31  bjornw
+*! * Initial version of arch/cris, the latest CRIS architecture with an MMU.
+*!   Mostly copied from arch/etrax100 with appropriate renames of files.
+*!   The mm/ subdir is copied from arch/i386.
+*!   This does not compile yet at all.
+*!
+*!
+*! Revision 1.4  1999/07/22 17:25:25  bjornw
+*! Dont wait for + in putpacket if we havent hit the initial breakpoint yet. Added a kgdb_init function which sets up the break and irq vectors.
+*!
+*! Revision 1.3  1999/07/21 19:51:18  bjornw
+*! Check if the interrupting char is a ctrl-C, ignore otherwise.
+*!
+*! Revision 1.2  1999/07/21 18:09:39  bjornw
+*! Ported to eLinux architecture, and added some kgdb documentation.
+*!
+*!
+*!---------------------------------------------------------------------------
+*!
+*! $Id: kgdb.c,v 1.2 2001/01/12 14:22:25 orjanf Exp $
+*!
+*! (C) Copyright 1999, Axis Communications AB, LUND, SWEDEN
+*!
+*!**************************************************************************/
+/* @(#) cris_stub.c 1.3 06/17/99 */
+
+/*
+ *  kgdb usage notes:
+ *  -----------------
+ *
+ * If you select CONFIG_KGDB in the configuration, the kernel will be built
+ * with different gcc flags: "-g" is added to get debug infos, and
+ * "-fomit-frame-pointer" is omitted to make debugging easier. Since the
+ * resulting kernel will be quite big (approx. > 7 MB), it will be stripped
+ * before compresion. Such a kernel will behave just as usually, except if
+ * given a "debug=<device>" command line option. (Only serial devices are
+ * allowed for <device>, i.e. no printers or the like; possible values are
+ * machine depedend and are the same as for the usual debug device, the one
+ * for logging kernel messages.) If that option is given and the device can be
+ * initialized, the kernel will connect to the remote gdb in trap_init(). The
+ * serial parameters are fixed to 8N1 and 115200 bps, for easyness of
+ * implementation.
+ *
+ * To start a debugging session, start that gdb with the debugging kernel
+ * image (the one with the symbols, vmlinux.debug) named on the command line.
+ * This file will be used by gdb to get symbol and debugging infos about the
+ * kernel. Next, select remote debug mode by
+ *    target remote <device>
+ * where <device> is the name of the serial device over which the debugged
+ * machine is connected. Maybe you have to adjust the baud rate by
+ *    set remotebaud <rate>
+ * or also other parameters with stty:
+ *    shell stty ... </dev/...
+ * If the kernel to debug has already booted, it waited for gdb and now
+ * connects, and you'll see a breakpoint being reported. If the kernel isn't
+ * running yet, start it now. The order of gdb and the kernel doesn't matter.
+ * Another thing worth knowing about in the getting-started phase is how to
+ * debug the remote protocol itself. This is activated with
+ *    set remotedebug 1
+ * gdb will then print out each packet sent or received. You'll also get some
+ * messages about the gdb stub on the console of the debugged machine.
+ *
+ * If all that works, you can use lots of the usual debugging techniques on
+ * the kernel, e.g. inspecting and changing variables/memory, setting
+ * breakpoints, single stepping and so on. It's also possible to interrupt the
+ * debugged kernel by pressing C-c in gdb. Have fun! :-)
+ *
+ * The gdb stub is entered (and thus the remote gdb gets control) in the
+ * following situations:
+ *
+ *  - If breakpoint() is called. This is just after kgdb initialization, or if
+ *    a breakpoint() call has been put somewhere into the kernel source.
+ *    (Breakpoints can of course also be set the usual way in gdb.)
+ *    In eLinux, we call breakpoint() in init/main.c after IRQ initialization.
+ *
+ *  - If there is a kernel exception, i.e. bad_super_trap() or die_if_kernel()
+ *    are entered. All the CPU exceptions are mapped to (more or less..., see
+ *    the hard_trap_info array below) appropriate signal, which are reported
+ *    to gdb. die_if_kernel() is usually called after some kind of access
+ *    error and thus is reported as SIGSEGV.
+ *
+ *  - When panic() is called. This is reported as SIGABRT.
+ *
+ *  - If C-c is received over the serial line, which is treated as
+ *    SIGINT.
+ *
+ * Of course, all these signals are just faked for gdb, since there is no
+ * signal concept as such for the kernel. It also isn't possible --obviously--
+ * to set signal handlers from inside gdb, or restart the kernel with a
+ * signal.
+ *
+ * Current limitations:
+ *
+ *  - While the kernel is stopped, interrupts are disabled for safety reasons
+ *    (i.e., variables not changing magically or the like). But this also
+ *    means that the clock isn't running anymore, and that interrupts from the
+ *    hardware may get lost/not be served in time. This can cause some device
+ *    errors...
+ *
+ *  - When single-stepping, only one instruction of the current thread is
+ *    executed, but interrupts are allowed for that time and will be serviced
+ *    if pending. Be prepared for that.
+ *
+ *  - All debugging happens in kernel virtual address space. There's no way to
+ *    access physical memory not mapped in kernel space, or to access user
+ *    space. A way to work around this is using get_user_long & Co. in gdb
+ *    expressions, but only for the current process.
+ *
+ *  - Interrupting the kernel only works if interrupts are currently allowed,
+ *    and the interrupt of the serial line isn't blocked by some other means
+ *    (IPL too high, disabled, ...)
+ *
+ *  - The gdb stub is currently not reentrant, i.e. errors that happen therein
+ *    (e.g. accesing invalid memory) may not be caught correctly. This could
+ *    be removed in future by introducing a stack of struct registers.
+ *
+ */
+
+/*
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to kgdb_init() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint(). 
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *    bBB..BB	    Set baud rate to BB..BB		   OK or BNN, then sets
+ *							   baud rate
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ */
+
+
+#include <linux/string.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/linkage.h>
+
+#include <asm/setup.h>
+#include <asm/ptrace.h>
+
+#include <asm/svinto.h>
+#include <asm/irq.h>
+
+static int kgdb_started = 0;
+
+/********************************* Register image ****************************/
+/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's
+   Reference", p. 1-1, with the additional register definitions of the
+   ETRAX 100LX in cris-opc.h.
+   There are 16 general 32-bit registers, R0-R15, where R14 is the stack
+   pointer, SP, and R15 is the program counter, PC.
+   There are 16 special registers, P0-P15, where three of the unimplemented
+   registers, P0, P4 and P8, are reserved as zero-registers. A read from
+   any of these registers returns zero and a write has no effect. */
+
+typedef
+struct register_image
+{
+	/* Offset */
+	unsigned int     r0;   /* 0x00 */
+	unsigned int     r1;   /* 0x04 */
+	unsigned int     r2;   /* 0x08 */
+	unsigned int     r3;   /* 0x0C */
+	unsigned int     r4;   /* 0x10 */
+	unsigned int     r5;   /* 0x14 */
+	unsigned int     r6;   /* 0x18 */
+	unsigned int     r7;   /* 0x1C */
+	unsigned int     r8;   /* 0x20 Frame pointer */
+	unsigned int     r9;   /* 0x24 */
+	unsigned int    r10;   /* 0x28 */
+	unsigned int    r11;   /* 0x2C */
+	unsigned int    r12;   /* 0x30 */
+	unsigned int    r13;   /* 0x34 */
+	unsigned int     sp;   /* 0x38 Stack pointer */
+	unsigned int     pc;   /* 0x3C Program counter */
+
+        unsigned char    p0;   /* 0x40 8-bit zero-register */
+	unsigned char    vr;   /* 0x41 Version register */
+
+        unsigned short   p4;   /* 0x42 16-bit zero-register */
+	unsigned short  ccr;   /* 0x44 Condition code register */
+	
+	unsigned int    mof;   /* 0x46 Multiply overflow register */
+	
+        unsigned int     p8;   /* 0x4A 32-bit zero-register */
+	unsigned int    ibr;   /* 0x4E Interrupt base register */
+	unsigned int    irp;   /* 0x52 Interrupt return pointer */
+	unsigned int    srp;   /* 0x56 Subroutine return pointer */
+	unsigned int    bar;   /* 0x5A Breakpoint address register */
+	unsigned int   dccr;   /* 0x5E Double condition code register */
+	unsigned int    brp;   /* 0x62 Breakpoint return pointer (pc in caller) */
+	unsigned int    usp;   /* 0x66 User mode stack pointer */
+} registers;
+
+/************** Prototypes for local library functions ***********************/
+
+/* Copy of strcpy from libc. */
+static char *gdb_cris_strcpy (char *s1, const char *s2);
+
+/* Copy of strlen from libc. */
+static int gdb_cris_strlen (const char *s);
+
+/* Copy of memchr from libc. */
+static void *gdb_cris_memchr (const void *s, int c, int n);
+
+/* Copy of strtol from libc. Does only support base 16. */
+static int gdb_cris_strtol (const char *s, char **endptr, int base);
+
+/********************** Prototypes for local functions. **********************/
+/* Copy the content of a register image into another. The size n is
+   the size of the register image. Due to struct assignment generation of
+   memcpy in libc. */
+static void copy_registers (registers *dptr, registers *sptr, int n);
+
+/* Copy the stored registers from the stack. Put the register contents
+   of thread thread_id in the struct reg. */
+static void copy_registers_from_stack (int thread_id, registers *reg);
+
+/* Copy the registers to the stack. Put the register contents of thread
+   thread_id from struct reg to the stack. */
+static void copy_registers_to_stack (int thread_id, registers *reg);
+
+/* Write a value to a specified register regno in the register image
+   of the current thread. */
+static int write_register (int regno, char *val);
+
+/* Write a value to a specified register in the stack of a thread other
+   than the current thread. */
+static write_stack_register (int thread_id, int regno, char *valptr);
+
+/* Read a value from a specified register in the register image. Returns the
+   status of the read operation. The register value is returned in valptr. */
+static int read_register (char regno, unsigned int *valptr);
+
+/* Serial port, reads one character. ETRAX 100 specific. from debugport.c */
+int getDebugChar (void);
+
+/* Serial port, writes one character. ETRAX 100 specific. from debugport.c */
+void putDebugChar (int val);
+
+void enableDebugIRQ (void);
+
+/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte,
+   represented by int x. */
+static char highhex (int x);
+
+/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte,
+   represented by int x. */
+static char lowhex (int x);
+
+/* Returns the integer equivalent of a hexadecimal character. */
+static int hex (char ch);
+
+/* Convert the memory, pointed to by mem into hexadecimal representation.
+   Put the result in buf, and return a pointer to the last character
+   in buf (null). */
+static char *mem2hex (char *buf, unsigned char *mem, int count);
+
+/* Convert the array, in hexadecimal representation, pointed to by buf into
+   binary representation. Put the result in mem, and return a pointer to
+   the character after the last byte written. */
+static unsigned char *hex2mem (unsigned char *mem, char *buf, int count);
+
+/* Put the content of the array, in binary representation, pointed to by buf
+   into memory pointed to by mem, and return a pointer to
+   the character after the last byte written. */
+static unsigned char *bin2mem (unsigned char *mem, unsigned char *buf, int count);
+
+/* Await the sequence $<data>#<checksum> and store <data> in the array buffer
+   returned. */
+static void getpacket (char *buffer);
+
+/* Send $<data>#<checksum> from the <data> in the array buffer. */
+static void putpacket (char *buffer);
+
+/* Build and send a response packet in order to inform the host the
+   stub is stopped. */
+static void stub_is_stopped (int sigval);
+
+/* All expected commands are sent from remote.c. Send a response according
+   to the description in remote.c. */
+static void handle_exception (int sigval);
+
+/* Performs a complete re-start from scratch. ETRAX specific. */
+static void kill_restart (void);
+
+/******************** Prototypes for global functions. ***********************/
+
+/* The string str is prepended with the GDB printout token and sent. */
+void putDebugString (const unsigned char *str, int length); /* used by etrax100ser.c */
+
+/* The hook for both static (compiled) and dynamic breakpoints set by GDB.
+   ETRAX 100 specific. */
+void handle_breakpoint (void);                          /* used by irq.c */
+
+/* The hook for an interrupt generated by GDB. ETRAX 100 specific. */
+void handle_interrupt (void);                           /* used by irq.c */
+
+/* A static breakpoint to be used at startup. */
+void breakpoint (void);                                 /* called by init/main.c */
+
+/* From osys_int.c, executing_task contains the number of the current
+   executing task in osys. Does not know of object-oriented threads. */
+extern unsigned char executing_task;
+
+/* The number of characters used for a 64 bit thread identifier. */
+#define HEXCHARS_IN_THREAD_ID 16
+
+/* Avoid warning as the internal_stack is not used in the C-code. */
+#define USEDVAR(name)    { if (name) { ; } }
+#define USEDFUN(name) { void (*pf)(void) = (void *)name; USEDVAR(pf) }
+
+/********************************** Packet I/O ******************************/
+/* BUFMAX defines the maximum number of characters in
+   inbound/outbound buffers */
+#define BUFMAX 512
+
+/* Run-length encoding maximum length. Send 64 at most. */
+#define RUNLENMAX 64
+
+/* Definition of all valid hexadecimal characters */
+static const char hexchars[] = "0123456789abcdef";
+
+/* The inbound/outbound buffers used in packet I/O */
+static char remcomInBuffer[BUFMAX];
+static char remcomOutBuffer[BUFMAX];
+
+/* Error and warning messages. */
+enum error_type
+{
+	SUCCESS, E01, E02, E03, E04, E05, E06, E07
+};
+static char *error_message[] =
+{
+	"",
+	"E01 Set current or general thread - H[c,g] - internal error.",
+	"E02 Change register content - P - cannot change read-only register.",
+	"E03 Thread is not alive.", /* T, not used. */
+	"E04 The command is not supported - [s,C,S,!,R,d,r] - internal error.",
+	"E05 Change register content - P - the register is not implemented..",
+	"E06 Change memory content - M - internal error.",
+	"E07 Change register content - P - the register is not stored on the stack"
+};
+/********************************* Register image ****************************/
+/* Use the order of registers as defined in "AXIS ETRAX CRIS Programmer's
+   Reference", p. 1-1, with the additional register definitions of the
+   ETRAX 100LX in cris-opc.h.
+   There are 16 general 32-bit registers, R0-R15, where R14 is the stack
+   pointer, SP, and R15 is the program counter, PC.
+   There are 16 special registers, P0-P15, where three of the unimplemented
+   registers, P0, P4 and P8, are reserved as zero-registers. A read from
+   any of these registers returns zero and a write has no effect. */
+enum register_name
+{
+	R0,  R1,   R2,  R3,
+	R4,  R5,   R6,  R7,
+	R8,  R9,   R10, R11,
+	R12, R13,  SP,  PC,
+	P0,  VR,   P2,  P3,
+	P4,  CCR,  P6,  MOF,
+	P8,  IBR,  IRP, SRP,
+	BAR, DCCR, BRP, USP
+};
+
+/* The register sizes of the registers in register_name. An unimplemented register
+   is designated by size 0 in this array. */
+static int register_size[] =
+{
+	4, 4, 4, 4,
+	4, 4, 4, 4,
+	4, 4, 4, 4,
+	4, 4, 4, 4,
+	1, 1, 0, 0,
+	2, 2, 0, 4,
+	4, 4, 4, 4,
+	4, 4, 4, 4
+};
+
+/* Contains the register image of the executing thread in the assembler
+   part of the code in order to avoid horrible addressing modes. */
+static registers reg;
+
+/* FIXME: Should this be used? Delete otherwise. */
+/* Contains the assumed consistency state of the register image. Uses the
+   enum error_type for state information. */
+static int consistency_status = SUCCESS;
+
+/********************************** Handle exceptions ************************/
+/* The variable reg contains the register image associated with the
+   current_thread_c variable. It is a complete register image created at
+   entry. The reg_g contains a register image of a task where the general
+   registers are taken from the stack and all special registers are taken
+   from the executing task. It is associated with current_thread_g and used
+   in order to provide access mainly for 'g', 'G' and 'P'.
+*/
+
+/* Need two task id pointers in order to handle Hct and Hgt commands. */
+static int current_thread_c = 0;
+static int current_thread_g = 0;
+
+/* Need two register images in order to handle Hct and Hgt commands. The
+   variable reg_g is in addition to reg above. */
+static registers reg_g;
+
+/********************************** Breakpoint *******************************/
+/* Use an internal stack in the breakpoint and interrupt response routines */
+#define INTERNAL_STACK_SIZE 1024
+static char internal_stack[INTERNAL_STACK_SIZE];
+
+/* Due to the breakpoint return pointer, a state variable is needed to keep
+   track of whether it is a static (compiled) or dynamic (gdb-invoked)
+   breakpoint to be handled. A static breakpoint uses the content of register
+   BRP as it is whereas a dynamic breakpoint requires subtraction with 2
+   in order to execute the instruction. The first breakpoint is static. */
+static unsigned char is_dyn_brkp = 0;
+
+/********************************* String library ****************************/
+/* Single-step over library functions creates trap loops. */
+
+/* Copy char s2[] to s1[]. */
+static char*
+gdb_cris_strcpy (char *s1, const char *s2)
+{
+	char *s = s1;
+	
+	for (s = s1; (*s++ = *s2++) != '\0'; )
+		;
+	return (s1);
+}
+
+/* Find length of s[]. */
+static int
+gdb_cris_strlen (const char *s)
+{
+	const char *sc;
+	
+	for (sc = s; *sc != '\0'; sc++)
+		;
+	return (sc - s);
+}
+
+/* Find first occurrence of c in s[n]. */
+static void*
+gdb_cris_memchr (const void *s, int c, int n)
+{
+	const unsigned char uc = c;
+	const unsigned char *su;
+	
+	for (su = s; 0 < n; ++su, --n)
+		if (*su == uc)
+			return ((void *)su);
+	return (NULL);
+}
+/******************************* Standard library ****************************/
+/* Single-step over library functions creates trap loops. */
+/* Convert string to long. */
+static int
+gdb_cris_strtol (const char *s, char **endptr, int base)
+{
+	char *s1;
+	char *sd;
+	int x = 0;
+	
+	for (s1 = (char*)s; (sd = gdb_cris_memchr(hexchars, *s1, base)) != NULL; ++s1)
+		x = x * base + (sd - hexchars);
+        
+        if (endptr)
+        {
+                /* Unconverted suffix is stored in endptr unless endptr is NULL. */
+                *endptr = s1;
+        }
+        
+	return x;
+}
+
+int
+double_this(int x)
+{
+        return 2 * x;
+}
+
+/********************************* Register image ****************************/
+/* Copy the content of a register image into another. The size n is
+   the size of the register image. Due to struct assignment generation of
+   memcpy in libc. */
+static void
+copy_registers (registers *dptr, registers *sptr, int n)
+{
+	unsigned char *dreg;
+	unsigned char *sreg;
+	
+	for (dreg = (unsigned char*)dptr, sreg = (unsigned char*)sptr; n > 0; n--)
+		*dreg++ = *sreg++;
+}
+
+#ifdef PROCESS_SUPPORT
+/* Copy the stored registers from the stack. Put the register contents
+   of thread thread_id in the struct reg. */
+static void
+copy_registers_from_stack (int thread_id, registers *regptr)
+{
+	int j;
+	stack_registers *s = (stack_registers *)stack_list[thread_id];
+	unsigned int *d = (unsigned int *)regptr;
+	
+	for (j = 13; j >= 0; j--)
+		*d++ = s->r[j];
+	regptr->sp = (unsigned int)stack_list[thread_id];
+	regptr->pc = s->pc;
+	regptr->dccr = s->dccr;
+	regptr->srp = s->srp;
+}
+
+/* Copy the registers to the stack. Put the register contents of thread
+   thread_id from struct reg to the stack. */
+static void
+copy_registers_to_stack (int thread_id, registers *regptr)
+{
+	int i;
+	stack_registers *d = (stack_registers *)stack_list[thread_id];
+	unsigned int *s = (unsigned int *)regptr;
+	
+	for (i = 0; i < 14; i++) {
+		d->r[i] = *s++;
+	}
+	d->pc = regptr->pc;
+	d->dccr = regptr->dccr;
+	d->srp = regptr->srp;
+}
+#endif
+
+/* Write a value to a specified register in the register image of the current
+   thread. Returns status code SUCCESS, E02 or E05. */
+static int
+write_register (int regno, char *val)
+{
+	int status = SUCCESS;
+	registers *current_reg = &reg;
+
+        if (regno >= R0 && regno <= PC) {
+		/* 32-bit register with simple offset. */
+		hex2mem ((unsigned char *)current_reg + regno * sizeof(unsigned int),
+			 val, sizeof(unsigned int));
+	}
+        else if (regno == P0 || regno == VR || regno == P4 || regno == P8) {
+		/* Do not support read-only registers. */
+		status = E02;
+	}
+        else if (regno == CCR) {
+		/* 16 bit register with complex offset. (P4 is read-only, P6 is not implemented, 
+                   and P7 (MOF) is 32 bits in ETRAX 100LX. */
+		hex2mem ((unsigned char *)&(current_reg->ccr) + (regno-CCR) * sizeof(unsigned short),
+			 val, sizeof(unsigned short));
+	}
+	else if (regno >= MOF && regno <= USP) {
+		/* 32 bit register with complex offset.  (P8 has been taken care of.) */
+		hex2mem ((unsigned char *)&(current_reg->ibr) + (regno-IBR) * sizeof(unsigned int),
+			 val, sizeof(unsigned int));
+	} 
+        else {
+		/* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */
+		status = E05;
+	}
+	return status;
+}
+
+#ifdef PROCESS_SUPPORT
+/* Write a value to a specified register in the stack of a thread other
+   than the current thread. Returns status code SUCCESS or E07. */
+static int
+write_stack_register (int thread_id, int regno, char *valptr)
+{
+	int status = SUCCESS;
+	stack_registers *d = (stack_registers *)stack_list[thread_id];
+	unsigned int val;
+	
+	hex2mem ((unsigned char *)&val, valptr, sizeof(unsigned int));
+	if (regno >= R0 && regno < SP) {
+		d->r[regno] = val;
+	}
+	else if (regno == SP) {
+		stack_list[thread_id] = val;
+	}
+	else if (regno == PC) {
+		d->pc = val;
+	}
+	else if (regno == SRP) {
+		d->srp = val;
+	}
+	else if (regno == DCCR) {
+		d->dccr = val;
+	}
+	else {
+		/* Do not support registers in the current thread. */
+		status = E07;
+	}
+	return status;
+}
+#endif
+
+/* Read a value from a specified register in the register image. Returns the
+   value in the register or -1 for non-implemented registers.
+   Should check consistency_status after a call which may be E05 after changes
+   in the implementation. */
+static int
+read_register (char regno, unsigned int *valptr)
+{
+	registers *current_reg = &reg;
+
+	if (regno >= R0 && regno <= PC) {
+		/* 32-bit register with simple offset. */
+		*valptr = *(unsigned int *)((char *)current_reg + regno * sizeof(unsigned int));
+                return SUCCESS;
+	}
+	else if (regno == P0 || regno == VR) {
+		/* 8 bit register with complex offset. */
+		*valptr = (unsigned int)(*(unsigned char *)
+                                         ((char *)&(current_reg->p0) + (regno-P0) * sizeof(char)));
+                return SUCCESS;
+	}
+	else if (regno == P4 || regno == CCR) {
+		/* 16 bit register with complex offset. */
+		*valptr = (unsigned int)(*(unsigned short *)
+                                         ((char *)&(current_reg->p4) + (regno-P4) * sizeof(unsigned short)));
+                return SUCCESS;
+	}
+	else if (regno >= MOF && regno <= USP) {
+		/* 32 bit register with complex offset. */
+		*valptr = *(unsigned int *)((char *)&(current_reg->p8)
+                                            + (regno-P8) * sizeof(unsigned int));
+                return SUCCESS;
+	}
+	else {
+		/* Do not support nonexisting or unimplemented registers (P2, P3, and P6). */
+		consistency_status = E05;
+		return E05;
+	}
+}
+
+/********************************** Packet I/O ******************************/
+/* Returns the character equivalent of a nibble, bit 7, 6, 5, and 4 of a byte,
+   represented by int x. */
+static inline char
+highhex(int x)
+{
+	return hexchars[(x >> 4) & 0xf];
+}
+
+/* Returns the character equivalent of a nibble, bit 3, 2, 1, and 0 of a byte,
+   represented by int x. */
+static inline char
+lowhex(int x)
+{
+	return hexchars[x & 0xf];
+}
+
+/* Returns the integer equivalent of a hexadecimal character. */
+static int
+hex (char ch)
+{
+	if ((ch >= 'a') && (ch <= 'f'))
+		return (ch - 'a' + 10);
+	if ((ch >= '0') && (ch <= '9'))
+		return (ch - '0');
+	if ((ch >= 'A') && (ch <= 'F'))
+		return (ch - 'A' + 10);
+	return (-1);
+}
+
+/* Convert the memory, pointed to by mem into hexadecimal representation.
+   Put the result in buf, and return a pointer to the last character
+   in buf (null). */
+
+static int do_printk = 0;
+
+static char *
+mem2hex(char *buf, unsigned char *mem, int count)
+{
+	int i;
+	int ch;
+        
+        if (mem == NULL) {
+                /* Bogus read from m0. FIXME: What constitutes a valid address? */
+                for (i = 0; i < count; i++) {
+                        *buf++ = '0';
+                        *buf++ = '0';
+                }
+        } else {
+                /* Valid mem address. */
+                for (i = 0; i < count; i++) {
+                        ch = *mem++;
+                        *buf++ = highhex (ch);
+                        *buf++ = lowhex (ch);
+                }
+        }
+        
+        /* Terminate properly. */
+	*buf = '\0';
+	return (buf);
+}
+
+/* Convert the array, in hexadecimal representation, pointed to by buf into
+   binary representation. Put the result in mem, and return a pointer to
+   the character after the last byte written. */
+static unsigned char*
+hex2mem (unsigned char *mem, char *buf, int count)
+{
+	int i;
+	unsigned char ch;
+	for (i = 0; i < count; i++) {
+		ch = hex (*buf++) << 4;
+		ch = ch + hex (*buf++);
+		*mem++ = ch;
+	}
+	return (mem);
+}
+
+/* Put the content of the array, in binary representation, pointed to by buf
+   into memory pointed to by mem, and return a pointer to the character after
+   the last byte written.
+   Gdb will escape $, #, and the escape char (0x7d). */
+static unsigned char*
+bin2mem (unsigned char *mem, unsigned char *buf, int count)
+{
+	int i;
+	unsigned char *next;
+	for (i = 0; i < count; i++) {
+		/* Check for any escaped characters. Be paranoid and
+		   only unescape chars that should be escaped. */
+		if (*buf == 0x7d) {
+			next = buf + 1;
+			if (*next == 0x3 || *next == 0x4 || *next == 0x5D) /* #, $, ESC */
+				{
+					buf++;
+					*buf += 0x20;
+				}
+		}
+		*mem++ = *buf++;
+	}
+	return (mem);
+}
+
+/* Await the sequence $<data>#<checksum> and store <data> in the array buffer
+   returned. */
+static void
+getpacket (char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	char ch;
+	do {
+		while ((ch = getDebugChar ()) != '$')
+			/* Wait for the start character $ and ignore all other characters */;
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+		/* Read until a # or the end of the buffer is reached */
+		while (count < BUFMAX) {
+			ch = getDebugChar ();
+			if (ch == '#')
+				break;
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+		buffer[count] = '\0';
+		
+		if (ch == '#') {
+			xmitcsum = hex (getDebugChar ()) << 4;
+			xmitcsum += hex (getDebugChar ());
+			if (checksum != xmitcsum) {
+				/* Wrong checksum */
+				putDebugChar ('-');
+			}
+			else {
+				/* Correct checksum */
+				putDebugChar ('+');
+				/* If sequence characters are received, reply with them */
+				if (buffer[2] == ':') {
+					putDebugChar (buffer[0]);
+					putDebugChar (buffer[1]);
+					/* Remove the sequence characters from the buffer */
+					count = gdb_cris_strlen (buffer);
+					for (i = 3; i <= count; i++)
+						buffer[i - 3] = buffer[i];
+				}
+			}
+		}
+	} while (checksum != xmitcsum);
+}
+
+/* Send $<data>#<checksum> from the <data> in the array buffer. */
+
+static void
+putpacket(char *buffer)
+{
+	int checksum;
+	int runlen;
+	int encode;
+	
+	do {
+		char *src = buffer;
+		putDebugChar ('$');
+		checksum = 0;
+		while (*src) {
+			/* Do run length encoding */
+			putDebugChar (*src);
+			checksum += *src;
+			runlen = 0;
+			while (runlen < RUNLENMAX && *src == src[runlen]) {
+				runlen++;
+			}
+			if (runlen > 3) {
+				/* Got a useful amount */
+				putDebugChar ('*');
+				checksum += '*';
+				encode = runlen + ' ' - 4;
+				putDebugChar (encode);
+				checksum += encode;
+				src += runlen;
+			}
+			else {
+				src++;
+			}
+		}
+		putDebugChar ('#');
+		putDebugChar (highhex (checksum));
+		putDebugChar (lowhex (checksum));
+	} while(kgdb_started && (getDebugChar() != '+'));
+}
+
+/* The string str is prepended with the GDB printout token and sent. Required
+   in traditional implementations. */
+void
+putDebugString (const unsigned char *str, int length)
+{
+        remcomOutBuffer[0] = 'O';
+        mem2hex(&remcomOutBuffer[1], (unsigned char *)str, length);
+        putpacket(remcomOutBuffer);
+}
+
+/********************************** Handle exceptions ************************/
+/* Build and send a response packet in order to inform the host the
+   stub is stopped. TAAn...:r...;n...:r...;n...:r...;
+                    AA = signal number
+                    n... = register number (hex)
+                    r... = register contents
+                    n... = `thread'
+                    r... = thread process ID.  This is a hex integer.
+                    n... = other string not starting with valid hex digit.
+                    gdb should ignore this n,r pair and go on to the next.
+                    This way we can extend the protocol. */
+static void
+stub_is_stopped(int sigval)
+{
+	char *ptr = remcomOutBuffer;
+	int regno;
+
+	unsigned int reg_cont;
+	int status;
+        
+	/* Send trap type (converted to signal) */
+
+	*ptr++ = 'T';	
+	*ptr++ = highhex (sigval);
+	*ptr++ = lowhex (sigval);
+
+	/* Send register contents. We probably only need to send the
+	 * PC, frame pointer and stack pointer here. Other registers will be
+	 * explicitely asked for. But for now, send all. 
+	 */
+	
+	for (regno = R0; regno <= USP; regno++) {
+		/* Store n...:r...; for the registers in the buffer. */
+
+                status = read_register (regno, &reg_cont);
+                
+		if (status == SUCCESS) {
+                        
+                        *ptr++ = highhex (regno);
+                        *ptr++ = lowhex (regno);
+                        *ptr++ = ':';
+
+                        ptr = mem2hex(ptr, (unsigned char *)&reg_cont,
+                                      register_size[regno]);
+                        *ptr++ = ';';
+                }
+                
+	}
+
+#ifdef PROCESS_SUPPORT
+	/* Store the registers of the executing thread. Assume that both step,
+	   continue, and register content requests are with respect to this
+	   thread. The executing task is from the operating system scheduler. */
+
+	current_thread_c = executing_task;
+	current_thread_g = executing_task;
+
+	/* A struct assignment translates into a libc memcpy call. Avoid
+	   all libc functions in order to prevent recursive break points. */
+	copy_registers (&reg_g, &reg, sizeof(registers));
+
+	/* Store thread:r...; with the executing task TID. */
+	gdb_cris_strcpy (&remcomOutBuffer[pos], "thread:");
+	pos += gdb_cris_strlen ("thread:");
+	remcomOutBuffer[pos++] = highhex (executing_task);
+	remcomOutBuffer[pos++] = lowhex (executing_task);
+	gdb_cris_strcpy (&remcomOutBuffer[pos], ";");
+#endif
+
+	/* null-terminate and send it off */
+
+	*ptr = 0;
+
+	putpacket (remcomOutBuffer);
+}
+
+/* All expected commands are sent from remote.c. Send a response according
+   to the description in remote.c. */
+static void
+handle_exception (int sigval)
+{
+	/* Avoid warning of not used. */
+
+	USEDFUN(handle_exception);
+	USEDVAR(internal_stack[0]);
+
+	/* Send response. */
+
+	stub_is_stopped (sigval);
+
+	for (;;) {
+		remcomOutBuffer[0] = '\0';
+		getpacket (remcomInBuffer);
+		switch (remcomInBuffer[0]) {
+			case 'g':
+				/* Read registers: g
+				   Success: Each byte of register data is described by two hex digits.
+				   Registers are in the internal order for GDB, and the bytes
+				   in a register  are in the same order the machine uses.
+				   Failure: void. */
+				
+				{
+#ifdef PROCESS_SUPPORT
+					/* Use the special register content in the executing thread. */
+					copy_registers (&reg_g, &reg, sizeof(registers));
+					/* Replace the content available on the stack. */
+					if (current_thread_g != executing_task) {
+						copy_registers_from_stack (current_thread_g, &reg_g);
+					}
+					mem2hex ((unsigned char *)remcomOutBuffer, (unsigned char *)&reg_g, sizeof(registers));
+#else
+					mem2hex(remcomOutBuffer, (char *)&reg, sizeof(registers));
+#endif
+				}
+				break;
+				
+			case 'G':
+				/* Write registers. GXX..XX
+				   Each byte of register data  is described by two hex digits.
+				   Success: OK
+				   Failure: void. */
+#ifdef PROCESS_SUPPORT
+				hex2mem ((unsigned char *)&reg_g, &remcomInBuffer[1], sizeof(registers));
+				if (current_thread_g == executing_task) {
+					copy_registers (&reg, &reg_g, sizeof(registers));
+				}
+				else {
+					copy_registers_to_stack(current_thread_g, &reg_g);
+				}
+#else
+				hex2mem((char *)&reg, &remcomInBuffer[1], sizeof(registers));
+#endif
+				gdb_cris_strcpy (remcomOutBuffer, "OK");
+				break;
+				
+			case 'P':
+				/* Write register. Pn...=r...
+				   Write register n..., hex value without 0x, with value r...,
+				   which contains a hex value without 0x and two hex digits
+				   for each byte in the register (target byte order). P1f=11223344 means
+				   set register 31 to 44332211.
+				   Success: OK
+				   Failure: E02, E05 */
+				{
+					char *suffix;
+					int regno = gdb_cris_strtol (&remcomInBuffer[1], &suffix, 16);
+					int status;
+#ifdef PROCESS_SUPPORT
+					if (current_thread_g =! executing_task)
+						status = write_stack_register (current_thread_g, regno, suffix+1);
+					else
+#endif
+						status = write_register (regno, suffix+1);
+
+					switch (status) {
+						case E02:
+							/* Do not support read-only registers. */
+							gdb_cris_strcpy (remcomOutBuffer, error_message[E02]);
+							break;
+						case E05:
+							/* Do not support non-existing registers. */
+							gdb_cris_strcpy (remcomOutBuffer, error_message[E05]);
+							break;
+						case E07:
+							/* Do not support non-existing registers on the stack. */
+							gdb_cris_strcpy (remcomOutBuffer, error_message[E07]);
+							break;
+						default:
+							/* Valid register number. */
+							gdb_cris_strcpy (remcomOutBuffer, "OK");
+							break;
+					}
+				}
+				break;
+				
+			case 'm':
+				/* Read from memory. mAA..AA,LLLL
+				   AA..AA is the address and LLLL is the length.
+				   Success: XX..XX is the memory content.  Can be fewer bytes than
+				   requested if only part of the data may be read. m6000120a,6c means
+				   retrieve 108 byte from base address 6000120a.
+				   Failure: void. */
+				{
+                                        char *suffix;
+					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1],
+                                                                                               &suffix, 16);                                        int length = gdb_cris_strtol(suffix+1, 0, 16);
+                                        
+                                        mem2hex(remcomOutBuffer, addr, length);
+                                }
+				break;
+				
+			case 'X':
+				/* Write to memory. XAA..AA,LLLL:XX..XX
+				   AA..AA is the start address,  LLLL is the number of bytes, and
+				   XX..XX is the binary data.
+				   Success: OK
+				   Failure: void. */
+			case 'M':
+				/* Write to memory. MAA..AA,LLLL:XX..XX
+				   AA..AA is the start address,  LLLL is the number of bytes, and
+				   XX..XX is the hexadecimal data.
+				   Success: OK
+				   Failure: void. */
+				{
+					char *lenptr;
+					char *dataptr;
+					unsigned char *addr = (unsigned char *)gdb_cris_strtol(&remcomInBuffer[1],
+										      &lenptr, 16);
+					int length = gdb_cris_strtol(lenptr+1, &dataptr, 16);
+					if (*lenptr == ',' && *dataptr == ':') {
+						if (remcomInBuffer[0] == 'M') {
+							hex2mem(addr, dataptr + 1, length);
+						}
+						else /* X */ {
+							bin2mem(addr, dataptr + 1, length);
+						}
+						gdb_cris_strcpy (remcomOutBuffer, "OK");
+					}
+					else {
+						gdb_cris_strcpy (remcomOutBuffer, error_message[E06]);
+					}
+				}
+				break;
+				
+			case 'c':
+				/* Continue execution. cAA..AA
+				   AA..AA is the address where execution is resumed. If AA..AA is
+				   omitted, resume at the present address.
+				   Success: return to the executing thread.
+				   Failure: will never know. */
+				if (remcomInBuffer[1] != '\0') {
+					reg.pc = gdb_cris_strtol (&remcomInBuffer[1], 0, 16);
+				}
+				enableDebugIRQ();
+				return;
+				
+			case 's':
+				/* Step. sAA..AA
+				   AA..AA is the address where execution is resumed. If AA..AA is
+				   omitted, resume at the present address. Success: return to the
+				   executing thread. Failure: will never know.
+				   
+				   Should never be invoked. The single-step is implemented on
+				   the host side. If ever invoked, it is an internal error E04. */
+				gdb_cris_strcpy (remcomOutBuffer, error_message[E04]);
+				putpacket (remcomOutBuffer);
+				return;
+				
+			case '?':
+				/* The last signal which caused a stop. ?
+				   Success: SAA, where AA is the signal number.
+				   Failure: void. */
+				remcomOutBuffer[0] = 'S';
+				remcomOutBuffer[1] = highhex (sigval);
+				remcomOutBuffer[2] = lowhex (sigval);
+				remcomOutBuffer[3] = 0;
+				break;
+				
+			case 'D':
+				/* Detach from host. D
+				   Success: OK, and return to the executing thread.
+				   Failure: will never know */
+				putpacket ("OK");
+				return;
+				
+			case 'k':
+			case 'r':
+				/* kill request or reset request.
+				   Success: restart of target.
+				   Failure: will never know. */
+				kill_restart ();
+				break;
+				
+			case 'C':
+			case 'S':
+			case '!':
+			case 'R':
+			case 'd':
+				/* Continue with signal sig. Csig;AA..AA
+				   Step with signal sig. Ssig;AA..AA
+				   Use the extended remote protocol. !
+				   Restart the target system. R0
+				   Toggle debug flag. d
+				   Search backwards. tAA:PP,MM
+				   Not supported: E04 */
+				gdb_cris_strcpy (remcomOutBuffer, error_message[E04]);
+				break;
+#ifdef PROCESS_SUPPORT
+
+			case 'T':
+				/* Thread alive. TXX
+				   Is thread XX alive?
+				   Success: OK, thread XX is alive.
+				   Failure: E03, thread XX is dead. */
+				{
+					int thread_id = (int)gdb_cris_strtol (&remcomInBuffer[1], 0, 16);
+					/* Cannot tell whether it is alive or not. */
+					if (thread_id >= 0 && thread_id < number_of_tasks)
+						gdb_cris_strcpy (remcomOutBuffer, "OK");
+				}
+				break;
+								
+			case 'H':
+				/* Set thread for subsequent operations: Hct
+				   c = 'c' for thread used in step and continue;
+				   t can be -1 for all threads.
+				   c = 'g' for thread used in other  operations.
+				   t = 0 means pick any thread.
+				   Success: OK
+				   Failure: E01 */
+				{
+					int thread_id = gdb_cris_strtol (&remcomInBuffer[2], 0, 16);
+					if (remcomInBuffer[1] == 'c') {
+						/* c = 'c' for thread used in step and continue */
+						/* Do not change current_thread_c here. It would create a mess in
+						   the scheduler. */
+						gdb_cris_strcpy (remcomOutBuffer, "OK");
+					}
+					else if (remcomInBuffer[1] == 'g') {
+						/* c = 'g' for thread used in other  operations.
+						   t = 0 means pick any thread. Impossible since the scheduler does
+						   not allow that. */
+						if (thread_id >= 0 && thread_id < number_of_tasks) {
+							current_thread_g = thread_id;
+							gdb_cris_strcpy (remcomOutBuffer, "OK");
+						}
+						else {
+							/* Not expected - send an error message. */
+							gdb_cris_strcpy (remcomOutBuffer, error_message[E01]);
+						}
+					}
+					else {
+						/* Not expected - send an error message. */
+						gdb_cris_strcpy (remcomOutBuffer, error_message[E01]);
+					}
+				}
+				break;
+				
+			case 'q':
+			case 'Q':
+				/* Query of general interest. qXXXX
+				   Set general value XXXX. QXXXX=yyyy */
+				{
+					int pos;
+					int nextpos;
+					int thread_id;
+					
+					switch (remcomInBuffer[1]) {
+						case 'C':
+							/* Identify the remote current thread. */
+							gdb_cris_strcpy (&remcomOutBuffer[0], "QC");
+							remcomOutBuffer[2] = highhex (current_thread_c);
+							remcomOutBuffer[3] = lowhex (current_thread_c);
+							remcomOutBuffer[4] = '\0';
+							break;
+						case 'L':
+							gdb_cris_strcpy (&remcomOutBuffer[0], "QM");
+							/* Reply with number of threads. */
+							if (os_is_started()) {
+								remcomOutBuffer[2] = highhex (number_of_tasks);
+								remcomOutBuffer[3] = lowhex (number_of_tasks);
+							}
+							else {
+								remcomOutBuffer[2] = highhex (0);
+								remcomOutBuffer[3] = lowhex (1);
+							}
+							/* Done with the reply. */
+							remcomOutBuffer[4] = lowhex (1);
+							pos = 5;
+							/* Expects the argument thread id. */
+							for (; pos < (5 + HEXCHARS_IN_THREAD_ID); pos++)
+								remcomOutBuffer[pos] = remcomInBuffer[pos];
+							/* Reply with the thread identifiers. */
+							if (os_is_started()) {
+								/* Store the thread identifiers of all tasks. */
+								for (thread_id = 0; thread_id < number_of_tasks; thread_id++) {
+									nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
+									for (; pos < nextpos; pos ++)
+										remcomOutBuffer[pos] = lowhex (0);
+									remcomOutBuffer[pos++] = lowhex (thread_id);
+								}
+							}
+							else {
+								/* Store the thread identifier of the boot task. */
+								nextpos = pos + HEXCHARS_IN_THREAD_ID - 1;
+								for (; pos < nextpos; pos ++)
+									remcomOutBuffer[pos] = lowhex (0);
+								remcomOutBuffer[pos++] = lowhex (current_thread_c);
+							}
+							remcomOutBuffer[pos] = '\0';
+							break;
+						default:
+							/* Not supported: "" */
+							/* Request information about section offsets: qOffsets. */
+							remcomOutBuffer[0] = 0;
+							break;
+					}
+				}
+				break;
+#endif /* PROCESS_SUPPORT */
+				
+			default:
+				/* The stub should ignore other request and send an empty
+				   response ($#<checksum>). This way we can extend the protocol and GDB
+				   can tell whether the stub it is talking to uses the old or the new. */
+				remcomOutBuffer[0] = 0;
+				break;
+		}
+		putpacket(remcomOutBuffer);
+	}
+}
+
+/* The jump is to the address 0x00000002. Performs a complete re-start
+   from scratch. */
+static void
+kill_restart ()
+{
+	__asm__ volatile ("jump 2");
+}
+
+/********************************** Breakpoint *******************************/
+/* The hook for both a static (compiled) and a dynamic breakpoint set by GDB.
+   An internal stack is used by the stub. The register image of the caller is
+   stored in the structure register_image.
+   Interactive communication with the host is handled by handle_exception and
+   finally the register image is restored. */
+
+void kgdb_handle_breakpoint(void);
+
+asm ("
+  .global _kgdb_handle_breakpoint
+_kgdb_handle_breakpoint:
+;;
+;; Response to the break-instruction
+;;
+;; Create a register image of the caller
+;;
+  move     dccr,[_reg+0x5E] ; Save the flags in DCCR before disable interrupts
+  di                        ; Disable interrupts
+  move.d   r0,[_reg]        ; Save R0
+  move.d   r1,[_reg+0x04]   ; Save R1
+  move.d   r2,[_reg+0x08]   ; Save R2
+  move.d   r3,[_reg+0x0C]   ; Save R3
+  move.d   r4,[_reg+0x10]   ; Save R4
+  move.d   r5,[_reg+0x14]   ; Save R5
+  move.d   r6,[_reg+0x18]   ; Save R6
+  move.d   r7,[_reg+0x1C]   ; Save R7
+  move.d   r8,[_reg+0x20]   ; Save R8
+  move.d   r9,[_reg+0x24]   ; Save R9
+  move.d   r10,[_reg+0x28]  ; Save R10
+  move.d   r11,[_reg+0x2C]  ; Save R11
+  move.d   r12,[_reg+0x30]  ; Save R12
+  move.d   r13,[_reg+0x34]  ; Save R13
+  move.d   sp,[_reg+0x38]   ; Save SP (R14)
+;; Due to the old assembler-versions BRP might not be recognized
+  .word 0xE670              ; move brp,r0
+  subq     2,r0             ; Set to address of previous instruction.
+  move.d   r0,[_reg+0x3c]   ; Save the address in PC (R15)
+  clear.b  [_reg+0x40]      ; Clear P0
+  move     vr,[_reg+0x41]   ; Save special register P1
+  clear.w  [_reg+0x42]      ; Clear P4
+  move     ccr,[_reg+0x44]  ; Save special register CCR
+  move     mof,[_reg+0x46]  ; P7
+  clear.d  [_reg+0x4A]      ; Clear P8
+  move     ibr,[_reg+0x4E]  ; P9,
+  move     irp,[_reg+0x52]  ; P10,
+  move     srp,[_reg+0x56]  ; P11,
+  move     dtp0,[_reg+0x5A] ; P12, register BAR, assembler might not know BAR
+                            ; P13, register DCCR already saved
+;; Due to the old assembler-versions BRP might not be recognized
+  .word 0xE670              ; move brp,r0
+;; Static (compiled) breakpoints must return to the next instruction in order
+;; to avoid infinite loops. Dynamic (gdb-invoked) must restore the instruction
+;; in order to execute it when execution is continued.
+  test.b   [_is_dyn_brkp]    ; Is this a dynamic breakpoint?
+  beq      is_static         ; No, a static breakpoint
+  nop
+  subq     2,r0              ; rerun the instruction the break replaced
+is_static:
+  moveq    1,r1
+  move.b   r1,[_is_dyn_brkp] ; Set the state variable to dynamic breakpoint
+  move.d   r0,[_reg+0x62]    ; Save the return address in BRP
+  move     usp,[_reg+0x66]   ; USP
+;;
+;; Handle the communication
+;;
+  move.d   _internal_stack+1020,sp ; Use the internal stack which grows upward
+  moveq    5,r10                   ; SIGTRAP
+  jsr      _handle_exception       ; Interactive routine
+;;
+;; Return to the caller
+;;
+   move.d  [_reg],r0         ; Restore R0
+   move.d  [_reg+0x04],r1    ; Restore R1
+   move.d  [_reg+0x08],r2    ; Restore R2
+   move.d  [_reg+0x0C],r3    ; Restore R3
+   move.d  [_reg+0x10],r4    ; Restore R4
+   move.d  [_reg+0x14],r5    ; Restore R5
+   move.d  [_reg+0x18],r6    ; Restore R6
+   move.d  [_reg+0x1C],r7    ; Restore R7
+   move.d  [_reg+0x20],r8    ; Restore R8
+   move.d  [_reg+0x24],r9    ; Restore R9
+   move.d  [_reg+0x28],r10   ; Restore R10
+   move.d  [_reg+0x2C],r11   ; Restore R11
+   move.d  [_reg+0x30],r12   ; Restore R12
+   move.d  [_reg+0x34],r13   ; Restore R13
+;;
+;; FIXME: Which registers should be restored?
+;;
+   move.d  [_reg+0x38],sp    ; Restore SP (R14)
+   move    [_reg+0x56],srp   ; Restore the subroutine return pointer.
+   move    [_reg+0x5E],dccr  ; Restore DCCR
+   move    [_reg+0x66],usp   ; Restore USP
+   jump    [_reg+0x62]       ; A jump to the content in register BRP works.
+   nop                       ;
+");
+
+/* The hook for an interrupt generated by GDB. An internal stack is used
+   by the stub. The register image of the caller is stored in the structure
+   register_image. Interactive communication with the host is handled by
+   handle_exception and finally the register image is restored. Due to the
+   old assembler which does not recognise the break instruction and the
+   breakpoint return pointer hex-code is used. */
+
+void kgdb_handle_serial(void);
+
+asm ("
+  .global _kgdb_handle_serial
+_kgdb_handle_serial:
+;;
+;; Response to a serial interrupt
+;;
+
+  move     dccr,[_reg+0x5E] ; Save the flags in DCCR
+  di                        ; Disable interrupts
+  move.d   r0,[_reg]        ; Save R0
+  move.d   r1,[_reg+0x04]   ; Save R1
+  move.d   r2,[_reg+0x08]   ; Save R2
+  move.d   r3,[_reg+0x0C]   ; Save R3
+  move.d   r4,[_reg+0x10]   ; Save R4
+  move.d   r5,[_reg+0x14]   ; Save R5
+  move.d   r6,[_reg+0x18]   ; Save R6
+  move.d   r7,[_reg+0x1C]   ; Save R7
+  move.d   r8,[_reg+0x20]   ; Save R8
+  move.d   r9,[_reg+0x24]   ; Save R9
+  move.d   r10,[_reg+0x28]  ; Save R10
+  move.d   r11,[_reg+0x2C]  ; Save R11
+  move.d   r12,[_reg+0x30]  ; Save R12
+  move.d   r13,[_reg+0x34]  ; Save R13
+  move.d   sp,[_reg+0x38]   ; Save SP (R14)
+  move     irp,[_reg+0x3c]  ; Save the address in PC (R15)
+  clear.b  [_reg+0x40]      ; Clear P0
+  move     vr,[_reg+0x41]   ; Save special register P1,
+  clear.w  [_reg+0x42]      ; Clear P4
+  move     ccr,[_reg+0x44]  ; Save special register CCR
+  move     mof,[_reg+0x46]  ; P7
+  clear.d  [_reg+0x4A]      ; Clear P8
+  move     ibr,[_reg+0x4E]  ; P9,
+  move     irp,[_reg+0x52]  ; P10,
+  move     srp,[_reg+0x56]  ; P11,
+  move     dtp0,[_reg+0x5A] ; P12, register BAR, assembler might not know BAR
+                            ; P13, register DCCR already saved
+;; Due to the old assembler-versions BRP might not be recognized
+  .word 0xE670              ; move brp,r0
+  move.d   r0,[_reg+0x62]   ; Save the return address in BRP
+  move     usp,[_reg+0x66]  ; USP
+
+;; get the serial character (from debugport.c) and check if its a ctrl-c
+
+  jsr _getDebugChar
+  cmp.b 3, r10
+  bne goback
+  nop
+
+;;
+;; Handle the communication
+;;
+  move.d   _internal_stack+1020,sp ; Use the internal stack
+  moveq    2,r10                   ; SIGINT
+  jsr      _handle_exception       ; Interactive routine
+
+goback:
+;;
+;; Return to the caller
+;;
+   move.d  [_reg],r0         ; Restore R0
+   move.d  [_reg+0x04],r1    ; Restore R1
+   move.d  [_reg+0x08],r2    ; Restore R2
+   move.d  [_reg+0x0C],r3    ; Restore R3
+   move.d  [_reg+0x10],r4    ; Restore R4
+   move.d  [_reg+0x14],r5    ; Restore R5
+   move.d  [_reg+0x18],r6    ; Restore R6
+   move.d  [_reg+0x1C],r7    ; Restore R7
+   move.d  [_reg+0x20],r8    ; Restore R8
+   move.d  [_reg+0x24],r9    ; Restore R9
+   move.d  [_reg+0x28],r10   ; Restore R10
+   move.d  [_reg+0x2C],r11   ; Restore R11
+   move.d  [_reg+0x30],r12   ; Restore R12
+   move.d  [_reg+0x34],r13   ; Restore R13
+;;
+;; FIXME: Which registers should be restored?
+;;
+   move.d  [_reg+0x38],sp    ; Restore SP (R14)
+   move    [_reg+0x56],srp   ; Restore the subroutine return pointer.
+   move    [_reg+0x5E],dccr  ; Restore DCCR
+   move    [_reg+0x66],usp   ; Restore USP
+   reti                      ; Return from the interrupt routine
+   nop
+");
+
+/* Use this static breakpoint in the start-up only. */
+
+void
+breakpoint(void)
+{
+	kgdb_started = 1;
+	is_dyn_brkp = 0;     /* This is a static, not a dynamic breakpoint. */
+	__asm__ volatile ("break 8"); /* Jump to handle_breakpoint. */
+}
+
+/* initialize kgdb. doesn't break into the debugger, but sets up irq and ports */
+
+void
+kgdb_init(void)
+{
+	/* could initialize debug port as well but it's done in head.S already... */
+
+	set_break_vector(8, kgdb_handle_breakpoint);
+	set_int_vector(8, kgdb_handle_serial, 0);
+	
+	enableDebugIRQ();
+}
+
+/****************************** End of file **********************************/
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/ksyms.c linux/arch/cris/kernel/ksyms.c
--- v2.4.1/linux/arch/cris/kernel/ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/ksyms.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,2 @@
+/* no kernel support yet */
+
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/process.c linux/arch/cris/kernel/process.c
--- v2.4.1/linux/arch/cris/kernel/process.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/process.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,327 @@
+/* $Id: process.c,v 1.8 2000/09/13 14:34:13 bjornw Exp $
+ * 
+ *  linux/arch/cris/kernel/process.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 2000  Axis Communications AB
+ *
+ *  Authors:   Bjorn Wesen (bjornw@axis.com)
+ *
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <linux/smp.h>
+
+//#define DEBUG
+
+/*
+ * Initial task structure. Make this a per-architecture thing,
+ * because different architectures tend to have different
+ * alignment requirements and potentially different initial
+ * setup.
+ */
+
+static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS;
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+
+union task_union init_task_union 
+      __attribute__((__section__(".data.init_task"))) =
+             { INIT_TASK(init_task_union.task) };
+
+static int hlt_counter=0;
+
+/* in a system call, set_esp0 is called to remember the stack frame, therefore
+   in the implementation of syscalls we can use that value to access the stack
+   frame and saved registers.
+*/
+
+#define currentregs ((struct pt_regs *)current->thread.esp0)
+
+asmlinkage void set_esp0(unsigned long ssp)
+{
+	current->thread.esp0 = ssp;
+}
+
+void disable_hlt(void)
+{
+	hlt_counter++;
+}
+
+void enable_hlt(void)
+{
+	hlt_counter--;
+}
+ 
+int cpu_idle(void *unused)
+{
+	while(1) {
+		current->counter = -100;
+		schedule();
+	}
+}
+
+/* if the watchdog is enabled, we can simply disable interrupts and go
+ * into an eternal loop, and the watchdog will reset the CPU after 0.1s
+ */
+
+void hard_reset_now (void)
+{
+	printk("*** HARD RESET ***\n");
+	cli();
+	while(1) /* waiting for RETRIBUTION! */ ;
+}
+
+void machine_restart(void)
+{
+	hard_reset_now();
+}
+
+/* can't do much here... */
+
+void machine_halt(void)
+{
+}
+
+void machine_power_off(void)
+{
+}
+
+/*
+ * This is the mechanism for creating a new kernel thread.
+ *
+ * NOTE! Only a kernel-only process(ie the swapper or direct descendants
+ * who haven't done an "execve()") should use this: it will work within
+ * a system call from a "real" process, but the process memory space will
+ * not be free'd until both the parent and the child have exited.
+ */
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	register long __a __asm__ ("r10");
+	
+	__asm__ __volatile__
+		("movu.w %1,r1\n\t"     /* r1 contains syscall number, to sys_clone */
+		 "clear.d r10\n\t"      /* r10 is argument 1 to clone */
+		 "move.d %2,r11\n\t"    /* r11 is argument 2 to clone, the flags */
+		 "break 13\n\t"         /* call sys_clone, this will fork */
+		 "test.d r10\n\t"       /* parent or child? child returns 0 here. */
+		 "bne 1f\n\t"           /* jump if parent */
+		 "nop\n\t"              /* delay slot */
+		 "move.d %4,r10\n\t"    /* set argument to function to call */
+		 "jsr %5\n\t"           /* call specified function */
+		 "movu.w %3,r1\n\t"     /* r1 is sys_exit syscall number */
+		 "moveq -1,r10\n\t"     /* Give a really bad exit-value */
+		 "break 13\n\t"         /* call sys_exit, killing the child */
+		 "1:\n\t"
+		 : "=r" (__a) 
+		 : "g" (__NR_clone), "r" (flags | CLONE_VM), "g" (__NR_exit),
+		   "r" (arg), "r" (fn) 
+		 : "r10", "r11", "r1");
+	
+	return __a;
+}
+
+
+
+void flush_thread(void)
+{
+}
+
+asmlinkage void ret_from_sys_call(void);
+
+/* setup the child's kernel stack with a pt_regs and switch_stack on it.
+ * it will be un-nested during _resume and _ret_from_sys_call when the
+ * new thread is scheduled.
+ *
+ * also setup the thread switching structure which is used to keep
+ * thread-specific data during _resumes.
+ *
+ */
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+		unsigned long unused,
+		struct task_struct *p, struct pt_regs *regs)
+{
+	struct pt_regs * childregs;
+	struct switch_stack *swstack;
+	
+	/* put the pt_regs structure at the end of the new kernel stack page and fix it up
+	 * remember that the task_struct doubles as the kernel stack for the task
+	 */
+
+	childregs = ((struct pt_regs *) ((unsigned long)p + THREAD_SIZE)) - 1;
+
+	*childregs = *regs;  /* struct copy of pt_regs */
+
+	childregs->r10 = 0;  /* child returns 0 after a fork/clone */
+	
+	/* put the switch stack right below the pt_regs */
+
+	swstack = ((struct switch_stack *)childregs) - 1;
+
+	swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */
+
+	/* we want to return into ret_from_sys_call after the _resume */
+
+	swstack->return_ip = (unsigned long) ret_from_sys_call;
+	
+	/* fix the user-mode stackpointer */
+
+	p->thread.usp = usp;	
+
+	/* and the kernel-mode one */
+
+	p->thread.ksp = (unsigned long) swstack;
+
+	/* esp0 keeps the pt_regs stacked structure pointer */
+
+	p->thread.esp0 = (unsigned long) childregs;
+
+#ifdef DEBUG
+	printk("kern_stack_page 0x%x, used stack %d, thread.usp 0x%x, usp 0x%x\n", 
+	       current->kernel_stack_page, usedstack, p->thread.usp, usp);
+#endif
+	return 0;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+	int i;
+#if 0
+/* changed the size calculations - should hopefully work better. lbt */
+	dump->magic = CMAGIC;
+	dump->start_code = 0;
+	dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
+	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+	dump->u_dsize -= dump->u_tsize;
+	dump->u_ssize = 0;
+	for (i = 0; i < 8; i++)
+		dump->u_debugreg[i] = current->debugreg[i];  
+
+	if (dump->start_stack < TASK_SIZE)
+		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+
+	dump->regs = *regs;
+
+	dump->u_fpvalid = dump_fpu (regs, &dump->i387);
+#endif 
+}
+
+asmlinkage int sys_fork(void)
+{
+	return do_fork(SIGCHLD, rdusp(), currentregs, 0);
+}
+
+/* if newusp is 0, we just grab the old usp */
+
+asmlinkage int sys_clone(unsigned long newusp, unsigned long flags)
+{
+	if (!newusp)
+		newusp = rdusp();
+	return do_fork(flags, newusp, currentregs, 0);
+}
+
+/* vfork is a system call in i386 because of register-pressure - maybe
+ * we can remove it and handle it in libc but we put it here until then.
+ */
+
+asmlinkage int sys_vfork(void)
+{
+        return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), currentregs, 0);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(const char *fname, char **argv, char **envp)
+{
+	int error;
+	char *filename;
+
+	filename = getname(fname);
+	error = PTR_ERR(filename);
+
+	if (IS_ERR(filename))
+	        goto out;
+	error = do_execve(filename, argv, envp, currentregs);
+	putname(filename);
+ out:
+	return error;
+}
+
+/*
+ * These bracket the sleeping functions..
+ */
+
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched     ((unsigned long) scheduling_functions_start_here)
+#define last_sched      ((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+#if 0
+	/* YURGH. TODO. */
+
+        unsigned long ebp, esp, eip;
+        unsigned long stack_page;
+        int count = 0;
+        if (!p || p == current || p->state == TASK_RUNNING)
+                return 0;
+        stack_page = (unsigned long)p;
+        esp = p->thread.esp;
+        if (!stack_page || esp < stack_page || esp > 8188+stack_page)
+                return 0;
+        /* include/asm-i386/system.h:switch_to() pushes ebp last. */
+        ebp = *(unsigned long *) esp;
+        do {
+                if (ebp < stack_page || ebp > 8184+stack_page)
+                        return 0;
+                eip = *(unsigned long *) (ebp+4);
+                if (eip < first_sched || eip >= last_sched)
+                        return eip;
+                ebp = *(unsigned long *) ebp;
+        } while (count++ < 16);
+#endif
+        return 0;
+}
+#undef last_sched
+#undef first_sched
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/ptrace.c linux/arch/cris/kernel/ptrace.c
--- v2.4.1/linux/arch/cris/kernel/ptrace.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/ptrace.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,340 @@
+/*
+ *  linux/arch/cris/kernel/ptrace.c
+ *
+ * Parts taken from the m68k port.
+ * 
+ * Copyright (c) 2000 Axis Communications AB
+ *
+ * Authors:   Bjorn Wesen
+ *
+ * $Log: ptrace.c,v $
+ * Revision 1.3  2000/12/18 23:45:25  bjornw
+ * Linux/CRIS first version
+ *
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which bits in DCCR the user has access to. */
+/* 1 = access 0 = no access */
+#define DCCR_MASK 0x0000001f     /* XNZVC */
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, unsigned int regno)
+{
+	/* USP is a special case, it's not in the pt_regs struct but
+	 * in the tasks thread struct
+	 */
+
+	if (regno == PT_USP)
+		return task->thread.usp;
+	else if (regno <= PT_MAX)
+		return ((unsigned long *)(task->thread.esp0))[regno];
+	else
+		return 0;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task, unsigned int regno,
+			  unsigned long data)
+{
+	unsigned long *addr;
+
+	if (regno == PT_USP)
+		task->thread.usp = data;
+	else if (regno <= PT_MAX)
+		((unsigned long *)(task->thread.esp0))[regno] = data;
+	else
+		return -1;
+	return 0;
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	int ret;
+
+	lock_kernel();
+	ret = -EPERM;
+	if (request == PTRACE_TRACEME) {
+		/* are we already being traced? */
+		if (current->ptrace & PT_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->ptrace |= PT_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	if (child)
+		get_task_struct(child);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out_tsk;
+	if (request == PTRACE_ATTACH) {
+		if (child == current)
+			goto out_tsk;
+		if ((!child->dumpable ||
+		    (current->uid != child->euid) ||
+		    (current->uid != child->suid) ||
+		    (current->uid != child->uid) ||
+	 	    (current->gid != child->egid) ||
+		    (current->gid != child->sgid) ||
+	 	    (!cap_issubset(child->cap_permitted, current->cap_permitted)) ||
+	 	    (current->gid != child->gid)) && !capable(CAP_SYS_PTRACE))
+			goto out_tsk;
+		/* the same process cannot be attached many times */
+		if (child->ptrace & PT_PTRACED)
+			goto out_tsk;
+		child->ptrace |= PT_PTRACED;
+
+		write_lock_irq(&tasklist_lock);
+		if (child->p_pptr != current) {
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+		}
+		write_unlock_irq(&tasklist_lock);
+
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out_tsk;
+	}
+	ret = -ESRCH;
+	if (!(child->ptrace & PT_PTRACED))
+		goto out_tsk;
+	if (child->state != TASK_STOPPED) {
+		if (request != PTRACE_KILL)
+			goto out_tsk;
+	}
+	if (child->p_pptr != current)
+		goto out_tsk;
+
+	switch (request) {
+	/* when I and D space are separate, these will need to be fixed. */
+		case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+		case PTRACE_PEEKDATA: {
+			unsigned long tmp;
+			int copied;
+
+			copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+			ret = -EIO;
+			if (copied != sizeof(tmp))
+				break;
+			ret = put_user(tmp,(unsigned long *) data);
+			break;
+		}
+
+		/* read the word at location addr in the USER area. */
+		case PTRACE_PEEKUSR: {
+			unsigned long tmp;
+			
+			ret = -EIO;
+			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+				break;
+			
+			tmp = 0;  /* Default return condition */
+			ret = -EIO;
+			if (addr < sizeof(struct pt_regs)) {
+				tmp = get_reg(child, addr >> 2);
+				ret = put_user(tmp, (unsigned long *)data);
+			}
+			break;
+		}
+
+		/* when I and D space are separate, this will have to be fixed. */
+		case PTRACE_POKETEXT: /* write the word at location addr. */
+		case PTRACE_POKEDATA:
+			ret = 0;
+			if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+				break;
+			ret = -EIO;
+			break;
+
+		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+			ret = -EIO;
+			if ((addr & 3) || addr < 0 || addr >= sizeof(struct user))
+				break;
+
+			if (addr < sizeof(struct pt_regs)) {
+				addr >>= 2;
+
+				if (addr == PT_DCCR) {
+				/* don't allow the tracing process to change stuff like
+				 * interrupt enable, kernel/user bit, dma enables etc.
+				 */
+					data &= DCCR_MASK;
+					data |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
+				}
+				if (put_reg(child, addr, data))
+					break;
+				ret = 0;
+			}
+			break;
+
+		case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
+		case PTRACE_CONT: { /* restart after signal. */
+			long tmp;
+
+			ret = -EIO;
+			if ((unsigned long) data > _NSIG)
+				break;
+			if (request == PTRACE_SYSCALL)
+				child->ptrace |= PT_TRACESYS;
+			else
+				child->ptrace &= ~PT_TRACESYS;
+			child->exit_code = data;
+			/* TODO: make sure any pending breakpoint is killed */
+			wake_up_process(child);
+			ret = 0;
+			break;
+		}
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it wants to 
+ * exit.
+ */
+		case PTRACE_KILL: {
+			long tmp;
+
+			ret = 0;
+			if (child->state == TASK_ZOMBIE) /* already dead */
+				break;
+			child->exit_code = SIGKILL;
+			/* TODO: make sure any pending breakpoint is killed */
+			wake_up_process(child);
+			break;
+		}
+
+		case PTRACE_SINGLESTEP: {  /* set the trap flag. */
+			long tmp;
+
+			ret = -EIO;
+			if ((unsigned long) data > _NSIG)
+				break;
+			child->ptrace &= ~PT_TRACESYS;
+
+			/* TODO: set some clever breakpoint mechanism... */
+
+			child->exit_code = data;
+			/* give it a chance to run. */
+			wake_up_process(child);
+			ret = 0;
+			break;
+		}
+
+		case PTRACE_DETACH: { /* detach a process that was attached. */
+			long tmp;
+
+			ret = -EIO;
+			if ((unsigned long) data > _NSIG)
+				break;
+			child->ptrace &= ~(PT_PTRACED | PT_TRACESYS);
+			child->exit_code = data;
+			write_lock_irq(&tasklist_lock);
+			REMOVE_LINKS(child);
+			child->p_pptr = child->p_opptr;
+			SET_LINKS(child);
+			write_unlock_irq(&tasklist_lock);
+			/* TODO: make sure any pending breakpoint is killed */
+			wake_up_process(child);
+			ret = 0;
+			break;
+		}
+
+		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
+		  	int i;
+			unsigned long tmp;
+			for (i = 0; i <= PT_MAX; i++) {
+				tmp = get_reg(child, i);
+				if (put_user(tmp, (unsigned long *) data)) {
+					ret = -EFAULT;
+					break;
+				}
+				data += sizeof(long);
+			}
+			ret = 0;
+			break;
+		}
+
+		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+			int i;
+			unsigned long tmp;
+			for (i = 0; i <= PT_MAX; i++) {
+				if (get_user(tmp, (unsigned long *) data)) {
+					ret = -EFAULT;
+					break;
+				}
+				if (i == PT_DCCR) {
+					tmp &= DCCR_MASK;
+					tmp |= get_reg(child, PT_DCCR) & ~DCCR_MASK;
+				}
+				put_reg(child, i, tmp);
+				data += sizeof(long);
+			}
+			ret = 0;
+			break;
+		}
+
+		default:
+			ret = -EIO;
+			break;
+	}
+out_tsk:
+	free_task_struct(child);
+out:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+	if ((current->ptrace & (PT_PTRACED | PT_TRACESYS)) !=
+	    (PT_PTRACED | PT_TRACESYS))
+		return;
+	/* TODO: make a way to distinguish between a syscall stop and SIGTRAP
+	 * delivery like in the i386 port ? 
+	 */
+	current->exit_code = SIGTRAP;
+	current->state = TASK_STOPPED;
+	notify_parent(current, SIGCHLD);
+	schedule();
+	/*
+	 * this isn't the same as continuing with a signal, but it will do
+	 * for normal use.  strace only continues with a signal if the
+	 * stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/semaphore.c linux/arch/cris/kernel/semaphore.c
--- v2.4.1/linux/arch/cris/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/semaphore.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,238 @@
+/*
+ *  Generic semaphore code. Buyer beware. Do your own
+ * specific changes in <asm/semaphore-helper.h>
+ */
+
+#include <linux/sched.h>
+#include <asm/semaphore-helper.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to sleep, while the "waking" variable is
+ * incremented when the "up()" code goes to wake up waiting
+ * processes.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * waking_non_zero() (from asm/semaphore.h) must execute
+ * atomically.
+ *
+ * When __up() is called, the count was negative before
+ * incrementing it, and we need to wake up somebody.
+ *
+ * This routine adds one to the count of processes that need to
+ * wake up and exit.  ALL waiting processes actually wake up but
+ * only the one that gets to the "waking" field first will gate
+ * through and acquire the semaphore.  The others will go back
+ * to sleep.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+void __up(struct semaphore *sem)
+{
+	wake_one_more(sem);
+	wake_up(&sem->wait);
+}
+
+/*
+ * Perform the "down" function.  Return zero for semaphore acquired,
+ * return negative for signalled out of the function.
+ *
+ * If called from __down, the return is ignored and the wait loop is
+ * not interruptible.  This means that a task waiting on a semaphore
+ * using "down()" cannot be killed until someone does an "up()" on
+ * the semaphore.
+ *
+ * If called from __down_interruptible, the return value gets checked
+ * upon return.  If the return value is negative then the task continues
+ * with the negative value in the return register (it can be tested by
+ * the caller).
+ *
+ * Either form may be used in conjunction with "up()".
+ *
+ */
+
+#define DOWN_VAR				\
+	struct task_struct *tsk = current;	\
+	wait_queue_t wait;			\
+	init_waitqueue_entry(&wait, tsk);
+
+#define DOWN_HEAD(task_state)						\
+									\
+									\
+	tsk->state = (task_state);					\
+	add_wait_queue(&sem->wait, &wait);				\
+									\
+	/*								\
+	 * Ok, we're set up.  sem->count is known to be less than zero	\
+	 * so we must wait.						\
+	 *								\
+	 * We can let go the lock for purposes of waiting.		\
+	 * We re-acquire it after awaking so as to protect		\
+	 * all semaphore operations.					\
+	 *								\
+	 * If "up()" is called before we call waking_non_zero() then	\
+	 * we will catch it right away.  If it is called later then	\
+	 * we will have to go through a wakeup cycle to catch it.	\
+	 *								\
+	 * Multiple waiters contend for the semaphore lock to see	\
+	 * who gets to gate through and who has to wait some more.	\
+	 */								\
+	for (;;) {
+
+#define DOWN_TAIL(task_state)			\
+		tsk->state = (task_state);	\
+	}					\
+	tsk->state = TASK_RUNNING;		\
+	remove_wait_queue(&sem->wait, &wait);
+
+void __down(struct semaphore * sem)
+{
+	DOWN_VAR
+	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
+	if (waking_non_zero(sem))
+		break;
+	schedule();
+	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+	DOWN_VAR
+	DOWN_HEAD(TASK_INTERRUPTIBLE)
+
+	ret = waking_non_zero_interruptible(sem, tsk);
+	if (ret)
+	{
+		if (ret == 1)
+			/* ret != 0 only if we get interrupted -arca */
+			ret = 0;
+		break;
+	}
+	schedule();
+	DOWN_TAIL(TASK_INTERRUPTIBLE)
+	return ret;
+}
+
+int __down_trylock(struct semaphore * sem)
+{
+	return waking_non_zero_trylock(sem);
+}
+
+/*
+ * RW Semaphores
+ */
+void
+__down_read(struct rw_semaphore *sem, int count)
+{
+	DOWN_VAR;
+
+ retry_down:
+	if (count < 0) {
+		/* Wait for the lock to become unbiased.  Readers
+		   are non-exclusive.  */
+		
+		/* This takes care of granting the lock.  */
+		up_read(sem);
+
+		add_wait_queue(&sem->wait, &wait);
+		while (atomic_read(&sem->count) < 0) {
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			if (atomic_read(&sem->count) >= 0)
+				break;
+			schedule();
+		}
+
+		remove_wait_queue(&sem->wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		mb();
+		count = atomic_dec_return(&sem->count);
+		if (count <= 0)
+			goto retry_down;
+	} else {
+		add_wait_queue(&sem->wait, &wait);
+
+		while (1) {
+			if (test_and_clear_bit(0, &sem->granted))
+				break;
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			if ((sem->granted & 1) == 0)
+				schedule();
+		}
+
+		remove_wait_queue(&sem->wait, &wait);
+		tsk->state = TASK_RUNNING;
+	}
+}
+
+void
+__down_write(struct rw_semaphore *sem, int count)
+{
+	DOWN_VAR;
+
+ retry_down:
+	if (count + RW_LOCK_BIAS < 0) {
+		up_write(sem);
+
+		add_wait_queue_exclusive(&sem->wait, &wait);
+	
+		while (atomic_read(&sem->count) < 0) {
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			if (atomic_read(&sem->count) >= RW_LOCK_BIAS)
+				break;
+			schedule();
+		}
+
+		remove_wait_queue(&sem->wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		mb();
+		count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
+		if (count != 0)
+			goto retry_down;
+	} else {
+		/* Put ourselves at the end of the list.  */
+		add_wait_queue_exclusive(&sem->write_bias_wait, &wait);
+
+		while (1) {
+			if (test_and_clear_bit(1, &sem->granted))
+				break;
+			set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+			if ((sem->granted & 2) == 0)
+				schedule();
+		}
+
+		remove_wait_queue(&sem->write_bias_wait, &wait);
+		tsk->state = TASK_RUNNING;
+
+		/* If the lock is currently unbiased, awaken the sleepers.
+		   FIXME: This wakes up the readers early in a bit of a
+		   stampede -> bad!  */
+		if (atomic_read(&sem->count) >= 0)
+			wake_up(&sem->wait);
+	}
+}
+
+void
+__rwsem_wake(struct rw_semaphore *sem, unsigned long readers)
+{
+	if (readers) {
+		if (test_and_set_bit(0, &sem->granted))
+			BUG();
+		wake_up(&sem->wait);
+	} else {
+		if (test_and_set_bit(1, &sem->granted))
+			BUG();
+		wake_up(&sem->write_bias_wait);
+	}
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/setup.c linux/arch/cris/kernel/setup.c
--- v2.4.1/linux/arch/cris/kernel/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/setup.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,264 @@
+/* $Id: setup.c,v 1.8 2001/01/16 16:31:38 bjornw Exp $
+ *
+ *  linux/arch/cris/kernel/setup.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (c) 2000  Axis Communications AB
+ */
+
+/*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+
+#include <asm/segment.h>
+#include <asm/system.h>
+#include <asm/smp.h>
+#include <asm/types.h>
+#include <asm/svinto.h>
+
+/*
+ * Setup options
+ */
+struct drive_info_struct { char dummy[32]; } drive_info;
+struct screen_info screen_info;
+
+unsigned char aux_device_present;
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;		/* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;		/* 1 = prompt for ramdisk, 0 = don't prompt */
+extern int rd_image_start;	/* starting block # of image */
+#endif
+
+extern int root_mountflags;
+extern char _etext, _edata, _end;
+
+#define COMMAND_LINE_SIZE 256
+
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+       char saved_command_line[COMMAND_LINE_SIZE];
+
+extern const unsigned long text_start, edata; /* set by the linker script */
+
+extern unsigned long romfs_start, romfs_length, romfs_in_flash; /* from head.S */
+
+/* This mainly sets up the memory area, and can be really confusing.
+ *
+ * The physical DRAM is virtually mapped into dram_start to dram_end
+ * (usually c0000000 to c0000000 + DRAM size). The physical address is
+ * given by the macro __pa().
+ *
+ * In this DRAM, the kernel code and data is loaded, in the beginning.
+ * It really starts at c00a0000 to make room for some special pages - 
+ * the start address is text_start. The kernel data ends at _end. After
+ * this the ROM filesystem is appended (if there is any).
+ * 
+ * Between this address and dram_end, we have RAM pages usable to the
+ * boot code and the system.
+ *
+ */
+
+void __init setup_arch(char **cmdline_p)
+{
+        unsigned long bootmap_size;
+	unsigned long start_pfn, max_pfn;
+	unsigned long memory_start;
+	extern void console_print_etrax(const char *b);
+
+#if (defined(CONFIG_CHR_DEV_FLASH) || defined(CONFIG_BLK_DEV_FLASH))
+	/* TODO: move this into flash_init I think */
+	flash_probe();
+#endif
+
+ 	/* register an initial console printing routine for printk's */
+
+	init_etrax_debug();
+
+	/* we should really poll for DRAM size! */
+
+	high_memory = &dram_end;
+
+	if(romfs_in_flash || !romfs_length) {
+		/* if we have the romfs in flash, or if there is no rom filesystem,
+		 * our free area starts directly after the BSS 
+		 */
+		memory_start = (unsigned long) &_end;
+	} else {
+		/* otherwise the free area starts after the ROM filesystem */
+		printk("ROM fs in RAM, size %d bytes\n", romfs_length);
+		memory_start = romfs_start + romfs_length;
+	}
+
+	/* process 1's initial memory region is the kernel code/data */
+
+	init_mm.start_code = (unsigned long) &text_start;
+	init_mm.end_code =   (unsigned long) &_etext;
+	init_mm.end_data =   (unsigned long) &_edata;
+	init_mm.brk =        (unsigned long) &_end;
+
+#define PFN_UP(x)       (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+#define PFN_DOWN(x)     ((x) >> PAGE_SHIFT)
+#define PFN_PHYS(x)     ((x) << PAGE_SHIFT)
+
+	/* min_low_pfn points to the start of DRAM, start_pfn points
+	 * to the first DRAM pages after the kernel, and max_low_pfn
+	 * to the end of DRAM.
+	 */
+
+        /*
+         * partially used pages are not usable - thus
+         * we are rounding upwards:
+         */
+
+        start_pfn = PFN_UP(memory_start);  /* usually c0000000 + kernel + romfs */
+	max_pfn =   PFN_DOWN((unsigned long)high_memory); /* usually c0000000 + dram size */
+
+        /*
+         * Initialize the boot-time allocator (start, end)
+	 *
+	 * We give it access to all our DRAM, but we could as well just have
+	 * given it a small slice. No point in doing that though, unless we
+	 * have non-contiguous memory and want the boot-stuff to be in, say,
+	 * the smallest area.
+	 *
+	 * It will put a bitmap of the allocated pages in the beginning
+	 * of the range we give it, but it won't mark the bitmaps pages
+	 * as reserved. We have to do that ourselves below.
+	 *
+	 * We need to use init_bootmem_node instead of init_bootmem
+	 * because our map starts at a quite high address (min_low_pfn).
+         */
+
+	max_low_pfn = max_pfn;
+	min_low_pfn = PAGE_OFFSET >> PAGE_SHIFT;
+
+	bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn,
+					 min_low_pfn, 
+					 max_low_pfn);
+
+	/* And free all memory not belonging to the kernel (addr, size) */
+
+	free_bootmem(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn - start_pfn));
+
+        /*
+         * Reserve the bootmem bitmap itself as well. We do this in two
+         * steps (first step was init_bootmem()) because this catches
+         * the (very unlikely) case of us accidentally initializing the
+         * bootmem allocator with an invalid RAM area.
+	 *
+	 * Arguments are start, size
+         */
+
+        reserve_bootmem(PFN_PHYS(start_pfn), bootmap_size);
+
+	/* paging_init() sets up the MMU and marks all pages as reserved */
+
+	paging_init();
+
+	/* we dont use a command line yet, so just let it be an empty string */
+
+	*cmdline_p = command_line;
+	strcpy(command_line, "root=/dev/rom"); /* use the appended romdisk as root */
+
+	/* give credit for the CRIS port */
+
+	printk("Linux/CRIS port on ETRAX 100LX (c) 2000 Axis Communications AB\n");
+
+}
+
+#ifdef CONFIG_PROC_FS
+#define HAS_FPU		0x0001
+#define HAS_MMU		0x0002
+#define HAS_ETHERNET100	0x0004
+#define HAS_TOKENRING	0x0008
+#define HAS_SCSI	0x0010
+#define HAS_ATA		0x0020
+#define HAS_USB		0x0040
+#define HAS_IRQ_BUG	0x0080
+
+static struct cpu_info {
+	char *model;
+	unsigned short cache;
+	unsigned short flags;
+} cpu_info[] = {
+	{ "ETRAX 1",   0, 0 },
+	{ "ETRAX 2",   0, 0 },	/* Don't say it HAS_TOKENRING - there are
+				   lethal bugs in that chip that
+				   prevents T-R from ever working.
+				   Never go there, and never lead anyone
+				   into believing it can work.  BTW:
+				   Anyone working on a T-R network
+				   driver? :-) :-) :-) :-/ */
+	{ "ETRAX 3",   0, HAS_TOKENRING },
+	{ "ETRAX 4",   0, HAS_TOKENRING | HAS_SCSI },
+	{ "Unknown",   0, 0 },
+	{ "Unknown",   0, 0 },
+	{ "Unknown",   0, 0 },
+	{ "Simulator",     8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
+	{ "ETRAX 100",     8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_IRQ_BUG },
+	{ "ETRAX 100",     8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA },
+	{ "ETRAX 100LX",  8, HAS_ETHERNET100 | HAS_SCSI | HAS_ATA | HAS_USB | HAS_MMU },
+	{ "Unknown",   0, 0 },
+};
+
+/*
+ * BUFFER is PAGE_SIZE bytes long.
+ */
+int get_cpuinfo(char *buffer)
+{
+	int revision;
+#ifndef CONFIG_SVINTO_SIM
+	unsigned char tmp;
+
+	__asm__ volatile ("move vr,%0" : "=rm" (tmp));
+	revision = tmp;
+#else
+        /* Fake a revision for the simulator */
+	revision = 7;
+#endif
+
+	return sprintf(buffer,
+		       "cpu\t\t: CRIS\n"
+		       "cpu revision\t: %d\n"
+		       "cpu model\t: %s\n"
+		       "cache size\t: %d kB\n"
+		       "fpu\t\t: %s\n"
+		       "mmu\t\t: %s\n"
+		       "ethernet\t: %s Mbps\n"
+		       "token ring\t: %s\n"
+		       "scsi\t\t: %s\n"
+		       "ata\t\t: %s\n"
+		       "usb\t\t: %s\n"
+		       "bogomips\t: %lu.%02lu\n",
+
+		       revision,
+		       cpu_info[revision].model,
+		       cpu_info[revision].cache,
+		       cpu_info[revision].flags & HAS_FPU ? "yes" : "no",
+		       cpu_info[revision].flags & HAS_MMU ? "yes" : "no",
+		       cpu_info[revision].flags & HAS_ETHERNET100 ? "10/100" : "10",
+		       cpu_info[revision].flags & HAS_TOKENRING ? "4/16 Mbps" : "no",
+		       cpu_info[revision].flags & HAS_SCSI ? "yes" : "no",
+		       cpu_info[revision].flags & HAS_ATA ? "yes" : "no",
+		       cpu_info[revision].flags & HAS_USB ? "yes" : "no",
+		       (loops_per_jiffy * HZ + 500) / 100000,
+		       ((loops_per_jiffy * HZ + 500) / 1000) % 100);
+}
+#endif /* CONFIG_PROC_FS */
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/shadows.c linux/arch/cris/kernel/shadows.c
--- v2.4.1/linux/arch/cris/kernel/shadows.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/shadows.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,20 @@
+/* $Id: shadows.c,v 1.1 2000/07/10 16:25:21 bjornw Exp $
+ * 
+ * Various Etrax shadow registers. Defines for these are in include/asm-etrax100/io.h
+ */
+
+#include <linux/config.h>
+
+unsigned long genconfig_shadow = 42;
+unsigned long port_g_data_shadow = 42;
+unsigned char port_pa_dir_shadow = 42;
+unsigned char port_pa_data_shadow = 42;
+unsigned char port_pb_i2c_shadow = 42;
+unsigned char port_pb_config_shadow = 42;
+unsigned char port_pb_dir_shadow = 42;
+unsigned char port_pb_data_shadow = 42;
+unsigned long r_timer_ctrl_shadow = 42;
+
+#ifdef CONFIG_ETRAX_90000000_LEDS
+unsigned long port_90000000_shadow = 42;
+#endif
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/signal.c linux/arch/cris/kernel/signal.c
--- v2.4.1/linux/arch/cris/kernel/signal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/signal.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,667 @@
+/*
+ *  linux/arch/cris/kernel/signal.c
+ *
+ *  Based on arch/i386/kernel/signal.c by
+ *     Copyright (C) 1991, 1992  Linus Torvalds
+ *     1997-11-28  Modified for POSIX.1b signals by Richard Henderson *
+ *
+ *  Ideas also taken from arch/arm.
+ *
+ *  Copyright (C) 2000 Axis Communications AB
+ *
+ *  Authors:  Bjorn Wesen (bjornw@axis.com)
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+
+#include <asm/processor.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */
+/* manipulate regs so that upon return, it will be re-executed */
+
+#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2;
+
+int sys_wait4(pid_t pid, unsigned long *stat_addr,
+			 int options, unsigned long *ru);
+
+int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs);
+
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+		return -EFAULT;
+	if (from->si_code < 0)
+		return __copy_to_user(to, from, sizeof(siginfo_t));
+	else {
+		int err;
+
+		/* If you change siginfo_t structure, please be sure
+		   this code is fixed accordingly.
+		   It should never copy any pad contained in the structure
+		   to avoid security leaks, but must copy the generic
+		   3 ints plus the relevant union member.  */
+		err = __put_user(from->si_signo, &to->si_signo);
+		err |= __put_user(from->si_errno, &to->si_errno);
+		err |= __put_user((short)from->si_code, &to->si_code);
+		/* First 32bits of unions are always present.  */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		switch (from->si_code >> 16) {
+		case __SI_FAULT >> 16:
+			break;
+		case __SI_CHLD >> 16:
+			err |= __put_user(from->si_utime, &to->si_utime);
+			err |= __put_user(from->si_stime, &to->si_stime);
+			err |= __put_user(from->si_status, &to->si_status);
+		default:
+			err |= __put_user(from->si_uid, &to->si_uid);
+			break;
+		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		}
+		return err;
+	}
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+int
+sys_sigsuspend(old_sigset_t mask)
+{
+	struct pt_regs * regs = (struct pt_regs *)current_regs();
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	regs->r10 = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(0, &saveset, regs))
+			return -EINTR;
+	}
+}
+
+int
+sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize)
+{
+	struct pt_regs * regs = (struct pt_regs *)current_regs();
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+
+	regs->r10 = -EINTR;
+	while (1) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		if (do_signal(0, &saveset, regs))
+			return -EINTR;
+	}
+}
+
+int 
+sys_sigaction(int sig, const struct old_sigaction *act,
+	      struct old_sigaction *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+{
+	return do_sigaltstack(uss, uoss, rdusp());
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ */
+
+struct sigframe {
+	struct sigcontext sc;
+	unsigned long extramask[_NSIG_WORDS-1];
+	unsigned char retcode[8];  /* trampoline code */
+};
+
+struct rt_sigframe {
+	struct siginfo *pinfo;
+	void *puc;
+	struct siginfo info;
+	struct ucontext uc;
+	unsigned char retcode[8];  /* trampoline code */
+};
+
+
+static int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
+{
+	unsigned int err = 0;
+	unsigned long old_usp;
+
+	/* restore the regs from &sc->regs (same as sc, since regs is first)
+	 * (sc is already checked for VERIFY_READ since the sigframe was
+	 *  checked in sys_sigreturn previously)
+	 */
+
+	if (__copy_from_user(regs, sc, sizeof(struct pt_regs)))
+                goto badframe;
+
+	/* make sure the U-flag is set so user-mode cannot fool us */
+
+	regs->dccr |= 1 << 8;
+
+	/* restore the old USP as it was before we stacked the sc etc.
+	 * (we cannot just pop the sigcontext since we aligned the sp and
+	 *  stuff after pushing it)
+	 */
+
+	err |= __get_user(old_usp, &sc->usp);
+
+	wrusp(old_usp);
+
+	/* TODO: the other ports use regs->orig_XX to disable syscall checks
+	 * after this completes, but we don't use that mechanism. maybe we can
+	 * use it now ? 
+	 */
+
+	return err;
+
+badframe:
+	return 1;
+}
+
+asmlinkage int sys_sigreturn(void)
+{
+	struct pt_regs *regs = (struct pt_regs *)current_regs();
+	struct sigframe *frame = (struct sigframe *)rdusp();
+	sigset_t set;
+
+        /*
+         * Since we stacked the signal on a dword boundary,
+         * then frame should be dword aligned here.  If it's
+         * not, then the user is trying to mess with us.
+         */
+        if (((long)frame) & 3)
+                goto badframe;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.oldmask)
+	    || (_NSIG_WORDS > 1
+		&& __copy_from_user(&set.sig[1], &frame->extramask,
+				    sizeof(frame->extramask))))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	
+	if (restore_sigcontext(regs, &frame->sc))
+		goto badframe;
+
+	/* TODO: SIGTRAP when single-stepping as in arm ? */
+
+	return regs->r10;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+asmlinkage int sys_rt_sigreturn(void)
+{
+	struct pt_regs *regs = (struct pt_regs *)current_regs();
+	struct rt_sigframe *frame = (struct rt_sigframe *)rdusp();
+	sigset_t set;
+	stack_t st;
+
+        /*
+         * Since we stacked the signal on a dword boundary,
+         * then frame should be dword aligned here.  If it's
+         * not, then the user is trying to mess with us.
+         */
+        if (((long)frame) & 3)
+                goto badframe;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	
+	if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
+		goto badframe;
+
+	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, rdusp());
+
+	return regs->r10;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+/*
+ * Set up a signal frame.
+ */
+
+static int
+setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, unsigned long mask)
+{
+	int err = 0;
+	unsigned long usp = rdusp();
+
+	/* copy the regs. they are first in sc so we can use sc directly */
+
+	err |= __copy_to_user(sc, regs, sizeof(struct pt_regs));
+
+	/* then some other stuff */
+
+	err |= __put_user(mask, &sc->oldmask);
+
+	err |= __put_user(usp, &sc->usp);
+
+	return err;
+}
+
+/* figure out where we want to put the new signal frame - usually on the stack */
+
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+{
+	unsigned long sp = rdusp();
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (! on_sig_stack(sp))
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	/* make sure the frame is dword-aligned */
+
+	sp &= ~3;
+
+	return (void *)(sp - frame_size);
+}
+
+/* grab and setup a signal frame.
+ * 
+ * basically we stack a lot of state info, and arrange for the
+ * user-mode program to return to the kernel using either a
+ * trampoline which performs the syscall sigreturn, or a provided
+ * user-mode trampoline.
+ */
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs)
+{
+	struct sigframe *frame;
+	unsigned long return_ip;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
+	if (err)
+		goto give_sigsegv;
+
+	if (_NSIG_WORDS > 1) {
+		err |= __copy_to_user(frame->extramask, &set->sig[1],
+				      sizeof(frame->extramask));
+	}
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		return_ip = (unsigned long)ka->sa.sa_restorer;
+	} else {
+		/* trampoline - the desired return ip is the retcode itself */
+		return_ip = (unsigned long)&frame->retcode;
+		/* This is movu.w __NR_sigreturn, r1; break 13; */
+		/* TODO: check byteorder */
+		err |= __put_user(0x1c5f,         (short *)(frame->retcode+0));
+		err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
+		err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
+	}
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up registers for signal handler */
+
+	regs->irp = (unsigned long) ka->sa.sa_handler;  /* what we enter NOW   */
+	regs->srp = return_ip;                          /* what we enter LATER */
+
+	/* actually move the usp to reflect the stacked frame */
+
+	wrusp((unsigned long)frame);
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs * regs)
+{
+	struct rt_sigframe *frame;
+	unsigned long return_ip;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
+		goto give_sigsegv;
+
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+	if (err)
+		goto give_sigsegv;
+
+	/* Clear all the bits of the ucontext we don't use.  */
+        err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
+
+	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
+
+	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+		return_ip = (unsigned long)ka->sa.sa_restorer;
+	} else {
+		/* trampoline - the desired return ip is the retcode itself */
+		return_ip = (unsigned long)&frame->retcode;
+		/* This is movu.w __NR_sigreturn, r1; break 13; */
+		/* TODO: check byteorder */
+		err |= __put_user(0x1c5f,         (short *)(frame->retcode+0));
+		err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
+		err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
+	}
+
+	if (err)
+		goto give_sigsegv;
+
+	/* TODO what is the current->exec_domain stuff and invmap ? */
+
+	/* Set up registers for signal handler */
+
+	regs->irp = (unsigned long) ka->sa.sa_handler;  /* what we enter NOW   */
+	regs->srp = return_ip;                          /* what we enter LATER */
+
+	/* actually move the usp to reflect the stacked frame */
+
+	wrusp((unsigned long)frame);
+
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */	
+
+static inline void
+handle_signal(int canrestart, unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+	/* Are we from a system call? */
+	if (canrestart) {
+		/* If so, check system call restarting.. */
+		switch (regs->r10) {
+			case -ERESTARTNOHAND:
+				/* ERESTARTNOHAND means that the syscall should only be
+				   restarted if there was no handler for the signal, and since
+				   we only get here if there is a handler, we dont restart */
+				regs->r10 = -EINTR;
+				break;
+
+			case -ERESTARTSYS:
+				/* ERESTARTSYS means to restart the syscall if there is no
+				   handler or the handler was registered with SA_RESTART */
+				if (!(ka->sa.sa_flags & SA_RESTART)) {
+					regs->r10 = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				/* ERESTARTNOINTR means that the syscall should be called again
+				   after the signal handler returns. */
+				RESTART_CRIS_SYS(regs);
+		}
+	}
+
+	/* Set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		setup_frame(sig, ka, oldset, regs);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sigmask_lock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigaddset(&current->blocked,sig);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
+{
+	siginfo_t info;
+	struct k_sigaction *ka;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return 1;
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	for (;;) {
+		unsigned long signr;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		if (!signr)
+			break;
+
+		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+			/* Let the debugger run.  */
+			current->exit_code = signr;
+			current->state = TASK_STOPPED;
+			notify_parent(current, SIGCHLD);
+			schedule();
+
+			/* We're back.  Did the debugger cancel the sig?  */
+			if (!(signr = current->exit_code))
+				continue;
+			current->exit_code = 0;
+
+			/* The debugger continued.  Ignore SIGSTOP.  */
+			if (signr == SIGSTOP)
+				continue;
+
+			/* Update the siginfo structure.  Is this good?  */
+			if (signr != info.si_signo) {
+				info.si_signo = signr;
+				info.si_errno = 0;
+				info.si_code = SI_USER;
+				info.si_pid = current->p_pptr->pid;
+				info.si_uid = current->p_pptr->uid;
+			}
+
+			/* If the (new) signal is now blocked, requeue it.  */
+			if (sigismember(&current->blocked, signr)) {
+				send_sig_info(signr, &info, current);
+				continue;
+			}
+		}
+
+		ka = &current->sig->action[signr-1];
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
+				continue;
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+				/* nothing */;
+			continue;
+		}
+
+		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr;
+
+			/* Init gets no signals it doesn't want.  */
+			if (current->pid == 1)
+				continue;
+
+			switch (signr) {
+			case SIGCONT: case SIGCHLD: case SIGWINCH:
+				continue;
+
+			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+				/* FALLTHRU */
+
+			case SIGSTOP:
+				current->state = TASK_STOPPED;
+				current->exit_code = signr;
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+					notify_parent(current, SIGCHLD);
+				schedule();
+				continue;
+
+			case SIGQUIT: case SIGILL: case SIGTRAP:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
+			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
+				if (do_coredump(signr, regs))
+					exit_code |= 0x80;
+				/* FALLTHRU */
+
+			default:
+				lock_kernel();
+				sigaddset(&current->pending.signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
+				/* NOTREACHED */
+			}
+		}
+
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(canrestart, signr, ka, &info, oldset, regs);
+		return 1;
+	}
+
+	/* Did we come from a system call? */
+	if (canrestart) {
+		/* Restart the system call - no handlers present */
+		if (regs->r10 == -ERESTARTNOHAND ||
+		    regs->r10 == -ERESTARTSYS ||
+		    regs->r10 == -ERESTARTNOINTR) {
+			RESTART_CRIS_SYS(regs);
+		}
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/sys_cris.c linux/arch/cris/kernel/sys_cris.c
--- v2.4.1/linux/arch/cris/kernel/sys_cris.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/sys_cris.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,201 @@
+/* $Id: sys_cris.c,v 1.3 2000/08/02 13:59:02 bjornw Exp $
+ *
+ * linux/arch/cris/kernel/sys_etrax.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on some platforms.
+ * Since we don't have to do any backwards compatibility, our
+ * versions are done in the most "normal" way possible.
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+#include <asm/segment.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way Unix traditionally does this, though.
+ */
+asmlinkage int sys_pipe(unsigned long * fildes)
+{
+        int fd[2];
+        int error;
+
+        lock_kernel();
+        error = do_pipe(fd);
+        unlock_kernel();
+        if (!error) {
+                if (copy_to_user(fildes, fd, 2*sizeof(int)))
+                        error = -EFAULT;
+        }
+        return error;
+}
+
+/* sys_mmap used to take a ptr to a buffer instead containing the args
+ * but we support syscalls with 6 arguments now 
+ */
+
+asmlinkage unsigned long sys_mmap(unsigned long addr, size_t len,
+				  unsigned long prot, unsigned long flags,
+                                  unsigned long fd, off_t offset)
+{
+	struct file * file = NULL;
+        int ret = -EBADF;
+	
+        lock_kernel();
+        if (!(flags & MAP_ANONYMOUS)) {
+                if (!(file = fget(fd)))
+                        goto out;
+        }
+        
+        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+        down(&current->mm->mmap_sem);
+        ret = do_mmap(file, addr, len, prot, flags, offset);
+        up(&current->mm->mmap_sem);
+        if (file)
+                fput(file);
+ out:
+        unlock_kernel();
+        return ret;
+}
+
+/* common code for old and new mmaps */
+static inline long
+do_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+        unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+        int error = -EBADF;
+        struct file * file = NULL;
+
+        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+        if (!(flags & MAP_ANONYMOUS)) {
+                file = fget(fd);
+                if (!file)
+                        goto out;
+        }
+
+        down(&current->mm->mmap_sem);
+        error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+        up(&current->mm->mmap_sem);
+
+        if (file)
+                fput(file);
+out:
+        return error;
+}
+
+asmlinkage unsigned long old_mmap(unsigned long addr, size_t len, int prot,
+                                  int flags, int fd, off_t offset)
+{
+        return do_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
+}
+
+asmlinkage long
+sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot,
+          unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+        return do_mmap2(addr, len, prot, flags, fd, pgoff);
+}
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly. (same as arch/i386)
+ */
+
+asmlinkage int sys_ipc (uint call, int first, int second,
+			int third, void *ptr, long fifth)
+{
+	int version, ret;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	switch (call) {
+	case SEMOP:
+		return sys_semop (first, (struct sembuf *)ptr, second);
+	case SEMGET:
+		return sys_semget (first, second, third);
+	case SEMCTL: {
+		union semun fourth;
+		if (!ptr)
+			return -EINVAL;
+		if (get_user(fourth.__pad, (void **) ptr))
+			return -EFAULT;
+		return sys_semctl (first, second, third, fourth);
+	}
+
+	case MSGSND:
+		return sys_msgsnd (first, (struct msgbuf *) ptr, 
+				   second, third);
+	case MSGRCV:
+		switch (version) {
+		case 0: {
+			struct ipc_kludge tmp;
+			if (!ptr)
+				return -EINVAL;
+			
+			if (copy_from_user(&tmp,
+					   (struct ipc_kludge *) ptr, 
+					   sizeof (tmp)))
+				return -EFAULT;
+			return sys_msgrcv (first, tmp.msgp, second,
+					   tmp.msgtyp, third);
+		}
+		default:
+			return sys_msgrcv (first,
+					   (struct msgbuf *) ptr,
+					   second, fifth, third);
+		}
+	case MSGGET:
+		return sys_msgget ((key_t) first, second);
+	case MSGCTL:
+		return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+
+	case SHMAT:
+		switch (version) {
+		default: {
+			ulong raddr;
+			ret = sys_shmat (first, (char *) ptr, second, &raddr);
+			if (ret)
+				return ret;
+			return put_user (raddr, (ulong *) third);
+		}
+		case 1:	/* iBCS2 emulator entry point */
+			if (!segment_eq(get_fs(), get_ds()))
+				return -EINVAL;
+			return sys_shmat (first, (char *) ptr, second, (ulong *) third);
+		}
+	case SHMDT: 
+		return sys_shmdt ((char *)ptr);
+	case SHMGET:
+		return sys_shmget (first, second, third);
+	case SHMCTL:
+		return sys_shmctl (first, second,
+				   (struct shmid_ds *) ptr);
+	default:
+		return -EINVAL;
+	}
+}
+
+/* apparently this is legacy - if we don't need this in Linux/CRIS we can remove it. */
+
+asmlinkage int sys_pause(void)
+{
+        current->state = TASK_INTERRUPTIBLE;
+        schedule();
+        return -ERESTARTNOHAND;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/time.c linux/arch/cris/kernel/time.c
--- v2.4.1/linux/arch/cris/kernel/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/time.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,453 @@
+/* $Id: time.c,v 1.4 2000/10/17 14:44:58 bjornw Exp $
+ *
+ *  linux/arch/cris/kernel/time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *  Copyright (C) 1999, 2000 Axis Communications AB
+ *
+ * 1994-07-02    Alan Modra
+ *	fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
+ * 1995-03-26    Markus Kuhn
+ *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
+ *      precision CMOS clock update
+ * 1996-05-03    Ingo Molnar
+ *      fixed time warps in do_[slow|fast]_gettimeoffset()
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
+ *
+ * Linux/CRIS specific code:
+ *
+ * Authors:    Bjorn Wesen
+ *
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/delay.h>
+#include <asm/rtc.h>
+
+#include <linux/timex.h>
+#include <linux/config.h>
+
+#include <asm/svinto.h>
+
+static int have_rtc;  /* used to remember if we have an RTC or not */
+
+/* define this if you need to use print_timestamp */
+/* it will make jiffies at 96 hz instead of 100 hz though */
+#undef USE_CASCADE_TIMERS
+
+extern int setup_etrax_irq(int, struct irqaction *);
+
+#define TICK_SIZE tick
+
+static unsigned long do_slow_gettimeoffset(void)
+{
+	unsigned long count;
+
+	static unsigned long count_p = LATCH;    /* for the first call after boot */
+	static unsigned long jiffies_p = 0;
+
+	/*
+	 * cache volatile jiffies temporarily; we have IRQs turned off. 
+	 */
+	unsigned long jiffies_t;
+
+	/* The timer interrupt comes from Etrax timer 0. In order to get
+	 * better precision, we check the current value. It might have
+	 * underflowed already though.
+	 */
+
+#ifndef CONFIG_SVINTO_SIM
+	/* Not available in the xsim simulator. */
+	count = *R_TIMER0_DATA;
+#else
+	count = 0;
+#endif
+
+ 	jiffies_t = jiffies;
+
+	/*
+	 * avoiding timer inconsistencies (they are rare, but they happen)...
+	 * there are three kinds of problems that must be avoided here:
+	 *  1. the timer counter underflows
+	 *  2. hardware problem with the timer, not giving us continuous time,
+	 *     the counter does small "jumps" upwards on some Pentium systems,
+	 *     thus causes time warps
+	 *  3. we are after the timer interrupt, but the bottom half handler
+	 *     hasn't executed yet.
+	 */
+	if( jiffies_t == jiffies_p ) {
+		if( count > count_p ) {
+		}
+	} else
+		jiffies_p = jiffies_t;
+
+        count_p = count;
+
+	count = ((LATCH-1) - count) * TICK_SIZE;
+	count = (count + LATCH/2) / LATCH;
+
+	return count;
+}
+
+static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
+
+/*
+ * This version of gettimeofday has near microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+
+	save_flags(flags);
+	cli();
+	*tv = xtime;
+	tv->tv_usec += do_gettimeoffset();
+	if (tv->tv_usec >= 1000000) {
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+	restore_flags(flags);
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+	cli();
+	/* This is revolting. We need to set the xtime.tv_usec
+	 * correctly. However, the value in this location is
+	 * is value at the last tick.
+	 * Discover what correction gettimeofday
+	 * would have done, and then undo it!
+	 */
+	tv->tv_usec -= do_gettimeoffset();
+
+	if (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_state = TIME_ERROR;	/* p. 24, (a) */
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+	sti();
+}
+
+
+/*
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you'll only notice that after reboot!
+ */
+
+static int set_rtc_mmss(unsigned long nowtime)
+{
+	int retval = 0;
+	int real_seconds, real_minutes, cmos_minutes;
+	unsigned char save_control, save_freq_select;
+
+	printk("set_rtc_mmss(%d)\n", nowtime);
+
+	if(!have_rtc)
+		return 0;
+
+	cmos_minutes = CMOS_READ(RTC_MINUTES);
+	BCD_TO_BIN(cmos_minutes);
+
+	/*
+	 * since we're only adjusting minutes and seconds,
+	 * don't interfere with hour overflow. This avoids
+	 * messing with unknown time zones but requires your
+	 * RTC not to be off by more than 15 minutes
+	 */
+	real_seconds = nowtime % 60;
+	real_minutes = nowtime / 60;
+	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)
+		real_minutes += 30;		/* correct for half hour time zone */
+	real_minutes %= 60;
+
+	if (abs(real_minutes - cmos_minutes) < 30) {
+		BIN_TO_BCD(real_seconds);
+		BIN_TO_BCD(real_minutes);
+		CMOS_WRITE(real_seconds,RTC_SECONDS);
+		CMOS_WRITE(real_minutes,RTC_MINUTES);
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+		retval = -1;
+	}
+
+	return retval;
+}
+
+/* Except from the Etrax100 HSDD about the built-in watchdog:
+ *
+ * 3.10.4 Watchdog timer
+
+ * When the watchdog timer is started, it generates an NMI if the watchdog
+ * isn't restarted or stopped within 0.1 s. If it still isn't restarted or
+ * stopped after an additional 3.3 ms, the watchdog resets the chip.
+ * The watchdog timer is stopped after reset. The watchdog timer is controlled
+ * by the R_WATCHDOG register. The R_WATCHDOG register contains an enable bit
+ * and a 3-bit key value. The effect of writing to the R_WATCHDOG register is
+ * described in the table below:
+ * 
+ *   Watchdog    Value written:
+ *   state:      To enable:  To key:      Operation:
+ *   --------    ----------  -------      ----------
+ *   stopped         0         X          No effect.
+ *   stopped         1       key_val      Start watchdog with key = key_val.
+ *   started         0       ~key         Stop watchdog
+ *   started         1       ~key         Restart watchdog with key = ~key.
+ *   started         X       new_key_val  Change key to new_key_val.
+ * 
+ * Note: '~' is the bitwise NOT operator.
+ * 
+ */
+
+/* right now, starting the watchdog is the same as resetting it */
+#define start_watchdog reset_watchdog
+
+static int watchdog_key = 0;  /* arbitrary number */
+
+/* number of pages to consider "out of memory". it is normal that the memory
+ * is used though, so put this really low.
+ */
+
+#define WATCHDOG_MIN_FREE_PAGES 8
+
+extern int nr_free_pages;
+
+static inline void
+reset_watchdog(void)
+{
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+	/* only keep watchdog happy as long as we have memory left! */
+	if(nr_free_pages > WATCHDOG_MIN_FREE_PAGES) {
+		/* reset the watchdog with the inverse of the old key */
+		watchdog_key ^= 0x7; /* invert key, which is 3 bits */
+		*R_WATCHDOG = IO_FIELD(R_WATCHDOG, key, watchdog_key) |
+			IO_STATE(R_WATCHDOG, enable, start);
+	}
+#endif
+}
+
+/* last time the cmos clock got updated */
+static long last_rtc_update = 0;
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+
+//static unsigned short myjiff; /* used by our debug routine print_timestamp */
+
+static inline void
+timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* acknowledge the timer irq */
+
+#ifdef USE_CASCADE_TIMERS
+	*R_TIMER_CTRL =
+		IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
+		IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
+		IO_STATE( R_TIMER_CTRL, i1, clr) |
+		IO_STATE( R_TIMER_CTRL, tm1, run) |
+		IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
+		IO_STATE( R_TIMER_CTRL, i0, clr) |
+		IO_STATE( R_TIMER_CTRL, tm0, run) |
+		IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
+#else
+	*R_TIMER_CTRL = r_timer_ctrl_shadow | 
+		IO_STATE(R_TIMER_CTRL, i0, clr);
+#endif
+
+	/* reset watchdog otherwise it resets us! */
+
+	reset_watchdog();
+	
+	/* call the real timer interrupt handler */
+
+	do_timer(regs);
+	
+	/*
+	 * If we have an externally synchronized Linux clock, then update
+	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
+	 * called as close as possible to 500 ms before the new second starts.
+	 */
+
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec > 500000 - (tick >> 1) &&
+	    xtime.tv_usec < 500000 + (tick >> 1))
+		if (set_rtc_mmss(xtime.tv_sec) == 0)
+			last_rtc_update = xtime.tv_sec;
+		else
+			last_rtc_update = xtime.tv_sec - 600;
+	
+}
+
+#if 0
+/* some old debug code for testing the microsecond timing of packets */
+static unsigned int lastjiff;
+
+void print_timestamp(const char *s)
+{
+	unsigned long flags;
+	unsigned int newjiff;
+	save_flags(flags);
+	cli();
+	newjiff = (myjiff << 16) | (unsigned short)(-*R_TIMER01_DATA); 
+	printk("%s: %x (%x)\n", s, newjiff, newjiff - lastjiff);
+	lastjiff = newjiff;
+	restore_flags(flags);
+}
+#endif
+
+/* grab the time from the RTC chip */
+
+unsigned long
+get_cmos_time(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+	int i;
+
+	sec = CMOS_READ(RTC_SECONDS);
+	min = CMOS_READ(RTC_MINUTES);
+	hour = CMOS_READ(RTC_HOURS);
+	day = CMOS_READ(RTC_DAY_OF_MONTH);
+	mon = CMOS_READ(RTC_MONTH);
+	year = CMOS_READ(RTC_YEAR);
+
+	printk("rtc: sec 0x%x min 0x%x hour 0x%x day 0x%x mon 0x%x year 0x%x\n", 
+	       sec, min, hour, day, mon, year);
+
+	BCD_TO_BIN(sec);
+	BCD_TO_BIN(min);
+	BCD_TO_BIN(hour);
+	BCD_TO_BIN(day);
+	BCD_TO_BIN(mon);
+	BCD_TO_BIN(year);
+
+	if ((year += 1900) < 1970)
+		year += 100;
+
+	return mktime(year, mon, day, hour, min, sec);
+}
+
+/* update xtime from the CMOS settings. used when /dev/rtc gets a SET_TIME.
+ * TODO: this doesn't reset the fancy NTP phase stuff as do_settimeofday does.
+ */
+
+void
+update_xtime_from_cmos(void)
+{
+	if(have_rtc) {
+		xtime.tv_sec = get_cmos_time();
+		xtime.tv_usec = 0;
+	}
+}
+
+/* timer is SA_SHIRQ so drivers can add stuff to the timer irq chain
+ * it needs to be SA_INTERRUPT to make the jiffies update work properly
+ */
+
+static struct irqaction irq2  = { timer_interrupt, SA_SHIRQ | SA_INTERRUPT,
+				  0, "timer", NULL, NULL};
+
+void __init
+time_init(void)
+{	
+	/* probe for the RTC and read it if it exists */
+
+	if(RTC_INIT() < 0) {
+		/* no RTC, start at 1980 */
+		xtime.tv_sec = 0;
+		xtime.tv_usec = 0;
+		have_rtc = 0;
+	} else {		
+		/* get the current time */
+		have_rtc = 1;
+		update_xtime_from_cmos();
+	}
+
+	/* Setup the etrax timers
+	 * Base frequency is 19200 hz, divider 192 -> 100 hz as Linux wants
+	 * In normal mode, we use timer0, so timer1 is free. In cascade
+	 * mode (which we sometimes use for debugging) both timers are used.
+	 * Remember that linux/timex.h contains #defines that rely on the
+	 * timer settings below (hz and divide factor) !!!
+	 */
+	
+#ifdef USE_CASCADE_TIMERS
+	*R_TIMER_CTRL =
+		IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
+		IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
+		IO_STATE( R_TIMER_CTRL, i1, nop) |
+		IO_STATE( R_TIMER_CTRL, tm1, stop_ld) |
+		IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
+		IO_STATE( R_TIMER_CTRL, i0, nop) |
+		IO_STATE( R_TIMER_CTRL, tm0, stop_ld) |
+		IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
+	
+	*R_TIMER_CTRL = r_timer_ctrl_shadow = 
+		IO_FIELD( R_TIMER_CTRL, timerdiv1, 0) |
+		IO_FIELD( R_TIMER_CTRL, timerdiv0, 0) |
+		IO_STATE( R_TIMER_CTRL, i1, nop) |
+		IO_STATE( R_TIMER_CTRL, tm1, run) |
+		IO_STATE( R_TIMER_CTRL, clksel1, cascade0) |
+		IO_STATE( R_TIMER_CTRL, i0, nop) |
+		IO_STATE( R_TIMER_CTRL, tm0, run) |
+		IO_STATE( R_TIMER_CTRL, clksel0, c6250kHz);
+#else
+	*R_TIMER_CTRL = 
+		IO_FIELD(R_TIMER_CTRL, timerdiv1, 192)      | 
+		IO_FIELD(R_TIMER_CTRL, timerdiv0, 192)      |
+		IO_STATE(R_TIMER_CTRL, i1,        nop)      | 
+		IO_STATE(R_TIMER_CTRL, tm1,       stop_ld)  |
+		IO_STATE(R_TIMER_CTRL, clksel1,   c19k2Hz)  |
+		IO_STATE(R_TIMER_CTRL, i0,        nop)      |
+		IO_STATE(R_TIMER_CTRL, tm0,       stop_ld)  |
+		IO_STATE(R_TIMER_CTRL, clksel0,   c19k2Hz);
+	
+	*R_TIMER_CTRL = r_timer_ctrl_shadow =
+		IO_FIELD(R_TIMER_CTRL, timerdiv1, 192)      | 
+		IO_FIELD(R_TIMER_CTRL, timerdiv0, 192)      |
+		IO_STATE(R_TIMER_CTRL, i1,        nop)      |
+		IO_STATE(R_TIMER_CTRL, tm1,       run)      |
+		IO_STATE(R_TIMER_CTRL, clksel1,   c19k2Hz)  |
+		IO_STATE(R_TIMER_CTRL, i0,        nop)      |
+		IO_STATE(R_TIMER_CTRL, tm0,       run)      |
+		IO_STATE(R_TIMER_CTRL, clksel0,   c19k2Hz);
+#endif
+	
+	*R_IRQ_MASK0_SET =
+		IO_STATE(R_IRQ_MASK0_SET, timer0, set); /* unmask the timer irq */
+	
+	/* now actually register the timer irq handler that calls timer_interrupt() */
+	
+	setup_etrax_irq(2, &irq2); /* irq 2 is the timer0 irq in etrax */
+
+	/* enable watchdog if we should use one */
+
+#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
+	printk("Enabling watchdog...\n");
+	start_watchdog();
+#endif
+
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/kernel/traps.c linux/arch/cris/kernel/traps.c
--- v2.4.1/linux/arch/cris/kernel/traps.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/kernel/traps.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,167 @@
+/* $Id: traps.c,v 1.3 2000/10/04 16:50:06 bjornw Exp $
+ *
+ *  linux/arch/cris/traps.c
+ *
+ *  Etrax100 does not have any hardware traps, only IRQ's, which we setup
+ *  in irq.c instead. Here we just define the die_if_kernel Oops'er.
+ *
+ *  Copyright (C) 2000 Axis Communications AB
+ *
+ *  Authors:   Bjorn Wesen
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/io.h>
+#include <asm/pgtable.h>
+
+int kstack_depth_to_print = 24;
+
+/*
+ * These constants are for searching for possible module text
+ * segments. MODULE_RANGE is a guess of how much space is likely
+ * to be vmalloced.
+ */
+
+#define MODULE_RANGE (8*1024*1024)
+
+void show_stack(unsigned long *sp)
+{
+        unsigned long *stack, addr, module_start, module_end;
+        int i;
+	extern char _stext, _etext;
+
+        // debugging aid: "show_stack(NULL);" prints the
+        // back trace for this cpu.
+
+        if(sp == NULL)
+                sp = (unsigned long*)rdsp();
+
+        stack = sp;
+
+        for(i = 0; i < kstack_depth_to_print; i++) {
+                if (((long) stack & (THREAD_SIZE-1)) == 0)
+                        break;
+                if (i && ((i % 8) == 0))
+                        printk("\n       ");
+                printk("%08lx ", *stack++);
+        }
+
+        printk("\nCall Trace: ");
+        stack = sp;
+        i = 1;
+        module_start = VMALLOC_START;
+        module_end = VMALLOC_END;
+        while (((long) stack & (THREAD_SIZE-1)) != 0) {
+                addr = *stack++;
+                /*
+                 * If the address is either in the text segment of the
+                 * kernel, or in the region which contains vmalloc'ed
+                 * memory, it *may* be the address of a calling
+                 * routine; if so, print it so that someone tracing
+                 * down the cause of the crash will be able to figure
+                 * out the call path that was taken.
+                 */
+                if (((addr >= (unsigned long) &_stext) &&
+                     (addr <= (unsigned long) &_etext)) ||
+                    ((addr >= module_start) && (addr <= module_end))) {
+                        if (i && ((i % 8) == 0))
+                                printk("\n       ");
+                        printk("[<%08lx>] ", addr);
+                        i++;
+                }
+        }
+}
+
+#if 0
+/* displays a short stack trace */
+
+int show_stack()
+{
+	unsigned long *sp = (unsigned long *)rdusp();
+	int i;
+	printk("Stack dump [0x%08lx]:\n", (unsigned long)sp);
+	for(i = 0; i < 16; i++)
+		printk("sp + %d: 0x%08lx\n", i*4, sp[i]);
+	return 0;
+}
+#endif
+
+void show_registers(struct pt_regs * regs)
+{
+	unsigned long usp = rdusp();
+
+	printk("IRP: %08lx SRP: %08lx CCR: %08lx USP: %08lx\n",
+	       regs->irp, regs->srp, regs->dccr, usp );
+	printk(" r0: %08lx  r1: %08lx  r2: %08lx  r3: %08lx\n",
+	       regs->r0, regs->r1, regs->r2, regs->r3);
+	printk(" r4: %08lx  r5: %08lx  r6: %08lx  r7: %08lx\n",
+	       regs->r4, regs->r5, regs->r6, regs->r7);
+	printk(" r8: %08lx  r9: %08lx r10: %08lx r11: %08lx\n",
+	       regs->r8, regs->r9, regs->r10, regs->r11);
+	printk("r12: %08lx r13: %08lx oR10: %08lx\n",
+	       regs->r12, regs->r13, regs->orig_r10);
+	printk("Process %s (pid: %d, stackpage=%08lx)\n",
+	       current->comm, current->pid, (unsigned long)current);
+
+	// TODO, fix in_kernel detection
+
+#if 0
+	/*
+         * When in-kernel, we also print out the stack and code at the
+         * time of the fault..
+         */
+        if (1) {
+		
+                printk("\nStack: ");
+                show_stack((unsigned long*)usp);
+
+                printk("\nCode: ");
+                if(regs->irp < PAGE_OFFSET)
+                        goto bad;
+
+                for(i = 0; i < 20; i++)
+                {
+                        unsigned char c;
+                        if(__get_user(c, &((unsigned char*)regs->irp)[i])) {
+bad:
+                                printk(" Bad IP value.");
+                                break;
+                        }
+                        printk("%02x ", c);
+                }
+        }
+        printk("\n");
+#endif
+}
+
+
+
+void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+{
+	if(user_mode(regs))
+		return;
+
+	printk("%s: %04lx\n", str, err & 0xffff);
+
+	show_registers(regs);
+	show_stack(NULL);  /* print backtrace for kernel stack on this CPU */
+
+	do_exit(SIGSEGV);
+}
+
+void __init trap_init(void)
+{
+  
+
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/Makefile linux/arch/cris/lib/Makefile
--- v2.4.1/linux/arch/cris/lib/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,11 @@
+#
+# Makefile for Etrax-specific library files..
+#
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+L_TARGET = lib.a
+obj-y  = checksum.o checksumcopy.o string.o usercopy.o memset.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/checksum.S linux/arch/cris/lib/checksum.S
--- v2.4.1/linux/arch/cris/lib/checksum.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/checksum.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,113 @@
+	;; $Id: checksum.S,v 1.1 2000/07/10 16:25:21 bjornw Exp $
+	;; A fast checksum routine using movem
+	;; Copyright (c) 1998 Bjorn Wesen/Axis Communications AB
+
+	;; csum_partial(const unsigned char * buff, int len, unsigned int sum)
+	
+	.globl	_csum_partial
+_csum_partial:
+	
+	;; check for breakeven length between movem and normal word looping versions
+	
+	cmpu.w	80,r11
+	bcs	no_movem
+	nop
+
+	;; need to save the registers we use below in the movem loop
+	;; this overhead is why we have a check above for breakeven length
+	
+	subq	9*4,sp
+	movem	r8,[sp]
+	
+	;; do a movem checksum
+
+	;; r10 - src
+	;; r11 - length
+	;; r12 - checksum
+
+	subq	10*4,r11	; update length for the first loop
+	
+mloop:	movem	[r10+],r9	; read 10 longwords
+
+	;; perform dword checksumming on the 10 longwords
+	
+	add.d	r0,r12
+	ax
+	add.d	r1,r12
+	ax
+	add.d	r2,r12
+	ax
+	add.d	r3,r12
+	ax
+	add.d	r4,r12
+	ax
+	add.d	r5,r12
+	ax
+	add.d	r6,r12
+	ax
+	add.d	r7,r12
+	ax
+	add.d	r8,r12
+	ax
+	add.d	r9,r12
+
+	;; fold the carry into the checksum, to avoid having to loop the carry
+	;; back into the top
+	
+	ax
+	addq	0,r12
+	ax			; do it again, since we might have generated a carry
+	addq	0,r12
+
+	subq	10*4,r11
+	bge	mloop
+	nop
+
+	addq	10*4,r11	; compensate for last loop underflowing length
+
+	;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below
+	
+	moveq	-1,r1		; put 0xffff in r1, faster than move.d 0xffff,r1
+	lsrq	16,r1
+	
+	move.d	r12,r0
+	lsrq	16,r0		; r0 = checksum >> 16
+	and.d	r1,r12		; checksum = checksum & 0xffff
+	add.d	r0,r12		; checksum += r0
+	move.d	r12,r0		; do the same again, maybe we got a carry last add
+	lsrq	16,r0
+	and.d	r1,r12
+	add.d	r0,r12
+	
+	movem	[sp+],r8	; restore regs
+
+no_movem:
+	cmpq	2,r11
+	blt	no_words
+	nop
+	
+	;; checksum the rest of the words
+	
+	subq	2,r11
+	
+wloop:	subq	2,r11
+	bge	wloop
+	addu.w	[r10+],r12
+	
+	addq	2,r11
+		
+no_words:
+	;; see if we have one odd byte more
+	cmpq	1,r11
+	beq	do_byte
+	nop
+	ret
+	move.d	r12, r10
+
+do_byte:	
+	;; copy and checksum the last byte
+	addu.b	[r10],r12
+	ret
+	move.d	r12, r10
+		
+	
\ No newline at end of file
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/checksumcopy.S linux/arch/cris/lib/checksumcopy.S
--- v2.4.1/linux/arch/cris/lib/checksumcopy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/checksumcopy.S	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,120 @@
+	;; $Id: checksumcopy.S,v 1.2 2000/08/08 16:57:31 bjornw Exp $
+	;; A fast checksum+copy routine using movem
+	;; Copyright (c) 1998, 2000 Axis Communications AB
+	;;
+	;; Authors:	Bjorn Wesen
+	;; 
+	;; csum_partial_copy_nocheck(const char *src, char *dst,
+	;;		             int len, unsigned int sum)
+
+	.globl	_csum_partial_copy_nocheck
+_csum_partial_copy_nocheck:	
+	
+	;; check for breakeven length between movem and normal word looping versions
+	
+	cmpu.w	80,r12
+	bcs	no_movem
+	nop
+
+	;; need to save the registers we use below in the movem loop
+	;; this overhead is why we have a check above for breakeven length
+	
+	subq	9*4,sp
+	movem	r8,[sp]
+	
+	;; do a movem copy and checksum
+
+	;; r10 - src
+	;; r11 - dst
+	;; r12 - length
+	;; r13 - checksum
+
+	subq	10*4,r12	; update length for the first loop
+	
+mloop:	movem	[r10+],r9	; read 10 longwords
+	movem	r9,[r11+]	; write 10 longwords
+
+	;; perform dword checksumming on the 10 longwords
+	
+	add.d	r0,r13
+	ax
+	add.d	r1,r13
+	ax
+	add.d	r2,r13
+	ax
+	add.d	r3,r13
+	ax
+	add.d	r4,r13
+	ax
+	add.d	r5,r13
+	ax
+	add.d	r6,r13
+	ax
+	add.d	r7,r13
+	ax
+	add.d	r8,r13
+	ax
+	add.d	r9,r13
+
+	;; fold the carry into the checksum, to avoid having to loop the carry
+	;; back into the top
+	
+	ax
+	addq	0,r13
+
+	subq	10*4,r12
+	bge	mloop
+	nop
+
+	addq	10*4,r12	; compensate for last loop underflowing length
+
+	;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below
+	
+	moveq	-1,r1		; put 0xffff in r1, faster than move.d 0xffff,r1
+	lsrq	16,r1
+	
+	move.d	r13,r0
+	lsrq	16,r0		; r0 = checksum >> 16
+	and.d	r1,r13		; checksum = checksum & 0xffff
+	add.d	r0,r13		; checksum += r0
+	move.d	r13,r0		; do the same again, maybe we got a carry last add
+	lsrq	16,r0
+	and.d	r1,r13
+	add.d	r0,r13
+	
+	movem	[sp+],r8	; restore regs
+		
+no_movem:
+	cmpq	2,r12
+	blt	no_words
+	nop
+	
+	;; copy and checksum the rest of the words
+	
+	subq	2,r12
+	
+wloop:	move.w	[r10+],r9
+	addu.w	r9,r13
+	subq	2,r12
+	bge	wloop
+	move.w	r9,[r11+]
+	
+	addq	2,r12
+		
+no_words:
+	;; see if we have one odd byte more
+	cmpq	1,r12
+	beq	do_byte
+	nop
+	ret
+	move.d	r13, r10
+
+do_byte:	
+	;; copy and checksum the last byte
+	move.b	[r10],r9
+	addu.b	r9,r13
+	move.b	r9,[r11]
+	ret
+	move.d	r13, r10
+		
+	
\ No newline at end of file
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/dmacopy.c linux/arch/cris/lib/dmacopy.c
--- v2.4.1/linux/arch/cris/lib/dmacopy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/dmacopy.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,43 @@
+/* $Id: dmacopy.c,v 1.1 2000/07/10 16:25:21 bjornw Exp $ 
+ *
+ * memcpy for large blocks, using memory-memory DMA channels 6 and 7 in Etrax
+ */
+
+#include <asm/svinto.h>
+#include <asm/io.h>
+
+#define D(x)
+
+void *dma_memcpy(void *pdst,
+		 const void *psrc,
+		 unsigned int pn)
+{
+	static etrax_dma_descr indma, outdma;
+	
+	D(printk("dma_memcpy %d bytes... ", pn));
+
+#if 0
+	*R_GEN_CONFIG = genconfig_shadow = 
+		(genconfig_shadow & ~0x3c0000) |
+		IO_STATE(R_GEN_CONFIG, dma6, intdma7) |
+		IO_STATE(R_GEN_CONFIG, dma7, intdma6);
+#endif
+	indma.sw_len = outdma.sw_len = pn;
+	indma.ctrl = d_eol | d_eop;
+	outdma.ctrl = d_eol;
+	indma.buf = psrc;
+	outdma.buf = pdst;
+
+	*R_DMA_CH6_FIRST = &indma;
+	*R_DMA_CH7_FIRST = &outdma;
+	*R_DMA_CH6_CMD = IO_STATE(R_DMA_CH6_CMD, cmd, start);
+	*R_DMA_CH7_CMD = IO_STATE(R_DMA_CH7_CMD, cmd, start);
+	
+	while(*R_DMA_CH7_CMD == 1) /* wait for completion */ ;
+
+	D(printk("done\n"));
+
+}
+
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/memset.c linux/arch/cris/lib/memset.c
--- v2.4.1/linux/arch/cris/lib/memset.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/memset.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,245 @@
+/*#************************************************************************#*/
+/*#-------------------------------------------------------------------------*/
+/*#                                                                         */
+/*# FUNCTION NAME: memset()                                                 */
+/*#                                                                         */
+/*# PARAMETERS:  void* dst;   Destination address.                          */
+/*#              int     c;   Value of byte to write.                       */
+/*#              int   len;   Number of bytes to write.                     */
+/*#                                                                         */
+/*# RETURNS:     dst.                                                       */
+/*#                                                                         */
+/*# DESCRIPTION: Sets the memory dst of length len bytes to c, as standard. */
+/*#              Framework taken from memcpy.  This routine is              */
+/*#              very sensitive to compiler changes in register allocation. */
+/*#              Should really be rewritten to avoid this problem.          */
+/*#                                                                         */
+/*#-------------------------------------------------------------------------*/
+/*#                                                                         */
+/*# HISTORY                                                                 */
+/*#                                                                         */
+/*# DATE      NAME            CHANGES                                       */
+/*# ----      ----            -------                                       */
+/*# 990713    HP              Tired of watching this function (or           */
+/*#                           really, the nonoptimized generic              */
+/*#                           implementation) take up 90% of simulator      */
+/*#                           output.  Measurements needed.                 */
+/*#                                                                         */
+/*#-------------------------------------------------------------------------*/
+
+/* No, there's no macro saying 12*4, since it is "hard" to get it into
+   the asm in a good way.  Thus better to expose the problem everywhere.
+   */
+
+/* Assuming 1 cycle per dword written or read (ok, not really true), and
+   one per instruction, then 43+3*(n/48-1) <= 24+24*(n/48-1)
+   so n >= 45.7; n >= 0.9; we win on the first full 48-byte block to set. */
+
+#define ZERO_BLOCK_SIZE (1*12*4)
+
+void *memset(void *pdst,
+             int c,
+             unsigned int plen)
+{
+  /* Ok.  Now we want the parameters put in special registers.
+     Make sure the compiler is able to make something useful of this. */
+
+  register char *return_dst __asm__ ("r10") = pdst;
+  register int n __asm__ ("r12") = plen;
+  register int lc __asm__ ("r11") = c;
+
+  /* Most apps use memset sanely.  Only those memsetting about 3..4
+     bytes or less get penalized compared to the generic implementation
+     - and that's not really sane use. */
+
+  /* Ugh.  This is fragile at best.  Check with newer GCC releases, if
+     they compile cascaded "x |= x << 8" sanely! */
+  __asm__("movu.b %0,r13\n\tlslq 8,r13\n\tmove.b %0,r13\n\tmove.d r13,%0\n\tlslq 16,r13\n\tor.d r13,%0"
+          : "=r" (lc) : "0" (lc) : "r13");
+
+  {
+    register char *dst __asm__ ("r13") = pdst;
+ 
+  /* This is NONPORTABLE, but since this whole routine is     */
+  /* grossly nonportable that doesn't matter.                 */
+
+  if (((unsigned long) pdst & 3) != 0
+     /* Oops! n=0 must be a legal call, regardless of alignment. */
+      && n >= 3)
+  {
+    if ((unsigned long)dst & 1)
+    {
+      *dst = (char) lc;
+      n--;
+      dst++;
+    }
+
+    if ((unsigned long)dst & 2)
+    {
+      *(short *)dst = lc;
+      n -= 2;
+      dst += 2;
+    }
+  }
+
+  /* Now the fun part.  For the threshold value of this, check the equation
+     above. */
+  /* Decide which copying method to use. */
+  if (n >= ZERO_BLOCK_SIZE)
+  {
+    /* For large copies we use 'movem' */
+
+  /* It is not optimal to tell the compiler about clobbering any
+     registers; that will move the saving/restoring of those registers
+     to the function prologue/epilogue, and make non-movem sizes
+     suboptimal.
+
+      This method is not foolproof; it assumes that the "asm reg"
+     declarations at the beginning of the function really are used
+     here (beware: they may be moved to temporary registers).
+      This way, we do not have to save/move the registers around into
+     temporaries; we can safely use them straight away.
+
+      If you want to check that the allocation was right; then
+      check the equalities in the first comment.  It should say
+      "r13=r13, r12=r12, r11=r11" */
+    __asm__ volatile ("
+        ;; Check that the following is true (same register names on
+        ;; both sides of equal sign, as in r8=r8):
+        ;; %0=r13, %1=r12, %4=r11
+        ;;
+	;; Save the registers we'll clobber in the movem process
+	;; on the stack.  Don't mention them to gcc, it will only be
+	;; upset.
+	subq 	11*4,sp
+        movem   r10,[sp]
+
+        move.d  r11,r0
+        move.d  r11,r1
+        move.d  r11,r2
+        move.d  r11,r3
+        move.d  r11,r4
+        move.d  r11,r5
+        move.d  r11,r6
+        move.d  r11,r7
+        move.d  r11,r8
+        move.d  r11,r9
+        move.d  r11,r10
+
+        ;; Now we've got this:
+	;; r13 - dst
+	;; r12 - n
+	
+        ;; Update n for the first loop
+        subq    12*4,r12
+0:
+        subq   12*4,r12
+        bge     0b
+	movem	r11,[r13+]
+
+        addq   12*4,r12  ;; compensate for last loop underflowing n
+
+	;; Restore registers from stack
+        movem [sp+],r10" 
+
+     /* Outputs */ : "=r" (dst), "=r" (n)
+     /* Inputs */ : "0" (dst), "1" (n), "r" (lc));
+    
+  }
+
+    /* Either we directly starts copying, using dword copying
+       in a loop, or we copy as much as possible with 'movem' 
+       and then the last block (<44 bytes) is copied here.
+       This will work since 'movem' will have updated src,dst,n. */
+
+    while ( n >= 16 )
+    {
+      *((long*)dst)++ = lc;
+      *((long*)dst)++ = lc;
+      *((long*)dst)++ = lc;
+      *((long*)dst)++ = lc;
+      n -= 16;
+    }
+
+    /* A switch() is definitely the fastest although it takes a LOT of code.
+     * Particularly if you inline code this.
+     */
+    switch (n)
+    {
+      case 0:
+        break;
+      case 1:
+        *(char*)dst = (char) lc;
+        break;
+      case 2:
+        *(short*)dst = (short) lc;
+        break;
+      case 3:
+        *((short*)dst)++ = (short) lc;
+        *(char*)dst = (char) lc;
+        break;
+      case 4:
+        *((long*)dst)++ = lc;
+        break;
+      case 5:
+        *((long*)dst)++ = lc;
+        *(char*)dst = (char) lc;
+        break;
+      case 6:
+        *((long*)dst)++ = lc;
+        *(short*)dst = (short) lc;
+        break;
+      case 7:
+        *((long*)dst)++ = lc;
+        *((short*)dst)++ = (short) lc;
+        *(char*)dst = (char) lc;
+        break;
+      case 8:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        break;
+      case 9:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *(char*)dst = (char) lc;
+        break;
+      case 10:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *(short*)dst = (short) lc;
+        break;
+      case 11:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *((short*)dst)++ = (short) lc;
+        *(char*)dst = (char) lc;
+        break;
+      case 12:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        break;
+      case 13:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *(char*)dst = (char) lc;
+        break;
+      case 14:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *(short*)dst = (short) lc;
+        break;
+      case 15:
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *((long*)dst)++ = lc;
+        *((short*)dst)++ = (short) lc;
+        *(char*)dst = (char) lc;
+        break;
+    }
+  }
+
+  return return_dst; /* destination pointer. */
+} /* memset() */
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/old_checksum.c linux/arch/cris/lib/old_checksum.c
--- v2.4.1/linux/arch/cris/lib/old_checksum.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/old_checksum.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,127 @@
+/* $Id: old_checksum.c,v 1.1 2000/07/10 16:25:21 bjornw Exp $
+ *
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		IP/TCP/UDP checksumming routines
+ *
+ * Authors:	Jorge Cwik, <jorge@laser.satlink.net>
+ *		Arnt Gulbrandsen, <agulbra@nvg.unit.no>
+ *		Tom May, <ftom@netcom.com>
+ *		Lots of code moved from tcp.c and ip.c; see those files
+ *		for more names.
+ *
+ *		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.
+ */
+
+#include <net/checksum.h>
+
+#undef PROFILE_CHECKSUM
+
+#ifdef PROFILE_CHECKSUM
+/* these are just for profiling the checksum code with an oscillioscope.. uh */
+#if 0
+#define BITOFF *((unsigned char *)0xb0000030) = 0xff
+#define BITON *((unsigned char *)0xb0000030) = 0x0
+#endif
+#include <asm/io.h>
+#define CBITON LED_ACTIVE_SET(1)
+#define CBITOFF LED_ACTIVE_SET(0)
+#define BITOFF
+#define BITON
+#else
+#define BITOFF
+#define BITON
+#define CBITOFF
+#define CBITON
+#endif
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+#include <asm/delay.h>
+
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
+{
+  /*
+   * Experiments with ethernet and slip connections show that buff
+   * is aligned on either a 2-byte or 4-byte boundary.
+   */
+  const unsigned char *endMarker = buff + len;
+  const unsigned char *marker = endMarker - (len % 16);
+#if 0
+  if((int)buff & 0x3)
+    printk("unaligned buff %p\n", buff);
+  __delay(900); /* extra delay of 90 us to test performance hit */
+#endif
+  BITON;
+  while (buff < marker) {
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+    sum += *((unsigned short *)buff)++;
+  }
+  marker = endMarker - (len % 2);
+  while(buff < marker) {
+    sum += *((unsigned short *)buff)++;
+  }
+  if(endMarker - buff > 0) {
+    sum += *buff;                 /* add extra byte seperately */
+  }
+  BITOFF;
+  return(sum);
+}
+
+#if 0
+
+/*
+ * copy while checksumming, otherwise like csum_partial
+ */
+
+unsigned int csum_partial_copy(const unsigned char *src, unsigned char *dst, 
+				  int len, unsigned int sum)
+{
+  const unsigned char *endMarker;
+  const unsigned char *marker;
+  printk("csum_partial_copy len %d.\n", len);
+#if 0
+  if((int)src & 0x3)
+    printk("unaligned src %p\n", src);
+  if((int)dst & 0x3)
+    printk("unaligned dst %p\n", dst);
+  __delay(1800); /* extra delay of 90 us to test performance hit */
+#endif
+  endMarker = src + len;
+  marker = endMarker - (len % 16);
+  CBITON;
+  while(src < marker) {
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+  }
+  marker = endMarker - (len % 2);
+  while(src < marker) {
+    sum += (*((unsigned short *)dst)++ = *((unsigned short *)src)++);
+  }
+  if(endMarker - src > 0) {
+    sum += (*dst = *src);                 /* add extra byte seperately */
+  }
+  CBITOFF;
+  return(sum);
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/string.c linux/arch/cris/lib/string.c
--- v2.4.1/linux/arch/cris/lib/string.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/string.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,223 @@
+/*#************************************************************************#*/
+/*#-------------------------------------------------------------------------*/
+/*#                                                                         */
+/*# FUNCTION NAME: memcpy()                                                 */
+/*#                                                                         */
+/*# PARAMETERS:  void* dst;   Destination address.                          */
+/*#              void* src;   Source address.                               */
+/*#              int   len;   Number of bytes to copy.                      */
+/*#                                                                         */
+/*# RETURNS:     dst.                                                       */
+/*#                                                                         */
+/*# DESCRIPTION: Copies len bytes of memory from src to dst.  No guarantees */
+/*#              about copying of overlapping memory areas. This routine is */
+/*#              very sensitive to compiler changes in register allocation. */
+/*#              Should really be rewritten to avoid this problem.          */
+/*#                                                                         */
+/*#-------------------------------------------------------------------------*/
+/*#                                                                         */
+/*# HISTORY                                                                 */
+/*#                                                                         */
+/*# DATE      NAME            CHANGES                                       */
+/*# ----      ----            -------                                       */
+/*# 941007    Kenny R         Creation                                      */
+/*# 941011    Kenny R         Lots of optimizations and inlining.           */
+/*# 941129    Ulf A           Adapted for use in libc.                      */
+/*# 950216    HP              N==0 forgotten if non-aligned src/dst.        */
+/*#                           Added some optimizations.                     */
+/*# 001025    HP              Make src and dst char *.  Align dst to	    */
+/*#			      dword, not just word-if-both-src-and-dst-	    */
+/*#			      are-misaligned.				    */
+/*#                                                                         */
+/*#-------------------------------------------------------------------------*/
+
+void *memcpy(void *pdst,
+             const void *psrc,
+             unsigned int pn)
+{
+  /* Ok.  Now we want the parameters put in special registers.
+     Make sure the compiler is able to make something useful of this.
+      As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
+
+     If gcc was allright, it really would need no temporaries, and no
+     stack space to save stuff on. */
+
+  register void *return_dst __asm__ ("r10") = pdst;
+  register char *dst __asm__ ("r13") = pdst;
+  register const char *src __asm__ ("r11") = psrc;
+  register int n __asm__ ("r12") = pn;
+  
+ 
+  /* When src is aligned but not dst, this makes a few extra needless
+     cycles.  I believe it would take as many to check that the
+     re-alignment was unnecessary.  */
+  if (((unsigned long) dst & 3) != 0
+      /* Don't align if we wouldn't copy more than a few bytes; so we
+	 don't have to check further for overflows.  */
+      && n >= 3)
+  {
+    if ((unsigned long) dst & 1)
+    {
+      n--;
+      *(char*)dst = *(char*)src;
+      src++;
+      dst++;
+    }
+
+    if ((unsigned long) dst & 2)
+    {
+      n -= 2;
+      *(short*)dst = *(short*)src;
+      src += 2;
+      dst += 2;
+    }
+  }
+
+  /* Decide which copying method to use. */
+  if (n >= 44*2)                /* Break even between movem and
+                                   move16 is at 38.7*2, but modulo 44. */
+  {
+    /* For large copies we use 'movem' */
+
+  /* It is not optimal to tell the compiler about clobbering any
+     registers; that will move the saving/restoring of those registers
+     to the function prologue/epilogue, and make non-movem sizes
+     suboptimal.
+
+      This method is not foolproof; it assumes that the "asm reg"
+     declarations at the beginning of the function really are used
+     here (beware: they may be moved to temporary registers).
+      This way, we do not have to save/move the registers around into
+     temporaries; we can safely use them straight away.
+
+      If you want to check that the allocation was right; then
+      check the equalities in the first comment.  It should say
+      "r13=r13, r11=r11, r12=r12" */
+    __asm__ volatile ("
+        ;; Check that the following is true (same register names on
+        ;; both sides of equal sign, as in r8=r8):
+        ;; %0=r13, %1=r11, %2=r12
+        ;;
+	;; Save the registers we'll use in the movem process
+	;; on the stack.
+	subq 	11*4,sp
+	movem	r10,[sp]
+
+        ;; Now we've got this:
+	;; r11 - src
+	;; r13 - dst
+	;; r12 - n
+	
+        ;; Update n for the first loop
+        subq    44,r12
+0:
+	movem	[r11+],r10
+        subq   44,r12
+        bge     0b
+	movem	r10,[r13+]
+
+        addq   44,r12  ;; compensate for last loop underflowing n
+
+	;; Restore registers from stack
+        movem [sp+],r10" 
+
+     /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n) 
+     /* Inputs */ : "0" (dst), "1" (src), "2" (n));
+    
+  }
+
+  /* Either we directly starts copying, using dword copying
+     in a loop, or we copy as much as possible with 'movem' 
+     and then the last block (<44 bytes) is copied here.
+     This will work since 'movem' will have updated src,dst,n. */
+
+  while ( n >= 16 )
+  {
+    *((long*)dst)++ = *((long*)src)++;
+    *((long*)dst)++ = *((long*)src)++;
+    *((long*)dst)++ = *((long*)src)++;
+    *((long*)dst)++ = *((long*)src)++;
+    n -= 16;
+  }
+
+  /* A switch() is definitely the fastest although it takes a LOT of code.
+   * Particularly if you inline code this.
+   */
+  switch (n)
+  {
+    case 0:
+      break;
+    case 1:
+      *(char*)dst = *(char*)src;
+      break;
+    case 2:
+      *(short*)dst = *(short*)src;
+      break;
+    case 3:
+      *((short*)dst)++ = *((short*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+    case 4:
+      *((long*)dst)++ = *((long*)src)++;
+      break;
+    case 5:
+      *((long*)dst)++ = *((long*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+    case 6:
+      *((long*)dst)++ = *((long*)src)++;
+      *(short*)dst = *(short*)src;
+      break;
+    case 7:
+      *((long*)dst)++ = *((long*)src)++;
+      *((short*)dst)++ = *((short*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+    case 8:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      break;
+    case 9:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+    case 10:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *(short*)dst = *(short*)src;
+      break;
+    case 11:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *((short*)dst)++ = *((short*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+    case 12:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      break;
+    case 13:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+    case 14:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *(short*)dst = *(short*)src;
+      break;
+    case 15:
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *((long*)dst)++ = *((long*)src)++;
+      *((short*)dst)++ = *((short*)src)++;
+      *(char*)dst = *(char*)src;
+      break;
+  }
+
+  return return_dst; /* destination pointer. */
+} /* memcpy() */
diff -u --recursive --new-file v2.4.1/linux/arch/cris/lib/usercopy.c linux/arch/cris/lib/usercopy.c
--- v2.4.1/linux/arch/cris/lib/usercopy.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/lib/usercopy.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,501 @@
+/*
+ * User address space access functions.
+ * The non-inlined parts of asm-cris/uaccess.h are here.
+ *
+ * Copyright (C) 2000, Axis Communications AB.
+ *
+ * Written by Hans-Peter Nilsson.
+ * Pieces used from memcpy, originally by Kenny Ranerup long time ago.
+ */
+
+#include <asm/uaccess.h>
+
+/* Asm:s have been tweaked (within the domain of correctness) to give
+   satisfactory results for "gcc version 2.96 20000427 (experimental)".
+
+   Check regularly...
+
+   Note that the PC saved at a bus-fault is the address *after* the
+   faulting instruction, which means the branch-target for instructions in
+   delay-slots for taken branches.  Note also that the postincrement in
+   the instruction is performed regardless of bus-fault; the register is
+   seen updated in fault handlers.
+
+   Oh, and on the code formatting issue, to whomever feels like "fixing
+   it" to Conformity: I'm too "lazy", but why don't you go ahead and "fix"
+   string.c too.  I just don't think too many people will hack this file
+   for the code format to be an issue.  */
+
+
+/* Copy to userspace.  This is based on the memcpy used for
+   kernel-to-kernel copying; see "string.c".  */
+
+unsigned long
+__copy_user (void *pdst, const void *psrc, unsigned long pn)
+{
+  /* We want the parameters put in special registers.
+     Make sure the compiler is able to make something useful of this.
+     As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
+
+     FIXME: Comment for old gcc version.  Check.
+     If gcc was allright, it really would need no temporaries, and no
+     stack space to save stuff on. */
+
+  register char *dst __asm__ ("r13") = pdst;
+  register const char *src __asm__ ("r11") = psrc;
+  register int n __asm__ ("r12") = pn;
+  register int retn __asm__ ("r10") = 0;
+
+
+  /* When src is aligned but not dst, this makes a few extra needless
+     cycles.  I believe it would take as many to check that the
+     re-alignment was unnecessary.  */
+  if (((unsigned long) dst & 3) != 0
+      /* Don't align if we wouldn't copy more than a few bytes; so we
+	 don't have to check further for overflows.  */
+      && n >= 3)
+  {
+    if ((unsigned long) dst & 1)
+    {
+      __asm_copy_to_user_1 (dst, src, retn);
+      n--;
+    }
+
+    if ((unsigned long) dst & 2)
+    {
+      __asm_copy_to_user_2 (dst, src, retn);
+      n -= 2;
+    }
+  }
+
+  /* Decide which copying method to use. */
+  if (n >= 44*2)		/* Break even between movem and
+				   move16 is at 38.7*2, but modulo 44. */
+  {
+    /* For large copies we use 'movem'.  */
+
+    /* It is not optimal to tell the compiler about clobbering any
+       registers; that will move the saving/restoring of those registers
+       to the function prologue/epilogue, and make non-movem sizes
+       suboptimal.
+
+       This method is not foolproof; it assumes that the "asm reg"
+       declarations at the beginning of the function really are used
+       here (beware: they may be moved to temporary registers).
+       This way, we do not have to save/move the registers around into
+       temporaries; we can safely use them straight away.
+
+       If you want to check that the allocation was right; then
+       check the equalities in the first comment.  It should say
+       "r13=r13, r11=r11, r12=r12".  */
+    __asm__ volatile ("
+	;; Check that the following is true (same register names on
+	;; both sides of equal sign, as in r8=r8):
+	;; %0=r13, %1=r11, %2=r12 %3=r10
+	;;
+	;; Save the registers we'll use in the movem process
+	;; on the stack.
+	subq	11*4,sp
+	movem	r10,[sp]
+
+	;; Now we've got this:
+	;; r11 - src
+	;; r13 - dst
+	;; r12 - n
+
+	;; Update n for the first loop
+	subq	44,r12
+
+; Since the noted PC of a faulting instruction in a delay-slot of a taken
+; branch, is that of the branch target, we actually point at the from-movem
+; for this case.  There is no ambiguity here; if there was a fault in that
+; instruction (meaning a kernel oops), the faulted PC would be the address
+; after *that* movem.
+
+0:
+	movem	[r11+],r10
+	subq   44,r12
+	bge	0b
+	movem	r10,[r13+]
+1:
+	addq   44,r12  ;; compensate for last loop underflowing n
+
+	;; Restore registers from stack
+	movem [sp+],r10
+2:
+	.section .fixup,\"ax\"
+
+; To provide a correct count in r10 of bytes that failed to be copied,
+; we jump back into the loop if the loop-branch was taken.  There is no
+; performance penalty for sany use; the program will segfault soon enough.
+
+3:
+	move.d [sp],r10
+	addq 44,r10
+	move.d r10,[sp]
+	jump 0b
+4:
+	movem [sp+],r10
+	addq 44,r10
+	addq 44,r12
+	jump 2b
+
+	.previous
+	.section __ex_table,\"a\"
+	.dword 0b,3b
+	.dword 1b,4b
+	.previous"
+
+     /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
+     /* Inputs */ : "0" (dst), "1" (src), "2" (n), "3" (retn));
+
+  }
+
+  /* Either we directly start copying, using dword copying in a loop, or
+     we copy as much as possible with 'movem' and then the last block (<44
+     bytes) is copied here.  This will work since 'movem' will have
+     updated SRC, DST and N.  */
+
+  while (n >= 16)
+  {
+    __asm_copy_to_user_16 (dst, src, retn);
+    n -= 16;
+  }
+
+  /* Having a separate by-four loops cuts down on cache footprint.
+     FIXME:  Test with and without; increasing switch to be 0..15.  */
+  while (n >= 4)
+  {
+    __asm_copy_to_user_4 (dst, src, retn);
+    n -= 4;
+  }
+
+  switch (n)
+  {
+    case 0:
+      break;
+    case 1:
+      __asm_copy_to_user_1 (dst, src, retn);
+      break;
+    case 2:
+      __asm_copy_to_user_2 (dst, src, retn);
+      break;
+    case 3:
+      __asm_copy_to_user_3 (dst, src, retn);
+      break;
+  }
+
+  return retn;
+}
+
+/* Copy from user to kernel, zeroing the bytes that were inaccessible in
+   userland.  */
+
+unsigned long
+__copy_user_zeroing (void *pdst, const void *psrc, unsigned long pn)
+{
+  /* We want the parameters put in special registers.
+     Make sure the compiler is able to make something useful of this.
+     As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
+
+     FIXME: Comment for old gcc version.  Check.
+     If gcc was allright, it really would need no temporaries, and no
+     stack space to save stuff on.  */
+
+  register char *dst __asm__ ("r13") = pdst;
+  register const char *src __asm__ ("r11") = psrc;
+  register int n __asm__ ("r12") = pn;
+  register int retn __asm__ ("r10") = 0;
+
+  /* When src is aligned but not dst, this makes a few extra needless
+     cycles.  I believe it would take as many to check that the
+     re-alignment was unnecessary.  */
+  if (((unsigned long) dst & 3) != 0
+      /* Don't align if we wouldn't copy more than a few bytes; so we
+	 don't have to check further for overflows.  */
+      && n >= 3)
+  {
+    if ((unsigned long) dst & 1)
+    {
+      __asm_copy_from_user_1 (dst, src, retn);
+      n--;
+    }
+
+    if ((unsigned long) dst & 2)
+    {
+      __asm_copy_from_user_2 (dst, src, retn);
+      n -= 2;
+    }
+  }
+
+  /* Decide which copying method to use. */
+  if (n >= 44*2)		/* Break even between movem and
+				   move16 is at 38.7*2, but modulo 44. */
+  {
+    /* For large copies we use 'movem' */
+
+    /* It is not optimal to tell the compiler about clobbering any
+       registers; that will move the saving/restoring of those registers
+       to the function prologue/epilogue, and make non-movem sizes
+       suboptimal.
+
+       This method is not foolproof; it assumes that the "asm reg"
+       declarations at the beginning of the function really are used
+       here (beware: they may be moved to temporary registers).
+       This way, we do not have to save/move the registers around into
+       temporaries; we can safely use them straight away.
+
+       If you want to check that the allocation was right; then
+       check the equalities in the first comment.  It should say
+       "r13=r13, r11=r11, r12=r12" */
+    __asm__ volatile ("
+	;; Check that the following is true (same register names on
+	;; both sides of equal sign, as in r8=r8):
+	;; %0=r13, %1=r11, %2=r12 %3=r10
+	;;
+	;; Save the registers we'll use in the movem process
+	;; on the stack.
+	subq	11*4,sp
+	movem	r10,[sp]
+
+	;; Now we've got this:
+	;; r11 - src
+	;; r13 - dst
+	;; r12 - n
+
+	;; Update n for the first loop
+	subq	44,r12
+0:
+	movem	[r11+],r10
+1:
+	subq   44,r12
+	bge	0b
+	movem	r10,[r13+]
+
+	addq   44,r12  ;; compensate for last loop underflowing n
+
+	;; Restore registers from stack
+	movem [sp+],r10
+
+	.section .fixup,\"ax\"
+
+; To provide a correct count in r10 of bytes that failed to be copied,
+; we jump back into the loop if the loop-branch was taken.
+;  There is no performance penalty; the program will segfault soon
+; enough.
+
+3:
+	move.d [sp],r10
+	addq 44,r10
+	move.d r10,[sp]
+	clear.d r0
+	clear.d r1
+	clear.d r2
+	clear.d r3
+	clear.d r4
+	clear.d r5
+	clear.d r6
+	clear.d r7
+	clear.d r8
+	clear.d r9
+	clear.d r10
+	jump 1b
+
+	.previous
+	.section __ex_table,\"a\"
+	.dword 1b,3b
+	.previous"
+
+     /* Outputs */ : "=r" (dst), "=r" (src), "=r" (n), "=r" (retn)
+     /* Inputs */ : "0" (dst), "1" (src), "2" (n), "3" (retn));
+
+  }
+
+  /* Either we directly start copying here, using dword copying in a loop,
+     or we copy as much as possible with 'movem' and then the last block
+     (<44 bytes) is copied here.  This will work since 'movem' will have
+     updated src, dst and n. */
+
+  while (n >= 16)
+  {
+    __asm_copy_from_user_16 (dst, src, retn);
+    n -= 16;
+  }
+
+  /* Having a separate by-four loops cuts down on cache footprint.
+     FIXME:  Test with and without; increasing switch to be 0..15.  */
+  while (n >= 4)
+  {
+    __asm_copy_from_user_4 (dst, src, retn);
+    n -= 4;
+  }
+
+  switch (n)
+  {
+    case 0:
+      break;
+    case 1:
+      __asm_copy_from_user_1 (dst, src, retn);
+      break;
+    case 2:
+      __asm_copy_from_user_2 (dst, src, retn);
+      break;
+    case 3:
+      __asm_copy_from_user_3 (dst, src, retn);
+      break;
+  }
+
+  return retn;
+}
+
+/* Zero userspace.  */
+
+unsigned long
+__do_clear_user (void *pto, unsigned long pn)
+{
+  /* We want the parameters put in special registers.
+     Make sure the compiler is able to make something useful of this.
+      As it is now: r10 -> r13; r11 -> r11 (nop); r12 -> r12 (nop).
+
+     FIXME: Comment for old gcc version.  Check.
+     If gcc was allright, it really would need no temporaries, and no
+     stack space to save stuff on. */
+
+  register char *dst __asm__ ("r13") = pto;
+  register int n __asm__ ("r12") = pn;
+  register int retn __asm__ ("r10") = 0;
+
+
+  if (((unsigned long) dst & 3) != 0
+     /* Don't align if we wouldn't copy more than a few bytes.  */
+      && n >= 3)
+  {
+    if ((unsigned long) dst & 1)
+    {
+      __asm_clear_1 (dst, retn);
+      n--;
+    }
+
+    if ((unsigned long) dst & 2)
+    {
+      __asm_clear_2 (dst, retn);
+      n -= 2;
+    }
+  }
+
+  /* Decide which copying method to use.
+     FIXME: This number is from the "ordinary" kernel memset.  */
+  if (n >= (1*48))
+  {
+    /* For large clears we use 'movem' */
+
+    /* It is not optimal to tell the compiler about clobbering any
+       call-saved registers; that will move the saving/restoring of
+       those registers to the function prologue/epilogue, and make
+       non-movem sizes suboptimal.
+
+       This method is not foolproof; it assumes that the "asm reg"
+       declarations at the beginning of the function really are used
+       here (beware: they may be moved to temporary registers).
+       This way, we do not have to save/move the registers around into
+       temporaries; we can safely use them straight away.
+
+      If you want to check that the allocation was right; then
+      check the equalities in the first comment.  It should say
+      something like "r13=r13, r11=r11, r12=r12". */
+    __asm__ volatile ("
+	;; Check that the following is true (same register names on
+	;; both sides of equal sign, as in r8=r8):
+	;; %0=r13, %1=r12 %2=r10
+	;;
+	;; Save the registers we'll clobber in the movem process
+	;; on the stack.  Don't mention them to gcc, it will only be
+	;; upset.
+	subq	11*4,sp
+	movem	r10,[sp]
+
+	clear.d r0
+	clear.d r1
+	clear.d r2
+	clear.d r3
+	clear.d r4
+	clear.d r5
+	clear.d r6
+	clear.d r7
+	clear.d r8
+	clear.d r9
+	clear.d r10
+	clear.d r11
+
+	;; Now we've got this:
+	;; r13 - dst
+	;; r12 - n
+
+	;; Update n for the first loop
+	subq	12*4,r12
+0:
+	subq   12*4,r12
+	bge	0b
+	movem	r11,[r13+]
+1:
+	addq   12*4,r12	 ;; compensate for last loop underflowing n
+
+	;; Restore registers from stack
+	movem [sp+],r10
+2:
+	.section .fixup,\"ax\"
+3:
+	move.d [sp],r10
+	addq 12*4,r10
+	move.d r10,[sp]
+	clear.d r10
+	jump 0b
+
+4:
+	movem [sp+],r10
+	addq 12*4,r10
+	addq 12*4,r12
+	jump 2b
+
+	.previous
+	.section __ex_table,\"a\"
+	.dword 0b,3b
+	.dword 1b,4b
+	.previous"
+
+     /* Outputs */ : "=r" (dst), "=r" (n), "=r" (retn)
+     /* Inputs */ : "0" (dst), "1" (n), "2" (retn)
+     /* Clobber */ : "r11");
+  }
+
+  while (n >= 16)
+  {
+    __asm_clear_16 (dst, retn);
+    n -= 16;
+  }
+
+  /* Having a separate by-four loops cuts down on cache footprint.
+     FIXME:  Test with and without; increasing switch to be 0..15.  */
+  while (n >= 4)
+  {
+    __asm_clear_4 (dst, retn);
+    n -= 4;
+  }
+
+  switch (n)
+  {
+    case 0:
+      break;
+    case 1:
+      __asm_clear_1 (dst, retn);
+      break;
+    case 2:
+      __asm_clear_2 (dst, retn);
+      break;
+    case 3:
+      __asm_clear_3 (dst, retn);
+      break;
+  }
+
+  return retn;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/mm/Makefile linux/arch/cris/mm/Makefile
--- v2.4.1/linux/arch/cris/mm/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/mm/Makefile	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,13 @@
+#
+# Makefile for the linux cris-specific parts of the memory manager.
+#
+# 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 := mm.o
+obj-y	 := init.o fault.o tlb.o extable.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/cris/mm/extable.c linux/arch/cris/mm/extable.c
--- v2.4.1/linux/arch/cris/mm/extable.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/mm/extable.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/cris/mm/extable.c
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+extern const struct exception_table_entry _start___ex_table[];
+extern const struct exception_table_entry _stop___ex_table[];
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+		 const struct exception_table_entry *last,
+		 unsigned long value)
+{
+        while (first <= last) {
+		const struct exception_table_entry *mid;
+		long diff;
+
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+                if (diff == 0)
+                        return mid->fixup;
+                else if (diff < 0)
+                        first = mid+1;
+                else
+                        last = mid-1;
+        }
+        return 0;
+}
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+	unsigned long ret;
+
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
+	ret = search_one_table(_start___ex_table, _stop___ex_table-1, addr);
+	if (ret) return ret;
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
+	for (mp = module_list; mp != NULL; mp = mp->next) {
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_end - 1, addr);
+		if (ret) return ret;
+	}
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/mm/fault.c linux/arch/cris/mm/fault.c
--- v2.4.1/linux/arch/cris/mm/fault.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/mm/fault.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,390 @@
+/*
+ *  linux/arch/cris/mm/fault.c
+ *
+ *  Copyright (C) 2000  Axis Communications AB
+ *
+ *  Authors:  Bjorn Wesen 
+ * 
+ *  $Log: fault.c,v $
+ *  Revision 1.8  2000/11/22 14:45:31  bjornw
+ *  * 2.4.0-test10 removed the set_pgdir instantaneous kernel global mapping
+ *    into all processes. Instead we fill in the missing PTE entries on demand.
+ *
+ *  Revision 1.7  2000/11/21 16:39:09  bjornw
+ *  fixup switches frametype
+ *
+ *  Revision 1.6  2000/11/17 16:54:08  bjornw
+ *  More detailed siginfo reporting
+ *
+ *
+ */
+
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
+#include <asm/svinto.h>
+
+extern void die_if_kernel(const char *,struct pt_regs *,long);
+
+asmlinkage void do_invalid_op (struct pt_regs *, unsigned long);
+asmlinkage void do_page_fault(unsigned long address, struct pt_regs *regs,
+			      int error_code);
+
+/* debug of low-level TLB reload */
+#define D(x)
+/* debug of higher-level faults */
+#define DPG(x)
+
+/* fast TLB-fill fault handler */
+
+void
+handle_mmu_bus_fault(struct pt_regs *regs)
+{
+	int cause, select;
+	int index;
+	int page_id;
+	int miss, we, acc, inv;  
+	struct mm_struct *mm = current->active_mm;
+	pmd_t *pmd;
+	pte_t pte;
+	int errcode = 0;
+	unsigned long address;
+
+	cause = *R_MMU_CAUSE;
+	select = *R_TLB_SELECT;
+
+	address = cause & PAGE_MASK; /* get faulting address */
+	
+	page_id = IO_EXTRACT(R_MMU_CAUSE,  page_id,   cause);
+	miss    = IO_EXTRACT(R_MMU_CAUSE,  miss_excp, cause);
+	we      = IO_EXTRACT(R_MMU_CAUSE,  we_excp,   cause);
+	acc     = IO_EXTRACT(R_MMU_CAUSE,  acc_excp,  cause);
+	inv     = IO_EXTRACT(R_MMU_CAUSE,  inv_excp,  cause);  
+	index  =  IO_EXTRACT(R_TLB_SELECT, index,     select);
+	
+	D(printk("bus_fault from IRP 0x%x: addr 0x%x, miss %d, inv %d, we %d, acc %d, "
+		 "idx %d pid %d\n",
+		 regs->irp, address, miss, inv, we, acc, index, page_id));
+
+	/* for a miss, we need to reload the TLB entry */
+
+	if(miss) {
+
+		/* see if the pte exists at all */
+		
+		pmd = (pmd_t *)pgd_offset(mm, address);
+		if(pmd_none(*pmd))
+			goto dofault;
+		if(pmd_bad(*pmd)) {
+			printk("bad pgdir entry 0x%x at 0x%x\n", *pmd, pmd);
+			pmd_clear(pmd);
+			return;
+		}
+		pte = *pte_offset(pmd, address);
+		if(!pte_present(pte))
+			goto dofault;
+		
+		D(printk(" found pte %x pg %x ", pte_val(pte), pte_page(pte)));
+		D(
+		  {
+			  if(pte_val(pte) & _PAGE_SILENT_WRITE)
+				  printk("Silent-W ");
+			  if(pte_val(pte) & _PAGE_KERNEL)
+				  printk("Kernel ");
+			  if(pte_val(pte) & _PAGE_SILENT_READ)
+				  printk("Silent-R ");
+			  if(pte_val(pte) & _PAGE_GLOBAL)
+				  printk("Global ");
+			  if(pte_val(pte) & _PAGE_PRESENT)
+				  printk("Present ");
+			  if(pte_val(pte) & _PAGE_ACCESSED)
+				  printk("Accessed ");
+			  if(pte_val(pte) & _PAGE_MODIFIED)
+				  printk("Modified ");
+			  if(pte_val(pte) & _PAGE_READ)
+				  printk("Readable ");
+			  if(pte_val(pte) & _PAGE_WRITE)
+				  printk("Writeable ");
+			  printk("\n");
+		  });
+
+		/* load up the chosen TLB entry
+		 * this assumes the pte format is the same as the TLB_LO layout.
+		 *
+		 * the write to R_TLB_LO also writes the vpn and page_id fields from
+		 * R_MMU_CAUSE, which we in this case obviously want to keep
+		 */
+		
+		*R_TLB_LO = pte_val(pte);
+
+		return;
+	} 
+
+	errcode = 0x01 | (we << 1);
+
+ dofault:
+	/* leave it to the MM system fault handler below */
+	D(printk("do_page_fault %p errcode %d\n", address, errcode));
+	do_page_fault(address, regs, errcode);
+}
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * Notice that the address we're given is aligned to the page the fault
+ * occured in, since we only get the PFN in R_MMU_CAUSE not the complete
+ * address.
+ *
+ * error_code:
+ *	bit 0 == 0 means no page found, 1 means protection fault
+ *	bit 1 == 0 means read, 1 means write
+ *
+ * If this routine detects a bad access, it returns 1, otherwise it
+ * returns 0.
+ */
+
+asmlinkage void
+do_page_fault(unsigned long address, struct pt_regs *regs,
+	      int error_code)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	struct vm_area_struct * vma;
+	int writeaccess;
+	int fault;
+	unsigned long fixup;
+	siginfo_t info;
+
+	tsk = current;
+
+        /*
+         * We fault-in kernel-space virtual memory on-demand. The
+         * 'reference' page table is init_mm.pgd.
+         *
+         * NOTE! We MUST NOT take any locks for this case. We may
+         * be in an interrupt or a critical region, and should
+         * only copy the information from the master page table,
+         * nothing more.
+	 *
+	 * NOTE2: This is done so that, when updating the vmalloc
+	 * mappings we don't have to walk all processes pgdirs and
+	 * add the high mappings all at once. Instead we do it as they
+	 * are used.
+	 *
+	 * TODO: On CRIS, we have a PTE Global bit which should be set in
+	 * all the PTE's related to vmalloc in all processes - that means if
+	 * we switch process and a vmalloc PTE is still in the TLB, it won't
+	 * need to be reloaded. It's an optimization.
+	 *
+	 * Linux/CRIS's kernel is not page-mapped, so the comparision below
+	 * should really be >= VMALLOC_START, however, kernel fixup errors
+	 * will be handled more quickly by going through vmalloc_fault and then
+	 * into bad_area_nosemaphore than falling through the find_vma user-mode
+	 * tests.
+         */
+
+        if (address >= TASK_SIZE)
+                goto vmalloc_fault;
+
+	mm = tsk->mm;
+	writeaccess = error_code & 2;
+	info.si_code = SEGV_MAPERR;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+
+	if (in_interrupt() || !mm)
+		goto no_context;
+
+	down(&mm->mmap_sem);
+	vma = find_vma(mm, address);
+	if (!vma)
+		goto bad_area;
+	if (vma->vm_start <= address)
+		goto good_area;
+	if (!(vma->vm_flags & VM_GROWSDOWN))
+		goto bad_area;
+	if (user_mode(regs)) {
+		/*
+		 * accessing the stack below usp is always a bug.
+		 * we get page-aligned addresses so we can only check
+		 * if we're within a page from usp, but that might be
+		 * enough to catch brutal errors at least.
+		 */
+		if (address + PAGE_SIZE < rdusp())
+			goto bad_area;
+	}
+	if (expand_stack(vma, address))
+		goto bad_area;
+
+	/*
+	 * Ok, we have a good vm_area for this memory access, so
+	 * we can handle it..
+	 */
+
+ good_area:
+	info.si_code = SEGV_ACCERR;
+
+	/* first do some preliminary protection checks */
+
+	if (writeaccess) {
+		if (!(vma->vm_flags & VM_WRITE))
+			goto bad_area;
+	} else {
+		if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+			goto bad_area;
+	}
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+
+	switch (handle_mm_fault(mm, vma, address, writeaccess)) {
+        case 1:
+                tsk->min_flt++;
+                break;
+        case 2:
+                tsk->maj_flt++;
+                break;
+        case 0:
+                goto do_sigbus;
+        default:
+                goto out_of_memory;
+	}
+
+	up(&mm->mmap_sem);
+	return;
+	
+	/*
+	 * Something tried to access memory that isn't in our memory map..
+	 * Fix it, but check if it's kernel or user first..
+	 */
+
+ bad_area:
+
+	up(&mm->mmap_sem);
+
+ bad_area_nosemaphore:
+	DPG(show_registers(regs));
+
+	/* User mode accesses just cause a SIGSEGV */
+
+	if (user_mode(regs)) {
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		/* info.si_code has been set above */
+		info.si_addr = (void *)address;
+		force_sig_info(SIGSEGV, &info, tsk);
+		return;
+	}
+
+ no_context:
+
+	/* Are we prepared to handle this kernel fault?
+	 *
+	 * (The kernel has valid exception-points in the source 
+	 *  when it acesses user-memory. When it fails in one
+	 *  of those points, we find it in a table and do a jump
+	 *  to some fixup code that loads an appropriate error
+	 *  code)
+	 */
+
+        if ((fixup = search_exception_table(regs->irp)) != 0) {
+                regs->irp = fixup;
+		regs->frametype = CRIS_FRAME_FIXUP;
+		D(printk("doing fixup to 0x%x\n", fixup));
+                return;
+        }
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+	if ((unsigned long) (address) < PAGE_SIZE)
+		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+	else
+		printk(KERN_ALERT "Unable to handle kernel access");
+	printk(" at virtual address %08lx\n",address);
+
+	die_if_kernel("Oops", regs, error_code);
+
+	do_exit(SIGKILL);
+
+	/*
+	 * We ran out of memory, or some other thing happened to us that made
+	 * us unable to handle the page fault gracefully.
+	 */
+
+ out_of_memory:
+        up(&mm->mmap_sem);
+	printk("VM: killing process %s\n", tsk->comm);
+	if(user_mode(regs))
+		do_exit(SIGKILL);
+	goto no_context;
+
+ do_sigbus:
+	up(&mm->mmap_sem);
+
+	/*
+         * Send a sigbus, regardless of whether we were in kernel
+         * or user mode.
+         */
+	info.si_code = SIGBUS;
+	info.si_errno = 0;
+	info.si_code = BUS_ADRERR;
+	info.si_addr = (void *)address;
+	force_sig_info(SIGBUS, &info, tsk);
+	
+        /* Kernel mode? Handle exceptions or die */
+        if (!user_mode(regs))
+                goto no_context;
+        return;
+
+vmalloc_fault:
+        {
+                /*
+                 * Synchronize this task's top level page-table
+                 * with the 'reference' page table.
+                 */
+                int offset = pgd_index(address);
+                pgd_t *pgd, *pgd_k;
+                pmd_t *pmd, *pmd_k;
+
+                pgd = tsk->active_mm->pgd + offset;
+                pgd_k = init_mm.pgd + offset;
+
+                if (!pgd_present(*pgd)) {
+                        if (!pgd_present(*pgd_k))
+                                goto bad_area_nosemaphore;
+                        set_pgd(pgd, *pgd_k);
+                        return;
+                }
+
+                pmd = pmd_offset(pgd, address);
+                pmd_k = pmd_offset(pgd_k, address);
+
+                if (pmd_present(*pmd) || !pmd_present(*pmd_k))
+                        goto bad_area_nosemaphore;
+                set_pmd(pmd, *pmd_k);
+                return;
+        }
+
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/mm/init.c linux/arch/cris/mm/init.c
--- v2.4.1/linux/arch/cris/mm/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/mm/init.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,506 @@
+/*
+ *  linux/arch/cris/mm/init.c
+ *
+ *  Copyright (C) 1995  Linus Torvalds
+ *  Copyright (C) 2000  Axis Communications AB
+ *
+ *  Authors:  Bjorn Wesen (bjornw@axis.com)
+ *
+ *  $Log: init.c,v $
+ *  Revision 1.15  2001/01/10 21:12:10  bjornw
+ *  loops_per_sec -> loops_per_jiffy
+ *
+ *  Revision 1.14  2000/11/22 16:23:20  bjornw
+ *  Initialize totalhigh counters to 0 to make /proc/meminfo look nice.
+ *
+ *  Revision 1.13  2000/11/21 16:37:51  bjornw
+ *  Temporarily disable initmem freeing
+ *
+ *  Revision 1.12  2000/11/21 13:55:07  bjornw
+ *  Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
+ *
+ *  Revision 1.11  2000/10/06 12:38:22  bjornw
+ *  Cast empty_bad_page correctly (should really be of * type from the start..
+ *
+ *  Revision 1.10  2000/10/04 16:53:57  bjornw
+ *  Fix memory-map due to LX features
+ *
+ *  Revision 1.9  2000/09/13 15:47:49  bjornw
+ *  Wrong count in reserved-pages loop
+ *
+ *  Revision 1.8  2000/09/13 14:35:10  bjornw
+ *  2.4.0-test8 added a new arg to free_area_init_node
+ *
+ *  Revision 1.7  2000/08/17 15:35:55  bjornw
+ *  2.4.0-test6 removed MAP_NR and inserted virt_to_page
+ *
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/bootmem.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgalloc.h>
+#include <asm/pgtable.h>
+#include <asm/dma.h>
+#include <asm/svinto.h>
+
+static unsigned long totalram_pages;
+
+struct pgtable_cache_struct quicklists;  /* see asm/pgalloc.h */
+
+const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
+
+extern void die_if_kernel(char *,struct pt_regs *,long);
+extern void show_net_buffers(void);
+extern void tlb_init(void);
+
+/*
+ * empty_bad_page is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving a inode
+ * unused etc..
+ *
+ * the main point is that when a page table error occurs, we want to get
+ * out of the kernel safely before killing the process, so we need something
+ * to feed the MMU with when the fault occurs even if we don't have any
+ * real PTE's or page tables.
+ *
+ * empty_bad_page_table is the accompanying page-table: it is initialized
+ * to point to empty_bad_page writable-shared entries.
+ *
+ * empty_zero_page is a special page that is used for zero-initialized
+ * data and COW.
+ */
+
+unsigned long empty_bad_page_table;
+unsigned long empty_bad_page;
+unsigned long empty_zero_page;
+
+pte_t * __bad_pagetable(void)
+{
+	/* somehow it is enough to just clear it and not fill it with
+	 * bad page PTE's...
+	 */
+	memset((void *)empty_bad_page_table, 0, PAGE_SIZE);
+
+	return (pte_t *) empty_bad_page_table;
+}
+
+pte_t __bad_page(void)
+{
+
+	/* clear the empty_bad_page page. this should perhaps be
+	 * a more simple inlined loop like it is on the other 
+	 * architectures.
+	 */
+
+	memset((void *)empty_bad_page, 0, PAGE_SIZE);
+
+	return pte_mkdirty(__mk_pte((void *)empty_bad_page, PAGE_SHARED));
+}
+
+static pte_t * get_bad_pte_table(void)
+{
+	pte_t *empty_bad_pte_table = (pte_t *)empty_bad_page_table;
+	pte_t v;
+	int i;
+
+	v = __bad_page();
+
+	for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
+		empty_bad_pte_table[i] = v;
+
+	return empty_bad_pte_table;
+}
+
+void __handle_bad_pmd(pmd_t *pmd)
+{
+	pmd_ERROR(*pmd);
+	pmd_set(pmd, get_bad_pte_table());
+}
+
+void __handle_bad_pmd_kernel(pmd_t *pmd)
+{
+	pmd_ERROR(*pmd);
+	pmd_set_kernel(pmd, get_bad_pte_table());
+}
+
+pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
+{
+        pte_t *pte;
+
+        pte = (pte_t *) __get_free_page(GFP_KERNEL);
+        if (pmd_none(*pmd)) {
+                if (pte) {
+                        clear_page(pte);
+			pmd_set_kernel(pmd, pte);
+                        return pte + offset;
+                }
+		pmd_set_kernel(pmd, get_bad_pte_table());
+                return NULL;
+        }
+        free_page((unsigned long)pte);
+        if (pmd_bad(*pmd)) {
+                __handle_bad_pmd_kernel(pmd);
+                return NULL;
+        }
+        return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+	pte_t *pte;
+
+        pte = (pte_t *) __get_free_page(GFP_KERNEL);
+        if (pmd_none(*pmd)) {
+                if (pte) {
+                        clear_page(pte);
+			pmd_set(pmd, pte);
+                        return pte + offset;
+                }
+		pmd_set(pmd, get_bad_pte_table());
+                return NULL;
+        }
+        free_page((unsigned long)pte);
+        if (pmd_bad(*pmd)) {
+                __handle_bad_pmd(pmd);
+                return NULL;
+        }
+        return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+#ifndef CONFIG_NO_PGT_CACHE
+struct pgtable_cache_struct quicklists;
+
+/* trim the page-table cache if necessary */
+
+int do_check_pgt_cache(int low, int high)
+{
+        int freed = 0;
+
+        if(pgtable_cache_size > high) {
+                do {
+                        if(pgd_quicklist) {
+                                free_pgd_slow(get_pgd_fast());
+                                freed++;
+                        }
+                        if(pmd_quicklist) {
+                                free_pmd_slow(get_pmd_fast());
+                                freed++;
+                        }
+                        if(pte_quicklist) {
+                                free_pte_slow(get_pte_fast());
+                                 freed++;
+                        }
+                } while(pgtable_cache_size > low);
+        }
+        return freed;
+}
+#else
+int do_check_pgt_cache(int low, int high)
+{
+        return 0;
+}
+#endif
+
+void show_mem(void)
+{
+	int i,free = 0,total = 0,cached = 0, reserved = 0, nonshared = 0;
+	int shared = 0;
+
+	printk("\nMem-info:\n");
+	show_free_areas();
+	printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+	i = max_mapnr;
+	while (i-- > 0) {
+		total++;
+		if (PageReserved(mem_map+i))
+			reserved++;
+		else if (PageSwapCache(mem_map+i))
+			cached++;
+		else if (!page_count(mem_map+i))
+			free++;
+		else if (page_count(mem_map+i) == 1)
+			nonshared++;
+		else
+			shared += page_count(mem_map+i) - 1;
+	}
+	printk("%d pages of RAM\n",total);
+	printk("%d free pages\n",free);
+	printk("%d reserved pages\n",reserved);
+	printk("%d pages nonshared\n",nonshared);
+	printk("%d pages shared\n",shared);
+	printk("%d pages swap cached\n",cached);
+	printk("%ld pages in page table cache\n",pgtable_cache_size);
+	show_buffers();
+}
+
+/*
+ * The kernel is already mapped with a kernel segment at kseg_c so 
+ * we don't need to map it with a page table. However head.S also
+ * temporarily mapped it at kseg_4 so we should set up the ksegs again,
+ * clear the TLB and do some other paging setup stuff.
+ */
+
+void __init 
+paging_init(void)
+{
+	int i;
+	unsigned long zones_size[MAX_NR_ZONES];
+
+	printk("Setting up paging and the MMU.\n");
+	
+	/* clear out the init_mm.pgd that will contain the kernel's mappings */
+
+	for(i = 0; i < PTRS_PER_PGD; i++)
+		swapper_pg_dir[i] = __pgd(0);
+
+	/* initialise the TLB (tlb.c) */
+
+	tlb_init();
+
+	/* see README.mm for details on the KSEG setup */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+
+	/* Etrax-100 LX version 1 has a bug so that we cannot map anything
+	 * across the 0x80000000 boundary, so we need to shrink the user-virtual
+	 * area to 0x50000000 instead of 0xb0000000 and map things slightly
+	 * different. The unused areas are marked as paged so that we can catch
+	 * freak kernel accesses there.
+	 *
+	 * The Juliette chip is mapped at 0xa so we pass that segment straight
+	 * through. We cannot vremap it because the vmalloc area is below 0x8
+	 * and Juliette needs an uncached area above 0x8.
+	 */
+
+	*R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, page ) | 
+			IO_STATE(R_MMU_KSEG, seg_e, seg  ) |  /* uncached flash */
+			IO_STATE(R_MMU_KSEG, seg_d, page ) | 
+			IO_STATE(R_MMU_KSEG, seg_c, page ) | 
+			IO_STATE(R_MMU_KSEG, seg_b, seg  ) |  /* kernel reg area */
+			IO_STATE(R_MMU_KSEG, seg_a, seg  ) |  /* Juliette etc. */
+			IO_STATE(R_MMU_KSEG, seg_9, page ) |
+			IO_STATE(R_MMU_KSEG, seg_8, page ) |
+			IO_STATE(R_MMU_KSEG, seg_7, page ) |  /* kernel vmalloc area */
+			IO_STATE(R_MMU_KSEG, seg_6, seg  ) |  /* kernel DRAM area */
+			IO_STATE(R_MMU_KSEG, seg_5, seg  ) |  /* cached flash */
+			IO_STATE(R_MMU_KSEG, seg_4, page ) |  /* user area */
+			IO_STATE(R_MMU_KSEG, seg_3, page ) |  /* user area */
+			IO_STATE(R_MMU_KSEG, seg_2, page ) |  /* user area */
+			IO_STATE(R_MMU_KSEG, seg_1, page ) |  /* user area */
+			IO_STATE(R_MMU_KSEG, seg_0, page ) ); /* user area */
+
+	*R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_c, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_a, 0xa ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
+	
+	*R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_6, 0x4 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
+#else
+	/* This code is for the hopefully corrected Etrax-100 LX version 2... */
+
+	*R_MMU_KSEG = ( IO_STATE(R_MMU_KSEG, seg_f, seg  ) | /* cached flash */
+			IO_STATE(R_MMU_KSEG, seg_e, seg  ) | /* uncached flash */
+			IO_STATE(R_MMU_KSEG, seg_d, page ) | /* vmalloc area */
+			IO_STATE(R_MMU_KSEG, seg_c, seg  ) | /* kernel area */
+			IO_STATE(R_MMU_KSEG, seg_b, seg  ) | /* kernel reg area */
+			IO_STATE(R_MMU_KSEG, seg_a, page ) | /* user area */
+			IO_STATE(R_MMU_KSEG, seg_9, page ) |
+			IO_STATE(R_MMU_KSEG, seg_8, page ) |
+			IO_STATE(R_MMU_KSEG, seg_7, page ) |
+			IO_STATE(R_MMU_KSEG, seg_6, page ) |
+			IO_STATE(R_MMU_KSEG, seg_5, page ) |
+			IO_STATE(R_MMU_KSEG, seg_4, page ) |
+			IO_STATE(R_MMU_KSEG, seg_3, page ) |
+			IO_STATE(R_MMU_KSEG, seg_2, page ) |
+			IO_STATE(R_MMU_KSEG, seg_1, page ) |
+			IO_STATE(R_MMU_KSEG, seg_0, page ) );
+
+	*R_MMU_KBASE_HI = ( IO_FIELD(R_MMU_KBASE_HI, base_f, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_e, 0x8 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_d, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_c, 0x4 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_b, 0xb ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_a, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_9, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_HI, base_8, 0x0 ) );
+	
+	*R_MMU_KBASE_LO = ( IO_FIELD(R_MMU_KBASE_LO, base_7, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_6, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_5, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_4, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_3, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_2, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_1, 0x0 ) |
+			    IO_FIELD(R_MMU_KBASE_LO, base_0, 0x0 ) );
+#endif	
+
+	*R_MMU_CONTEXT = ( IO_FIELD(R_MMU_CONTEXT, page_id, 0 ) );
+	
+	/* The MMU has been enabled ever since head.S but just to make
+	 * it totally obvious we do it here as well.
+	 */
+
+	*R_MMU_CTRL = ( IO_STATE(R_MMU_CTRL, inv_excp, enable ) |
+			IO_STATE(R_MMU_CTRL, acc_excp, enable ) |
+			IO_STATE(R_MMU_CTRL, we_excp,  enable ) );
+	
+	*R_MMU_ENABLE = IO_STATE(R_MMU_ENABLE, mmu_enable, enable);
+
+	/*
+	 * initialize the bad page table and bad page to point
+	 * to a couple of allocated pages
+	 */
+
+	empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+	empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+	empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+	memset((void *)empty_zero_page, 0, PAGE_SIZE);
+
+	/* All pages are DMA'able in Etrax, so put all in the DMA'able zone */
+
+	zones_size[0] = ((unsigned long)high_memory - PAGE_OFFSET) >> PAGE_SHIFT;
+
+	for (i = 1; i < MAX_NR_ZONES; i++)
+		zones_size[i] = 0;
+
+	/* Use free_area_init_node instead of free_area_init, because the former
+	 * is designed for systems where the DRAM starts at an address substantially
+	 * higher than 0, like us (we start at PAGE_OFFSET). This saves space in the
+	 * mem_map page array.
+	 */
+
+	free_area_init_node(0, 0, 0, zones_size, PAGE_OFFSET, 0);
+}
+
+extern unsigned long loops_per_jiffy; /* init/main.c */
+unsigned long loops_per_usec;
+
+extern char _stext, _edata, _etext;
+extern char __init_begin, __init_end;
+
+void __init
+mem_init(void)
+{
+	int codesize, reservedpages, datasize, initsize;
+	unsigned long tmp;
+
+	if(!mem_map)
+		BUG();
+
+	/* max/min_low_pfn was set by setup.c
+	 * now we just copy it to some other necessary places...
+	 *
+	 * high_memory was also set in setup.c
+	 */
+
+	max_mapnr = num_physpages = max_low_pfn - min_low_pfn;
+ 
+	/* this will put all memory onto the freelists */
+        totalram_pages = free_all_bootmem();
+
+	reservedpages = 0;
+	for (tmp = 0; tmp < max_mapnr; tmp++) {
+		/*
+                 * Only count reserved RAM pages
+                 */
+		if (PageReserved(mem_map + tmp))
+			reservedpages++;
+	}
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_stext;
+        datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+        initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+	
+        printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, "
+	       "%dk init)\n" ,
+	       (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+	       max_mapnr << (PAGE_SHIFT-10),
+	       codesize >> 10,
+	       reservedpages << (PAGE_SHIFT-10),
+	       datasize >> 10,
+	       initsize >> 10
+               );
+	
+	/* HACK alert - calculate a loops_per_usec for asm/delay.h here
+	 * since this is called just after calibrate_delay in init/main.c
+	 * but before places which use udelay. cannot be in time.c since
+	 * that is called _before_ calibrate_delay
+	 */
+
+	loops_per_usec = (loops_per_jiffy * HZ) / 1000000;
+
+	return;
+}
+
+/* free the pages occupied by initialization code */
+
+void free_initmem(void)
+{
+#if 0
+	/* currently this is a bad idea since the cramfs image is catted onto
+	 * the vmlinux image, and the end of that image is not page-padded so
+	 * part of the cramfs image will be freed here
+	 */
+        unsigned long addr;
+
+        addr = (unsigned long)(&__init_begin);
+        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+                ClearPageReserved(virt_to_page(addr));
+                set_page_count(virt_to_page(addr), 1);
+                free_page(addr);
+                totalram_pages++;
+        }
+        printk ("Freeing unused kernel memory: %dk freed\n", 
+		(&__init_end - &__init_begin) >> 10);
+#endif
+}
+
+void si_meminfo(struct sysinfo *val)
+{
+	int i;
+
+	i = max_mapnr;
+	val->totalram = 0;
+	val->sharedram = 0;
+	val->freeram = nr_free_pages();
+	val->bufferram = atomic_read(&buffermem_pages);
+	while (i-- > 0)  {
+		if (PageReserved(mem_map+i))
+			continue;
+		val->totalram++;
+		if (!atomic_read(&mem_map[i].count))
+			continue;
+		val->sharedram += atomic_read(&mem_map[i].count) - 1;
+	}
+	val->mem_unit = PAGE_SIZE;
+	val->totalhigh = 0;
+	val->freehigh = 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/cris/mm/tlb.c linux/arch/cris/mm/tlb.c
--- v2.4.1/linux/arch/cris/mm/tlb.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/cris/mm/tlb.c	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,301 @@
+/*
+ *  linux/arch/cris/mm/tlb.c
+ *
+ *  Copyright (C) 2000  Axis Communications AB
+ *  
+ *  Authors:   Bjorn Wesen (bjornw@axis.com)
+ *
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/segment.h>
+#include <asm/pgtable.h>
+#include <asm/svinto.h>
+
+#define D(x)
+
+/* CRIS in Etrax100LX TLB */
+
+#define NUM_TLB_ENTRIES 64
+#define NUM_PAGEID 64
+#define INVALID_PAGEID 63
+#define NO_CONTEXT -1
+
+/* The TLB can host up to 64 different mm contexts at the same time.
+ * The running context is R_MMU_CONTEXT, and each TLB entry contains a
+ * page_id that has to match to give a hit. In page_id_map, we keep track
+ * of which mm's we have assigned which page_id's, so that we know when
+ * to invalidate TLB entries.
+ *
+ * The last page_id is never running - it is used as an invalid page_id
+ * so we can make TLB entries that will never match.
+ */
+
+struct mm_struct *page_id_map[NUM_PAGEID];
+
+static int map_replace_ptr = 1;  /* which page_id_map entry to replace next */
+
+/* invalidate all TLB entries */
+
+void
+flush_tlb_all()
+{
+	int i;
+
+	/* the vpn of i & 0xf is so we dont write similar TLB entries
+	 * in the same 4-way entry group. details.. 
+	 */
+
+	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+		*R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) );
+
+		*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+			      IO_FIELD(R_TLB_HI, vpn,     i & 0xf ) );
+		
+		*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no       ) |
+			      IO_STATE(R_TLB_LO, valid, no       ) |
+			      IO_STATE(R_TLB_LO, kernel,no	 ) |
+			      IO_STATE(R_TLB_LO, we,    no       ) |
+			      IO_FIELD(R_TLB_LO, pfn,   0        ) );
+	}
+	D(printk("tlb: flushed all\n"));
+}
+
+/* invalidate the selected mm context only */
+
+void
+flush_tlb_mm(struct mm_struct *mm)
+{
+	int i;
+	int page_id = mm->context;
+
+	D(printk("tlb: flush mm context %d (%p)\n", page_id, mm));
+
+	if(page_id == NO_CONTEXT)
+		return;
+	
+	/* mark the TLB entries that match the page_id as invalid.
+	 * here we could also check the _PAGE_GLOBAL bit and NOT flush
+	 * global pages. is it worth the extra I/O ? 
+	 */
+
+	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+		*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
+		if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) {
+			*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+				      IO_FIELD(R_TLB_HI, vpn,     i & 0xf ) );
+			
+			*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no  ) |
+				      IO_STATE(R_TLB_LO, valid, no  ) |
+				      IO_STATE(R_TLB_LO, kernel,no  ) |
+				      IO_STATE(R_TLB_LO, we,    no  ) |
+				      IO_FIELD(R_TLB_LO, pfn,   0   ) );
+		}
+	}
+}
+
+/* invalidate a single page */
+
+void
+flush_tlb_page(struct vm_area_struct *vma, 
+	       unsigned long addr)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	int page_id = mm->context;
+	int i;
+
+	D(printk("tlb: flush page %p in context %d (%p)\n", addr, page_id, mm));
+
+	if(page_id == NO_CONTEXT)
+		return;
+
+	addr &= PAGE_MASK; /* perhaps not necessary */
+
+	/* invalidate those TLB entries that match both the mm context
+	 * and the virtual address requested 
+	 */
+
+	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+		unsigned long tlb_hi;
+		*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
+		tlb_hi = *R_TLB_HI;
+		if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
+		    (tlb_hi & PAGE_MASK) == addr) {
+			*R_TLB_HI = IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+				addr; /* same addr as before works. */
+			
+			*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no  ) |
+				      IO_STATE(R_TLB_LO, valid, no  ) |
+				      IO_STATE(R_TLB_LO, kernel,no  ) |
+				      IO_STATE(R_TLB_LO, we,    no  ) |
+				      IO_FIELD(R_TLB_LO, pfn,   0   ) );
+		}
+	}
+}
+
+/* invalidate a page range */
+
+void
+flush_tlb_range(struct mm_struct *mm, 
+		unsigned long start,
+		unsigned long end)
+{
+	int page_id = mm->context;
+	int i;
+
+	D(printk("tlb: flush range %p<->%p in context %d (%p)\n",
+		 start, end, page_id, mm));
+
+	if(page_id == NO_CONTEXT)
+		return;
+
+	start &= PAGE_MASK;  /* probably not necessary */
+	end &= PAGE_MASK;    /* dito */
+
+	/* invalidate those TLB entries that match both the mm context
+	 * and the virtual address range
+	 */
+
+	for(i = 0; i < NUM_TLB_ENTRIES; i++) {
+		unsigned long tlb_hi, vpn;
+		*R_TLB_SELECT = IO_FIELD(R_TLB_SELECT, index, i);
+		tlb_hi = *R_TLB_HI;
+		vpn = tlb_hi & PAGE_MASK;
+		if (IO_EXTRACT(R_TLB_HI, page_id, tlb_hi) == page_id &&
+		    vpn >= start && vpn < end) {
+			*R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) |
+				      IO_FIELD(R_TLB_HI, vpn,     i & 0xf ) );
+			
+			*R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no  ) |
+				      IO_STATE(R_TLB_LO, valid, no  ) |
+				      IO_STATE(R_TLB_LO, kernel,no  ) |
+				      IO_STATE(R_TLB_LO, we,    no  ) |
+				      IO_FIELD(R_TLB_LO, pfn,   0   ) );
+		}
+	}
+}
+
+/*
+ * Initialize the context related info for a new mm_struct
+ * instance.
+ */
+
+int
+init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+{
+	mm->context = NO_CONTEXT;
+	return 0;
+}
+
+/* the following functions are similar to those used in the PPC port */
+
+static inline void
+alloc_context(struct mm_struct *mm)
+{
+	struct mm_struct *old_mm;
+
+	D(printk("tlb: alloc context %d (%p)\n", map_replace_ptr, mm));
+
+	/* did we replace an mm ? */
+
+	old_mm = page_id_map[map_replace_ptr];
+
+	if(old_mm) {
+		/* throw out any TLB entries belonging to the mm we replace
+		 * in the map
+		 */
+		flush_tlb_mm(old_mm);
+
+		old_mm->context = NO_CONTEXT;
+	}
+
+	/* insert it into the page_id_map */
+
+	mm->context = map_replace_ptr;
+	page_id_map[map_replace_ptr] = mm;
+
+	map_replace_ptr++;
+
+	if(map_replace_ptr == INVALID_PAGEID)
+		map_replace_ptr = 0;         /* wrap around */
+	
+}
+
+/* 
+ * if needed, get a new MMU context for the mm. otherwise nothing is done.
+ */
+
+void
+get_mmu_context(struct mm_struct *mm)
+{
+	if(mm->context == NO_CONTEXT)
+		alloc_context(mm);
+}
+
+/* called in schedule() just before actually doing the switch_to */
+
+void 
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk, int cpu)
+{
+	/* make sure we have a context */
+
+	get_mmu_context(next);
+
+	/* switch context in the MMU */
+	
+	D(printk("switching mmu_context to %d (%p)\n", next->context, next));
+
+	*R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context);
+}
+
+
+/* called by __exit_mm to destroy the used MMU context if any before
+ * destroying the mm itself. this is only called when the last user of the mm
+ * drops it.
+ *
+ * the only thing we really need to do here is mark the used PID slot
+ * as empty.
+ */
+
+void
+destroy_context(struct mm_struct *mm)
+{
+	if(mm->context != NO_CONTEXT) {
+		D(printk("destroy_context %d (%p)\n", mm->context, mm));
+		flush_tlb_mm(mm);  /* TODO this might be redundant ? */
+		page_id_map[mm->context] = NULL;
+		/* mm->context = NO_CONTEXT; redundant.. mm will be freed */
+	}
+}
+
+/* called once during VM initialization, from init.c */
+
+void __init
+tlb_init(void)
+{
+	int i;
+
+	/* clear the page_id map */
+
+	for(i = 0; i < 64; i++)
+		page_id_map[i] = NULL;
+	
+	/* invalidate the entire TLB */
+
+	flush_tlb_all();
+
+	/* the init_mm has context 0 from the boot */
+
+	page_id_map[0] = &init_mm;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/i386/boot/compressed/misc.c linux/arch/i386/boot/compressed/misc.c
--- v2.4.1/linux/arch/i386/boot/compressed/misc.c	Mon Jul 31 10:48:17 2000
+++ linux/arch/i386/boot/compressed/misc.c	Tue Feb 13 13:15:04 2001
@@ -10,6 +10,7 @@
  */
 
 #include <linux/vmalloc.h>
+#include <linux/tty.h>
 #include <asm/io.h>
 /*
  * gzip declarations
diff -u --recursive --new-file v2.4.1/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.4.1/linux/arch/i386/defconfig	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/defconfig	Mon Feb 19 17:10:28 2001
@@ -162,6 +162,11 @@
 # CONFIG_BRIDGE is not set
 
 #
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
 # Telephony Support
 #
 # CONFIG_PHONE is not set
@@ -628,6 +633,8 @@
 CONFIG_SOUND_ES1371=y
 # CONFIG_SOUND_ESSSOLO1 is not set
 # CONFIG_SOUND_MAESTRO is not set
+# CONFIG_SOUND_MAESTRO3 is not set
+# CONFIG_SOUND_ICH is not set
 # CONFIG_SOUND_SONICVIBES is not set
 # CONFIG_SOUND_TRIDENT is not set
 # CONFIG_SOUND_MSNDCLAS is not set
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/apm.c linux/arch/i386/kernel/apm.c
--- v2.4.1/linux/arch/i386/kernel/apm.c	Wed Dec  6 21:00:12 2000
+++ linux/arch/i386/kernel/apm.c	Fri Feb  9 11:29:44 2001
@@ -176,7 +176,7 @@
 #include <linux/stddef.h>
 #include <linux/timer.h>
 #include <linux/fcntl.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 #include <linux/miscdevice.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/dmi_scan.c linux/arch/i386/kernel/dmi_scan.c
--- v2.4.1/linux/arch/i386/kernel/dmi_scan.c	Fri Dec 29 14:07:20 2000
+++ linux/arch/i386/kernel/dmi_scan.c	Tue Feb 13 14:13:43 2001
@@ -12,6 +12,8 @@
 	u16	handle;
 };
 
+#define dmi_printk(x)
+
 static char * __init dmi_string(struct dmi_header *dm, u8 s)
 {
 	u8 *bp=(u8 *)dm;
@@ -73,13 +75,13 @@
 			u16 len=buf[7]<<8|buf[6];
 			u32 base=buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8];
 
-			printk(KERN_INFO "DMI %d.%d present.\n",
-				buf[14]>>4, buf[14]&0x0F);
-			printk(KERN_INFO "%d structures occupying %d bytes.\n",
+			dmi_printk((KERN_INFO "DMI %d.%d present.\n",
+				buf[14]>>4, buf[14]&0x0F));
+			dmi_printk((KERN_INFO "%d structures occupying %d bytes.\n",
 				buf[13]<<8|buf[12],
-				buf[7]<<8|buf[6]);
-			printk(KERN_INFO "DMI table at 0x%08X.\n",
-				buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]);
+				buf[7]<<8|buf[6]));
+			dmi_printk((KERN_INFO "DMI table at 0x%08X.\n",
+				buf[11]<<24|buf[10]<<16|buf[9]<<8|buf[8]));
 			if(dmi_table(base,len, num, decode)==0)
 				return 0;
 		}
@@ -106,11 +108,11 @@
 
 			if(*p && *p!=' ')
 			{
-				printk("BIOS Vendor: %s\n", p);
-				printk("BIOS Version: %s\n", 
-					dmi_string(dm, data[5]));
-				printk("BIOS Release: %s\n",
-					dmi_string(dm, data[8]));
+				dmi_printk(("BIOS Vendor: %s\n", p));
+				dmi_printk(("BIOS Version: %s\n", 
+					dmi_string(dm, data[5])));
+				dmi_printk(("BIOS Release: %s\n",
+					dmi_string(dm, data[8])));
 			}
 				
 			/*
@@ -144,13 +146,13 @@
 
 			if(*p && *p!=' ')
 			{
-				printk("System Vendor: %s.\n",p);
-				printk("Product Name: %s.\n",
-					dmi_string(dm, data[5]));
-				printk("Version %s.\n",
-					dmi_string(dm, data[6]));
-				printk("Serial Number %s.\n",
-					dmi_string(dm, data[7]));
+				dmi_printk(("System Vendor: %s.\n",p));
+				dmi_printk(("Product Name: %s.\n",
+					dmi_string(dm, data[5])));
+				dmi_printk(("Version %s.\n",
+					dmi_string(dm, data[6])));
+				dmi_printk(("Serial Number %s.\n",
+					dmi_string(dm, data[7])));
 			}
 			break;
 		case 2:
@@ -158,17 +160,17 @@
 
 			if(*p && *p!=' ')
 			{
-				printk("Board Vendor: %s.\n",p);
-				printk("Board Name: %s.\n",
-				dmi_string(dm, data[5]));
-				printk("Board Version: %s.\n",
-					dmi_string(dm, data[6]));
+				dmi_printk(("Board Vendor: %s.\n",p));
+				dmi_printk(("Board Name: %s.\n",
+					dmi_string(dm, data[5])));
+				dmi_printk(("Board Version: %s.\n",
+					dmi_string(dm, data[6])));
 			}
 			break;
 		case 3:
 			p=dmi_string(dm,data[8]);
 			if(*p && *p!=' ')
-				printk("Asset Tag: %s.\n", p);
+				dmi_printk(("Asset Tag: %s.\n", p));
 			break;
 	}
 }
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/head.S linux/arch/i386/kernel/head.S
--- v2.4.1/linux/arch/i386/kernel/head.S	Tue Nov 28 22:43:39 2000
+++ linux/arch/i386/kernel/head.S	Fri Feb 16 15:53:08 2001
@@ -34,7 +34,7 @@
 #define X86_HARD_MATH	CPU_PARAMS+6
 #define X86_CPUID	CPU_PARAMS+8
 #define X86_CAPABILITY	CPU_PARAMS+12
-#define X86_VENDOR_ID	CPU_PARAMS+16
+#define X86_VENDOR_ID	CPU_PARAMS+28
 
 /*
  * swapper_pg_dir is the main page directory, address 0x00101000
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.4.1/linux/arch/i386/kernel/i386_ksyms.c	Wed Dec  6 21:00:12 2000
+++ linux/arch/i386/kernel/i386_ksyms.c	Tue Feb 13 13:15:04 2001
@@ -13,6 +13,7 @@
 #include <linux/apm_bios.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
+#include <linux/tty.h>
 
 #include <asm/semaphore.h>
 #include <asm/processor.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c
--- v2.4.1/linux/arch/i386/kernel/i387.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/i387.c	Sat Feb  3 12:09:34 2001
@@ -216,7 +216,7 @@
 void set_fpu_mxcsr( struct task_struct *tsk, unsigned short mxcsr )
 {
 	if ( cpu_has_xmm ) {
-		tsk->thread.i387.fxsave.mxcsr = mxcsr;
+		tsk->thread.i387.fxsave.mxcsr = (mxcsr & 0xffbf);
 	}
 }
 
@@ -354,6 +354,8 @@
 	if ( __copy_from_user( &tsk->thread.i387.fxsave, &buf->_fxsr_env[0],
 			       sizeof(struct i387_fxsave_struct) ) )
 		return 1;
+	/* mxcsr bit 6 and 31-16 must be zero for security reasons */
+	tsk->thread.i387.fxsave.mxcsr &= 0xffbf;
 	return convert_fxsr_from_user( &tsk->thread.i387.fxsave, buf );
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/i8259.c linux/arch/i386/kernel/i8259.c
--- v2.4.1/linux/arch/i386/kernel/i8259.c	Sat Nov 18 20:54:39 2000
+++ linux/arch/i386/kernel/i8259.c	Fri Feb  9 11:29:44 2001
@@ -6,7 +6,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/io_apic.c linux/arch/i386/kernel/io_apic.c
--- v2.4.1/linux/arch/i386/kernel/io_apic.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/io_apic.c	Fri Feb  9 11:28:31 2001
@@ -1509,15 +1509,16 @@
  * - IRQ2 is the cascade IRQ, and cannot be a io-apic IRQ.
  *   Linux doesn't really care, as it's not actually used
  *   for any interrupt handling anyway.
- * - IRQ13 is the FPU error IRQ, and may be connected
- *   directly from the FPU to the old PIC. Linux doesn't
- *   really care, because Linux doesn't want to use IRQ13
- *   anyway (exception 16 is the proper FPU error signal)
+ * - There used to be IRQ13 here as well, but all
+ *   MPS-compliant must not use it for FPU coupling and we
+ *   want to use exception 16 anyway.  And there are
+ *   systems who connect it to an I/O APIC for other uses.
+ *   Thus we don't mark it special any longer.
  *
  * Additionally, something is definitely wrong with irq9
  * on PIIX4 boards.
  */
-#define PIC_IRQS	((1<<2)|(1<<13))
+#define PIC_IRQS	(1<<2)
 
 void __init setup_IO_APIC(void)
 {
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.4.1/linux/arch/i386/kernel/irq.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/i386/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
@@ -312,6 +312,7 @@
 		/* Uhhuh.. Somebody else got it. Wait.. */
 		do {
 			do {
+				rep_nop();
 			} while (test_bit(0,&global_irq_lock));
 		} while (test_and_set_bit(0,&global_irq_lock));		
 	}
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/microcode.c linux/arch/i386/kernel/microcode.c
--- v2.4.1/linux/arch/i386/kernel/microcode.c	Mon Dec 11 13:42:08 2000
+++ linux/arch/i386/kernel/microcode.c	Fri Feb  9 11:29:44 2001
@@ -52,7 +52,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/miscdevice.h>
 #include <linux/devfs_fs_kernel.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/mtrr.c linux/arch/i386/kernel/mtrr.c
--- v2.4.1/linux/arch/i386/kernel/mtrr.c	Tue Nov 28 22:34:01 2000
+++ linux/arch/i386/kernel/mtrr.c	Fri Feb  9 11:29:44 2001
@@ -241,7 +241,7 @@
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/pci-irq.c linux/arch/i386/kernel/pci-irq.c
--- v2.4.1/linux/arch/i386/kernel/pci-irq.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/pci-irq.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/pci-pc.c linux/arch/i386/kernel/pci-pc.c
--- v2.4.1/linux/arch/i386/kernel/pci-pc.c	Thu Jun 22 07:17:16 2000
+++ linux/arch/i386/kernel/pci-pc.c	Thu Feb  8 11:36:58 2001
@@ -843,30 +843,40 @@
 	pcibios_last_bus = -1;
 }
 
+/*
+ * ServerWorks host bridges -- Find and scan all secondary buses.
+ * Register 0x44 contains first, 0x45 last bus number routed there.
+ */
 static void __init pci_fixup_serverworks(struct pci_dev *d)
 {
-	/*
-	 * ServerWorks host bridges -- Find and scan all secondary buses.
-	 * Register 0x44 contains first, 0x45 last bus number routed there.
-	 */
-	u8 busno;
-	pci_read_config_byte(d, 0x44, &busno);
-	printk("PCI: ServerWorks host bridge: secondary bus %02x\n", busno);
-	pci_scan_bus(busno, pci_root_ops, NULL);
-	pcibios_last_bus = -1;
+	u8 busno1, busno2;
+
+	pci_read_config_byte(d, 0x44, &busno1);
+	pci_read_config_byte(d, 0x45, &busno2);
+	if (busno2 < busno1)
+		busno2 = busno1;
+	if (busno2 > pcibios_last_bus) {
+		pcibios_last_bus = busno2;
+		printk("PCI: ServerWorks host bridge: last bus %02x\n", pcibios_last_bus);
+	}
 }
 
+/*	
+ * Compaq host bridges -- Find and scan all secondary buses.
+ * This time registers 0xc8 and 0xc9.
+ */
 static void __init pci_fixup_compaq(struct pci_dev *d)
 {
-	/*	
-	 * Compaq host bridges -- Find and scan all secondary buses.
-	 * This time registers 0xc8 and 0xc9.
-	 */
-	u8 busno;
-	pci_read_config_byte(d, 0xc8, &busno);
-	printk("PCI: Compaq host bridge: secondary bus %02x\n", busno);
-	pci_scan_bus(busno, pci_root_ops, NULL);
-	pcibios_last_bus = -1;
+	u8 busno1, busno2;
+
+	pci_read_config_byte(d, 0xc8, &busno1);
+	pci_read_config_byte(d, 0xc9, &busno2);
+	if (busno2 < busno1)
+		busno2 = busno1;
+	if (busno2 > pcibios_last_bus) {
+		pcibios_last_bus = busno2;
+		printk("PCI: Compaq host bridge: last bus %02x\n", busno2);
+	}
 }
 
 static void __init pci_fixup_umc_ide(struct pci_dev *d)
@@ -924,6 +934,22 @@
 	pcibios_max_latency = 32;
 }
 
+static void __init pci_fixup_vt8363(struct pci_dev *d)
+{
+	/*
+	 *  VIA VT8363 host bridge has broken feature 'PCI Master Read
+	 *  Caching'. It caches more than is good for it, sometimes
+	 *  serving the bus master with stale data. Some BIOSes enable
+	 *  it by default, so we disable it.
+	 */
+	u8 tmp;
+	pci_read_config_byte(d, 0x70, &tmp);
+	if(tmp & 4) {
+		printk("PCI: Bus master read caching disabled\n");
+		pci_write_config_byte(d, 0x70, tmp & ~4);
+	}
+}
+
 struct pci_fixup pcibios_fixups[] = {
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82451NX,	pci_fixup_i450nx },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82454GX,	pci_fixup_i450gx },
@@ -936,6 +962,7 @@
 	{ PCI_FIXUP_HEADER,	PCI_ANY_ID,		PCI_ANY_ID,			pci_fixup_ide_bases },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5597,		pci_fixup_latency },
 	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_SI,	PCI_DEVICE_ID_SI_5598,		pci_fixup_latency },
+	{ PCI_FIXUP_HEADER,	PCI_VENDOR_ID_VIA,	PCI_DEVICE_ID_VIA_8363_0,	pci_fixup_vt8363 },
 	{ 0 }
 };
 
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.4.1/linux/arch/i386/kernel/process.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/i386/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -23,7 +23,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.4.1/linux/arch/i386/kernel/setup.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/setup.c	Fri Feb 16 16:02:37 2001
@@ -71,7 +71,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
@@ -1104,6 +1104,9 @@
 /*
  * Cx86_dir0_msb is a HACK needed by check_cx686_cpuid/slop in bugs.h in
  * order to identify the Cyrix CPU model after we're out of setup.c
+ *
+ * Actually since bugs.h doesnt even reference this perhaps someone should
+ * fix the documentation ???
  */
 unsigned char Cx86_dir0_msb __initdata = 0;
 
@@ -1129,6 +1132,8 @@
  * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old
  * BIOSes for compatability with DOS games.  This makes the udelay loop
  * work correctly, and improves performance.
+ *
+ * FIXME: our newer udelay uses the tsc. We dont need to frob with SLOP
  */
 
 extern void calibrate_delay(void) __init;
@@ -1401,6 +1406,7 @@
 					wrmsr (0x1107, lo, hi);
 
 					set_bit(X86_FEATURE_CX8, &c->x86_capability);
+					set_bit(X86_FEATURE_3DNOW, &c->x86_capability);
 
 					get_model_name(c);
 					display_cacheinfo(c);
@@ -1565,12 +1571,10 @@
 				case 4:
 					if ( c->x86 > 6 && dl ) {
 						/* P4 family */
-						if ( dl ) {
-							/* L3 cache */
-							cs = 128 << (dl-1);
-							l3 += cs;
-							break;
-						}
+						/* L3 cache */
+						cs = 128 << (dl-1);
+						l3 += cs;
+						break;
 					}
 					/* else same as 8 - fall through */
 				case 8:
@@ -1870,8 +1874,34 @@
 
 	/* Detect Cyrix with disabled CPUID */
 	if ( c->x86 == 4 && test_cyrix_52div() ) {
+		unsigned char dir0, dir1;
+		
 		strcpy(c->x86_vendor_id, "CyrixInstead");
 	        c->x86_vendor = X86_VENDOR_CYRIX;
+	        
+	        /* Actually enable cpuid on the older cyrix */
+	    
+	    	/* Retrieve CPU revisions */
+	    	
+		do_cyrix_devid(&dir0, &dir1);
+
+		dir0>>=4;		
+		
+		/* Check it is an affected model */
+		
+   	        if (dir0 == 5 || dir0 == 3)
+   	        {
+			unsigned char ccr3, ccr4;
+
+			printk(KERN_INFO "Enabling CPUID on Cyrix processor.\n");
+			cli();
+			ccr3 = getCx86(CX86_CCR3);
+			setCx86(CX86_CCR3, (ccr3 & 0x0f) | 0x10); /* enable MAPEN  */
+			ccr4 = getCx86(CX86_CCR4);
+			setCx86(CX86_CCR4, ccr4 | 0x80);          /* enable cpuid  */
+			setCx86(CX86_CCR3, ccr3);                 /* disable MAPEN */
+			sti();
+		}
 	} else
 
 	/* Detect NexGen with old hypercode */
@@ -1914,7 +1944,6 @@
 		      (int *)&c->x86_vendor_id[4]);
 		
 		get_cpu_vendor(c);
-
 		/* Initialize the standard set of capabilities */
 		/* Note that the vendor-specific code below might override */
 
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/signal.c linux/arch/i386/kernel/signal.c
--- v2.4.1/linux/arch/i386/kernel/signal.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/signal.c	Tue Feb 13 13:15:04 2001
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
+#include <linux/tty.h>
 #include <asm/ucontext.h>
 #include <asm/uaccess.h>
 #include <asm/i387.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.4.1/linux/arch/i386/kernel/smp.c	Fri Dec 29 14:35:47 2000
+++ linux/arch/i386/kernel/smp.c	Tue Feb 13 14:13:43 2001
@@ -4,7 +4,7 @@
  *	(c) 1995 Alan Cox, Building #3 <alan@redhat.com>
  *	(c) 1998-99, 2000 Ingo Molnar <mingo@redhat.com>
  *
- *	This code is released under the GNU public license version 2 or
+ *	This code is released under the GNU General Public License version 2 or
  *	later.
  */
 
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/smpboot.c linux/arch/i386/kernel/smpboot.c
--- v2.4.1/linux/arch/i386/kernel/smpboot.c	Sun Dec 31 10:26:18 2000
+++ linux/arch/i386/kernel/smpboot.c	Tue Feb 13 14:13:43 2001
@@ -11,7 +11,7 @@
  *	Pentium Pro and Pentium-II/Xeon MP machines.
  *	Original development of Linux SMP code supported by Caldera.
  *
- *	This code is released under the GNU public license version 2 or
+ *	This code is released under the GNU General Public License version 2 or
  *	later.
  *
  *	Fixes
@@ -389,6 +389,7 @@
 		 */
 		if (test_bit(cpuid, &cpu_callout_map))
 			break;
+		rep_nop();
 	}
 
 	if (!time_before(jiffies, timeout)) {
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.4.1/linux/arch/i386/kernel/traps.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/i386/kernel/traps.c	Tue Feb 13 14:15:04 2001
@@ -127,6 +127,11 @@
 	printk("\n");
 }
 
+void show_trace_task(struct task_struct *tsk)
+{
+	show_trace(&tsk->thread.esp);
+}
+
 void show_stack(unsigned long * esp)
 {
 	unsigned long *stack;
diff -u --recursive --new-file v2.4.1/linux/arch/i386/kernel/visws_apic.c linux/arch/i386/kernel/visws_apic.c
--- v2.4.1/linux/arch/i386/kernel/visws_apic.c	Thu Jul 13 09:29:34 2000
+++ linux/arch/i386/kernel/visws_apic.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/arch/i386/mm/extable.c linux/arch/i386/mm/extable.c
--- v2.4.1/linux/arch/i386/mm/extable.c	Wed Nov 10 08:31:37 1999
+++ linux/arch/i386/mm/extable.c	Fri Feb 16 16:02:37 2001
@@ -4,6 +4,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
 extern const struct exception_table_entry __start___ex_table[];
@@ -30,26 +31,32 @@
         return 0;
 }
 
+extern spinlock_t modlist_lock;
+
 unsigned long
 search_exception_table(unsigned long addr)
 {
-	unsigned long ret;
-
+	unsigned long ret = 0;
+	unsigned long flags;
+	
 #ifndef CONFIG_MODULES
 	/* There is only the kernel to search.  */
 	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-	if (ret) return ret;
+	return ret;
 #else
 	/* The kernel is the last "module" -- no need to treat it special.  */
 	struct module *mp;
+
+	spin_lock_irqsave(&modlist_lock, flags);
 	for (mp = module_list; mp != NULL; mp = mp->next) {
 		if (mp->ex_table_start == NULL)
 			continue;
 		ret = search_one_table(mp->ex_table_start,
 				       mp->ex_table_end - 1, addr);
-		if (ret) return ret;
+		if (ret)
+			break;
 	}
+	spin_unlock_irqrestore(&modlist_lock, flags);
+	return ret;
 #endif
-
-	return 0;
 }
diff -u --recursive --new-file v2.4.1/linux/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- v2.4.1/linux/arch/i386/mm/fault.c	Sat Nov 11 19:01:11 2000
+++ linux/arch/i386/mm/fault.c	Tue Feb 13 14:13:43 2001
@@ -81,7 +81,7 @@
 
 /*
  * Unlock any spinlocks which will prevent us from getting the
- * message out (timerlist_lock is aquired through the
+ * message out (timerlist_lock is acquired through the
  * console unblank code)
  */
 void bust_spinlocks(void)
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/config.in linux/arch/ia64/config.in
--- v2.4.1/linux/arch/ia64/config.in	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/config.in	Fri Feb 16 15:53:08 2001
@@ -70,7 +70,7 @@
 	if [ "$CONFIG_ITANIUM_BSTEP_SPECIFIC" = "y" ]; then
 	  bool '    Enable Itanium B0-step specific code' CONFIG_ITANIUM_B0_SPECIFIC
 	fi
-	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN1_SIM n
+	bool '  Enable SGI Medusa Simulator Support' CONFIG_IA64_SGI_SN1_SIM
 	define_bool CONFIG_DEVFS_DEBUG y
 	define_bool CONFIG_DEVFS_FS y
 	define_bool CONFIG_IA64_BRL_EMU y
@@ -79,8 +79,8 @@
 	define_bool CONFIG_SGI_IOC3_ETH y
 	define_bool CONFIG_PERCPU_IRQ y
 	define_int  CONFIG_CACHE_LINE_SHIFT 7
-	bool '  Enable DISCONTIGMEM support' CONFIG_DISCONTIGMEM y
-	bool '	Enable NUMA support' CONFIG_NUMA y
+	bool '  Enable DISCONTIGMEM support' CONFIG_DISCONTIGMEM
+	bool '	Enable NUMA support' CONFIG_NUMA
 fi
 
 define_bool CONFIG_KCORE_ELF y	# On IA-64, we always want an ELF /proc/kcore.
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/ia32/sys_ia32.c linux/arch/ia64/ia32/sys_ia32.c
--- v2.4.1/linux/arch/ia64/ia32/sys_ia32.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/ia64/ia32/sys_ia32.c	Fri Feb  9 11:29:44 2001
@@ -31,7 +31,7 @@
 #include <linux/msg.h>
 #include <linux/mm.h>
 #include <linux/shm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/uio.h>
 #include <linux/nfs_fs.h>
 #include <linux/smb_fs.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/kernel/irq.c linux/arch/ia64/kernel/irq.c
--- v2.4.1/linux/arch/ia64/kernel/irq.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -25,7 +25,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/kernel/irq_ia64.c linux/arch/ia64/kernel/irq_ia64.c
--- v2.4.1/linux/arch/ia64/kernel/irq_ia64.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/irq_ia64.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel_stat.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ptrace.h>
 #include <linux/random.h>	/* for rand_initialize_irq() */
 #include <linux/signal.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/kernel/palinfo.c linux/arch/ia64/kernel/palinfo.c
--- v2.4.1/linux/arch/ia64/kernel/palinfo.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/kernel/palinfo.c	Fri Feb 16 15:53:08 2001
@@ -23,9 +23,6 @@
 #include <linux/proc_fs.h>
 #include <linux/mm.h>
 #include <linux/module.h>
-#if defined(MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <asm/pal.h>
 #include <asm/sal.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/kernel/pci.c linux/arch/ia64/kernel/pci.c
--- v2.4.1/linux/arch/ia64/kernel/pci.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/pci.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/spinlock.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/kernel/ptrace.c linux/arch/ia64/kernel/ptrace.c
--- v2.4.1/linux/arch/ia64/kernel/ptrace.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/ptrace.c	Tue Feb 13 14:13:43 2001
@@ -447,7 +447,7 @@
  * When new_bsp is zero and force_loadrs_to_zero is 1 (non-zero),
  * loadrs is set to 0, and the bspstore value is set to the old bsp
  * value.  This will cause the stacked registers (r32 and up) to be
- * obtained entirely from the the child's memory space rather than
+ * obtained entirely from the child's memory space rather than
  * from the kernel.  (This makes it easier to write code for
  * modifying the stacked registers in multi-threaded programs.)
  *
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/kernel/unwind.c linux/arch/ia64/kernel/unwind.c
--- v2.4.1/linux/arch/ia64/kernel/unwind.c	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/kernel/unwind.c	Tue Feb 13 14:13:43 2001
@@ -5,7 +5,7 @@
 /*
  * This file implements call frame unwind support for the Linux
  * kernel.  Parsing and processing the unwind information is
- * time-consuming, so this implementation translates the the unwind
+ * time-consuming, so this implementation translates the unwind
  * descriptors into unwind scripts.  These scripts are very simple
  * (basically a sequence of assignments) and efficient to execute.
  * They are cached for later re-use.  Each script is specific for a
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/lib/copy_user.S linux/arch/ia64/lib/copy_user.S
--- v2.4.1/linux/arch/ia64/lib/copy_user.S	Thu Jan  4 12:50:17 2001
+++ linux/arch/ia64/lib/copy_user.S	Tue Feb 13 14:13:43 2001
@@ -518,7 +518,7 @@
 	// Other key point:
 	// 	- if you fail on the ld8 in the head, it means you went straight
 	//	  to it, i.e. 8byte alignment within an unexisting page.
-	// Again this comes from the fact that if you crossed just for the the ld8 then
+	// Again this comes from the fact that if you crossed just for the ld8 then
 	// you are 8byte aligned but also 16byte align, therefore you would
 	// either go for the 16byte copy loop OR the ld8 in the tail part.
 	// The combination ld1, ld2, ld4, ld8 where you fail on ld8 is impossible
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/sn/io/klconflib.c linux/arch/ia64/sn/io/klconflib.c
--- v2.4.1/linux/arch/ia64/sn/io/klconflib.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/klconflib.c	Fri Feb 16 16:02:34 2001
@@ -511,7 +511,7 @@
 				moduleid_t kgm, pkgm;
 				int	kgs, pkgs;
 
-#if defined(DEBUG) && (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1 || defined(CONFIG_IA64_GENERIC))) && defined(BRINGUP)
+#if defined(DEBUG) && (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && defined(BRINGUP)
 				printf("find_gfxpipe(): PIPE: %s mod %M slot %d\n",lb?lb->brd_name:"!LBRD",
 					lb->brd_module,lb->brd_slot);
 #endif
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/sn/io/klgraph_hack.c linux/arch/ia64/sn/io/klgraph_hack.c
--- v2.4.1/linux/arch/ia64/sn/io/klgraph_hack.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/klgraph_hack.c	Fri Feb 16 16:02:34 2001
@@ -139,7 +139,7 @@
 	uint64_t	*tmp;
 	volatile u32	*tmp32;
 
-#ifdef 0
+#if 0
 	/* Preset some values */
 	/* Write IOERR clear to clear the CRAZY bit in the status */
 	tmp = (uint64_t *)0xc0000a0001c001f8; *tmp = (uint64_t)0xffffffff;
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/sn/io/l1.c linux/arch/ia64/sn/io/l1.c
--- v2.4.1/linux/arch/ia64/sn/io/l1.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/l1.c	Tue Feb 13 14:13:43 2001
@@ -1462,7 +1462,7 @@
 	isr_reg = READ_L1_UART_REG(sc->nasid, REG_ISR);
     }
 
-    /* uart interrupts were blocked at bedrock when the the interrupt
+    /* uart interrupts were blocked at bedrock when the interrupt
      * was initially answered; reenable them now
      */
     intr_unblock_bit( sc->intr_cpu, UART_INTR );
@@ -2865,7 +2865,7 @@
 
 
 /*
- * _elscuart_flush flushes queued output to the the L1.
+ * _elscuart_flush flushes queued output to the L1.
  * This routine blocks until the queue is flushed.
  */
 int
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/sn/io/pcibr.c linux/arch/ia64/sn/io/pcibr.c
--- v2.4.1/linux/arch/ia64/sn/io/pcibr.c	Thu Jan  4 15:25:55 2001
+++ linux/arch/ia64/sn/io/pcibr.c	Fri Feb 16 16:02:34 2001
@@ -3753,7 +3753,7 @@
 	 * completion interrupts will reach a CPU
 	 * after all DMA data has reached memory.
 	 * (Of course, there may be a few special
-	 * drivers/controlers that explicitly manage
+	 * drivers/controllers that explicitly manage
 	 * this ordering problem.)
 	 */
 
@@ -8609,7 +8609,7 @@
 			BRIDGE_ERRUPPR_ADDRMASK) << 32)));
 
     /*
-     * need to ensure that the xtalk adress in ioe
+     * need to ensure that the xtalk address in ioe
      * maps to PCI error address read from bridge.
      * How to convert PCI address back to Xtalk address ?
      * (better idea: convert XTalk address to PCI address
@@ -9108,7 +9108,7 @@
 
 #ifdef LITTLE_ENDIAN
 /*
- * on sn-ia we need to twiddle the the addresses going out
+ * on sn-ia we need to twiddle the addresses going out
  * the pci bus because we use the unswizzled synergy space
  * (the alternative is to use the swizzled synergy space
  * and byte swap the data)
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/sn/io/xbow.c linux/arch/ia64/sn/io/xbow.c
--- v2.4.1/linux/arch/ia64/sn/io/xbow.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/xbow.c	Tue Feb 13 14:13:43 2001
@@ -314,7 +314,7 @@
 
     /*
      * get the name of this xbow vertex and keep the info.
-     * This is needed during errors and interupts, but as
+     * This is needed during errors and interrupts, but as
      * long as we have it, we can use it elsewhere.
      */
     s = dev_to_name(vhdl, devnm, MAXDEVNAME);
diff -u --recursive --new-file v2.4.1/linux/arch/ia64/sn/io/xtalk.c linux/arch/ia64/sn/io/xtalk.c
--- v2.4.1/linux/arch/ia64/sn/io/xtalk.c	Thu Jan  4 13:00:15 2001
+++ linux/arch/ia64/sn/io/xtalk.c	Tue Feb 13 14:13:43 2001
@@ -959,7 +959,7 @@
     widget_info->w_einfo = 0;
     /*
      * get the name of this xwidget vertex and keep the info.
-     * This is needed during errors and interupts, but as
+     * This is needed during errors and interrupts, but as
      * long as we have it, we can use it elsewhere.
      */
     s = dev_to_name(widget,devnm,MAXDEVNAME);
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/atari/hades-pci.c linux/arch/m68k/atari/hades-pci.c
--- v2.4.1/linux/arch/m68k/atari/hades-pci.c	Wed Jan 26 12:44:20 2000
+++ linux/arch/m68k/atari/hades-pci.c	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
 
 #if defined(CONFIG_PCI) && defined(CONFIG_HADES)
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 
@@ -372,6 +372,8 @@
 	 */
 
 	bus = kmalloc(sizeof(struct pci_bus_info), GFP_KERNEL);
+	if (!bus)
+		return NULL;
 	memset(bus, 0, sizeof(struct pci_bus_info));
 
 	/*
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/atari/stram.c linux/arch/m68k/atari/stram.c
--- v2.4.1/linux/arch/m68k/atari/stram.c	Mon Nov 27 17:57:34 2000
+++ linux/arch/m68k/atari/stram.c	Fri Feb  9 11:29:44 2001
@@ -16,7 +16,7 @@
 #include <linux/major.h>
 #include <linux/init.h>
 #include <linux/swap.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/shm.h>
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/bvme6000/rtc.c linux/arch/m68k/bvme6000/rtc.c
--- v2.4.1/linux/arch/m68k/bvme6000/rtc.c	Wed Jul 12 21:58:42 2000
+++ linux/arch/m68k/bvme6000/rtc.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/ifpsp060/src/fplsp.S linux/arch/m68k/ifpsp060/src/fplsp.S
--- v2.4.1/linux/arch/m68k/ifpsp060/src/fplsp.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/ifpsp060/src/fplsp.S	Tue Feb 13 14:13:42 2001
@@ -9963,7 +9963,7 @@
 # ALGORITHM ***********************************************************	#
 #	An underflow should occur as the result of transcendental	#
 # emulation in the 060FPLSP. Create an underflow by using "fmul"	#
-# and two very small numbers of appropriate sign so the the operating	#
+# and two very small numbers of appropriate sign so the operating	#
 # system can log the event.						#
 #									#
 #########################################################################
@@ -10020,7 +10020,7 @@
 # ALGORITHM ***********************************************************	#
 #	An overflow should occur as the result of transcendental	#
 # emulation in the 060FPLSP. Create an overflow by using "fmul"		#
-# and two very lareg numbers of appropriate sign so the the operating	#
+# and two very lareg numbers of appropriate sign so the operating	#
 # system can log the event.						#
 #	For t_ovfl_sc() we take special care not to lose the INEX2 bit.	#
 #									#
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/ifpsp060/src/fpsp.S linux/arch/m68k/ifpsp060/src/fpsp.S
--- v2.4.1/linux/arch/m68k/ifpsp060/src/fpsp.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/ifpsp060/src/fpsp.S	Tue Feb 13 14:13:42 2001
@@ -2944,7 +2944,7 @@
 # The FPU is disabled and so we should really have taken the "Line
 # F Emulator" exception. So, here we create an 8-word stack frame
 # from our 4-word stack frame. This means we must calculate the length
-# the the faulting instruction to get the "next PC". This is trivial for
+# the faulting instruction to get the "next PC". This is trivial for
 # immediate operands but requires some extra work for fmovm dynamic
 # which can use most addressing modes.
 iea_disabled:
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/ifpsp060/src/isp.S linux/arch/m68k/ifpsp060/src/isp.S
--- v2.4.1/linux/arch/m68k/ifpsp060/src/isp.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/ifpsp060/src/isp.S	Tue Feb 13 14:13:43 2001
@@ -2516,7 +2516,7 @@
 	cmpi.b		%d0, &0x7		# is src mode Dn or other?
 	bgt.w		mul64_memop		# src is in memory
 
-# multiplier operand in the the data register file.
+# multiplier operand in the data register file.
 # must extract the register number and fetch the operand from the stack.
 mul64_regop:
 	andi.w		&0x7, %d0		# extract Dn
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/ifpsp060/src/pfpsp.S linux/arch/m68k/ifpsp060/src/pfpsp.S
--- v2.4.1/linux/arch/m68k/ifpsp060/src/pfpsp.S	Fri Dec 29 14:07:20 2000
+++ linux/arch/m68k/ifpsp060/src/pfpsp.S	Tue Feb 13 14:13:43 2001
@@ -2943,7 +2943,7 @@
 # The FPU is disabled and so we should really have taken the "Line
 # F Emulator" exception. So, here we create an 8-word stack frame
 # from our 4-word stack frame. This means we must calculate the length
-# the the faulting instruction to get the "next PC". This is trivial for
+# the faulting instruction to get the "next PC". This is trivial for
 # immediate operands but requires some extra work for fmovm dynamic
 # which can use most addressing modes.
 iea_disabled:
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/kernel/bios32.c linux/arch/m68k/kernel/bios32.c
--- v2.4.1/linux/arch/m68k/kernel/bios32.c	Wed Jan 26 12:44:20 2000
+++ linux/arch/m68k/kernel/bios32.c	Fri Feb  9 11:29:44 2001
@@ -26,7 +26,7 @@
  */
 
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S
--- v2.4.1/linux/arch/m68k/kernel/entry.S	Mon Nov 27 18:02:06 2000
+++ linux/arch/m68k/kernel/entry.S	Tue Feb 13 14:13:43 2001
@@ -140,7 +140,7 @@
 	bnes	2f			| if so, skip resched, signals
 	| only allow interrupts when we are really the last one on the
 	| kernel stack, otherwise stack overflow can occur during
-	| heavy interupt load
+	| heavy interrupt load
 	andw	#ALLOWINT,%sr
 	tstl	%curptr@(TASK_NEEDRESCHED)
 	jne	SYMBOL_NAME(reschedule)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.4.1/linux/arch/m68k/kernel/process.c	Tue Sep  5 13:50:01 2000
+++ linux/arch/m68k/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/reboot.h>
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/mac/misc.c linux/arch/m68k/mac/misc.c
--- v2.4.1/linux/arch/m68k/mac/misc.c	Mon Sep 11 08:39:48 2000
+++ linux/arch/m68k/mac/misc.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/time.h>
 #include <linux/kd.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/mac/oss.c linux/arch/m68k/mac/oss.c
--- v2.4.1/linux/arch/m68k/mac/oss.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/m68k/mac/oss.c	Tue Feb 13 14:13:43 2001
@@ -123,7 +123,7 @@
 /*
  * Nubus IRQ handler, OSS style
  *
- * Unlike the VIA/RBV this is on its own autovector interupt level.
+ * Unlike the VIA/RBV this is on its own autovector interrupt level.
  */
 
 void oss_nubus_irq(int irq, void *dev_id, struct pt_regs *regs)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_cond.S linux/arch/m68k/math-emu/fp_cond.S
--- v2.4.1/linux/arch/m68k/math-emu/fp_cond.S	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/fp_cond.S	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_decode.h linux/arch/m68k/math-emu/fp_decode.h
--- v2.4.1/linux/arch/m68k/math-emu/fp_decode.h	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/fp_decode.h	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_emu.h linux/arch/m68k/math-emu/fp_emu.h
--- v2.4.1/linux/arch/m68k/math-emu/fp_emu.h	Wed Nov 10 10:00:48 1999
+++ linux/arch/m68k/math-emu/fp_emu.h	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_entry.S linux/arch/m68k/math-emu/fp_entry.S
--- v2.4.1/linux/arch/m68k/math-emu/fp_entry.S	Fri Nov 12 04:29:47 1999
+++ linux/arch/m68k/math-emu/fp_entry.S	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_move.S linux/arch/m68k/math-emu/fp_move.S
--- v2.4.1/linux/arch/m68k/math-emu/fp_move.S	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/fp_move.S	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_movem.S linux/arch/m68k/math-emu/fp_movem.S
--- v2.4.1/linux/arch/m68k/math-emu/fp_movem.S	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/fp_movem.S	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_scan.S linux/arch/m68k/math-emu/fp_scan.S
--- v2.4.1/linux/arch/m68k/math-emu/fp_scan.S	Sun Aug 15 11:47:29 1999
+++ linux/arch/m68k/math-emu/fp_scan.S	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/math-emu/fp_util.S linux/arch/m68k/math-emu/fp_util.S
--- v2.4.1/linux/arch/m68k/math-emu/fp_util.S	Fri Nov 12 04:29:47 1999
+++ linux/arch/m68k/math-emu/fp_util.S	Tue Feb 13 14:13:43 2001
@@ -17,7 +17,7 @@
  *    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
+ * the GNU General 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.)
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/mm/kmap.c linux/arch/m68k/mm/kmap.c
--- v2.4.1/linux/arch/m68k/mm/kmap.c	Wed Jan 26 12:44:20 2000
+++ linux/arch/m68k/mm/kmap.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.4.1/linux/arch/m68k/mm/memory.c	Mon Aug  7 21:02:27 2000
+++ linux/arch/m68k/mm/memory.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/pagemap.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/m68k/mvme16x/rtc.c linux/arch/m68k/mvme16x/rtc.c
--- v2.4.1/linux/arch/m68k/mvme16x/rtc.c	Wed Jul 12 21:58:42 2000
+++ linux/arch/m68k/mvme16x/rtc.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/baget/irq.c linux/arch/mips/baget/irq.c
--- v2.4.1/linux/arch/mips/baget/irq.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/baget/irq.c	Fri Feb  9 11:29:44 2001
@@ -16,7 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/delay.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/mips/baget/vacserial.c linux/arch/mips/baget/vacserial.c
--- v2.4.1/linux/arch/mips/baget/vacserial.c	Thu Oct 12 14:20:48 2000
+++ linux/arch/mips/baget/vacserial.c	Fri Feb  9 11:29:44 2001
@@ -56,7 +56,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #ifdef CONFIG_SERIAL_CONSOLE
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/Makefile linux/arch/mips/cobalt/Makefile
--- v2.4.1/linux/arch/mips/cobalt/Makefile	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/Makefile	Wed Dec 31 16:00:00 1969
@@ -1,24 +0,0 @@
-#
-# Makefile for the Cobalt micro systems family specific parts of the 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).
-#
-# $Id: Makefile,v 1.1 1997/10/23 22:25:41 ralf Exp $
-#
-
-.S.s:
-	$(CPP) $(CFLAGS) $< -o $*.s
-.S.o:
-	$(CC) $(CFLAGS) -c $< -o $*.o
-
-all: cobalt.o
-O_TARGET := cobalt.o
-O_OBJS	 := cobaltscc.o hw-access.o int-handler.o pci.o reset.o setup.o via.o
-
-int-handler.o: int-handler.S
-
-clean:
-
-include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/cobaltscc.c linux/arch/mips/cobalt/cobaltscc.c
--- v2.4.1/linux/arch/mips/cobalt/cobaltscc.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/cobaltscc.c	Wed Dec 31 16:00:00 1969
@@ -1,350 +0,0 @@
-/*
- * Filename: cobaltscc.c
- * 
- * Description: Functions for supporting and testing serial I/O
- * 
- * Author(s): Timothy Stonis
- * 
- * Copyright 1997, Cobalt Microserver, Inc.
- */
-#include "z8530.h"
-#include "diagdefs.h"
-#include "serial.h"
-#include "asm/io.h"
-
-/*
- * Function prototypes
- */
-void InitSerialPort(unsigned char *);
-void RegisterDelay(void);
-void InitScc(void);
-
-/*
- * Function: RegisterDelay
- *
- * Description: A little delay since the SCC can't handle quick consecutive 
- *              accesses
- * In: none
- * Out: none
- */
-void RegisterDelay(void)
-{
-	register int ctr;
-  
-	for(ctr=0;ctr<0x40;ctr++);
-}
-
-/*
- * Function: SccInit
- *
- * Description: Initialize all the SCC registers for 19200 baud, asynchronous,
- *		8 bit, 1 stop bit, no parity communication (Channel A)
- *
- * In: none
- *
- * Out: none
- */
-void InitScc(void)
-{
-	/* Force hardware reset */
-	Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, FHWRES);
-	RegisterDelay();
-  
-	/* x32 clock, 1 stop bit, no parity */
-	Write8530(kSCC_ChanA | kSCC_Command, R4 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, X16CLK | SB1);
-	RegisterDelay();
-  
-	/* Rx 8 bits, Rx disabled */
-	Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, Rx8);
-	RegisterDelay();
-   
-	/* Tx 8 bits, DTR, RTS, Tx off */
-	Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, Tx8 | DTR | RTS);
-	RegisterDelay();
-
-	/* Int. Disabled */
-	Write8530(kSCC_ChanA | kSCC_Command, R9 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, 0x0);
-	RegisterDelay();
-
-	/* NRZ */
-	Write8530(kSCC_ChanA | kSCC_Command, R10 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, NRZ);
-	RegisterDelay();
-
-	/* Tx & Rx = BRG out, TRxC = BRG out */
-	Write8530(kSCC_ChanA | kSCC_Command, R11 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, TCBR | RCBR | TRxCBR | TRxCOI); 
-	RegisterDelay();
-
-	/* Time constant = 0x01 */
-	Write8530(kSCC_ChanA | kSCC_Command, R12 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, kSCC_115200 ); 
-	RegisterDelay();
-
-	/* Time constant high = 0x00 */
-	Write8530(kSCC_ChanA | kSCC_Command, R13 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, 0x00); 
-	RegisterDelay();
-
-	/* BRG in = ~RTxC, BRG off, loopback */
-	Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, LOOPBAK | BRSRC); 
-	RegisterDelay();
-}
-
-/*
- * Function: EnableScc
- *
- * Description: Enable transmit and receive on SCC Channel A
- * In: none
- * Out: none
- */
-void EnableScc(void)
-{
-	/* Enable BRG */
-	Write8530(kSCC_ChanA | kSCC_Command, R14 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, BRENABL | BRSRC);
-	RegisterDelay();
-  
-	/* Rx enable (Rx 8 bits) */
-	Write8530(kSCC_ChanA | kSCC_Command, R3 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, RxENABLE | Rx8);
-	RegisterDelay();
-
-	/* Tx enable (Tx8, DTR, RTS) */
-	Write8530(kSCC_ChanA | kSCC_Command, R5 | NULLCODE);
-	RegisterDelay();
-	Write8530(kSCC_ChanA, TxENAB | Tx8 | DTR | RTS); 
-	RegisterDelay();
-}
-
-/*
- * Function: SccOutb
- *
- * Description: Write a byte to the SCC (Channel A) and blink LED
- * In: Byte to send
- * Out: none
- */
-void SccOutb(unsigned char byte)
-{
-	/* LED on.. */
-	Write8530(kSCC_ChanB | kSCC_Command, R5);
-	RegisterDelay();
-	Write8530(kSCC_ChanB | kSCC_Command, RTS);
-	RegisterDelay();
- 
-	while ((Read8530(kSCC_ChanA) & Tx_BUF_EMP) == 0)
-		RegisterDelay();
- 
-	Write8530(kSCC_ChanA | kSCC_Direct, byte);
-	RegisterDelay();
- 
-	/* LED off.. */
-	Write8530(kSCC_ChanB | kSCC_Command, R9);
-	RegisterDelay();
-	Write8530(kSCC_ChanB | kSCC_Command, CHRB);
-	RegisterDelay();
-}
-
-/*
- * Function: SccInb
- *
- * Description: Read a byte from the SCC (Channel A)
- * In: Byte to send
- * Out: none
- */
-void SccInb(unsigned char *byte)
-{
-	while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0)
-		RegisterDelay();
- 
-	*byte = Read8530(kSCC_ChanA | kSCC_Direct);
-	RegisterDelay();
-}
-
-/*
- * Function: SccWrite
- *
- * Description: Write a null terminated string to the SCC 
- * In: C string
- * Out: none
- */
-void SccWrite(const unsigned char *string)
-{
-	while((*string) != 0) { 
-		if (*string == 10)
-			SccOutb((unsigned char) 13);
-		SccOutb(*(string++));
-	}
-}
-
-/*
- * Function: InitSerialPort
- *
- * Description: Initialize the SCC and spit out the header message 
- * In: Header message
- * Out: none
- */
-void InitSerialPort(unsigned char *msg)
-{
-	InitScc();
-	EnableScc();
-	SccWrite(msg);
-}
-
-/*
- * Function: SccInbTimeout
- *
- * Description: Read a byte from the SCC (Channel A) with timeout
- * In: Byte to send
- * Out: Timeout status
- */
-unsigned char SccInbTimeout(unsigned char *byte, unsigned long timeout)
-{
-	unsigned long ctr = 0;
-
-	while ((Read8530(kSCC_ChanA) & Rx_CH_AV) == 0) {
-		RegisterDelay();
-		if ((ctr++) > timeout)
-			return 0xFF;
-	}
-
-	*byte = Read8530(kSCC_ChanA | kSCC_Direct);
-	RegisterDelay();
- 
-	return 0;
-}
-
-#include <linux/serial_reg.h>
-
-extern int serial_echo_init (int base);
-extern int serial_echo_print (const char *s);
-
-/*
- * this defines the address for the port to which printk echoing is done
- *  when CONFIG_SERIAL_ECHO is defined
- */
-#define SERIAL_ECHO_PORT       0x1C800000 
-
-static int serial_echo_port = 0;
-
-#define serial_echo_outb(v,a) outb((v),(a)+serial_echo_port)
-#define serial_echo_inb(a)    inb((a)+serial_echo_port)
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/* Wait for transmitter & holding register to empty */
-#define WAIT_FOR_XMITR \
- do { \
-       lsr = serial_echo_inb(UART_LSR); \
- } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
-
-/*
- * These two functions abstract the actual communications with the
- * debug port.  This is so we can change the underlying communications
- * mechanism without modifying the rest of the code.
- */
-int
-serial_echo_print(const char *s)
-{
-        int     lsr, ier;
-        int     i;
-
-        if (!serial_echo_port)
-		return 0;
-
-        /*
-         * First save the IER then disable the interrupts
-         */
-        ier = serial_echo_inb(UART_IER);
-        serial_echo_outb(0x00, UART_IER);
-
-        /*
-         * Now, do each character
-         */
-        for (i = 0; *s; i++, s++) {
-                WAIT_FOR_XMITR;
-
-                /* Send the character out. */
-                serial_echo_outb(*s, UART_TX);
-
-                /* if a LF, also do CR... */
-                if (*s == 10) {
-                        WAIT_FOR_XMITR;
-                        serial_echo_outb(13, UART_TX);
-                }
-        }
-
-        /*
-         * Finally, Wait for transmitter & holding register to empty
-         *  and restore the IER
-         */
-        do {
-                lsr = serial_echo_inb(UART_LSR);
-        } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
-        serial_echo_outb(ier, UART_IER);
-
-        return 0;
-}
-
-
-int
-serial_echo_init(int base)
-{
-        int comstat, hi, lo;
-
-        serial_echo_port = base;
-
-        /*
-         * read the Divisor Latch
-         */
-        comstat = serial_echo_inb(UART_LCR);
-        serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR);
-        hi = serial_echo_inb(UART_DLM);
-        lo = serial_echo_inb(UART_DLL);
-        serial_echo_outb(comstat, UART_LCR);
-
-        /*
-         * now do hardwired init
-         */
-        serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
-        serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
-
-	/* This is computed using:
-	 *
-	 * const BASE_BAUD = (18432000 / 16);
-	 * UART_DLM = (BASE_BAUD / baud_I_want) >> 8;
-	 * UART_DLL = (BASE_BAUD / baud_I_want) & 0xff;
-	 */
-        serial_echo_outb(0x00, UART_DLM); /* 115200 baud */
-        serial_echo_outb(0x0A, UART_DLL);
-
-        serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
-
-        /*
-	 * Prior to disabling interrupts, read the LSR and RBR
-         * registers
-         */
-        comstat = serial_echo_inb(UART_LSR); /* COM? LSR */
-        comstat = serial_echo_inb(UART_RX);     /* COM? RBR */
-        serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */
-
-        return 0;
-}
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/diagdefs.h linux/arch/mips/cobalt/diagdefs.h
--- v2.4.1/linux/arch/mips/cobalt/diagdefs.h	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/diagdefs.h	Wed Dec 31 16:00:00 1969
@@ -1,177 +0,0 @@
-/*
- * Filename: diagdefs.h
- * 
- * Description: Some general definitions used by the diagnostics 
- * 
- * Author(s): Timothy Stonis
- * 
- * Copyright 1997, Cobalt Microserver, Inc.
- */
-
-#define KSEG0_Base		0x80000000
-#define KSEG1_Base		0xA0000000
-
-// Some useful Galileo registers/base addresses (boot time kseg1 mapping) 
-#define kGal_InternalBase	( 0x14000000 | KSEG1_Base ) 
-#define kGal_DevBank0Base	( 0x1C000000 | KSEG1_Base )
-#define kGal_DevBank1Base 	( 0x1C800000 | KSEG1_Base )
-
-#define kGal_RAS10Lo		0x008
-#define kGal_RAS10Hi		0x010
-#define kGal_RAS32Lo		0x018
-#define kGal_RAS32Hi		0x020
-
-#define kGal_PCIIOLo		0x048
-#define kGal_PCIIOHi		0x050
-
-#define kGal_RAS10LoCfg		0x000
-#define kGal_RAS10HiCfg		0x03
-#define kGal_RAS32LoCfg		0x004
-#define kGal_RAS32HiCfg		0x07
-
-#define kGal_PCIIOLoCfg		0x000
-#define kGal_PCIIOHiCfg		0x0F
-
-
-#define kGal_DevBank0PReg	0x45C
-#define kGal_DevBank1PReg	0x460
-#define kGal_DevBank2PReg	0x464
-#define kGal_DevBank3PReg	0x468
-#define kGal_DevBankBPReg	0x46C
-
-#define kGal_DRAMCReg		0x448
-#define kGal_DRAM0PReg		0x44C
-#define kGal_DRAM1PReg		0x450
-#define kGal_DRAM2PReg		0x454
-#define kGal_DRAM3PReg		0x458
-
-#define kGal_ConfigAddr		0xCF8
-#define kGal_ConfigData		0xCFC
-#define kGal_PCICfgEn		0x1F // Generate config cycle 
-#define kGal_DevNum		0x00 // Technically 0x06, but 0 works too
-#define kGal_MasMemEn		0x06
-#define kGal_Latency		0x700
-
-#define kGal_RAS01StartReg	0x10
-#define kGal_RAS23StartReg	0x14
-#define kGal_RAS01SizeReg	0x0C08
-#define kGal_RAS23SizeReg	0x0C0C
-
-
-#define kGal_RAS01Start		0x000
-#define kGal_RAS23Start		0x00800000
-#define kGal_RAS01Size		0x007FFFFF
-#define kGal_RAS23Size		0x007FFFFF
-
-
-// Paramter information for devices, DRAM, etc
-#define	kGal_DevBank0Cfg	0x1446DB33
-#define	kGal_DevBank1Cfg	0x144FE667
-#define	kGal_DevBankBCfg	0x1446DC43
-#define	kGal_DRAMConfig		0x00000300
-#define	kGal_DRAM0Config	0x00000010
-#define	kGal_DRAM1Config	0x00000010
-#define	kGal_DRAM2Config	0x00000010
-#define	kGal_DRAM3Config	0x00000010
-
-#define	kGal_DRAM0Hi		0x00000003
-#define	kGal_DRAM0Lo		0x00000000
-#define	kGal_DRAM1Hi		0x00000007
-#define	kGal_DRAM1Lo		0x00000004
-#define	kGal_DRAM2Hi		0x0000000B
-#define	kGal_DRAM2Lo		0x00000008
-#define	kGal_DRAM3Hi		0x0000000F
-#define	kGal_DRAM3Lo		0x0000000C
-
-#define kGal_RAS0Lo		0x400
-#define kGal_RAS0Hi		0x404
-#define kGal_RAS1Lo		0x408
-#define kGal_RAS1Hi		0x40C
-#define kGal_RAS2Lo		0x410
-#define kGal_RAS2Hi		0x414
-#define kGal_RAS3Lo		0x418
-#define kGal_RAS3Hi		0x41C
-
-// Feedback LED indicators during setup code (reset.S, main.c) 
-#define kLED_AllOn	0x0F
-#define kLED_FlashTest	0x01
-#define kLED_MemTest	0x02
-#define kLED_SCCTest	0x03
-#define kLED_GalPCI	0x04
-#define kLED_EnetTest	0x05
-#define kLED_SCSITest	0x06
-#define kLED_IOCTest	0x07
-#define kLED_Quickdone	0x0A
-#define kLED_Exception	0x0B
-#define kLED_ProcInit	0x0E
-#define kLED_AllOff	0x00
-
-#define kLEDBase	kGal_DevBank0Base
-
-// Some memory related constants 
-#define kRAM_Start	(0x00000000 | KSEG0_Base)
-
-#define	kTestPat1	0xA5A5A5A5
-#define kTestPat2	0x5A5A5A5A
-
-#define k1Meg_kseg1 	(0x00100000 | KSEG0_Base)
-#define k2Meg_kseg1  	(0x00200000 | KSEG0_Base)
-#define k4Meg_kseg1  	(0x00400000 | KSEG0_Base)
-#define k8Meg_kseg1  	(0x00800000 | KSEG0_Base)
-#define k16Meg_kseg1  	(0x01000000 | KSEG0_Base)
-
-#define kInit_SP	k4Meg_kseg1 - 0x100
-#define kVectorBase	0x200	
-#define kDebugVectors	0x400
-#define kMallocCheese	0x80E00000
-#define kDecompAddr	0x80700000
-#define kCompAddr	0x80500000
-
-
-// Ethernet definitions
-#define	kEnet_VIOBase	( 0x12100000 | KSEG1_Base )
-#define	kEnet_PIOBase	0x12100000
-#define	kEnet_CSCfg	0x46
-#define kEnet_DevNum	0x07
-#define kEnet_CSR3	0x18
-#define kEnet_CSR15	0x78
-
-
-#define kEnet_GEPOut	0x080f0000
-#define kEnet_GEPOn	0x000f0000
-
-
-// SCSI definitions
-#define	kSCSI_VIOBase	( 0x12200000 | KSEG1_Base )
-#define	kSCSI_PIOBase	0x12200000 
-#define	kSCSI_CSCfg	0x46 
-#define kSCSI_DevNum	0x08
-#define kSCSI_GPCNTL	0x47
-#define kSCSI_GPREG	0x07
-#define kSCSI_SCRTCHA	0x34
-
-#define kSCSI_GPIOOut	0x0C
-#define kSCSI_LEDsOn	0x00
-
-// I/O Controller definitions
-#define kIOC_VIOBase	( 0x10000000 | KSEG1_Base )
-#define kIOC_RIOBase	0x10000000 
-#define kIOC_DevNum	0x09
-#define kIOC_ISAFunc	0x00
-#define kIOC_IDEFunc	0x01
-#define kIOC_USBFunc	0x02
-#define kIOC_MiscC0	0x44
-#define kIOC_IDEEnable	0x40
-
-#define kIOC_PCIIDEOn 	0x02800085
-#define kIOC_PriIDEOn	0x0A
-
-// Some PCI Definitions
-#define	kPCI_StatCmd	0x04
-#define	kPCI_LatCache	0x0C
-#define	kPCI_CBIO	0x10
-#define	kPCI_CBMEM	0x14
-
-// Random constants
-#define kBogoSec	0x0003F940
-#define kSCCDelay	0x00000001
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/hw-access.c linux/arch/mips/cobalt/hw-access.c
--- v2.4.1/linux/arch/mips/cobalt/hw-access.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/hw-access.c	Wed Dec 31 16:00:00 1969
@@ -1,58 +0,0 @@
-/*
- * Low-level hardware access stuff for Cobalt Microserver 27 board.
- *
- * 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.
- *
- * Copyright (C) 1995, 1996, 1997 by Ralf Baechle
- */
-#include <linux/delay.h>
-#include <linux/kernel.h>
-#include <linux/linkage.h>
-#include <linux/types.h>
-#include <asm/cachectl.h>
-#include <asm/cobalt.h>
-#include <asm/segment.h>
-#include <asm/vector.h>
-
-void
-dummy(void)
-{
-	panic("What the hell is this called for?");
-}
-
-static unsigned char cobalt_read_cmos(unsigned long reg)
-{
-	unsigned char retval;
-
-	VIA_PORT_WRITE(0x70, reg);
-	retval = VIA_PORT_READ(0x71);
-	VIA_DELAY();
-
-	return retval;
-}
-
-static void cobalt_write_cmos(unsigned char val, unsigned long reg)
-{
-	VIA_PORT_WRITE(0x70, reg);
-	VIA_PORT_WRITE(0x71, val); 
-}
-
-struct feature cobalt_feature = {
-	/*
-	 * How to access the floppy controller's ports
-	 */
-	(void *)dummy, (void *)dummy,
-	/*
-	 * How to access the floppy DMA functions.
-	 */
-	(void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy,
-	(void *)dummy, (void *)dummy, (void *)dummy, (void *)dummy,
-	(void *)dummy, (void *)dummy, (void *)dummy,
-	/*
-	 * How to access the RTC functions.
-	 */
-	cobalt_read_cmos,
-	cobalt_write_cmos
-};
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/int-handler.S linux/arch/mips/cobalt/int-handler.S
--- v2.4.1/linux/arch/mips/cobalt/int-handler.S	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/int-handler.S	Wed Dec 31 16:00:00 1969
@@ -1,140 +0,0 @@
-/*
- * arch/mips/cobalt/int-handler.S
- */
-#include <asm/asm.h>
-#include <asm/mipsconfig.h>
-#include <asm/mipsregs.h>
-#include <asm/cobalt.h>
-#include <asm/irq.h>
-#include <asm/regdef.h>
-#include <asm/stackframe.h>
-
-/*
- * cobalt_handle_int: Interrupt handler for the twenty-seven board.
- */
-		.align	5
-		.set	noreorder
-		NESTED(cobalt_handle_int, PT_SIZE, ra)
-		.set	noat
-		SAVE_ALL
-		REG_S	sp,PT_OR2(sp)
-		CLI
-		.set	at
-		mfc0	t0,CP0_CAUSE
-		mfc0	t1,CP0_STATUS
-		and	t0,t1
-		xor	t1,t0
-		mtc0	t1,CP0_STATUS	# mask all active ints
-		/* Such a kind of cascade is optimal for R5000 */
-
-		andi	t1,t0,STATUSF_IP2
-		bnez	t1,ll_galileo_irq
-		 andi	t1,t0,STATUSF_IP3
-		bnez	t1,ll_ethernet0_irq
-/*
- * This should be conditional, and not used for the cube-1, but
- * there is not a config flag that is useful.
- */
-	
-		 andi	t1,t0,STATUSF_IP4
-		bnez	t1,ll_ethernet1_irq
-/* #endif  */
-		 andi	t1,t0,STATUSF_IP6
-		bnez	t1,ll_via_irq
-		 andi	t1,t0,STATUSF_IP5
-		bnez	t1,ll_serial_irq
-		 andi	t1,t0,STATUSF_IP7
-		bnez	t1,ll_pci_irq
-		  nop
-		/* wrong alarm ... */
-		j	spurious_interrupt
-		 nop
-		END(cobalt_handle_int)
-	
-
-		.align	5
-		.set	reorder
-ll_galileo_irq:	move	a0,sp
-		INC_INTR_COUNT(s1,s2)
-		jal	galileo_irq
-		  nop
-		DEC_INTR_COUNT(s1,s2)
-		j	ret_from_irq
-		  nop
-
-		.align	5
-		.set	reorder
-ll_via_irq:	move	a0,sp
-		INC_INTR_COUNT(s1,s2)
-		jal	via_irq
-		  nop
-		DEC_INTR_COUNT(s1,s2)
-		j	ret_from_irq
-		  nop
-
-		.align	5
-		.set	reorder
-ll_ethernet0_irq:
-		INC_INTR_COUNT(s1,s2)
-		mfc0	s0,CP0_STATUS		# mask interrupt
-		ori	t0,s0,(STATUSF_IP3 | STATUSF_IP4)
-		xori	t0,(STATUSF_IP3 | STATUSF_IP4)
-		mtc0	t0,CP0_STATUS
-		li	a0,4
-		move	a1,sp
-		jal     do_IRQ
-		  nop
-		mtc0	s0,CP0_STATUS
-		DEC_INTR_COUNT(s1,s2)
-		j	ret_from_irq
-		  nop
-
-		.align	5
-		.set	reorder
-ll_serial_irq:	li	a0,7
-		INC_INTR_COUNT(s1,s2)
-		move	a1,sp
-		jal     do_IRQ
-		  nop
-		DEC_INTR_COUNT(s1,s2)
-		j	ret_from_irq
-		  nop
-
-
-		.align	5
-		.set	reorder
-ll_ethernet1_irq:
-		INC_INTR_COUNT(s1,s2)
-		mfc0	s0,CP0_STATUS		# mask interrupt
-
-		ori	t0,s0, (STATUSF_IP3 | STATUSF_IP4)
-		xori	t0,(STATUSF_IP3 | STATUSF_IP4)
-
-		mtc0	t0,CP0_STATUS
-		li	a0,13
-		move	a1,sp
-		jal     do_IRQ
-		  nop
-		mtc0	s0,CP0_STATUS
-		DEC_INTR_COUNT(s1,s2)
-		j	ret_from_irq
-		  nop
-
-	#
-	# This is pretty weird.  The "pci" interrupt on the hardware
-	# skematic is from the PCI side of the galileo, so we would
-	# only get interrupts here if WE write the control register
-	# that normally enables the cpu to send interrupts to the PCI.
-	#
-	# If you want to interrupt a PCI card, look elsewhere.
-	#
-		.align	5
-		.set	reorder
-ll_pci_irq:	li	a0,7
-		INC_INTR_COUNT(s1,s2)
-		move	a1,sp
-		jal     do_IRQ
-		  nop
-		DEC_INTR_COUNT(s1,s2)
-		j	ret_from_irq
-		  nop
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/pci.c linux/arch/mips/cobalt/pci.c
--- v2.4.1/linux/arch/mips/cobalt/pci.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/pci.c	Wed Dec 31 16:00:00 1969
@@ -1,348 +0,0 @@
-/*
- * 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.
- *
- * Cobalt Qube specific PCI support.
- */
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
-#include <linux/kernel.h>
-#include <asm/cobalt.h>
-#include <asm/pci.h>
-#include <asm/io.h>
- 
-#undef PCI_DEBUG 
-
-#ifdef CONFIG_PCI
-
-static void qube_expansion_slot_bist(void)
-{
-	unsigned char ctrl;
-	int timeout = 100000;
-
-	pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl);
-	if(!(ctrl & PCI_BIST_CAPABLE))
-		return;
-
-	pcibios_write_config_byte(0, (0x0a<<3), PCI_BIST, ctrl|PCI_BIST_START);
-	do {
-		pcibios_read_config_byte(0, (0x0a<<3), PCI_BIST, &ctrl);
-		if(!(ctrl & PCI_BIST_START))
-			break;
-	} while(--timeout > 0);
-	if((timeout <= 0) || (ctrl & PCI_BIST_CODE_MASK))
-		printk("PCI: Expansion slot card failed BIST with code %x\n",
-		       (ctrl & PCI_BIST_CODE_MASK));
-}
-
-static void qube_expansion_slot_fixup(void)
-{
-	unsigned short pci_cmd;
-	unsigned long ioaddr_base = 0x10108000; /* It's magic, ask Doug. */
-	unsigned long memaddr_base = 0x12000000;
-	int i;
-
-	/* Enable bits in COMMAND so driver can talk to it. */
-	pcibios_read_config_word(0, (0x0a<<3), PCI_COMMAND, &pci_cmd);
-	pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-	pcibios_write_config_word(0, (0x0a<<3), PCI_COMMAND, pci_cmd);
-
-	/* Give it a working IRQ. */
-	pcibios_write_config_byte(0, (0x0a<<3), PCI_INTERRUPT_LINE, 9);
-
-	/* Fixup base addresses, we only support I/O at the moment. */
-	for(i = 0; i <= 5; i++) {
-		unsigned int regaddr = (PCI_BASE_ADDRESS_0 + (i * 4));
-		unsigned int rval, mask, size, alignme, aspace;
-		unsigned long *basep = &ioaddr_base;
-
-		/* Check type first, punt if non-IO. */
-		pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval);
-		aspace = (rval & PCI_BASE_ADDRESS_SPACE);
-		if(aspace != PCI_BASE_ADDRESS_SPACE_IO)
-			basep = &memaddr_base;
-
-		/* Figure out how much it wants, if anything. */
-		pcibios_write_config_dword(0, (0x0a<<3), regaddr, 0xffffffff);
-		pcibios_read_config_dword(0, (0x0a<<3), regaddr, &rval);
-
-		/* Unused? */
-		if(rval == 0)
-			continue;
-
-		rval &= PCI_BASE_ADDRESS_IO_MASK;
-		mask = (~rval << 1) | 0x1;
-		size = (mask & rval) & 0xffffffff;
-		alignme = size;
-		if(alignme < 0x400)
-			alignme = 0x400;
-		rval = ((*basep + (alignme - 1)) & ~(alignme - 1));
-		*basep = (rval + size);
-		pcibios_write_config_dword(0, (0x0a<<3), regaddr, rval | aspace);
-	}
-	qube_expansion_slot_bist();
-}
-
-static void qube_raq_tulip_fixup(void)
-{
-	unsigned short pci_cmd;
-
-	/* Enable the device. */
-	pcibios_read_config_word(0, (0x0c<<3), PCI_COMMAND, &pci_cmd);
-	pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER);
-	pcibios_write_config_word(0, (0x0c<<3), PCI_COMMAND, pci_cmd);
-
-	/* Give it it's IRQ. */
-	/* NOTE: RaQ board #1 has a bunch of green wires which swapped the
-	 *       IRQ line values of Tulip 0 and Tulip 1.  All other
-	 *       boards have eth0=4,eth1=13.  -DaveM
-	 */
-#ifndef RAQ_BOARD_1_WITH_HWHACKS
-	pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 13);
-#else
-	pcibios_write_config_byte(0, (0x0c<<3), PCI_INTERRUPT_LINE, 4);
-#endif
-
-	/* And finally, a usable I/O space allocation, right after what
-	 * the first Tulip uses.
-	 */
-	pcibios_write_config_dword(0, (0x0c<<3), PCI_BASE_ADDRESS_0, 0x10101001);
-}
-
-static void qube_raq_scsi_fixup(void)
-{
-	unsigned short pci_cmd;
-
-	/* Enable the device. */
-	pcibios_read_config_word(0, (0x08<<3), PCI_COMMAND, &pci_cmd);
-
-	pci_cmd |= (PCI_COMMAND_IO | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY
-		| PCI_COMMAND_INVALIDATE);
-	pcibios_write_config_word(0, (0x08<<3), PCI_COMMAND, pci_cmd);
-
-	/* Give it it's IRQ. */
-	pcibios_write_config_byte(0, (0x08<<3), PCI_INTERRUPT_LINE, 4);
-
-	/* And finally, a usable I/O space allocation, right after what
-	 * the second Tulip uses.
-	 */
-	pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_0, 0x10102001);
-	pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_1, 0x00002000);
-	pcibios_write_config_dword(0, (0x08<<3), PCI_BASE_ADDRESS_2, 0x00100000);
-}
-
-static unsigned long
-qube_pcibios_fixup(unsigned long mem_start, unsigned long mem_end)
-{
-	extern int cobalt_is_raq;
-	int raq_p = cobalt_is_raq;
-	unsigned int tmp;
-
-	/* Fixup I/O and Memory space decoding on Galileo.  */
-	isa_slot_offset = COBALT_LOCAL_IO_SPACE;
-
-	/* Fix PCI latency-timer and cache-line-size values in Galileo
-	 * host bridge.
-	 */
-	pcibios_write_config_byte(0, 0, PCI_LATENCY_TIMER, 64);
-	pcibios_write_config_byte(0, 0, PCI_CACHE_LINE_SIZE, 7);
-
-        /*
-         * Now tell the SCSI device that we expect an interrupt at
-         * IRQ 7 and not the default 0.
-         */
-        pcibios_write_config_byte(0, 0x08<<3, PCI_INTERRUPT_LINE,
-                                  COBALT_SCSI_IRQ);
-
-        /*
-         * Now tell the Ethernet device that we expect an interrupt at
-         * IRQ 13 and not the default 189.
-	 *
-	 * The IRQ of the first Tulip is different on Qube and RaQ
-	 * hardware except for the weird first RaQ bringup board,
-	 * see above for details.  -DaveM
-         */
-	if (! raq_p) {
-		/* All Qube's route this the same way. */
-		pcibios_write_config_byte(0, 0x07<<3, PCI_INTERRUPT_LINE,
-					  COBALT_ETHERNET_IRQ);
-	} else {
-#ifndef RAQ_BOARD_1_WITH_HWHACKS
-		pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 4);
-#else
-		pcibios_write_config_byte(0, (0x07<<3), PCI_INTERRUPT_LINE, 13);
-#endif
-	}
-
-	if (! raq_p) {
-		/* See if there is a device in the expansion slot, if so
-		 * fixup IRQ, fix base addresses, and enable master +
-		 * I/O + memory accesses in config space.
-		 */
-		pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp);
-		if(tmp != 0xffffffff && tmp != 0x00000000)
-			qube_expansion_slot_fixup();
-	} else {
-		/* If this is a RAQ, we may need to setup the second Tulip
-		 * and SCSI as well.  Due to the different configurations
-		 * a RaQ can have, we need to explicitly check for the
-		 * presence of each of these (optional) devices.  -DaveM
-		 */
-		pcibios_read_config_dword(0, 0x0c<<3, PCI_VENDOR_ID, &tmp);
-		if(tmp != 0xffffffff && tmp != 0x00000000)
-			qube_raq_tulip_fixup();
-
-		pcibios_read_config_dword(0, 0x08<<3, PCI_VENDOR_ID, &tmp);
-		if(tmp != 0xffffffff && tmp != 0x00000000)
-			qube_raq_scsi_fixup();
-
-		/* And if we are a 2800 we have to setup the expansion slot
-		 * too.
-		 */
-		pcibios_read_config_dword(0, 0x0a<<3, PCI_VENDOR_ID, &tmp);
-		if(tmp != 0xffffffff && tmp != 0x00000000)
-			qube_expansion_slot_fixup();
-	}
-
-	return mem_start;
-}
-
-static __inline__ int pci_range_ck(unsigned char bus, unsigned char dev) 
-{
-	if ((bus == 0) && ( (dev==0) || ((dev>6) && (dev <= 12))) )
-		return 0;  /* OK device number  */
-
-	return -1;  /* NOT ok device number */
-}
-
-#define PCI_CFG_DATA	((volatile unsigned long *)0xb4000cfc)
-#define PCI_CFG_CTRL	((volatile unsigned long *)0xb4000cf8)
-
-#define PCI_CFG_SET(dev,fun,off) \
-	((*PCI_CFG_CTRL) = (0x80000000 | ((dev)<<11) | \
-			    ((fun)<<8) | (off)))
-
-static int qube_pcibios_read_config_dword (unsigned char bus,
-					   unsigned char dev,
-					   unsigned char offset,
-					   unsigned int *val)
-{
-	unsigned char fun = dev & 0x07;
-
-	dev >>= 3;
-	if (offset & 0x3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (pci_range_ck(bus, dev)) {
-		*val = 0xFFFFFFFF;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	PCI_CFG_SET(dev, fun, offset);
-	*val = *PCI_CFG_DATA;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int qube_pcibios_read_config_word (unsigned char bus,
-					  unsigned char dev,
-					  unsigned char offset,
-					  unsigned short *val)
-{
-	unsigned char fun = dev & 0x07;
-
-	dev >>= 3;
-	if (offset & 0x1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (pci_range_ck(bus, dev)) {
-		*val = 0xffff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	PCI_CFG_SET(dev, fun, (offset & ~0x3));
-	*val = *PCI_CFG_DATA >> ((offset & 3) * 8);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int qube_pcibios_read_config_byte (unsigned char bus,
-					  unsigned char dev,
-					  unsigned char offset,
-					  unsigned char *val)
-{
-	unsigned char fun = dev & 0x07;
-
-	dev >>= 3;
-	if (pci_range_ck(bus, dev)) {
-		*val = 0xff;
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	}
-	PCI_CFG_SET(dev, fun, (offset & ~0x3));
-	*val = *PCI_CFG_DATA >> ((offset & 3) * 8);
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int qube_pcibios_write_config_dword (unsigned char bus,
-					    unsigned char dev,
-					    unsigned char offset,
-					    unsigned int val)
-{
-	unsigned char fun = dev & 0x07;
-
-	dev >>= 3;
-	if(offset & 0x3)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	PCI_CFG_SET(dev, fun, offset);
-	*PCI_CFG_DATA = val;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-qube_pcibios_write_config_word (unsigned char bus, unsigned char dev,
-                                unsigned char offset, unsigned short val)
-{
-	unsigned char fun = dev & 0x07;
-	unsigned long tmp;
-
-	dev >>= 3;
-	if (offset & 0x1)
-		return PCIBIOS_BAD_REGISTER_NUMBER;
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	PCI_CFG_SET(dev, fun, (offset & ~0x3));
-	tmp = *PCI_CFG_DATA;
-	tmp &= ~(0xffff << ((offset & 0x3) * 8));
-	tmp |=  (val << ((offset & 0x3) * 8));
-	*PCI_CFG_DATA = tmp;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-qube_pcibios_write_config_byte (unsigned char bus, unsigned char dev,
-                                unsigned char offset, unsigned char val)
-{
-	unsigned char fun = dev & 0x07;
-	unsigned long tmp;
-
-	dev >>= 3;
-	if (pci_range_ck(bus, dev))
-		return PCIBIOS_DEVICE_NOT_FOUND;
-	PCI_CFG_SET(dev, fun, (offset & ~0x3));
-	tmp = *PCI_CFG_DATA;
-	tmp &= ~(0xff << ((offset & 0x3) * 8));
-	tmp |=  (val << ((offset & 0x3) * 8));
-	*PCI_CFG_DATA = tmp;
-	return PCIBIOS_SUCCESSFUL;
-}
-
-struct pci_ops qube_pci_ops = {
-	qube_pcibios_fixup,
-	qube_pcibios_read_config_byte,
-	qube_pcibios_read_config_word,
-	qube_pcibios_read_config_dword,
-	qube_pcibios_write_config_byte,
-	qube_pcibios_write_config_word,
-	qube_pcibios_write_config_dword
-};
-
-#endif /* CONFIG_PCI */
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/reset.c linux/arch/mips/cobalt/reset.c
--- v2.4.1/linux/arch/mips/cobalt/reset.c	Thu Jul 13 09:39:49 2000
+++ linux/arch/mips/cobalt/reset.c	Wed Dec 31 16:00:00 1969
@@ -1,61 +0,0 @@
-/*
- *  Reset a Cobalt Qube.
- */
-#include <linux/config.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/processor.h>
-#include <asm/reboot.h>
-#include <asm/system.h>
-
-void cobalt_machine_restart(char *command)
-{
-	*(volatile char *)0xbc000000 = 0x0f;
-
-	/*
-	 * Ouch, we're still alive ... This time we take the silver bullet ...
-	 * ... and find that we leave the hardware in a state in which the
-	 * kernel in the flush locks up somewhen during of after the PCI
-	 * detection stuff.
-	 */
-	set_cp0_status((ST0_BEV | ST0_ERL), (ST0_BEV | ST0_ERL));
-	set_cp0_config(CONFIG_CM_CMASK, CONFIG_CM_UNCACHED);
-	flush_cache_all();
-	write_32bit_cp0_register(CP0_WIRED, 0);
-	__asm__ __volatile__(
-		"jr\t%0"
-		:
-		: "r" (0xbfc00000));
-}
-
-extern int led_state;
-#define kLED            0xBC000000
-#define LEDSet(x)       (*(volatile unsigned char *) kLED) = (( unsigned char)x)
-
-void cobalt_machine_halt(void)
-{
-	int mark;
-
-	// Blink our cute little LED (number 3)...
-	while (1) {
-		led_state = led_state | ( 1 << 3 );
-		LEDSet(led_state);  
-		mark = jiffies;
-		while (jiffies<(mark+HZ));
-		led_state = led_state & ~( 1 << 3 );
-		LEDSet(led_state);
-		mark = jiffies;
-		while (jiffies<(mark+HZ));
-	} 
-}
-
-/*
- * This triggers the luser mode device driver for the power switch ;-)
- */
-void cobalt_machine_power_off(void)
-{
-	printk("You can switch the machine off now.\n");
-	cobalt_machine_halt();
-}
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/serial.h linux/arch/mips/cobalt/serial.h
--- v2.4.1/linux/arch/mips/cobalt/serial.h	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/serial.h	Wed Dec 31 16:00:00 1969
@@ -1,28 +0,0 @@
-/*
- * 
- * Filename: serial.h
- * 
- * Description: Some general definitions used for serial code 
- * 
- * Author(s): Timothy Stonis
- * 
- * Copyright 1997, Cobalt Microserver, Inc.
- */
- 
-/*
- * Serial port definitions
- */
-#define kSCC_Base	kGal_DevBank1Base
-#define kHelloWorldMsg	"Cobalt Networks Diagnostics - 'We serve it, you surf it'\n\r"
-#define kSCC_ChanA	0x01
-#define kSCC_ChanB	0x00
-#define kSCC_Direct	0x02
-#define kSCC_Command	0x00
-
-#define kSCC_TestVal	0xA5
-#define kSCC_19200	0x07	/* x32 clock mode, 19200 baud 	*/
-#define kSCC_115200	0x01	/* x16 clock mode, 115200 baud 	*/
-
-#define Read8530(n)	(*((unsigned char *) (kSCC_Base | (n))))
-
-#define Write8530(x,y)	(*((unsigned char *) (kSCC_Base | (x))) = (y))
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/setup.c linux/arch/mips/cobalt/setup.c
--- v2.4.1/linux/arch/mips/cobalt/setup.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/setup.c	Wed Dec 31 16:00:00 1969
@@ -1,411 +0,0 @@
-/*
- * Setup pointers to hardware dependand routines.
- *
- * 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.
- *
- * Copyright (C) 1996, 1997 by Ralf Baechle
- */
-#include <linux/bios32.h>
-#include <linux/config.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/timex.h>
-#include <asm/bootinfo.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/cobalt.h>
-#include <asm/pci.h>
-#include <asm/processor.h>
-#include <asm/ptrace.h>
-#include <asm/reboot.h>
-#include <asm/vector.h>
-
-extern void cobalt_machine_restart(char *command);
-extern void cobalt_machine_halt(void);
-extern void cobalt_machine_power_off(void);
-
-extern int serial_console;
-
-/*
- * Initial irq handlers.
- */
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs)
-{ 
-}
-
-/*
- * IRQ2 is cascade interrupt to second interrupt controller
- */
-static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
-
-extern struct feature cobalt_feature;
-extern asmlinkage void cobalt_handle_int(void);
-
-static void cobalt_irq_setup(void) 
-{
-	/*
-	 * Clear all of the interrupts while we change the able around a bit.
-	 */
- 	set_cp0_status(ST0_IM, 0);
-
-	/* Sets the exception_handler array. */
-	set_except_vector(0, cobalt_handle_int);
-
-	request_region(0xb0000020, 0x20, "pic1");
-	request_region(0xb00000A0, 0x20, "pic2");
-	setup_x86_irq(2, &irq2);
-
-	cli();
-
-	set_cp0_status(ST0_IM, IE_IRQ4 | IE_IRQ3 | IE_IRQ2 | IE_IRQ1 | IE_IRQ0);
-
-	/* Setup VIA irq mask */
-	VIA_PORT_WRITE(0x20, 0x10);
-	VIA_PORT_WRITE(0x21, 0x00);
-	VIA_PORT_WRITE(0x21, 0x00);
-
-	VIA_PORT_WRITE(0xa0, 0x10);
-	VIA_PORT_WRITE(0xa1, 0x00);
-	VIA_PORT_WRITE(0xa1, 0x00);
-}
-
-void (*board_time_init)(struct irqaction *irq);
-
-static void cobalt_calibrate_timer(void)
-{
-	volatile unsigned long *timer_reg = (volatile unsigned long *)0xb4000850;
-
-	/* Default to 150MHZ, since this is what we are shipping. */
-	*timer_reg = 500000;
-}
-
-static void cobalt_time_init(struct irqaction *irq)
-{
-	/* Load timer value for 100 Hz */
-	cobalt_calibrate_timer();
-	/* *((volatile unsigned long *) 0xb4000850) = (unsigned long) 440000; */
-
-	setup_x86_irq(0, irq);
-
-	/* Enable timer ints */
-	*((volatile unsigned long *) 0xb4000864) = (unsigned long) 0x00000003;
-	/* Unmask timer int */
-	*((volatile unsigned long *) 0xb4000c1c) = (unsigned long) 0x00000100; 
-}
-
-extern struct pci_ops qube_pci_ops;
-int cobalt_serial_present;
-int cobalt_serial_type;
-int cobalt_is_raq;
-
-void cobalt_setup(void)
-{
-	tag *atag;
-
-	/*
-	 * We just check if a tag_screen_info can be gathered
-	 * in setup_arch(), if yes we don't proceed futher...
-	 */
-	atag = bi_TagFind(tag_screen_info);
-	if (!atag) {
-		/*
-		 * If no, we try to find the tag_arc_displayinfo which is
-		 * always created by Milo for an ARC box (for now Milo only
-		 * works on ARC boxes :) -Stoned.
-		 */
-		atag = bi_TagFind(tag_arcdisplayinfo);
-		if (atag) {
-
-			screen_info.orig_x = 
-				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_x;
-			screen_info.orig_y = 
-				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->cursor_y;
-			screen_info.orig_video_cols  = 
-				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->columns;
-			screen_info.orig_video_lines  = 
-				((mips_arc_DisplayInfo*)TAGVALPTR(atag))->lines;
-		}
-	}
-
-	_machine_restart = cobalt_machine_restart;
-	_machine_halt = cobalt_machine_halt;
-	_machine_power_off = cobalt_machine_power_off;
-
-	irq_setup = cobalt_irq_setup;
-	board_time_init = cobalt_time_init;
-	feature = &cobalt_feature;
-	mips_io_port_base = COBALT_LOCAL_IO_SPACE;
-
-	pci_ops = &qube_pci_ops;
-
-#ifdef CONFIG_COBALT_SERIAL
-	serial_console = 1;
-#endif /* CONFIG_COBALT_SERIAL */
-
-	/* We have to do this early, here, before the value could
-	 * possibly be overwritten by the bootup sequence.
-	 */
-	cobalt_serial_present = *((unsigned long *) 0xa020001c);
-	cobalt_serial_type    = *((unsigned long *) 0xa0200020);
-	cobalt_is_raq         = (cobalt_serial_present != 0x0
-				 && cobalt_serial_type == 0x1);
-}
-
-void	AddTagsEndSymbol(void);
-int bi_TagAdd (enum bi_tag type, unsigned long size, void *data);
-unsigned long next_tag = (unsigned long) NULL;
-unsigned long memory_upper = (unsigned long) NULL;
-
-int bi_TagAdd (enum bi_tag type, unsigned long size, void *data)
-{
-	tag t;
-	unsigned long addr;
-
-	t.tag = type;
-	t.size = size;
-
-	/*
-	 * If next_tag equals NULL it means it's the first tag we're asked
-	 * to create.
-	 */
-	if (next_tag == (unsigned long) NULL)  {
-		/*
-		 * If memory_upper not equals NULL it means that identify()
-		 * was able to figure out how much memory is present in the
-		 * box so we initialize next_tag from it.
-		 */
-		if (memory_upper != (unsigned long) NULL)
-			next_tag = memory_upper;
-
-		/* Else we rely on the fact that the first tag we create for
-		 * a box for which we don't know how RAM it gots is a tag of
-		 * type tag_memupper.  This is ensured by the first entry in
-		 * the defaults tag list for such a box (see identify.c).
-		 * First we check this.
-		 */
-		else {
-			/* Ok it's a memupper tag: we put it's value in 
-			 * memory_upper so launch() can pass it to the
-			 * kernel in register a0 and we initialize next_tag.
-			 */
- 			next_tag = *(unsigned long *) data;
-			memory_upper = *((unsigned long *) data);
-		}
-	}
-
-	/* We put the tag structure.  */
-	addr = next_tag - (sizeof (tag));
-
-	memcpy ((void *) addr, (void *) &t, (size_t) (sizeof (tag)));
-
-	/* We put the tag's data if any.  */
-	if (size != 0) {
-		addr = addr - size;
-		memcpy ((void *) addr, data, (size_t) (t.size));
-	}
-
-	/*
-	 * Set next_tag ready for the next tag creation.
-	 */
-	next_tag = addr;
-	AddTagsEndSymbol();
-
-	return 0;
-}
-
-void SetUpBootInfo(void)
-{
-	unsigned long LongVar;
-	int atag;
-
-	/*
-	 * This is hard coded here but will change when we have a
-	 * Size mem routine.
-	 */
-
-	/*
-	 * 64mb of memory.
-	 */
-
- 	//mips_memory_upper = 0x84000000;
-
-
-#ifndef BOOTLOADER
-
-#if 0	/* You break'a the kernel I break'a ya face. -DaveM */
-
-	/* Eight meg of memory.         */
-	mips_memory_upper = 0x80800000;  /* XXX  this appears to be unused  - 
-                                           this assignment is not present in the normal
-                                           $cvstree/linux/arch/mips/cobalt/setup.c */
-#endif
-#else
-#include "../../../../include/diagdefs.h"
-	mips_memory_upper = (unsigned long) kBootloaderMipsMemoryUpper;
-#endif
- 
-	LongVar = mips_memory_upper;
-	atag = bi_TagAdd(tag_memupper, ULONGSIZE, &LongVar);
-
-	/* Here is the machine type.
-	*/
-	LongVar = MACH_COBALT_27;
-	atag = bi_TagAdd(tag_machtype, ULONGSIZE, &LongVar);
-
-	LongVar = 0x80000000;
-	atag = bi_TagAdd(tag_memlower, ULONGSIZE, &LongVar);
-
-	LongVar = CPU_R4300;
-	atag = bi_TagAdd(tag_cputype, ULONGSIZE, &LongVar);
-
-	LongVar = MACH_GROUP_COBALT;
-	atag = bi_TagAdd(tag_machgroup, ULONGSIZE, &LongVar);
-
-	LongVar = 0;
-	atag = bi_TagAdd(tag_scache_size, ULONGSIZE, &LongVar);
-
-	LongVar = 48;
-	atag = bi_TagAdd(tag_tlb_entries, ULONGSIZE, &LongVar);
-
- 	LongVar = 0;
-	atag = bi_TagAdd(tag_drive_info, ULONGSIZE, &LongVar);
-
-	LongVar = 0xe0800000;
-	atag = bi_TagAdd(tag_vram_base, ULONGSIZE, &LongVar);
-
-	LongVar = 0;
-	atag = bi_TagAdd(tag_dummy, 0, &LongVar);
-}
-
-void AddTagsEndSymbol(void)
-{
-	short	X;
-	X = 1;
-}
-
-/*
- * Oh shit, this is so crappy ...
- */
-#include <linux/mm.h>
-#include <asm/pgtable.h>
-int my_cacheflush(unsigned long start, unsigned long size, unsigned int what)
-{
-	flush_cache_range(current->mm, start, start + size);
-	return 0;
-}
-
-
-/*
- * The ROM set the flag to 0x1 to turn off output.  This is interpreted
- * as "valid", "no kernel output", and index '0' into the following
- * tables.  We overload entry '0' to specify a sensible default rate.
- */
-static int cons_baud_int[]  = { 9600, 0,  9600, 0, 0,  115200, 0, 0 };
-static int cons_baud_baud[] = { B9600, 0, B9600, 0, 0, B115200, 0, 0 };
-
-static union cobalt_cons_info
-cobalt_get_console_info(void)
-{
-	char board_id = 0;
-	static union cobalt_cons_info cons_info;
-	static int read_info = 0;
-	extern void add_init_env(char *);
-
-	if (read_info)
-		return cons_info;
-
-	VIA_PORT_WRITE(VIA_CMOS_ADDR, VIA_CMOS_CONSOLE_FLG);
-	cons_info.ccons_char = VIA_PORT_READ(VIA_CMOS_DATA);
-
-#if 0
-	printk("cobalt_get_console_info: read 0x%x from console flag\n",
-	       cons_info.ccons_char);
-#endif
-
-	/*
-	 * CMOS hasn't been initialized or baud rate isn't known.
-	 * - read the board id and provide backwards compat.
-	 */
-	if (cons_info.ccons_bits.valid != VIA_CMOS_CONS_VALID
-	    || ! cons_baud_int[cons_info.ccons_bits.baud]
-	    || ! cons_baud_baud[cons_info.ccons_bits.baud]) {
-		pcibios_read_config_byte(0, PCI_DEVSHFT(COBALT_PCICONF_VIA),
-	                                 VIA_COBALT_BRD_ID_REG, &board_id);
-
-#if 0
-		printk("cobalt_get_console_info: read 0x%x from board config\n",
-		       board_id);
-#endif
-
-		switch (VIA_COBALT_BRD_REG_to_ID(board_id)) {
-		case COBALT_BRD_ID_QUBE1:
-			cons_info.ccons_bits.baud = VIA_CMOS_CONS_115K;
-			cons_info.ccons_bits.kout = 1;
-			break;
-		case COBALT_BRD_ID_RAQ1:
-			cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
-			cons_info.ccons_bits.kout = 1;
-			break;
-		case COBALT_BRD_ID_QUBE2:
-			cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
-			cons_info.ccons_bits.kout = 0;
-			break;
-		case COBALT_BRD_ID_RAQ2:
-			cons_info.ccons_bits.baud = VIA_CMOS_CONS_9600;
-			cons_info.ccons_bits.kout = 1;
-			break;
-		}
-		cons_info.ccons_bits.valid = VIA_CMOS_CONS_VALID;
-	}
-
-	read_info = 1;
-
-#if defined(DEBUG_LOADER)
-	cons_info.ccons_bits.kout = 1;
-#endif
-
-	if (!cons_info.ccons_bits.kout) {
-		add_init_env("CONSOLE=/dev/null");
-	}
-
-#if 0
-	printk("cobalt_get_console_info: returning 0x%x\n",
-		cons_info.ccons_char);
-#endif
-
-	return cons_info;
-}
-
-int
-cobalt_cons_koutok(void)
-{
-	union cobalt_cons_info cons;
-
-	cons = cobalt_get_console_info();
-
-	return cons.ccons_bits.kout;
-}
-
-int
-cobalt_cons_baudbaud(void)
-{
-	union cobalt_cons_info cons;
-
-	cons = cobalt_get_console_info();
-
-	return cons_baud_baud[cons.ccons_bits.baud];
-}
-
-int
-cobalt_cons_baudint(void)
-{
-	union cobalt_cons_info cons;
-
-	cons = cobalt_get_console_info();
-
-	return cons_baud_int[cons.ccons_bits.baud];
-}
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/via.c linux/arch/mips/cobalt/via.c
--- v2.4.1/linux/arch/mips/cobalt/via.c	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/via.c	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-/*
- * Interrupt handling for the VIA ISA bridge.
- *
- * Everything the same ... just different ...
- */
-#include <linux/kernel.h>
-#include <asm/cobalt.h>
-#include <asm/ptrace.h>
-#include <asm/io.h>
-
-extern asmlinkage void do_IRQ(int irq, struct pt_regs * regs);
-
-extern unsigned char cache_21;
-extern unsigned char cache_A1;
-
-/*
- * (un)mask_irq, disable_irq() and enable_irq() only handle (E)ISA and
- * PCI devices.  Other onboard hardware needs specific routines.
- */
-void mask_irq(unsigned int irq_nr)
-{
-	unsigned char mask;
-
-	mask = 1 << (irq_nr & 7);
-	if (irq_nr < 8) {
-		cache_21 |= mask;
-		outb(cache_21, 0x10000021);
-	} else {
-		cache_A1 |= mask;
-		outb(cache_A1, 0x100000a1);
-	}
-}
-
-void unmask_irq(unsigned int irq_nr)
-{
-	unsigned char mask;
-
-	mask = ~(1 << (irq_nr & 7));
-	if (irq_nr < 8) {
-		cache_21 &= mask;
-		outb(cache_21, 0x10000021);
-	} else {
-		cache_A1 &= mask;
-		outb(cache_A1, 0x100000a1);
-	}
-}
-
-asmlinkage void via_irq(struct pt_regs *regs)
-{
-	char mstat, sstat;
-  
-	/* Read Master Status */
-	VIA_PORT_WRITE(0x20, 0x0C);
-	mstat = VIA_PORT_READ(0x20);
- 
-	if (mstat < 0) {
-		mstat &= 0x7f;
-		if (mstat != 2) {     	
-			do_IRQ(mstat, regs);
-			VIA_PORT_WRITE(0x20, mstat | 0x20);
-		} else {
-			sstat = VIA_PORT_READ(0xA0);
-
-			/* Slave interrupt */
-			VIA_PORT_WRITE(0xA0, 0x0C);
-			sstat = VIA_PORT_READ(0xA0);
-   
-			if (sstat < 0) {
-				do_IRQ((sstat + 8) & 0x7f, regs);
-				VIA_PORT_WRITE(0x20, 0x22);       
-				VIA_PORT_WRITE(0xA0, (sstat & 0x7f) | 0x20);
-			} else {
-				printk("Spurious slave interrupt...\n");
-			}
-		}
-	} else
-		printk("Spurious master interrupt...");
-}
-
-asmlinkage void galileo_irq(struct pt_regs *regs)
-{
-	unsigned long irq_src = *((unsigned long *) 0xb4000c18); 
-  
-	/* Check for timer irq ... */
-	if (irq_src & 0x00000100) {
-		*((volatile unsigned long *) 0xb4000c18) = 0;
-		do_IRQ(0, regs);
-	} else
-		printk("Spurious Galileo interrupt...\n");
-}
diff -u --recursive --new-file v2.4.1/linux/arch/mips/cobalt/z8530.h linux/arch/mips/cobalt/z8530.h
--- v2.4.1/linux/arch/mips/cobalt/z8530.h	Sun Jul  9 22:18:15 2000
+++ linux/arch/mips/cobalt/z8530.h	Wed Dec 31 16:00:00 1969
@@ -1,219 +0,0 @@
-/* 8530 Serial Communications Controller Register definitions */
-#define	FLAG	0x7e
-
-/* Write Register 0 */
-#define	R0	0		/* Register selects */
-#define	R1	1
-#define	R2	2
-#define	R3	3
-#define	R4	4
-#define	R5	5
-#define	R6	6
-#define	R7	7
-#define	R8	8
-#define	R9	9
-#define	R10	10
-#define	R11	11
-#define	R12	12
-#define	R13	13
-#define	R14	14
-#define	R15	15
-
-#define	NULLCODE	0	/* Null Code */
-#define	POINT_HIGH	0x8	/* Select upper half of registers */
-#define	RES_EXT_INT	0x10	/* Reset Ext. Status Interrupts */
-#define	SEND_ABORT	0x18	/* HDLC Abort */
-#define	RES_RxINT_FC	0x20	/* Reset RxINT on First Character */
-#define	RES_Tx_P	0x28	/* Reset TxINT Pending */
-#define	ERR_RES		0x30	/* Error Reset */
-#define	RES_H_IUS	0x38	/* Reset highest IUS */
-
-#define	RES_Rx_CRC	0x40	/* Reset Rx CRC Checker */
-#define	RES_Tx_CRC	0x80	/* Reset Tx CRC Checker */
-#define	RES_EOM_L	0xC0	/* Reset EOM latch */
-
-/* Write Register 1 */
-
-#define	EXT_INT_ENAB	0x1	/* Ext Int Enable */
-#define	TxINT_ENAB	0x2	/* Tx Int Enable */
-#define	PAR_SPEC	0x4	/* Parity is special condition */
-
-#define	RxINT_DISAB	0	/* Rx Int Disable */
-#define	RxINT_FCERR	0x8	/* Rx Int on First Character Only or Error */
-#define	INT_ALL_Rx	0x10	/* Int on all Rx Characters or error */
-#define	INT_ERR_Rx	0x18	/* Int on error only */
-
-#define	WT_RDY_RT	0x20	/* Wait/Ready on R/T */
-#define	WT_FN_RDYFN	0x40	/* Wait/FN/Ready FN */
-#define	WT_RDY_ENAB	0x80	/* Wait/Ready Enable */
-
-/* Write Register #2 (Interrupt Vector) */
-
-/* Write Register 3 */
-
-#define	RxENABLE	0x1	/* Rx Enable */
-#define	SYNC_L_INH	0x2	/* Sync Character Load Inhibit */
-#define	ADD_SM		0x4	/* Address Search Mode (SDLC) */
-#define	RxCRC_ENAB	0x8	/* Rx CRC Enable */
-#define	ENT_HM		0x10	/* Enter Hunt Mode */
-#define	AUTO_ENAB	0x20	/* Auto Enables */
-#define	Rx5		0x0	/* Rx 5 Bits/Character */
-#define	Rx7		0x40	/* Rx 7 Bits/Character */
-#define	Rx6		0x80	/* Rx 6 Bits/Character */
-#define	Rx8		0xc0	/* Rx 8 Bits/Character */
-
-/* Write Register 4 */
-
-#define	PAR_ENA		0x1	/* Parity Enable */
-#define	PAR_EVEN	0x2	/* Parity Even/Odd* */
-
-#define	SYNC_ENAB	0	/* Sync Modes Enable */
-#define	SB1		0x4	/* 1 stop bit/char */
-#define	SB15		0x8	/* 1.5 stop bits/char */
-#define	SB2		0xc	/* 2 stop bits/char */
-
-#define	MONSYNC		0	/* 8 Bit Sync character */
-#define	BISYNC		0x10	/* 16 bit sync character */
-#define	SDLC		0x20	/* SDLC Mode (01111110 Sync Flag) */
-#define	EXTSYNC		0x30	/* External Sync Mode */
-
-#define	X1CLK		0x0	/* x1 clock mode */
-#define	X16CLK		0x40	/* x16 clock mode */
-#define	X32CLK		0x80	/* x32 clock mode */
-#define	X64CLK		0xC0	/* x64 clock mode */
-
-/* Write Register 5 */
-
-#define	TxCRC_ENAB	0x1	/* Tx CRC Enable */
-#define	RTS		0x2	/* RTS */
-#define	SDLC_CRC	0x4	/* SDLC/CRC-16 */
-#define	TxENAB		0x8	/* Tx Enable */
-#define	SND_BRK		0x10	/* Send Break */
-#define	Tx5		0x0	/* Tx 5 bits (or less)/character */
-#define	Tx7		0x20	/* Tx 7 bits/character */
-#define	Tx6		0x40	/* Tx 6 bits/character */
-#define	Tx8		0x60	/* Tx 8 bits/character */
-#define	DTR		0x80	/* DTR */
-
-/* Write Register 6 (Sync bits 0-7/SDLC Address Field) */
-
-/* Write Register 7 (Sync bits 8-15/SDLC 01111110) */
-
-/* Write Register 8 (transmit buffer) */
-
-/* Write Register 9 (Master interrupt control) */
-#define	VIS	1	/* Vector Includes Status */
-#define	NV	2	/* No Vector */
-#define	DLC	4	/* Disable Lower Chain */
-#define	MIE	8	/* Master Interrupt Enable */
-#define	STATHI	0x10	/* Status high */
-#define	NORESET	0	/* No reset on write to R9 */
-#define	CHRB	0x40	/* Reset channel B */
-#define	CHRA	0x80	/* Reset channel A */
-#define	FHWRES	0xc0	/* Force hardware reset */
-
-/* Write Register 10 (misc control bits) */
-#define	BIT6	1	/* 6 bit/8bit sync */
-#define	LOOPMODE 2	/* SDLC Loop mode */
-#define	ABUNDER	4	/* Abort/flag on SDLC xmit underrun */
-#define	MARKIDLE 8	/* Mark/flag on idle */
-#define	GAOP	0x10	/* Go active on poll */
-#define	NRZ	0	/* NRZ mode */
-#define	NRZI	0x20	/* NRZI mode */
-#define	FM1	0x40	/* FM1 (transition = 1) */
-#define	FM0	0x60	/* FM0 (transition = 0) */
-#define	CRCPS	0x80	/* CRC Preset I/O */
-
-/* Write Register 11 (Clock Mode control) */
-#define	TRxCXT	0	/* TRxC = Xtal output */
-#define	TRxCTC	1	/* TRxC = Transmit clock */
-#define	TRxCBR	2	/* TRxC = BR Generator Output */
-#define	TRxCDP	3	/* TRxC = DPLL output */
-#define	TRxCOI	4	/* TRxC O/I */
-#define	TCRTxCP	0	/* Transmit clock = RTxC pin */
-#define	TCTRxCP	8	/* Transmit clock = TRxC pin */
-#define	TCBR	0x10	/* Transmit clock = BR Generator output */
-#define	TCDPLL	0x18	/* Transmit clock = DPLL output */
-#define	RCRTxCP	0	/* Receive clock = RTxC pin */
-#define	RCTRxCP	0x20	/* Receive clock = TRxC pin */
-#define	RCBR	0x40	/* Receive clock = BR Generator output */
-#define	RCDPLL	0x60	/* Receive clock = DPLL output */
-#define	RTxCX	0x80	/* RTxC Xtal/No Xtal */
-
-/* Write Register 12 (lower byte of baud rate generator time constant) */
-
-/* Write Register 13 (upper byte of baud rate generator time constant) */
-
-/* Write Register 14 (Misc control bits) */
-#define	BRENABL	1	/* Baud rate generator enable */
-#define	BRSRC	2	/* Baud rate generator source */
-#define	DTRREQ	4	/* DTR/Request function */
-#define	AUTOECHO 8	/* Auto Echo */
-#define	LOOPBAK	0x10	/* Local loopback */
-#define	SEARCH	0x20	/* Enter search mode */
-#define	RMC	0x40	/* Reset missing clock */
-#define	DISDPLL	0x60	/* Disable DPLL */
-#define	SSBR	0x80	/* Set DPLL source = BR generator */
-#define	SSRTxC	0xa0	/* Set DPLL source = RTxC */
-#define	SFMM	0xc0	/* Set FM mode */
-#define	SNRZI	0xe0	/* Set NRZI mode */
-
-/* Write Register 15 (external/status interrupt control) */
-#define	ZCIE	2	/* Zero count IE */
-#define	DCDIE	8	/* DCD IE */
-#define	SYNCIE	0x10	/* Sync/hunt IE */
-#define	CTSIE	0x20	/* CTS IE */
-#define	TxUIE	0x40	/* Tx Underrun/EOM IE */
-#define	BRKIE	0x80	/* Break/Abort IE */
-
-
-/* Read Register 0 */
-#define	Rx_CH_AV	0x1	/* Rx Character Available */
-#define	ZCOUNT		0x2	/* Zero count */
-#define	Tx_BUF_EMP	0x4	/* Tx Buffer empty */
-#define	DCD		0x8	/* DCD */
-#define	SYNC_HUNT	0x10	/* Sync/hunt */
-#define	CTS		0x20	/* CTS */
-#define	TxEOM		0x40	/* Tx underrun */
-#define	BRK_ABRT	0x80	/* Break/Abort */
-
-/* Read Register 1 */
-#define	ALL_SNT		0x1	/* All sent */
-/* Residue Data for 8 Rx bits/char programmed */
-#define	RES3		0x8	/* 0/3 */
-#define	RES4		0x4	/* 0/4 */
-#define	RES5		0xc	/* 0/5 */
-#define	RES6		0x2	/* 0/6 */
-#define	RES7		0xa	/* 0/7 */
-#define	RES8		0x6	/* 0/8 */
-#define	RES18		0xe	/* 1/8 */
-#define	RES28		0x0	/* 2/8 */
-/* Special Rx Condition Interrupts */
-#define	PAR_ERR		0x10	/* Parity error */
-#define	Rx_OVR		0x20	/* Rx Overrun Error */
-#define	CRC_ERR		0x40	/* CRC/Framing Error */
-#define	END_FR		0x80	/* End of Frame (SDLC) */
-
-/* Read Register 2 (channel b only) - Interrupt vector */
-
-/* Read Register 3 (interrupt pending register) ch a only */
-#define	CHBEXT	0x1		/* Channel B Ext/Stat IP */
-#define	CHBTxIP	0x2		/* Channel B Tx IP */
-#define	CHBRxIP	0x4		/* Channel B Rx IP */
-#define	CHAEXT	0x8		/* Channel A Ext/Stat IP */
-#define	CHATxIP	0x10		/* Channel A Tx IP */
-#define	CHARxIP	0x20		/* Channel A Rx IP */
-
-/* Read Register 8 (receive data register) */
-
-/* Read Register 10  (misc status bits) */
-#define	ONLOOP	2		/* On loop */
-#define	LOOPSEND 0x10		/* Loop sending */
-#define	CLK2MIS	0x40		/* Two clocks missing */
-#define	CLK1MIS	0x80		/* One clock missing */
-
-/* Read Register 12 (lower byte of baud rate generator constant) */
-
-/* Read Register 13 (upper byte of baud rate generator constant) */
-
-/* Read Register 15 (value of WR 15) */
diff -u --recursive --new-file v2.4.1/linux/arch/mips/dec/irq.c linux/arch/mips/dec/irq.c
--- v2.4.1/linux/arch/mips/dec/irq.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/dec/irq.c	Fri Feb  9 11:29:44 2001
@@ -15,7 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/kernel/irixelf.c linux/arch/mips/kernel/irixelf.c
--- v2.4.1/linux/arch/mips/kernel/irixelf.c	Sun Sep  3 11:49:25 2000
+++ linux/arch/mips/kernel/irixelf.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/file.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/personality.h>
 #include <linux/elfcore.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
--- v2.4.1/linux/arch/mips/kernel/irq.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c
--- v2.4.1/linux/arch/mips/kernel/process.c	Tue Sep  5 13:50:02 2000
+++ linux/arch/mips/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/sys.h>
 #include <linux/user.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/kernel/setup.c linux/arch/mips/kernel/setup.c
--- v2.4.1/linux/arch/mips/kernel/setup.c	Tue Jul 11 11:14:48 2000
+++ linux/arch/mips/kernel/setup.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/utsname.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/kernel/sysirix.c linux/arch/mips/kernel/sysirix.c
--- v2.4.1/linux/arch/mips/kernel/sysirix.c	Sat Aug 12 19:48:04 2000
+++ linux/arch/mips/kernel/sysirix.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
 #include <linux/pagemap.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/errno.h>
 #include <linux/timex.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/orion/irq.c linux/arch/mips/orion/irq.c
--- v2.4.1/linux/arch/mips/orion/irq.c	Fri Aug  4 16:15:38 2000
+++ linux/arch/mips/orion/irq.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/orion/misc.c linux/arch/mips/orion/misc.c
--- v2.4.1/linux/arch/mips/orion/misc.c	Fri Aug  4 18:31:19 2000
+++ linux/arch/mips/orion/misc.c	Fri Feb  9 11:29:44 2001
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/utsname.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/orion/setup.c linux/arch/mips/orion/setup.c
--- v2.4.1/linux/arch/mips/orion/setup.c	Fri Aug  4 18:31:19 2000
+++ linux/arch/mips/orion/setup.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/utsname.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips/sgi/kernel/indy_int.c linux/arch/mips/sgi/kernel/indy_int.c
--- v2.4.1/linux/arch/mips/sgi/kernel/indy_int.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/mips/sgi/kernel/indy_int.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/Makefile linux/arch/mips64/Makefile
--- v2.4.1/linux/arch/mips64/Makefile	Wed Dec  6 20:32:41 2000
+++ linux/arch/mips64/Makefile	Sun Feb  4 21:48:46 2001
@@ -33,7 +33,7 @@
 # machines may also.  Since BFD is incredibly buggy with respect to
 # crossformat linking we rely on the elf2ecoff tool for format conversion.
 #
-CFLAGS		+= -I $(TOPDIR)/include/asm $(CFLAGS)
+CFLAGS		+= -I $(TOPDIR)/include/asm/gcc $(CFLAGS)
 CFLAGS		+= -mabi=64 -G 0 -mno-abicalls -fno-pic -Wa,--trap -pipe
 LINKFLAGS	+= -G 0 -static # -N
 MODFLAGS	+= -mlong-calls
@@ -153,7 +153,6 @@
 
 archclean:
 	@$(MAKEBOOT) clean
-	$(MAKE) -C arch/$(ARCH)/kernel clean
 	$(MAKE) -C arch/$(ARCH)/tools clean
 	rm -f vmlinux.64 arch/$(ARCH)/ld.script.elf32
 
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/arc/Makefile linux/arch/mips64/arc/Makefile
--- v2.4.1/linux/arch/mips64/arc/Makefile	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/arc/Makefile	Sun Feb  4 21:48:46 2001
@@ -3,15 +3,13 @@
 #
 
 L_TARGET = arclib.a
-L_OBJS  = init.o printf.o tree.o env.o cmdline.o misc.o time.o \
-	  file.o identify.o
+obj-y	:= init.o printf.o tree.o env.o cmdline.o misc.o time.o file.o \
+	   identify.o
 
 ifndef CONFIG_SGI_IP27
-L_OBJS += console.o
+  obj-y += console.o
 endif
 
-ifdef CONFIG_ARC_MEMORY
-L_OBJS += memory.o
-endif
+obj-$(CONFIG_ARC_MEMORY) += memory.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/boot/Makefile linux/arch/mips64/boot/Makefile
--- v2.4.1/linux/arch/mips64/boot/Makefile	Sun Jul  9 22:18:16 2000
+++ linux/arch/mips64/boot/Makefile	Sun Feb  4 21:48:46 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/18 21:46:52 ralf Exp $
 #
 # 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
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/config.in linux/arch/mips64/config.in
--- v2.4.1/linux/arch/mips64/config.in	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/config.in	Sun Feb  4 21:48:46 2001
@@ -1,4 +1,3 @@
-# $Id: config.in,v 1.19 2000/03/27 01:44:45 ralf Exp $
 #
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
@@ -76,7 +75,7 @@
 	"R4300 CONFIG_CPU_R4300			\
 	 R4x00 CONFIG_CPU_R4X00			\
 	 R5000 CONFIG_CPU_R5000			\
-	 R56x0 CONFIG_CPU_NEVADA		\
+	 R52x0 CONFIG_CPU_NEVADA		\
 	 R8000 CONFIG_CPU_R8000			\
 	 R10000 CONFIG_CPU_R10000" R4x00
 endmenu
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/defconfig linux/arch/mips64/defconfig
--- v2.4.1/linux/arch/mips64/defconfig	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/defconfig	Sun Feb  4 21:48:46 2001
@@ -91,7 +91,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -144,6 +143,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -350,6 +350,8 @@
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -405,8 +407,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -426,6 +426,7 @@
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 CONFIG_KCORE_ELF=y
 
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/defconfig-ip22 linux/arch/mips64/defconfig-ip22
--- v2.4.1/linux/arch/mips64/defconfig-ip22	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/defconfig-ip22	Sun Feb  4 21:48:46 2001
@@ -81,7 +81,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -267,6 +266,8 @@
 # CONFIG_QUOTA is not set
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -321,8 +322,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -331,6 +330,7 @@
 #
 # CONFIG_PARTITION_ADVANCED is not set
 CONFIG_SGI_PARTITION=y
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 
 #
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/defconfig-ip27 linux/arch/mips64/defconfig-ip27
--- v2.4.1/linux/arch/mips64/defconfig-ip27	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/defconfig-ip27	Sun Feb  4 21:48:46 2001
@@ -91,7 +91,6 @@
 # CONFIG_MD_RAID1 is not set
 # CONFIG_MD_RAID5 is not set
 # CONFIG_BLK_DEV_LVM is not set
-# CONFIG_LVM_PROC_FS is not set
 
 #
 # Networking options
@@ -144,6 +143,7 @@
 CONFIG_BLK_DEV_SD=y
 CONFIG_SD_EXTRA_DEVS=40
 CONFIG_CHR_DEV_ST=y
+# CONFIG_CHR_DEV_OSST is not set
 # CONFIG_BLK_DEV_SR is not set
 # CONFIG_CHR_DEV_SG is not set
 
@@ -350,6 +350,8 @@
 # CONFIG_QUOTA is not set
 CONFIG_AUTOFS_FS=y
 # CONFIG_AUTOFS4_FS is not set
+# CONFIG_REISERFS_FS is not set
+# CONFIG_REISERFS_CHECK is not set
 # CONFIG_ADFS_FS is not set
 # CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
@@ -405,8 +407,6 @@
 # CONFIG_NCPFS_NFS_NS is not set
 # CONFIG_NCPFS_OS2_NS is not set
 # CONFIG_NCPFS_SMALLDOS is not set
-# CONFIG_NCPFS_MOUNT_SUBDIR is not set
-# CONFIG_NCPFS_NDS_DOMAINS is not set
 # CONFIG_NCPFS_NLS is not set
 # CONFIG_NCPFS_EXTRAS is not set
 
@@ -426,6 +426,7 @@
 CONFIG_SGI_PARTITION=y
 # CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
+# CONFIG_SMB_NLS is not set
 # CONFIG_NLS is not set
 CONFIG_KCORE_ELF=y
 
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/kernel/Makefile linux/arch/mips64/kernel/Makefile
--- v2.4.1/linux/arch/mips64/kernel/Makefile	Sun Jul  9 22:18:16 2000
+++ linux/arch/mips64/kernel/Makefile	Sun Feb  4 21:48:46 2001
@@ -12,27 +12,20 @@
 all:	kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
-O_OBJS	:= branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \
+
+export-objs = mips64_ksyms.o
+
+obj-y	:= branch.o entry.o proc.o process.o ptrace.o r4k_cache.o r4k_fpu.o \
 	   r4k_genex.o r4k_switch.o r4k_tlb.o r4k_tlb_debug.o r4k_tlb_glue.o \
 	   scall_64.o semaphore.o setup.o signal.o softfp.o syscall.o \
 	   traps.o unaligned.o
-OX_OBJS := mips64_ksyms.o
-
-ifdef CONFIG_MIPS32_COMPAT
-O_OBJS += linux32.o scall_o32.o signal32.o ioctl32.o
-endif
 
-ifdef CONFIG_BINFMT_ELF32
-O_OBJS += binfmt_elf32.o
-endif
-
-ifdef CONFIG_SMP
-O_OBJS += smp.o
-endif
+obj-$(CONFIG_MODULES)		+= mips64_ksyms.o
+obj-$(CONFIG_MIPS32_COMPAT)	+= linux32.o scall_o32.o signal32.o ioctl32.o
+obj-$(CONFIG_BINFMT_ELF32)	+= binfmt_elf32.o
+obj-$(CONFIG_SMP)		+= smp.o
 
 CFLAGS_r4k_genex.o := -P
 CFLAGS_r4k_tlb_glue.o := -P
-
-clean:
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c
--- v2.4.1/linux/arch/mips64/kernel/process.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -13,7 +13,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/sys.h>
 #include <linux/user.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/kernel/setup.c linux/arch/mips64/kernel/setup.c
--- v2.4.1/linux/arch/mips64/kernel/setup.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/kernel/setup.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/utsname.h>
 #include <linux/a.out.h>
@@ -55,6 +55,8 @@
  * Do we have a cyclecounter available?
  */
 char cyclecounter_available;
+
+unsigned long loops_per_sec;
 
 /*
  * Set if box has EISA slots.
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/kernel/smp.c linux/arch/mips64/kernel/smp.c
--- v2.4.1/linux/arch/mips64/kernel/smp.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/kernel/smp.c	Sun Feb  4 21:48:46 2001
@@ -57,7 +57,7 @@
 int smp_threads_ready;	/* Not used */
 atomic_t smp_commenced = ATOMIC_INIT(0);
 struct cpuinfo_mips cpu_data[NR_CPUS];
-int smp_num_cpus;		/* Number that came online.  */
+int smp_num_cpus = 1;		/* Number that came online.  */
 int __cpu_number_map[NR_CPUS];
 int __cpu_logical_map[NR_CPUS];
 cycles_t cacheflush_time;
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/lib/Makefile linux/arch/mips64/lib/Makefile
--- v2.4.1/linux/arch/mips64/lib/Makefile	Tue Dec  5 23:15:12 2000
+++ linux/arch/mips64/lib/Makefile	Sun Feb  4 21:48:46 2001
@@ -8,7 +8,8 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 L_TARGET = lib.a
-L_OBJS	= csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
+
+obj-y	+= csum_partial.o csum_partial_copy.o dump_tlb.o floppy-std.o \
 	  floppy-no.o ide-std.o ide-no.o kbd-std.o kbd-no.o rtc-std.o \
 	  rtc-no.o memset.o memcpy.o strlen_user.o strncpy_user.o \
 	  strnlen_user.o watch.o
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/lib/rtc-no.c linux/arch/mips64/lib/rtc-no.c
--- v2.4.1/linux/arch/mips64/lib/rtc-no.c	Sat May 13 08:30:17 2000
+++ linux/arch/mips64/lib/rtc-no.c	Sun Feb  4 21:48:46 2001
@@ -1,5 +1,4 @@
-/* $Id: rtc-no.c,v 1.1 1999/08/21 21:43:01 ralf Exp $
- *
+/*
  * 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.
@@ -7,9 +6,10 @@
  * Stub RTC routines to keep Linux from crashing on machine which don't
  * have a RTC chip.
  *
- * Copyright (C) 1998 by Ralf Baechle
+ * Copyright (C) 1998, 2001 by Ralf Baechle
  */
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 #include <linux/mc146818rtc.h>
 
 static unsigned char no_rtc_read_data(unsigned long addr)
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/lib/rtc-std.c linux/arch/mips64/lib/rtc-std.c
--- v2.4.1/linux/arch/mips64/lib/rtc-std.c	Sat May 13 08:30:17 2000
+++ linux/arch/mips64/lib/rtc-std.c	Sun Feb  4 21:48:46 2001
@@ -1,5 +1,4 @@
-/* $Id: rtc-std.c,v 1.1 1999/08/21 21:43:01 ralf Exp $
- *
+/*
  * 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.
@@ -8,6 +7,7 @@
  *
  * Copyright (C) 1998 by Ralf Baechle
  */
+#include <linux/spinlock.h>
 #include <linux/mc146818rtc.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/mm/Makefile linux/arch/mips64/mm/Makefile
--- v2.4.1/linux/arch/mips64/mm/Makefile	Sat May 13 08:30:17 2000
+++ linux/arch/mips64/mm/Makefile	Sun Feb  4 21:48:46 2001
@@ -1,33 +1,16 @@
-# $Id: Makefile,v 1.4 2000/01/17 23:32:46 ralf Exp $
 #
 # Makefile for the Linux/MIPS-specific parts of the memory manager.
 #
 
 O_TARGET := mm.o
-O_OBJS	 := extable.o init.o fault.o loadmmu.o
 
-ifdef CONFIG_CPU_R4300
-O_OBJS	+= r4xx0.o
-endif
-ifdef CONFIG_CPU_R4X00
-O_OBJS	+= r4xx0.o
-endif
-ifdef CONFIG_CPU_R5000
-O_OBJS	+= r4xx0.o
-endif
-ifdef CONFIG_CPU_NEVADA
-O_OBJS	+= r4xx0.o
-endif
-ifdef CONFIG_CPU_R10000
-O_OBJS	+= andes.o
-endif
+obj-y	 := extable.o init.o fault.o loadmmu.o
 
-ifdef CONFIG_SGI_IP22
-O_OBJS   += umap.o
-endif
-
-ifdef CONFIG_BAGET_MIPS
-O_OBJS   += umap.o
-endif
+obj-$(CONFIG_CPU_R4300)		+= r4xx0.o
+obj-$(CONFIG_CPU_R4X00)		+= r4xx0.o
+obj-$(CONFIG_CPU_R5000)		+= r4xx0.o
+obj-$(CONFIG_CPU_NEVADA)	+= r4xx0.o
+obj-$(CONFIG_CPU_R10000)	+= andes.o
+obj-$(CONFIG_SGI_IP22)		+= umap.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/mm/r4xx0.c linux/arch/mips64/mm/r4xx0.c
--- v2.4.1/linux/arch/mips64/mm/r4xx0.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/mm/r4xx0.c	Sun Feb  4 21:48:46 2001
@@ -2129,7 +2129,6 @@
 	       regs->cp0_epc, regs->cp0_badvaddr);
 	printk("Status  : %08x\nCause   : %08x\n",
 	       (unsigned int) regs->cp0_status, (unsigned int) regs->cp0_cause);
-//{static int x = 3; x--; if(!x) while(1);}
 }
 
 /* Detect and size the various r4k caches. */
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/sgi-ip22/Makefile linux/arch/mips64/sgi-ip22/Makefile
--- v2.4.1/linux/arch/mips64/sgi-ip22/Makefile	Sat May 13 08:30:17 2000
+++ linux/arch/mips64/sgi-ip22/Makefile	Sun Feb  4 21:48:46 2001
@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.1 1999/08/20 21:13:33 ralf Exp $
 #
 # Makefile for the SGI specific kernel interface routines
 # under Linux.
@@ -10,7 +9,8 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 L_TARGET = ip22.a
-L_OBJS  = ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \
-        ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o
+
+obj-y	+= ip22-berr.o ip22-mc.o ip22-sc.o ip22-hpc.o ip22-int.o ip22-rtc.o \
+	   ip22-setup.o system.o ip22-timer.o ip22-irq.o ip22-reset.o time.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/sgi-ip22/ip22-int.c linux/arch/mips64/sgi-ip22/ip22-int.c
--- v2.4.1/linux/arch/mips64/sgi-ip22/ip22-int.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/sgi-ip22/ip22-int.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/sgi-ip27/Makefile linux/arch/mips64/sgi-ip27/Makefile
--- v2.4.1/linux/arch/mips64/sgi-ip27/Makefile	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/sgi-ip27/Makefile	Sun Feb  4 21:48:46 2001
@@ -8,8 +8,9 @@
 	$(CC) $(CFLAGS) -c $< -o $*.o
 
 O_TARGET = ip27.a
-O_OBJS  = ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
-	  ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \
-	  ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o
+
+obj-y	:= ip27-berr.o ip27-console.o ip27-irq.o ip27-init.o ip27-irq-glue.o \
+	   ip27-klconfig.o ip27-klnuma.o ip27-memory.o ip27-nmi.o ip27-pci.o \
+	   ip27-pci-dma.o ip27-reset.o ip27-setup.o ip27-timer.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/sgi-ip27/ip27-init.c linux/arch/mips64/sgi-ip27/ip27-init.c
--- v2.4.1/linux/arch/mips64/sgi-ip27/ip27-init.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/sgi-ip27/ip27-init.c	Sun Feb  4 21:48:46 2001
@@ -472,9 +472,9 @@
 			sprintf(p->comm, "%s%d", "Idle", num_cpus);
 			init_tasks[num_cpus] = p;
 			alloc_cpupda(cpu, num_cpus);
+			del_from_runqueue(p);
 			p->processor = num_cpus;
 			p->has_cpu = 1; /* we schedule the first task manually */
-			del_from_runqueue(p);
 			unhash_process(p);
 			/* Attach to the address space of init_task. */
 			atomic_inc(&init_mm.mm_count);
diff -u --recursive --new-file v2.4.1/linux/arch/mips64/sgi-ip27/ip27-irq.c linux/arch/mips64/sgi-ip27/ip27-irq.c
--- v2.4.1/linux/arch/mips64/sgi-ip27/ip27-irq.c	Tue Nov 28 21:42:04 2000
+++ linux/arch/mips64/sgi-ip27/ip27-irq.c	Fri Feb  9 11:29:44 2001
@@ -13,7 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/ccio-dma.c linux/arch/parisc/kernel/ccio-dma.c
--- v2.4.1/linux/arch/parisc/kernel/ccio-dma.c	Wed Dec  6 11:46:39 2000
+++ linux/arch/parisc/kernel/ccio-dma.c	Fri Feb  9 11:29:44 2001
@@ -36,7 +36,7 @@
 #include <linux/init.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/pci.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/iosapic.c linux/arch/parisc/kernel/iosapic.c
--- v2.4.1/linux/arch/parisc/kernel/iosapic.c	Wed Dec  6 11:46:39 2000
+++ linux/arch/parisc/kernel/iosapic.c	Fri Feb  9 11:29:44 2001
@@ -162,7 +162,7 @@
 #include <linux/spinlock.h>
 #include <linux/pci.h>		/* pci cfg accessor functions  */
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>	/* irqaction */
 #include <linux/irq.h>		/* irq_region support */
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/irq.c linux/arch/parisc/kernel/irq.c
--- v2.4.1/linux/arch/parisc/kernel/irq.c	Wed Dec  6 11:46:39 2000
+++ linux/arch/parisc/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -35,7 +35,7 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/lba_pci.c linux/arch/parisc/kernel/lba_pci.c
--- v2.4.1/linux/arch/parisc/kernel/lba_pci.c	Wed Dec  6 11:46:39 2000
+++ linux/arch/parisc/kernel/lba_pci.c	Fri Feb  9 11:29:44 2001
@@ -36,7 +36,7 @@
 #include <linux/init.h>		/* for __init and __devinit */
 #include <linux/pci.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 
 #include <asm/byteorder.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/pci-dma.c linux/arch/parisc/kernel/pci-dma.c
--- v2.4.1/linux/arch/parisc/kernel/pci-dma.c	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/kernel/pci-dma.c	Fri Feb  9 11:29:44 2001
@@ -26,7 +26,7 @@
 #include <linux/pci.h>
 #include <linux/init.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/process.c linux/arch/parisc/kernel/process.c
--- v2.4.1/linux/arch/parisc/kernel/process.c	Wed Dec  6 11:46:39 2000
+++ linux/arch/parisc/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/interrupt.h>
 #include <linux/reboot.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/sba_iommu.c linux/arch/parisc/kernel/sba_iommu.c
--- v2.4.1/linux/arch/parisc/kernel/sba_iommu.c	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/kernel/sba_iommu.c	Fri Feb  9 11:29:44 2001
@@ -23,7 +23,7 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <linux/mm.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/kernel/setup.c linux/arch/parisc/kernel/setup.c
--- v2.4.1/linux/arch/parisc/kernel/setup.c	Wed Dec  6 11:46:39 2000
+++ linux/arch/parisc/kernel/setup.c	Fri Feb  9 11:29:44 2001
@@ -28,7 +28,7 @@
 
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/arch/parisc/mm/kmap.c linux/arch/parisc/mm/kmap.c
--- v2.4.1/linux/arch/parisc/mm/kmap.c	Tue Dec  5 12:29:39 2000
+++ linux/arch/parisc/mm/kmap.c	Fri Feb  9 11:29:44 2001
@@ -7,7 +7,7 @@
 #include <linux/string.h>
 #include <linux/pci.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8260_io/enet.c linux/arch/ppc/8260_io/enet.c
--- v2.4.1/linux/arch/ppc/8260_io/enet.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/ppc/8260_io/enet.c	Fri Feb  9 11:29:44 2001
@@ -30,7 +30,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8260_io/fcc_enet.c linux/arch/ppc/8260_io/fcc_enet.c
--- v2.4.1/linux/arch/ppc/8260_io/fcc_enet.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/ppc/8260_io/fcc_enet.c	Fri Feb 16 16:02:34 2001
@@ -23,7 +23,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -46,7 +46,7 @@
 #define TX_TIMEOUT	(2*HZ)
 
 /* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it it best
+ * pool.  The code may assume these are power of two, so it is best
  * to keep them that size.
  * We don't need to allocate pages for the transmitter.  We just use
  * the skbuffer directly.
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8260_io/uart.c linux/arch/ppc/8260_io/uart.c
--- v2.4.1/linux/arch/ppc/8260_io/uart.c	Wed Dec  6 12:06:18 2000
+++ linux/arch/ppc/8260_io/uart.c	Fri Feb  9 11:29:44 2001
@@ -38,7 +38,7 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8xx_io/commproc.h linux/arch/ppc/8xx_io/commproc.h
--- v2.4.1/linux/arch/ppc/8xx_io/commproc.h	Thu Jul 13 09:42:50 2000
+++ linux/arch/ppc/8xx_io/commproc.h	Fri Feb 16 16:02:34 2001
@@ -76,7 +76,7 @@
 	uint	cbd_bufaddr;	/* Buffer address in host memory */
 } cbd_t;
 
-#define BD_SC_EMPTY	((ushort)0x8000)	/* Recieve is empty */
+#define BD_SC_EMPTY	((ushort)0x8000)	/* Receive is empty */
 #define BD_SC_READY	((ushort)0x8000)	/* Transmit is ready */
 #define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor */
 #define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8xx_io/enet.c linux/arch/ppc/8xx_io/enet.c
--- v2.4.1/linux/arch/ppc/8xx_io/enet.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/ppc/8xx_io/enet.c	Fri Feb  9 11:29:44 2001
@@ -29,7 +29,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8xx_io/fec.c linux/arch/ppc/8xx_io/fec.c
--- v2.4.1/linux/arch/ppc/8xx_io/fec.c	Sat Feb  3 19:51:22 2001
+++ linux/arch/ppc/8xx_io/fec.c	Fri Feb 16 16:02:34 2001
@@ -33,7 +33,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -73,7 +73,7 @@
 } phy_info_t;
 
 /* The number of Tx and Rx buffers.  These are allocated from the page
- * pool.  The code may assume these are power of two, so it it best
+ * pool.  The code may assume these are power of two, so it is best
  * to keep them that size.
  * We don't need to allocate pages for the transmitter.  We just use
  * the skbuffer directly.
@@ -953,7 +953,7 @@
 /* 
  * I had some nice ideas of running the MDIO faster...
  * The 971 should support 8MHz and I tried it, but things acted really
- * wierd, so 2.5 MHz ought to be enough for anyone...
+ * weird, so 2.5 MHz ought to be enough for anyone...
  */
 
 static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/8xx_io/uart.c linux/arch/ppc/8xx_io/uart.c
--- v2.4.1/linux/arch/ppc/8xx_io/uart.c	Wed Dec  6 12:06:18 2000
+++ linux/arch/ppc/8xx_io/uart.c	Fri Feb  9 11:29:44 2001
@@ -34,7 +34,7 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/amiga/amiints.c linux/arch/ppc/amiga/amiints.c
--- v2.4.1/linux/arch/ppc/amiga/amiints.c	Wed Feb  9 19:43:47 2000
+++ linux/arch/ppc/amiga/amiints.c	Fri Feb 16 16:02:34 2001
@@ -119,7 +119,7 @@
 	custom.intreq = 0x7fff;
 
 #ifdef CONFIG_APUS
-	/* Clear any inter-CPU interupt requests. Circumvents bug in
+	/* Clear any inter-CPU interrupt requests. Circumvents bug in
            Blizzard IPL emulation HW (or so it appears). */
 	APUS_WRITE(APUS_INT_LVL, INTLVL_SETRESET | INTLVL_MASK);
 
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/checks.c linux/arch/ppc/kernel/checks.c
--- v2.4.1/linux/arch/ppc/kernel/checks.c	Wed May 26 16:55:40 1999
+++ linux/arch/ppc/kernel/checks.c	Fri Feb  9 11:29:44 2001
@@ -7,7 +7,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/chrp_setup.c linux/arch/ppc/kernel/chrp_setup.c
--- v2.4.1/linux/arch/ppc/kernel/chrp_setup.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/chrp_setup.c	Tue Feb 13 13:15:04 2001
@@ -18,7 +18,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/idle.c linux/arch/ppc/kernel/idle.c
--- v2.4.1/linux/arch/ppc/kernel/idle.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/idle.c	Fri Feb  9 11:29:44 2001
@@ -21,7 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
--- v2.4.1/linux/arch/ppc/kernel/irq.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -40,7 +40,7 @@
 #include <linux/timex.h>
 #include <linux/config.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/irq.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/m8260_setup.c linux/arch/ppc/kernel/m8260_setup.c
--- v2.4.1/linux/arch/ppc/kernel/m8260_setup.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/m8260_setup.c	Fri Feb  9 11:29:44 2001
@@ -22,7 +22,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/m8xx_setup.c linux/arch/ppc/kernel/m8xx_setup.c
--- v2.4.1/linux/arch/ppc/kernel/m8xx_setup.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/m8xx_setup.c	Fri Feb  9 11:29:44 2001
@@ -22,7 +22,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/pmac_pic.c linux/arch/ppc/kernel/pmac_pic.c
--- v2.4.1/linux/arch/ppc/kernel/pmac_pic.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/pmac_pic.c	Fri Feb 16 16:02:34 2001
@@ -457,7 +457,7 @@
 /*
  * These procedures are used in implementing sleep on the powerbooks.
  * sleep_save_intrs() saves the states of all interrupt enables
- * and disables all interupts except for the nominated one.
+ * and disables all interrupts except for the nominated one.
  * sleep_restore_intrs() restores the states of all interrupt enables.
  */
 unsigned int sleep_save_mask[2];
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/pmac_setup.c linux/arch/ppc/kernel/pmac_setup.c
--- v2.4.1/linux/arch/ppc/kernel/pmac_setup.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/pmac_setup.c	Fri Feb  9 11:29:44 2001
@@ -30,7 +30,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/ppc_ksyms.c linux/arch/ppc/kernel/ppc_ksyms.c
--- v2.4.1/linux/arch/ppc/kernel/ppc_ksyms.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/ppc_ksyms.c	Tue Feb 13 13:15:04 2001
@@ -6,6 +6,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/interrupt.h>
+#include <linux/tty.h>
 #include <linux/vt_kern.h>
 #include <linux/nvram.h>
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/prep_nvram.c linux/arch/ppc/kernel/prep_nvram.c
--- v2.4.1/linux/arch/ppc/kernel/prep_nvram.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/prep_nvram.c	Fri Feb  9 11:29:44 2001
@@ -6,7 +6,7 @@
  */
 #include <linux/init.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 
 #include <asm/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/prep_setup.c linux/arch/ppc/kernel/prep_setup.c
--- v2.4.1/linux/arch/ppc/kernel/prep_setup.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/prep_setup.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/process.c linux/arch/ppc/kernel/process.c
--- v2.4.1/linux/arch/ppc/kernel/process.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -29,7 +29,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/elf.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/residual.c linux/arch/ppc/kernel/residual.c
--- v2.4.1/linux/arch/ppc/kernel/residual.c	Tue Oct 12 10:00:58 1999
+++ linux/arch/ppc/kernel/residual.c	Fri Feb  9 11:29:44 2001
@@ -30,7 +30,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
--- v2.4.1/linux/arch/ppc/kernel/setup.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/setup.c	Tue Feb 13 13:15:04 2001
@@ -12,6 +12,7 @@
 #include <linux/delay.h>
 #include <linux/blk.h>
 #include <linux/ide.h>
+#include <linux/tty.h>
 #include <linux/bootmem.h>
 
 #include <asm/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/softemu8xx.c linux/arch/ppc/kernel/softemu8xx.c
--- v2.4.1/linux/arch/ppc/kernel/softemu8xx.c	Tue Aug 31 11:36:43 1999
+++ linux/arch/ppc/kernel/softemu8xx.c	Fri Feb  9 11:29:44 2001
@@ -21,7 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
--- v2.4.1/linux/arch/ppc/kernel/traps.c	Sat Feb  3 19:51:23 2001
+++ linux/arch/ppc/kernel/traps.c	Fri Feb  9 11:29:44 2001
@@ -23,7 +23,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/arch/s390/Makefile linux/arch/s390/Makefile
--- v2.4.1/linux/arch/s390/Makefile	Fri May 12 11:41:44 2000
+++ linux/arch/s390/Makefile	Tue Feb 13 14:13:43 2001
@@ -14,6 +14,7 @@
 #
 
 LD=$(CROSS_COMPILE)ld -m elf_s390
+CPP=$(CC) -E
 OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
 LDFLAGS=-e start
 LINKFLAGS =-T $(TOPDIR)/arch/s390/vmlinux.lds $(LDFLAGS)
diff -u --recursive --new-file v2.4.1/linux/arch/s390/boot/Makefile linux/arch/s390/boot/Makefile
--- v2.4.1/linux/arch/s390/boot/Makefile	Fri May 12 11:41:44 2000
+++ linux/arch/s390/boot/Makefile	Tue Feb 13 14:13:43 2001
@@ -10,12 +10,11 @@
 OBJCOPY = $(CROSS_COMPILE)objcopy
 
 O_TARGET := 
-O_OBJS	 := 
 
 include $(TOPDIR)/Rules.make
 
 .S.o:
-	$(CC) $(AFLAGS) -traditional -c $< -o $*.o
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
 
 %.lnk: %.o
 	$(LD) -Ttext 0x0 -o $@ $<
diff -u --recursive --new-file v2.4.1/linux/arch/s390/boot/ipldump.S linux/arch/s390/boot/ipldump.S
--- v2.4.1/linux/arch/s390/boot/ipldump.S	Fri May 12 11:41:44 2000
+++ linux/arch/s390/boot/ipldump.S	Tue Feb 13 14:13:43 2001
@@ -38,7 +38,7 @@
 #
 # find out memory size
 #
-        mvc   104(8,0),.Lpcmem0          # setup program check handler
+        mvc   104(8),.Lpcmem0          # setup program check handler
         slr   %r3,%r3
         lhi   %r2,1
         sll   %r2,20
diff -u --recursive --new-file v2.4.1/linux/arch/s390/boot/ipleckd.S linux/arch/s390/boot/ipleckd.S
--- v2.4.1/linux/arch/s390/boot/ipleckd.S	Fri May 12 11:41:44 2000
+++ linux/arch/s390/boot/ipleckd.S	Tue Feb 13 14:13:43 2001
@@ -3,7 +3,7 @@
 #    IPL record for 3380/3390 DASD
 #
 #  S390 version
-#    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+#    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
 #    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
 #
 #
@@ -11,6 +11,8 @@
 # FIXME:	 should insert zeroes into memory when filling holes
 # FIXME:	 calculate blkpertrack from rdc data and blksize
 
+# change 09/20/00       removed obsolete store of ipldevice to textesegment
+
 # Usage of registers
 # r1:	ipl subchannel ( general use, dont overload without save/restore !)
 # r10:
@@ -39,7 +41,7 @@
 
 	.org 0xf0			# Lets start now...
 _start: .globl _start
-	l  	%r1,__LC_SUBCHANNEL_ID  # get IPL-subchannel from lowcore
+	l  	%r1,__LC_SUBCHANNEL_ID	# get IPL-subchannel from lowcore
 	st	%r1,__LC_IPLDEV         # keep it for reipl
 	stsch	.Lrdcdata
 	oi      .Lrdcdata+5,0x84        # enable ssch and multipath mode
@@ -111,10 +113,10 @@
 	mvc	0x600(256,%r3),0x180(%r4)
 	mvc	0x700(256,%r3),0x280(%r4)
 .Lrunkern:
-	lhi	%r2,17
-	sll	%r2,12
-	st	%r1,0xc6c(%r2)		# store iplsubchannel to lowcore
-	st	%r1,0xc6c		# store iplsubchannel to lowcore
+#	lhi	%r2,17
+#	sll	%r2,12
+#	st	%r1,0xc6c(%r2)		# store iplsubchannel to lowcore
+#	st	%r1,0xc6c		# store iplsubchannel to lowcore
 	br	%r3
 # This function does the start IO
 # r2:	number of first block to read ( input by caller )
@@ -140,17 +142,16 @@
 	lr	%r15,%r4		# save number or blocks
 	slr	%r7,%r7
 	icm	%r7,3,.Lrdcdata+14      # load heads to r7
+	lhi     %r6,9
+	clc     .Lrdcdata+3(2),.L9345
+	je	.L011
+	lhi	%r6,10
+	clc	.Lrdcdata+3(2),.L3380
+	je	.L011
+	lhi	%r6,12
 	clc	.Lrdcdata+3(2),.L3390     
-	jne	.L010			# 3380 or 3390 ?
-	lhi	%r6,12			# setup r6 correct!
-	j	.L011
-.L010:	
-        clc     .Lrdcdata+3(2),.L9343
-        jne     .L013
-        lhi     %r6,9
-        j       .L011
-.L013:
-	lhi	%r6,10	
+	je	.L011			
+        bras 	%r14,.Ldisab
 .L011:	
 	# loop for nbl times
 .Lrdloop:	
@@ -245,10 +246,13 @@
 	.long	0x00008000              # they are loaded with a LM
 .L3390:
 	.word 	0x3390
-.L9343:
-	.word	0x9343
+.L9345:
+	.word	0x9345
+.L3380:
+	.word	0x3380
 .Lnull:	
 	.long 0x00000000,0x00000000
+	.align 4
 .Lrdcdata:
 	.long 0x00000000,0x00000000
 	.long 0x00000000,0x00000000
diff -u --recursive --new-file v2.4.1/linux/arch/s390/config.in linux/arch/s390/config.in
--- v2.4.1/linux/arch/s390/config.in	Thu Nov 16 12:51:28 2000
+++ linux/arch/s390/config.in	Tue Feb 13 14:13:43 2001
@@ -44,30 +44,19 @@
 bool 'System V IPC' CONFIG_SYSVIPC
 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
 bool 'Sysctl support' CONFIG_SYSCTL
+define CONFIG_KCORE ELF
 tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
-
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG
 endmenu
 
 source drivers/s390/Config.in
 
-mainmenu_option next_comment
-comment 'Character devices'
-bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
-if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-  int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
-fi
-
-endmenu
-
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
 fi
 
 source fs/Config.in
-
-# source drivers/char/Config.in
-
-# source drivers/media/Config.in
 
 mainmenu_option next_comment
 comment 'Kernel hacking'
diff -u --recursive --new-file v2.4.1/linux/arch/s390/defconfig linux/arch/s390/defconfig
--- v2.4.1/linux/arch/s390/defconfig	Mon Jun 19 13:25:06 2000
+++ linux/arch/s390/defconfig	Tue Feb 13 14:13:43 2001
@@ -1,6 +1,9 @@
 #
 # Automatically generated by make menuconfig: don't edit
 #
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
 CONFIG_UID16=y
 CONFIG_ARCH_S390=y
 
@@ -20,7 +23,7 @@
 #
 CONFIG_MODULES=y
 # CONFIG_MODVERSIONS is not set
-# CONFIG_KMOD is not set
+CONFIG_KMOD=y
 
 #
 # General setup
@@ -34,41 +37,60 @@
 # CONFIG_BSD_PROCESS_ACCT is not set
 CONFIG_SYSCTL=y
 CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PROCESS_DEBUG is not set
 
 #
-# S/390 block device drivers
+# Block device drivers
 #
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_MD is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=24576
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_MDISK is not set
+CONFIG_BLK_DEV_XPRAM=m
 CONFIG_DASD=y
 CONFIG_DASD_ECKD=y
-# CONFIG_DASD_MDSK is not set
+CONFIG_DASD_FBA=y
 
 #
-# S/390 Network device support
+# Multi-device support (RAID and LVM)
 #
-# CONFIG_CHANDEV is not set
-CONFIG_NETDEVICES=y
-CONFIG_CTC=y
-CONFIG_IUCV=y
-# CONFIG_DUMMY is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_TR=y
-# CONFIG_FDDI is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_BLK_DEV_LVM=m
+CONFIG_LVM_PROC_FS=y
 
 #
-# S/390 Terminal and Console options
+# Character device drivers
 #
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
 CONFIG_3215=y
 CONFIG_3215_CONSOLE=y
 CONFIG_HWC=y
 CONFIG_HWC_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_S390_TAPE=m
+CONFIG_S390_TAPE_CHAR=y
+CONFIG_S390_TAPE_BLOCK=y
+CONFIG_S390_TAPE_3490=y
+CONFIG_S390_TAPE_3480=y
+
+#
+# Network device drivers
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_TR=y
+# CONFIG_FDDI is not set
+# CONFIG_CHANDEV is not set
+CONFIG_CTC=m
+CONFIG_IUCV=m
 
 #
 # Networking options
@@ -82,25 +104,24 @@
 # CONFIG_FILTER is not set
 CONFIG_UNIX=y
 CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_MULTICAST=y
 # CONFIG_IP_ADVANCED_ROUTER is not set
 # CONFIG_IP_PNP is not set
-# CONFIG_IP_ROUTER is not set
 # CONFIG_NET_IPIP is not set
 # CONFIG_NET_IPGRE is not set
-# CONFIG_IP_ALIAS is not set
+# CONFIG_INET_ECN is not set
 # CONFIG_SYN_COOKIES is not set
-CONFIG_SKB_LARGE=y
 # CONFIG_IPV6 is not set
 # CONFIG_KHTTPD is not set
 # CONFIG_ATM is not set
 # CONFIG_IPX is not set
 # CONFIG_ATALK is not set
 # CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
 # CONFIG_X25 is not set
 # CONFIG_LAPB is not set
-# CONFIG_BRIDGE is not set
 # CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
 # CONFIG_ECONET is not set
 # CONFIG_WAN_ROUTER is not set
 # CONFIG_NET_FASTROUTE is not set
@@ -118,6 +139,7 @@
 # CONFIG_AUTOFS_FS is not set
 # CONFIG_AUTOFS4_FS is not set
 # CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
 # CONFIG_AFFS_FS is not set
 # CONFIG_HFS_FS is not set
 # CONFIG_BFS_FS is not set
@@ -126,28 +148,37 @@
 # CONFIG_UMSDOS_FS is not set
 # CONFIG_VFAT_FS is not set
 # CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
 # CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
 # CONFIG_ISO9660_FS is not set
 # CONFIG_JOLIET is not set
 # CONFIG_MINIX_FS is not set
 # CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
 # CONFIG_HPFS_FS is not set
 CONFIG_PROC_FS=y
 # CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
 # CONFIG_DEVFS_DEBUG is not set
 # CONFIG_DEVPTS_FS is not set
 # CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
 # CONFIG_ROMFS_FS is not set
 CONFIG_EXT2_FS=y
 # CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
 # CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
 # CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
 
 #
 # Network File Systems
 #
 # CONFIG_CODA_FS is not set
 CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
 # CONFIG_ROOT_NFS is not set
 CONFIG_NFSD=y
 # CONFIG_NFSD_V3 is not set
@@ -155,6 +186,16 @@
 CONFIG_LOCKD=y
 # CONFIG_SMB_FS is not set
 # CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
 
 #
 # Partition Types
@@ -168,10 +209,10 @@
 # CONFIG_MAC_PARTITION is not set
 # CONFIG_MSDOS_PARTITION is not set
 # CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
 # CONFIG_SUN_PARTITION is not set
 # CONFIG_NLS is not set
 
 #
 # Kernel hacking
 #
-# CONFIG_REMOTE_DEBUG is not set
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/Makefile linux/arch/s390/kernel/Makefile
--- v2.4.1/linux/arch/s390/kernel/Makefile	Fri May 12 11:41:44 2000
+++ linux/arch/s390/kernel/Makefile	Tue Feb 13 14:13:43 2001
@@ -8,47 +8,25 @@
 # Note 2! The CFLAGS definitions are now in the main makefile...
 
 .S.o:
-	$(CC) $(AFLAGS) -traditional -c $< -o $*.o
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
 
 all: kernel.o head.o init_task.o
 
 O_TARGET := kernel.o
-O_OBJS   := lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \
-            setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
-            semaphore.o s390fpu.o s390io.o s390mach.o s390dyn.o reipl.o
-OX_OBJS := s390_ksyms.o
-MX_OBJS  :=
-
-ifdef CONFIG_SMP
-O_OBJS += smp.o
-endif
-
-ifdef CONFIG_PCI
-O_OBJS += bios32.o
-endif
 
-ifdef CONFIG_MCA
-O_OBJS += mca.o
-endif
-
-ifeq ($(CONFIG_MTRR),y)
-OX_OBJS += mtrr.o
-else
-  ifeq ($(CONFIG_MTRR),m)
-  MX_OBJS += mtrr.o
-  endif
-endif
+export-objs	:= s390_ksyms.o
+obj-y	:= lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \
+            setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
+            semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
 
-ifeq ($(CONFIG_IEEEFPU_EMULATION),y)
-  O_OBJS += mathemu.o floatlib.o
-endif
+obj-$(CONFIG_MODULES)		+= s390_ksyms.o
+obj-$(CONFIG_SMP)		+= smp.o
+obj-$(CONFIG_IEEEFPU_EMULATION)	+= mathemu.o floatlib.o
 
 #
 # Kernel debugging
 #
-ifdef CONFIG_REMOTE_DEBUG
-O_OBJS += gdb-stub.o #gdb-low.o 
-endif
+obj-$(CONFIG_REMOTE_DEBUG)	+= gdb-stub.o #gdb-low.o 
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/cpcmd.c linux/arch/s390/kernel/cpcmd.c
--- v2.4.1/linux/arch/s390/kernel/cpcmd.c	Fri May 12 11:41:44 2000
+++ linux/arch/s390/kernel/cpcmd.c	Tue Feb 13 14:13:43 2001
@@ -8,7 +8,7 @@
 
 #include <linux/stddef.h>
 #include <linux/kernel.h>
-#include <asm/string.h>
+#include <linux/string.h>
 #include <asm/ebcdic.h>
 
 void cpcmd(char *cmd, char *response, int rlen)
@@ -22,10 +22,10 @@
         ASCEBC(obuffer,olen);
 
         if (response != NULL && rlen > 0) {
-                asm volatile ("LRA   2,0(0,%0)\n\t"
+                asm volatile ("LRA   2,0(%0)\n\t"
                               "LR    4,%1\n\t"
                               "O     4,%4\n\t"
-                              "LRA   3,0(0,%2)\n\t"
+                              "LRA   3,0(%2)\n\t"
                               "LR    5,%3\n\t"
                               ".long 0x83240008 # Diagnose 83\n\t"
                               : /* no output */
@@ -34,7 +34,7 @@
                               : "2", "3", "4", "5" );
                 EBCASC(response, rlen);
         } else {
-                asm volatile ("LRA   2,0(0,%0)\n\t"
+                asm volatile ("LRA   2,0(%0)\n\t"
                               "LR    3,%1\n\t"
                               ".long 0x83230008 # Diagnose 83\n\t"
                               : /* no output */
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/debug.c linux/arch/s390/kernel/debug.c
--- v2.4.1/linux/arch/s390/kernel/debug.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390/kernel/debug.c	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,1167 @@
+/*
+ *  arch/s390/kernel/debug.c
+ *   S/390 debug facility
+ *
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+ *                             IBM Corporation
+ *    Author(s): Michael Holzheu (holzheu@de.ibm.com),
+ *               Holger Smolinski (Holger.Smolinski@de.ibm.com)
+ *
+ *    Bugreports to: <Linux390@de.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <asm/debug.h>
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+#if defined(CONFIG_ARCH_S390X)
+#define DEBUG_PROC_HEADER_SIZE 46
+#else
+#define DEBUG_PROC_HEADER_SIZE 38
+#endif
+
+#define ADD_BUFFER 1000
+
+/* typedefs */
+
+typedef struct file_private_info {
+	loff_t len;			/* length of output in byte */
+	int size;			/* size of buffer for output */
+	char *data;			/* buffer for output */
+	debug_info_t *debug_info;	/* the debug information struct */
+	struct debug_view *view;	/* used view of debug info */
+} file_private_info_t;
+
+extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
+
+/* internal function prototyes */
+
+static int debug_init(void);
+static int debug_format_output(debug_info_t * debug_area, char *buf,
+			       int size, struct debug_view *view);
+static ssize_t debug_output(struct file *file, char *user_buf,
+			    size_t user_len, loff_t * offset);
+static ssize_t debug_input(struct file *file, const char *user_buf,
+			   size_t user_len, loff_t * offset);
+static int debug_open(struct inode *inode, struct file *file);
+static int debug_close(struct inode *inode, struct file *file);
+static struct proc_dir_entry 
+*debug_create_proc_dir_entry(struct proc_dir_entry *root,
+			     const char *name, mode_t mode,
+			     struct inode_operations *iops,
+			     struct file_operations *fops);
+static void debug_delete_proc_dir_entry(struct proc_dir_entry *root,
+					struct proc_dir_entry *entry);
+static debug_info_t*  debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
+static void debug_info_get(debug_info_t *);
+static void debug_info_put(debug_info_t *);
+static int debug_prolog_level_fn(debug_info_t * id,
+				 struct debug_view *view, char *out_buf);
+static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
+				struct file *file, const char *user_buf,
+				size_t user_buf_size, loff_t * offset);
+static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
+                                char *out_buf, const char *in_buf);
+static int debug_raw_format_fn(debug_info_t * id,
+				 struct debug_view *view, char *out_buf,
+				 const char *in_buf);
+static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
+                         int area, debug_entry_t * entry, char *out_buf);
+
+/* globals */
+
+struct debug_view debug_raw_view = {
+	"raw",
+	NULL,
+	&debug_raw_header_fn,
+	&debug_raw_format_fn,
+	NULL
+};
+
+struct debug_view debug_hex_ascii_view = {
+	"hex_ascii",
+	NULL,
+	&debug_dflt_header_fn,
+	&debug_hex_ascii_format_fn,
+	NULL
+};
+
+struct debug_view debug_level_view = {
+	"level",
+	&debug_prolog_level_fn,
+	NULL,
+	NULL,
+	&debug_input_level_fn
+};
+
+/* static globals */
+
+static debug_info_t *debug_area_first = NULL;
+static debug_info_t *debug_area_last = NULL;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+static struct semaphore debug_lock = MUTEX;
+#else
+DECLARE_MUTEX(debug_lock);
+#endif
+
+static int initialized = 0;
+
+static struct file_operations debug_file_ops = {
+	read:    debug_output,
+	write:   debug_input,	
+	open:    debug_open,
+	release: debug_close,
+};
+
+static struct inode_operations debug_inode_ops = {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+	default_file_ops: &debug_file_ops,	/* file ops */
+#endif
+};
+
+
+static struct proc_dir_entry *debug_proc_root_entry;
+
+
+/* functions */
+
+/*
+ * debug_info_create
+ * - create new debug-info
+ */
+
+static debug_info_t*  debug_info_create(char *name, int page_order, 
+                                        int nr_areas, int buf_size)
+{
+	debug_info_t* rc;
+	int i;
+
+        /* alloc everything */
+
+        rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC);
+        if(!rc) 
+		goto fail_malloc_rc;
+	rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC);
+	if(!rc->active_entry)
+		goto fail_malloc_active_entry;
+	memset(rc->active_entry, 0, nr_areas * sizeof(int));
+        rc->areas = (debug_entry_t **) kmalloc(nr_areas *
+                                               sizeof(debug_entry_t *),
+                                               GFP_ATOMIC);
+        if (!rc->areas) 
+                goto fail_malloc_areas;
+        for (i = 0; i < nr_areas; i++) {
+                rc->areas[i] =
+                    (debug_entry_t *) __get_free_pages(GFP_ATOMIC,
+                                                       page_order);
+                if (!rc->areas[i]) {
+                        for (i--; i >= 0; i--) {
+                                free_pages((unsigned long) rc->areas[i],
+                                           page_order);
+                        }
+                        goto fail_malloc_areas2;
+                } else {
+                        memset(rc->areas[i], 0, PAGE_SIZE << page_order);
+                }
+        }
+
+        /* initialize members */
+
+        spin_lock_init(&rc->lock);
+        rc->page_order  = page_order;
+        rc->nr_areas    = nr_areas;
+        rc->active_area = 0;
+        rc->level       = DEBUG_DEFAULT_LEVEL;
+        rc->buf_size    = buf_size;
+        rc->entry_size  = sizeof(debug_entry_t) + buf_size;
+        strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1)));
+        rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0;
+        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
+	memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS * 
+               sizeof(struct proc_dir_entry*));
+        atomic_set(&(rc->ref_count), 0);
+        rc->proc_root_entry =
+            debug_create_proc_dir_entry(debug_proc_root_entry, rc->name,
+                                        S_IFDIR | S_IRUGO | S_IXUGO |
+                                        S_IWUSR | S_IWGRP, NULL, NULL);
+
+	/* append new element to linked list */
+
+        if(debug_area_first == NULL){
+                /* first element in list */
+                debug_area_first = rc;
+                rc->prev = NULL;
+        }
+        else{
+                /* append element to end of list */
+                debug_area_last->next = rc;
+                rc->prev = debug_area_last;
+        }
+        debug_area_last = rc;
+        rc->next = NULL;
+
+	debug_info_get(rc);
+	return rc;
+
+fail_malloc_areas2:
+	kfree(rc->areas);
+fail_malloc_areas:
+	kfree(rc->active_entry);
+fail_malloc_active_entry:
+	kfree(rc);
+fail_malloc_rc:
+	return NULL;
+}
+
+/*
+ * debug_info_get
+ * - increments reference count for debug-info
+ */
+
+static void debug_info_get(debug_info_t * db_info)
+{
+	if (db_info)
+		atomic_inc(&db_info->ref_count);
+}
+
+/*
+ * debug_info_put:
+ * - decreases reference count for debug-info and frees it if necessary
+ */
+
+static void debug_info_put(debug_info_t *db_info)
+{
+	int i;
+
+	if (!db_info)
+		return;
+	if (atomic_dec_and_test(&db_info->ref_count)) {
+		printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
+		       db_info, db_info->name);
+		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+			if (db_info->views[i] != NULL)
+				debug_delete_proc_dir_entry
+				    (db_info->proc_root_entry,
+				     db_info->proc_entries[i]);
+		}
+		debug_delete_proc_dir_entry(debug_proc_root_entry,
+					    db_info->proc_root_entry);
+		for (i = 0; i < db_info->nr_areas; i++) {
+			free_pages((unsigned long) db_info->areas[i],
+				   db_info->page_order);
+		}
+		kfree(db_info->areas);
+		kfree(db_info->active_entry);
+		if(db_info == debug_area_first)
+			debug_area_first = db_info->next;
+		if(db_info == debug_area_last)
+			debug_area_last = db_info->prev;
+		if(db_info->prev) db_info->prev->next = db_info->next;
+		if(db_info->next) db_info->next->prev = db_info->prev;
+		kfree(db_info);
+	}
+}
+
+
+/*
+ * debug_output:
+ * - called for user read()
+ * - copies formated output form private_data of the file
+ *   handle to the user buffer
+ */
+
+static ssize_t debug_output(struct file *file,	/* file descriptor */
+			    char *user_buf,	/* user buffer */
+			    size_t user_len,	/* length of buffer */
+			    loff_t *offset	/* offset in the file */ )
+{
+	loff_t len;
+	int rc;
+	file_private_info_t *p_info;
+
+	p_info = ((file_private_info_t *) file->private_data);
+	if (*offset >= p_info->len) {
+		return 0;	/* EOF */
+	} else {
+		len = MIN(user_len, (p_info->len - *offset));
+		if ((rc = copy_to_user(user_buf, &(p_info->data[*offset]),len)))
+			return rc;;
+		(*offset) += len;
+		return len;	/* number of bytes "read" */
+	}
+}
+
+/*
+ * debug_input:
+ * - called for user write()
+ * - calls input function of view
+ */
+
+static ssize_t debug_input(struct file *file,
+			   const char *user_buf, size_t length,
+			   loff_t *offset)
+{
+	int rc = 0;
+	file_private_info_t *p_info;
+
+	down(&debug_lock);
+	p_info = ((file_private_info_t *) file->private_data);
+	if (p_info->view->input_proc)
+		rc = p_info->view->input_proc(p_info->debug_info,
+					      p_info->view, file, user_buf,
+					      length, offset);
+	up(&debug_lock);
+	return rc;		/* number of input characters */
+}
+
+/*
+ * debug_format_output:
+ * - calls prolog, header and format functions of view to format output
+ */
+
+static int debug_format_output(debug_info_t * debug_area, char *buf,
+			       int size, struct debug_view *view)
+{
+	int len = 0;
+	int i, j;
+	int nr_of_entries;
+	debug_entry_t *act_entry;
+
+	/* print prolog */
+	if (view->prolog_proc)
+		len += view->prolog_proc(debug_area, view, buf);
+	/* print debug records */
+	if (!(view->format_proc) && !(view->header_proc))
+		goto out;
+	nr_of_entries = PAGE_SIZE / debug_area->entry_size
+			<< debug_area->page_order;
+	for (i = 0; i < debug_area->nr_areas; i++) {
+		act_entry = debug_area->areas[i];
+		for (j = 0; j < nr_of_entries; j++) {
+			if (act_entry->id.fields.used == 0)
+				break;	/* empty entry */
+			if (view->header_proc)
+				len += view->header_proc(debug_area, view, i,
+						         act_entry, buf + len);
+			if (view->format_proc)
+				len += view->format_proc(debug_area, view,
+						         buf + len,
+						         DEBUG_DATA(act_entry));
+			if (len > size) {
+				printk(KERN_ERR
+				"debug: error -- memory exceeded for (%s/%s)\n",
+				debug_area->name, view->name);
+				printk(KERN_ERR "debug: fix view %s!!\n",
+				       view->name);
+				printk(KERN_ERR
+				"debug: area: %i (0 - %i) entry: %i (0 - %i)\n",
+				i, debug_area->nr_areas - 1, j,
+				nr_of_entries - 1);
+				goto out;
+			}
+			act_entry = (debug_entry_t *) (((char *) act_entry) +
+					       debug_area->entry_size);
+		}
+	}
+      out:
+	return len;
+}
+
+
+/*
+ * debug_open:
+ * - called for user open()
+ * - copies formated output to private_data area of the file
+ *   handle
+ */
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+	int i = 0, size = 0, rc = 0, f_entry_size = 0;
+	file_private_info_t *p_info;
+	debug_info_t* debug_info;
+
+#ifdef DEBUG
+	printk("debug_open\n");
+#endif
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	down(&debug_lock);
+
+	/* find debug log and view */
+
+	debug_info = debug_area_first;
+	while(debug_info != NULL){
+		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+			if (debug_info->views[i] == NULL)
+				continue;
+			else if (debug_info->proc_entries[i]->low_ino ==
+				 file->f_dentry->d_inode->i_ino) {
+				goto found;	/* found view ! */
+			}
+		}
+		debug_info = debug_info->next;
+	}
+	/* no entry found */
+	rc = -EINVAL;
+	goto out;
+      found:
+	if ((file->private_data =
+	     kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
+		printk(KERN_ERR "debug_open: kmalloc failed\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	p_info = (file_private_info_t *) file->private_data;
+
+	/*
+	 * the size for the formated output is calculated
+	 * with the following formula:
+	 *
+	 *   prolog-size
+	 *   +
+	 *   (record header size + record data field size)
+	 *   * number of entries per page
+	 *   * number of pages per area
+	 *   * number of areas
+	 */
+
+	if (debug_info->views[i]->prolog_proc)
+		size +=
+		    debug_info->views[i]->prolog_proc(debug_info,
+							 debug_info->
+							 views[i], NULL);
+
+	if (debug_info->views[i]->header_proc)
+		f_entry_size =
+		    debug_info->views[i]->header_proc(debug_info,
+							 debug_info->
+							 views[i], 0, NULL,
+							 NULL);
+	if (debug_info->views[i]->format_proc)
+		f_entry_size +=
+		    debug_info->views[i]->format_proc(debug_info,
+							 debug_info->
+							 views[i], NULL,
+							 NULL);
+
+	size += f_entry_size 
+		* (PAGE_SIZE / debug_info->entry_size
+		<< debug_info->page_order)
+		* debug_info->nr_areas + 1;	/* terminating \0 */
+#ifdef DEBUG
+	printk("debug_open: size: %i\n", size);
+#endif
+
+	/* alloc some bytes more to be safe against bad views */
+	if ((p_info->data = vmalloc(size + ADD_BUFFER)) == 0) {
+		printk(KERN_ERR "debug_open: vmalloc failed\n");
+		vfree(file->private_data);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	p_info->size = size;
+	p_info->debug_info = debug_info;
+	p_info->view = debug_info->views[i];
+
+	spin_lock_irq(&debug_info->lock);
+
+	p_info->len =
+	    debug_format_output(debug_info, p_info->data, size,
+				debug_info->views[i]);
+#ifdef DEBUG
+	{
+		int ilen = p_info->len;
+		printk("debug_open: len: %i\n", ilen);
+	}
+#endif
+
+	spin_unlock_irq(&debug_info->lock);
+	debug_info_get(debug_info);
+
+      out:
+	up(&debug_lock);
+#ifdef MODULE
+	if (rc != 0)
+		MOD_DEC_USE_COUNT;
+#endif
+	return rc;
+}
+
+/*
+ * debug_close:
+ * - called for user close()
+ * - deletes  private_data area of the file handle
+ */
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	file_private_info_t *p_info;
+#ifdef DEBUG
+	printk("debug_close\n");
+#endif
+	down(&debug_lock);
+	p_info = (file_private_info_t *) file->private_data;
+	debug_info_put(p_info->debug_info);
+	if (p_info->data) {
+		vfree(p_info->data);
+		kfree(file->private_data);
+	}
+	up(&debug_lock);
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+	return 0;		/* success */
+}
+
+/*
+ * debug_create_proc_dir_entry:
+ * - initializes proc-dir-entry and registers it
+ */
+
+static struct proc_dir_entry *debug_create_proc_dir_entry
+    (struct proc_dir_entry *root, const char *name, mode_t mode,
+     struct inode_operations *iops, struct file_operations *fops) 
+{
+	struct proc_dir_entry *rc = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+	const char *fn = name;
+	int len;
+	len = strlen(fn);
+
+	rc = (struct proc_dir_entry *) kmalloc(sizeof(struct proc_dir_entry)
+					       + len + 1, GFP_ATOMIC);
+	if (!rc)
+		goto out;
+
+	memset(rc, 0, sizeof(struct proc_dir_entry));
+	memcpy(((char *) rc) + sizeof(*rc), fn, len + 1);
+	rc->name = ((char *) rc) + sizeof(*rc);
+	rc->namelen = len;
+	rc->low_ino = 0, rc->mode = mode;
+	rc->nlink = 1;
+	rc->uid = 0;
+	rc->gid = 0;
+	rc->size = 0;
+	rc->get_info = NULL;
+	rc->ops = iops;
+
+	proc_register(root, rc);
+#else
+	rc = create_proc_entry(name, mode, root);
+	if (!rc)
+		goto out;
+	if (fops)
+		rc->proc_fops = fops;
+#endif
+
+      out:
+	return rc;
+}
+
+
+/*
+ * delete_proc_dir_entry:
+ */
+
+static void debug_delete_proc_dir_entry
+    (struct proc_dir_entry *root, struct proc_dir_entry *proc_entry) 
+{
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+	proc_unregister(root, proc_entry->low_ino);
+	kfree(proc_entry);
+#else
+	remove_proc_entry(proc_entry->name, root);
+#endif
+}
+
+/*
+ * debug_register:
+ * - creates and initializes debug area for the caller
+ * - returns handle for debug area
+ */
+
+debug_info_t *debug_register
+    (char *name, int page_order, int nr_areas, int buf_size) 
+{
+	debug_info_t *rc = NULL;
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	if (!initialized)
+		debug_init();
+	down(&debug_lock);
+
+        /* create new debug_info */
+
+	rc = debug_info_create(name, page_order, nr_areas, buf_size);
+	if(!rc) 
+		goto out;
+	debug_register_view(rc, &debug_level_view);
+	printk(KERN_INFO
+	       "debug: reserved %d areas of %d pages for debugging %s\n",
+	       nr_areas, 1 << page_order, rc->name);
+      out:
+        if (rc == NULL){
+		printk(KERN_ERR "debug: debug_register failed for %s\n",name);
+#ifdef MODULE
+		MOD_DEC_USE_COUNT;
+#endif
+        }
+	up(&debug_lock);
+	return rc;
+}
+
+/*
+ * debug_unregister:
+ * - give back debug area
+ */
+
+void debug_unregister(debug_info_t * id)
+{
+	if (!id)
+		goto out;
+	down(&debug_lock);
+	printk(KERN_INFO "debug: unregistering %s\n", id->name);
+	debug_info_put(id);
+	up(&debug_lock);
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+      out:
+	return;
+}
+
+/*
+ * debug_set_level:
+ * - set actual debug level
+ */
+
+void debug_set_level(debug_info_t* id, int new_level)
+{
+	long flags;
+	if(!id)
+		return;	
+	spin_lock_irqsave(&id->lock,flags);
+        if(new_level == DEBUG_OFF_LEVEL){
+                id->level = DEBUG_OFF_LEVEL;
+                printk(KERN_INFO "debug: %s: switched off\n",id->name);
+        } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
+                printk(KERN_INFO
+                        "debug: %s: level %i is out of range (%i - %i)\n",
+                        id->name, new_level, 0, DEBUG_MAX_LEVEL);
+        } else {
+                id->level = new_level;
+                printk(KERN_INFO 
+			"debug: %s: new level %i\n",id->name,id->level);
+        }
+	spin_unlock_irqrestore(&id->lock,flags);
+}
+
+
+/*
+ * proceed_active_entry:
+ * - set active entry to next in the ring buffer
+ */
+
+static inline void proceed_active_entry(debug_info_t * id)
+{
+	if ((id->active_entry[id->active_area] += id->entry_size)
+	    > ((PAGE_SIZE << (id->page_order)) - id->entry_size))
+		id->active_entry[id->active_area] = 0;
+}
+
+/*
+ * proceed_active_area:
+ * - set active area to next in the ring buffer
+ */
+
+static inline void proceed_active_area(debug_info_t * id)
+{
+	id->active_area++;
+	id->active_area = id->active_area % id->nr_areas;
+}
+
+/*
+ * get_active_entry:
+ */
+
+static inline debug_entry_t *get_active_entry(debug_info_t * id)
+{
+	return (debug_entry_t *) ((char *) id->areas[id->active_area] +
+				  id->active_entry[id->active_area]);
+}
+
+/*
+ * debug_common:
+ * - set timestamp, caller address, cpu number etc.
+ */
+
+static inline debug_entry_t *debug_common(debug_info_t * id)
+{
+	debug_entry_t *active;
+
+	active = get_active_entry(id);
+	STCK(active->id.stck);
+	active->id.fields.cpuid = smp_processor_id();
+	active->id.fields.used = 1;
+	active->caller = __builtin_return_address(0);
+	return active;
+}
+
+/*
+ * debug_event:
+ */
+
+debug_entry_t *debug_event(debug_info_t * id, int level, void *buf,
+			   int len)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 0;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	proceed_active_entry(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_int_event:
+ */
+
+debug_entry_t *debug_int_event(debug_info_t * id, int level,
+			       unsigned int tag)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 0;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), &tag, MIN(sizeof(unsigned int), id->buf_size));
+	proceed_active_entry(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_text_event:
+ */
+
+debug_entry_t *debug_text_event(debug_info_t * id, int level,
+				const char *txt)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	strncpy(DEBUG_DATA(active), txt, MIN(strlen(txt), id->buf_size));
+	active->id.fields.exception = 0;
+	proceed_active_entry(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+
+}
+
+/*
+ * debug_exception:
+ */
+
+debug_entry_t *debug_exception(debug_info_t * id, int level, void *buf,
+			       int len)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 1;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	proceed_active_entry(id);
+	proceed_active_area(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_int_exception:
+ */
+
+debug_entry_t *debug_int_exception(debug_info_t * id, int level,
+				   unsigned int tag)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 1;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), &tag,
+	       MIN(sizeof(unsigned int), id->buf_size));
+	proceed_active_entry(id);
+	proceed_active_area(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_text_exception:
+ */
+
+debug_entry_t *debug_text_exception(debug_info_t * id, int level,
+				    const char *txt)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	strncpy(DEBUG_DATA(active), txt, MIN(strlen(txt), id->buf_size));
+	active->id.fields.exception = 1;
+	proceed_active_entry(id);
+	proceed_active_area(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+
+}
+
+/*
+ * debug_init:
+ * - is called exactly once to initialize the debug feature
+ */
+
+int debug_init(void)
+{
+	int rc = 0;
+
+	down(&debug_lock);
+	if (!initialized) {
+		debug_proc_root_entry =
+		    debug_create_proc_dir_entry(&proc_root, DEBUG_DIR_ROOT,
+						S_IFDIR | S_IRUGO | S_IXUGO
+						| S_IWUSR | S_IWGRP, NULL,
+						NULL);
+		printk(KERN_INFO "debug: Initialization complete\n");
+		initialized = 1;
+	}
+	up(&debug_lock);
+
+	return rc;
+}
+
+/*
+ * debug_register_view:
+ */
+
+int debug_register_view(debug_info_t * id, struct debug_view *view)
+{
+	int rc = 0;
+	int i;
+	long flags;
+	mode_t mode = S_IFREG;
+
+	if (!id)
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+		if (id->views[i] == NULL)
+			break;
+	}
+	if (i == DEBUG_MAX_VIEWS) {
+		printk(KERN_WARNING "debug: cannot register view %s/%s\n",
+			id->name,view->name);
+		printk(KERN_WARNING 
+			"debug: maximum number of views reached (%i)!\n", i);
+		rc = -1;
+	}
+	else {
+		id->views[i] = view;
+		if (view->prolog_proc || view->format_proc || view->header_proc)
+			mode |= S_IRUSR;
+		if (view->input_proc)
+			mode |= S_IWUSR;
+		id->proc_entries[i] =
+		    debug_create_proc_dir_entry(id->proc_root_entry,
+						view->name, mode,
+						&debug_inode_ops,
+						&debug_file_ops);
+		rc = 0;
+	}
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return rc;
+}
+
+/*
+ * debug_unregister_view:
+ */
+
+int debug_unregister_view(debug_info_t * id, struct debug_view *view)
+{
+	int rc = 0;
+	int i;
+	long flags;
+
+	if (!id)
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+		if (id->views[i] == view)
+			break;
+	}
+	if (i == DEBUG_MAX_VIEWS)
+		rc = -1;
+	else {
+		debug_delete_proc_dir_entry(id->proc_root_entry,
+					    id->proc_entries[i]);		
+		id->views[i] = NULL;
+		rc = 0;
+	}
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return rc;
+}
+
+/*
+ * functions for debug-views
+ ***********************************
+*/
+
+/*
+ * prints out actual debug level
+ */
+
+static int debug_prolog_level_fn(debug_info_t * id,
+				 struct debug_view *view, char *out_buf)
+{
+	int rc = 0;
+
+	if (out_buf == NULL) {
+		rc = 2;
+		goto out;
+	}
+	if(id->level == -1) rc = sprintf(out_buf,"-\n");
+	else rc = sprintf(out_buf, "%i\n", id->level);
+      out:
+	return rc;
+}
+
+/*
+ * reads new debug level
+ */
+
+static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
+				struct file *file, const char *user_buf,
+				size_t in_buf_size, loff_t * offset)
+{
+	char input_buf[1];
+	int rc = in_buf_size;
+
+	if (*offset != 0)
+		goto out;
+	if ((rc = copy_from_user(input_buf, user_buf, 1)))
+		goto out;
+	if (isdigit(input_buf[0])) {
+		int new_level = ((int) input_buf[0] - (int) '0');
+		debug_set_level(id, new_level);
+	} else if(input_buf[0] == '-') {
+		debug_set_level(id, DEBUG_OFF_LEVEL);
+	} else {
+		printk(KERN_INFO "debug: level `%c` is not valid\n",
+		       input_buf[0]);
+	}
+      out:
+	*offset += in_buf_size;
+	return rc;		/* number of input characters */
+}
+
+/*
+ * prints debug header in raw format
+ */
+
+int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
+                         int area, debug_entry_t * entry, char *out_buf)
+{
+        int rc;
+
+	rc = sizeof(debug_entry_t);
+        if (out_buf == NULL)
+                goto out;
+	memcpy(out_buf,entry,sizeof(debug_entry_t));
+      out:
+        return rc;
+}
+
+/*
+ * prints debug data in raw format
+ */
+
+static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
+			       char *out_buf, const char *in_buf)
+{
+	int rc;
+
+	rc = id->buf_size;
+	if (out_buf == NULL || in_buf == NULL)
+		goto out;
+	memcpy(out_buf, in_buf, id->buf_size);
+      out:
+	return rc;
+}
+
+/*
+ * prints debug data in hex/ascii format
+ */
+
+static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
+		    		  char *out_buf, const char *in_buf)
+{
+	int i, rc = 0;
+
+	if (out_buf == NULL || in_buf == NULL) {
+		rc = id->buf_size * 4 + 3;
+		goto out;
+	}
+	for (i = 0; i < id->buf_size; i++) {
+                rc += sprintf(out_buf + rc, "%02x ",
+                              ((unsigned char *) in_buf)[i]);
+        }
+	rc += sprintf(out_buf + rc, "| ");
+	for (i = 0; i < id->buf_size; i++) {
+		unsigned char c = in_buf[i];
+		if (!isprint(c))
+			rc += sprintf(out_buf + rc, ".");
+		else
+			rc += sprintf(out_buf + rc, "%c", c);
+	}
+	rc += sprintf(out_buf + rc, "\n");
+      out:
+	return rc;
+}
+
+/*
+ * prints header for debug entry
+ */
+
+int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
+			 int area, debug_entry_t * entry, char *out_buf)
+{
+	struct timeval time_val;
+	unsigned long long time;
+	char *except_str;
+	unsigned long caller;
+	int rc = 0;
+
+	if (out_buf == NULL) {
+		rc = DEBUG_PROC_HEADER_SIZE;
+		goto out;
+	}
+
+	time = entry->id.stck;
+	/* adjust todclock to 1970 */
+	time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+	tod_to_timeval(time, &time_val);
+
+	if (entry->id.fields.exception)
+		except_str = "*";
+	else
+		except_str = "-";
+	caller = (unsigned long) entry->caller;
+#if defined(CONFIG_ARCH_S390X)
+	rc += sprintf(out_buf, "%02i %011lu:%06lu %1s %02i %016lx  ",
+		      area, time_val.tv_sec,
+		      time_val.tv_usec, except_str,
+		      entry->id.fields.cpuid, caller);
+#else
+	caller &= 0x7fffffff;
+	rc += sprintf(out_buf, "%02i %011lu:%06lu %1s %02i %08lx  ",
+		      area, time_val.tv_sec,
+		      time_val.tv_usec, except_str,
+		      entry->id.fields.cpuid, caller);
+#endif
+      out:
+	return rc;
+}
+
+/*
+ * init_module:
+ */
+
+#ifdef MODULE
+int init_module(void)
+{
+	int rc = 0;
+#ifdef DEBUG
+	printk("debug_module_init: \n");
+#endif
+	rc = debug_init();
+	if (rc) 
+		printk(KERN_INFO "debug: an error occurred with debug_init\n");
+	return rc;
+}
+
+/*
+ * cleanup_module:
+ */
+
+void cleanup_module(void)
+{
+#ifdef DEBUG
+	printk("debug_cleanup_module: \n");
+#endif
+	debug_delete_proc_dir_entry(&proc_root, debug_proc_root_entry);
+	return;
+}
+
+#endif			/* MODULE */
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/ebcdic.c linux/arch/s390/kernel/ebcdic.c
--- v2.4.1/linux/arch/s390/kernel/ebcdic.c	Fri May 12 11:41:44 2000
+++ linux/arch/s390/kernel/ebcdic.c	Tue Feb 13 14:13:43 2001
@@ -161,7 +161,156 @@
 
 
 /*
- * EBCDIC 037 conversion table:
+ * ASCII (IBM PC 437)  -> EBCDIC 500
+ */
+__u8 _ascebc_500[256] =
+{
+ /*00 NUL   SOH   STX   ETX   EOT   ENQ   ACK   BEL */
+     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08  BS    HT    LF    VT    FF    CR    SO    SI */
+ /*              ->NL                               */
+     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10 DLE   DC1   DC2   DC3   DC4   NAK   SYN   ETB */
+     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ /*18 CAN    EM   SUB   ESC    FS    GS    RS    US */
+ /*                               ->IGS ->IRS ->IUS */
+     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ /*20  SP     !     "     #     $     %     &     ' */
+     0x40, 0x4F, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28   (     )     *     +     ,     -    .      / */
+     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30   0     1     2     3     4     5     6     7 */
+     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38   8     9     :     ;     <     =     >     ? */
+     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40   @     A     B     C     D     E     F     G */
+     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48   H     I     J     K     L     M     N     O */
+     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50   P     Q     R     S     T     U     V     W */
+     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58   X     Y     Z     [     \     ]     ^     _ */
+     0xE7, 0xE8, 0xE9, 0x4A, 0xE0, 0x5A, 0x5F, 0x6D,
+ /*60   `     a     b     c     d     e     f     g */
+     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68   h     i     j     k     l     m     n     o */
+     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70   p     q     r     s     t     u     v     w */
+     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78   x     y     z     {     |     }     ~    DL */
+     0xA7, 0xA8, 0xA9, 0xC0, 0xBB, 0xD0, 0xA1, 0x07,
+ /*80*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*88*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*90*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*98*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E0        sz						*/
+     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F8*/
+     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+/*
+ * EBCDIC 500 -> ASCII (IBM PC 437)
+ */
+__u8 _ebcasc_500[256] =
+{
+ /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
+          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
+          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
+                                  -ENP  ->LF             */
+          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
+                                                    -IUS */
+          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
+                                  -INP                   */
+          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
+                       -SW                               */ 
+          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
+          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
+          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ /* 0x40    SP   RSP           �ä              ----       */
+          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ /* 0x48                 [     .     <     (     +     ! */
+          0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ /* 0x50     &                                      ---- */
+          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ /* 0x58           �ß     ]     $     *     )     ;     ^ */
+          0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ /* 0x60     -     /  ----     �Ä  ----  ----  ----       */
+          0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ /* 0x68              ----     ,     %     _     >     ? */ 
+          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
+          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x78     *     `     :     #     @     '     =     " */
+          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ /* 0x80     *     a     b     c     d     e     f     g */
+          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ /* 0x88     h     i              ----  ----  ----       */
+          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ /* 0x90     �°     j     k     l     m     n     o     p */
+          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ /* 0x98     q     r                    ----        ---- */
+          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ /* 0xA0           ~     s     t     u     v     w     x */
+          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ /* 0xA8     y     z              ----  ----  ----  ---- */
+          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ /* 0xB0                          ----     �§  ----       */
+          0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ /* 0xB8        ----           |  ----  ----  ----  ---- */
+          0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+ /* 0xC0     {     A     B     C     D     E     F     G */
+          0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ /* 0xC8     H     I  ----           �ö              ---- */
+          0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ /* 0xD0     }     J     K     L     M     N     O     P */
+          0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ /* 0xD8     Q     R  ----           �ü                   */
+          0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ /* 0xE0     \           S     T     U     V     W     X */
+          0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ /* 0xE8     Y     Z        ----     �Ö  ----  ----  ---- */
+          0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ /* 0xF0     0     1     2     3     4     5     6     7 */
+          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ /* 0xF8     8     9  ----  ----     �Ü  ----  ----  ---- */
+          0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
+};
+
+
+/*
+ * EBCDIC 037/500 conversion table:
  * from upper to lower case
  */
 __u8 _ebc_tolower[256] =
@@ -202,7 +351,7 @@
 
 
 /*
- * EBCDIC 037 conversion table:
+ * EBCDIC 037/500 conversion table:
  * from lower to upper case
  */
 __u8 _ebc_toupper[256] =
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/entry.S linux/arch/s390/kernel/entry.S
--- v2.4.1/linux/arch/s390/kernel/entry.S	Fri Aug 11 14:29:05 2000
+++ linux/arch/s390/kernel/entry.S	Tue Feb 13 14:13:43 2001
@@ -81,6 +81,7 @@
 flags        =  4
 sigpending   =  8
 need_resched = 24
+tsk_ptrace   = 28
 processor    = 60
 
 /* PSW related defines */
@@ -88,6 +89,13 @@
 enable       = 0x03
 daton        = 0x04
 
+/*
+ * Base Address of this Module --- saved in __LC_ENTRY_BASE
+ */
+       .globl entry_base
+entry_base:
+
+#define BASED(name) name-entry_base(%r13)
 
 #if 0
 /* some code left lying around in case we need a
@@ -118,39 +126,37 @@
  */
 
 #define SAVE_ALL(psworg) \
-	st      %r15,__LC_SAVE_AREA   ; \
+	stm     %r13,%r15,__LC_SAVE_AREA ; \
+        stam    %a2,%a4,__LC_SAVE_AREA+12 ; \
+        basr    %r13,0                ; /* temp base pointer */ \
+        l       %r13,.Lentry_base-.(%r13) ; /* load &entry_base to %r13 */ \
         tm      psworg+1,0x01         ; /* test problem state bit */ \
-	jz	0f		      ; /* skip stack setup save */ \
+	bz	BASED(.+12)           ; /* skip stack setup save */ \
 	l	%r15,__LC_KERNEL_STACK ; /* problem state -> load ksp */ \
-0:	ahi     %r15,-SP_SIZE         ; /* make room for registers & psw */ \
-        srl     %r15,3                ; \
-        sll     %r15,3                ; /* align stack pointer to 8 */ \
-        stm     %r0,%r14,SP_R0(%r15)  ; /* store gprs 0-14 to kernel stack */ \
+        lam     %a2,%a4,BASED(.Lc_ac) ; /* set ac.reg. 2 to primary space */ \
+                                        /* and access reg. 4 to home space */ \
+0:	s       %r15,BASED(.Lc_spsize); /* make room for registers & psw */ \
+        n       %r15,BASED(.Lc0xfffffff8) ; /* align stack pointer to 8 */ \
+        stm     %r0,%r12,SP_R0(%r15)  ; /* store gprs 0-12 to kernel stack */ \
         st      %r2,SP_ORIG_R2(%r15)  ; /* store original content of gpr 2 */ \
-        mvc     SP_RF(4,%r15),__LC_SAVE_AREA   ; /* move R15 to stack */ \
+        mvc     SP_RD(12,%r15),__LC_SAVE_AREA  ; /* move R13-R15 to stack */ \
         stam    %a0,%a15,SP_AREGS(%r15) ; /* store access registers to kst. */ \
+        mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 ; /* store ac. regs */ \
         mvc     SP_PSW(8,%r15),psworg ; /* move user PSW to stack */ \
-        lhi     %r0,psworg            ; /* store trap indication */ \
+        la      %r0,psworg            ; /* store trap indication */ \
         st      %r0,SP_TRAP(%r15)     ; \
-        xc      0(4,%r15),0(%r15)     ; /* clear back chain */ \
-        tm      psworg+1,0x01         ; /* kmod.c .wishes the set_fs & gs */ \
-        jz      1f                    ; /* to work across syscalls */ \
-        slr     %r0,%r0               ; \
-        sar     %a2,%r0               ; /* set ac.reg. 2 to primary space */ \
-        lhi     %r0,1                 ; \
-        sar     %a4,%r0               ; /* set access reg. 4 to home space */ \
-1:
+        xc      0(4,%r15),0(%r15)     ; /* clear back chain */
 
 #define RESTORE_ALL \
-        mvc     __LC_RETURN_PSW(8,0),SP_PSW(%r15) ; /* move user PSW to lowcore */ \
-        lam     %a0,%a15,SP_AREGS(%r15)   ; /* load the access registers */ \
-        lm      %r0,%r15,SP_R0(%r15)      ; /* load gprs 0-15 of user */ \
-        ni      __LC_RETURN_PSW+1(0),0xfd ; /* clear wait state bit */ \
-        lpsw    __LC_RETURN_PSW             /* back to caller */
+        mvc     __LC_RETURN_PSW(8),SP_PSW(%r15) ; /* move user PSW to lowcore */ \
+        lam     %a0,%a15,SP_AREGS(%r15) ; /* load the access registers */ \
+        lm      %r0,%r15,SP_R0(%r15)    ; /* load gprs 0-15 of user */ \
+        ni      __LC_RETURN_PSW+1,0xfd  ; /* clear wait state bit */ \
+        lpsw    __LC_RETURN_PSW           /* back to caller */
 
 #define GET_CURRENT /* load pointer to task_struct to R9 */ \
-        lhi     %r9,-8192             ; \
-        nr      %r9,15
+        lr      %r9,%r15              ; \
+        n       %r9,BASED(.Lc0xffffe000)
 
 
 /*
@@ -162,22 +168,24 @@
  */
         .globl  resume
 resume:
+        basr    %r1,0
+resume_base:
         l       %r4,_TSS_PTREGS(%r3)
         tm      SP_PSW-SP_PTREGS(%r4),0x40 # is the new process using per ?
-        jz      RES_DN1                 # if not we're fine
-        stctl   %r9,%r11,24(%r15)       # We are using per stuff
+        bz      resume_noper-resume_base(%r1) # if not we're fine
+        stctl   %r9,%r11,24(%r15)             # We are using per stuff
         clc     _TSS_PER(12,%r3),24(%r15)
-        je      RES_DN1                 # we got away without bashing TLB's
-        lctl    %c9,%c11,_TSS_PER(%r3)  # Nope we didn't
-RES_DN1:
+        be      resume_noper-resume_base(%r1) # we got away w/o bashing TLB's
+        lctl    %c9,%c11,_TSS_PER(%r3)        # Nope we didn't
+resume_noper:
         stm     %r6,%r15,24(%r15)       # store resume registers of prev task
         st      %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp
-        lhi     %r0,-8192
-        nr      %r0,%r15
+        lr      %r0,%r15
+        n       %r0,.Lc0xffffe000-resume_base(%r1)
         l       %r15,_TSS_KSP(%r3) # load kernel stack ptr from next->tss.ksp
-        lhi     %r1,8191
+        l       %r1,.Lc8191-resume_base(%r1)
         or      %r1,%r15
-        ahi     %r1,1
+        la      %r1,1(%r1)
         st      %r1,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
         stam    %a2,%a2,_TSS_AR2(%r2)   # store kernel access reg. 2
         stam    %a4,%a4,_TSS_AR4(%r2)   # store kernel access reg. 4
@@ -192,38 +200,19 @@
  * are executed with interrupts enabled.
  */
 
-sysc_lit:
-  sysc_do_signal:     .long  do_signal
-  sysc_do_softirq:    .long  do_softirq
-  sysc_schedule:      .long  schedule
-  sysc_trace:         .long  syscall_trace
-#ifdef CONFIG_SMP
-  sysc_schedtail:     .long  schedule_tail
-#endif
-  sysc_clone:         .long  sys_clone
-  sysc_fork:          .long  sys_fork
-  sysc_vfork:         .long  sys_vfork
-  sysc_sigreturn:     .long  sys_sigreturn
-  sysc_rt_sigreturn:  .long  sys_rt_sigreturn
-  sysc_execve:        .long  sys_execve
-  sysc_sigsuspend:    .long  sys_sigsuspend
-  sysc_rt_sigsuspend: .long  sys_rt_sigsuspend
-
 	.globl  system_call
 system_call:
         SAVE_ALL(0x20)
-	XC      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
+	xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
 pgm_system_call:	
-        basr    %r13,0
-        ahi     %r13,sysc_lit-.   # setup base pointer R13 to sysc_lit
         slr     %r8,%r8           # gpr 8 is call save (-> tracesys)
         ic      %r8,0x8B          # get svc number from lowcore
         stosm   24(%r15),0x03     # reenable interrupts
         GET_CURRENT               # load pointer to task_struct to R9
         sll     %r8,2
-        l       %r8,sys_call_table-sysc_lit(8,%r13) # get address of system call
-        tm      flags+3(%r9),0x20 # PF_TRACESYS
-        jnz     sysc_tracesys
+        l       %r8,sys_call_table-entry_base(8,%r13) # get address of system call
+        tm      tsk_ptrace+3(%r9),0x02 # PT_TRACESYS
+        bnz     BASED(sysc_tracesys)
         basr    %r14,%r8          # call sys_xxxx
         st      %r2,SP_R2(%r15)   # store return value (change R2 on stack)
                                   # ATTENTION: check sys_execve_glue before
@@ -232,24 +221,24 @@
 sysc_return:
         GET_CURRENT               # load pointer to task_struct to R9
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
-        jno     sysc_leave        # no-> skip bottom half, resched & signal
+        bno     BASED(sysc_leave) # no-> skip bottom half, resched & signal
 #
 # check, if bottom-half has to be done
 #
         l       %r0,__LC_IRQ_STAT     # get softirq_active
         n       %r0,__LC_IRQ_STAT+4   # and it with softirq_mask
-        jnz     sysc_handle_bottom_half
+        bnz     BASED(sysc_handle_bottom_half)
 #
 # check, if reschedule is needed
 #
 sysc_return_bh:	
         icm     %r0,15,need_resched(%r9) # get need_resched from task_struct
-        jnz     sysc_reschedule
+        bnz     BASED(sysc_reschedule)
         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
-        jnz     sysc_signal_return
+        bnz     BASED(sysc_signal_return)
 sysc_leave:
 	icm     %r0,15,SP_SVC_STEP(%r15)   # get sigpending from task_struct
-        jnz     pgm_svcret
+        bnz     BASED(pgm_svcret)
 	stnsm   24(%r15),disable  # disable I/O and ext. interrupts
         RESTORE_ALL
 
@@ -259,24 +248,24 @@
 sysc_signal_return:     
         la      %r2,SP_PTREGS(%r15) # load pt_regs
         sr      %r3,%r3           # clear *oldset
-        l       %r1,sysc_do_signal-sysc_lit(%r13)
-	la      %r14,sysc_leave-sysc_lit(%r13)
+        l       %r1,BASED(.Ldo_signal)
+	la      %r14,BASED(sysc_leave)
         br      %r1               # return point is sysc_leave
 
 #
 # call trace before and after sys_call
 #
 sysc_tracesys:
-        l       %r1,sysc_trace-sysc_lit(%r13)
-	lhi     %r2,-ENOSYS
+        l       %r1,BASED(.Ltrace)
+	l       %r2,BASED(.Lc_ENOSYS)
 	st      %r2,SP_R2(%r15)   # give sysc_trace an -ENOSYS retval
         basr    %r14,%r1
 	lm      %r3,%r6,SP_R3(%r15)
 	l       %r2,SP_ORIG_R2(%r15)
         basr    %r14,%r8          # call sys_xxx
         st      %r2,SP_R2(%r15)   # store return value
-        l       %r1,sysc_trace-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13)
+        l       %r1,BASED(.Ltrace)
+	la      %r14,BASED(sysc_return)
         br      %r1               # return point is sysc_return
 
 
@@ -285,16 +274,16 @@
 # is zero
 #
 sysc_handle_bottom_half:        
-        l       %r1,sysc_do_softirq-sysc_lit(%r13)
-	la      %r14,sysc_return_bh-sysc_lit(%r13)
+        l       %r1,BASED(.Ldo_softirq)
+	la      %r14,BASED(sysc_return_bh)
         br      %r1               # call do_softirq
 
 #
 # call schedule with sysc_return as return-address
 #
 sysc_reschedule:        
-        l       %r1,sysc_schedule-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13)
+        l       %r1,BASED(.Lschedule)
+	la      %r14,BASED(sysc_return)
         br      %r1               # call scheduler, return to sysc_return
 
 #
@@ -303,17 +292,17 @@
         .globl  ret_from_fork
 ret_from_fork:  
         basr    %r13,0
-        ahi     %r13,sysc_lit-.   # setup base pointer R13 to $SYSCDAT
+        l       %r13,.Lentry_base-.(%r13)  # setup base pointer to &entry_base
         GET_CURRENT               # load pointer to task_struct to R9
         stosm   24(%r15),0x03     # reenable interrupts
         sr      %r0,%r0           # child returns 0
         st      %r0,SP_R2(%r15)   # store return value (change R2 on stack)
 #ifdef CONFIG_SMP
-        l       %r1,sysc_schedtail-sysc_lit(%r13)
-	la      %r14,sysc_return-sysc_lit(%r13)
+        l       %r1,BASED(.Lschedtail)
+	la      %r14,BASED(sysc_return)
         br      %r1               # call schedule_tail, return to sysc_return
 #else
-        j       sysc_return
+        b       BASED(sysc_return)
 #endif
 
 #
@@ -324,22 +313,22 @@
 #
 sys_clone_glue: 
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,sysc_clone-sysc_lit(%r13)
+        l       %r1,BASED(.Lclone)
         br      %r1                   # branch to sys_clone
 
 sys_fork_glue:  
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,sysc_fork-sysc_lit(%r13)
+        l       %r1,BASED(.Lfork)
         br      %r1                   # branch to sys_fork
 
 sys_vfork_glue: 
         la      %r2,SP_PTREGS(%r15)    # load pt_regs
-        l       %r1,sysc_vfork-sysc_lit(%r13)
+        l       %r1,BASED(.Lvfork)
         br      %r1                   # branch to sys_vfork
 
 sys_execve_glue:        
         la      %r2,SP_PTREGS(%r15)   # load pt_regs
-        l       %r1,sysc_execve-sysc_lit(%r13)
+        l       %r1,BASED(.Lexecve)
 	lr      %r12,%r14             # save return address
         basr    %r14,%r1              # call sys_execve
         ltr     %r2,%r2               # check if execve failed
@@ -349,12 +338,12 @@
 
 sys_sigreturn_glue:     
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,sysc_sigreturn-sysc_lit(%r13)
+        l       %r1,BASED(.Lsigreturn)
         br      %r1                   # branch to sys_sigreturn
 
 sys_rt_sigreturn_glue:     
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
-        l       %r1,sysc_rt_sigreturn-sysc_lit(%r13)
+        l       %r1,BASED(.Lrt_sigreturn)
         br      %r1                   # branch to sys_sigreturn
 
 #
@@ -369,7 +358,7 @@
         lr      %r4,%r3               # move history1 parameter
         lr      %r3,%r2               # move history0 parameter
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,sysc_sigsuspend-sysc_lit(%r13)
+        l       %r1,BASED(.Lsigsuspend)
 	la      %r14,4(%r14)          # skip store of return value
         br      %r1                   # branch to sys_sigsuspend
 
@@ -377,10 +366,15 @@
         lr      %r4,%r3               # move sigsetsize parameter
         lr      %r3,%r2               # move unewset parameter
         la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
-        l       %r1,sysc_rt_sigsuspend-sysc_lit(%r13)
+        l       %r1,BASED(.Lrt_sigsuspend)
 	la      %r14,4(%r14)          # skip store of return value
         br      %r1                   # branch to sys_rt_sigsuspend
 
+sys_sigaltstack_glue:
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        l       %r1,BASED(.Lsigaltstack)
+        br      %r1                   # branch to sys_sigreturn
+
 	.globl  sys_call_table	
 sys_call_table:
         .long  sys_ni_syscall            /* 0 */
@@ -459,7 +453,7 @@
         .long  sys_sigpending
         .long  sys_sethostname
         .long  sys_setrlimit            /* 75 */
-        .long  sys_getrlimit
+        .long  sys_old_getrlimit
         .long  sys_getrusage
         .long  sys_gettimeofday
         .long  sys_settimeofday
@@ -569,13 +563,13 @@
         .long  sys_getcwd
         .long  sys_capget
         .long  sys_capset                /* 185 */
-        .long  sys_sigaltstack
+        .long  sys_sigaltstack_glue
         .long  sys_sendfile
         .long  sys_ni_syscall            /* streams1 */
         .long  sys_ni_syscall            /* streams2 */
         .long  sys_vfork_glue            /* 190 */
         .long  sys_getrlimit
-	.long  sys_ni_syscall  /* FIXME: problem with sys_mmap2: 6 parms */
+	.long  sys_mmap2
         .long  sys_truncate64
         .long  sys_ftruncate64
         .long  sys_stat64                /* 195 */
@@ -604,7 +598,8 @@
         .long  sys_mincore
         .long  sys_madvise
 	.long  sys_getdents64		 /* 220 */
-	.rept  255-220
+        .long  sys_fcntl64 
+	.rept  255-221
 	.long  sys_ni_syscall
 	.endr
 
@@ -612,13 +607,6 @@
  * Program check handler routine
  */
 
-pgm_lit:
-  pgm_handle_per:  .long  handle_per_exception
-  pgm_jump_table:  .long  pgm_check_table
-  pgm_sysc_ret:    .long  sysc_return
-  pgm_sysc_lit:    .long  sysc_lit
-  pgm_do_signal:   .long  do_signal
-
         .globl  pgm_check_handler
 pgm_check_handler:
 /*
@@ -634,110 +622,131 @@
  * we just ignore the PER event (FIXME: is there anything we have to do
  * for LPSW?).
  */
+	stm     %r13,%r15,__LC_SAVE_AREA
+	stam    %a2,%a4,__LC_SAVE_AREA+12
+	basr    %r13,0                   # temp base pointer
+	l       %r13,.Lentry_base-.(%r13)# load &entry_base to %r13
         tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
-        jz      pgm_sv                   # skip if not
+        bz      BASED(pgm_sv)            # skip if not
         tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
-        jnz     pgm_sv                   # skip if it is
+        bnz     BASED(pgm_sv)            # skip if it is
 # ok its one of the special cases, now we need to find out which one
         clc     __LC_PGM_OLD_PSW(8),__LC_SVC_NEW_PSW
-        je      pgm_svcper
+        be      BASED(pgm_svcper)
 # no interesting special case, ignore PER event
-        lpsw    0x28
+        lm      %r13,%r15,__LC_SAVE_AREA
+	lpsw    0x28
 # it was a single stepped SVC that is causing all the trouble
 pgm_svcper:
-        SAVE_ALL(0x20)
+        tm      0x21,0x01                # test problem state bit
+	bz	BASED(.+12)              # skip stack & access regs setup
+	l	%r15,__LC_KERNEL_STACK   # problem state -> load ksp
+	lam     %a2,%a4,BASED(.Lc_ac)    # set ac.reg. 2 to primary space
+                                         # and access reg. 4 to home space
+	s       %r15,BASED(.Lc_spsize)   # make room for registers & psw
+        n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
+        stm     %r0,%r12,SP_R0(%r15)     # store gprs 0-12 to kernel stack
+        st      %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
+        mvc     SP_RD(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack
+        stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
+	mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
+        mvc     SP_PSW(8,%r15),0x20      # move user PSW to stack
+        la      %r0,0x20                 # store trap indication
+        st      %r0,SP_TRAP(%r15)
+        xc      0(4,%r15),0(%r15)        # clear back chain
         mvi     SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero
         mvc     SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information
-        j       pgm_system_call              # now do the svc
+        b       BASED(pgm_system_call)   # now do the svc
 pgm_svcret:
-        lh      %r7,SP_PGM_OLD_ILC(%r15)     # get ilc from stack
-        lhi     %r0,0x28
-        st      %r0,SP_TRAP(%r15) # set new trap indicator
+        mvi     SP_TRAP+3(%r15),0x28     # set trap indication back to pgm_chk
+        lh      %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack
         xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
-        basr    %r13,0
-        ahi     %r13,pgm_lit-.    # setup base pointer
-        j       pgm_no_sv
+	b       BASED(pgm_no_sv)
 pgm_sv:
-        SAVE_ALL(0x28)
-        XC      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
-        basr    %r13,0
-        ahi     %r13,pgm_lit-.    # setup base pointer R13 to $PGMDAT
+        tm      0x29,0x01                # test problem state bit
+	bz	BASED(.+12)              # skip stack & access regs setup
+	l	%r15,__LC_KERNEL_STACK   # problem state -> load ksp
+	lam     %a2,%a4,BASED(.Lc_ac)    # set ac.reg. 2 to primary space
+                                         # and access reg. 4 to home space
+	s       %r15,BASED(.Lc_spsize)   # make room for registers & psw
+        n       %r15,BASED(.Lc0xfffffff8) # align stack pointer to 8
+        stm     %r0,%r12,SP_R0(%r15)     # store gprs 0-12 to kernel stack
+        st      %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
+        mvc     SP_RD(12,%r15),__LC_SAVE_AREA # move R13-R15 to stack
+        stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
+	mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+12 # store ac. regs
+        mvc     SP_PSW(8,%r15),0x28      # move user PSW to stack
+        la      %r0,0x28                 # store trap indication
+        st      %r0,SP_TRAP(%r15)
+        xc      0(4,%r15),0(%r15)        # clear back chain
+        xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
         lh      %r7,__LC_PGM_ILC  # load instruction length
 pgm_no_sv:
         lh      %r8,__LC_PGM_INT_CODE  # N.B. saved int code used later KEEP it
         stosm   24(%r15),0x03     # reenable interrupts
         lr      %r3,%r8
-        lhi     %r0,0x7f
+        la      %r0,0x7f
         nr      %r3,%r0           # clear per-event-bit
-        je      pgm_dn            # none of Martins exceptions occured bypass
-        l       %r9,pgm_jump_table-pgm_lit(%r13)
+        be      BASED(pgm_dn)     # none of Martins exceptions occured bypass
+        l       %r9,BASED(.Ljump_table)
         sll     %r3,2
         l       %r9,0(%r3,%r9)    # load address of handler routine
         la      %r2,SP_PTREGS(%r15) # address of register-save area
         srl     %r3,2
-        chi     %r3,0x4           # protection-exception ?
-        jne     pgm_go            # if not,
+        cl      %r3,BASED(.Lc4)   # protection-exception ?
+        bne     BASED(pgm_go)     # if not,
         l       %r5,SP_PSW+4(15)  # load psw addr
         sr      %r5,%r7           # substract ilc from psw
         st      %r5,SP_PSW+4(15)  # store corrected psw addr
 pgm_go: basr    %r14,%r9          # branch to interrupt-handler
-pgm_dn: lhi     %r0,0x80
+pgm_dn: la      %r0,0x80
         nr      %r8,%r0           # check for per exception
-        je      pgm_return
+        be      BASED(pgm_return)
         la      %r2,SP_PTREGS(15) # address of register-save area
-        l       %r9,pgm_handle_per-pgm_lit(%r13) # load adr. of per handler
-        l       %r14,pgm_sysc_ret-pgm_lit(%r13)  # load adr. of system return
-        l       %r13,pgm_sysc_lit-pgm_lit(%r13)
+        l       %r9,BASED(.Lhandle_per) # load adr. of per handler
+        la      %r14,BASED(sysc_return) # load adr. of system return
         br      %r9               # branch to handle_per_exception
+
 #
 # the backend code is the same as for sys-call
 #
 pgm_return:
-        l       %r14,pgm_sysc_ret-pgm_lit(%r13)
-        l       %r13,pgm_sysc_lit-pgm_lit(%r13)
-        br      %r14
+        b       BASED(sysc_return)
 
 /*
  * IO interrupt handler routine
  */
 
-io_lit:
-  io_do_IRQ:        .long do_IRQ
-  io_schedule:	    .long schedule
-  io_do_signal:     .long do_signal
-  io_do_softirq:    .long  do_softirq
-
         .globl io_int_handler
 io_int_handler:
         SAVE_ALL(0x38)
-        basr    %r13,0
-        ahi     %r13,io_lit-.     # setup base pointer R13 to $IODAT
         la      %r2,SP_PTREGS(%r15) # address of register-save area
         sr      %r3,%r3
         icm     %r3,%r3,__LC_SUBCHANNEL_NR # load subchannel nr & extend to int
-        l       %r4,__LC_IO_INT_PARM       # load interuption parm
-        l       %r9,io_do_IRQ-io_lit(%r13) # load address of do_IRQ
+        l       %r4,__LC_IO_INT_PARM       # load interruption parm
+	l       %r5,__LC_IO_INT_WORD       # load interruption word
+        l       %r9,BASED(.Ldo_IRQ)        # load address of do_IRQ
         basr    %r14,%r9          # branch to standard irq handler
 
 io_return:
         GET_CURRENT               # load pointer to task_struct to R9
         tm      SP_PSW+1(%r15),0x01 # returning to user ?
-        jz      io_leave          # no-> skip resched & signal
+        bz      BASED(io_leave)   # no-> skip resched & signal
         stosm   24(%r15),0x03     # reenable interrupts
 #
 # check, if bottom-half has to be done
 #
         l       %r0,__LC_IRQ_STAT     # get softirq_active
         n       %r0,__LC_IRQ_STAT+4   # and it with softirq_mask
-        jnz     io_handle_bottom_half
+        bnz     BASED(io_handle_bottom_half)
 io_return_bh:	
 #
 # check, if reschedule is needed
 #
         icm     %r0,15,need_resched(%r9) # get need_resched from task_struct
-        jnz     io_reschedule
+        bnz     BASED(io_reschedule)
         icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
-        jnz     io_signal_return
+        bnz     BASED(io_signal_return)
 io_leave:
         stnsm   24(%r15),disable  # disable I/O and ext. interrupts
         RESTORE_ALL
@@ -747,16 +756,16 @@
 # is zero
 #
 io_handle_bottom_half:        
-        l       %r1,io_do_softirq-io_lit(%r13)
-	la      %r14,io_return_bh-io_lit(%r13)
+        l       %r1,BASED(.Ldo_softirq)
+	la      %r14,BASED(io_return_bh)
         br      %r1               # call do_softirq
 
 #
 # call schedule with io_return as return-address
 #
 io_reschedule:        
-        l       %r1,io_schedule-io_lit(%r13)
-	la      %r14,io_return-io_lit(%r13)
+        l       %r1,BASED(.Lschedule)
+	la      %r14,BASED(io_return)
         br      %r1               # call scheduler, return to io_return
 
 #
@@ -765,103 +774,46 @@
 io_signal_return:     
         la      %r2,SP_PTREGS(%r15) # load pt_regs
         sr      %r3,%r3           # clear *oldset
-        l       %r1,io_do_signal-io_lit(%r13)
-	la      %r14,io_leave-io_lit(%r13)
+        l       %r1,BASED(.Ldo_signal)
+	la      %r14,BASED(io_leave)
         br      %r1               # return point is io_leave
 
 /*
  * External interrupt handler routine
  */
 
-ext_lit:
-  ext_timer_int:     .long  do_timer_interrupt
-#ifdef CONFIG_SMP
-  ext_call_int:      .long  do_ext_call_interrupt
-#endif
-#ifdef CONFIG_HWC
-  ext_hwc_int:      .long  do_hwc_interrupt
-#endif
-#ifdef CONFIG_MDISK
-  ext_mdisk_int:     .long  do_mdisk_interrupt
-#endif
-#ifdef CONFIG_IUCV
-  ext_iucv_int:      .long  do_iucv_interrupt
-#endif
-  ext_io_lit:	     .long  io_lit
-  ext_io_return:     .long  io_return
-
         .globl  ext_int_handler
 ext_int_handler:
         SAVE_ALL(0x18)
-        basr    %r13,0
-        ahi     %r13,ext_lit-.    # setup base pointer R13 to $EXTDAT
         la      %r2,SP_PTREGS(%r15)    # address of register-save area
         lh      %r3,__LC_EXT_INT_CODE  # error code
-#ifdef CONFIG_SMP
-	chi     %r3,0x1202        # EXTERNAL_CALL
-	jne     ext_no_extcall
-	l       %r9,ext_call_int-ext_lit(%r13) # load ext_call_interrupt
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_extcall:
-#endif
-        chi     %r3,0x1004        # CPU_TIMER
-        jne     ext_no_timer
-        l       %r9,ext_timer_int-ext_lit(%r13) # load timer_interrupt
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_timer:   
-#ifdef CONFIG_HWC
-        chi     %r3,0x2401        # HWC interrupt
-        jne     ext_no_hwc
-        l       %r9,ext_hwc_int-ext_lit(%r13) # load addr. of hwc routine
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_hwc:    
-#endif
-#ifdef CONFIG_MDISK
-        chi     %r3,0x2603        # diag 250 (VM) interrupt
-        jne     ext_no_mdisk
-        l       %r9,ext_mdisk_int-ext_lit(%r13)
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_mdisk:   
-#endif
-#ifdef CONFIG_IUCV
-        chi     %r3,0x4000        # diag 250 (VM) interrupt
-        jne     ext_no_iucv
-        l       %r9,ext_iucv_int-ext_lit(%r13)
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r9               # branch to ext call handler
-ext_no_iucv:    
-#endif
-
-	l       %r14,ext_io_return-ext_lit(%r13)
-        l       %r13,ext_io_lit-ext_lit(%r13)
-	br      %r14              # use backend code of io_int_handler
+        lr      %r1,%r3                # calculate index = code & 0xff
+        n       %r1,BASED(.Lc0xff)
+        sll     %r1,2
+        l       %r9,BASED(.Lext_hash)
+        l       %r9,0(%r1,%r9)         # get first list entry for hash value
+        ltr     %r9,%r9                # == NULL ?
+        bz      BASED(io_return)       # yes, nothing to do, exit
+ext_int_loop:
+        ch      %r3,8(%r9)             # compare external interrupt code
+        be      BASED(ext_int_found)
+        icm     %r9,15,0(%r9)          # next list entry
+        bnz     BASED(ext_int_loop)
+        b       BASED(io_return)
+ext_int_found:
+        l       %r9,4(%r9)             # get handler address
+        la      %r14,BASED(io_return)
+        br      %r9                    # branch to ext call handler
 
 /*
  * Machine check handler routines
  */
-mcck_lit:
-  mcck_crw_pending: .long  do_crw_pending
-
 
         .globl mcck_int_handler
 mcck_int_handler:
         SAVE_ALL(0x30)
-        basr    %r13,0
-        ahi     %r13,mcck_lit-.   # setup base pointer R13 to $MCCKDAT
-	tm      __LC_MCCK_CODE+1,0x40
-	jno     mcck_no_crw
-	l       %r1,mcck_crw_pending-mcck_lit(%r13)
-	basr    %r14,%r1	  # call do_crw_pending
-mcck_no_crw:
+	l       %r1,BASED(.Ls390_mcck)
+	basr    %r14,%r1	  # call machine check handler
 mcck_return:
         RESTORE_ALL
 
@@ -876,11 +828,11 @@
         lam     %a0,%a15,__LC_AREGS_SAVE_AREA
         stosm   0(%r15),daton          # now we can turn dat on
         lm      %r6,%r15,24(%r15)      # load registers from clone
-        bras    %r14,restart_go
-        .long   start_secondary
-restart_go:
-        l       %r14,0(%r14)
+        basr    %r14,0
+        l       %r14,restart_addr-.(%r14)
         br      %r14                   # branch to start_secondary
+restart_addr:
+        .long   start_secondary
 #else
 /*
  * If we do not run with SMP enabled, let the new CPU crash ...
@@ -894,5 +846,50 @@
 restart_crash:
         .long  0x000a0000,0x00000000
 restart_go:
+#endif
+
+/*
+ * Integer constants
+ */
+               .align 4
+.Lc0xfffffff8: .long  -8           # to align stack pointer to 8
+.Lc0xffffe000: .long  -8192        # to round stack pointer to &task_struct
+.Lc8191:       .long  8191
+.Lc_spsize:    .long  SP_SIZE
+.Lc_ac:        .long  0,0,1
+.Lc_ENOSYS:    .long  -ENOSYS
+.Lc4:          .long  4
+.Lc0x1202:     .long  0x1202
+.Lc0x1004:     .long  0x1004
+.Lc0x2401:     .long  0x2401
+.Lc0x4000:     .long  0x4000
+.Lc0xff:       .long  0xff
+
+/*
+ * Symbol constants
+ */
+.Ls390_mcck:   .long  s390_do_machine_check
+.Ldo_IRQ:      .long  do_IRQ
+.Ldo_signal:   .long  do_signal
+.Ldo_softirq:  .long  do_softirq
+.Lentry_base:  .long  entry_base
+.Lext_hash:    .long  ext_int_hash
+.Lhandle_per:  .long  handle_per_exception
+.Ljump_table:  .long  pgm_check_table
+.Lschedule:    .long  schedule
+.Lclone:       .long  sys_clone
+.Lexecve:      .long  sys_execve
+.Lfork:        .long  sys_fork
+.Lrt_sigreturn:.long  sys_rt_sigreturn
+.Lrt_sigsuspend:
+               .long  sys_rt_sigsuspend
+.Lsigreturn:   .long  sys_sigreturn
+.Lsigsuspend:  .long  sys_sigsuspend
+.Lsigaltstack: .long  sys_sigaltstack
+.Ltrace:       .long  syscall_trace
+.Lvfork:       .long  sys_vfork
+
+#ifdef CONFIG_SMP
+.Lschedtail:   .long  schedule_tail
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/head.S linux/arch/s390/kernel/head.S
--- v2.4.1/linux/arch/s390/kernel/head.S	Fri May 12 11:41:44 2000
+++ linux/arch/s390/kernel/head.S	Tue Feb 13 14:13:43 2001
@@ -2,20 +2,29 @@
  *  arch/s390/kernel/head.S
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Rob van der Heij (rvdhei@iae.nl)
  *
- * There are 4 different IPL methods
+ * There are 5 different IPL methods
  *  1) load the image directly into ram at address 0 and do an PSW restart
  *  2) linload will load the image from address 0x10000 to memory 0x10000
  *     and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
  *  3) generate the tape ipl header, store the generated image on a tape
  *     and ipl from it
+ *     In case of SL tape you need to IPL 5 times to get past VOL1 etc
  *  4) generate the vm reader ipl header, move the generated image to the
  *     VM reader (use option NOH!) and do a ipl from reader (VM only)
+ *  5) direct call of start by the SALIPL loader
  *  We use the cpuid to distinguish between VM and native ipl
  *  params for kernel are pushed to 0x10400 (see setup.h)
+
+    Changes: 
+    Okt 25 2000 <rvdheij@iae.nl>
+	added code to skip HDR and EOF to allow SL tape IPL (5 retries)
+	changed first CCW from rewind to backspace block
+
  */
 
 #include <linux/config.h>
@@ -24,40 +33,13 @@
 
 #ifndef CONFIG_IPL
         .org   0
-        .long  0x00080000,0x80000000+iplstart  # Just a restart PSW
-
-iplstart:
-        l     %r12,.Lparm                      # pointer to parameter area
-#
-# find out memory size
-#
-        mvc   104(8,0),.Lpcmem0          # setup program check handler
-        slr   %r2,%r2
-        lhi   %r3,1
-        sll   %r3,20
-.Lloop0:
-        l     %r0,0(%r2)                 # test page
-        ar    %r2,%r3                    # add 1M
-        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
-.Lchkmem0:
-        n     %r2,.L4malign0             # align to multiples of 4M
-        st    %r2,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
-        slr   %r2,%r2
-        st    %r2,INITRD_SIZE-PARMAREA(%r12)  # null ramdisk
-        st    %r2,INITRD_START-PARMAREA(%r12)
-        j     start
-
-.Lparm: .long  PARMAREA
-.L4malign0:.long 0xffc00000
-        .align 8
-.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
-
+        .long  0x00080000,0x80000000+startup   # Just a restart PSW
 #else
 #ifdef CONFIG_IPL_TAPE
 #define IPL_BS 1024
         .org   0
         .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
-        .long  0x07000000,0x60000001           # by ipl to addresses 0-23.
+        .long  0x27000000,0x60000001           # by ipl to addresses 0-23.
         .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
         .long  0x00000000,0x00000000           # external old psw
         .long  0x00000000,0x00000000           # svc old psw
@@ -74,92 +56,6 @@
         .long  0x00080000,0x80000000+.Lioint   # io new psw
 
         .org   0x100
-iplstart:
-	l     %r1,0xb8                         # load ipl subchannel number
-        lhi   %r2,IPL_BS                       # load start address
-        bras  %r14,.Lloader                    # load rest of ipl image
-        st    %r1,__LC_IPLDEV                  # store ipl device number
-        l     %r12,.Lparm                      # pointer to parameter area
-
-#
-# find out memory size
-#
-        mvc   104(8,0),.Lpcmem0          # setup program check handler
-        slr   %r2,%r2
-        lhi   %r3,1
-        sll   %r3,20
-.Lloop0:
-        l     %r0,0(%r2)                 # test page
-        ar    %r2,%r3                    # add 1M
-        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
-.Lchkmem0:
-        n     %r2,.L4malign0             # align to multiples of 4M
-        st    %r2,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
-        c     %r2,.Lbigmem               # more than 64 MB of memory ?
-        jl    .Lmemok                    # if yes load ramdisk to 32 MB
-        mvc   INITRD_START-PARMAREA(4,%r12),.Lrdstart
-.Lmemok:
-
-#
-# load parameter file from tape
-#
- 	l     %r2,INITRD_START-PARMAREA(%r12)  # use ramdisk location as temp
-        bras  %r14,.Lloader                    # load parameter file
-        ltr   %r2,%r2                          # got anything ?
-        jz    .Lnopf
-	chi   %r2,895
-	jnh   .Lnotrunc
-	lhi   %r2,895
-.Lnotrunc:
-        l     %r4,INITRD_START-PARMAREA(%r12)
-        la    %r5,0(%r4,%r2)
-        lr    %r3,%r2
-.Lidebc:
-        tm    0(%r5),0x80                      # high order bit set ?
-        jo    .Ldocv                           #  yes -> convert from EBCDIC
-        ahi   %r5,-1
-        brct  %r3,.Lidebc
-        j     .Lnocv
-.Ldocv:
-        l     %r3,.Lcvtab
-        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
-        tr    256(256,%r4),0(%r3)
-        tr    512(256,%r4),0(%r3)
-        tr    768(122,%r4),0(%r3)
-.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
-	mvc   0(256,%r3),0(%r4)
-	mvc   256(256,%r3),256(%r4)
-	mvc   512(256,%r3),512(%r4)
-	mvc   768(122,%r3),768(%r4)
-        slr   %r0,%r0
-        j     .Lcntlp
-.Ldelspc:
-        ic    %r0,0(%r2,%r3)
-        chi   %r0,0x20                         # is it a space ?
-        je    .Lcntlp
-        ahi   %r2,1
-        j     .Leolp
-.Lcntlp:
-        brct  %r2,.Ldelspc
-.Leolp:
-        slr   %r0,%r0
-        stc   %r0,0(%r2,%r3)                   # terminate buffer
-.Lnopf:
-
-#
-# load ramdisk from tape
-#	
- 	l     %r2,INITRD_START-PARMAREA(%r12)  # load adr. of ramdisk
-        bras  %r14,.Lloader                    # load ramdisk
- 	st    %r2,INITRD_SIZE-PARMAREA(%r12)   # store size of ramdisk
-        ltr   %r2,%r2
-        jnz   .Lrdcont
-        st    %r2,INITRD_START-PARMAREA(%r12)  # no ramdisk found, null it
-.Lrdcont:
-#
-# everything loaded, go for it
-#
-        j     start
 #
 # subroutine for loading from tape
 # Paramters:	
@@ -173,32 +69,32 @@
         lctl  %c6,%c6,.Lcr6               
         slr   %r2,%r2
 .Lldlp:
-        lhi   %r6,3                            # 3 retries
+        la    %r6,3                            # 3 retries
 .Lssch:
         ssch  0(%r3)                           # load chunk of IPL_BS bytes
-        jnz   .Llderr
+        bnz   .Llderr
 .Lw4end:
-        bras  %r14,.Lwait4io
+        bas   %r14,.Lwait4io
         tm    8(%r5),0x82                      # do we have a problem ?
-        jnz   .Lrecov
+        bnz   .Lrecov
         slr   %r7,%r7
         icm   %r7,3,10(%r5)                    # get residual count
         lcr   %r7,%r7
-        ahi   %r7,IPL_BS                       # IPL_BS-residual=#bytes read
+        la    %r7,IPL_BS(%r7)                  # IPL_BS-residual=#bytes read
         ar    %r2,%r7                          # add to total size
         tm    8(%r5),0x01                      # found a tape mark ?
-        jnz   .Ldone
+        bnz   .Ldone
         l     %r0,.Lccwread+4                  # update CCW data addresses
         ar    %r0,%r7
         st    %r0,.Lccwread+4                
-        j     .Lldlp
+        b     .Lldlp
 .Ldone:
         l     %r14,.Lldret
         br    %r14                             # r2 contains the total size
 .Lrecov:
-        bras  %r14,.Lsense                     # do the sensing
-        brct  %r6,.Lssch                       # dec. retry count & branch
-        j     .Llderr
+        bas   %r14,.Lsense                     # do the sensing
+        bct   %r6,.Lssch                       # dec. retry count & branch
+        b     .Llderr
 #
 # Sense subroutine
 #
@@ -206,11 +102,11 @@
         st    %r14,.Lsnsret
         la    %r7,.Lorbsense              
         ssch  0(%r7)                           # start sense command
-        jnz   .Llderr
-        bras  %r14,.Lwait4io
+        bnz   .Llderr
+        bas   %r14,.Lwait4io
         l     %r14,.Lsnsret
         tm    8(%r5),0x82                      # do we have a problem ?
-        jnz   .Llderr
+        bnz   .Llderr
         br    %r14
 #
 # Wait for interrupt subroutine
@@ -219,13 +115,13 @@
         lpsw  .Lwaitpsw                 
 .Lioint:
         c     %r1,0xb8                         # compare subchannel number
-        jne   .Lwait4io
+        bne   .Lwait4io
         tsch  0(%r5)
         slr   %r0,%r0
         tm    8(%r5),0x82                      # do we have a problem ?
-        jnz   .Lwtexit
+        bnz   .Lwtexit
         tm    8(%r5),0x04                      # got device end ?
-        jz    .Lwait4io
+        bz    .Lwait4io
 .Lwtexit:
         br    %r14
 .Llderr:
@@ -249,18 +145,12 @@
 .Lcr6:  .long  0xff000000
         .align 8
 .Lcrash:.long  0x000a0000,0x00000000
-.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
-.Lparm: .long  PARMAREA
-.L4malign0:.long 0xffc00000
-.Lbigmem:.long 0x04000000
-.Lrdstart:.long 0x02000000
 .Lldret:.long  0
 .Lsnsret: .long 0
-.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
-
 #endif  /* CONFIG_IPL_TAPE */
 
 #ifdef CONFIG_IPL_VM
+#define IPL_BS 0x730
         .org   0
         .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
         .long  0x02000018,0x60000050           # by ipl to addresses 0-23.
@@ -287,103 +177,7 @@
         .long  0x02000690,0x60000050
         .long  0x020006e0,0x20000050
 
-
         .org   0xf0
-iplstart:
-	l     %r1,0xb8                         # load ipl subchannel number
-        lhi   %r2,0x730                        # load start address
-        bras  %r14,.Lloader                    # load rest of ipl image
-        st    %r1,__LC_IPLDEV                  # store ipl device number
-	l     %r12,.Lparm                      # pointer to parameter area
-
-#
-# find out memory size
-#
-        mvc   104(8,0),.Lpcmem0           # setup program check handler
-        slr   %r2,%r2
-        lhi   %r3,1
-        sll   %r3,20
-.Lloop0:
-        l     %r0,0(%r2)                 # test page
-        ar    %r2,%r3                    # add 1M
-        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
-.Lchkmem0:
-        n     %r2,.L4malign0             # align to multiples of 4M
-        st    %r2,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
-        c     %r2,.Lbigmem               # more than 64 MB of memory ?
-        jl    .Lmemok                    # if yes load ramdisk to 32 MB
-        mvc   INITRD_START-PARMAREA(4,%r12),.Lrdstart
-.Lmemok:
-
-#
-# load parameter file from reader
-#
-        l     %r2,INITRD_START-PARMAREA(%r12)  # use ramdisk location as temp
-        bras  %r14,.Lloader                    # load parameter file
-        ltr   %r2,%r2                          # got anything ?
-        jz    .Lnopf
-        chi   %r2,895
-        jnh   .Lnotrunc
-        lhi   %r2,895
-.Lnotrunc:
-        l     %r4,INITRD_START-PARMAREA(%r12)
-        la    %r5,0(%r4,%r2)
-        lr    %r3,%r2
-.Lidebc:
-        tm    0(%r5),0x80                      # high order bit set ?
-        jo    .Ldocv                           #  yes -> convert from EBCDIC
-        ahi   %r5,-1
-        brct  %r3,.Lidebc
-        j     .Lnocv
-.Ldocv:
-        l     %r3,.Lcvtab
-        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
-        tr    256(256,%r4),0(%r3)
-        tr    512(256,%r4),0(%r3)
-        tr    768(122,%r4),0(%r3)
-.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
-        mvc   0(256,%r3),0(%r4)
-        mvc   256(256,%r3),256(%r4)
-        mvc   512(256,%r3),512(%r4)
-        mvc   768(122,%r3),768(%r4)
-        slr   %r0,%r0
-        j     .Lcntlp
-.Ldelspc:
-        ic    %r0,0(%r2,%r3)
-        chi   %r0,0x20                         # is it a space ?
-        je    .Lcntlp
-        ahi   %r2,1
-        j     .Leolp
-.Lcntlp:
-        brct  %r2,.Ldelspc
-.Leolp:
-        slr   %r0,%r0
-        stc   %r0,0(%r2,%r3)                   # terminate buffer
-.Lnopf:
-
-#
-# load ramdisk from reader
-#	
-	l     %r2,INITRD_START-PARMAREA(%r12)  # load adr. of ramdisk
-        bras  %r14,.Lloader                    # load ramdisk
-	st    %r2,INITRD_SIZE-PARMAREA(%r12)   # store size of ramdisk
-        ltr   %r2,%r2
-        jnz   .Lrdcont
-        st    %r2,INITRD_START-PARMAREA(%r12)  # no ramdisk found, null it
-.Lrdcont:
-
-#
-# everything loaded, reset files in reader, then go for it
-#
-        stidp __LC_CPUID                       # store cpuid
-        lh    %r0,__LC_CPUID+4                 # get cpu version
-        chi   %r0,0x7490                       # running on P/390 ?
-        je   start                             #   no -> skip reset
-        la    %r2,.Lreset              
-        lhi   %r3,26
-        .long 0x83230008
-	j     start
-
 #
 # subroutine for loading cards from the reader
 #
@@ -394,29 +188,29 @@
         la    %r7,20
 .Linit:
         st    %r2,4(%r6)                       # initialize CCW data addresses
-        ahi   %r2,0x50
-        ahi   %r6,8
-        brct  7,.Linit
+        la    %r2,0x50(%r2)
+        la    %r6,8(%r6)
+        bct   7,.Linit
 
         lctl  %c6,%c6,.Lcr6                    # set IO subclass mask
 	slr   %r2,%r2
 .Lldlp:
         ssch  0(%r3)                           # load chunk of 1600 bytes
-        jnz   .Llderr
+        bnz   .Llderr
 .Lwait4irq:
         mvc   __LC_IO_NEW_PSW(8),.Lnewpsw      # set up IO interrupt psw
         lpsw  .Lwaitpsw              
 .Lioint:
         c     %r1,0xb8                         # compare subchannel number
-	jne   .Lwait4irq
+	bne   .Lwait4irq
 	tsch  0(%r5)
 
 	slr   %r0,%r0
 	ic    %r0,8(%r5)                       # get device status
 	chi   %r0,8                            # channel end ?
-	je    .Lcont
+	be    .Lcont
 	chi   %r0,12                           # channel end + device end ?
-	je    .Lcont
+	be    .Lcont
 
         l     %r0,4(%r5)
         s     %r0,8(%r3)                       # r0/8 = number of ccws executed
@@ -436,9 +230,9 @@
         ahi   %r0,0x640
         st    %r0,4(%r6)
         ahi   %r6,8
-        brct  7,.Lincr
+        bct   7,.Lincr
 
-        j     .Lldlp
+        b     .Lldlp
 .Llderr:
         lpsw  .Lcrash              
 
@@ -447,16 +241,7 @@
 .Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 .Lcr6:  .long  0xff000000
 .Lloadp:.long  0,0
-.Lparm:	.long  PARMAREA
-.L4malign0:.long 0xffc00000
-.Lbigmem:.long 0x04000000
-.Lrdstart:.long 0x02000000
-.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
-.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
-        .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
-        .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
         .align 8
-.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
 .Lcrash:.long  0x000a0000,0x00000000
 .Lnewpsw:
         .long  0x00080000,0x80000000+.Lioint
@@ -468,79 +253,330 @@
         .long  0x02600050,0x00000000
         .endr
         .long  0x02200050,0x00000000
-	
-        .org   0x730     # end of the area loaded by the ipl channel program
 #endif  /* CONFIG_IPL_VM */
 
+iplstart:
+        lh    %r1,0xb8                         # test if subchannel number
+        bct   %r1,.Lnoload                     #  is valid
+	l     %r1,0xb8                         # load ipl subchannel number
+        la    %r2,IPL_BS                       # load start address
+        bas   %r14,.Lloader                    # load rest of ipl image
+        st    %r1,__LC_IPLDEV                  # store ipl device number
+        l     %r12,.Lparm                      # pointer to parameter area
+
+#
+# load parameter file from ipl device
+#
+.Lagain1:
+ 	l     %r2,INITRD_START-PARMAREA(%r12)  # use ramdisk location as temp
+        bas   %r14,.Lloader                    # load parameter file
+        ltr   %r2,%r2                          # got anything ?
+        bz    .Lnopf
+	chi   %r2,895
+	bnh   .Lnotrunc
+	la    %r2,895
+.Lnotrunc:
+	l     %r4,INITRD_START-PARMAREA(%r12)
+	clc   0(3,%r4),.L_hdr		       # if it is HDRx
+	bz    .Lagain1			       # skip dataset header
+	clc   0(3,%r4),.L_eof		       # if it is EOFx
+	bz    .Lagain1			       # skip dateset trailer
+        la    %r5,0(%r4,%r2)
+        lr    %r3,%r2
+.Lidebc:
+        tm    0(%r5),0x80                      # high order bit set ?
+        bo    .Ldocv                           #  yes -> convert from EBCDIC
+        ahi   %r5,-1
+        bct   %r3,.Lidebc
+        b     .Lnocv
+.Ldocv:
+        l     %r3,.Lcvtab
+        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
+        tr    256(256,%r4),0(%r3)
+        tr    512(256,%r4),0(%r3)
+        tr    768(122,%r4),0(%r3)
+.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
+	mvc   0(256,%r3),0(%r4)
+	mvc   256(256,%r3),256(%r4)
+	mvc   512(256,%r3),512(%r4)
+	mvc   768(122,%r3),768(%r4)
+        slr   %r0,%r0
+        b     .Lcntlp
+.Ldelspc:
+        ic    %r0,0(%r2,%r3)
+        chi   %r0,0x20                         # is it a space ?
+        be    .Lcntlp
+        ahi   %r2,1
+        b     .Leolp
+.Lcntlp:
+        brct  %r2,.Ldelspc
+.Leolp:
+        slr   %r0,%r0
+        stc   %r0,0(%r2,%r3)                   # terminate buffer
+.Lnopf:
+
+#
+# load ramdisk from ipl device
+#	
+.Lagain2:
+ 	l     %r2,INITRD_START-PARMAREA(%r12)  # load adr. of ramdisk
+        bas   %r14,.Lloader                    # load ramdisk
+ 	st    %r2,INITRD_SIZE-PARMAREA(%r12)   # store size of ramdisk
+        ltr   %r2,%r2
+        bnz   .Lrdcont
+        st    %r2,INITRD_START-PARMAREA(%r12)  # no ramdisk found, null it
+.Lrdcont:
+	l     %r2,INITRD_START-PARMAREA(%r12)
+
+	clc   0(3,%r2),.L_hdr		       # skip HDRx and EOFx 
+	bz    .Lagain2
+	clc   0(3,%r2),.L_eof
+	bz    .Lagain2
+
+#ifdef CONFIG_IPL_VM
+#
+# reset files in VM reader
+#
+        stidp __LC_CPUID                       # store cpuid
+        lh    %r0,__LC_CPUID+4                 # get cpu version
+        chi   %r0,0x7490                       # running on P/390 ?
+        be    start                            #   no -> skip reset
+        la    %r2,.Lreset              
+        lhi   %r3,26
+        .long 0x83230008
+#endif
+	
+#
+# everything loaded, go for it
+#
+.Lnoload:
+        l     %r1,.Lstartup
+        br    %r1
+
+.Lparm:	.long  PARMAREA
+.Lstartup: .long startup
+.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
+.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
+        .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
+        .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
+.L_eof: .long  0xc5d6c600       /* C'EOF' */
+.L_hdr: .long  0xc8c4d900       /* C'HDR' */
+
 #endif  /* CONFIG_IPL */
 
 #
+# SALIPL loader support. Based on a patch by Rob van der Heij.
+# This entry point is called directly from the SALIPL loader and
+# doesn't need a builtin ipl record.
+#
+        .org  0x800
+	.globl start
+start:
+	stm   %r0,%r15,0x07b0		# store registers
+	basr  %r12,%r0
+.base:
+	l     %r11,.parm
+	l     %r8,.cmd			# pointer to command buffer
+
+	ltr   %r9,%r9			# do we have SALIPL parameters?
+	bp    .sk8x8
+
+	mvc   0(64,%r8),0x00b0		# copy saved registers
+	xc    64(240-64,%r8),0(%r8)	# remainder of buffer
+	tr    0(64,%r8),.lowcase	
+	b     .gotr
+.sk8x8:
+	mvc   0(240,%r8),0(%r9)		# copy iplparms into buffer
+.gotr:
+	l     %r10,.tbl			# EBCDIC to ASCII table
+	tr    0(240,%r8),0(%r10)
+	stidp __LC_CPUID		# Are we running on VM maybe
+	cli   __LC_CPUID,0xff
+	bnz   .test
+	.long 0x83300060		# diag 3,0,x'0060' - storage size
+	b     .done
+.test:
+	mvc   0x68(8),.pgmnw		# set up pgm check handler
+	l     %r2,.fourmeg
+	lr    %r3,%r2
+	bctr  %r3,%r0			# 4M-1
+.loop:  iske  %r0,%r3
+	ar    %r3,%r2
+.pgmx:
+	sr    %r3,%r2
+	la    %r3,1(%r3)
+.done:
+	st    %r3,MEMORY_SIZE-PARMAREA(%r11)	
+	slr   %r0,%r0
+	st    %r0,INITRD_SIZE-PARMAREA(%r11)
+	st    %r0,INITRD_START-PARMAREA(%r11)
+	j     startup                   # continue with startup
+.tbl:	.long _ebcasc			# translate table
+.cmd:	.long COMMAND_LINE		# address of command line buffer
+.parm:	.long PARMAREA
+.fourmeg: .long 0x00400000      	# 4M
+.pgmnw:	.long 0x00080000,.pgmx
+.lowcase:
+	.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 
+	.byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
+	.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 
+	.byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
+	.byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 
+	.byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
+	.byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 
+	.byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
+	.byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 
+	.byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
+	.byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 
+	.byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
+	.byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 
+	.byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
+	.byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 
+	.byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
+
+	.byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 
+	.byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
+	.byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 
+	.byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
+	.byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 
+	.byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
+	.byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 
+	.byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
+	.byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87	# .abcdefg 
+	.byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf	# hi
+	.byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 	# .jklmnop
+	.byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf	# qr
+	.byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7	# ..stuvwx
+	.byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef	# yz
+	.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
+	.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+
+#
 # startup-code at 0x10000, running in real mode
-# this is called either by the ipl loader or directly by PSW restart or linload
+# this is called either by the ipl loader or directly by PSW restart
+# or linload or SALIPL
 #
         .org  0x10000
-        .globl start
-start:  basr  %r13,0                     # get base
-.LPG1:  lctl  %c1,%c1,.Lpstd-.LPG1(%r13) # load pstd
-        lctl  %c7,%c7,.Lpstd-.LPG1(%r13) # load sstd
-        lctl  %c13,%c13,.Lpstd-.LPG1(%r13) # load hstd
-        lctl  %c0,%c0,.Lcr0-.LPG1(%r13)  # set CR0
+startup:basr  %r13,0                     # get base
+.LPG1:  lctl  %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
 	l     %r12,.Lparm1-.LPG1(%r13)   # pointer to parameter area
 
 #
-# find out memory size. That is done in the ipl loader too but for
-# ipl from dasd the size of the memory has to be detected too...
+# find out memory size.
 #
-        icm   %r0,15,MEMORY_SIZE-PARMAREA(%r12)
-        jnz   .Lsizeok
-	mvc   104(8,0),.Lpcmem-.LPG1(%r13) # setup program check handler
-        slr   %r1,%r1
+	mvc   104(8),.Lpcmem-.LPG1(%r13) # setup program check handler
         lhi   %r2,1
-        sll   %r2,20
+        sll   %r2,17                     # test in increments of 128KB
+	lr    %r1,%r2
+	ahi   %r1,-4                     # test last word in the segment
 .Lloop:	
-	l     %r0,0(%r1)                 # test page
-	ar    %r1,%r2                    # add 1M
-	jnm   .Lloop                     # r1 < 0x80000000 -> loop
+	l     %r0,0(%r1)                 # test 128KB segment
+	st    %r0,0(%r1)
+	ar    %r1,%r2                    # add 128KB
+	bnm   .Lloop-.LPG1(%r13)         # r1 < 0x80000000 -> loop
 .Lchkmem:
 	n     %r1,.L4malign-.LPG1(%r13)  # align to multiples of 4M
 	st    %r1,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
 .Lsizeok:
 
 #
+# Now we have to move the ramdisk to a location approriate for the
+# memory size. If we have more than 64 MB of memory we move it to 32MB
+# to make room for the page tables set up by paging_init.
+#
+        l     %r1,MEMORY_SIZE-PARMAREA(%r12)
+        cl    %r1,.Lbigmem-.LPG1(%r13)   # memory < 64mb ?
+        bl    .Lnomove-.LPG1(%r13)       # if yes ramdisk @8MB is ok
+        icm   %r4,15,INITRD_START-PARMAREA(%r12)
+        bz    .Lnomove-.LPG1(%r13)
+	l     %r2,.Lrdstart-.LPG1(%r13)  # new address of ramdisk
+	st    %r2,INITRD_START-PARMAREA(%r12)
+        l     %r1,INITRD_SIZE-PARMAREA(%r12)
+	ar    %r2,%r1                    # we start moving at the end
+	ar    %r4,%r1                    #  because new location > old location
+.Lmove:	lr    %r0,%r2                    # new - old is the maximum we can move
+	sr    %r0,%r4                    #  because of overlapping
+	cr    %r0,%r1                    # we shouldn't move more than there is
+	bnh   .Lnoend-.LPG1(%r13)
+	lr    %r0,%r1
+.Lnoend:cl    %r0,.Lmaxchunk-.LPG1(%r13) # mvcl can move 2^24-1 in one go
+	bnh   .Lchunk-.LPG1(%r13)
+	l     %r0,.Lmaxchunk-.LPG1(%r13)
+.Lchunk:sr    %r2,%r0                    # make source & destination pointer
+	sr    %r4,%r0
+	lr    %r3,%r0                    # set source & destination length
+	lr    %r5,%r0
+	mvcl  %r2,%r4
+	sr    %r2,%r0                    # substract length again, since
+	sr    %r4,%r0                    #  mvcl added it to the pointers
+	sr    %r1,%r0                    # substract chunk size from length
+	bnz   .Lmove-.LPG1(%r13)
+.Lnomove:
+
+#
 # find out if we are running under VM
 #
         stidp  __LC_CPUID               # store cpuid
 	tm     __LC_CPUID,0xff          # running under VM ?
-	jno    .Lnovm
+	bno    .Lnovm-.LPG1(%r13)
         oi     MACHINE_FLAGS+3-PARMAREA(%r12),1    # set VM flag
 .Lnovm:
         lh     %r0,__LC_CPUID+4         # get cpu version
         chi    %r0,0x7490               # running on a P/390 ?
-        jne    .Lnop390
+        bne    .Lnop390-.LPG1(%r13)
         oi     MACHINE_FLAGS+3-PARMAREA(%r12),4    # set P/390 flag
 .Lnop390:
 
 #
 # find out if we have an IEEE fpu
 #
-        mvc    104(8,0),.Lpcfpu-.LPG1(%r13) # setup program check handler
+        mvc    104(8),.Lpcfpu-.LPG1(%r13) # setup program check handler
         ld     %f0,.Lflt0-.LPG1(%r13)   # load (float) 0.0
         ldr    %f2,%f0
         adbr   %f0,%f2                  # test IEEE add instruction
         oi     MACHINE_FLAGS+3-PARMAREA(%r12),2    # set IEEE fpu flag
 .Lchkfpu:
 
+#
+# find out if we have the CSP instruction
+#
+       mvc    104(8),.Lpccsp-.LPG1(%r13) # setup program check handler
+       la     %r0,0
+       lr     %r1,%r0
+       la     %r2,.Lflt0-.LPG1(%r13)
+       csp    %r0,%r2                   # Test CSP instruction
+       oi     MACHINE_FLAGS+3-PARMAREA(%r12),8 # set CSP flag
+.Lchkcsp:
+
         lpsw  .Lentry-.LPG1(13)         # jump to _stext in primary-space,
                                         # virtual and never return ...
         .align 8
-.Lentry:.long  0x04080000,0x80000000 + _stext
-.Lpstd: .long  .Lpgd+0x7F               # segment-table
-.Lcr0:  .long  0x04b50002
+.Lentry:.long  0x00080000,0x80000000 + _stext
+.Lctl:  .long  0x04b50002               # cr0: various things
+        .long  0                        # cr1: primary space segment table
+        .long  0                        # cr2: access register translation
+        .long  0                        # cr3: instruction authorization
+        .long  0                        # cr4: instruction authorization
+        .long  0                        # cr5:  various things
+        .long  0                        # cr6:  I/O interrupts
+        .long  0                        # cr7:  secondary space segment table
+        .long  0                        # cr8:  access registers translation
+        .long  0                        # cr9:  tracing off
+        .long  0                        # cr10: tracing off
+        .long  0                        # cr11: tracing off
+        .long  0                        # cr12: tracing off
+        .long  0                        # cr13: home space segment table
+        .long  0xc0000000               # cr14: machine check handling off
+        .long  0                        # cr15: linkage stack operations
 .Lpcmem:.long  0x00080000,0x80000000 + .Lchkmem
 .Lpcfpu:.long  0x00080000,0x80000000 + .Lchkfpu
+.Lpccsp:.long  0x00080000,0x80000000 + .Lchkcsp
 .Lflt0: .double 0
 .Lparm1:.long  PARMAREA
 .L4malign:.long 0xffc00000
+.Lbigmem:.long 0x04000000
+.Lrdstart:.long 0x02000000
+.Lmaxchunk:.long  0x00ffffff
 
 #
 # params at 10400 (setup.h)
@@ -555,17 +591,8 @@
 	.word  0                        # RAMDISK_FLAGS
 
         .org   COMMAND_LINE
-#       .byte  "root=/dev/nfs rw nfsroot=9.164.160.7:/home/mschwide/nfsboot "
-#       .byte  "ip=9.164.147.12:9.164.160.7:9.164.147.1:255.255.255.0:vmlinux:tr0:off"
-#       .byte  "root=/dev/nfs nfsroot=9.164.160.7:/home/mschwide/nfsboot "
-#       .byte  "ip=9.164.181.228:9.164.160.7:9.164.181.1:255.255.224.0:vmlinux:tr0:off"
-#       .byte  "root=/dev/nfs nfsroot=9.164.160.7:/home/pasch/nfsboot "
-#       .byte  "ip=9.164.185.120:9.164.160.7:9.164.181.1:255.255.224.0:vmlinux:tr0:off"
-#       .byte  "mdisk=402:65536:1229,403:131072:2780 root=/dev/mnda ro"
-#       .byte  "root=/dev/nfs rw nfsroot=9.164.160.209:/usr/local/nfsboot "
-#       .byte  "ip=9.164.181.228:9.164.160.209:9.164.181.1:255.255.224.0:vmlinux:tr0:off"
     	.byte  "root=/dev/ram0 ro"
-#       .byte  0
+        .byte  0
 
 #
 # startup-code, running in virtual mode
@@ -625,44 +652,4 @@
 .Laregs:    .long  0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
 	    .align 8
 .Ldw:	    .long  0x000a0000,0x00000000
-
-#
-#        tempory segment-table at 0x11000
-#
-        .org   0x11000
-.Lpgd:  .long  .Lpt0+0x1f               # 00000000-000fffff
-        .long  .Lpt1+0x1f               # 00100000-001fffff
-        .long  .Lpt2+0x1f               # 00200000-002fffff
-        .long  .Lpt3+0x1f               # 00300000-003fffff
-        .fill  2044,4,0x20              # 00400000-7fffffff
-
-#
-#        tempory page-tables at 0x12000-0x15fff
-#
-        .macro  mktable from,to
-        .long   \from*0x10000
-        .long   \from*0x10000+0x1000
-        .long   \from*0x10000+0x2000
-        .long   \from*0x10000+0x3000
-        .long   \from*0x10000+0x4000
-        .long   \from*0x10000+0x5000
-        .long   \from*0x10000+0x6000
-        .long   \from*0x10000+0x7000
-        .long   \from*0x10000+0x8000
-        .long   \from*0x10000+0x9000
-        .long   \from*0x10000+0xa000
-        .long   \from*0x10000+0xb000
-        .long   \from*0x10000+0xc000
-        .long   \from*0x10000+0xd000
-        .long   \from*0x10000+0xe000
-        .long   \from*0x10000+0xf000
-        .if     \to-\from
-        mktable "(\from+1)",\to
-        .endif
-        .endm
-
-.Lpt0:  mktable 0,15
-.Lpt1:  mktable 16,31
-.Lpt2:  mktable 32,47
-.Lpt3:  mktable 48,63
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/irq.c linux/arch/s390/kernel/irq.c
--- v2.4.1/linux/arch/s390/kernel/irq.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/s390/kernel/irq.c	Tue Feb 13 14:13:43 2001
@@ -20,11 +20,11 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/random.h>
 #include <linux/smp.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 
@@ -205,6 +205,8 @@
 			if (!local_bh_count(cpu)
 			    && atomic_read(&global_bh_count))
 				continue;
+			/* this works even though global_irq_lock not
+                           a long, but is arch-specific --RR */
 			if (!test_and_set_bit(0,&global_irq_lock))
 				break;
 		}
@@ -243,6 +245,8 @@
 
 static inline void get_irqlock(int cpu)
 {
+	/* this works even though global_irq_lock not a long, but is
+	   arch-specific --RR */
 	if (test_and_set_bit(0,&global_irq_lock)) {
 		/* do we already hold the lock? */
 		if ( cpu == atomic_read(&global_irq_holder))
@@ -398,7 +402,7 @@
 
 void __init init_IRQ(void)
 {
-   s390_init_IRQ();
+        s390_init_IRQ();
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/mathemu.c linux/arch/s390/kernel/mathemu.c
--- v2.4.1/linux/arch/s390/kernel/mathemu.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/mathemu.c	Tue Feb 13 14:13:43 2001
@@ -9,6 +9,7 @@
  * that does not have the IEEE fpu
  */
 
+#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/ptrace.h>
@@ -16,7 +17,59 @@
 #include <asm/uaccess.h>
 #include <asm/mathemu.h>
 
-static void set_CC_df(__u64 val1,__u64 val2) {
+#ifdef CONFIG_SYSCTL
+int sysctl_ieee_emulation_warnings=1;
+#endif
+
+#define mathemu_put_user(x, ptr) \
+{                                \
+	if(put_user((x),(ptr)))  \
+		return 1;        \
+}
+
+#define mathemu_get_user(x, ptr) \
+{                                \
+	if(get_user((x),(ptr)))  \
+		return 1;        \
+}
+
+
+#define mathemu_copy_from_user(to,from,n)                 \
+{                                                         \
+	if(copy_from_user((to),(from),(n))==-EFAULT)      \
+		return 1;                                 \
+}
+
+
+#define mathemu_copy_to_user(to, from, n)                 \
+{                                                         \
+	if(copy_to_user((to),(from),(n))==-EFAULT)      \
+		return 1;                                 \
+}
+
+
+
+static void display_emulation_not_implemented(char *instr)
+{
+	struct pt_regs *regs;
+	__u16 *location;
+	
+#if CONFIG_SYSCTL
+	if(sysctl_ieee_emulation_warnings)
+#endif
+	{
+		regs=current->thread.regs;
+		location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+		printk("%s ieee fpu instruction not emulated process name: %s pid: %d \n",
+		       instr,
+		       current->comm, current->pid);
+		printk("%s's PSW:    %08lx %08lx\n",instr,
+		       (unsigned long) regs->psw.mask,
+		       (unsigned long) location);
+	}
+}
+
+static int set_CC_df(__u64 val1,__u64 val2) {
         int rc;
         rc = __cmpdf2(val1,val2);
         current->thread.regs->psw.mask &= 0xFFFFCFFF;
@@ -28,9 +81,10 @@
                         current->thread.regs->psw.mask |= 0x00002000;
                         break;
         }
+	return 0;
 }
 
-static void set_CC_sf(__u32 val1,__u32 val2) {
+static int set_CC_sf(__u32 val1,__u32 val2) {
         int rc;
         rc = __cmpsf2(val1,val2);
         current->thread.regs->psw.mask &= 0xFFFFCFFF;
@@ -42,384 +96,473 @@
                         current->thread.regs->psw.mask |= 0x00002000;
                         break;
         }
+	return 0;
 }
 
 
-static void emu_adb (int rx, __u64 val) {
+static int emu_adb (int rx, __u64 val) {
         current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,val);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_adbr (int rx, int ry) {
+static int emu_adbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,
                                          current->thread.fp_regs.fprs[ry].d);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_aeb (int rx, __u32 val) {
+static int emu_aeb (int rx, __u32 val) {
         current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,val);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_aebr (int rx, int ry) {
+static int emu_aebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,
                                         current->thread.fp_regs.fprs[ry].f);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_axbr (int rx, int ry) {
-        printk("axbr emulation not implemented!\n");
+static int emu_axbr (int rx, int ry) {
+        display_emulation_not_implemented("axbr");
+	return 0;
 }
 
-static void emu_cdb (int rx, __u64 val) {
+static int emu_cdb (int rx, __u64 val) {
         set_CC_df(current->thread.fp_regs.fprs[rx].d,val);
+	return 0;
 }
 
-static void emu_cdbr (int rx, int ry) {
+static int emu_cdbr (int rx, int ry) {
         set_CC_df(current->thread.fp_regs.fprs[rx].d,current->thread.fp_regs.fprs[ry].d);
+	return 0;
 }
 
-static void emu_cdfbr (int rx, int ry) {
+static int emu_cdfbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d =
                      __floatsidf(current->thread.regs->gprs[ry]);
+	return 0;
 }
 
-static void emu_ceb (int rx, __u32 val) {
+static int emu_ceb (int rx, __u32 val) {
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,val);
+	return 0;
 }
 
-static void emu_cebr (int rx, int ry) {
+static int emu_cebr (int rx, int ry) {
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,current->thread.fp_regs.fprs[ry].f);
+	return 0;
 }
 
-static void emu_cefbr (int rx, int ry) {
+static int emu_cefbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f =
                      __floatsisf(current->thread.regs->gprs[ry]);
+	return 0;
 }
 
-static void emu_cfdbr (int rx, int ry, int mask) {
+static int emu_cfdbr (int rx, int ry, int mask) {
         current->thread.regs->gprs[rx] =
                      __fixdfsi(current->thread.fp_regs.fprs[ry].d);
+	return 0;
 }
 
-static void emu_cfebr (int rx, int ry, int mask) {
+static int emu_cfebr (int rx, int ry, int mask) {
         current->thread.regs->gprs[rx] =
                      __fixsfsi(current->thread.fp_regs.fprs[ry].f);
+	return 0;
 }
 
-static void emu_cfxbr (int rx, int ry, int mask) {
-        printk("cfxbr emulation not implemented!\n");
+static int emu_cfxbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("cfxbr");
+	return 0;
 }
 
-static void emu_cxbr (int rx, int ry) {
-        printk("cxbr emulation not implemented!\n");
+static int emu_cxbr (int rx, int ry) {
+        display_emulation_not_implemented("cxbr");
+	return 0;
 }
 
-static void emu_cxfbr (int rx, int ry) {
-        printk("cxfbr emulation not implemented!\n");
+static int emu_cxfbr (int rx, int ry) {
+        display_emulation_not_implemented("cxfbr");
+	return 0;
 }
 
-static void emu_ddb (int rx, __u64 val) {
+static int emu_ddb (int rx, __u64 val) {
         current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,val);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_ddbr (int rx, int ry) {
+static int emu_ddbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,
                                          current->thread.fp_regs.fprs[ry].d);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_deb (int rx, __u32 val) {
+static int emu_deb (int rx, __u32 val) {
         current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,val);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_debr (int rx, int ry) {
+static int emu_debr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,
                                          current->thread.fp_regs.fprs[ry].f);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_didbr (int rx, int ry, int mask) {
-        printk("didbr emulation not implemented!\n");
+static int emu_didbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("didbr");
+	return 0;
 }
 
-static void emu_diebr (int rx, int ry, int mask) {
-        printk("diebr emulation not implemented!\n");
+static int emu_diebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("diebr");
+	return 0;
 }
 
-static void emu_dxbr (int rx, int ry) {
-        printk("dxbr emulation not implemented!\n");
+static int emu_dxbr (int rx, int ry) {
+        display_emulation_not_implemented("dxbr");
+	return 0;
 }
 
-static void emu_efpc (int rx, int ry) {
-        printk("efpc emulation not implemented!\n");
+static int emu_efpc (int rx, int ry) {
+	current->thread.regs->gprs[rx]=current->thread.fp_regs.fpc;
+	return 0;
 }
 
-static void emu_fidbr (int rx, int ry, int mask) {
-        printk("fidbr emulation not implemented!\n");
+static int emu_fidbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("fidbr");
+	return 0;
 }
 
-static void emu_fiebr (int rx, int ry, int mask) {
-        printk("fiebr emulation not implemented!\n");
+static int emu_fiebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("fiebr");
+	return 0;
 }
 
-static void emu_fixbr (int rx, int ry, int mask) {
-        printk("fixbr emulation not implemented!\n");
+static int emu_fixbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("fixbr");
+	return 0;
 }
 
-static void emu_kdb (int rx, __u64 val) {
-        printk("kdb emulation not implemented!\n");
+static int emu_kdb (int rx, __u64 val) {
+        display_emulation_not_implemented("kdb");
+	return 0;
 }
 
-static void emu_kdbr (int rx, int ry) {
-        printk("kdbr emulation not implemented!\n");
+static int emu_kdbr (int rx, int ry) {
+        display_emulation_not_implemented("kdbr");
+	return 0;
 }
 
-static void emu_keb (int rx, __u32 val) {
-        printk("keb emulation not implemented!\n");
+static int emu_keb (int rx, __u32 val) {
+        display_emulation_not_implemented("keb");
+	return 0;
 }
 
-static void emu_kebr (int rx, int ry) {
-        printk("kebr emulation not implemented!\n");
+static int emu_kebr (int rx, int ry) {
+        display_emulation_not_implemented("kebr");
+	return 0;
 }
 
-static void emu_kxbr (int rx, int ry) {
-        printk("kxbr emulation not implemented!\n");
+static int emu_kxbr (int rx, int ry) {
+        display_emulation_not_implemented("kxbr");
+	return 0;
 }
 
-static void emu_lcdbr (int rx, int ry) {
+static int emu_lcdbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d =
         __negdf2(current->thread.fp_regs.fprs[ry].d);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_lcebr (int rx, int ry) {
+static int emu_lcebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f =
         __negsf2(current->thread.fp_regs.fprs[ry].f);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_lcxbr (int rx, int ry) {
-        printk("lcxbr emulation not implemented!\n");
+static int emu_lcxbr (int rx, int ry) {
+        display_emulation_not_implemented("lcxbr");
+	return 0;
 }
 
-static void emu_ldeb (int rx, __u32 val) {
+static int emu_ldeb (int rx, __u32 val) {
         current->thread.fp_regs.fprs[rx].d = __extendsfdf2(val);
+	return 0;
 }
 
-static void emu_ldebr (int rx, int ry) {
+static int emu_ldebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d =
         __extendsfdf2(current->thread.fp_regs.fprs[ry].f);
+	return 0;
 }
 
-static void emu_ldxbr (int rx, int ry) {
-        printk("ldxbr emulation not implemented!\n");
+static int emu_ldxbr (int rx, int ry) {
+        display_emulation_not_implemented("ldxbr");
+	return 0;
 }
 
-static void emu_ledbr (int rx, int ry) {
+static int emu_ledbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = __truncdfsf2(current->thread.fp_regs.fprs[ry].d);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_lexbr (int rx, int ry) {
-        printk("lexbr emulation not implemented!\n");
+static int emu_lexbr (int rx, int ry) {
+        display_emulation_not_implemented("lexbr");
+	return 0;
 }
 
-static void emu_lndbr (int rx, int ry) {
-        printk("lndbr emulation not implemented!\n");
+static int emu_lndbr (int rx, int ry) {
+        display_emulation_not_implemented("lndbr");
+	return 0;
 }
 
-static void emu_lnebr (int rx, int ry) {
-        printk("lnebr emulation not implemented!\n");
+static int emu_lnebr (int rx, int ry) {
+        display_emulation_not_implemented("lnebr");
+	return 0;
 }
 
-static void emu_lnxbr (int rx, int ry) {
-        printk("lnxbr emulation not implemented!\n");
+static int emu_lnxbr (int rx, int ry) {
+        display_emulation_not_implemented("lnxbr");
+	return 0;
 }
 
-static void emu_lpdbr (int rx, int ry) {
+static int emu_lpdbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d = __absdf2(current->thread.fp_regs.fprs[ry].d);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0);
+	return 0;
 }
 
-static void emu_lpebr (int rx, int ry) {
+static int emu_lpebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = __abssf2(current->thread.fp_regs.fprs[ry].f);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_lpxbr (int rx, int ry) {
-        printk("lpxbr emulation not implemented!\n");
+static int emu_lpxbr (int rx, int ry) {
+        display_emulation_not_implemented("lpxbr");
+	return 0;
 }
 
-static void emu_ltdbr (int rx, int ry) {
+static int emu_ltdbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d = current->thread.fp_regs.fprs[ry].d;
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_ltebr (int rx, int ry) {
+static int emu_ltebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = current->thread.fp_regs.fprs[ry].f;
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_ltxbr (int rx, int ry) {
-        printk("ltxbr emulation not implemented!\n");
+static int emu_ltxbr (int rx, int ry) {
+        display_emulation_not_implemented("ltxbr");
+	return 0;
 }
 
-static void emu_lxdb (int rx, __u64 val) {
-        printk("lxdb emulation not implemented!\n");
+static int emu_lxdb (int rx, __u64 val) {
+        display_emulation_not_implemented("lxdb");
+	return 0;
 }
 
-static void emu_lxdbr (int rx, int ry) {
-        printk("lxdbr emulation not implemented!\n");
+static int emu_lxdbr (int rx, int ry) {
+        display_emulation_not_implemented("lxdbr");
+	return 0;
 }
 
-static void emu_lxeb (int rx, __u32 val) {
-        printk("lxeb emulation not implemented!\n");
+static int emu_lxeb (int rx, __u32 val) {
+        display_emulation_not_implemented("lxeb");
+	return 0;
 }
 
-static void emu_lxebr (int rx, int ry) {
-        printk("lxebr emulation not implemented!\n");
+static int emu_lxebr (int rx, int ry) {
+        display_emulation_not_implemented("lxebr");
+	return 0;
 }
 
-static void emu_madb (int rx, __u64 val, int mask) {
-        printk("madb emulation not implemented!\n");
+static int emu_madb (int rx, __u64 val, int mask) {
+        display_emulation_not_implemented("madb");
+	return 0;
 }
 
-static void emu_madbr (int rx, int ry, int mask) {
-        printk(" emulation not implemented!\n");
+static int emu_madbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("madbr");
+	return 0;
 }
 
-static void emu_maeb (int rx, __u32 val, int mask) {
-        printk("maeb emulation not implemented!\n");
+static int emu_maeb (int rx, __u32 val, int mask) {
+        display_emulation_not_implemented("maeb");
+	return 0;
 }
 
-static void emu_maebr (int rx, int ry, int mask) {
-        printk("maebr emulation not implemented!\n");
+static int emu_maebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("maebr");
+	return 0;
 }
 
-static void emu_mdb (int rx, __u64 val) {
+static int emu_mdb (int rx, __u64 val) {
         current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,val);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_mdbr (int rx, int ry) {
+static int emu_mdbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,
                                          current->thread.fp_regs.fprs[ry].d);
         set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_mdeb (int rx, __u32 val) {
-        printk("mdeb emulation not implemented!\n");
+static int emu_mdeb (int rx, __u32 val) {
+        display_emulation_not_implemented("mdeb");
+	return 0;
 }
 
-static void emu_mdebr (int rx, int ry) {
-        printk("mdebr emulation not implemented!\n");
+static int emu_mdebr (int rx, int ry) {
+        display_emulation_not_implemented("mdebr");
+	return 0;
 }
 
-static void emu_meeb (int rx, __u32 val) {
+static int emu_meeb (int rx, __u32 val) {
         current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f,
                                          val);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_meebr (int rx, int ry) {
+static int emu_meebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f,
                                          current->thread.fp_regs.fprs[ry].f);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_msdb (int rx, __u64 val, int mask) {
-        printk("msdb emulation not implemented!\n");
+static int emu_msdb (int rx, __u64 val, int mask) {
+        display_emulation_not_implemented("msdb");
+	return 0;
 }
 
-static void emu_msdbr (int rx, int ry, int mask) {
-        printk("msdbr emulation not implemented!\n");
+static int emu_msdbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("msdbr");
+	return 0;
 }
 
-static void emu_mseb (int rx, __u32 val, int mask) {
-        printk("mseb emulation not implemented!\n");
+static int emu_mseb (int rx, __u32 val, int mask) {
+        display_emulation_not_implemented("mseb");
+	return 0;
 }
 
-static void emu_msebr (int rx, int ry, int mask) {
-        printk("msebr emulation not implemented!\n");
+static int emu_msebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("msebr");
+	return 0;
 }
 
-static void emu_mxbr (int rx, int ry) {
-        printk("mxbr emulation not implemented!\n");
+static int emu_mxbr (int rx, int ry) {
+        display_emulation_not_implemented("mxbr");
+	return 0;
 }
 
-static void emu_mxdb (int rx, __u64 val) {
-        printk("mxdb emulation not implemented!\n");
+static int emu_mxdb (int rx, __u64 val) {
+        display_emulation_not_implemented("mxdb");
+	return 0;
 }
 
-static void emu_mxdbr (int rx, int ry) {
-        printk("mxdbr emulation not implemented!\n");
+static int emu_mxdbr (int rx, int ry) {
+        display_emulation_not_implemented("mxdbr");
+	return 0;
 }
 
-static void emu_sdb (int rx, __u64 val) {
+static int emu_sdb (int rx, __u64 val) {
         current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d,
                                          val);
         set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_sdbr (int rx, int ry) {
+static int emu_sdbr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d,
                                          current->thread.fp_regs.fprs[ry].d);
         set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL);
+	return 0;
 }
 
-static void emu_seb (int rx, __u32 val) {
+static int emu_seb (int rx, __u32 val) {
         current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f,
                                          val);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_sebr (int rx, int ry) {
+static int emu_sebr (int rx, int ry) {
         current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f,
                                          current->thread.fp_regs.fprs[ry].f);
         set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+	return 0;
 }
 
-static void emu_sfpc (int rx, int ry) {
-        printk("sfpc emulation not implemented!\n");
+static int emu_sfpc (int rx, int ry) {
+	__u32 val=current->thread.regs->gprs[rx];
+	if(val==0)
+		current->thread.fp_regs.fpc=val;
+	else
+		display_emulation_not_implemented("sfpc");
+	return 0;
 }
 
-static void emu_sqdb (int rx, __u64 val) {
-        printk("sqdb emulation not implemented!\n");
+static int emu_sqdb (int rx, __u64 val) {
+        display_emulation_not_implemented("sqdb");
+	return 0;
 }
 
-static void emu_sqdbr (int rx, int ry) {
-        printk("sqdbr emulation not implemented!\n");
+static int emu_sqdbr (int rx, int ry) {
+        display_emulation_not_implemented("sqdbr");
+	return 0;
 }
 
-static void emu_sqeb (int rx, __u32 val) {
-        printk("sqeb emulation not implemented!\n");
+static int emu_sqeb (int rx, __u32 val) {
+        display_emulation_not_implemented("sqeb");
+	return 0;
 }
 
-static void emu_sqebr (int rx, int ry) {
-        printk("sqebr emulation not implemented!\n");
+static int emu_sqebr (int rx, int ry) {
+        display_emulation_not_implemented("sqebr");
+	return 0;
 }
 
-static void emu_sqxbr (int rx, int ry) {
-        printk("sqxbr emulation not implemented!\n");
+static int emu_sqxbr (int rx, int ry) {
+        display_emulation_not_implemented("sqxbr");
+	return 0;
 }
 
-static void emu_sxbr (int rx, int ry) {
-        printk("sxbr emulation not implemented!\n");
+static int emu_sxbr (int rx, int ry) {
+        display_emulation_not_implemented("sxbr");
+	return 0;
 }
 
-static void emu_tcdb (int rx, __u64 val) {
-        printk("tcdb emulation not implemented!\n");
+static int emu_tcdb (int rx, __u64 val) {
+        display_emulation_not_implemented("tcdb");
+	return 0;
 }
 
-static void emu_tceb (int rx, __u32 val) {
-        printk("tceb emulation not implemented!\n");
+static int emu_tceb (int rx, __u32 val) {
+        display_emulation_not_implemented("tceb");
+	return 0;
 }
 
-static void emu_tcxb (int rx, __u64 val) {
-        printk("tcxb emulation not implemented!\n");
+static int emu_tcxb (int rx, __u64 val) {
+        display_emulation_not_implemented("tcxb");
+	return 0;
 }
 
 
@@ -473,6 +616,7 @@
 }
 
 int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
+	int rc=0;
         static const __u8 format_table[] = {
                 2, 2, 2, 2, 9, 1, 2, 1, 2, 2, 2, 2, 9, 2, 4, 4,
                 1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3,
@@ -538,84 +682,82 @@
                 emu_store_regd((opcode[3]>>4)&15);
                 emu_store_regd(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15);
-                emu_load_regd((opcode[3]>>4)&15);
-                emu_load_regd(opcode[3]&15);
-                return 0;
+		emu_load_regd((opcode[3]>>4)&15);
+		emu_load_regd(opcode[3]&15);
+                return rc;
         case 2: /* RRE format, float operation */
                 emu_store_rege((opcode[3]>>4)&15);
                 emu_store_rege(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15);
-                emu_load_rege((opcode[3]>>4)&15);
-                emu_load_rege(opcode[3]&15);
-                return 0;
+		emu_load_rege((opcode[3]>>4)&15);
+		emu_load_rege(opcode[3]&15);
+                return rc;
         case 3: /* RRF format, double operation */
                 emu_store_regd((opcode[3]>>4)&15);
                 emu_store_regd(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
-                emu_load_regd((opcode[3]>>4)&15);
-                emu_load_regd(opcode[3]&15);
-                return 0;
+		emu_load_regd((opcode[3]>>4)&15);
+		emu_load_regd(opcode[3]&15);
+		return rc;
         case 4: /* RRF format, float operation */
                 emu_store_rege((opcode[3]>>4)&15);
                 emu_store_rege(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
-                emu_load_rege((opcode[3]>>4)&15);
-                emu_load_rege(opcode[3]&15);
-                return 0;
+		emu_load_rege((opcode[3]>>4)&15);
+		emu_load_rege(opcode[3]&15);
+                return rc;
         case 5: /* RRE format, cefbr instruction */
                 emu_store_rege((opcode[3]>>4)&15);
                 /* call the emulation function */
-                ((void (*)(int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15);
-                emu_load_rege((opcode[3]>>4)&15);
-                return 0;
+		emu_load_rege((opcode[3]>>4)&15);
+                return rc;
         case 6: /* RRE format, cdfbr & cxfbr instruction */
                 emu_store_regd((opcode[3]>>4)&15);
                 /* call the emulation function */
-                ((void (*)(int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15);
-                emu_load_regd((opcode[3]>>4)&15);
-                return 0;
-                /* FIXME !! */
-                return 0;
-        case 7: /* RRF format, cfebr instruction */
+		emu_load_regd((opcode[3]>>4)&15);
+                return rc;
+	case 7: /* RRF format, cfebr instruction */
                 emu_store_rege(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
-                return 0;
+                return rc;
         case 8: /* RRF format, cfdbr & cfxbr instruction */
                 emu_store_regd(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
-                return 0;
+                return rc;
 	case 9: /* RRE format, ldebr & mdebr instruction */
 		/* float store but double load */
                 emu_store_rege((opcode[3]>>4)&15);
                 emu_store_rege(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15);
-                emu_load_regd((opcode[3]>>4)&15);
-                return 0;
+		emu_load_regd((opcode[3]>>4)&15);
+                return rc;
         case 10: /* RRE format, ledbr instruction */
 		/* double store but float load */
                 emu_store_regd((opcode[3]>>4)&15);
                 emu_store_regd(opcode[3]&15);
                 /* call the emulation function */
-                ((void (*)(int, int))jump_table[opcode[1]])
+                rc=((int (*)(int, int))jump_table[opcode[1]])
                         (opcode[3]>>4,opcode[3]&15);
-                emu_load_rege((opcode[3]>>4)&15);
-                return 0;
+		emu_load_rege((opcode[3]>>4)&15);
+                return rc;
         default:
                 return 1;
         }
@@ -632,6 +774,8 @@
 }
     
 int math_emu_ed(__u8 *opcode, struct pt_regs * regs) {
+	int rc=0;
+
         static const __u8 format_table[] = {
                 0, 0, 0, 0, 5, 1, 2, 1, 2, 2, 2, 2, 5, 2, 4, 4,
                 2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 1, 3, 3,
@@ -669,13 +813,12 @@
                 emu_store_regd((opcode[1]>>4)&15);
                 opc = *((__u32 *) opcode);
                 dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
-                /* FIXME: how to react if copy_from_user fails ? */
-                copy_from_user(&temp, dxb, 8);
+                mathemu_copy_from_user(&temp, dxb, 8);
                 /* call the emulation function */
-                ((void (*)(int, __u64))jump_table[opcode[5]])
+                rc=((int (*)(int, __u64))jump_table[opcode[5]])
                         (opcode[1]>>4,temp);
-                emu_load_regd((opcode[1]>>4)&15);
-                return 0;
+		emu_load_regd((opcode[1]>>4)&15);
+                return rc;
         }
         case 2: /* RXE format, __u32 constant */ {
                 __u32 *dxb, temp;
@@ -684,13 +827,12 @@
                 emu_store_rege((opcode[1]>>4)&15);
                 opc = *((__u32 *) opcode);
                 dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
-                /* FIXME: how to react if get_user fails ? */
-                get_user(temp, dxb);
+                mathemu_get_user(temp, dxb);
                 /* call the emulation function */
-                ((void (*)(int, __u32))jump_table[opcode[5]])
+                rc=((int (*)(int, __u32))jump_table[opcode[5]])
                         (opcode[1]>>4,temp);
-                emu_load_rege((opcode[1]>>4)&15);
-                return 0;
+		emu_load_rege((opcode[1]>>4)&15);
+                return rc;
         }
         case 3: /* RXF format, __u64 constant */ {
                 __u32 *dxb, temp;
@@ -699,13 +841,12 @@
                 emu_store_regd((opcode[1]>>4)&15);
                 opc = *((__u32 *) opcode);
                 dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
-                /* FIXME: how to react if copy_from_user fails ? */
-                copy_from_user(&temp, dxb, 8);
+                 mathemu_copy_from_user(&temp, dxb, 8);
                 /* call the emulation function */
-                ((void (*)(int, __u32, int))jump_table[opcode[5]])
+                rc=((int (*)(int, __u32, int))jump_table[opcode[5]])
                         (opcode[1]>>4,temp,opcode[4]>>4);
-                emu_load_regd((opcode[1]>>4)&15);
-                return 0;
+		emu_load_regd((opcode[1]>>4)&15);
+                return rc;
         }
         case 4: /* RXF format, __u32 constant */ {
                 __u32 *dxb, temp;
@@ -714,29 +855,27 @@
                 emu_store_rege((opcode[1]>>4)&15);
                 opc = *((__u32 *) opcode);
                 dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
-                /* FIXME: how to react if get_user fails ? */
-                get_user(temp, dxb);
+                mathemu_get_user(temp, dxb);
                 /* call the emulation function */
-                ((void (*)(int, __u32, int))jump_table[opcode[5]])
+                rc=((int (*)(int, __u32, int))jump_table[opcode[5]])
                         (opcode[1]>>4,temp,opcode[4]>>4);
                 emu_load_rege((opcode[1]>>4)&15);
-                return 0;
+                return rc;
         }
 	case 5: /* RXE format, __u32 constant */
                 /* store_rege and load_regd */ 
-		{
+	{
                 __u32 *dxb, temp;
                 __u32 opc;
                 emu_store_rege((opcode[1]>>4)&15);
                 opc = *((__u32 *) opcode);
                 dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
-                /* FIXME: how to react if get_user fails ? */
-                get_user(temp, dxb);
+                mathemu_get_user(temp, dxb);
                 /* call the emulation function */
-                ((void (*)(int, __u32))jump_table[opcode[5]])
+                rc=((int (*)(int, __u32))jump_table[opcode[5]])
                         (opcode[1]>>4,temp);
                 emu_load_regd((opcode[1]>>4)&15);
-                return 0;
+                return rc;
         }
         default:
                 return 1;
@@ -746,7 +885,7 @@
 /*
  * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
  */
-void math_emu_ldr(__u8 *opcode) {
+int math_emu_ldr(__u8 *opcode) {
         __u16 opc = *((__u16 *) opcode);
 
         if ((opc & 0x0090) == 0) {         /* test if rx in {0,2,4,6} */
@@ -772,12 +911,13 @@
                 current->thread.fp_regs.fprs[(opc&0x00f0)>>4] =
                         current->thread.fp_regs.fprs[opc&0x000f];
         }
+	return 0;
 }
 
 /*
  * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
  */
-void math_emu_ler(__u8 *opcode) {
+int math_emu_ler(__u8 *opcode) {
         __u16 opc = *((__u16 *) opcode);
 
         if ((opc & 0x0090) == 0) {         /* test if rx in {0,2,4,6} */
@@ -803,61 +943,68 @@
                 current->thread.fp_regs.fprs[(opc&0x00f0)>>4] =
                         current->thread.fp_regs.fprs[opc&0x000f];
         }
+	return 0;
 }
 
 /*
  * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6}
  */
-void math_emu_ld(__u8 *opcode, struct pt_regs * regs) {
+int math_emu_ld(__u8 *opcode, struct pt_regs * regs) {
         __u32 opc = *((__u32 *) opcode);
         __u64 *dxb;
 
         dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
-        /* FIXME: how to react if copy_from_user fails ? */
-        copy_from_user(&current->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8);
+        mathemu_copy_from_user(&current->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8);
+	return 0;
 }
 
 /*
  * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6}
  */
-void math_emu_le(__u8 *opcode, struct pt_regs * regs) {
+int math_emu_le(__u8 *opcode, struct pt_regs * regs) {
         __u32 opc = *((__u32 *) opcode);
         __u32 *mem, *dxb;
 
         dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
-        /* FIXME: how to react if get_user fails ? */
         mem = (__u32 *) (&current->thread.fp_regs.fprs[(opc>>20)&15].f);
-        get_user(mem[0], dxb);
+        mathemu_get_user(mem[0], dxb);
+	return 0;
 }
 
 /*
  * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6}
  */
-void math_emu_std(__u8 *opcode, struct pt_regs * regs) {
+int math_emu_std(__u8 *opcode, struct pt_regs * regs) {
         __u32 opc = *((__u32 *) opcode);
         __u64 *dxb;
         dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
-        /* FIXME: how to react if copy_to_user fails ? */
-        copy_to_user(dxb, &current->thread.fp_regs.fprs[(opc>>20)&15].d, 8);
+        mathemu_copy_to_user(dxb, &current->thread.fp_regs.fprs[(opc>>20)&15].d, 8);
+	return 0;
 }
 
 /*
  * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6}
  */
-void math_emu_ste(__u8 *opcode, struct pt_regs * regs) {
+int math_emu_ste(__u8 *opcode, struct pt_regs * regs) {
         __u32 opc = *((__u32 *) opcode);
         __u32 *mem, *dxb;
         dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
-        /* FIXME: how to react if put_user fails ? */
+        /* FIXME: how to react if mathemu_put_user fails ? */
         mem = (__u32 *) (&current->thread.fp_regs.fprs[(opc>>20)&15].f);
-        put_user(mem[0], dxb);
+        mathemu_put_user(mem[0], dxb);
+	return 0;
 }
 
 /*
  * Emulate LFPC D(B)
  */
 int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) {
-        /* FIXME: how to do that ?!? */
+	__u32 *dxb,temp;
+	__u32 opc = *((__u32 *) opcode);
+	dxb= (__u32 *) calc_addr(regs,0,opc>>12,opc);
+	mathemu_get_user(temp, dxb);
+	if(temp!=0)
+		display_emulation_not_implemented("lfpc");
         return 0;
 }
 
@@ -865,7 +1012,10 @@
  * Emulate STFPC D(B)
  */
 int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) {
-        /* FIXME: how to do that ?!? */
+	__u32 *dxb;
+	__u32 opc = *((__u32 *) opcode);
+	dxb= (__u32 *) calc_addr(regs,0,opc>>12,opc);
+	mathemu_put_user(current->thread.fp_regs.fpc, dxb);
         return 0;
 }
 
@@ -874,6 +1024,7 @@
  */
 int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) {
         /* FIXME: how to do that ?!? */
+	display_emulation_not_implemented("srnm");
         return 0;
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/process.c linux/arch/s390/kernel/process.c
--- v2.4.1/linux/arch/s390/kernel/process.c	Tue Sep  5 13:50:01 2000
+++ linux/arch/s390/kernel/process.c	Tue Feb 13 14:13:43 2001
@@ -28,7 +28,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
@@ -67,7 +67,9 @@
                 if (softirq_active(smp_processor_id()) &
 		    softirq_mask(smp_processor_id())) {
                         do_softirq();
-                        continue;
+                        __sti();
+                        if (!current->need_resched)
+                                continue;
                 }
                 if (current->need_resched) {
                         schedule();
@@ -92,12 +94,13 @@
   0 returned you know you've got all the lines
  */
 
-int sprintf_regs(int line, char *buff, struct task_struct * task,
-		 struct thread_struct *thread, struct pt_regs * regs)
-{	
+static int sprintf_regs(int line, char *buff, struct task_struct *task, struct pt_regs *regs)
+{
 	int linelen=0;
 	int regno,chaincnt;
 	u32 backchain,prev_backchain,endchain;
+	u32 ksp = 0;
+	char *mode = "???";
 
 	enum
 	{
@@ -118,106 +121,125 @@
 		sp_kern_backchain1
 	};
 
-	if(task)
-		thread = &task->thread;
-	if(thread)
-		regs = thread->regs;
-	switch (line) {
-	case sp_linefeed:
+	if (task)
+		ksp = task->thread.ksp;
+	if (regs && !(regs->psw.mask & PSW_PROBLEM_STATE))
+		ksp = regs->gprs[15];
+
+	if (regs)
+		mode = (regs->psw.mask & PSW_PROBLEM_STATE)?
+		       "User" : "Kernel";
+
+	switch(line)
+	{
+	case sp_linefeed: 
 		linelen=sprintf(buff,"\n");
 		break;
 	case sp_psw:
 		if(regs)
-			linelen = sprintf(buff,"User PSW:    %08lx %08lx\n",
-					  (unsigned long) regs->psw.mask,
-					  (unsigned long) regs->psw.addr);
+			linelen=sprintf(buff, "%s PSW:    %08lx %08lx\n", mode,
+				(unsigned long) regs->psw.mask,
+				(unsigned long) regs->psw.addr);
 		else
-			linelen = sprintf(buff,"pt_regs=NULL some info unavailable\n");
+			linelen=sprintf(buff,"pt_regs=NULL some info unavailable\n");
 		break;
 	case sp_ksp:
-		if (task)
-			linelen += sprintf(&buff[linelen],
-					   "task: %08x ", (addr_t)task);
-		if (thread)
-			linelen += sprintf(&buff[linelen],
-					   "thread: %08x ksp: %08x ",
-					   (addr_t)thread,(addr_t)thread->ksp);
-		if (regs)
-			linelen += sprintf(&buff[linelen],
-					   "pt_regs: %08x\n", (addr_t)regs);
+		linelen=sprintf(&buff[linelen],
+				"task: %08x ksp: %08x pt_regs: %08x\n",
+				(addr_t)task, (addr_t)ksp, (addr_t)regs);
 		break;
 	case sp_gprs:
-		if (regs)
-			linelen = sprintf(buff,"User GPRS:\n");
+		if(regs)
+			linelen=sprintf(buff, "%s GPRS:\n", mode);
 		break;
 	case sp_gprs1 ... sp_gprs4:
-		if (regs) {
-			regno = (line-sp_gprs1)*4;
-			linelen = sprintf(buff,"%08x  %08x  %08x  %08x\n",
-					  regs->gprs[regno],
-					  regs->gprs[regno+1],
-					  regs->gprs[regno+2],
-					  regs->gprs[regno+3]);
+		if(regs)
+		{
+			regno=(line-sp_gprs1)*4;
+			linelen=sprintf(buff,"%08x  %08x  %08x  %08x\n",
+					regs->gprs[regno], 
+					regs->gprs[regno+1],
+					regs->gprs[regno+2],
+					regs->gprs[regno+3]);
 		}
 		break;
 	case sp_acrs:
-		if (regs)
-			linelen = sprintf(buff,"User ACRS:\n");
+		if(regs)
+			linelen=sprintf(buff, "%s ACRS:\n", mode);
 		break;	
         case sp_acrs1 ... sp_acrs4:
-		if (regs) {
-			regno = (line-sp_acrs1)*4;
-			linelen = sprintf(buff,"%08x  %08x  %08x  %08x\n",
-					  regs->acrs[regno],
-					  regs->acrs[regno+1],
-					  regs->acrs[regno+2],
-					  regs->acrs[regno+3]);
+		if(regs)
+		{
+			regno=(line-sp_acrs1)*4;
+			linelen=sprintf(buff,"%08x  %08x  %08x  %08x\n",
+					regs->acrs[regno],
+					regs->acrs[regno+1],
+					regs->acrs[regno+2],
+					regs->acrs[regno+3]);
 		}
 		break;
 	case sp_kern_backchain:
-		if (thread && thread->ksp && regs)
-			linelen = sprintf(buff,"Kernel BackChain  CallChain    BackChain  CallChain\n");
+		if (regs && (regs->psw.mask & PSW_PROBLEM_STATE))
+			break;	
+		if (ksp)
+			linelen=sprintf(buff, "Kernel BackChain  CallChain\n");
 		break;
 	default:
-		if(thread && thread->ksp && regs) {
-			backchain = (thread->ksp & PSW_ADDR_MASK);
-			endchain = ((backchain & (-8192)) + 8192);
-			prev_backchain = backchain - 1;
-			line -= sp_kern_backchain1;
-			for (chaincnt = 0; ; chaincnt++) {
-				if ((backchain == 0) ||
-				    (backchain >= endchain) ||
-				    (chaincnt >= 8) || 
-				    (prev_backchain >= backchain))
+		if (ksp)
+		{
+			
+			backchain=ksp&PSW_ADDR_MASK;
+			endchain=((backchain&(-8192))+8192);
+			prev_backchain=backchain-1;
+			line-=sp_kern_backchain1;
+			for(chaincnt=0;;chaincnt++)
+			{
+				if((backchain==0)||(backchain>=endchain)
+				   ||(chaincnt>=8)||(prev_backchain>=backchain))
 					break;
-				if ((chaincnt >> 1) == line) {
-					linelen += sprintf(&buff[linelen],"%s%08x   %08x     ",
-							 (chaincnt&1) ? "":"       ",
-							 backchain,*(u32 *)(backchain+56));
-				}
-				if ((chaincnt >> 1) > line)
+				if(chaincnt==line)
+				{
+					linelen+=sprintf(&buff[linelen],"       %08x   [<%08lx>]\n",
+							 backchain,
+							 *(u32 *)(backchain+56)&PSW_ADDR_MASK);
 					break;
-				prev_backchain = backchain;
-				backchain = (*((u32 *)backchain)) & PSW_ADDR_MASK;
+				}
+				prev_backchain=backchain;
+				backchain=(*((u32 *)backchain))&PSW_ADDR_MASK;
 			}
-			if (linelen)
-				linelen += sprintf(&buff[linelen],"\n");
 		}
 	}
-	return linelen;
+	return(linelen);
 }
 
 
-void show_regs(struct task_struct *task, struct thread_struct *thread,
-	       struct pt_regs *regs)
+void show_regs(struct pt_regs *regs)
 {
 	char buff[80];
 	int line;
+
+        printk("CPU:    %d\n",smp_processor_id());
+        printk("Process %s (pid: %d, stackpage=%08X)\n",
+                current->comm, current->pid, 4096+(addr_t)current);
 	
-	for (line = 0; sprintf_regs(line,buff,task,thread,regs); line++)
+	for (line = 0; sprintf_regs(line, buff, current, regs); line++)
 		printk(buff);
 }
 
+char *task_show_regs(struct task_struct *task, char *buffer)
+{
+	int line, len;
+
+	for (line = 0; ; line++)
+	{
+		len = sprintf_regs(line, buffer, task, task->thread.regs);
+		if (!len) break;
+		buffer += len;
+	}
+	return buffer;
+}
+
+
 int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 {
         int clone_arg = flags | CLONE_VM;
@@ -327,7 +349,7 @@
 
         lock_kernel();
         clone_flags = regs.gprs[3];
-        newsp = regs.gprs[2];
+        newsp = regs.orig_gpr2;
         if (!newsp)
                 newsp = regs.gprs[15];
         ret = do_fork(clone_flags, newsp, &regs, 0);
@@ -365,7 +387,19 @@
                 goto out;
         error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
 	if (error == 0)
-		current->flags &= ~PF_DTRACE;
+	{
+		current->ptrace &= ~PT_DTRACE;
+		current->thread.fp_regs.fpc=0;
+		if(MACHINE_HAS_IEEE)
+		{
+			__asm__ __volatile__
+			("sr  0,0\n\t"
+			 "sfpc 0,0\n\t"
+				:
+			        :
+                                :"0");
+		}
+	}
         putname(filename);
 out:
         return error;
@@ -412,21 +446,77 @@
 
 unsigned long get_wchan(struct task_struct *p)
 {
-	unsigned long r14, r15;
+	unsigned long r14, r15, bc;
 	unsigned long stack_page;
 	int count = 0;
 	if (!p || p == current || p->state == TASK_RUNNING)
 		return 0;
 	stack_page = (unsigned long) p;
 	r15 = p->thread.ksp;
+        if (!stack_page || r15 < stack_page || r15 >= 8188+stack_page)
+                return 0;
+        bc = (*(unsigned long *) r15) & 0x7fffffff;
 	do {
-		r14 = *(unsigned long *) (r15+56);
+                if (bc < stack_page || bc >= 8188+stack_page)
+                        return 0;
+		r14 = (*(unsigned long *) (bc+56)) & 0x7fffffff;
 		if (r14 < first_sched || r14 >= last_sched)
 			return r14;
-		r15 = *(unsigned long *) (r15+60);
+		bc = (*(unsigned long *) bc) & 0x7fffffff;
 	} while (count++ < 16);
 	return 0;
 }
 #undef last_sched
 #undef first_sched
 
+/*
+ * This should be safe even if called from tq_scheduler
+ * A typical mask would be sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM) or 0.
+ *
+ */
+void s390_daemonize(char *name,unsigned long mask,int use_init_fs)
+{
+	struct fs_struct *fs;
+	extern struct task_struct *child_reaper;
+	struct task_struct *this_process=current;
+	
+	/*
+	 * If we were started as result of loading a module, close all of the
+	 * user space pages.  We don't need them, and if we didn't close them
+	 * they would be locked into memory.
+	 */
+	exit_mm(current);
+
+	this_process->session = 1;
+	this_process->pgrp = 1;
+	if(name)
+	{
+		strncpy(current->comm,name,15);
+		current->comm[15]=0;
+	}
+	else
+		current->comm[0]=0;
+	/* set signal mask to what we want to respond */
+        siginitsetinv(&current->blocked,mask);
+	/* exit_signal isn't set up */
+        /* if we inherit from cpu idle  */
+	this_process->exit_signal=SIGCHLD;
+	/* if priority=0 schedule can go into a tight loop */
+	this_process->policy= SCHED_OTHER;
+	/* nice goes priority=20-nice; */
+	this_process->nice=10;
+	if(use_init_fs)
+	{
+		exit_fs(this_process);	/* current->fs->count--; */
+		fs = init_task.fs;
+		current->fs = fs;
+		atomic_inc(&fs->count);
+		exit_files(current);
+	}
+	write_lock_irq(&tasklist_lock);
+	/* We want init as our parent */
+	REMOVE_LINKS(this_process);
+	this_process->p_opptr=this_process->p_pptr=child_reaper;
+	SET_LINKS(this_process);
+	write_unlock_irq(&tasklist_lock);
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/ptrace.c linux/arch/s390/kernel/ptrace.c
--- v2.4.1/linux/arch/s390/kernel/ptrace.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/ptrace.c	Tue Feb 13 14:13:43 2001
@@ -66,10 +66,16 @@
 		regs->psw.mask |=PSW_PER_MASK;
 	else
 		regs->psw.mask &= ~PSW_PER_MASK;
-	if(per_info->control_regs.bits.storage_alt_space_ctl)
-		task->thread.user_seg|=USER_STD_MASK;
+	if (per_info->control_regs.bits.em_storage_alteration)
+	{
+		per_info->control_regs.bits.storage_alt_space_ctl=1;
+		//((pgd_t *)__pa(task->mm->pgd))->pgd |= USER_STD_MASK;
+	}
 	else
-		task->thread.user_seg&=~USER_STD_MASK;
+	{
+		per_info->control_regs.bits.storage_alt_space_ctl=0;
+		//((pgd_t *)__pa(task->mm->pgd))->pgd &= ~USER_STD_MASK;
+	}
 }
 
 void set_single_step(struct task_struct *task)
@@ -209,10 +215,10 @@
 	if (request == PTRACE_TRACEME) 
 	{
 		/* are we already being traced? */
-		if (current->flags & PF_PTRACED)
+		if (current->ptrace & PT_PTRACED)
 			goto out;
 		/* set the ptrace bit in the process flags. */
-		current->flags |= PF_PTRACED;
+		current->ptrace |= PT_PTRACED;
 		ret = 0;
 		goto out;
 	}
@@ -237,9 +243,9 @@
 		     (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE))
 			goto out;
 		/* the same process cannot be attached many times */
-		if (child->flags & PF_PTRACED)
+		if (child->ptrace & PT_PTRACED)
 			goto out;
-		child->flags |= PF_PTRACED;
+		child->ptrace |= PT_PTRACED;
 
 		write_lock_irqsave(&tasklist_lock, flags);
 		if (child->p_pptr != current) 
@@ -256,16 +262,20 @@
 	}
 	ret = -ESRCH;
 	// printk("child=%lX child->flags=%lX",child,child->flags);
-	if (!(child->flags & PF_PTRACED))
-		goto out;
-	if (child->state != TASK_STOPPED) 
+	/* I added child!=current line so we can get the */
+	/* ieee_instruction_pointer from the user structure DJB */
+	if(child!=current)
 	{
-		if (request != PTRACE_KILL)
+		if (!(child->ptrace & PT_PTRACED))
+			goto out;
+		if (child->state != TASK_STOPPED) 
+		{
+			if (request != PTRACE_KILL)
+				goto out;
+		}
+		if (child->p_pptr != current)
 			goto out;
 	}
-	if (child->p_pptr != current)
-		goto out;
-
 	switch (request) 
 	{
 		/* If I and D space are separate, these will need to be fixed. */
@@ -303,9 +313,9 @@
 		if ((unsigned long) data >= _NSIG)
 			break;
 		if (request == PTRACE_SYSCALL)
-			child->flags |= PF_TRACESYS;
+			child->ptrace |= PT_TRACESYS;
 		else
-			child->flags &= ~PF_TRACESYS;
+			child->ptrace &= ~PT_TRACESYS;
 		child->exit_code = data;
 		/* make sure the single step bit is not set. */
 		clear_single_step(child);
@@ -332,7 +342,7 @@
 		ret = -EIO;
 		if ((unsigned long) data >= _NSIG)
 			break;
-		child->flags &= ~PF_TRACESYS;
+		child->ptrace &= ~PT_TRACESYS;
 		child->exit_code = data;
 		set_single_step(child);
 		/* give it a chance to run. */
@@ -344,7 +354,7 @@
 		ret = -EIO;
 		if ((unsigned long) data >= _NSIG)
 			break;
-		child->flags &= ~(PF_PTRACED|PF_TRACESYS);
+		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
 		child->exit_code = data;
 		write_lock_irqsave(&tasklist_lock, flags);
 		REMOVE_LINKS(child);
@@ -374,11 +384,11 @@
 asmlinkage void syscall_trace(void)
 {
 	lock_kernel();
-	if ((current->flags & (PF_PTRACED|PF_TRACESYS))
-	    != (PF_PTRACED|PF_TRACESYS))
+	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+	    != (PT_PTRACED|PT_TRACESYS))
 		goto out;
 	current->exit_code = SIGTRAP;
-	current->state = TASK_STOPPED;
+	set_current_state(TASK_STOPPED);
 	notify_parent(current, SIGCHLD);
 	schedule();
 	/*
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/reipl.S linux/arch/s390/kernel/reipl.S
--- v2.4.1/linux/arch/s390/kernel/reipl.S	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/reipl.S	Tue Feb 13 14:13:43 2001
@@ -1,4 +1,13 @@
+/*
+ *  arch/s390/kernel/reipl.S
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
+ */
+
 #include <asm/lowcore.h>
+
 		.globl	do_reipl
 do_reipl:	basr	%r13,0
 .Lpg0:		lpsw	.Lnewpsw-.Lpg0(%r13)
@@ -7,7 +16,7 @@
                 ni      .Lctlsave-.Lpg0(%r13),0xef
                 lctl    %c0,%c0,.Lctlsave-.Lpg0(%r13)
                 lr      %r1,%r2
-        	mvc     __LC_PGM_NEW_PSW(8,0),.Lpcnew-.Lpg0(%r13)
+        	mvc     __LC_PGM_NEW_PSW(8),.Lpcnew-.Lpg0(%r13)
                 stsch   .Lschib-.Lpg0(%r13)                                    
 	        oi      .Lschib+5-.Lpg0(%r13),0x84 
 .Lecs:  	xi      .Lschib+27-.Lpg0(%r13),0x01 
@@ -15,9 +24,9 @@
 		ssch	.Liplorb-.Lpg0(%r13)           
 		jz	.L001   
 		bas	%r14,.Ldisab-.Lpg0(%r13)
-.L001:		mvc	__LC_IO_NEW_PSW(8,0),.Lionew-.Lpg0(%r13)	
+.L001:		mvc	__LC_IO_NEW_PSW(8),.Lionew-.Lpg0(%r13)	
 .Ltpi:		lpsw	.Lwaitpsw-.Lpg0(%r13)          
-.Lcont:		c	%r1,__LC_SUBCHANNEL_ID(%r0)
+.Lcont:		c	%r1,__LC_SUBCHANNEL_ID
 		jnz	.Ltpi
 		clc	__LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
 		jnz	.Ltpi
@@ -29,7 +38,7 @@
                 jz      .L003
                 bas     %r14,.Ldisab-.Lpg0(%r13)	
 .L003:		spx	.Lnull-.Lpg0(%r13)
-		st 	%r1,__LC_SUBCHANNEL_ID(%r0)	
+		st 	%r1,__LC_SUBCHANNEL_ID
                 lpsw 	0
 		sigp    0,0,0(6)               
 .Ldisab:	st      %r14,.Ldispsw+4-.Lpg0(%r13)
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/s390_ext.c linux/arch/s390/kernel/s390_ext.c
--- v2.4.1/linux/arch/s390/kernel/s390_ext.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390/kernel/s390_ext.c	Tue Feb 13 14:13:43 2001
@@ -0,0 +1,77 @@
+/*
+ *  arch/s390/kernel/s390_ext.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <asm/lowcore.h>
+#include <asm/s390_ext.h>
+
+/*
+ * Simple hash strategy: index = code & 0xff;
+ * ext_int_hash[index] is the start of the list for all external interrupts
+ * that hash to this index. With the current set of external interrupts 
+ * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console and 0x4000
+ * iucv) this is always the first element. 
+ */
+ext_int_info_t *ext_int_hash[256] = { 0, };
+ext_int_info_t ext_int_info_timer;
+ext_int_info_t ext_int_info_hwc;
+
+int register_external_interrupt(__u16 code, ext_int_handler_t handler) {
+        ext_int_info_t *p;
+        int index;
+
+        index = code & 0xff;
+        p = ext_int_hash[index];
+        while (p != NULL) {
+                if (p->code == code)
+                        return -EBUSY;
+                p = p->next;
+        }
+        if (code == 0x1004) /* time_init is done before kmalloc works :-/ */
+                p = &ext_int_info_timer;
+        else if (code == 0x2401) /* hwc_init is done too early too */
+                p = &ext_int_info_hwc;
+        else
+                p = (ext_int_info_t *)
+                          kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+        if (p == NULL)
+                return -ENOMEM;
+        p->code = code;
+        p->handler = handler;
+        p->next = ext_int_hash[index];
+        ext_int_hash[index] = p;
+        return 0;
+}
+
+int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) {
+        ext_int_info_t *p, *q;
+        int index;
+
+        index = code & 0xff;
+        q = NULL;
+        p = ext_int_hash[index];
+        while (p != NULL) {
+                if (p->code == code && p->handler == handler)
+                        break;
+                q = p;
+                p = p->next;
+        }
+        if (p == NULL)
+                return -ENOENT;
+        if (q != NULL)
+                q->next = p->next;
+        else
+                ext_int_hash[index] = p->next;
+        if (code != 0x1004 && code != 0x2401)
+                kfree(p);
+        return 0;
+}
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/s390_ksyms.c linux/arch/s390/kernel/s390_ksyms.c
--- v2.4.1/linux/arch/s390/kernel/s390_ksyms.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/s390_ksyms.c	Tue Feb 13 14:13:43 2001
@@ -5,14 +5,27 @@
  */
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/string.h>
+#include <asm/ccwcache.h>
+#include <asm/debug.h>
 #include <asm/irq.h>
-#include <asm/string.h>
+#include <asm/s390_ext.h>
+#include <asm/s390dyn.h>
+#include <asm/ebcdic.h>
 #include <asm/checksum.h>
+#include <asm/delay.h>
+#if CONFIG_CHANDEV
+#include <asm/chandev.h>
+#endif
+#if CONFIG_IP_MULTICAST
+#include <net/arp.h>
+#endif
 
 /*
  * I/O subsystem
  */
 EXPORT_SYMBOL(halt_IO);
+EXPORT_SYMBOL(clear_IO);
 EXPORT_SYMBOL(do_IO);
 EXPORT_SYMBOL(resume_IO);
 EXPORT_SYMBOL(ioinfo);
@@ -22,6 +35,35 @@
 EXPORT_SYMBOL(get_devno_by_irq);
 EXPORT_SYMBOL(get_irq_first);
 EXPORT_SYMBOL(get_irq_next);
+EXPORT_SYMBOL(read_conf_data);
+EXPORT_SYMBOL(read_dev_chars);
+EXPORT_SYMBOL(s390_request_irq_special);
+EXPORT_SYMBOL(s390_device_register);
+EXPORT_SYMBOL(s390_device_unregister);
+
+EXPORT_SYMBOL(ccw_alloc_request);
+EXPORT_SYMBOL(ccw_free_request);
+
+EXPORT_SYMBOL(register_external_interrupt);
+EXPORT_SYMBOL(unregister_external_interrupt);
+
+/* 
+ * debug feature
+ */
+EXPORT_SYMBOL(debug_register);
+EXPORT_SYMBOL(debug_unregister);
+EXPORT_SYMBOL(debug_set_level);
+EXPORT_SYMBOL(debug_register_view);
+EXPORT_SYMBOL(debug_unregister_view);
+EXPORT_SYMBOL(debug_event);
+EXPORT_SYMBOL(debug_int_event);
+EXPORT_SYMBOL(debug_text_event);
+EXPORT_SYMBOL(debug_exception);
+EXPORT_SYMBOL(debug_int_exception);
+EXPORT_SYMBOL(debug_text_exception);
+EXPORT_SYMBOL(debug_hex_ascii_view);
+EXPORT_SYMBOL(debug_raw_view);
+EXPORT_SYMBOL(debug_dflt_header_fn);
 
 /*
  * memory management
@@ -29,6 +71,16 @@
 EXPORT_SYMBOL(_oi_bitmap);
 EXPORT_SYMBOL(_ni_bitmap);
 EXPORT_SYMBOL(_zb_findmap);
+EXPORT_SYMBOL(__copy_from_user_fixup);
+EXPORT_SYMBOL(__copy_to_user_fixup);
+
+/*
+ * semaphore ops
+ */
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
 
 /*
  * string functions
@@ -36,6 +88,7 @@
 EXPORT_SYMBOL_NOVERS(memcmp);
 EXPORT_SYMBOL_NOVERS(memset);
 EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(strlen);
 EXPORT_SYMBOL_NOVERS(strchr);
 EXPORT_SYMBOL_NOVERS(strcmp);
 EXPORT_SYMBOL_NOVERS(strncat);
@@ -46,19 +99,42 @@
 EXPORT_SYMBOL_NOVERS(strtok);
 EXPORT_SYMBOL_NOVERS(strpbrk);
 
+EXPORT_SYMBOL_NOVERS(_ascebc_500);
+EXPORT_SYMBOL_NOVERS(_ebcasc_500);
+EXPORT_SYMBOL_NOVERS(_ascebc);
+EXPORT_SYMBOL_NOVERS(_ebcasc);
+EXPORT_SYMBOL_NOVERS(_ebc_tolower);
+EXPORT_SYMBOL_NOVERS(_ebc_toupper);
+
 /*
  * misc.
  */
+EXPORT_SYMBOL(module_list);
+EXPORT_SYMBOL(__udelay);
 #ifdef CONFIG_SMP
 #include <asm/smplock.h>
 EXPORT_SYMBOL(__global_cli);
 EXPORT_SYMBOL(__global_sti);
 EXPORT_SYMBOL(__global_save_flags);
 EXPORT_SYMBOL(__global_restore_flags);
+EXPORT_SYMBOL(lowcore_ptr);
 EXPORT_SYMBOL(global_bh_lock);
 EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(smp_ctl_set_bit);
+EXPORT_SYMBOL(smp_ctl_clear_bit);
 #endif
 EXPORT_SYMBOL(kernel_thread);
 EXPORT_SYMBOL(csum_fold);
-
+#if CONFIG_CHANDEV
+EXPORT_SYMBOL(chandev_register_and_probe);
+EXPORT_SYMBOL(chandev_request_irq);
+EXPORT_SYMBOL(chandev_unregister);
+EXPORT_SYMBOL(chandev_initdevice);
+EXPORT_SYMBOL(chandev_initnetdevice);
+#endif
+#if CONFIG_IP_MULTICAST
+/* Required for lcs gigabit ethernet multicast support */
+EXPORT_SYMBOL(arp_mc_map);
+#endif
+EXPORT_SYMBOL(s390_daemonize);
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/s390dyn.c linux/arch/s390/kernel/s390dyn.c
--- v2.4.1/linux/arch/s390/kernel/s390dyn.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/s390dyn.c	Wed Dec 31 16:00:00 1969
@@ -1,36 +0,0 @@
-/*
- *  arch/s390/kernel/s390dyn.c
- *   S/390 dynamic device attachment
- *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/s390io.h>
-#include <asm/s390dyn.h>
-
-int s390_device_register( devreg_t *drinfo )
-{
-	return -EOPNOTSUPP;
-}
-
-
-int s390_device_deregister  ( devreg_t *dreg )
-{
-	return -EOPNOTSUPP;
-}
-
-int s390_request_irq_special( int                      irq,
-                              io_handler_func_t        io_handler,
-                              not_oper_handler_func_t  not_oper_handler,
-                              unsigned long            irqflags,
-                              const char              *devname,
-                              void                    *dev_id)
-{
-	return -EOPNOTSUPP;
-}
-
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/s390fpu.c linux/arch/s390/kernel/s390fpu.c
--- v2.4.1/linux/arch/s390/kernel/s390fpu.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/s390fpu.c	Tue Feb 13 14:13:43 2001
@@ -81,6 +81,11 @@
 {
 	int has_ieee=MACHINE_HAS_IEEE;
 
+	/* If we don't mask with the FPC_VALID_MASK here
+	 * we've got a very quick shutdown -h now command
+         * via a kernel specification exception.
+	 */
+	fpregs->fpc&=FPC_VALID_MASK;
 	asm volatile ("LD   0,8(%0)\n\t"
 		      "LD   2,24(%0)\n\t"
 		      "LD   4,40(%0)\n\t"
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/s390io.c linux/arch/s390/kernel/s390io.c
--- v2.4.1/linux/arch/s390/kernel/s390io.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/s390/kernel/s390io.c	Wed Dec 31 16:00:00 1969
@@ -1,4605 +0,0 @@
-/*
- *  arch/s390/kernel/s390io.c
- *   S/390 common I/O routines
- *
- *  S390 version
- *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
- *                             IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
-#include <linux/config.h>
-#include <linux/errno.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/malloc.h>
-#include <linux/string.h>
-#include <linux/smp.h>
-#include <linux/tasks.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <linux/bootmem.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/processor.h>
-#include <asm/lowcore.h>
-
-#include <asm/s390io.h>
-#include <asm/s390dyn.h>
-#include <asm/s390mach.h>
-
-#ifndef TRUE
-#define TRUE  1
-#define FALSE 0
-#endif
-
-#undef CONFIG_DEBUG_IO
-
-#define REIPL_DEVID_MAGIC 0x87654321
-
-struct irqaction  init_IRQ_action;
-unsigned int      highest_subchannel;
-ioinfo_t         *ioinfo_head = NULL;
-ioinfo_t         *ioinfo_tail = NULL;
-ioinfo_t         *ioinfo[__MAX_SUBCHANNELS] = {
-	[0 ... (__MAX_SUBCHANNELS-1)] = INVALID_STORAGE_AREA
-};
-
-static spinlock_t        sync_isc;                 // synchronous irq processing lock
-static psw_t             io_sync_wait;             // wait PSW for sync IO, prot. by sync_isc
-static psw_t             io_new_psw;               // save I/O new PSW, prot. by sync_isc
-static int               cons_dev          = -1;   // identify console device
-static int               init_IRQ_complete = 0;
-static schib_t           init_schib;
-static __u64             irq_IPL_TOD;
-
-/*
- * Dummy controller type for unused interrupts
- */
-int  do_none(unsigned int irq, int cpu, struct pt_regs * regs) { return 0;}
-int  enable_none(unsigned int irq) { return(-ENODEV); }
-int  disable_none(unsigned int irq) { return(-ENODEV); }
-
-struct hw_interrupt_type no_irq_type = {
-	"none",
-	do_none,
-	enable_none,
-	disable_none
-};
-
-static void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs);
-static int  s390_setup_irq(unsigned int irq, struct irqaction * new);
-static void s390_process_subchannels( void);
-static void s390_device_recognition( void);
-static int  s390_validate_subchannel( int irq);
-static int  s390_SenseID( int irq, senseid_t *sid);
-static int  s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid);
-static int  s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid);
-static int  s390_process_IRQ( unsigned int irq );
-static int  s390_DevicePathVerification( int irq );
-
-extern int  do_none(unsigned int irq, int cpu, struct pt_regs * regs);
-extern int  enable_none(unsigned int irq);
-extern int  disable_none(unsigned int irq);
-extern void tod_wait(unsigned long usecs);
-
-asmlinkage void do_IRQ( struct pt_regs regs,
-                        unsigned int   irq,
-                        __u32          s390_intparm );
-
-void s390_displayhex(char *str,void *ptr,s32 cnt);
-
-void s390_displayhex(char *str,void *ptr,s32 cnt)
-{
-	s32	cnt1,cnt2,maxcnt2;
-	u32	*currptr=(__u32 *)ptr;
-
-	printk("\n%s\n",str);
-
-	for(cnt1=0;cnt1<cnt;cnt1+=16)
-	{
-		printk("%08lX ",(unsigned long)currptr);
-		maxcnt2=cnt-cnt1;
-		if(maxcnt2>16)
-			maxcnt2=16;
-		for(cnt2=0;cnt2<maxcnt2;cnt2+=4)
-			printk("%08X ",*currptr++);
-		printk("\n");
-	}
-}
-
-int s390_request_irq( unsigned int   irq,
-                      void           (*handler)(int, void *, struct pt_regs *),
-                      unsigned long  irqflags,
-                      const char    *devname,
-                      void          *dev_id)
-{
-	int               retval;
-	struct irqaction *action;
-
-	if (irq >= __MAX_SUBCHANNELS)
-		return -EINVAL;
-
-	if ( !handler || !dev_id )
-		return -EINVAL;
-
-	/*
-	 * during init_IRQ() processing we don't have memory
-	 *  management yet, thus need to use a statically
-	 *  allocated irqaction control block
-	 */
-	if ( init_IRQ_complete )
-	{
-		action = (struct irqaction *)
-		kmalloc(sizeof(struct irqaction), GFP_KERNEL);
-	}
-	else
-	{
-		action = &init_IRQ_action;
-
-	} /* endif */
-
-	if (!action)
-	{
-		return -ENOMEM;
-
-	} /* endif */
-
-	action->handler = handler;
-	action->flags   = irqflags;
-	action->mask    = 0;
-	action->name    = devname;
-	action->next    = NULL;
-	action->dev_id  = dev_id;
-
-	retval = s390_setup_irq( irq, action);
-
-	if ( !retval )
-	{
-		retval = s390_DevicePathVerification( irq );
-	}
-	else if ( retval && init_IRQ_complete )
-	{
-		kfree(action);
-
-	} /* endif */
-
-	return retval;
-}
-
-void s390_free_irq(unsigned int irq, void *dev_id)
-{
-	unsigned int flags;
-	int          ret;
-
-	unsigned int count = 0;
-
-	if ( irq >= __MAX_SUBCHANNELS || ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return;
-
-	} /* endif */
-
-	s390irq_spin_lock_irqsave( irq, flags);
-
-#ifdef  CONFIG_KERNEL_DEBUG
-	if ( irq != cons_dev )
-	{
-		printk("Trying to free IRQ%d\n",irq);
-
-	} /* endif */
-#endif
-
-	/*
-	 * disable the device and reset all IRQ info if
-	 *  the IRQ is actually owned by the handler ...
-	 */
-	if ( ioinfo[irq]->irq_desc.action )
-	{
-		if (    (dev_id == ioinfo[irq]->irq_desc.action->dev_id  )
-		     || (dev_id == (devstat_t *)REIPL_DEVID_MAGIC) )
-		{
-			/* start deregister */
-			ioinfo[irq]->ui.flags.unready = 1;
-
-			do
-			{
-				ret = ioinfo[irq]->irq_desc.handler->disable(irq);
-
-				count++;
-
-				if ( ret == -EBUSY )
-				{
-					int iret;
-
-					/*
-					 * kill it !
-					 * ... we first try sync and eventually
-					 *  try terminating the current I/O by
-					 *  an async request, twice halt, then
-					 *  clear.
-					 */
-					if ( count < 3 )
-					{              	
-						iret = halt_IO( irq,
-						                0xC8C1D3E3,
-						                DOIO_WAIT_FOR_INTERRUPT );
-   	
-						if ( iret == -EBUSY )
-						{
-							halt_IO( irq, 0xC8C1D3E3, 0);
-							s390irq_spin_unlock_irqrestore( irq, flags);
-							tod_wait( 200000 ); /* 200 ms */
-							s390irq_spin_lock_irqsave( irq, flags);
-
-						} /* endif */
-					}
-					else
-					{
-						iret = clear_IO( irq,
-						                 0x40C3D3D9,
-						                 DOIO_WAIT_FOR_INTERRUPT );
-   	
-						if ( iret == -EBUSY )
-						{
-							clear_IO( irq, 0xC8C1D3E3, 0);
-							s390irq_spin_unlock_irqrestore( irq, flags);
-							tod_wait( 1000000 ); /* 1000 ms */
-							s390irq_spin_lock_irqsave( irq, flags);
-
-						} /* endif */
-
-					} /* endif */
-
-					if ( count == 3 )
-               {
-						/* give it a very last try ... */
-						ioinfo[irq]->irq_desc.handler->disable(irq);
-
-						if ( ioinfo[irq]->ui.flags.busy )
-					   {
-							printk( KERN_CRIT"free_irq(%04X) "
-							       "- device %04X busy, retry "
-							       "count exceeded\n",
-						   	    irq,
-						      	 ioinfo[irq]->devstat.devno);
-
-                  } /* endif */
-						
-						break; /* sigh, let's give up ... */
-
-					} /* endif */
-
-				} /* endif */
-		
-			} while ( ret == -EBUSY );
-
-			if ( init_IRQ_complete )
-				kfree( ioinfo[irq]->irq_desc.action );
-
-			ioinfo[irq]->irq_desc.action  = NULL;
-			ioinfo[irq]->ui.flags.ready   = 0;
-
-			ioinfo[irq]->irq_desc.handler->enable  = &enable_none;
-			ioinfo[irq]->irq_desc.handler->disable = &disable_none;
-
-			ioinfo[irq]->ui.flags.unready = 0; /* deregister ended */
-
-			s390irq_spin_unlock_irqrestore( irq, flags);
-		}
-		else
-		{
-			s390irq_spin_unlock_irqrestore( irq, flags);
-
-			printk("free_irq() : error, dev_id does not match !");
-
-		} /* endif */
-
-	}
-	else
-	{
-		s390irq_spin_unlock_irqrestore( irq, flags);
-
-		printk("free_irq() : error, no action block ... !");
-
-	} /* endif */
-
-}
-
-/*
- * Generic enable/disable code
- */
-int disable_irq(unsigned int irq)
-{
-	unsigned long flags;
-	int           ret;
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-		return( -ENODEV);
-
-	s390irq_spin_lock_irqsave(irq, flags);
-
-	/*
-	 * At this point we may actually have a pending interrupt being active
-	 * on another CPU. So don't touch the IRQ_INPROGRESS bit..
-	 */
-	ioinfo[irq]->irq_desc.status |= IRQ_DISABLED;
-	ret = ioinfo[irq]->irq_desc.handler->disable(irq);
-	s390irq_spin_unlock_irqrestore(irq, flags);
-
-	synchronize_irq();
-
-	return( ret);
-}
-
-int enable_irq(unsigned int irq)
-{
-	unsigned long flags;
-	int           ret;
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-		return( -ENODEV);
-
-	s390irq_spin_lock_irqsave(irq, flags);
-
-	ioinfo[irq]->irq_desc.status = 0;
-	ret = ioinfo[irq]->irq_desc.handler->enable(irq);
-
-	s390irq_spin_unlock_irqrestore(irq, flags);
-
-	return(ret);
-}
-
-/*
- * Enable IRQ by modifying the subchannel
- */
-static int enable_subchannel( unsigned int irq)
-{
-	int   ret;
-	int   ccode;
-	int   retry = 5;
-
-	if ( irq > highest_subchannel || irq < 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-		return( -ENODEV);
-
-	/*
-	 * If a previous disable request is pending we reset it. However, this
-	 *  status implies that the device may (still) be not-operational.
-	 */
-	if (  ioinfo[irq]->ui.flags.d_disable )
-	{
-		ioinfo[irq]->ui.flags.d_disable = 0;
-		ret                             = 0;
-	}
-	else
-	{
-
-		ccode = stsch(irq, &(ioinfo[irq]->schib) );
-
-		if ( ccode )
-		{
-			ret = -ENODEV;
-		}
-		else
-		{
-			ioinfo[irq]->schib.pmcw.ena = 1;
-
-			do
-			{
-				ccode = msch( irq, &(ioinfo[irq]->schib) );
-
-				switch (ccode) {
-				case 0:
-					ret = 0;
-					break;
-
-				case 1:
-					/*
-					 * very bad, requires interrupt alike
-					 *  processing, where "rbh" is a dummy
-					 *  parameter for interface compatibility
-					 *  only. Bottom-half handling cannot be
-					 *  required as this must be an
-					 *  unsolicited interrupt (!busy).
-					 */
-
-					ioinfo[irq]->ui.flags.s_pend = 1;
-
-					s390_process_IRQ( irq );
-
-					ioinfo[irq]->ui.flags.s_pend = 0;
-
-					ret = -EIO;    /* might be overwritten */
-					               /* ... on re-driving    */
-					               /* ... the msch() */
-					retry--;
-					break;
-
-				case 3:
-					ioinfo[irq]->ui.flags.oper = 0;
-					ret = -ENODEV;
-					break;
-
-				default:
-					printk( KERN_CRIT"enable_subchannel(%04X) "
-					        " : ccode 2 on msch() for device "
-					        "%04X received !\n",
-					        irq,
-					        ioinfo[irq]->devstat.devno);
-					ret = -ENODEV; // never reached
-				}
-
-			} while ( (ccode == 1) && retry );
-
-		} /* endif */
-
-	}  /* endif */
-
-	return( ret );
-}
-
-
-/*
- * Disable IRQ by modifying the subchannel
- */
-static int disable_subchannel( unsigned int irq)
-{
-	int  cc;          /* condition code */
-	int  ret;         /* function return value */
-	int  retry = 5;
-
-	if ( irq > highest_subchannel )
-	{
-		ret = -ENODEV;
-	}
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-	else if ( ioinfo[irq]->ui.flags.busy )
-	{
-		/*
-		 * the disable function must not be called while there are
-		 *  requests pending for completion !
-		 */
-		ret = -EBUSY;
-	}
-	else
-	{
-		/*
-		 * If device isn't operational we have to perform delayed
-		 *  disabling when the next interrupt occurs - unless the
-		 *  irq is re-requested prior to the interrupt to occur.
-		 */
-		cc = stsch(irq, &(ioinfo[irq]->schib) );
-
-		if ( cc == 3 )
-		{
-			ioinfo[irq]->ui.flags.oper      = 0;
-			ioinfo[irq]->ui.flags.d_disable = 1;
-
-			ret = 0;
-		}
-		else // cc == 0
-		{
-			ioinfo[irq]->schib.pmcw.ena = 0;
-
-			do
-			{
-				cc = msch( irq, &(ioinfo[irq]->schib) );
-
-				switch (cc) {
-				case 0 :
-					ret = 0;   /* done */
-					break;
-
-				case 1 :
-					/*
-					 * very bad, requires interrupt alike
-  					 *  processing, where "rbh" is a dummy
-					 *  parm for interface compatibility
-					 *  only. Bottom-half handling cannot
-					 *  be required as this must be an
-					 *  unsolicited interrupt (!busy).
-					 */
-					ioinfo[irq]->ui.flags.s_pend = 1;
-					s390_process_IRQ( irq );
-					ioinfo[irq]->ui.flags.s_pend = 0;
-
-					ret = -EBUSY;  /* might be overwritten  */
-					               /* ... on re-driving the */
-					               /* ... msch() call       */
-					retry--;
-					break;
-
-				case 2 :
-					/*
-					 * *** must not occur !              ***
-					 * ***                               ***
-					 * *** indicates our internal        ***
-					 * *** interrupt accounting is out   ***
-					 * ***  of sync ===> panic()         ***
-					 */
-					printk( KERN_CRIT"disable_subchannel(%04X) "
-					        "- unexpected busy condition for "
-							  "device %04X received !\n",
-					        irq,
-					        ioinfo[irq]->devstat.devno);
-
-					ret = -ENODEV; // never reached
-					break;
-
-				case 3 :
-					/*
-					 * should hardly occur ?!
-					 */
-					ioinfo[irq]->ui.flags.oper      = 0;
-					ioinfo[irq]->ui.flags.d_disable = 1;
-
-					ret = 0; /* if the device has gone we */
-					         /* ... don't need to disable */
-					         /* ... it anymore !    */
-					break;
-
-				default :
-					ret = -ENODEV;  // never reached ...
-					break;
-
-				} /* endswitch */
-
-			} while ( (cc == 1) && retry );
-
-		} /* endif */
-
-	} /* endif */
-
-	return( ret);
-}
-
-
-
-int s390_setup_irq( unsigned int irq, struct irqaction * new)
-{
-	unsigned long      flags;
-	int                rc = 0;
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-
-	/*
-	 * The following block of code has to be executed atomically
-	 */
-	s390irq_spin_lock_irqsave( irq, flags);
-
-	if ( ioinfo[irq]->irq_desc.action == NULL )
-	{
-		ioinfo[irq]->irq_desc.action           = new;
-		ioinfo[irq]->irq_desc.status           = 0;
-		ioinfo[irq]->irq_desc.handler->enable  = &enable_subchannel;
-		ioinfo[irq]->irq_desc.handler->disable = &disable_subchannel;
-		ioinfo[irq]->irq_desc.handler->handle  = &handle_IRQ_event;
-
-		ioinfo[irq]->ui.flags.ready            = 1;
-
-		ioinfo[irq]->irq_desc.handler->enable(irq);
-	}
-	else
-	{
-		/*
-		 *  interrupt already owned, and shared interrupts
-		 *   aren't supported on S/390.
-		 */
-		rc = -EBUSY;
-
-	} /* endif */
-
-	s390irq_spin_unlock_irqrestore(irq,flags);
-
-	return( rc);
-}
-
-void s390_init_IRQ( void )
-{
-	unsigned long flags;     /* PSW flags */
-	long          cr6 __attribute__ ((aligned (8)));
-
-	// Hopefully bh_count's will get set when we copy the prefix lowcore
-	// structure to other CPI's ( DJB )
-	softirq_active(smp_processor_id()) = 0;
-	softirq_mask(smp_processor_id()) = 0;
-	local_bh_count(smp_processor_id()) = 0;
-	local_irq_count(smp_processor_id()) = 0;
-	syscall_count(smp_processor_id()) = 0;
-
-	asm volatile ("STCK %0" : "=m" (irq_IPL_TOD));
-
-	/*
-	 * As we don't know about the calling environment
-	 *  we assure running disabled. Before leaving the
-	 *  function we resestablish the old environment.
-	 *
-	 * Note : as we don't need a system wide lock, therefore
-	 *        we shouldn't use cli(), but __cli() as this
-	 *        affects the current CPU only.
-	 */
-	__save_flags(flags);
-	__cli();
-
-	/*
-	 * disable all interrupts
-	 */
-	cr6 = 0;
-	asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-	s390_process_subchannels();
-
-	/*
-	 * enable default I/O-interrupt sublass 3
-	 */
-	cr6 = 0x10000000;
-	asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-	s390_device_recognition();
-
-	init_IRQ_complete = 1;
-
-	s390_init_machine_check();
-
-	__restore_flags(flags);
-
-	return;
-}
-
-
-/*
- * dummy handler, used during init_IRQ() processing for compatibility only
- */
-void  init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs)
-{
-   /* this is a dummy handler only ... */
-}
-
-
-int s390_start_IO( int            irq,      /* IRQ */
-                   ccw1_t        *cpa,      /* logical channel prog addr */
-                   unsigned long  user_intparm,  /* interruption parameter */
-                   __u8           lpm,      /* logical path mask */
-                   unsigned long  flag)     /* flags */
-{
-	int            ccode;
-	unsigned long  psw_flags;
-
-	int            sync_isc_locked = 0;
-	int            ret             = 0;
-
-	/*
-	 * The flag usage is mutal exclusive ...
-	 */
-	if (    (flag & DOIO_RETURN_CHAN_END)
-	     && (flag & DOIO_REPORT_ALL     ) )
-	{
-		return( -EINVAL );
-
-	} /* endif */
-
-	memset( &(ioinfo[irq]->orb), '\0', sizeof( orb_t) );
-
-	/*
-	 * setup ORB
-	 */
-  	ioinfo[irq]->orb.intparm = (__u32)&ioinfo[irq]->u_intparm;
-	ioinfo[irq]->orb.fmt     = 1;
-
-	ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH);
-	ioinfo[irq]->orb.spnd =  (flag & DOIO_ALLOW_SUSPEND);
-	ioinfo[irq]->orb.ssic =  (    (flag & DOIO_ALLOW_SUSPEND )
-	                           && (flag & DOIO_SUPPRESS_INTER) );
-
-	if ( flag & DOIO_VALID_LPM )
-	{
-		ioinfo[irq]->orb.lpm = lpm;
-	}
-	else
-	{
-		ioinfo[irq]->orb.lpm = ioinfo[irq]->opm;
-
-	} /* endif */
-
-	ioinfo[irq]->orb.cpa = (__u32)virt_to_phys( cpa);
-
-	/*
-	 * If sync processing was requested we lock the sync ISC, modify the
-	 *  device to present interrupts for this ISC only and switch the
-	 *  CPU to handle this ISC + the console ISC exclusively.
-	 */
-	if ( flag & DOIO_WAIT_FOR_INTERRUPT )
-	{
-		//
-		// check whether we run recursively (sense processing)
-		//
-		if ( !ioinfo[irq]->ui.flags.syncio )
-		{
-			spin_lock_irqsave( &sync_isc, psw_flags);
- 	
-			ret = enable_cpu_sync_isc( irq);
-
-			if ( ret )
-			{
-				spin_unlock_irqrestore( &sync_isc, psw_flags);
-				return( ret);
-			}
-			else
-			{
-				sync_isc_locked              = 1; // local
-				ioinfo[irq]->ui.flags.syncio = 1; // global
-
-			} /* endif */  	
- 	
-		} /* endif */
-
-	} /* endif */
-
-	/*
-	 * Issue "Start subchannel" and process condition code
-	 */
-	ccode = ssch( irq, &(ioinfo[irq]->orb) );
-
-	switch ( ccode ) {
-	case 0:
-
-		if ( !ioinfo[irq]->ui.flags.w4sense )
-		{
-			/*
-			 * init the device driver specific devstat irb area
-			 *
-			 * Note : don´t clear saved irb info in case of sense !
-			 */
-			memset( &((devstat_t *)ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
-				'\0', sizeof( irb_t) );
-		} /* endif */
-
-		/*
-		 * initialize device status information
-		 */
-		ioinfo[irq]->ui.flags.busy   = 1;
-		ioinfo[irq]->ui.flags.doio   = 1;
-
-		ioinfo[irq]->u_intparm       = user_intparm;
-		ioinfo[irq]->devstat.cstat   = 0;
-		ioinfo[irq]->devstat.dstat   = 0;
-		ioinfo[irq]->devstat.lpum    = 0;
-		ioinfo[irq]->devstat.flag    = DEVSTAT_START_FUNCTION;
-		ioinfo[irq]->devstat.scnt    = 0;
-
-		ioinfo[irq]->ui.flags.fast   = 0;
-		ioinfo[irq]->ui.flags.repall = 0;
-
-		/*
-		 * Check for either early (FAST) notification requests
-		 *  or if we are to return all interrupt info.
-		 * Default is to call IRQ handler at secondary status only
-		 */
-		if ( flag & DOIO_RETURN_CHAN_END )
-		{
-			ioinfo[irq]->ui.flags.fast = 1;
-		}
-		else if ( flag & DOIO_REPORT_ALL )
-		{
-			ioinfo[irq]->ui.flags.repall = 1;
-
-		} /* endif */
-
-		ioinfo[irq]->ulpm = ioinfo[irq]->orb.lpm;
-
-		/*
-		 * If synchronous I/O processing is requested, we have
-		 *  to wait for the corresponding interrupt to occur by
-		 *  polling the interrupt condition. However, as multiple
-		 *  interrupts may be outstanding, we must not just wait
-		 *  for the first interrupt, but must poll until ours
-		 *  pops up.
-		 */
-		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
-		{
-	//		__u32            io_parm;
-			psw_t            io_new_psw;
-			int              ccode;
-
-			int              ready  = 0;
-			int              io_sub = -1;
-			struct _lowcore *lc     = NULL;
-			int              count  = 30000;
-
-			/*
-			 * We shouldn't perform a TPI loop, waiting for an
-			 *  interrupt to occur, but should load a WAIT PSW
-			 *  instead. Otherwise we may keep the channel subsystem
-			 *  busy, not able to present the interrupt. When our
-			 *  sync. interrupt arrived we reset the I/O old PSW to
-			 *  its original value.
-			 */
-			memcpy( &io_new_psw, &lc->io_new_psw, sizeof(psw_t));
-
-			ccode = iac();
-
-			switch (ccode) {
-			case 0:  		// primary-space
-				io_sync_wait.mask =   _IO_PSW_MASK
-				                    | _PSW_PRIM_SPACE_MODE
-				                    | _PSW_IO_WAIT;
-				break;
-			case 1:			// secondary-space
-				io_sync_wait.mask =   _IO_PSW_MASK
-				                    | _PSW_SEC_SPACE_MODE
-				                    | _PSW_IO_WAIT;
-				break;
-			case 2:			// access-register
-				io_sync_wait.mask =   _IO_PSW_MASK
-				                    | _PSW_ACC_REG_MODE
-				                    | _PSW_IO_WAIT;
-				break;
-			case 3:			// home-space	
-				io_sync_wait.mask =   _IO_PSW_MASK
-				                    | _PSW_HOME_SPACE_MODE
-				                    | _PSW_IO_WAIT;
-				break;
-			default:
-				panic( "start_IO() : unexpected "
-				       "address-space-control %d\n",
-				       ccode);
-				break;
-			} /* endswitch */
-
-			io_sync_wait.addr = FIX_PSW(&&io_wakeup);
-
-			/*
-			 * Martin didn't like modifying the new PSW, now we take
-			 *  a fast exit in do_IRQ() instead
-			 */
-			*(__u32 *)__LC_SYNC_IO_WORD  = 1;
-
-			do
-			{
-				if ( flag & DOIO_TIMEOUT )
-				{
-					tpi_info_t tpi_info;
-
-					do
-					{
-						if ( tpi(&tpi_info) == 1 )
-						{
-							io_sub = tpi_info.irq;
-							break;
-						}
-						else
-						{
-							count--;
-							tod_wait(100); /* usecs */
-
-						} /* endif */
-				
-					} while ( count );
-				}
-				else
-				{
-					asm volatile ("lpsw %0" : : "m" (io_sync_wait));
-
-io_wakeup:
-					io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
-
-				} /* endif */
-
- 				if ( count )
-					ready = s390_process_IRQ( io_sub );
-
-				/*
-				 * surrender when retry count's exceeded ...
-				 */
-
-			} while ( !(     ( io_sub == irq )
-			              && ( ready  == 1   ))
-			            && count                );
-
-			*(__u32 *)__LC_SYNC_IO_WORD = 0;
-
-			if ( !count )
-				ret = -ETIMEDOUT;
-
-		} /* endif */
-
-		break;
-
-	case 1 :            /* status pending */
-
-		ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
-
-		/*
-		 * initialize the device driver specific devstat irb area
-		 */
-		memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
-		        '\0', sizeof( irb_t) );
-
-		/*
-		 * Let the common interrupt handler process the pending status.
-		 *  However, we must avoid calling the user action handler, as
-		 *  it won't be prepared to handle a pending status during
-		 *  do_IO() processing inline. This also implies that process_IRQ
-		 *  must terminate synchronously - especially if device sensing
-		 *  is required.
-		 */
-		ioinfo[irq]->ui.flags.s_pend   = 1;
-		ioinfo[irq]->ui.flags.busy     = 1;
-		ioinfo[irq]->ui.flags.doio     = 1;
-
-		s390_process_IRQ( irq );
-
-		ioinfo[irq]->ui.flags.s_pend   = 0;
-		ioinfo[irq]->ui.flags.busy     = 0;
-		ioinfo[irq]->ui.flags.doio     = 0;
-		ioinfo[irq]->ui.flags.repall   = 0;
-		ioinfo[irq]->ui.flags.w4final  = 0;
-
-		ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
-
-		/*
-		 * In multipath mode a condition code 3 implies the last path
-		 *  has gone, except we have previously restricted the I/O to
-		 *  a particular path. A condition code 1 (0 won't occur)
-		 *  results in return code EIO as well as 3 with another path
-		 *  than the one used (i.e. path available mask is non-zero).
-		 */
-		if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
-		{
-			ret                         = -ENODEV;
-			ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
-			ioinfo[irq]->ui.flags.oper  = 0;
-
-#if CONFIG_DEBUG_IO
-			{
-			char buffer[80];
-
-			stsch(irq, &(ioinfo[irq]->schib) );
-
-			sprintf( buffer, "s390_start_IO(%04X) - irb for "
-			         "device %04X, after status pending\n",
-			         irq,
-			         ioinfo[irq]->devstat.devno );
-
-			s390_displayhex( buffer,
-			                 &(ioinfo[irq]->devstat.ii.irb) ,
-			                 sizeof(irb_t));
-
-			sprintf( buffer, "s390_start_IO(%04X) - schib for "
-			         "device %04X, after status pending\n",
-			         irq,
-			         ioinfo[irq]->devstat.devno );
-
-			s390_displayhex( buffer,
-			                 &(ioinfo[irq]->schib) ,
-			                 sizeof(schib_t));
-
-
-			if (ioinfo[irq]->devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL)
-			{
-				sprintf( buffer, "s390_start_IO(%04X) - sense "
-				         "data for "
-				         "device %04X, after status pending\n",
-				         irq,
-				         ioinfo[irq]->devstat.devno );
-
-				s390_displayhex( buffer,
-		((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->ii.sense.data,
-		((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->rescnt);
-
-			}
-			}
-#endif
-		}
-		else
-		{
-			ret                         = -EIO;
-			ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
-			ioinfo[irq]->ui.flags.oper  = 1;
-
-		} /* endif */
-
-		break;
-
-	case 2 :            /* busy */
-
-		ret = -EBUSY;
-		break;
-
-	default:            /* device not operational */
-
-		ret                           = -ENODEV;
-		ioinfo[irq]->ui.flags.oper    = 0;
-
-		ioinfo[irq]->devstat.flag    |= DEVSTAT_NOT_OPER;
-
-		memcpy( ioinfo[irq]->irq_desc.action->dev_id,
-			&(ioinfo[irq]->devstat),
-			sizeof( devstat_t) );
-
-#if CONFIG_DEBUG_IO
-		{
-			char buffer[80];
-
-   			stsch(irq, &(ioinfo[irq]->schib) );
-
-			sprintf( buffer, "s390_start_IO(%04X) - schib for "
-			         "device %04X, after 'not oper' status\n",
-			         irq,
-			         ioinfo[irq]->devstat.devno );
-
-			s390_displayhex( buffer,
-			                 &(ioinfo[irq]->schib),
-			                 sizeof(schib_t));
-      	}
-#endif
-		break;
-
-	} /* endswitch */
-
-	if (    ( flag & DOIO_WAIT_FOR_INTERRUPT )   	
-	     && ( sync_isc_locked                ) )
-	{
-		disable_cpu_sync_isc( irq );
-
-		spin_unlock_irqrestore( &sync_isc, psw_flags);
-
-		sync_isc_locked              = 0;    // local setting
-		ioinfo[irq]->ui.flags.syncio = 0;    // global setting
-
-	} /* endif */
-
-	return( ret);
-}
-
-int do_IO( int            irq,          /* IRQ */
-           ccw1_t        *cpa,          /* channel program address */
-           unsigned long  user_intparm, /* interruption parameter */
-           __u8           lpm,          /* logical path mask */
-           unsigned long  flag)         /* flags : see above */
-{
-	int ret = 0;
-
-	if ( irq > highest_subchannel || irq < 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-
-	/* handler registered ? or free_irq() in process already ? */
-	if ( !ioinfo[irq]->ui.flags.ready || ioinfo[irq]->ui.flags.unready )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	/*
-	 * Note: We ignore the device operational status - if not operational,
-	 *        the SSCH will lead to an -ENODEV condition ...
-	 */
-	if ( !ioinfo[irq]->ui.flags.busy )         /* last I/O completed ? */
-	{
-		ret = s390_start_IO( irq, cpa, user_intparm, lpm, flag);
-	}
-	else if ( ioinfo[irq]->ui.flags.fast )
-	{
-		/*
-		 * If primary status was received and ending status is missing,
-		 *  the device driver won't be notified on the ending status
-		 *  if early (fast) interrupt notification was requested.
-		 *  Therefore we have to queue the next incoming request. If
-		 *  halt_IO() is issued while there is a request queued, a HSCH
-		 *  needs to be issued and the queued request must be deleted
-		 *  but its intparm must be returned (see halt_IO() processing)
-		 */
-		if (     ioinfo[irq]->ui.flags.w4final
-           && !ioinfo[irq]->ui.flags.doio_q )
-		{
-			ioinfo[irq]->qflag    = flag;
-			ioinfo[irq]->qcpa     = cpa;
-			ioinfo[irq]->qintparm = user_intparm;
-			ioinfo[irq]->qlpm     = lpm;
-		}
-		else
-		{
-			ret = -EBUSY;
-
-		} /* endif */
-	}
-	else
-	{
-		ret = -EBUSY;
-
-	} /* endif */
-
-	return( ret );
-
-}
-
-/*
- * resume suspended I/O operation
- */
-int resume_IO( int irq)
-{
-	int ret = 0;
-
-	if ( irq > highest_subchannel || irq < 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-
-	/*
-	 * We allow for 'resume' requests only for active I/O operations
-	 */
-	if ( ioinfo[irq]->ui.flags.busy )
-	{
-		int ccode;
-
-		ccode = rsch( irq);
-
-		switch (ccode) {
-		case 0 :
-			break;
-
-		case 1 :
-		  	s390_process_IRQ( irq );
-			ret = -EBUSY;
-			break;
-
-		case 2 :
-			ret = -EINVAL;
-			break;
-
-		case 3 :
-			/*
-			 * useless to wait for request completion
-			 *  as device is no longer operational !
-			 */
-			ioinfo[irq]->ui.flags.oper = 0;
-			ioinfo[irq]->ui.flags.busy = 0;
-			ret                        = -ENODEV;
-			break;
-
-		} /* endswitch */          	
-		
-	}
-	else
-	{
-		ret = -ENOTCONN;
-
-	} /* endif  */
-
-	return( ret);
-}
-
-/*
- * Note: The "intparm" parameter is not used by the halt_IO() function
- *       itself, as no ORB is built for the HSCH instruction. However,
- *       it allows the device interrupt handler to associate the upcoming
- *       interrupt with the halt_IO() request.
- */
-int halt_IO( int           irq,
-             unsigned long user_intparm,
-             unsigned long flag)  /* possible DOIO_WAIT_FOR_INTERRUPT */
-{
-	int            ret;
-	int            ccode;
-	unsigned long  psw_flags;
-
-	int            sync_isc_locked = 0;
-
-	if ( irq > highest_subchannel || irq < 0 )
-	{
-		ret = -ENODEV;
-	}
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-
-	/*
-	 * we only allow for halt_IO if the device has an I/O handler associated
-	 */
-	else if ( !ioinfo[irq]->ui.flags.ready )
-	{
-		ret = -ENODEV;
-	}
-	/*
-	 * we ignore the halt_io() request if ending_status was received but
-	 *  a SENSE operation is waiting for completion.
-	 */
-	else if ( ioinfo[irq]->ui.flags.w4sense )
-	{
-		ret = 0;
-	}
-	/*
-	 * We don't allow for halt_io with a sync do_IO() requests pending.
-	 */
-	else if ( ioinfo[irq]->ui.flags.syncio )
-	{
-		ret = -EBUSY;
-	}
-	else
-	{
-		/*
-		 * If sync processing was requested we lock the sync ISC,
-		 *  modify the device to present interrupts for this ISC only
-		 *  and switch the CPU to handle this ISC + the console ISC
-		 *  exclusively.
-		 */
-		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
-		{
-			//
-			// check whether we run recursively (sense processing)
-			//
-			if ( !ioinfo[irq]->ui.flags.syncio )
-			{
-				spin_lock_irqsave( &sync_isc, psw_flags);
-  	
-				ret = enable_cpu_sync_isc( irq);
-
-				if ( ret )
-				{
-					spin_unlock_irqrestore( &sync_isc,
-					                        psw_flags);
-					return( ret);
-				}
-				else
-				{
-					sync_isc_locked              = 1; // local
-					ioinfo[irq]->ui.flags.syncio = 1; // global
-
-				} /* endif */  	
-  	
-			} /* endif */
-
-		} /* endif */
-
-		/*
-		 * Issue "Halt subchannel" and process condition code
-		 */
-		ccode = hsch( irq );
-
-		switch ( ccode ) {
-		case 0:
-
-			ioinfo[irq]->ui.flags.haltio = 1;
-
-			if ( !ioinfo[irq]->ui.flags.doio )
-			{
-				ioinfo[irq]->ui.flags.busy   = 1;
-				ioinfo[irq]->u_intparm       = user_intparm;
-				ioinfo[irq]->devstat.cstat   = 0;
-				ioinfo[irq]->devstat.dstat   = 0;
-				ioinfo[irq]->devstat.lpum    = 0;
-				ioinfo[irq]->devstat.flag    = DEVSTAT_HALT_FUNCTION;
-				ioinfo[irq]->devstat.scnt    = 0;
-
-			}
-			else
-			{
-				ioinfo[irq]->devstat.flag   |= DEVSTAT_HALT_FUNCTION;
-
-			} /* endif */
-
-			/*
-			 * If synchronous I/O processing is requested, we have
-			 *  to wait for the corresponding interrupt to occur by
-			 *  polling the interrupt condition. However, as multiple
-			 *  interrupts may be outstanding, we must not just wait
-			 *  for the first interrupt, but must poll until ours
-			 *  pops up.
-			 */
-			if ( flag & DOIO_WAIT_FOR_INTERRUPT )
-			{
-				int              io_sub;
-				__u32            io_parm;
-				psw_t            io_new_psw;
-				int              ccode;
-  	
-				int              ready = 0;
-				struct _lowcore *lc    = NULL;
-
-				/*
-				 * We shouldn't perform a TPI loop, waiting for
-				 *  an interrupt to occur, but should load a
-				 *  WAIT PSW instead. Otherwise we may keep the
-				 *  channel subsystem busy, not able to present
-				 *  the interrupt. When our sync. interrupt
-				 *  arrived we reset the I/O old PSW to its
-				 *  original value.
-				 */
-				memcpy( &io_new_psw,
-				        &lc->io_new_psw,
-				        sizeof(psw_t));
-
-				ccode = iac();
-
-				switch (ccode) {
-				case 0:  		// primary-space
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_PRIM_SPACE_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				case 1:			// secondary-space
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_SEC_SPACE_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				case 2:			// access-register
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_ACC_REG_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				case 3:			// home-space	
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_HOME_SPACE_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				default:
-					panic( "halt_IO() : unexpected "
-					       "address-space-control %d\n",
-					       ccode);
-					break;
-				} /* endswitch */
-
-				io_sync_wait.addr = FIX_PSW(&&hio_wakeup);
-
-				/*
-				 * Martin didn't like modifying the new PSW, now we take
-				 *  a fast exit in do_IRQ() instead
-				 */
-				*(__u32 *)__LC_SYNC_IO_WORD  = 1;
-
-				do
-				{
-
-	      		asm volatile ( "lpsw %0" : : "m" (io_sync_wait) );
-hio_wakeup:
-				   io_parm = *(__u32 *)__LC_IO_INT_PARM;
-				   io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
-
-				   ready = s390_process_IRQ( io_sub );
-
-				} while ( !((io_sub == irq) && (ready == 1)) );
-
-				*(__u32 *)__LC_SYNC_IO_WORD = 0;
-
-			} /* endif */
-
-			ret = 0;
-			break;
-
-		case 1 :            /* status pending */
-	
-			ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
-
-			/*
-			 * initialize the device driver specific devstat irb area
-			 */
-			memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
-			        '\0', sizeof( irb_t) );
-
-			/*
-			 * Let the common interrupt handler process the pending
-			 *  status. However, we must avoid calling the user
-			 *  action handler, as it won't be prepared to handle
-                        *  a pending status during do_IO() processing inline.
-			 *  This also implies that s390_process_IRQ must
-			 *  terminate synchronously - especially if device
-			 *  sensing is required.
-			 */
-			ioinfo[irq]->ui.flags.s_pend   = 1;
-			ioinfo[irq]->ui.flags.busy     = 1;
-			ioinfo[irq]->ui.flags.doio     = 1;
-
-			s390_process_IRQ( irq );
-			
-			ioinfo[irq]->ui.flags.s_pend   = 0;
-			ioinfo[irq]->ui.flags.busy     = 0;
-			ioinfo[irq]->ui.flags.doio     = 0;
-			ioinfo[irq]->ui.flags.repall   = 0;
-			ioinfo[irq]->ui.flags.w4final  = 0;
-
-			ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
-
-			/*
-			 * In multipath mode a condition code 3 implies the last
-			 *  path has gone, except we have previously restricted
-			 *  the I/O to a particular path. A condition code 1
-			 *  (0 won't occur) results in return code EIO as well
-			 *  as 3 with another path than the one used (i.e. path available mask is non-zero).
-			 */
-			if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
-			{
-				ret                         = -ENODEV;
-				ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
-				ioinfo[irq]->ui.flags.oper  = 0;
-			}
-			else
-			{
-				ret                         = -EIO;
-				ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
-				ioinfo[irq]->ui.flags.oper  = 1;
-
-			} /* endif */
-
-			break;
-
-		case 2 :            /* busy */
-
-			ret = -EBUSY;
-			break;
-
-		default:            /* device not operational */
-
-			ret = -ENODEV;
-			break;
-
-		} /* endswitch */
-
-		if (    ( flag & DOIO_WAIT_FOR_INTERRUPT )
-	   	  && ( sync_isc_locked                ) )
-		{
-			sync_isc_locked              = 0;    // local setting
-		   ioinfo[irq]->ui.flags.syncio = 0;    // global setting
-  	
-			disable_cpu_sync_isc( irq );
-  	
-			spin_unlock_irqrestore( &sync_isc, psw_flags);
-  	
-		} /* endif */
-
-	} /* endif */
-
-	return( ret );
-}
-
-/*
- * Note: The "intparm" parameter is not used by the clear_IO() function
- *       itself, as no ORB is built for the CSCH instruction. However,
- *       it allows the device interrupt handler to associate the upcoming
- *       interrupt with the clear_IO() request.
- */
-int clear_IO( int           irq,
-              unsigned long user_intparm,
-              unsigned long flag)  /* possible DOIO_WAIT_FOR_INTERRUPT */
-{
-	int            ret;
-	int            ccode;
-	unsigned long  psw_flags;
-
-	int            sync_isc_locked = 0;
-
-	if ( irq > highest_subchannel || irq < 0 )
-	{
-		ret = -ENODEV;
-	}
-
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-
-	/*
-	 * we only allow for halt_IO if the device has an I/O handler associated
-	 */
-	else if ( !ioinfo[irq]->ui.flags.ready )
-	{
-		ret = -ENODEV;
-	}
-	/*
-	 * we ignore the halt_io() request if ending_status was received but
-	 *  a SENSE operation is waiting for completion.
-	 */
-	else if ( ioinfo[irq]->ui.flags.w4sense )
-	{
-		ret = 0;
-	}
-	/*
-	 * We don't allow for halt_io with a sync do_IO() requests pending.
-	 *  Concurrent I/O is possible in SMP environments only, but the
-	 *  sync. I/O request can be gated to one CPU at a time only.
-	 */
-	else if ( ioinfo[irq]->ui.flags.syncio )
-	{
-		ret = -EBUSY;
-	}
-	else
-	{
-		/*
-		 * If sync processing was requested we lock the sync ISC,
-		 *  modify the device to present interrupts for this ISC only
-		 *  and switch the CPU to handle this ISC + the console ISC
-		 *  exclusively.
-		 */
-		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
-		{
-			//
-			// check whether we run recursively (sense processing)
-			//
-			if ( !ioinfo[irq]->ui.flags.syncio )
-			{
-				spin_lock_irqsave( &sync_isc, psw_flags);
-  	
-				ret = enable_cpu_sync_isc( irq);
-
-				if ( ret )
-				{
-					spin_unlock_irqrestore( &sync_isc,
-					                        psw_flags);
-					return( ret);
-				}
-				else
-				{
-					sync_isc_locked              = 1; // local
-					ioinfo[irq]->ui.flags.syncio = 1; // global
-
-				} /* endif */  	
-  	
-			} /* endif */
-
-		} /* endif */
-
-		/*
-		 * Issue "Halt subchannel" and process condition code
-		 */
-		ccode = csch( irq );
-
-		switch ( ccode ) {
-		case 0:
-
-			ioinfo[irq]->ui.flags.haltio = 1;
-
-			if ( !ioinfo[irq]->ui.flags.doio )
-			{
-				ioinfo[irq]->ui.flags.busy   = 1;
-				ioinfo[irq]->u_intparm       = user_intparm;
-				ioinfo[irq]->devstat.cstat   = 0;
-				ioinfo[irq]->devstat.dstat   = 0;
-				ioinfo[irq]->devstat.lpum    = 0;
-				ioinfo[irq]->devstat.flag    = DEVSTAT_CLEAR_FUNCTION;
-				ioinfo[irq]->devstat.scnt    = 0;
-
-			}
-			else
-			{
-				ioinfo[irq]->devstat.flag   |= DEVSTAT_CLEAR_FUNCTION;
-
-			} /* endif */
-
-			/*
-			 * If synchronous I/O processing is requested, we have
-			 *  to wait for the corresponding interrupt to occur by
-			 *  polling the interrupt condition. However, as multiple
-			 *  interrupts may be outstanding, we must not just wait
-			 *  for the first interrupt, but must poll until ours
-			 *  pops up.
-			 */
-			if ( flag & DOIO_WAIT_FOR_INTERRUPT )
-			{
-				int              io_sub;
-				__u32            io_parm;
-				psw_t            io_new_psw;
-				int              ccode;
-  	
-				int              ready = 0;
-				struct _lowcore *lc    = NULL;
-
-				/*
-				 * We shouldn't perform a TPI loop, waiting for
-				 *  an interrupt to occur, but should load a
-				 *  WAIT PSW instead. Otherwise we may keep the
-				 *  channel subsystem busy, not able to present
-				 *  the interrupt. When our sync. interrupt
-				 *  arrived we reset the I/O old PSW to its
-				 *  original value.
-				 */
-				memcpy( &io_new_psw,
-				        &lc->io_new_psw,
-				        sizeof(psw_t));
-
-				ccode = iac();
-
-				switch (ccode) {
-				case 0:  		// primary-space
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_PRIM_SPACE_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				case 1:			// secondary-space
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_SEC_SPACE_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				case 2:			// access-register
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_ACC_REG_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				case 3:			// home-space	
-					io_sync_wait.mask =   _IO_PSW_MASK
-					                    | _PSW_HOME_SPACE_MODE
-					                    | _PSW_IO_WAIT;
-					break;
-				default:
-					panic( "halt_IO() : unexpected "
-					       "address-space-control %d\n",
-					       ccode);
-					break;
-				} /* endswitch */
-
-				io_sync_wait.addr = FIX_PSW(&&cio_wakeup);
-
-				/*
-				 * Martin didn't like modifying the new PSW, now we take
-				 *  a fast exit in do_IRQ() instead
-				 */
-				*(__u32 *)__LC_SYNC_IO_WORD  = 1;
-
-				do
-				{
-
-	      		asm volatile ( "lpsw %0" : : "m" (io_sync_wait) );
-cio_wakeup:
-				   io_parm = *(__u32 *)__LC_IO_INT_PARM;
-				   io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
-
-				   ready = s390_process_IRQ( io_sub );
-
-				} while ( !((io_sub == irq) && (ready == 1)) );
-
-				*(__u32 *)__LC_SYNC_IO_WORD = 0;
-
-			} /* endif */
-
-			ret = 0;
-			break;
-
-		case 1 :            /* status pending */
-	
-			ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
-
-			/*
-			 * initialize the device driver specific devstat irb area
-			 */
-			memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
-			        '\0', sizeof( irb_t) );
-
-			/*
-			 * Let the common interrupt handler process the pending
-			 *  status. However, we must avoid calling the user
-			 *  action handler, as it won't be prepared to handle
-                        *  a pending status during do_IO() processing inline.
-			 *  This also implies that s390_process_IRQ must
-			 *  terminate synchronously - especially if device
-			 *  sensing is required.
-			 */
-			ioinfo[irq]->ui.flags.s_pend   = 1;
-			ioinfo[irq]->ui.flags.busy     = 1;
-			ioinfo[irq]->ui.flags.doio     = 1;
-
-			s390_process_IRQ( irq );
-			
-			ioinfo[irq]->ui.flags.s_pend   = 0;
-			ioinfo[irq]->ui.flags.busy     = 0;
-			ioinfo[irq]->ui.flags.doio     = 0;
-			ioinfo[irq]->ui.flags.repall   = 0;
-			ioinfo[irq]->ui.flags.w4final  = 0;
-
-			ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
-
-			/*
-			 * In multipath mode a condition code 3 implies the last
-			 *  path has gone, except we have previously restricted
-			 *  the I/O to a particular path. A condition code 1
-			 *  (0 won't occur) results in return code EIO as well
-			 *  as 3 with another path than the one used (i.e. path available mask is non-zero).
-			 */
-			if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
-			{
-				ret                         = -ENODEV;
-				ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
-				ioinfo[irq]->ui.flags.oper  = 0;
-			}
-			else
-			{
-				ret                         = -EIO;
-				ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
-				ioinfo[irq]->ui.flags.oper  = 1;
-
-			} /* endif */
-
-			break;
-
-		case 2 :            /* busy */
-
-			ret = -EBUSY;
-			break;
-
-		default:            /* device not operational */
-
-			ret = -ENODEV;
-			break;
-
-		} /* endswitch */
-
-		if (    ( flag & DOIO_WAIT_FOR_INTERRUPT )
-	   	  && ( sync_isc_locked                ) )
-		{
-			sync_isc_locked              = 0;    // local setting
-		   ioinfo[irq]->ui.flags.syncio = 0;    // global setting
-  	
-			disable_cpu_sync_isc( irq );
-  	
-			spin_unlock_irqrestore( &sync_isc, psw_flags);
-  	
-		} /* endif */
-
-	} /* endif */
-
-	return( ret );
-}
-
-
-/*
- * do_IRQ() handles all normal I/O device IRQ's (the special
- *          SMP cross-CPU interrupts have their own specific
- *          handlers).
- *
- * Returns: 0 - no ending status received, no further action taken
- *          1 - interrupt handler was called with ending status
- */
-asmlinkage void do_IRQ( struct pt_regs regs,
-                        unsigned int   irq,
-                        __u32          s390_intparm )
-{
-#ifdef CONFIG_FAST_IRQ
-	int			ccode;
-	tpi_info_t 	tpi_info;
-	int			new_irq;
-#endif
-	int			use_irq     = irq;
-//	__u32       use_intparm = s390_intparm;
-
-	//
-	// fix me !!!
-	//
-	// We need to schedule device recognition, the interrupt stays
-	//  pending. We need to dynamically allocate an ioinfo structure.
-	//
-	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return;	/* this keeps the device boxed ... */
-	}
-
-	/*
-	 * take fast exit if CPU is in sync. I/O state
-	 *
-	 * Note: we have to turn off the WAIT bit and re-disable
-	 *       interrupts prior to return as this was the initial
-	 *       entry condition to synchronous I/O.
-	 */
- 	if (    *(__u32 *)__LC_SYNC_IO_WORD )
-	{
-		regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT);
-
-      return;
-
-	} /* endif */
-
-	s390irq_spin_lock(use_irq);
-
-#ifdef CONFIG_FAST_IRQ
-	do {
-#endif /*  CONFIG_FAST_IRQ */
-
-		s390_process_IRQ( use_irq );
-
-#ifdef CONFIG_FAST_IRQ
-
-		/*
-		 * more interrupts pending ?
-		 */
-		ccode = tpi( &tpi_info );
-
-		if ( ! ccode )
-			break;  	// no, leave ...
-
-		new_irq     = tpi_info.irq;
-//		use_intparm = tpi_info.intparm;
-
-		/*
-		 * if the interrupt is for a different irq we
-		 *  release the current irq lock and obtain
-		 *  a new one ...
-		 */
-		if ( new_irq != use_irq )
-      {
-			s390irq_spin_unlock(use_irq);
-         use_irq = new_irq;
-			s390irq_spin_lock(use_irq);
-
-      } /* endif */
-
-	} while ( 1 );
-
-#endif /*  CONFIG_FAST_IRQ */
-
-	s390irq_spin_unlock(use_irq);
-
-	return;
-}
-
-/*
- * s390_process_IRQ() handles status pending situations and interrupts
- *
- * Called by : do_IRQ()             - for "real" interrupts
- *             s390_start_IO, halt_IO()
- *                                  - status pending cond. after SSCH, or HSCH
- *             disable_subchannel() - status pending conditions (after MSCH)
- *
- * Returns: 0 - no ending status received, no further action taken
- *          1 - interrupt handler was called with ending status
- */
-int s390_process_IRQ( unsigned int irq )
-{
-	int               ccode;      /* condition code from tsch() operation */
-	int               irb_cc;     /* condition code from irb */
-	int               sdevstat;   /* effective struct devstat size to copy */
-	unsigned int      fctl;       /* function control */
-	unsigned int      stctl;      /* status   control */
-	unsigned int      actl;       /* activity control */
-	struct irqaction *action;
-	struct pt_regs    regs;       /* for interface compatibility only */
-
-	int               issense         = 0;
-	int               ending_status   = 0;
-	int               allow4handler   = 1;
-	int               chnchk          = 0;
-#if 0
-	int               cpu             = smp_processor_id();
-
-	kstat.irqs[cpu][irq]++;
-#endif
-	action = ioinfo[irq]->irq_desc.action;
-
-	/*
-	 * It might be possible that a device was not-oper. at the time
-	 *  of free_irq() processing. This means the handler is no longer
-	 *  available when the device possibly becomes ready again. In
-	 *  this case we perform delayed disable_subchannel() processing.
-	 */
-	if ( action == NULL )
-	{
-		if ( !ioinfo[irq]->ui.flags.d_disable )
-		{
-			printk( KERN_CRIT"s390_process_IRQ(%04X) "
-			        "- no interrupt handler registered"
-					  "for device %04X !\n",
-			        irq,
-			        ioinfo[irq]->devstat.devno);
-
-		} /* endif */
-
-	} /* endif */
-
-	/*
-	 * retrieve the i/o interrupt information (irb),
-	 *  update the device specific status information
-	 *  and possibly call the interrupt handler.
-	 *
-	 * Note 1: At this time we don't process the resulting
-	 *         condition code (ccode) from tsch(), although
-	 *         we probably should.
-	 *
-	 * Note 2: Here we will have to check for channel
-	 *         check conditions and call a channel check
-	 *         handler.
-	 *
-	 * Note 3: If a start function was issued, the interruption
-	 *         parameter relates to it. If a halt function was
-	 *         issued for an idle device, the intparm must not
-	 *         be taken from lowcore, but from the devstat area.
-	 */
-	ccode = tsch( irq, &(ioinfo[irq]->devstat.ii.irb) );
-
-	//
-	// We must only accumulate the status if initiated by do_IO() or halt_IO()
-	//
-	if ( ioinfo[irq]->ui.flags.busy )
-	{
-		ioinfo[irq]->devstat.dstat |= ioinfo[irq]->devstat.ii.irb.scsw.dstat;
-		ioinfo[irq]->devstat.cstat |= ioinfo[irq]->devstat.ii.irb.scsw.cstat;
-	}
-	else
-	{
-		ioinfo[irq]->devstat.dstat  = ioinfo[irq]->devstat.ii.irb.scsw.dstat;
-		ioinfo[irq]->devstat.cstat  = ioinfo[irq]->devstat.ii.irb.scsw.cstat;
-
-		ioinfo[irq]->devstat.flag   = 0;   // reset status flags
-
-	} /* endif */
-
-	ioinfo[irq]->devstat.lpum = ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum;
-
-	if ( ioinfo[irq]->ui.flags.busy)
-	{
-		ioinfo[irq]->devstat.intparm  = ioinfo[irq]->u_intparm;
-
-	} /* endif */
-
-	/*
-	 * reset device-busy bit if no longer set in irb
-	 */
-	if (   (ioinfo[irq]->devstat.dstat & DEV_STAT_BUSY                   )
-	    && ((ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0))
-	{
-		ioinfo[irq]->devstat.dstat &= ~DEV_STAT_BUSY;
-
-	} /* endif */
-
-	/*
-	 * Save residual count and CCW information in case primary and
-	 *  secondary status are presented with different interrupts.
-	 */
-	if ( ioinfo[irq]->devstat.ii.irb.scsw.stctl & SCSW_STCTL_PRIM_STATUS )
-	{
-		ioinfo[irq]->devstat.rescnt = ioinfo[irq]->devstat.ii.irb.scsw.count;
-
-#if CONFIG_DEBUG_IO
-      if ( irq != cons_dev )
-         printk( "s390_process_IRQ( %04X ) : "
-                 "residual count from irb after tsch() %d\n",
-                 irq, ioinfo[irq]->devstat.rescnt );
-#endif
-	} /* endif */
-
-	if ( ioinfo[irq]->devstat.ii.irb.scsw.cpa != 0 )
-	{
-		ioinfo[irq]->devstat.cpa = ioinfo[irq]->devstat.ii.irb.scsw.cpa;
-
-	} /* endif */
-
-	irb_cc = ioinfo[irq]->devstat.ii.irb.scsw.cc;
-
-	//
-	// check for any kind of channel or interface control check but don't
-	//  issue the message for the console device
-	//
-	if (    (ioinfo[irq]->devstat.ii.irb.scsw.cstat
-	            & (  SCHN_STAT_CHN_DATA_CHK
-	               | SCHN_STAT_CHN_CTRL_CHK
-	               | SCHN_STAT_INTF_CTRL_CHK )       )
-	     && (irq != cons_dev                         ) )
-	{
-		printk( "Channel-Check or Interface-Control-Check "
-		        "received\n"
-		        " ... device %04X on subchannel %04X, dev_stat "
-		        ": %02X sch_stat : %02X\n",
-		        ioinfo[irq]->devstat.devno,
-		        irq,
-		        ioinfo[irq]->devstat.dstat,
-		        ioinfo[irq]->devstat.cstat);
-
-		chnchk = 1;
-
-	} /* endif */
-
-	issense = ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.cons;
-
-	if ( issense )
-	{
-		ioinfo[irq]->devstat.scnt  =
-		             ioinfo[irq]->devstat.ii.irb.esw.esw0.erw.scnt;
-		ioinfo[irq]->devstat.flag |=
-		             DEVSTAT_FLAG_SENSE_AVAIL;
-                  	
-		sdevstat = sizeof( devstat_t);
-
-#if CONFIG_DEBUG_IO
-      if ( irq != cons_dev )
-         printk( "s390_process_IRQ( %04X ) : "
-                 "concurrent sense bytes avail %d\n",
-                 irq, ioinfo[irq]->devstat.scnt );
-#endif
-	}
-	else
-	{
-		/* don't copy the sense data area ! */
-		sdevstat = sizeof( devstat_t) - SENSE_MAX_COUNT;
-
-	} /* endif */
-
-	switch ( irb_cc ) {
-	case 1:      /* status pending */
-
-		ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
-
-	case 0:      /* normal i/o interruption */
-
-		fctl  = ioinfo[irq]->devstat.ii.irb.scsw.fctl;
-		stctl = ioinfo[irq]->devstat.ii.irb.scsw.stctl;
-		actl  = ioinfo[irq]->devstat.ii.irb.scsw.actl;
-
-		if ( chnchk && (ioinfo[irq]->senseid.cu_type == 0x3088))
-		{
-			char buffer[80];
-   	
-			sprintf( buffer, "s390_process_IRQ(%04X) - irb for "
-			         "device %04X after channel check\n",
-			         irq,
-			         ioinfo[irq]->devstat.devno );
-
-			s390_displayhex( buffer,
-			                 &(ioinfo[irq]->devstat.ii.irb) ,
-			                 sizeof(irb_t));
-		} /* endif */
-			
-		ioinfo[irq]->stctl |= stctl;
-
-		ending_status =    ( stctl & SCSW_STCTL_SEC_STATUS                          )
-			|| ( stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)         )
-		   || ( (fctl == SCSW_FCTL_HALT_FUNC)  && (stctl == SCSW_STCTL_STATUS_PEND) );
-
-		/*
-		 * Check for unsolicited interrupts - for debug purposes only
-		 *
-		 * We only consider an interrupt as unsolicited, if the device was not
-		 *  actively in use (busy) and an interrupt other than an ALERT status
-		 *  was received.
-		 *
-		 * Note: We must not issue a message to the console, if the
-		 *       unsolicited interrupt applies to the console device
-		 *       itself !
-		 */
-#if CONFIG_DEBUG_IO
-		if (     ( irq != cons_dev                 )
-			 && !( stctl & SCSW_STCTL_ALERT_STATUS )
-			 &&  ( ioinfo[irq]->ui.flags.busy == 0  ) )
-		{
-	      char buffer[80];
-
-			printk( "Unsolicited interrupt received for device %04X on subchannel %04X\n"
-				" ... device status : %02X subchannel status : %02X\n",
-				ioinfo[irq]->devstat.devno,
-				irq,
-				ioinfo[irq]->devstat.dstat,
-				ioinfo[irq]->devstat.cstat);
-
-   	   sprintf( buffer, "s390_process_IRQ(%04X) - irb for "
-			         "device %04X, ending_status %d\n",
-			         irq,
-			         ioinfo[irq]->devstat.devno,
-		   	      ending_status);
-
-			s390_displayhex( buffer,
-			                 &(ioinfo[irq]->devstat.ii.irb) ,
-			                 sizeof(irb_t));
-
-		} /* endif */
-
-		/*
-		 * take fast exit if no handler is available
-		 */
-		if ( !action )
-			return( ending_status );     		
-
-#endif
-		/*
-		 * Check whether we must issue a SENSE CCW ourselves if there is no
-		 *  concurrent sense facility installed for the subchannel.
-		 *
-		 * Note: We should check for ioinfo[irq]->ui.flags.consns but VM
-		 *       violates the ESA/390 architecture and doesn't present an
-		 *       operand exception for virtual devices without concurrent
-		 *       sense facility available/supported when enabling the
-       *       concurrent sense facility.
-		 */
-		if (    (    ( ioinfo[irq]->devstat.ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK )
-			       && ( !issense                                                     ) )
-           || ( ioinfo[irq]->ui.flags.delsense && ending_status                     ) )
-		{
-			int            ret_io;
-			ccw1_t        *s_ccw  = &ioinfo[irq]->senseccw;
-			unsigned long  s_flag = 0;
-
-         if ( ending_status )
-         {
-				/*
-				 * We copy the current status information into the device driver
-				 *  status area. Then we can use the local devstat area for device
-				 *  sensing. When finally calling the IRQ handler we must not overlay
-				 *  the original device status but copy the sense data only.
-				 */
-				memcpy( action->dev_id,
-				        &(ioinfo[irq]->devstat),
-				        sizeof( devstat_t) );
-
-				s_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
-				s_ccw->cda      = (__u32)virt_to_phys( ioinfo[irq]->devstat.ii.sense.data);
-				s_ccw->count    = SENSE_MAX_COUNT;
-				s_ccw->flags    = CCW_FLAG_SLI;
-
-				/*
-				 * If free_irq() or a sync do_IO/s390_start_IO() is in
-				 *  process we have to sense synchronously
-				 */
-				if ( ioinfo[irq]->ui.flags.unready || ioinfo[irq]->ui.flags.syncio )
-				{
-					s_flag = DOIO_WAIT_FOR_INTERRUPT;
-
-				} /* endif */
-
-				/*
-				 * Reset status info
-				 *
-				 * It does not matter whether this is a sync. or async.
-				 *  SENSE request, but we have to assure we don't call
-				 *  the irq handler now, but keep the irq in busy state.
-				 *  In sync. mode s390_process_IRQ() is called recursively,
-				 *  while in async. mode we re-enter do_IRQ() with the
-				 *  next interrupt.
-				 *
-				 * Note : this may be a delayed sense request !
-				 */
-				allow4handler                  = 0;
-
-				ioinfo[irq]->ui.flags.fast     = 0;
-				ioinfo[irq]->ui.flags.repall   = 0;
-				ioinfo[irq]->ui.flags.w4final  = 0;
-				ioinfo[irq]->ui.flags.delsense = 0;
-
-				ioinfo[irq]->devstat.cstat     = 0;
-				ioinfo[irq]->devstat.dstat     = 0;
-				ioinfo[irq]->devstat.rescnt    = SENSE_MAX_COUNT;
-
-				ioinfo[irq]->ui.flags.w4sense  = 1;
-			
-				ret_io = s390_start_IO( irq,
-				                        s_ccw,
-				                        0xE2C5D5E2,  // = SENSe
-				                        0,           // n/a
-				                        s_flag);
-			}
-			else
-			{
-				/*
-				 * we received an Unit Check but we have no final
-				 *  status yet, therefore we must delay the SENSE
-				 *  processing. However, we must not report this
-				 *  intermediate status to the device interrupt
-				 *  handler.
-				 */
-				ioinfo[irq]->ui.flags.fast     = 0;
-				ioinfo[irq]->ui.flags.repall   = 0;
-
-				ioinfo[irq]->ui.flags.delsense = 1;
-				allow4handler                  = 0;
-
-			} /* endif */
-
-		} /* endif */
-
-		/*
-		 * we allow for the device action handler if .
-		 *  - we received ending status
-		 *  - the action handler requested to see all interrupts
-		 *  - we received a PCI
-		 *  - fast notification was requested (primary status)
-		 *  - unsollicited interrupts
-		 *
-		 */
-		if ( allow4handler )
-		{
-			allow4handler =    ending_status
-			   || ( ioinfo[irq]->ui.flags.repall                                      )
-			   || ( ioinfo[irq]->devstat.ii.irb.scsw.cstat & SCHN_STAT_PCI            )
-				|| ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) )
-				|| ( ioinfo[irq]->ui.flags.oper == 0                                   );
-
-		} /* endif */
-
-		/*
-		 * We used to copy the device status information right before
-		 *  calling the device action handler. However, in status
-		 *  pending situations during do_IO() or halt_IO(), as well as
-		 *  enable_subchannel/disable_subchannel processing we must
-		 *  synchronously return the status information and must not
-		 *  call the device action handler.
-		 *
-		 */
-		if ( allow4handler )
-		{
-			/*
-			 * if we were waiting for sense data we copy the sense
-			 *  bytes only as the original status information was
-			 *  saved prior to sense already.
-			 */
-			if ( ioinfo[irq]->ui.flags.w4sense )
-			{
-				int sense_count = SENSE_MAX_COUNT-ioinfo[irq]->devstat.rescnt;
-
-#if CONFIG_DEBUG_IO
-      if ( irq != cons_dev )
-         printk( "s390_process_IRQ( %04X ) : "
-                 "BASIC SENSE bytes avail %d\n",
-                 irq, sense_count );
-#endif
-				ioinfo[irq]->ui.flags.w4sense          = 0;
-				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FLAG_SENSE_AVAIL;
-				((devstat_t *)(action->dev_id))->scnt  = sense_count;
-
-				if ( sense_count >= 0 )
-				{
-					memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data,
-					        &(ioinfo[irq]->devstat.ii.sense.data),
-					        sense_count);
-				}
-				else
-				{
-#if 1
-					panic( "s390_process_IRQ(%04x) encountered "
-					       "negative sense count\n",
-					       irq);
-#else
-					printk( KERN_CRIT"s390_process_IRQ(%04x) encountered "
-					        "negative sense count\n",
-					        irq);
-#endif
-				} /* endif */
-			}
-			else
-			{
-				memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );
-
-			}  /* endif */
-
-      } /* endif */
-
-		/*
-		 * for status pending situations other than deferred interrupt
-		 *  conditions detected by s390_process_IRQ() itself we must not
-		 *  call the handler. This will synchronously be reported back
-		 *  to the caller instead, e.g. when detected during do_IO().
-		 */
-		if ( ioinfo[irq]->ui.flags.s_pend || ioinfo[irq]->ui.flags.unready )
-			allow4handler = 0;
-
-		/*
-		 * Call device action handler if applicable
-		 */
-		if ( allow4handler )
-		{
-
-			/*
-			 *  We only reset the busy condition when we are sure that no further
-			 *   interrupt is pending for the current I/O request (ending_status).
-			 */
-			if ( ending_status || !ioinfo[irq]->ui.flags.oper )
-			{
-				ioinfo[irq]->ui.flags.oper     = 1;  /* dev IS oper */
-
-				ioinfo[irq]->ui.flags.busy     = 0;
-				ioinfo[irq]->ui.flags.doio     = 0;
-				ioinfo[irq]->ui.flags.haltio   = 0;
-				ioinfo[irq]->ui.flags.fast     = 0;
-				ioinfo[irq]->ui.flags.repall   = 0;
-				ioinfo[irq]->ui.flags.w4final  = 0;
-
-				ioinfo[irq]->devstat.flag             |= DEVSTAT_FINAL_STATUS;
-				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FINAL_STATUS;
-
-				action->handler( irq, action->dev_id, &regs);
-
-				//
-				// reset intparm after final status or we will badly present unsolicited
-				//  interrupts with a intparm value possibly no longer valid.
-				//
-				ioinfo[irq]->devstat.intparm   = 0;
-
-				//
-				// Was there anything queued ? Start the pending channel program
-				//  if there is one.
-				//
-				if ( ioinfo[irq]->ui.flags.doio_q )
-				{
-					int ret;
-
-					ret = s390_start_IO( irq,
-							               ioinfo[irq]->qcpa,
-							               ioinfo[irq]->qintparm,
-							               ioinfo[irq]->qlpm,
-							               ioinfo[irq]->qflag);
-
-					ioinfo[irq]->ui.flags.doio_q = 0;
-
-					/*
-					 * If s390_start_IO() failed call the device's interrupt
-					 *  handler, the IRQ related devstat area was setup by
-					 *  s390_start_IO() accordingly already (status pending
-					 *  condition).
-					 */
-					if ( ret )
-					{
-						action->handler( irq, action->dev_id, &regs);
-
-					} /* endif */
-
-				} /* endif */
-
-			}
-			else
-			{
-				ioinfo[irq]->ui.flags.w4final = 1;
-				action->handler( irq, action->dev_id, &regs);
-
-			} /* endif */
-
-		} /* endif */
-
-		break;
-
-	case 3:      /* device not operational */
-
-		ioinfo[irq]->ui.flags.oper    = 0;
-
-		ioinfo[irq]->ui.flags.busy    = 0;
-		ioinfo[irq]->ui.flags.doio    = 0;
-		ioinfo[irq]->ui.flags.haltio  = 0;
-
-		ioinfo[irq]->devstat.cstat    = 0;
-		ioinfo[irq]->devstat.dstat    = 0;
-		ioinfo[irq]->devstat.flag    |= DEVSTAT_NOT_OPER;
-		ioinfo[irq]->devstat.flag    |= DEVSTAT_FINAL_STATUS;
-
-		/*
-		 * When we find a device "not oper" we save the status
-		 *  information into the device status area and call the
-		 *  device specific interrupt handler.
-		 *
-		 * Note: currently we don't have any way to reenable
-		 *       the device unless an unsolicited interrupt
-		 *       is presented. We don't check for spurious
-		 *       interrupts on "not oper" conditions.
-		 */
-
-		if (    ( ioinfo[irq]->ui.flags.fast    )
-		     && ( ioinfo[irq]->ui.flags.w4final ) )
-		{
-			/*
-			 * If a new request was queued already, we have
-			 *  to simulate the "not oper" status for the
-			 *  queued request by switching the "intparm" value
-			 *  and notify the interrupt handler.
-			 */
-			if ( ioinfo[irq]->ui.flags.doio_q )
-			{
-				ioinfo[irq]->devstat.intparm = ioinfo[irq]->qintparm;
-
-			} /* endif */
-
-		} /* endif */
-
-		ioinfo[irq]->ui.flags.fast    = 0;
-		ioinfo[irq]->ui.flags.repall  = 0;
-		ioinfo[irq]->ui.flags.w4final = 0;
-
-		memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );
-
-		ioinfo[irq]->devstat.intparm  = 0;
-
-		if ( !ioinfo[irq]->ui.flags.s_pend )
-			action->handler( irq, action->dev_id, &regs);
-
-		ending_status    = 1;
-
-		break;
-
-	} /* endswitch */
-
-	return( ending_status );
-}
-
-/*
- * Set the special i/o-interruption sublass 7 for the
- *  device specified by parameter irq. There can only
- *  be a single device been operated on this special
- *  isc. This function is aimed being able to check
- *  on special device interrupts in disabled state,
- *  without having to delay I/O processing (by queueing)
- *  for non-console devices.
- *
- * Setting of this isc is done by set_cons_dev(), while
- *  reset_cons_dev() resets this isc and re-enables the
- *  default isc3 for this device. wait_cons_dev() allows
- *  to actively wait on an interrupt for this device in
- *  disabed state. When the interrupt condition is
- *  encountered, wait_cons_dev(9 calls do_IRQ() to have
- *  the console device driver processing the interrupt.
- */
-int set_cons_dev( int irq )
-{
-	int           ccode;
-	unsigned long cr6 __attribute__ ((aligned (8)));
-	int           rc = 0;
-
-	if ( cons_dev != -1  )
-	{
-		rc = -EBUSY;
-	}
-	else if ( (irq > highest_subchannel) || (irq < 0) )
-	{
-		rc = -ENODEV;
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-	else
-	{
-		/*
-		 * modify the indicated console device to operate
-		 *  on special console interrupt sublass 7
-		 */
-		ccode = stsch( irq, &(ioinfo[irq]->schib) );
-
-		if (ccode)
-		{
-			rc                         = -ENODEV;
-			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
-		}
-		else
-		{
-			ioinfo[irq]->schib.pmcw.isc = 7;
-
-			ccode = msch( irq, &(ioinfo[irq]->schib) );
-
-			if (ccode)
-			{
-				rc = -EIO;
-			}
-			else
-			{
-				cons_dev = irq;
-
-				/*
-				 * enable console I/O-interrupt sublass 7
-				 */
-				asm volatile ("STCTL 6,6,%0": "=m" (cr6));
-				cr6 |= 0x01000000;
-				asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-			} /* endif */
-
-		} /* endif */
-
-	} /* endif */
-
-	return( rc);
-}
-
-int reset_cons_dev( int irq)
-{
-	int     rc = 0;
-	int     ccode;
-	long    cr6 __attribute__ ((aligned (8)));
-
-	if ( cons_dev != -1  )
-	{
-		rc = -EBUSY;
-	}
-	else if ( (irq > highest_subchannel) || (irq < 0) )
-	{
-		rc = -ENODEV;
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-	else
-	{
-		/*
-		 * reset the indicated console device to operate
-		 *  on default console interrupt sublass 3
-		 */
-		ccode = stsch( irq, &(ioinfo[irq]->schib) );
-
-		if (ccode)
-		{
-			rc                         = -ENODEV;
-			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
-		}
-		else
-		{
-
-			ioinfo[irq]->schib.pmcw.isc = 3;
-
-			ccode = msch( irq, &(ioinfo[irq]->schib) );
-
-			if (ccode)
-			{
-				rc = -EIO;
-			}
-			else
-			{
-				cons_dev = -1;
-
-				/*
-				 * disable special console I/O-interrupt sublass 7
-				 */
-				asm volatile ("STCTL 6,6,%0": "=m" (cr6));
-				cr6 &= 0xFEFFFFFF;
-				asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-			} /* endif */
-
-		} /* endif */
-
-	} /* endif */
-
-	return( rc);
-}
-
-int wait_cons_dev( int irq )
-{
-	int              rc = 0;
-	long             save_cr6;
-
-	if ( irq == cons_dev )
-	{
-
-		/*
-		 * before entering the spinlock we may already have
-		 *  processed the interrupt on a different CPU ...
-		 */
-		if ( ioinfo[irq]->ui.flags.busy == 1 )
-		{
-			long cr6 __attribute__ ((aligned (8)));
-
-			/*
-			 * disable all, but isc 7 (console device)
-			 */
-			asm volatile ("STCTL 6,6,%0": "=m" (cr6));
-			save_cr6  = cr6;
-			cr6      &= 0x01FFFFFF;
-			asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-			do {
-				tpi_info_t tpi_info;
-				if (tpi(&tpi_info) == 1) {
-					s390_process_IRQ( tpi_info.irq );
-				} else {
-					s390irq_spin_unlock(irq);
-					tod_wait(100);
-					s390irq_spin_lock(irq);
-				}
-				eieio();
-			} while (ioinfo[irq]->ui.flags.busy == 1);
-
-			/*
-			 * restore previous isc value
-			 */
-			asm volatile ("STCTL 6,6,%0": "=m" (cr6));
-			cr6 = save_cr6;
-			asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-		} /* endif */
-
-	}
-	else
-	{
-		rc = EINVAL;
-
-	} /* endif */
-
-
-	return(rc);
-}
-
-
-int enable_cpu_sync_isc( int irq )
-{
-	int             ccode;
-	long            cr6 __attribute__ ((aligned (8)));
-
-	int             count = 0;
-	int             rc    = 0;
-
-	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )
-	{
-		ccode = stsch( irq, &(ioinfo[irq]->schib) );
-
-		if ( !ccode )
-		{
-			ioinfo[irq]->schib.pmcw.isc = 5;
-
-			do
-			{
-				ccode = msch( irq, &(ioinfo[irq]->schib) );
-
-				if (ccode == 0 )
-				{
-					/*
-					 * enable interrupt subclass in CPU
-					 */
-					asm volatile ("STCTL 6,6,%0": "=m" (cr6));
-					cr6 |= 0x04000000;  // enable sync isc 5
-					cr6 &= 0xEFFFFFFF;  // disable standard isc 3
-					asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-				}
-				else if (ccode == 3)
-				{
-					rc = -ENODEV;  // device not-oper - very unlikely
-
-				}
-				else if (ccode == 2)
-				{
-					rc = -EBUSY;   // device busy - should not happen
-
-				}
-				else if (ccode == 1)
-				{
-					//
-					// process pending status
-					//
-			      ioinfo[irq]->ui.flags.s_pend = 1;
-
-					s390_process_IRQ( irq );
-
-			      ioinfo[irq]->ui.flags.s_pend = 0;
-
-					count++;
-
-				} /* endif */
-
-			} while ( ccode == 1 && count < 3 );
-
-			if ( count == 3)
-			{
-				rc = -EIO;
-
-			} /* endif */
-		}
-		else
-		{
-			rc = -ENODEV;     // device is not-operational
-
-		} /* endif */
-	}
-	else
-	{
-		rc = -EINVAL;
-
-	} /* endif */
-
-	return( rc);
-}
-
-int disable_cpu_sync_isc( int irq)
-{
-	int     rc = 0;
-	int     ccode;
-	long    cr6 __attribute__ ((aligned (8)));
-
-	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )
-	{
-		ccode = stsch( irq, &(ioinfo[irq]->schib) );
-
-		ioinfo[irq]->schib.pmcw.isc = 3;
-
-		ccode = msch( irq, &(ioinfo[irq]->schib) );
-
-		if (ccode)
-		{
-			rc = -EIO;
-		}
-		else
-		{
-
-			/*
-			 * enable interrupt subclass in CPU
-			 */
-			asm volatile ("STCTL 6,6,%0": "=m" (cr6));
-			cr6 &= 0xFBFFFFFF;             // disable sync isc 5
-			cr6 |= 0x10000000;             // enable standard isc 3
-			asm volatile ("LCTL 6,6,%0":: "m" (cr6):"memory");
-
-		} /* endif */
-
-	}
-	else
-	{
-		rc = -EINVAL;
-
-	} /* endif */
-
-	return( rc);
-}
-
-//
-// Input :
-//   devno - device number
-//   ps    - pointer to sense ID data area
-//
-// Output : none
-//
-void VM_virtual_device_info( __u16      devno,
-                             senseid_t *ps )
-{
-	diag210_t  diag_data;
-	int        ccode;
-
-	int        error = 0;
-
-	diag_data.vrdcdvno = devno;
-	diag_data.vrdclen  = sizeof( diag210_t);
-	ccode              = diag210( (diag210_t *)virt_to_phys( &diag_data ) );
-	ps->reserved       = 0xff;
-
-	switch (diag_data.vrdcvcla) {
-	case 0x80:
-
-		switch (diag_data.vrdcvtyp) {
-		case 00:
-
-			ps->cu_type   = 0x3215;
-
-			break;
-
-		default:
-
-			error = 1;
-
-			break;
-
-		} /* endswitch */
-
-		break;
-
-	case 0x40:
-
-		switch (diag_data.vrdcvtyp) {
-		case 0xC0:
-
-			ps->cu_type   = 0x5080;
-
-			break;
-
-		case 0x80:
-
-			ps->cu_type   = 0x2250;
-
-			break;
-
-		case 0x04:
-
-			ps->cu_type   = 0x3277;
-
-			break;
-
-		case 0x01:
-
-			ps->cu_type   = 0x3278;
-
-			break;
-
-		default:
-
-			error = 1;
-
-			break;
-
-		} /* endswitch */
-
-		break;
-
-	case 0x20:
-
-		switch (diag_data.vrdcvtyp) {
-		case 0x84:
-
-			ps->cu_type   = 0x3505;
-
-			break;
-
-		case 0x82:
-
-			ps->cu_type   = 0x2540;
-
-			break;
-
-		case 0x81:
-
-			ps->cu_type   = 0x2501;
-
-			break;
-
-		default:
-
-			error = 1;
-
-			break;
-
-		} /* endswitch */
-
-		break;
-
-	case 0x10:
-
-		switch (diag_data.vrdcvtyp) {
-		case 0x84:
-
-			ps->cu_type   = 0x3525;
-
-			break;
-
-		case 0x82:
-
-			ps->cu_type   = 0x2540;
-
-			break;
-
-		case 0x4F:
-		case 0x4E:
-		case 0x48:
-
-			ps->cu_type   = 0x3820;
-
-			break;
-
-		case 0x4D:
-		case 0x49:
-		case 0x45:
-
-			ps->cu_type   = 0x3800;
-
-			break;
-
-		case 0x4B:
-
-			ps->cu_type   = 0x4248;
-
-			break;
-
-		case 0x4A:
-
-			ps->cu_type   = 0x4245;
-
-			break;
-
-		case 0x47:
-
-			ps->cu_type   = 0x3262;
-
-			break;
-
-		case 0x43:
-
-			ps->cu_type   = 0x3203;
-
-			break;
-
-		case 0x42:
-
-			ps->cu_type   = 0x3211;
-
-			break;
-
-		case 0x41:
-
-			ps->cu_type   = 0x1403;
-
-			break;
-
-		default:
-
-			error = 1;
-
-			break;
-
-		} /* endswitch */
-
-		break;
-
-	case 0x08:
-
-		switch (diag_data.vrdcvtyp) {
-		case 0x82:
-
-			ps->cu_type   = 0x3422;
-
-			break;
-
-		case 0x81:
-
-			ps->cu_type   = 0x3490;
-
-			break;
-
-		case 0x10:
-
-			ps->cu_type   = 0x3420;
-
-			break;
-
-		case 0x02:
-
-			ps->cu_type   = 0x3430;
-
-			break;
-
-		case 0x01:
-
-			ps->cu_type   = 0x3480;
-
-			break;
-
-		case 0x42:
-
-			ps->cu_type   = 0x3424;
-
-			break;
-
-		case 0x44:
-
-			ps->cu_type   = 0x9348;
-
-			break;
-
-		default:
-
-			error = 1;
-
-			break;
-
-		} /* endswitch */
-
-		break;
-
-	default:
-
-		error = 1;
-
-		break;
-
-	} /* endswitch */
-
-	if ( error )
-	{printk( "DIAG X'210' for device %04X returned (cc = %d): vdev class : %02X, "
-			"vdev type : %04X \n ...  rdev class : %02X, rdev type : %04X, rdev model: %02X\n",
-			devno,
-			ccode,
-			diag_data.vrdcvcla,
-			diag_data.vrdcvtyp,
-			diag_data.vrdcrccl,
-			diag_data.vrdccrty,
-			diag_data.vrdccrmd );
-
-	} /* endif */
-
-}
-
-/*
- * This routine returns the characteristics for the device
- *  specified. Some old devices might not provide the necessary
- *  command code information during SenseID processing. In this
- *  case the function returns -EINVAL. Otherwise the function
- *  allocates a decice specific data buffer and provides the
- *  device characteristics together with the buffer size. Its
- *  the callers responability to release the kernel memory if
- *  not longer needed. In case of persistent I/O problems -EBUSY
- *  is returned.
- *
- *  The function may be called enabled or disabled. However, the
- *   caller must have locked the irq it is requesting data for.
- *
- * Note : It would have been nice to collect this information
- *         during init_IRQ() processing but this is not possible
- *
- *         a) without statically pre-allocation fixed size buffers
- *            as virtual memory management isn't available yet.
- *
- *         b) without unnecessarily increase system startup by
- *            evaluating devices eventually not used at all.
- */
-int read_dev_chars( int irq, void **buffer, int length )
-{
-	unsigned int  flags;
-	ccw1_t       *rdc_ccw;
-	devstat_t     devstat;
-	char         *rdc_buf;
-	int           devflag;
-
-	int           ret      = 0;
-	int           emulated = 0;
-	int           retry    = 5;
-
-	if ( !buffer || !length )
-	{
-		return( -EINVAL );
-
-	} /* endif */
-
-	if ( (irq > highest_subchannel) || (irq < 0 ) )
-	{
-	return( -ENODEV );
-
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-   }
-
-	if ( ioinfo[irq]->ui.flags.oper == 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	/*
-	 * Before playing around with irq locks we should assure
-	 *   running disabled on (just) our CPU. Sync. I/O requests
-    *   also require to run disabled.
-	 *
-	 * Note : as no global lock is required, we must not use
-	 *        cli(), but __cli() instead.  	
-	 */
-	__save_flags(flags);
-	__cli();
-
-	rdc_ccw = &ioinfo[irq]->senseccw;
-
-	if ( !ioinfo[irq]->ui.flags.ready )
-	{
-		ret = request_irq( irq,
-		                   init_IRQ_handler,
-		                   0, "RDC", &devstat );
-
-		if ( !ret )
-		{
-			emulated = 1;
-
-		} /* endif */
-
-	} /* endif */
-
-	if ( !ret )
-	{
-		if ( ! *buffer )
-		{
-			rdc_buf  = kmalloc( length, GFP_KERNEL);
-		}
-		else
-		{
-			rdc_buf = *buffer;
-
-		} /* endif */
-
-		if ( !rdc_buf )
-		{
-			ret = -ENOMEM;
-		}
-		else
-		{
-			do
-			{
-				rdc_ccw->cmd_code = CCW_CMD_RDC;
-				rdc_ccw->cda      = (__u32)virt_to_phys( rdc_buf );
-				rdc_ccw->count    = length;
-				rdc_ccw->flags    = CCW_FLAG_SLI;
-
-				ret = s390_start_IO( irq,
-				                     rdc_ccw,
-				                     0x00524443, // RDC
-				                     0,          // n/a
-				                     DOIO_WAIT_FOR_INTERRUPT );
-				retry--;
-				devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag;
-
-			} while (    ( retry                                     )
-			          && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) );
-
-		} /* endif */
-
-		if ( !retry )
-		{
-			ret = -EBUSY;
-
-		} /* endif */
-
-		__restore_flags(flags);
-
-		/*
-		 * on success we update the user input parms
-		 */
-		if ( !ret )
-		{
-			*buffer = rdc_buf;
-
-		} /* endif */
-
-		if ( emulated )
-		{
-			free_irq( irq, &devstat);
-
-		} /* endif */
-
-	} /* endif */
-
-	return( ret );
-}
-
-/*
- *  Read Configuration data
- */
-int read_conf_data( int irq, void **buffer, int *length )
-{
-   int          found   = 0;
-   int          ciw_cnt = 0;
-   unsigned int flags;
-
-   int          ret = 0;
-
-   if ( (irq > highest_subchannel) || (irq < 0 ) )
-   {
-      return( -ENODEV );
-   }
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-
-   } /* endif */
-
-   if ( ioinfo[irq]->ui.flags.oper == 0 )
-   {
-      return( -ENODEV );
-
-   } /* endif */
-
-   /*
-    * scan for RCD command in extended SenseID data
-    */
-   for ( ; (found == 0) && (ciw_cnt < 62); ciw_cnt++ )
-   {
-      if ( ioinfo[irq]->senseid.ciw[ciw_cnt].ct == CIW_TYPE_RCD )
-      {
-         found = 1;
-      	break;
-      } /* endif */
-
-   } /* endfor */
-
-	if ( found )
-	{
-		ccw1_t    *rcd_ccw = &ioinfo[irq]->senseccw;
-		devstat_t  devstat;
-		char      *rcd_buf;
-		int        devflag;
-
-		int        emulated = 0;
-		int        retry    = 5;
-
-		__save_flags(flags);
-		__cli();
-
-		if ( !ioinfo[irq]->ui.flags.ready )
-		{
-			ret = request_irq( irq,
-			                   init_IRQ_handler,
-			                   0, "RCD", &devstat );
-
-			if ( !ret )
-			{
-				emulated = 1;
-
-			} /* endif */
-
-		} /* endif */
-
-		if ( !ret )
-		{
-			rcd_buf = kmalloc( ioinfo[irq]->senseid.ciw[ciw_cnt].count,
-			                   GFP_KERNEL);
-
-			do
-			{
-				rcd_ccw->cmd_code = ioinfo[irq]->senseid.ciw[ciw_cnt].cmd;
-				rcd_ccw->cda      = (__u32)virt_to_phys( rcd_buf );
-				rcd_ccw->count    = ioinfo[irq]->senseid.ciw[ciw_cnt].count;
-				rcd_ccw->flags    = CCW_FLAG_SLI;
-
-				ret = s390_start_IO( irq,
-				                     rcd_ccw,
-				                     0x00524344,  // == RCD
-				                     0,           // n/a
-				                     DOIO_WAIT_FOR_INTERRUPT );
-
-				retry--;
-
-				devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag;
-
-			} while (    ( retry                                     )
-			          && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) );
-
-			if ( !retry )
-				ret = -EBUSY;
-
-			__restore_flags(flags);
-
-		} /* endif */
-
-		/*
-		 * on success we update the user input parms
-		 */
-		if ( !ret )
-		{
-			*length = ioinfo[irq]->senseid.ciw[ciw_cnt].count;
-			*buffer = rcd_buf;
-
-		} /* endif */
-
-		if ( emulated )
-			free_irq( irq, &devstat);
-	}
-	else
-	{
-		ret = -EINVAL;
-
-	} /* endif */
-
-	return( ret );
-
-}
-
-int get_dev_info( int irq, dev_info_t * pdi)
-{
-	return( get_dev_info_by_irq( irq, pdi));
-}
-
-static int __inline__ get_next_available_irq( ioinfo_t *pi)
-{
-	int ret_val;
-
-	while ( TRUE )
-	{
-		if ( pi->ui.flags.oper )
-		{
-			ret_val = pi->irq;
-			break;
-		}
-		else
-		{
-			pi = pi->next;
-
-			//
-			// leave at end of list unconditionally
-			//
-			if ( pi == NULL )
-			{
-				ret_val = -ENODEV;
-				break;
-			}
-
-		} /* endif */
-
-	} /* endwhile */
-
-	return ret_val;
-}
-
-
-int get_irq_first( void )
-{
-   int ret_irq;
-
-	if ( ioinfo_head )
-	{
-		if ( ioinfo_head->ui.flags.oper )
-		{
-			ret_irq = ioinfo_head->irq;
-		}
-		else if ( ioinfo_head->next )
-		{
-			ret_irq = get_next_available_irq( ioinfo_head->next );
-
-		}
-		else
-		{
-			ret_irq = -ENODEV;
-   	
-		} /* endif */
-	}
-	else
-	{
-		ret_irq = -ENODEV;
-
-	} /* endif */
-
-	return ret_irq;
-}
-
-int get_irq_next( int irq )
-{
-	int ret_irq;	
-
-	if ( ioinfo[irq] != INVALID_STORAGE_AREA )
-	{
-		if ( ioinfo[irq]->next )
-		{
-			if ( ioinfo[irq]->next->ui.flags.oper )
-			{
-				ret_irq = ioinfo[irq]->next->irq;
-			}
-			else
-			{
-				ret_irq = get_next_available_irq( ioinfo[irq]->next );
-
-			} /* endif */
-		}
-		else
-		{
-			ret_irq = -ENODEV;     	
-
-		} /* endif */
-	}
-	else
-	{
-		ret_irq = -EINVAL;
-
-	} /* endif */
-
-	return ret_irq;
-}
-
-int get_dev_info_by_irq( int irq, dev_info_t *pdi)
-{
-
-	if ( irq > highest_subchannel || irq < 0 )
-	{
-		return -ENODEV;
-	}
-	else if ( pdi == NULL )
-	{
-		return -EINVAL;
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-	}
-	else
-	{
-		pdi->devno = ioinfo[irq]->schib.pmcw.dev;
-		pdi->irq   = irq;
-
-		if ( ioinfo[irq]->ui.flags.oper )
-		{
-			pdi->status = 0;
-			memcpy( &(pdi->sid_data),
-			        &ioinfo[irq]->senseid,
-			        sizeof( senseid_t));
-		}
-		else
-		{
-			pdi->status = DEVSTAT_NOT_OPER;
-			memcpy( &(pdi->sid_data),
-			        '\0',
-			        sizeof( senseid_t));
-			pdi->sid_data.cu_type = 0xFFFF;
-
-		} /* endif */
-
-		if ( ioinfo[irq]->ui.flags.ready )
-			pdi->status |= DEVSTAT_DEVICE_OWNED;
-
-		return 0;
-
-	} /* endif */
-
-}
-
-
-int get_dev_info_by_devno( __u16 devno, dev_info_t *pdi)
-{
-	int i;
-	int rc = -ENODEV;
-
-	if ( devno > 0x0000ffff )
-	{
-		return -ENODEV;
-	}
-	else if ( pdi == NULL )
-	{
-		return -EINVAL;
-	}
-	else
-	{
-
-		for ( i=0; i <= highest_subchannel; i++ )
-		{
-
-			if (    ioinfo[i] != INVALID_STORAGE_AREA
-			     && ioinfo[i]->schib.pmcw.dev == devno )
-			{
-				if ( ioinfo[i]->ui.flags.oper )
-				{
-					pdi->status = 0;
-					pdi->irq    = i;
-					pdi->devno  = devno;
-
-					memcpy( &(pdi->sid_data),
-					        &ioinfo[i]->senseid,
-					        sizeof( senseid_t));
-				}
-				else
-				{
-					pdi->status = DEVSTAT_NOT_OPER;
-					pdi->irq    = i;
-					pdi->devno  = devno;
-	
-					memcpy( &(pdi->sid_data), '\0', sizeof( senseid_t));
-					pdi->sid_data.cu_type = 0xFFFF;
-
-				} /* endif */
-
-				if ( ioinfo[i]->ui.flags.ready )
-					pdi->status |= DEVSTAT_DEVICE_OWNED;
-
-				rc = 0; /* found */
-				break;
-
-			} /* endif */
-
-		} /* endfor */
-
-		return( rc);
-
-	} /* endif */
-
-}
-
-int get_irq_by_devno( __u16 devno )
-{
-	int i;
-	int rc = -1;
-
-	if ( devno <= 0x0000ffff )
-	{
-		for ( i=0; i <= highest_subchannel; i++ )
-		{
-			if (    (ioinfo[i] != INVALID_STORAGE_AREA )
-			     && (ioinfo[i]->schib.pmcw.dev == devno)
-			     && (ioinfo[i]->schib.pmcw.dnv == 1    ) )
-			{
-				rc = i;
-				break;
-
-			} /* endif */
-
-		} /* endfor */
-	
-	} /* endif */
-
-	return( rc);
-}
-
-unsigned int get_devno_by_irq( int irq )
-{
-
-	if (    ( irq > highest_subchannel            )
-	     || ( irq < 0                             )
-	     || ( ioinfo[irq] == INVALID_STORAGE_AREA ) )
-	{
-		return -1;
-	
-	} /* endif */
-
-	/*
-	 * we don't need to check for the device be operational
-	 *  as the initial STSCH will always present the device
-	 *  number defined by the IOCDS regardless of the device
-	 *  existing or not. However, there could be subchannels
-	 *  defined who's device number isn't valid ...
-	 */
-	if ( ioinfo[irq]->schib.pmcw.dnv )
-		return( ioinfo[irq]->schib.pmcw.dev );
-	else
-		return -1;
-}
-
-/*
- * s390_device_recognition
- *
- * Used for system wide device recognition. Issues the device
- *  independant SenseID command to obtain info the device type.
- *
- */
-void s390_device_recognition( void)
-{
-
-	int irq = 0; /* let's start with subchannel 0 ... */
-
-	do
-	{
-		/*
-		 * We issue the SenseID command on I/O subchannels we think are
-		 *  operational only.
-		 */
-		if (    ( ioinfo[irq] != INVALID_STORAGE_AREA )	
-		     && ( ioinfo[irq]->schib.pmcw.st == 0     )
-		     && ( ioinfo[irq]->ui.flags.oper == 1     ) )
-		{
-			s390_SenseID( irq, &ioinfo[irq]->senseid );
-
-		} /* endif */
-
-		irq ++;
-
-	} while ( irq <= highest_subchannel );
-
-}
-
-
-/*
- * s390_search_devices
- *
- * Determines all subchannels available to the system.
- *
- */
-void s390_process_subchannels( void)
-{
-	int   isValid;
-	int   irq = 0;   /* Evaluate all subchannels starting with 0 ... */
-
-	do
-	{
-		isValid = s390_validate_subchannel( irq);
-
-		irq++;
-	
-  	} while ( isValid && irq < __MAX_SUBCHANNELS );
-
-	highest_subchannel = --irq;
-
-	printk( "\nHighest subchannel number detected: %u\n",
-	        highest_subchannel);
-}
-
-/*
- * s390_validate_subchannel()
- *
- * Process the subchannel for the requested irq. Returns 1 for valid
- *  subchannels, otherwise 0.
- */
-int s390_validate_subchannel( int irq )
-{
-
-	int      retry;     /* retry count for status pending conditions */
-	int      ccode;     /* condition code for stsch() only */
-	int      ccode2;    /* condition code for other I/O routines */
-	schib_t *p_schib;
-
-	/*
-	 * The first subchannel that is not-operational (ccode==3)
-	 *  indicates that there aren't any more devices available.
-	 */
-	if (    ( init_IRQ_complete                   )
-	     && ( ioinfo[irq] != INVALID_STORAGE_AREA ) )
-	{
-		p_schib = &ioinfo[irq]->schib;
-	}
-	else
-	{
-		p_schib = &init_schib;
-
-	} /* endif */
-
-	ccode = stsch( irq, p_schib);
-
-	if ( ccode == 0)
-	{
-		/*
-		 * ... just being curious we check for non I/O subchannels
-		 */
-		if ( p_schib->pmcw.st )
-		{
-			printk( "Subchannel %04X reports "
-			        "non-I/O subchannel type %04X\n",
-			        irq,
-			        p_schib->pmcw.st);
-
-			if ( ioinfo[irq] != INVALID_STORAGE_AREA )
-				ioinfo[irq]->ui.flags.oper = 0;
-
-		} /* endif */
-
-		if ( p_schib->pmcw.dnv )
-		{
-			if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-			{	
-
-				if ( !init_IRQ_complete )
-				{
-					ioinfo[irq] =
-					   (ioinfo_t *)alloc_bootmem( sizeof(ioinfo_t));
-				}
-				else
-				{
-					ioinfo[irq] =
-					   (ioinfo_t *)kmalloc( sizeof(ioinfo_t),
-				                           GFP_KERNEL );
-
-				} /* endif */
-
-				memset( ioinfo[irq], '\0', sizeof( ioinfo_t));
-				memcpy( &ioinfo[irq]->schib,
-			           &init_schib,
-			           sizeof( schib_t));
-				ioinfo[irq]->irq_desc.status  = IRQ_DISABLED;
-				ioinfo[irq]->irq_desc.handler = &no_irq_type;
-			
-				/*
-				 * We have to insert the new ioinfo element
-				 *  into the linked list, either at its head,
-				 *  its tail or insert it.
-				 */
-				if ( ioinfo_head == NULL )  /* first element */
-				{
-					ioinfo_head = ioinfo[irq];
-					ioinfo_tail = ioinfo[irq];
-				}
-				else if ( irq < ioinfo_head->irq ) /* new head */
-				{
-					ioinfo[irq]->next = ioinfo_head;
-					ioinfo_head->prev = ioinfo[irq];
-					ioinfo_head       = ioinfo[irq];
-				}
-				else if ( irq > ioinfo_tail->irq ) /* new tail */
-				{
-					ioinfo_tail->next = ioinfo[irq];
-					ioinfo[irq]->prev = ioinfo_tail;
-					ioinfo_tail       = ioinfo[irq];
-				}
-				else /* insert element */
-				{
-					ioinfo_t *pi = ioinfo_head;
-
-               do
-					{
-						if ( irq < pi->next->irq )
-						{
-							ioinfo[irq]->next = pi->next;
-							ioinfo[irq]->prev = pi;
-							pi->next->prev    = ioinfo[irq];
-							pi->next          = ioinfo[irq];
-							break;
-						
-						} /* endif */
-
-						pi = pi->next;
-
-					} while ( 1 );
-      	
-				} /* endif */
-
-			} /* endif */
-
-			// initialize some values ...	
-			ioinfo[irq]->ui.flags.pgid_supp = 1;
-
-			ioinfo[irq]->opm =    ioinfo[irq]->schib.pmcw.pam
-		                       & ioinfo[irq]->schib.pmcw.pom;
-
-			printk( "Detected device %04X on subchannel %04X"
-			        " - PIM = %02X, PAM = %02X, POM = %02X\n",
-			        ioinfo[irq]->schib.pmcw.dev,
-			        irq,
-			        ioinfo[irq]->schib.pmcw.pim,
-			        ioinfo[irq]->schib.pmcw.pam,
-			        ioinfo[irq]->schib.pmcw.pom);
-
-			/*
-			 * We should have at least one CHPID ...
-			 */
-			if (   ioinfo[irq]->schib.pmcw.pim 			
-			     & ioinfo[irq]->schib.pmcw.pam
-			     & ioinfo[irq]->schib.pmcw.pom )
-			{
-				ioinfo[irq]->ui.flags.oper = 0;
-	
-				/*
-				 * We now have to initially ...
-				 *  ... set "interruption sublass"
-				 *  ... enable "concurrent sense"
-				 *  ... enable "multipath mode" if more than one
-				 *        CHPID is available. This is done regardless
-				 *        whether multiple paths are available for us.
-				 *
-				 * Note : we don't enable the device here, this is temporarily
-				 *        done during device sensing below.
-				 */
-				ioinfo[irq]->schib.pmcw.isc     = 3; /* could be smth. else */
-				ioinfo[irq]->schib.pmcw.csense  = 1; /* concurrent sense */
-				ioinfo[irq]->schib.pmcw.ena     = 0; /* force disable it */
-				ioinfo[irq]->schib.pmcw.intparm =
-				                     ioinfo[irq]->schib.pmcw.dev;
-
-				if (    ( ioinfo[irq]->schib.pmcw.pim != 0    )
-				     && ( ioinfo[irq]->schib.pmcw.pim != 0x80 ) )
-				{
-					ioinfo[irq]->schib.pmcw.mp     = 1;     /* multipath mode */
-
-				} /* endif */
-
-				/*
-				 * initialize ioinfo structure
-			    */
-				ioinfo[irq]->irq             = irq;
-				ioinfo[irq]->ui.flags.busy   = 0;
-				ioinfo[irq]->ui.flags.ready  = 0;
-				ioinfo[irq]->ui.flags.oper   = 1;
-				ioinfo[irq]->devstat.intparm = 0;
-				ioinfo[irq]->devstat.devno   = ioinfo[irq]->schib.pmcw.dev;
-
-				retry = 5;
-
-				do
-				{
-					ccode2 = msch_err( irq, &ioinfo[irq]->schib);
-
-					switch (ccode2) {
-					case 0:  // successful completion
-						//
-						// concurrent sense facility available ...
-						//
-						ioinfo[irq]->ui.flags.consns = 1;
-						break;
-      	
-					case 1:  // status pending
-						//
-						// How can we have a pending status as device is
-						//  disabled for interrupts ? Anyway, clear it ...
-						//
-						tsch( irq, &(ioinfo[irq]->devstat.ii.irb) );
-						retry--;
-						break;
-   	
-					case 2:  // busy
-						retry--;
-						break;
-
-					case 3:  // not operational
-						ioinfo[irq]->ui.flags.oper = 0;
-						retry                      = 0;
-						break;
-
-					default:
-#define PGMCHK_OPERAND_EXC      0x15
-
-						if ( (ccode2 & PGMCHK_OPERAND_EXC) == PGMCHK_OPERAND_EXC )
-						{
-							/*
-							 * re-issue the modify subchannel without trying to
-							 *  enable the concurrent sense facility
-							 */
-							ioinfo[irq]->schib.pmcw.csense = 0;
-   	
-							ccode2 = msch_err( irq, &ioinfo[irq]->schib);
-
-							if ( ccode2 != 0 )
-							{
-								printk( " ... modify subchannel (2) failed with CC = %X\n",
-								        ccode2 );
-								ioinfo[irq]->ui.flags.oper = 0;
-							}
-							else
-							{
-								ioinfo[irq]->ui.flags.consns = 0;
-
-							} /* endif */
-						}
-						else
-						{
-							printk( " ... modify subchannel (1) failed with CC = %X\n",
-							        ccode2);
-							ioinfo[irq]->ui.flags.oper = 0;
-
-						} /* endif */
-   	
-						retry  = 0;
-						break;
-
-					} /* endswitch */
-
-				} while ( ccode2 && retry );
-
-				if ( (ccode2 < 3) && (!retry) )
-				{
-					printk( " ... msch() retry count for "
-					        "subchannel %04X exceeded, CC = %d\n",
-					        irq,
-					        ccode2);
-
-				} /* endif */
-
-			}
-			else
-			{
-				ioinfo[irq]->ui.flags.oper = 0;
-
-			} /* endif */
-
-		} /* endif */
-
-	} /* endif */
-
-	/*
-	 * indicate whether the subchannel is valid
-	 */
-	if ( ccode == 3)
-		return(0);
-	else
-		return(1);
-}
-
-/*
- * s390_SenseID
- *
- * Try to obtain the 'control unit'/'device type' information
- *  associated with the subchannel.
- *
- * The function is primarily meant to be called without irq
- *  action handler in place. However, it also allows for
- *  use with an action handler in place. If there is already
- *  an action handler registered assure it can handle the
- *  s390_SenseID() related device interrupts - interruption
- *  parameter used is 0x00E2C9C4 ( SID ).
- */
-int s390_SenseID( int irq, senseid_t *sid )
-{
-	ccw1_t     sense_ccw;   /* ccw area for SenseID command */
-   devstat_t  devstat;     /* required by request_irq() */
-
-   int        irq_ret = 0; /* return code */
-   int        retry   = 5; /* retry count */
-   int        inlreq  = 0; /* inline request_irq() */
-
-	if ( (irq > highest_subchannel) || (irq < 0 ) )
-	{
-		return( -ENODEV );
-
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-	} /* endif */
-
-	if ( ioinfo[irq]->ui.flags.oper == 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	if ( !ioinfo[irq]->ui.flags.ready )
-	{
-		/*
-		 * Perform SENSE ID command processing. We have to request device
-		 *  ownership and provide a dummy I/O handler. We issue sync. I/O
-       *  requests and evaluate the devstat area on return therefore
-       *  we don't need a real I/O handler in place.
-       */
-		irq_ret = request_irq( irq, init_IRQ_handler, 0, "SID", &devstat);
-
-		if ( irq_ret == 0 )
-			inlreq = 1;
-
-	} /* endif */
-
-	if ( irq_ret == 0 )
-   {
-		s390irq_spin_lock( irq);
-
-		sense_ccw.cmd_code = CCW_CMD_SENSE_ID;
-		sense_ccw.cda      = (__u32)virt_to_phys( sid );
-		sense_ccw.count    = sizeof( senseid_t);
-		sense_ccw.flags    = CCW_FLAG_SLI;
-
-		ioinfo[irq]->senseid.cu_type    = 0xFFFF;  /* initialize fields ... */
-		ioinfo[irq]->senseid.cu_model   = 0;
-		ioinfo[irq]->senseid.dev_type   = 0;
-		ioinfo[irq]->senseid.dev_model  = 0;
-
-		/*
-		 * We now issue a SenseID request. In case of BUSY
-		 *  or STATUS PENDING conditions we retry 5 times.
-		 */
-		do
-		{
-			memset( &devstat, '\0', sizeof( devstat_t) );
-
-			irq_ret = s390_start_IO( irq,
-			                         &sense_ccw,
-			                         0x00E2C9C4,  // == SID
-			                         0,           // n/a
-			                         DOIO_WAIT_FOR_INTERRUPT
-			                          | DOIO_TIMEOUT );
-
-			if ( irq_ret == -ETIMEDOUT )
-			{
-				halt_IO( irq,
-				         0x80E2C9C4,
-				         DOIO_WAIT_FOR_INTERRUPT);
-				devstat.flag |= DEVSTAT_NOT_OPER;
-
-			} /* endif */      	
-
-			if ( sid->cu_type == 0xFFFF && devstat.flag != DEVSTAT_NOT_OPER )
-			{
-				if ( devstat.flag & DEVSTAT_STATUS_PENDING )
-				{
-#if CONFIG_DEBUG_IO
-					printk( "Device %04X on Subchannel %04X "
-					        "reports pending status, retry : %d\n",
-					        ioinfo[irq]->schib.pmcw.dev,
-					        irq,
-					        retry);
-#endif
-				} /* endif */
-
-				if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL )
-				{
-					/*
-					 * if the device doesn't support the SenseID
-					 *  command further retries wouldn't help ...
-					 */
-					if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT )
-					{
-						retry = 0;
-					}
-#if CONFIG_DEBUG_IO
-					else
-					{
-						printk( "Device %04X,"
-						        " UC/SenseID,"
-						        " retry %d, cnt %02d,"
-						        " sns :"
-						        " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-						        ioinfo[irq]->schib.pmcw.dev,
-						        retry,
-						        devstat.scnt,
-						        devstat.ii.sense.data[0],
-						        devstat.ii.sense.data[1],
-						        devstat.ii.sense.data[2],
-						        devstat.ii.sense.data[3],
-						        devstat.ii.sense.data[4],
-						        devstat.ii.sense.data[5],
-						        devstat.ii.sense.data[6],
-						        devstat.ii.sense.data[7]);
-
-					} /* endif */
-#endif
-				}
-				else if ( devstat.flag & DEVSTAT_NOT_OPER )
-				{
-					printk( "Device %04X on Subchannel %04X "
-					        "became 'not operational'\n",
-					        ioinfo[irq]->schib.pmcw.dev,
-					        irq);
-
-					retry = 0;
-
-				} /* endif */
-			}
-			else   // we got it or the device is not-operational ...
-			{
-				retry = 0;
-
-			} /* endif */
-
-			retry--;
-
-		} while ( retry > 0 );
-
-		s390irq_spin_unlock( irq);
-
-		/*
-		 * If we installed the irq action handler we have to
-		 *  release it too.
-		 */
-		if ( inlreq )
-			free_irq( irq, &devstat);
-
-		/*
-		 * if running under VM check there ... perhaps we should do
-		 *  only if we suffered a command reject, but it doesn't harm
-		 */
-		if (    ( sid->cu_type == 0xFFFF )
-		     && ( MACHINE_IS_VM              ) )
-		{
-			VM_virtual_device_info( ioinfo[irq]->schib.pmcw.dev,
-			                        sid );
-		} /* endif */
-
-		if ( sid->cu_type == 0xFFFF )
-		{
-			/*
-			 * SenseID CU-type of 0xffff indicates that no device
-			 *  information could be retrieved (pre-init value).
-			 *
-			 * If we can't couldn't identify the device type we
-			 *  consider the device "not operational".
-			 */
-			printk( "Unknown device %04X on subchannel %04X\n",
-			        ioinfo[irq]->schib.pmcw.dev,
-			        irq);
-			ioinfo[irq]->ui.flags.oper = 0;
-
-		} /* endif */
-
-		/*
-		 * Issue device info message if unit was operational .
-		 */
-		if ( ioinfo[irq]->ui.flags.oper )
-		{
-			if ( sid->dev_type != 0 )
-			{
-				printk( "Device %04X reports: CU  Type/Mod = %04X/%02X,"
-				        " Dev Type/Mod = %04X/%02X\n",
-				        ioinfo[irq]->schib.pmcw.dev,
-				        sid->cu_type,
-				        sid->cu_model,
-				        sid->dev_type,
-				        sid->dev_model);
-			}
-			else
-			{
-				printk( "Device %04X reports:"
-				        " Dev Type/Mod = %04X/%02X\n",
-				        ioinfo[irq]->schib.pmcw.dev,
-				        sid->cu_type,
-				        sid->cu_model);
-
-			} /* endif */
-
-		} /* endif */
-
-		if ( ioinfo[irq]->ui.flags.oper )
-			irq_ret = 0;
-		else
-			irq_ret = -ENODEV;
-
-	} /* endif */
-
-   return( irq_ret );
-}
-
-static int __inline__ s390_SetMultiPath( int irq )
-{
-	int cc;
-
-	cc = stsch( irq, &ioinfo[irq]->schib );
-
-	if ( !cc )
-	{
-		ioinfo[irq]->schib.pmcw.mp = 1;     /* multipath mode */
-
-		cc = msch( irq, &ioinfo[irq]->schib );
-
-	} /* endif */
-
-	return( cc);
-}
-
-/*
- * Device Path Verification
- *
- * Path verification is accomplished by checking which paths (CHPIDs) are
- *  available. Further, a path group ID is set, if possible in multipath
- *  mode, otherwise in single path mode.
- *
- */
-int s390_DevicePathVerification( int irq )
-{
-#if 0
-	int  ccode;
-	__u8 pathmask;
-
-	int ret = 0;
-
-	if ( ioinfo[irq]->ui.flags.pgid_supp == 0 )
-	{
-		ret = -EOPNOTSUPP;
-
-	} /* endif */
-
-	ccode = stsch( irq, &(ioinfo[irq]->schib) );
-
-	if ( ccode )
-	{
-		ret = -ENODEV;
-	}
-	else
-	{
-		int    i;
-		pgid_t pgid;
-
-		int    first  = 1;
-		__u8 dev_path =   ioinfo[irq]->schib.pmcw.pam
-		                & ioinfo[irq]->schib.pmcw.pom;
-
-		/*
-		 * let's build a path group ID if we don't have one yet
-		 */
-		if ( ioinfo[irq]->ui.flags.pgid == 0)
-		{
-			struct _lowcore *lowcore = &get_cpu_lowcore(cpu);
-
-			ioinfo->pgid.cpu_addr  = lowcore->cpu_data.cpu_addr;
-			ioinfo->pgid.cpu_id    = lowcore->cpu_data.cpu_id.ident;
-			ioinfo->pgid.cpu_model = lowcore->cpu_data.cpu_id.machine;
-			ioinfo->pgid.tod_high  = *(__u32 *)&irq_IPL_TOD;
-
-			ioinfo[irq]->ui.flags.pgid = 1;
-
-		} /* endif */     		
-
-		memcpy( &pgid, ioinfo[irq]->pgid, sizeof(pgid_t));
-
-		for ( i = 0; i < 8 && !ret ; i++)
-		{
-			pathmask = 0x80 >> i;						
-
-			if ( dev_path & pathmask )
-			{
-				ret = s390_SetPGID( irq, pathmask, &pgid );
-
-				/*
-				 * For the *first* path we are prepared
-				 *  for recovery
-				 *
-				 *  - If we fail setting the PGID we assume its
-				 *     using  a different PGID already (VM) we
-				 *     try to sense.
-				 */
-				if ( ret == -EOPNOTSUPP && first )
-				{
-					*(int *)&pgid = 0;
-					
-					ret   = s390_SensePGID( irq, pathmask, &pgid);
-					first = 0;
-
-					if ( !ret )
-					{
-						/*
-						 * Check whether we retrieved
-						 *  a reasonable PGID ...
-						 */	
-						if ( !ret && (*(int *)&pgid == 0) )
-						{
-							ret = -EOPNOTSUPP;
-						}
-						else
-						{
-							ret = s390_SetPGID( irq, pathmask, &pgid );
-
-						} /* endif */
-
-					} /* endif */
-
-					if ( ret )
-					{
-						ioinfo[irq]->ui.flags.pgid_supp = 0;
-
-						printk( "PathVerification(%04X) "
-						        "- Device %04X doesn't "
-						        " support path grouping",
-						        irq,
-						        ioinfo[irq]->schib.pmcw.dev);
-
-					} /* endif */
-				}
-				else if ( ret )
-				{
-					ioinfo[irq]->ui.flags.pgid_supp = 0;
-
-				} /* endif */
-
-			} /* endif */
-
-		} /* endfor */
-
-	} /* endif */
-
-	return ret;
-#else
-	return 0;
-#endif
-}
-
-/*
- * s390_SetPGID
- *
- * Set Path Group ID
- *
- */
-int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid )
-{
-	ccw1_t     spid_ccw;    /* ccw area for SPID command */
-	devstat_t  devstat;     /* required by request_irq() */
-
-	int        irq_ret = 0; /* return code */
-	int        retry   = 5; /* retry count */
-	int        inlreq  = 0; /* inline request_irq() */
-	int        mpath   = 1; /* try multi-path first */
-
-	if ( (irq > highest_subchannel) || (irq < 0 ) )
-	{
-		return( -ENODEV );
-
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-
-	} /* endif */
-
-	if ( ioinfo[irq]->ui.flags.oper == 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	if ( !ioinfo[irq]->ui.flags.ready )
-	{
-		/*
-		 * Perform SENSE ID command processing. We have to request device
-		 *  ownership and provide a dummy I/O handler. We issue sync. I/O
-		 *  requests and evaluate the devstat area on return therefore
-		 *  we don't need a real I/O handler in place.
-		 */
-		irq_ret = request_irq( irq, init_IRQ_handler, 0, "SPID", &devstat);
-
-		if ( irq_ret == 0 )
-			inlreq = 1;
-
-	} /* endif */
-
-	if ( irq_ret == 0 )
-	{
-		s390irq_spin_lock( irq);
-
-		spid_ccw.cmd_code = CCW_CMD_SET_PGID;
-		spid_ccw.cda      = (__u32)virt_to_phys( pgid );
-		spid_ccw.count    = sizeof( pgid_t);
-		spid_ccw.flags    = CCW_FLAG_SLI;
-
-
-		/*
-		 * We now issue a SenseID request. In case of BUSY
-		 *  or STATUS PENDING conditions we retry 5 times.
-		 */
-		do
-		{
-			memset( &devstat, '\0', sizeof( devstat_t) );
-
-			irq_ret = s390_start_IO( irq,
-			                         &spid_ccw,
-			                         0xE2D7C9C4,  // == SPID
-			                         lpm,         // n/a
-			                         DOIO_WAIT_FOR_INTERRUPT
-			                          | DOIO_VALID_LPM );
-
-			if ( !irq_ret )
-			{
-				if ( devstat.flag & DEVSTAT_STATUS_PENDING )
-				{
-#if CONFIG_DEBUG_IO
-					printk( "SPID - Device %04X "
-					        "on Subchannel %04X "
-					        "reports pending status, "
-					        "retry : %d\n",
-					        ioinfo[irq]->schib.pmcw.dev,
-					        irq,
-					        retry);
-#endif
-				} /* endif */
-
-				if ( devstat.flag == (   DEVSTAT_START_FUNCTION
-				                       | DEVSTAT_FINAL_STATUS   ) )
-				{
-					retry = 0;	// successfully set ...
-				}
-				else if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL )
-				{
-					/*
-					 * If the device doesn't support the
-					 *  Sense Path Group ID command
-					 *  further retries wouldn't help ...
-					 */
-					if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT )
-					{
-						if ( mpath )
-						{
-							pgid->inf.fc = SPID_FUNC_ESTABLISH;
-							mpath       = 0;
-							retry--;
-						}
-						else
-						{
-							irq_ret = -EOPNOTSUPP;
-							retry   = 0;			
-
-						} /* endif */
-					}
-#if CONFIG_DEBUG_IO
-					else
-					{
-						printk( "SPID - device %04X,"
-						        " unit check,"
-						        " retry %d, cnt %02d,"
-						        " sns :"
-						        " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-						        ioinfo[irq]->schib.pmcw.dev,
-						        retry,
-						        devstat.scnt,
-						        devstat.ii.sense.data[0],
-						        devstat.ii.sense.data[1],
-						        devstat.ii.sense.data[2],
-						        devstat.ii.sense.data[3],
-						        devstat.ii.sense.data[4],
-						        devstat.ii.sense.data[5],
-						        devstat.ii.sense.data[6],
-						        devstat.ii.sense.data[7]);
-
-					} /* endif */
-#endif
-				}
-				else if ( devstat.flag & DEVSTAT_NOT_OPER )
-				{
-					printk( "SPID - Device %04X "
-					        "on Subchannel %04X "
-					        "became 'not operational'\n",
-					        ioinfo[irq]->schib.pmcw.dev,
-					        irq);
-
-					retry = 0;
-
-				} /* endif */
-			}
-			else if ( irq_ret != -ENODEV )
-			{
-				retry--;
-			}
-			else
-			{
-				retry = 0;
-
-			} /* endif */
-
-		} while ( retry > 0 );
-
-		s390irq_spin_unlock( irq);
-
-		/*
-		 * If we installed the irq action handler we have to
-		 *  release it too.
-		 */
-		if ( inlreq )
-			free_irq( irq, &devstat);
-
-	} /* endif */
-
-   return( irq_ret );
-}
-
-
-/*
- * s390_SensePGID
- *
- * Sense Path Group ID
- *
- */
-int s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid )
-{
-	ccw1_t     snid_ccw;    /* ccw area for SNID command */
-	devstat_t  devstat;     /* required by request_irq() */
-
-	int        irq_ret = 0; /* return code */
-	int        retry   = 5; /* retry count */
-	int        inlreq  = 0; /* inline request_irq() */
-
-	if ( (irq > highest_subchannel) || (irq < 0 ) )
-	{
-		return( -ENODEV );
-
-	}
-	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
-	{
-		return( -ENODEV);
-
-	} /* endif */
-
-	if ( ioinfo[irq]->ui.flags.oper == 0 )
-	{
-		return( -ENODEV );
-
-	} /* endif */
-
-	if ( !ioinfo[irq]->ui.flags.ready )
-	{
-		/*
-		 * Perform SENSE ID command processing. We have to request device
-		 *  ownership and provide a dummy I/O handler. We issue sync. I/O
-		 *  requests and evaluate the devstat area on return therefore
-		 *  we don't need a real I/O handler in place.
-		 */
-		irq_ret = request_irq( irq, init_IRQ_handler, 0, "SNID", &devstat);
-
-		if ( irq_ret == 0 )
-			inlreq = 1;
-
-	} /* endif */
-
-	if ( irq_ret == 0 )
-	{
-		s390irq_spin_lock( irq);
-
-		snid_ccw.cmd_code = CCW_CMD_SENSE_PGID;
-		snid_ccw.cda      = (__u32)virt_to_phys( pgid );
-		snid_ccw.count    = sizeof( pgid_t);
-		snid_ccw.flags    = CCW_FLAG_SLI;
-
-		/*
-		 * We now issue a SenseID request. In case of BUSY
-		 *  or STATUS PENDING conditions we retry 5 times.
-		 */
-		do
-		{
-			memset( &devstat, '\0', sizeof( devstat_t) );
-
-			irq_ret = s390_start_IO( irq,
-			                         &snid_ccw,
-			                         0xE2D5C9C4,  // == SNID
-			                         lpm,         // n/a
-			                         DOIO_WAIT_FOR_INTERRUPT
-			                          | DOIO_VALID_LPM );
-
-			if ( !irq_ret )
-			{
-				if ( devstat.flag & DEVSTAT_STATUS_PENDING )
-				{
-#if CONFIG_DEBUG_IO
-					printk( "SNID - Device %04X "
-					        "on Subchannel %04X "
-					        "reports pending status, "
-					        "retry : %d\n",
-					        ioinfo[irq]->schib.pmcw.dev,
-					        irq,
-					        retry);
-#endif
-				} /* endif */
-
-				if ( devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL )
-				{
-					/*
-					 * If the device doesn't support the
-					 *  Sense Path Group ID command
-					 *  further retries wouldn't help ...
-					 */
-					if ( devstat.ii.sense.data[0] & SNS0_CMD_REJECT )
-					{
-						retry   = 0;
-						irq_ret = -EOPNOTSUPP;
-					}
-#if CONFIG_DEBUG_IO
-					else
-					{
-						printk( "SNID - device %04X,"
-						        " unit check,"
-						        " retry %d, cnt %02d,"
-						        " sns :"
-						        " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
-						        ioinfo[irq]->schib.pmcw.dev,
-						        retry,
-						        devstat.scnt,
-						        devstat.ii.sense.data[0],
-						        devstat.ii.sense.data[1],
-						        devstat.ii.sense.data[2],
-						        devstat.ii.sense.data[3],
-						        devstat.ii.sense.data[4],
-						        devstat.ii.sense.data[5],
-						        devstat.ii.sense.data[6],
-						        devstat.ii.sense.data[7]);
-
-					} /* endif */
-#endif
-				}
-				else if ( devstat.flag & DEVSTAT_NOT_OPER )
-				{
-					printk( "SNID - Device %04X "
-					        "on Subchannel %04X "
-					        "became 'not operational'\n",
-					        ioinfo[irq]->schib.pmcw.dev,
-					        irq);
-
-					retry = 0;
-
-				} /* endif */
-			}
-			else if ( irq_ret != -ENODEV )
-			{
-				retry--;
-			}
-			else
-			{
-				retry = 0;
-
-			} /* endif */
-
-		} while ( retry > 0 );
-
-		s390irq_spin_unlock( irq);
-
-		/*
-		 * If we installed the irq action handler we have to
-		 *  release it too.
-		 */
-		if ( inlreq )
-			free_irq( irq, &devstat);
-
-	} /* endif */
-
-   return( irq_ret );
-}
-
-
-void do_crw_pending( void )
-{
-   return;
-}
-
-
-/* added by Holger Smolinski for reipl support in reipl.S */
-void
-reipl ( int sch )
-{
-	int i;
-
-	for ( i = 0; i < highest_subchannel; i ++ ) {
-	    free_irq ( i, (void*)REIPL_DEVID_MAGIC );
-	}
-	do_reipl( 0x10000 | sch );
-}
-
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/s390mach.c linux/arch/s390/kernel/s390mach.c
--- v2.4.1/linux/arch/s390/kernel/s390mach.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/s390mach.c	Wed Dec 31 16:00:00 1969
@@ -1,157 +0,0 @@
-/*
- *  arch/s390/kernel/s390mach.c
- *   S/390 machine check handler,
- *            currently only channel-reports are supported
- *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/lowcore.h>
-#include <asm/semaphore.h>
-#include <asm/s390io.h>
-#include <asm/s390dyn.h>
-#include <asm/s390mach.h>
-
-#define S390_MACHCHK_DEBUG
-
-static mchchk_queue_element_t *mchchk_queue_head = NULL;
-static mchchk_queue_element_t *mchchk_queue_tail = NULL;
-static mchchk_queue_element_t *mchchk_queue_free = NULL;
-static spinlock_t              mchchk_queue_lock;
-static struct semaphore        s_sem[2];
-
-//
-// initialize machine check handling
-//
-void s390_init_machine_check( void )
-{
-	init_MUTEX_LOCKED( &s_sem[0] );
-	init_MUTEX_LOCKED( &s_sem[1] );
-
-#if 0
-	//
-	// fix me ! initialize a machine check queue with 100 elements
-	//
-#ifdef S390_MACHCHK_DEBUG
-	printk( "init_mach : starting kernel thread\n");
-#endif	
-
-	kernel_thread( s390_machine_check_handler, s_sem, 0);
-
-	//
-	// wait for the machine check handler to be ready
-	//
-#ifdef S390_MACHCHK_DEBUG
-	printk( "init_mach : waiting for kernel thread\n");
-#endif	
-
-	down( &sem[0]);
-
-#ifdef S390_MACHCHK_DEBUG
-	printk( "init_mach : kernel thread ready\n");
-#endif	
-
-	//
-	// fix me ! we have to initialize CR14 to allow for CRW pending
-	//           conditions
-
-	//
-	// fix me ! enable machine checks in the PSW
-	//
-#endif
-	return;
-}
-
-//
-// machine check pre-processor
-//
-void __init s390_do_machine_check( void )
-{
-   // fix me ! we have to check for machine check and
-   //          post the handler eventually
-
-	return;
-}
-
-//
-// machine check handler
-//
-static void __init s390_machine_check_handler( struct semaphore *sem )
-{
-#ifdef S390_MACHCHK_DEBUG
-	printk( "mach_handler : kernel thread up\n");
-#endif	
-
-	up( &sem[0] );
-
-#ifdef S390_MACHCHK_DEBUG
-	printk( "mach_handler : kernel thread ready\n");
-#endif	
-
-	do {
-
-#ifdef S390_MACHCHK_DEBUG
-	printk( "mach_handler : waiting for wakeup\n");
-#endif	
-
-		down_interruptible( &sem[1] );
-#ifdef S390_MACHCHK_DEBUG
-	printk( "mach_handler : wakeup\n");
-#endif	
-
-		break;	// fix me ! unconditional surrender ...
-  	
-		// fix me ! check for machine checks and
-		//          call do_crw_pending() eventually
-	
-	} while (1);
-
-	return;
-}
-
-mchchk_queue_element_t *s390_get_mchchk( void )
-{
-	unsigned long           flags;
-	mchchk_queue_element_t *qe;
-
-	spin_lock_irqsave( &mchchk_queue_lock, flags );
-
-	// fix me ! dequeue first element if available
-	qe = NULL;
-
-	spin_unlock_irqrestore( &mchchk_queue_lock, flags );
-
-	return qe;
-}
-
-void s390_free_mchchk( mchchk_queue_element_t *mchchk )
-{
-	unsigned long flags;
-
-	if ( mchchk != NULL)
-	{
-		spin_lock_irqsave( &mchchk_queue_lock, flags );
-		
-		mchchk->next      = mchchk_queue_free;
-
-		if ( mchchk_queue_free != NULL )
-		{
-			mchchk_queue_free->prev = mchchk;
-
-		} /* endif */
-
-		mchchk->prev      = NULL;
-		mchchk_queue_free = mchchk;
-
-		spin_unlock_irqrestore( &mchchk_queue_lock, flags );
-
-	} /* endif */
-
-	return;
-}
-
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/semaphore.c linux/arch/s390/kernel/semaphore.c
--- v2.4.1/linux/arch/s390/kernel/semaphore.c	Sat Nov 11 19:02:40 2000
+++ linux/arch/s390/kernel/semaphore.c	Tue Feb 13 14:13:44 2001
@@ -2,7 +2,7 @@
  *  linux/arch/S390/kernel/semaphore.c
  *
  *  S390 version
- *    Copyright (C) 1998 IBM Corporation
+ *    Copyright (C) 1998-2000 IBM Corporation
  *    Author(s): Martin Schwidefsky
  *
  *  Derived from "linux/arch/i386/kernel/semaphore.c
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/setup.c linux/arch/s390/kernel/setup.c
--- v2.4.1/linux/arch/s390/kernel/setup.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/setup.c	Tue Feb 13 14:13:44 2001
@@ -21,7 +21,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
@@ -45,6 +45,7 @@
 __u16 boot_cpu_addr;
 int cpus_initialized = 0;
 unsigned long cpu_initialized = 0;
+volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
 
 /*
  * Setup options
@@ -80,6 +81,7 @@
 void __init cpu_init (void)
 {
         int nr = smp_processor_id();
+        int addr = hard_smp_processor_id();
 
         if (test_and_set_bit(nr,&cpu_initialized)) {
                 printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr);
@@ -91,7 +93,7 @@
          * Store processor id in lowcore (used e.g. in timer_interrupt)
          */
         asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
-        S390_lowcore.cpu_data.cpu_addr = hard_smp_processor_id();
+        S390_lowcore.cpu_data.cpu_addr = addr;
         S390_lowcore.cpu_data.cpu_nr = nr;
 
         /*
@@ -158,33 +160,18 @@
 {
         if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
                 cpcmd(vmhalt_cmd, NULL, 0);
-        disabled_wait(0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
 void machine_power_off(void)
 {
         if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
                 cpcmd(vmpoff_cmd, NULL, 0);
-        disabled_wait(0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 #endif
 
 /*
- * Waits for 'delay' microseconds using the tod clock
- */
-void tod_wait(unsigned long delay)
-{
-        uint64_t start_cc, end_cc;
-
-	if (delay == 0)
-		return;
-        asm volatile ("STCK %0" : "=m" (start_cc));
-	do {
-		asm volatile ("STCK %0" : "=m" (end_cc));
-	} while (((end_cc - start_cc)/4096) < delay);
-}
-
-/*
  * Setup function called from init/main.c just after the banner
  * was printed.
  */
@@ -192,12 +179,11 @@
 {
         unsigned long bootmap_size;
         unsigned long memory_start, memory_end;
-        char c = ' ', *to = command_line, *from = COMMAND_LINE;
+        char c = ' ', cn, *to = command_line, *from = COMMAND_LINE;
 	struct resource *res;
 	unsigned long start_pfn, end_pfn;
         static unsigned int smptrap=0;
         unsigned long delay = 0;
-        int len = 0;
 
         if (smptrap)
                 return;
@@ -210,6 +196,7 @@
          */
         cpu_init();
         boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+        __cpu_logical_map[0] = boot_cpu_addr;
 
         /*
          * print what head.S has found out about the machine 
@@ -227,10 +214,15 @@
         rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
         rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
 #endif
-	/* nasty stuff with PARMAREAs. we use head.S or parameterline
-	  if (!MOUNT_ROOT_RDONLY)
-	  root_mountflags &= ~MS_RDONLY;
-	*/
+        memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
+	memory_end = MEMORY_SIZE;
+        /*
+         * We need some free virtual space to be able to do vmalloc.
+         * On a machine with 2GB memory we make sure that we have at
+         * least 128 MB free space for vmalloc.
+         */
+        if (memory_end > 1920*1024*1024)
+                memory_end = 1920*1024*1024;
         memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
 	memory_end = MEMORY_SIZE;                /* detected in head.s */
         init_mm.start_code = PAGE_OFFSET;
@@ -252,7 +244,6 @@
                  * "mem=XXX[kKmM]" sets memsize 
                  */
                 if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
-                        if (to != command_line) to--;
                         memory_end = simple_strtoul(from+4, &from, 0);
                         if ( *from == 'K' || *from == 'k' ) {
                                 memory_end = memory_end << 10;
@@ -275,16 +266,22 @@
 				delay = delay*60*1000000;
 				from++;
 			}
-			/* now wait for the requestion amount of time */
-			tod_wait(delay);
+			/* now wait for the requestedn amount of time */
+			udelay(delay);
                 }
-                c = *(from++);
-                if (!c)
+                cn = *(from++);
+                if (!cn)
                         break;
-                if (COMMAND_LINE_SIZE <= ++len)
+                if (cn == '\n')
+                        cn = ' ';  /* replace newlines with space */
+                if (cn == ' ' && c == ' ')
+                        continue;  /* remove additional spaces */
+                c = cn;
+                if (to - command_line >= COMMAND_LINE_SIZE)
                         break;
                 *(to++) = c;
         }
+        if (c == ' ' && to > command_line) to--;
         *to = '\0';
         *cmdline_p = command_line;
 
@@ -317,7 +314,7 @@
         paging_init();
 #ifdef CONFIG_BLK_DEV_INITRD
         if (INITRD_START) {
-		if (INITRD_START + INITRD_SIZE < memory_end) {
+		if (INITRD_START + INITRD_SIZE <= memory_end) {
 			reserve_bootmem(INITRD_START, INITRD_SIZE);
 			initrd_start = INITRD_START;
 			initrd_end = initrd_start + INITRD_SIZE;
@@ -368,8 +365,8 @@
         p += sprintf(p,"vendor_id       : IBM/S390\n"
                        "# processors    : %i\n"
                        "bogomips per cpu: %lu.%02lu\n",
-                       smp_num_cpus, loops_per_sec/500000,
-                       (loops_per_sec/5000)%100);
+                       smp_num_cpus, loops_per_jiffy/(500000/HZ),
+                       (loops_per_jiffy/(5000/HZ))%100);
         for (i = 0; i < smp_num_cpus; i++) {
                 cpuinfo = &safe_get_cpu_lowcore(i).cpu_data;
                 p += sprintf(p,"processor %i: "
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/signal.c linux/arch/s390/kernel/signal.c
--- v2.4.1/linux/arch/s390/kernel/signal.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/s390/kernel/signal.c	Tue Feb 13 14:13:44 2001
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/signal.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
  *    Based on Intel version
@@ -37,7 +37,7 @@
 #define SIGFRAME_COMMON \
 __u8     callee_used_stack[__SIGNAL_FRAMESIZE]; \
 struct sigcontext sc; \
-sigregs sregs; \
+_sigregs sregs; \
 __u8 retcode[S390_SYSCALL_SIZE];
 
 typedef struct 
@@ -54,6 +54,41 @@
 
 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+		return -EFAULT;
+	if (from->si_code < 0)
+		return __copy_to_user(to, from, sizeof(siginfo_t));
+	else {
+		int err;
+
+		/* If you change siginfo_t structure, please be sure
+		   this code is fixed accordingly.
+		   It should never copy any pad contained in the structure
+		   to avoid security leaks, but must copy the generic
+		   3 ints plus the relevant union member.  */
+		err = __put_user(from->si_signo, &to->si_signo);
+		err |= __put_user(from->si_errno, &to->si_errno);
+		err |= __put_user((short)from->si_code, &to->si_code);
+		/* First 32bits of unions are always present.  */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		switch (from->si_code >> 16) {
+		case __SI_FAULT >> 16:
+			break;
+		case __SI_CHLD >> 16:
+			err |= __put_user(from->si_utime, &to->si_utime);
+			err |= __put_user(from->si_stime, &to->si_stime);
+			err |= __put_user(from->si_status, &to->si_status);
+		default:
+			err |= __put_user(from->si_uid, &to->si_uid);
+			break;
+		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		}
+		return err;
+	}
+}
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -71,7 +106,7 @@
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
 		if (do_signal(regs, &saveset))
 			return -EINTR;
@@ -99,7 +134,7 @@
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
 		if (do_signal(regs, &saveset))
 			return -EINTR;
@@ -139,16 +174,15 @@
 }
 
 asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
 {
-	struct pt_regs *regs = (struct pt_regs *) &uss;
 	return do_sigaltstack(uss, uoss, regs->gprs[15]);
 }
 
 
 
 
-static int save_sigregs(struct pt_regs *regs,sigregs *sregs)
+static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
 {
 	int err;
 	s390_fp_regs fpregs;
@@ -163,7 +197,7 @@
 	
 }
 
-static int restore_sigregs(struct pt_regs *regs,sigregs *sregs)
+static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
 {
 	int err;
 	s390_fp_regs fpregs;
@@ -185,13 +219,13 @@
 
 static int
 restore_sigcontext(struct sigcontext *sc, pt_regs *regs,
-		 sigregs *sregs,sigset_t *set)
+		 _sigregs *sregs,sigset_t *set)
 {
 	unsigned int err;
 
 	err=restore_sigregs(regs,sregs);
 	if(!err)
-		err=__copy_from_user(&set->sig,&sc->oldmask,SIGMASK_COPY_SIZE);
+		err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE);
 		return(err);
 }
 
@@ -227,15 +261,12 @@
 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 {
 	rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
-	stack_t st;
 
 	if (sigreturn_common(regs,sizeof(rt_sigframe)))
 		goto badframe;
-	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs->gprs[15]);
+	do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
 	return regs->gprs[2];
 
 badframe:
@@ -290,7 +321,7 @@
 		err=__put_user(&frame->sregs,&frame->sc.sregs);
 	if(!err)
 
-		err=__copy_to_user(&frame->sc.oldmask,&set->sig,SIGMASK_COPY_SIZE);
+		err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE);
 	if(!err)
 	{
 		regs->gprs[2]=(current->exec_domain
@@ -316,14 +347,17 @@
 static void setup_frame(int sig, struct k_sigaction *ka,
 			sigset_t *set, struct pt_regs * regs)
 {
+	sigframe *frame;
 
-	if(!setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
-		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))
+	if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
+		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
 		goto give_sigsegv;
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
 		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
+	/* Martin wants this for pthreads */
+	regs->gprs[3] = (addr_t)&frame->sc;
 	return;
 
 give_sigsegv:
@@ -343,7 +377,7 @@
 		    (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
 		goto give_sigsegv;
 	
-	err = __copy_to_user(&frame->info, info, sizeof(*info));
+	err = copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -352,8 +386,9 @@
 	err |= __put_user(sas_ss_flags(orig_sp),
 			  &frame->uc.uc_stack.ss_flags);
 	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	regs->gprs[3] = (u32)&frame->info;
-	regs->gprs[4] = (u32)&frame->uc;
+	err |= __put_user(&frame->sc,&frame->uc.sc);
+	regs->gprs[3] = (addr_t)&frame->info;
+	regs->gprs[4] = (addr_t)&frame->uc;
 
 	if (err)
 		goto give_sigsegv;
@@ -452,10 +487,10 @@
 		if (!signr)
 			break;
 
-		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			/* Let the debugger run.  */
 			current->exit_code = signr;
-			current->state = TASK_STOPPED;
+			set_current_state(TASK_STOPPED);
 			notify_parent(current, SIGCHLD);
 			schedule();
 
@@ -511,7 +546,7 @@
 				/* FALLTHRU */
 
 			case SIGSTOP:
-				current->state = TASK_STOPPED;
+				set_current_state(TASK_STOPPED);
 				current->exit_code = signr;
 				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
@@ -540,7 +575,7 @@
 	}
 
 	/* Did we come from a system call? */
-	if ( regs->trap == 0x20 /* System Call! */ ) {
+	if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
 		/* Restart the system call - no handlers present */
 		if (regs->gprs[2] == -ERESTARTNOHAND ||
 		    regs->gprs[2] == -ERESTARTSYS ||
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/smp.c linux/arch/s390/kernel/smp.c
--- v2.4.1/linux/arch/s390/kernel/smp.c	Tue Sep  5 13:50:01 2000
+++ linux/arch/s390/kernel/smp.c	Tue Feb 13 14:13:44 2001
@@ -32,16 +32,15 @@
 #include <asm/sigp.h>
 #include <asm/pgalloc.h>
 #include <asm/irq.h>
+#include <asm/s390_ext.h>
 
 #include "cpcmd.h"
 
 /* prototypes */
-extern void update_one_process( struct task_struct *p,
-                                unsigned long ticks, unsigned long user,
-                                unsigned long system, int cpu);
 extern int cpu_idle(void * unused);
 
 extern __u16 boot_cpu_addr;
+extern volatile int __cpu_logical_map[];
 
 /*
  * An array with a pointer the lowcore of every CPU.
@@ -52,10 +51,8 @@
 unsigned int     prof_multiplier[NR_CPUS];
 unsigned int     prof_old_multiplier[NR_CPUS];
 unsigned int     prof_counter[NR_CPUS];
-volatile int     __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
 cycles_t         cacheflush_time=0;
 int              smp_threads_ready=0;      /* Set when the idlers are all forked. */
-unsigned long    ipi_count=0;              /* Number of IPIs delivered. */
 static atomic_t  smp_commenced = ATOMIC_INIT(0);
 
 spinlock_t       kernel_flag = SPIN_LOCK_UNLOCKED;
@@ -104,7 +101,7 @@
 void machine_restart(char * __unused) 
 {
         if (smp_processor_id() != 0) {
-                smp_ext_call_async(0, ec_restart);
+                smp_ext_bitcall(0, ec_restart);
                 for (;;);
         } else
                 do_machine_restart();
@@ -115,13 +112,13 @@
         smp_send_stop();
         if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
                 cpcmd(vmhalt_cmd, NULL, 0);
-        disabled_wait(0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
 void machine_halt(void)
 {
         if (smp_processor_id() != 0) {
-                smp_ext_call_async(0, ec_halt);
+                smp_ext_bitcall(0, ec_halt);
                 for (;;);
         } else
                 do_machine_halt();
@@ -132,13 +129,13 @@
         smp_send_stop();
         if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
                 cpcmd(vmpoff_cmd, NULL, 0);
-        disabled_wait(0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
 }
 
 void machine_power_off(void)
 {
         if (smp_processor_id() != 0) {
-                smp_ext_call_async(0, ec_power_off);
+                smp_ext_bitcall(0, ec_power_off);
                 for (;;);
         } else
                 do_machine_power_off();
@@ -149,7 +146,7 @@
  * cpus are handled.
  */
 
-void do_ext_call_interrupt(__u16 source_cpu_addr)
+void do_ext_call_interrupt(struct pt_regs *regs, __u16 code)
 {
         ec_ext_call *ec, *next;
         int bits;
@@ -172,6 +169,8 @@
 		do_machine_halt();
         if (test_bit(ec_power_off, &bits))
 		do_machine_power_off();
+	if (test_bit(ec_ptlb, &bits))
+	        local_flush_tlb();
 
         /*
          * Handle external call commands with a parameter area
@@ -184,7 +183,7 @@
                 return;   /* no command signals */
 
         /* Make a fifo out of the lifo */
-        next = ec;
+        next = ec->next;
         ec->next = NULL;
         while (next != NULL) {
                 ec_ext_call *tmp = next->next;
@@ -196,61 +195,21 @@
         /* Execute every sigp command on the queue */
         while (ec != NULL) {
                 switch (ec->cmd) {
-                case ec_get_ctl: {
-                        ec_creg_parms *pp;
-                        pp = (ec_creg_parms *) ec->parms;
-                        atomic_set(&ec->status,ec_executing);
-                        asm volatile (
-                                "   bras  1,0f\n"
-                                "   stctl 0,0,0(%0)\n"
-                                "0: ex    %1,0(1)\n"
-                                : : "a" (pp->cregs+pp->start_ctl),
-                                "a" ((pp->start_ctl<<4) + pp->end_ctl)
-                                : "memory", "1" );
-                        atomic_set(&ec->status,ec_done);
-                        return;
-                }
-                case ec_set_ctl: {
-                        ec_creg_parms *pp;
-                        pp = (ec_creg_parms *) ec->parms;
+                case ec_callback_async: {
+                        void (*func)(void *info);
+                        void *info;
+
+                        func = ec->func;
+                        info = ec->info;
                         atomic_set(&ec->status,ec_executing);
-                        asm volatile (
-                                "   bras  1,0f\n"
-                                "   lctl 0,0,0(%0)\n"
-                                "0: ex    %1,0(1)\n"
-                                : : "a" (pp->cregs+pp->start_ctl),
-                                "a" ((pp->start_ctl<<4) + pp->end_ctl)
-                                : "memory", "1" );
-                        atomic_set(&ec->status,ec_done);
+                        (func)(info);
                         return;
                 }
-                case ec_set_ctl_masked: {
-                        ec_creg_mask_parms *pp;
-                        u32 cregs[16];
-                        int i;
-
-                        pp = (ec_creg_mask_parms *) ec->parms;
+                case ec_callback_sync:
                         atomic_set(&ec->status,ec_executing);
-                        asm volatile (
-                                "   bras  1,0f\n"
-                                "   stctl 0,0,0(%0)\n"
-                                "0: ex    %1,0(1)\n"
-                                : : "a" (cregs+pp->start_ctl),
-                                "a" ((pp->start_ctl<<4) + pp->end_ctl)
-                                : "memory", "1" );
-                        for (i = pp->start_ctl; i <= pp->end_ctl; i++)
-                                cregs[i] = (cregs[i] & pp->andvals[i])
-                                                     | pp->orvals[i];
-                        asm volatile (
-                                "   bras  1,0f\n"
-                                "   lctl 0,0,0(%0)\n"
-                                "0: ex    %1,0(1)\n"
-                                : : "a" (cregs+pp->start_ctl),
-                                "a" ((pp->start_ctl<<4) + pp->end_ctl)
-                                : "memory", "1" );
+                        (ec->func)(ec->info);
                         atomic_set(&ec->status,ec_done);
                         return;
-                }
                 default:
                 }
                 ec = ec->next;
@@ -258,17 +217,19 @@
 }
 
 /*
- * Send an external call sigp to another cpu and wait for its completion.
+ * Send a callback sigp to another cpu.
  */
-sigp_ccode smp_ext_call_sync(int cpu, ec_cmd_sig cmd, void *parms)
+sigp_ccode
+smp_ext_call(int cpu, void (*func)(void *info), void *info, int wait)
 {
         struct _lowcore *lowcore = &get_cpu_lowcore(cpu);
         sigp_ccode ccode;
         ec_ext_call ec;
 
-        ec.cmd = cmd;
+        ec.cmd = wait ? ec_callback_sync : ec_callback_async;
         atomic_set(&ec.status, ec_pending);
-        ec.parms = parms;
+	ec.func = func;
+        ec.info = info;
         do {
                 ec.next = (ec_ext_call*) atomic_read(&lowcore->ext_call_queue);
         } while (atomic_compare_and_swap((int) ec.next, (int)(&ec),
@@ -288,34 +249,15 @@
 
         if (ccode != sigp_not_operational)
                 /* wait for completion, FIXME: possible seed of a deadlock */
-                while (atomic_read(&ec.status) != ec_done);
-
-        return ccode;
-}
-
-/*
- * Send an external call sigp to another cpu and return without waiting
- * for its completion. Currently we do not support parameters with
- * asynchronous sigps.
- */
-sigp_ccode smp_ext_call_async(int cpu, ec_bit_sig sig)
-{
-        struct _lowcore *lowcore = &get_cpu_lowcore(cpu);
-        sigp_ccode ccode;
+                while (atomic_read(&ec.status) != (wait?ec_done:ec_executing));
 
-        /*
-         * Set signaling bit in lowcore of target cpu and kick it
-         */
-        atomic_set_mask(1<<sig, &lowcore->ext_call_fast);
-        ccode = signal_processor(cpu, sigp_external_call);
         return ccode;
 }
 
 /*
- * Send an external call sigp to every other cpu in the system and
- * wait for the completion of the sigps.
+ * Send a callback sigp to every other cpu in the system.
  */
-void smp_ext_call_sync_others(ec_cmd_sig cmd, void *parms)
+void smp_ext_call_others(void (*func)(void *info), void *info, int wait)
 {
         struct _lowcore *lowcore;
         ec_ext_call ec[NR_CPUS];
@@ -326,9 +268,10 @@
                 if (smp_processor_id() == i)
                         continue;
                 lowcore = &get_cpu_lowcore(i);
-                ec[i].cmd = cmd;
-                atomic_set(&ec[i].status, ec_pending);
-                ec[i].parms = parms;
+		ec[i].cmd = wait ? ec_callback_sync : ec_callback_async;
+		atomic_set(&ec[i].status, ec_pending);
+		ec[i].func = func;
+		ec[i].info = info;
                 do {
                         ec[i].next = (ec_ext_call *)
                                         atomic_read(&lowcore->ext_call_queue);
@@ -341,16 +284,33 @@
         for (i = 0; i < smp_num_cpus; i++) {
                 if (smp_processor_id() == i)
                         continue;
-                while (atomic_read(&ec[i].status) != ec_done);
+                while (atomic_read(&ec[i].status) != 
+		       (wait ? ec_done:ec_executing));
         }
 }
 
 /*
+ * Send an external call sigp to another cpu and return without waiting
+ * for its completion.
+ */
+sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+{
+        struct _lowcore *lowcore = &get_cpu_lowcore(cpu);
+        sigp_ccode ccode;
+
+        /*
+         * Set signaling bit in lowcore of target cpu and kick it
+         */
+        atomic_set_mask(1<<sig, &lowcore->ext_call_fast);
+        ccode = signal_processor(cpu, sigp_external_call);
+        return ccode;
+}
+
+/*
  * Send an external call sigp to every other cpu in the system and
- * return without waiting for the completion of the sigps. Currently
- * we do not support parameters with asynchronous sigps.
+ * return without waiting for its completion.
  */
-void smp_ext_call_async_others(ec_bit_sig sig)
+void smp_ext_bitcall_others(ec_bit_sig sig)
 {
         struct _lowcore *lowcore;
         sigp_ccode ccode;
@@ -420,7 +380,46 @@
 
 void smp_send_stop(void)
 {
-        smp_signal_others(sigp_stop, 0, 1, NULL);
+        int i;
+        u32 dummy;
+        unsigned long low_core_addr;
+
+        /* write magic number to zero page (absolute 0) */
+
+        get_cpu_lowcore(smp_processor_id()).panic_magic = __PANIC_MAGIC;
+
+        /* stop all processors */
+
+        smp_signal_others(sigp_stop, 0, TRUE, NULL);
+
+        /* store status of all processors in their lowcores (real 0) */
+
+        for (i =  0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        int ccode;
+                        low_core_addr = (unsigned long)&get_cpu_lowcore(i);
+                        do {
+                                ccode = signal_processor_ps(
+                                   &dummy,
+                                   low_core_addr,
+                                   i,
+                                   sigp_store_status_at_address);
+                        } while(ccode == sigp_busy);
+                }
+        }
+}
+
+/*
+ * this function sends a 'purge tlb' signal to another CPU.
+ */
+void smp_ptlb_callback(void *info)
+{
+	local_flush_tlb();
+}
+
+void smp_ptlb_all(void)
+{
+        smp_ext_call_others(smp_ptlb_callback, NULL, 1);
 }
 
 /*
@@ -431,7 +430,44 @@
 
 void smp_send_reschedule(int cpu)
 {
-        smp_ext_call_async(cpu, ec_schedule);
+        smp_ext_bitcall(cpu, ec_schedule);
+}
+
+/*
+ * parameter area for the set/clear control bit callbacks
+ */
+typedef struct
+{
+	__u16 start_ctl;
+	__u16 end_ctl;
+	__u32 orvals[16];
+	__u32 andvals[16];
+} ec_creg_mask_parms;
+
+/*
+ * callback for setting/clearing control bits
+ */
+void smp_ctl_bit_callback(void *info) {
+	ec_creg_mask_parms *pp;
+	u32 cregs[16];
+	int i;
+	
+	pp = (ec_creg_mask_parms *) info;
+	asm volatile ("   bras  1,0f\n"
+		      "   stctl 0,0,0(%0)\n"
+		      "0: ex    %1,0(1)\n"
+		      : : "a" (cregs+pp->start_ctl),
+		          "a" ((pp->start_ctl<<4) + pp->end_ctl)
+		      : "memory", "1" );
+	for (i = pp->start_ctl; i <= pp->end_ctl; i++)
+		cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
+	asm volatile ("   bras  1,0f\n"
+		      "   lctl 0,0,0(%0)\n"
+		      "0: ex    %1,0(1)\n"
+		      : : "a" (cregs+pp->start_ctl),
+		          "a" ((pp->start_ctl<<4) + pp->end_ctl)
+		      : "memory", "1" );
+	return;
 }
 
 /*
@@ -445,7 +481,7 @@
                 parms.end_ctl = cr;
                 parms.orvals[cr] = 1 << bit;
                 parms.andvals[cr] = 0xFFFFFFFF;
-                smp_ext_call_sync_others(ec_set_ctl_masked,&parms);
+                smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
         }
         __ctl_set_bit(cr, bit);
 }
@@ -461,11 +497,35 @@
                 parms.end_ctl = cr;
                 parms.orvals[cr] = 0x00000000;
                 parms.andvals[cr] = ~(1 << bit);
-                smp_ext_call_sync_others(ec_set_ctl_masked,&parms);
+                smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
         }
         __ctl_clear_bit(cr, bit);
 }
 
+/*
+ * Call a function on all other processors
+ */
+
+int
+smp_call_function(void (*func)(void *info), void *info, int retry, int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <retry> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+{
+        if (atomic_read(&smp_commenced) != 0)
+                smp_ext_call_others(func, info, 1);
+        (func)(info);
+        return 0;
+}
 
 /*
  * Lets check how many CPUs we have.
@@ -475,7 +535,6 @@
 {
         int curr_cpu;
 
-        __cpu_logical_map[0] = boot_cpu_addr;
         current->processor = 0;
         smp_num_cpus = 1;
         for (curr_cpu = 0;
@@ -527,7 +586,7 @@
        struct pt_regs regs;
        /* don't care about the psw and regs settings since we'll never
           reschedule the forked task. */
-       memset(&regs,sizeof(pt_regs),0);
+       memset(&regs,0,sizeof(pt_regs));
        return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
 }
 
@@ -594,7 +653,10 @@
         struct _lowcore *curr_lowcore;
         sigp_ccode   ccode;
         int i;
-        
+
+        /* request the 0x1202 external interrupt */
+        if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
+                panic("Couldn't request external interrupt 0x1202");
         smp_count_cpus();
         memset(lowcore_ptr,0,sizeof(lowcore_ptr));  
         
@@ -705,24 +767,7 @@
                  */
 
                 irq_enter(cpu, 0);
-                update_one_process(p, 1, user, system, cpu);
-                if (p->pid) {
-                        p->counter -= 1;
-                        if (p->counter <= 0) {
-                                p->counter = 0;
-                                p->need_resched = 1;
-                        }
-                        if (p->nice > 0) {
-                                kstat.cpu_nice += user;
-                                kstat.per_cpu_nice[cpu] += user;
-                        } else {
-                                kstat.cpu_user += user;
-                                kstat.per_cpu_user[cpu] += user;
-                        }
-                        kstat.cpu_system += system;
-                        kstat.per_cpu_system[cpu] += system;
-
-                }
+		update_process_times(user);
                 irq_exit(cpu, 0);
         }
 }
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/sys_s390.c linux/arch/s390/kernel/sys_s390.c
--- v2.4.1/linux/arch/s390/kernel/sys_s390.c	Wed Jul  5 11:31:01 2000
+++ linux/arch/s390/kernel/sys_s390.c	Tue Feb 13 14:13:44 2001
@@ -71,18 +71,10 @@
 	return error;
 }
 
-/* FIXME: 6 parameters is one too much ... */
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	return do_mmap2(addr, len, prot, flags, fd, pgoff);
-}
-
 /*
  * Perform the select(nd, in, out, ex, tv) and mmap() system
- * calls. Linux/i386 didn't use to be able to handle more than
- * 4 system call parameters, so these system calls used a memory
+ * calls. Linux for S/390 isn't able to handle more than 5
+ * system call parameters, so these system calls used a memory
  * block for parameter passing..
  */
 
@@ -95,6 +87,18 @@
 	unsigned long offset;
 };
 
+asmlinkage long sys_mmap2(struct mmap_arg_struct *arg)
+{
+	struct mmap_arg_struct a;
+	int error = -EFAULT;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		goto out;
+	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+out:
+	return error;
+}
+
 asmlinkage int old_mmap(struct mmap_arg_struct *arg)
 {
 	struct mmap_arg_struct a;
@@ -239,7 +243,7 @@
 
 asmlinkage int sys_pause(void)
 {
-	current->state = TASK_INTERRUPTIBLE;
+	set_current_state(TASK_INTERRUPTIBLE);
 	schedule();
 	return -ERESTARTNOHAND;
 }
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/time.c linux/arch/s390/kernel/time.c
--- v2.4.1/linux/arch/s390/kernel/time.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/kernel/time.c	Tue Feb 13 14:13:44 2001
@@ -11,7 +11,6 @@
  *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -27,15 +26,14 @@
 
 #include <asm/uaccess.h>
 #include <asm/delay.h>
+#include <asm/s390_ext.h>
 
-#include <linux/mc146818rtc.h>
 #include <linux/timex.h>
+#include <linux/config.h>
 
 #include <asm/irq.h>
 
 
-extern volatile unsigned long lost_ticks;
-
 /* change this if you have some constant time drift */
 #define USECS_PER_JIFFY ((signed long)1000000/HZ)
 #define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12)
@@ -45,6 +43,7 @@
 static uint64_t init_timer_cc, last_timer_cc;
 
 extern rwlock_t xtime_lock;
+extern unsigned long wall_jiffies;
 
 void tod_to_timeval(uint64_t todval, struct timeval *xtime)
 {
@@ -94,9 +93,9 @@
  */
 void do_gettimeofday(struct timeval *tv)
 {
-	extern volatile unsigned long lost_ticks;
 	unsigned long flags;
 	unsigned long usec, sec;
+	unsigned long lost_ticks = jiffies - wall_jiffies;
 
 	read_lock_irqsave(&xtime_lock, flags);
 	usec = do_gettimeoffset();
@@ -149,7 +148,7 @@
 extern __u16 boot_cpu_addr;
 #endif
 
-void do_timer_interrupt(struct pt_regs *regs,int error_code)
+void do_timer_interrupt(struct pt_regs *regs, __u16 error_code)
 {
         unsigned long flags;
 
@@ -242,6 +241,9 @@
                 printk("time_init: TOD clock stopped/non-operational\n");
                 break;
         }
+        /* request the 0x1004 external interrupt */
+        if (register_external_interrupt(0x1004, do_timer_interrupt) != 0)
+                panic("Couldn't request external interrupts 0x1004");
         init_100hz_timer();
         init_timer_cc = S390_lowcore.jiffy_timer_cc;
         init_timer_cc -= 0x8126d60e46000000LL -
diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/traps.c linux/arch/s390/kernel/traps.c
--- v2.4.1/linux/arch/s390/kernel/traps.c	Sun Dec  3 17:48:19 2000
+++ linux/arch/s390/kernel/traps.c	Tue Feb 13 14:13:44 2001
@@ -42,122 +42,15 @@
 typedef void pgm_check_handler_t(struct pt_regs *, long);
 pgm_check_handler_t *pgm_check_table[128];
 
-extern pgm_check_handler_t default_trap_handler;
-extern pgm_check_handler_t do_page_fault;
-
-asmlinkage int system_call(void);
-
-#define DO_ERROR(trapnr, signr, str, name, tsk) \
-asmlinkage void name(struct pt_regs * regs, long error_code) \
-{ \
-        tsk->thread.error_code = error_code; \
-        tsk->thread.trap_no = trapnr; \
-	die_if_no_fixup(str,regs,error_code); \
-        force_sig(signr, tsk); \
-}
-
-/* TODO: define these as 'pgm_check_handler_t xxx;'
-asmlinkage void divide_error(void);
-asmlinkage void debug(void);
-asmlinkage void nmi(void);
-asmlinkage void int3(void);
-asmlinkage void overflow(void);
-asmlinkage void bounds(void);
-asmlinkage void invalid_op(void);
-asmlinkage void device_not_available(void);
-asmlinkage void double_fault(void);
-asmlinkage void coprocessor_segment_overrun(void);
-asmlinkage void invalid_TSS(void);
-asmlinkage void segment_not_present(void);
-asmlinkage void stack_segment(void);
-asmlinkage void general_protection(void);
-asmlinkage void coprocessor_error(void);
-asmlinkage void reserved(void);
-asmlinkage void alignment_check(void);
-asmlinkage void spurious_interrupt_bug(void);
-*/
-
-int kstack_depth_to_print = 24;
-
-/*
- * These constants are for searching for possible module text
- * segments.  VMALLOC_OFFSET comes from mm/vmalloc.c; MODULE_RANGE is
- * a guess of how much space is likely to be vmalloced.
- */
-#define VMALLOC_OFFSET (8*1024*1024)
-#define MODULE_RANGE (8*1024*1024)
-
-void show_crashed_task_info(void)
-{
-	printk("CPU:    %d\n",smp_processor_id());
-	printk("Process %s (pid: %d, stackpage=%08X)\n",
-                current->comm, current->pid, 4096+(addr_t)current);
-	show_regs(current,NULL,NULL);
-}
-#if 0
-static void show_registers(struct pt_regs *regs)
-{
-        printk("CPU:    %d\nPSW:    %08lx %08lx\n",
-                smp_processor_id(), (unsigned long) regs->psw.mask,
-                (unsigned long) regs->psw.addr);
-        printk("GPRS:\n");
-
-        printk("%08lx  %08lx  %08lx  %08lx\n",
-                regs->gprs[0], regs->gprs[1],
-                regs->gprs[2], regs->gprs[3]);
-        printk("%08lx  %08lx  %08lx  %08lx\n",
-                regs->gprs[4], regs->gprs[5],
-                regs->gprs[6], regs->gprs[7]);
-        printk("%08lx  %08lx  %08lx  %08lx\n",
-                regs->gprs[8], regs->gprs[9],
-                regs->gprs[10], regs->gprs[11]);
-        printk("%08lx  %08lx  %08lx  %08lx\n",
-                regs->gprs[12], regs->gprs[13],
-                regs->gprs[14], regs->gprs[15]);
-        printk("Process %s (pid: %d, stackpage=%08lx)\nStack: ",
-                current->comm, current->pid, 4096+(unsigned long)current);
-/*
-        stack = (unsigned long *) esp;
-        for(i=0; i < kstack_depth_to_print; i++) {
-                if (((long) stack & 4095) == 0)
-                        break;
-                if (i && ((i % 8) == 0))
-                        printk("\n       ");
-                printk("%08lx ", get_seg_long(ss,stack++));
-        }
-        printk("\nCall Trace: ");
-        stack = (unsigned long *) esp;
-        i = 1;
-        module_start = PAGE_OFFSET + (max_mapnr << PAGE_SHIFT);
-        module_start = ((module_start + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1));
-        module_end = module_start + MODULE_RANGE;
-        while (((long) stack & 4095) != 0) {
-                addr = get_seg_long(ss, stack++); */
-                /*
-                 * If the address is either in the text segment of the
-                 * kernel, or in the region which contains vmalloc'ed
-                 * memory, it *may* be the address of a calling
-                 * routine; if so, print it so that someone tracing
-                 * down the cause of the crash will be able to figure
-                 * out the call path that was taken.
-                 */
-/*                if (((addr >= (unsigned long) &_stext) &&
-                     (addr <= (unsigned long) &_etext)) ||
-                    ((addr >= module_start) && (addr <= module_end))) {
-                        if (i && ((i % 8) == 0))
-                                printk("\n       ");
-                        printk("[<%08lx>] ", addr);
-                        i++;
-                }
-        }
-        printk("\nCode: ");
-        for(i=0;i<20;i++)
-                printk("%02x ",0xff & get_seg_byte(regs->xcs & 0xffff,(i+(char *)regs->eip)));
-        printk("\n");
-*/
-}
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_PROCESS_DEBUG
+int sysctl_userprocess_debug = 1;
+#else
+int sysctl_userprocess_debug = 0;
+#endif
 #endif
 
+extern pgm_check_handler_t do_page_fault;
 
 spinlock_t die_lock;
 
@@ -166,29 +59,65 @@
         console_verbose();
         spin_lock_irq(&die_lock);
         printk("%s: %04lx\n", str, err & 0xffff);
-        show_crashed_task_info();
+        show_regs(regs);
         spin_unlock_irq(&die_lock);
         do_exit(SIGSEGV);
 }
 
-int check_for_fixup(struct pt_regs * regs)
-{
-        if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
-		unsigned long fixup;
-		fixup = search_exception_table(regs->psw.addr);
-		if (fixup) {
-			regs->psw.addr = fixup;
-			return 1;
+#define DO_ERROR(signr, str, name) \
+asmlinkage void name(struct pt_regs * regs, long interruption_code) \
+{ \
+	do_trap(interruption_code, signr, str, regs, NULL); \
+}
+
+#define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \
+asmlinkage void name(struct pt_regs * regs, long interruption_code) \
+{ \
+        siginfo_t info; \
+        info.si_signo = signr; \
+        info.si_errno = 0; \
+        info.si_code = sicode; \
+        info.si_addr = (void *)siaddr; \
+        do_trap(interruption_code, signr, str, regs, &info); \
+}
+
+static void inline do_trap(long interruption_code, int signr, char *str,
+                           struct pt_regs *regs, siginfo_t *info)
+{
+        if (regs->psw.mask & PSW_PROBLEM_STATE) {
+                struct task_struct *tsk = current;
+                tsk->thread.trap_no = interruption_code;
+		if (info)
+			force_sig_info(signr, info, tsk);
+		else
+                	force_sig(signr, tsk);
+#ifndef CONFIG_SYSCTL
+#ifdef CONFIG_PROCESS_DEBUG
+                printk("User process fault: interruption code 0x%lX\n",
+                       interruption_code);
+                show_regs(regs);
+#endif
+#else
+		if (sysctl_userprocess_debug) {
+			printk("User process fault: interruption code 0x%lX\n",
+			       interruption_code);
+			show_regs(regs);
 		}
-	}
-	return 0;
+#endif
+        } else {
+                unsigned long fixup = search_exception_table(regs->psw.addr);
+                if (fixup)
+                        regs->psw.addr = fixup;
+                else
+                        die(str, regs, interruption_code);
+        }
 }
 
 int do_debugger_trap(struct pt_regs *regs,int signal)
 {
 	if(regs->psw.mask&PSW_PROBLEM_STATE)
 	{
-		if(current->flags & PF_PTRACED)
+		if(current->ptrace & PT_PTRACED)
 			force_sig(signal,current);
 		else
 			return 1;
@@ -207,50 +136,16 @@
 	return 0;
 }
 
-static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
-{
-	if (!(regs->psw.mask & PSW_PROBLEM_STATE)) {
-		unsigned long fixup;
-		fixup = search_exception_table(regs->psw.addr);
-		if (fixup) {
-			regs->psw.addr = fixup;
-			return;
-		}
-		die(str, regs, err);
-	}
-}
-
-asmlinkage void default_trap_handler(struct pt_regs * regs, long error_code)
-{
-        current->thread.error_code = error_code;
-        current->thread.trap_no = error_code;
-        die_if_no_fixup("Unknown program exception",regs,error_code);
-        force_sig(SIGSEGV, current);
-}
-
-DO_ERROR(2, SIGILL, "privileged operation", privileged_op, current)
-DO_ERROR(3, SIGILL, "execute exception", execute_exception, current)
-DO_ERROR(5, SIGSEGV, "addressing exception", addressing_exception, current)
-DO_ERROR(9, SIGFPE, "fixpoint divide exception", divide_exception, current)
-DO_ERROR(0x12, SIGILL, "translation exception", translation_exception, current)
-DO_ERROR(0x13, SIGILL, "special operand exception", special_op_exception, current)
-DO_ERROR(0x15, SIGILL, "operand exception", operand_exception, current)
-
-/* need to define
-DO_ERROR( 6, SIGILL,  "invalid operand", invalid_op, current)
-DO_ERROR( 8, SIGSEGV, "double fault", double_fault, current)
-DO_ERROR( 9, SIGFPE,  "coprocessor segment overrun", coprocessor_segment_overrun, last_task_used_math)
-DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS, current)
-DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present, current)
-DO_ERROR(12, SIGBUS,  "stack segment", stack_segment, current)
-DO_ERROR(17, SIGSEGV, "alignment check", alignment_check, current)
-DO_ERROR(18, SIGSEGV, "reserved", reserved, current)
-DO_ERROR(19, SIGSEGV, "cache flush denied", cache_flush_denied, current)
-*/
-
-#ifdef CONFIG_IEEEFPU_EMULATION
+DO_ERROR(SIGSEGV, "Unknown program exception", default_trap_handler)
+DO_ERROR(SIGILL,  "privileged operation", privileged_op)
+DO_ERROR(SIGILL,  "execute exception", execute_exception)
+DO_ERROR(SIGSEGV, "addressing exception", addressing_exception)
+DO_ERROR(SIGFPE,  "fixpoint divide exception", divide_exception)
+DO_ERROR(SIGILL,  "translation exception", translation_exception)
+DO_ERROR(SIGILL,  "special operand exception", special_op_exception)
+DO_ERROR(SIGILL,  "operand exception", operand_exception)
 
-asmlinkage void illegal_op(struct pt_regs * regs, long error_code)
+asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
 {
         __u8 opcode[6];
 	__u16 *location;
@@ -268,6 +163,7 @@
 		if(do_debugger_trap(regs,SIGTRAP))
 			do_sig=1;
 	}
+#ifdef CONFIG_IEEEFPU_EMULATION
         else if (problem_state )
 	{
 		if (opcode[0] == 0xb3) {
@@ -288,18 +184,19 @@
 			do_sig = math_emu_lfpc(opcode, regs);
 		} else
 			do_sig = 1;
-        } else
-		do_sig = 1;
-	if (do_sig) {
-		current->thread.error_code = error_code;
-		current->thread.trap_no = 1;
-		force_sig(SIGILL, current);
-		die_if_no_fixup("illegal operation", regs, error_code);
         }
+#endif 
+	else
+		do_sig = 1;
+	if (do_sig)
+		do_trap(interruption_code, SIGILL, "illegal operation", regs, NULL);
         unlock_kernel();
 }
 
-asmlinkage void specification_exception(struct pt_regs * regs, long error_code)
+
+
+#ifdef CONFIG_IEEEFPU_EMULATION
+asmlinkage void specification_exception(struct pt_regs * regs, long interruption_code)
 {
         __u8 opcode[6];
 	__u16 *location;
@@ -311,26 +208,26 @@
 		get_user(*((__u16 *) opcode), location);
 		switch (opcode[0]) {
 		case 0x28: /* LDR Rx,Ry   */
-			math_emu_ldr(opcode);
+			do_sig=math_emu_ldr(opcode);
 			break;
 		case 0x38: /* LER Rx,Ry   */
-			math_emu_ler(opcode);
+			do_sig=math_emu_ler(opcode);
 			break;
 		case 0x60: /* STD R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_std(opcode, regs);
+			do_sig=math_emu_std(opcode, regs);
 			break;
 		case 0x68: /* LD R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_ld(opcode, regs);
+			do_sig=math_emu_ld(opcode, regs);
 			break;
 		case 0x70: /* STE R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_ste(opcode, regs);
+			do_sig=math_emu_ste(opcode, regs);
 			break;
 		case 0x78: /* LE R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_le(opcode, regs);
+			do_sig=math_emu_le(opcode, regs);
 			break;
 		default:
 			do_sig = 1;
@@ -338,47 +235,59 @@
                 }
         } else
 		do_sig = 1;
-	if (do_sig) {
-		current->thread.error_code = error_code;
-		current->thread.trap_no = 1;
-		force_sig(SIGILL, current);
-		die_if_no_fixup("illegal operation", regs, error_code);
-        }
+        if (do_sig)
+                do_trap(interruption_code, SIGILL, "specification exception", regs, NULL);
         unlock_kernel();
 }
+#else
+DO_ERROR(SIGILL, "specification exception", specification_exception)
+#endif
 
-asmlinkage void data_exception(struct pt_regs * regs, long error_code)
+asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
 {
         __u8 opcode[6];
 	__u16 *location;
 	int do_sig = 0;
 
         lock_kernel();
-        if (regs->psw.mask & 0x00010000L) {
-		location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+	location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+	if(MACHINE_HAS_IEEE)
+	{
+		__asm__ volatile ("stfpc %0\n\t" 
+				  : "=m" (current->thread.fp_regs.fpc));
+	}
+	/* Same code should work when we implement fpu emulation */
+	/* provided we call data exception from the fpu emulator */
+	if(current->thread.fp_regs.fpc&FPC_DXC_MASK)
+	{
+		current->thread.ieee_instruction_pointer=(addr_t)location;
+		force_sig(SIGFPE, current);
+	}
+#ifdef CONFIG_IEEEFPU_EMULATION
+        else if (regs->psw.mask & 0x00010000L) {
 		get_user(*((__u16 *) opcode), location);
 		switch (opcode[0]) {
 		case 0x28: /* LDR Rx,Ry   */
-			math_emu_ldr(opcode);
+			do_sig=math_emu_ldr(opcode);
 			break;
 		case 0x38: /* LER Rx,Ry   */
-			math_emu_ler(opcode);
+			do_sig=math_emu_ler(opcode);
 			break;
 		case 0x60: /* STD R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_std(opcode, regs);
+			do_sig=math_emu_std(opcode, regs);
 			break;
 		case 0x68: /* LD R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_ld(opcode, regs);
+			do_sig=math_emu_ld(opcode, regs);
 			break;
 		case 0x70: /* STE R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_ste(opcode, regs);
+			do_sig=math_emu_ste(opcode, regs);
 			break;
 		case 0x78: /* LE R,D(X,B) */
 			get_user(*((__u16 *) (opcode+2)), location+1);
-			math_emu_le(opcode, regs);
+			do_sig=math_emu_le(opcode, regs);
 			break;
 		case 0xb3:
 			get_user(*((__u16 *) (opcode+2)), location+1);
@@ -406,22 +315,15 @@
 			do_sig = 1;
 			break;
                 }
-        } else
-		do_sig = 1;
-	if (do_sig) {
-		current->thread.error_code = error_code;
-		current->thread.trap_no = 1;
-		force_sig(SIGILL, current);
-		die_if_no_fixup("illegal operation", regs, error_code);
         }
+#endif 
+	else
+		do_sig = 1;
+        if (do_sig)
+                do_trap(interruption_code, SIGILL, "data exception", regs, NULL);
         unlock_kernel();
 }
 
-#else
-DO_ERROR(1, SIGILL, "illegal operation", illegal_op, current)
-DO_ERROR(6, SIGILL, "specification exception", specification_exception, current)
-DO_ERROR(7, SIGILL, "data exception", data_exception, current)
-#endif /* CONFIG_IEEEFPU_EMULATION */
 
 
 /* init is done in lowcore.S and head.S */
@@ -463,7 +365,7 @@
 		/* I've seen this possibly a task structure being reused ? */
 		printk("Spurious per exception detected\n");
 		printk("switching off per tracing for this task.\n");
-		show_crashed_task_info();
+		show_regs(regs);
 		/* Hopefully switching off per tracing will help us survive */
 		regs->psw.mask &= ~PSW_PER_MASK;
 	}
diff -u --recursive --new-file v2.4.1/linux/arch/s390/lib/Makefile linux/arch/s390/lib/Makefile
--- v2.4.1/linux/arch/s390/lib/Makefile	Fri May 12 11:41:45 2000
+++ linux/arch/s390/lib/Makefile	Tue Feb 13 14:13:44 2001
@@ -2,11 +2,17 @@
 # Makefile for s390-specific library files..
 #
 
+ifdef SMP
 .S.o:
-	$(CC) $(AFLAGS) -traditional -c $< -o $*.o
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+else
+.S.o:
+	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+endif
 
 L_TARGET = lib.a
-L_OBJS = checksum.o delay.o memset.o strcmp.o strncpy.o
+
+obj-y = checksum.o delay.o memset.o strcmp.o strncpy.o uaccess.o
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/lib/delay.c linux/arch/s390/lib/delay.c
--- v2.4.1/linux/arch/s390/lib/delay.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/lib/delay.c	Tue Feb 13 14:13:44 2001
@@ -21,25 +21,30 @@
 
 void __delay(unsigned long loops)
 {
-	__asm__ __volatile__(
-                "0: ahi  %0,-1\n"
-                "   jnm  0b"
-                : /* no outputs */ : "r" (loops) );
+        /*
+         * To end the bloody studid and useless discussion about the
+         * BogoMips number I took the liberty to define the __delay
+         * function in a way that that resulting BogoMips number will
+         * yield the megahertz number of the cpu. The important function
+         * is udelay and that is done using the tod clock. -- martin.
+         */
+        __asm__ __volatile__(
+                "0: brct %0,0b"
+                : /* no outputs */ : "r" (loops/2) );
 }
 
-inline void __const_udelay(unsigned long xloops)
+/*
+ * Waits for 'usecs' microseconds using the tod clock
+ */
+void __udelay(unsigned long usecs)
 {
+        uint64_t start_cc, end_cc;
 
-	__asm__("LR    3,%1\n\t"
-		"MR    2,%2\n\t"
-		"LR    %0,2\n\t"
-		: "=r" (xloops)
-		: "r" (xloops) , "r"  (loops_per_sec)
-		: "2" , "3");
-        __delay(xloops);
+        if (usecs == 0)
+                return;
+        asm volatile ("STCK %0" : "=m" (start_cc));
+        do {
+                asm volatile ("STCK %0" : "=m" (end_cc));
+        } while (((end_cc - start_cc)/4096) < usecs);
 }
 
-void __udelay(unsigned long usecs)
-{
-	__const_udelay(usecs * 0x000010c6);  /* 2**32 / 1000000 */
-}
diff -u --recursive --new-file v2.4.1/linux/arch/s390/lib/strcmp.S linux/arch/s390/lib/strcmp.S
--- v2.4.1/linux/arch/s390/lib/strcmp.S	Fri May 12 11:41:45 2000
+++ linux/arch/s390/lib/strcmp.S	Tue Feb 13 14:13:44 2001
@@ -18,8 +18,8 @@
         CLST    2,3
         JO      .-4
         JE      strcmp_equal
-        IC      0,0(0,3)
-        IC      1,0(0,2)
+        IC      0,0(3)
+        IC      1,0(2)
         SR      1,0
 strcmp_equal:
         LR      2,1
diff -u --recursive --new-file v2.4.1/linux/arch/s390/lib/strncpy.S linux/arch/s390/lib/strncpy.S
--- v2.4.1/linux/arch/s390/lib/strncpy.S	Fri May 12 11:41:45 2000
+++ linux/arch/s390/lib/strncpy.S	Tue Feb 13 14:13:44 2001
@@ -20,9 +20,9 @@
 	SR      0,0
 strncpy_loop:
         ICM     0,1,0(3)       # ICM sets the cc, IC does not
-	LA      3,1(0,3)
-        STC     0,0(0,1)
-	LA      1,1(0,1)
+	LA      3,1(3)
+        STC     0,0(1)
+	LA      1,1(1)
         JZ      strncpy_exit   # ICM inserted a 0x00
         BRCT    4,strncpy_loop # R4 -= 1, jump to strncpy_loop if >  0
 strncpy_exit:
diff -u --recursive --new-file v2.4.1/linux/arch/s390/lib/uaccess.S linux/arch/s390/lib/uaccess.S
--- v2.4.1/linux/arch/s390/lib/uaccess.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390/lib/uaccess.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,51 @@
+/*
+ *  arch/s390/lib/uaccess.S
+ *    fixup routines for copy_{from|to}_user functions.
+ *
+ *  s390
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  These functions have a non-standard call interface
+ */
+
+#include <asm/lowcore.h>
+
+        .text
+        .align 4
+        .globl __copy_from_user_fixup
+__copy_from_user_fixup:
+        l     1,__LC_PGM_OLD_PSW+4
+        sll   4,1
+        srl   4,1
+0:      lhi   3,-4096
+        sll   3,1
+        srl   3,1
+        n     3,__LC_TRANS_EXC_ADDR
+        sr    3,4
+        bm    4(1)
+1:      mvcle 2,4,0
+        b     4(1)
+        .section __ex_table,"a"
+	.long 1b,0b
+        .previous
+
+        .align 4
+        .text
+        .globl __copy_to_user_fixup
+__copy_to_user_fixup:
+        l     1,__LC_PGM_OLD_PSW+4
+        sll   4,1
+        srl   4,1
+0:      lhi   5,-4096
+        sll   5,1
+        srl   5,1
+        n     5,__LC_TRANS_EXC_ADDR
+        sr    5,4
+        bm    4(1)
+1:      mvcle 4,2,0
+        b     4(1)
+        .section __ex_table,"a"
+        .long 1b,0b
+        .previous
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390/mm/Makefile linux/arch/s390/mm/Makefile
--- v2.4.1/linux/arch/s390/mm/Makefile	Fri May 12 11:41:45 2000
+++ linux/arch/s390/mm/Makefile	Tue Feb 13 14:13:44 2001
@@ -8,6 +8,7 @@
 # Note 2! The CFLAGS definition is now in the main makefile...
 
 O_TARGET := mm.o
-O_OBJS	 := init.o fault.o ioremap.o extable.o
+
+obj-y	 := init.o fault.o ioremap.o extable.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/s390/mm/fault.c linux/arch/s390/mm/fault.c
--- v2.4.1/linux/arch/s390/mm/fault.c	Fri Aug  4 16:15:37 2000
+++ linux/arch/s390/mm/fault.c	Tue Feb 13 14:13:44 2001
@@ -9,6 +9,7 @@
  *    Copyright (C) 1995  Linus Torvalds
  */
 
+#include <linux/config.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
@@ -26,6 +27,10 @@
 #include <asm/pgtable.h>
 #include <asm/hardirq.h>
 
+#ifdef CONFIG_SYSCTL
+extern int sysctl_userprocess_debug;
+#endif
+
 extern void die(const char *,struct pt_regs *,long);
 
 /*
@@ -48,6 +53,8 @@
         int write;
         unsigned long psw_mask;
         unsigned long psw_addr;
+	int si_code = SEGV_MAPERR;
+	int kernel_address = 0;
 
         /*
          *  get psw mask of Program old psw to find out,
@@ -65,58 +72,106 @@
 
         address = S390_lowcore.trans_exc_code&0x7ffff000;
 
-        if (in_irq())
-                die("page fault from irq handler",regs,error_code);
-
         tsk = current;
         mm = tsk->mm;
 
+        if (in_interrupt() || !mm)
+                goto no_context;
+
+
+	/*
+	 * Check which address space the address belongs to
+	 */
+	switch (S390_lowcore.trans_exc_code & 3)
+	{
+	case 0: /* Primary Segment Table Descriptor */
+		kernel_address = 1;
+		goto no_context;
+
+	case 1: /* STD determined via access register */
+		if (S390_lowcore.exc_access_id == 0)
+		{
+			kernel_address = 1;
+			goto no_context;
+		}
+		if (regs && S390_lowcore.exc_access_id < NUM_ACRS)
+		{
+			if (regs->acrs[S390_lowcore.exc_access_id] == 0)
+			{
+				kernel_address = 1;
+				goto no_context;
+			}
+			if (regs->acrs[S390_lowcore.exc_access_id] == 1)
+			{
+				/* user space address */
+				break;
+			}
+		}
+		die("page fault via unknown access register", regs, error_code);
+		break;
+
+	case 2: /* Secondary Segment Table Descriptor */
+	case 3: /* Home Segment Table Descriptor */
+		/* user space address */
+		break;
+	}
+
+
+	/*
+	 * When we get here, the fault happened in the current
+	 * task's user address space, so we search the VMAs
+	 */
+
         down(&mm->mmap_sem);
 
         vma = find_vma(mm, address);
-        if (!vma) {
-	        printk("no vma for address %lX\n",address);
+        if (!vma)
                 goto bad_area;
-        }
         if (vma->vm_start <= address) 
                 goto good_area;
-        if (!(vma->vm_flags & VM_GROWSDOWN)) {
-                printk("VM_GROWSDOWN not set, but address %lX \n",address);
-                printk("not in vma %p (start %lX end %lX)\n",vma,
-                       vma->vm_start,vma->vm_end);
+        if (!(vma->vm_flags & VM_GROWSDOWN))
                 goto bad_area;
-        }
-        if (expand_stack(vma, address)) {
-                printk("expand of vma failed address %lX\n",address);
-                printk("vma %p (start %lX end %lX)\n",vma,
-                       vma->vm_start,vma->vm_end);
+        if (expand_stack(vma, address))
                 goto bad_area;
-        }
 /*
  * Ok, we have a good vm_area for this memory access, so
  * we can handle it..
  */
 good_area:
         write = 0;
+	si_code = SEGV_ACCERR;
+
         switch (error_code & 0xFF) {
                 case 0x04:                                /* write, present*/
                         write = 1;
                         break;
                 case 0x10:                                   /* not present*/
                 case 0x11:                                   /* not present*/
-                        if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
-                                printk("flags %X of vma for address %lX wrong \n",
-                                       vma->vm_flags,address);
-                                printk("vma %p (start %lX end %lX)\n",vma,
-                                       vma->vm_start,vma->vm_end);
+                        if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
                                 goto bad_area;
-                        }
                         break;
                 default:
                        printk("code should be 4, 10 or 11 (%lX) \n",error_code&0xFF);  
                        goto bad_area;
         }
-        handle_mm_fault(tsk, vma, address, write);
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	switch (handle_mm_fault(mm, vma, address, write)) {
+	case 1:
+		tsk->min_flt++;
+		break;
+	case 2:
+		tsk->maj_flt++;
+		break;
+	case 0:
+		goto do_sigbus;
+	default:
+		goto out_of_memory;
+	}
 
         up(&mm->mmap_sem);
         return;
@@ -130,19 +185,32 @@
 
         /* User mode accesses just cause a SIGSEGV */
         if (psw_mask & PSW_PROBLEM_STATE) {
+		struct siginfo si;
                 tsk->thread.prot_addr = address;
-                tsk->thread.error_code = error_code;
-                tsk->thread.trap_no = 14;
-
+                tsk->thread.trap_no = error_code;
+#ifndef CONFIG_SYSCTL
+#ifdef CONFIG_PROCESS_DEBUG
                 printk("User process fault: interruption code 0x%lX\n",error_code);
                 printk("failing address: %lX\n",address);
-		show_crashed_task_info();
-                force_sig(SIGSEGV, tsk);
+		show_regs(regs);
+#endif
+#else
+		if (sysctl_userprocess_debug) {
+			printk("User process fault: interruption code 0x%lX\n",
+			       error_code);
+			printk("failing address: %lX\n", address);
+			show_regs(regs);
+		}
+#endif
+		si.si_signo = SIGSEGV;
+		si.si_code = si_code;
+		si.si_addr = (void*) address;
+		force_sig_info(SIGSEGV, &si, tsk);
                 return;
 	}
 
+no_context:
         /* Are we prepared to handle this kernel fault?  */
-
         if ((fixup = search_exception_table(regs->psw.addr)) != 0) {
                 regs->psw.addr = fixup;
                 return;
@@ -151,53 +219,47 @@
 /*
  * Oops. The kernel tried to access some bad page. We'll have to
  * terminate things with extreme prejudice.
- *
- * First we check if it was the bootup rw-test, though..
  */
-        if (address < PAGE_SIZE)
-                printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+
+        if (kernel_address)
+                printk(KERN_ALERT "Unable to handle kernel pointer dereference"
+        	       " at virtual kernel address %08lx\n", address);
         else
-                printk(KERN_ALERT "Unable to handle kernel paging request");
-        printk(" at virtual address %08lx\n",address);
+                printk(KERN_ALERT "Unable to handle kernel paging request"
+		       " at virtual user address %08lx\n", address);
 /*
  * need to define, which information is useful here
  */
 
-        lock_kernel();
         die("Oops", regs, error_code);
         do_exit(SIGKILL);
-        unlock_kernel();
-}
 
-/*
-                {
-		  char c;
-                  int i,j;
-		  char *addr;
-		  addr = ((char*) psw_addr)-0x20;
-		  for (i=0;i<16;i++) {
-		    if (i == 2)
-		      printk("\n");
-		    printk ("%08X:    ",(unsigned long) addr);
-		    for (j=0;j<4;j++) {
-		      printk("%08X ",*(unsigned long*)addr);
-		      addr += 4;
-		    }
-		    addr -=0x10;
-		    printk(" | ");
-		    for (j=0;j<16;j++) {
-		      printk("%c",(c=*addr++) < 0x20 ? '.' : c );
-		    }
-
-		    printk("\n");
-		  }
-                  printk("\n");
-                }
 
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
 */
-
-
-
-
+out_of_memory:
+	up(&mm->mmap_sem);
+	printk("VM: killing process %s\n", tsk->comm);
+	if (psw_mask & PSW_PROBLEM_STATE)
+		do_exit(SIGKILL);
+	goto no_context;
+
+do_sigbus:
+	up(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+        tsk->thread.prot_addr = address;
+        tsk->thread.trap_no = error_code;
+	force_sig(SIGBUS, tsk);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!(psw_mask & PSW_PROBLEM_STATE))
+		goto no_context;
+}
 
 
diff -u --recursive --new-file v2.4.1/linux/arch/s390/mm/init.c linux/arch/s390/mm/init.c
--- v2.4.1/linux/arch/s390/mm/init.c	Tue Nov 28 22:43:39 2000
+++ linux/arch/s390/mm/init.c	Tue Feb 13 14:13:44 2001
@@ -52,10 +52,10 @@
  * data and COW.
  */
 
-pgd_t         swapper_pg_dir[512]   __attribute__ ((__aligned__ (4096)));
-unsigned long empty_bad_page[1024] __attribute__ ((__aligned__ (4096)));
-unsigned long empty_zero_page[1024] __attribute__ ((__aligned__ (4096)));
-pte_t         empty_bad_pte_table[1024] __attribute__ ((__aligned__ (4096)));
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
+char  empty_bad_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+pte_t empty_bad_pte_table[PTRS_PER_PTE] __attribute__((__aligned__(PAGE_SIZE)));
 
 static int test_access(unsigned long loc)
 {
@@ -104,47 +104,6 @@
                 pte_clear(pte++);
 }
 
-void __handle_bad_pmd(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-        pmd_val(*pmd) = _PAGE_TABLE + __pa(get_bad_pte_table());
-}
-
-void __handle_bad_pmd_kernel(pmd_t *pmd)
-{
-	pmd_ERROR(*pmd);
-        pmd_val(*pmd) = _KERNPG_TABLE + __pa(get_bad_pte_table());
-}
-
-pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long offset)
-{
-        pte_t *pte;
-
-        pte = (pte_t *) __get_free_page(GFP_KERNEL);
-        if (pmd_none(*pmd)) {
-                if (pte) {
-                        invalidate_page(pte);
-                        pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(pte);
-                        pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(pte)+1024;
-                        pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(pte)+2048;
-                        pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(pte)+3072;
-                        return pte + offset;
-                }
-		pte = get_bad_pte_table();
-                pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(pte);
-                pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(pte)+1024;
-                pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(pte)+2048;
-                pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(pte)+3072;
-                return NULL;
-        }
-        free_page((unsigned long)pte);
-        if (pmd_bad(*pmd)) {
-                __handle_bad_pmd_kernel(pmd);
-                return NULL;
-        }
-        return (pte_t *) pmd_page(*pmd) + offset;
-}
-
 pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
 {
         unsigned long pte;
@@ -167,10 +126,8 @@
                 return NULL;
         }
         free_page(pte);
-        if (pmd_bad(*pmd)) {
-                __handle_bad_pmd(pmd);
-                return NULL;
-        }
+        if (pmd_bad(*pmd))
+		BUG();
         return (pte_t *) pmd_page(*pmd) + offset;
 }
 
@@ -180,7 +137,7 @@
         if(pgtable_cache_size > high) {
                 do {
                         if(pgd_quicklist)
-                                free_pgd_slow(get_pgd_fast()), freed++;
+                                free_pgd_slow(get_pgd_fast()), freed += 2;
                         if(pmd_quicklist)
                                 free_pmd_slow(get_pmd_fast()), freed++;
                         if(pte_quicklist)
@@ -245,6 +202,7 @@
         unsigned long address=0;
         unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE;
 	unsigned long end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE);
+        static const int ssm_mask = 0x04000000L;
 
 	/* unmap whole virtual address space */
 
@@ -283,8 +241,9 @@
         /* enable virtual mapping in kernel mode */
         __asm__ __volatile__("    LCTL  1,1,%0\n"
                              "    LCTL  7,7,%0\n"
-                             "    LCTL  13,13,%0" 
-			     : :"m" (pgdir_k));
+                             "    LCTL  13,13,%0\n"
+                             "    SSM   %1" 
+			     : : "m" (pgdir_k), "m" (ssm_mask));
 
         local_flush_tlb();
 
@@ -378,6 +337,7 @@
 	val->sharedram = 0;
 	val->freeram = nr_free_pages();
 	val->bufferram = atomic_read(&buffermem_pages);
+	val->totalhigh = 0;
+	val->freehigh = 0;
 	val->mem_unit = PAGE_SIZE;
-	return;
 }
diff -u --recursive --new-file v2.4.1/linux/arch/s390/mm/ioremap.c linux/arch/s390/mm/ioremap.c
--- v2.4.1/linux/arch/s390/mm/ioremap.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/mm/ioremap.c	Tue Feb 13 14:13:44 2001
@@ -33,8 +33,8 @@
                         printk("remap_area_pte: page already exists\n");
 			BUG();
 		}
-                set_pte(pte, mk_pte_phys(phys_addr, __pgprot(_PAGE_PRESENT |
-                                        _PAGE_DIRTY | _PAGE_ACCESSED | flags)));
+                set_pte(pte, mk_pte_phys(phys_addr,
+                                         __pgprot(_PAGE_PRESENT | flags)));
                 address += PAGE_SIZE;
                 phys_addr += PAGE_SIZE;
                 pte++;
diff -u --recursive --new-file v2.4.1/linux/arch/s390/tools/dasdfmt/Makefile linux/arch/s390/tools/dasdfmt/Makefile
--- v2.4.1/linux/arch/s390/tools/dasdfmt/Makefile	Fri May 12 11:41:45 2000
+++ linux/arch/s390/tools/dasdfmt/Makefile	Tue Feb 13 14:13:44 2001
@@ -1,7 +1,7 @@
 all: dasdfmt
 
 dasdfmt: dasdfmt.c
-	$(CROSS_COMPILE)gcc -o $@ $^
+	$(CC) -o $@ $^
 	$(STRIP) $@
 
 clean:
diff -u --recursive --new-file v2.4.1/linux/arch/s390/tools/dasdfmt/dasdfmt.8 linux/arch/s390/tools/dasdfmt/dasdfmt.8
--- v2.4.1/linux/arch/s390/tools/dasdfmt/dasdfmt.8	Fri May 12 11:41:45 2000
+++ linux/arch/s390/tools/dasdfmt/dasdfmt.8	Fri Feb 16 16:02:34 2001
@@ -3,8 +3,7 @@
 .SH NAME
 dasdfmt \- formatting of DSAD (ECKD) disk drives.
 .SH SYNOPSIS
-\fBdasdfmt\fR [-tvyV] [-b \fIblockSize\fR] [\fIblockRange\fI]
-	\fIdiskSpec\fR
+\fBdasdfmt\fR [-tvyLV] [-b \fIblockSize\fR] [-l \fIdiskLabel\fR] \fIdiskSpec\fR
 .SH DESCRIPTION
 \fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
 for usage with Linux for S/390. \fBWARNING\fR: Incautious usage of
@@ -25,6 +24,10 @@
 Start formatting without further user-confirmation.
 
 .TP
+\fB-L\fR 
+Omit the writing of a disk label after formatting.
+
+.TP
 \fB-V\fR 
 Print version number and exit.
 
@@ -35,26 +38,17 @@
 it is \fBstrongly\fR recommended to use a \fIblockSize\fR of \fI4096\fR.
 
 .TP
-\fIblockRange\fR
-This parameter specifies the number of the first and last block to be
-formatted. If this parameter is \fBomitted\fR, formatting the \fBwhole\fR disk
-is assumed. The \fIblockRange\fR can be specified in two different formats:
-.sp
-	\fB-s\fR \fIstartBlock\fR \fB-e\fR \fIendBlock\fR
-.br
-or
-.br
-	\fB-r\fR \fIstartBlock\fR-\fIendBlock\fR
-.sp
-If \fIstartBlock\fR is omitted, block \fB0\fR is assumed. If
-\fIendBlock\fR is omitted, the last block of the disk is assumed.
+\fB-l\fR \fIdiskLabel\fR
+Specify the label to be written to disk after formatting. If no label is
+specified, a sensible default is used. \fIdiskLabel\fR is interpreted as
+ASCII string and is automatically converted to EBCDIC.
 
 .TP
 \fIdiskSpec\fR
 This parameter specified the device to be formatted. It also can be
 given in two variants:
 .sp
-	\fB-f\fR \fB/dev/dd\fR\fIX\fR
+	\fB-f\fR \fB/dev/dasd\fR\fIX\fR
 .br
 or
 .br
@@ -63,7 +57,7 @@
 The first form uses the commonly used
 .SM UNIX
 device notation where \fIX\fR is a single lowercase letter.
-The second form uses simply the VM vdev number.
+The second form uses simply the device number.
 
 .SH BUGS
 None so far ;-)
diff -u --recursive --new-file v2.4.1/linux/arch/s390/tools/dasdfmt/dasdfmt.c linux/arch/s390/tools/dasdfmt/dasdfmt.c
--- v2.4.1/linux/arch/s390/tools/dasdfmt/dasdfmt.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/tools/dasdfmt/dasdfmt.c	Tue Feb 13 14:13:44 2001
@@ -12,6 +12,8 @@
  *   detect non-switch parameters ("dasdfmt -n 170 XY") and complain about them 
  */
 
+/* #define _LINUX_BLKDEV_H */
+
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/types.h>
@@ -25,19 +27,25 @@
 #include <string.h>
 #include <dirent.h>
 #include <mntent.h>
-#include "../../../drivers/s390/block/dasd.h" /* uses DASD_PARTN_BITS */
 #define __KERNEL__ /* we want to use kdev_t and not have to define it */
 #include <linux/kdev_t.h>
 #undef __KERNEL__
 
+#include <linux/fs.h>
+#include <asm/dasd.h>
+#include <linux/hdreg.h>
+
 #define EXIT_MISUSE 1
 #define EXIT_BUSY 2
 #define TEMPFILENAME "/tmp/ddfXXXXXX"
 #define TEMPFILENAMECHARS 8  /* 8 characters are fixed in all temp filenames */
-#define IOCTL_COMMAND 'D' << 8
 #define SLASHDEV "/dev/"
 #define PROC_DASD_DEVICES "/proc/dasd/devices"
+/* _PATH_MOUNTED is /etc/mtab - /proc/mounts does not show root-fs correctly */
+#define PROC_MOUNTS _PATH_MOUNTED
+#define PROC_SWAPS "/proc/swaps"
 #define DASD_DRIVER_NAME "dasd"
+#define LABEL_LENGTH 10
 #define PROC_LINE_LENGTH 80
 #define ERR_LENGTH 80
 
@@ -66,24 +74,108 @@
 		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
 			"is in invalid format\n",prog_name);}
 
-typedef struct {
-	int start_unit;
-	int stop_unit;
-	int blksize;
-} format_data_t;
-
-char prog_name[]="dasd_format";
+char *prog_name;/*="dasdfmt";*/
 char tempfilename[]=TEMPFILENAME;
 
+__u8 _ascebc[256] =
+{
+ /*00 NUL   SOH   STX   ETX   EOT   ENQ   ACK   BEL */
+     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08  BS    HT    LF    VT    FF    CR    SO    SI */
+ /*              ->NL                               */
+     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10 DLE   DC1   DC2   DC3   DC4   NAK   SYN   ETB */
+     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ /*18 CAN    EM   SUB   ESC    FS    GS    RS    US */
+ /*                               ->IGS ->IRS ->IUS */
+     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ /*20  SP     !     "     #     $     %     &     ' */
+     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28   (     )     *     +     ,     -    .      / */
+     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30   0     1     2     3     4     5     6     7 */
+     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38   8     9     :     ;     <     =     >     ? */
+     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40   @     A     B     C     D     E     F     G */
+     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48   H     I     J     K     L     M     N     O */
+     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50   P     Q     R     S     T     U     V     W */
+     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58   X     Y     Z     [     \     ]     ^     _ */
+     0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+ /*60   `     a     b     c     d     e     f     g */
+     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68   h     i     j     k     l     m     n     o */
+     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70   p     q     r     s     t     u     v     w */
+     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78   x     y     z     {     |     }     ~    DL */
+     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ /*80*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*88*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*90*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*98*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E0        sz						*/
+     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F8*/
+     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+void convert_label(char *str)
+{
+	int i;
+	for (i=0;i<LABEL_LENGTH;i++) str[i]=_ascebc[str[i]];
+}
+
 void
 exit_usage(int exitcode)
 {
-	printf("Usage: %s [-htvyV] [-b blocksize] <range> <diskspec>\n\n",
-	       prog_name);
-	printf("       where <range> is either\n");
-	printf("           -s start_track -e end_track\n");
+#ifdef RANGE_FORMATTING
+	printf("Usage: %s [-htvyLV] [-l <label>] [-b <blocksize>] [<range>] " \
+		"<diskspec>\n\n",prog_name);
+#else /* RANGE_FORMATTING */
+	printf("Usage: %s [-htvyLV] [-l <label>] [-b <blocksize>] " \
+		"<diskspec>\n\n",prog_name);
+#endif /* RANGE_FORMATTING */
+	printf("       -t means testmode\n");
+	printf("       -v means verbose mode\n");
+	printf("       -V means print version\n");
+	printf("       -L means don't write disk label\n");
+	printf("       <label> is a label which is converted to EBCDIC and " \
+		"written to disk\n");
+	printf("       <blocksize> has to be power of 2 and at least 512\n");
+#ifdef RANGE_FORMATTING
+	printf("       <range> is either\n");
+	printf("           -s <start_track> -e <end_track>\n");
 	printf("       or\n");
-	printf("           -r start_track-end_track\n");
+	printf("           -r <start_track>-<end_track>\n");
+#endif /* RANGE_FORMATTING */
 	printf("       and <diskspec> is either\n");
 	printf("           -f /dev/dasdX\n");
 	printf("       or\n");
@@ -106,9 +198,9 @@
 			PROC_DASD_DEVICES ": %s (do you have the /proc " \
 			"filesystem enabled?)\n",prog_name,strerror(errno));
 
-	fgets(line,sizeof(line),file); /* omit first line */
+	/*	fgets(line,sizeof(line),file); omit first line */ 
 	while (fgets(line,sizeof(line),file)!=NULL) {
-		rc=sscanf(line,"%X%d%d",&d,&ma_i,&mi_i);
+		rc=sscanf(line,"%X %*[(A-Z)] at (%d:%d)",&d,&ma_i,&mi_i);
 		ma=ma_i;
 		mi=mi_i;
 		if ( (rc==3) &&
@@ -253,6 +345,7 @@
 	char *str;
 	char output[60],o2[12];
 
+#ifdef RANGE_FORMATTING
 	i=params.start_unit;
 	do {
 		params.start_unit=i;
@@ -284,6 +377,7 @@
 			ASK_CHECK_PARAM(CHECK_END);
 		}
 	} while (rc!=1);
+#endif /* RANGE_FORMATTING */
 
 	i=params.blksize;
 	do {
@@ -320,8 +414,8 @@
 	/*
 	 * first, check filesystems
 	 */
-	if (!(f = fopen(_PATH_MOUNTED, "r")))
-		ERRMSG_EXIT(EXIT_FAILURE, "%s: %s\n", _PATH_MOUNTED,
+	if (!(f = fopen(PROC_MOUNTS, "r")))
+		ERRMSG_EXIT(EXIT_FAILURE, "%s: %s\n", PROC_MOUNTS,
 			strerror(errno));
 	while ((ment = getmntent(f))) {
 		if (stat(ment->mnt_fsname, &stbuf) == 0)
@@ -337,8 +431,8 @@
 	/*
 	 * second, check active swap spaces
 	 */
-	if (!(f = fopen("/proc/swaps", "r")))
-		ERRMSG_EXIT(EXIT_FAILURE, "/proc/swaps: %s", strerror(errno));
+	if (!(f = fopen(PROC_SWAPS, "r")))
+		ERRMSG_EXIT(EXIT_FAILURE, PROC_SWAPS " %s", strerror(errno));
 	/*
 	 * skip header line
 	 */
@@ -362,12 +456,15 @@
 
 void
 do_format_dasd(char *dev_name,format_data_t format_params,int testmode,
-	int verbosity,int withoutprompt)
+	int verbosity,int writenolabel,int labelspec,
+	char *label,int withoutprompt,int devno)
 {
 	int fd,rc;
 	struct stat stat_buf;
 	kdev_t minor_no,major_no;
-	int devno;
+	int new_blksize;
+	unsigned int label_position;
+	struct hd_geometry new_geometry;
 	char inp_buffer[5]; /* to contain yes */
 
 	fd=open(dev_name,O_RDWR);
@@ -390,6 +487,10 @@
 		minor_no=MINOR(stat_buf.st_rdev);
 	}
 	check_mounted(major_no, minor_no);
+
+	if ((!writenolabel) && (!labelspec)) {
+		sprintf(label,"LNX1 x%04x",devno);
+	}
 	
 	if ( ((withoutprompt)&&(verbosity>=1)) ||
 		(!withoutprompt) ) {
@@ -400,6 +501,11 @@
 		printf("   Device number of device : 0x%x\n",devno);
 		printf("   Major number of device  : %u\n",major_no);
 		printf("   Minor number of device  : %u\n",minor_no);
+		printf("   Labelling device        : %s\n",(writenolabel)?
+			"no":"yes");
+		if (!writenolabel)
+			printf("   Disk label              : %s\n",label);
+#ifdef RANGE_FORMATTING
 		printf("   Start track             : %d\n" \
 			,format_params.start_unit);
 		printf("   End track               : ");
@@ -407,6 +513,7 @@
 			printf("last track of disk\n");
 		else
 			printf("%d\n",format_params.stop_unit);
+#endif /* RANGE_FORMATTING */
 		printf("   Blocksize               : %d\n" \
 			,format_params.blksize);
 		if (testmode) printf("Test mode active, omitting ioctl.\n");
@@ -416,8 +523,8 @@
 		if (!withoutprompt) {
 			printf("\n--->> ATTENTION! <<---\n");
 			printf("All data in the specified range of that " \
-				"device will be lost.\nType yes to continue" \
-				", no will leave the disk untouched: ");
+				"device will be lost.\nType \"yes\" to " \
+				"continue, no will leave the disk untouched: ");
 			fgets(inp_buffer,sizeof(inp_buffer),stdin);
 			if (strcasecmp(inp_buffer,"yes") &&
 				strcasecmp(inp_buffer,"yes\n")) {
@@ -430,13 +537,70 @@
 		if ( !(  (withoutprompt)&&(verbosity<1) ))
 			printf("Formatting the device. This may take a " \
 				"while (get yourself a coffee).\n");
-		rc=ioctl(fd,IOCTL_COMMAND,format_params);
+		rc=ioctl(fd,BIODASDFORMAT,format_params);
 		if (rc)
 			ERRMSG_EXIT(EXIT_FAILURE,"%s: the dasd driver " \
 				"returned with the following error " \
 				"message:\n%s\n",prog_name,strerror(errno));
 		printf("Finished formatting the device.\n");
 
+		if (!writenolabel) {
+			if (verbosity>0)
+				printf("Retrieving disk geometry... ");
+
+			rc=ioctl(fd,HDIO_GETGEO,&new_geometry);
+			if (rc) {
+				ERRMSG("%s: the ioctl call to get geometry " \
+					"returned with the following error " \
+					"message:\n%s\n",prog_name,
+					strerror(errno));
+				goto reread;
+			}
+	
+
+			rc=ioctl(fd,BLKGETSIZE,&new_blksize);
+			if (rc) {
+				ERRMSG("%s: the ioctl call to get blocksize " \
+					"returned with the following error " \
+					"message:\n%s\n",prog_name,
+					strerror(errno));
+				goto reread;
+			}
+	
+			if (verbosity>0) printf("done\n");
+
+			label_position=new_geometry.start*new_blksize;
+	
+			if (verbosity>0) printf("Writing label... ");
+			convert_label(label);
+			rc=lseek(fd,label_position,SEEK_SET);
+			if (rc!=label_position) {
+				ERRMSG("%s: lseek on the device to %i " \
+					"failed with the following error " \
+					"message:\n%s\n",prog_name,
+					label_position,strerror(errno));
+				goto reread;
+			}
+			rc=write(fd,label,LABEL_LENGTH);
+			if (rc!=LABEL_LENGTH) {
+				ERRMSG("%s: writing the label only wrote %d " \
+					"bytes.\n",prog_name,rc);
+				goto reread;
+			}
+
+			sync();
+			sync();
+
+			if (verbosity>0) printf("done\n");
+		}
+ reread:
+		printf("Rereading the partition table... ");
+		rc=ioctl(fd,BLKRRPART,NULL);
+		if (rc) {
+			ERRMSG("%s: error during rereading the partition " \
+			       "table: %s.\n",prog_name,strerror(errno));
+		} else printf("done.\n");
+
 		break;
 	}
 
@@ -452,11 +616,13 @@
 	int verbosity;
 	int testmode;
 	int withoutprompt;
+	int writenolabel,labelspec;
 
 	char *dev_name;
 	int devno;
 	char *dev_filename,*devno_param_str,*range_param_str;
 	char *start_param_str,*end_param_str,*blksize_param_str;
+	char label[LABEL_LENGTH+1];
 	
 	format_data_t format_params;
 
@@ -465,23 +631,30 @@
 	char *endptr;
 
 	char c1,c2,cbuffer[6]; /* should be able to contain -end plus 1 char */
-	int i1,i2;
+	int i,i1,i2;
 	char *str;
 
 	int start_specified,end_specified,blksize_specified;
 	int devfile_specified,devno_specified,range_specified;
 
 	/******************* initialization ********************/
+	prog_name=argv[0];
 
 	endptr=NULL;
 
 	/* set default values */
-	format_params.start_unit=0;
-	format_params.stop_unit=-1;
-	format_params.blksize=4096;
+	format_params.start_unit=DASD_FORMAT_DEFAULT_START_UNIT;
+	format_params.stop_unit=DASD_FORMAT_DEFAULT_STOP_UNIT;
+	format_params.blksize=DASD_FORMAT_DEFAULT_BLOCKSIZE;
+	format_params.intensity=DASD_FORMAT_DEFAULT_INTENSITY;
 	testmode=0;
 	verbosity=0;
 	withoutprompt=0;
+	writenolabel=0;
+	labelspec=0;
+	for (i=0;i<LABEL_LENGTH;i++) label[i]=' ';
+	label[LABEL_LENGTH]=0;
+
 	start_specified=end_specified=blksize_specified=0;
 	devfile_specified=devno_specified=range_specified=0;
 
@@ -490,7 +663,10 @@
 	/* avoid error message generated by getopt */
 	opterr=0;
 
-	while ( (oc=getopt(argc,argv,"r:s:e:b:n:f:hty?vV")) !=EOF) {
+#ifdef RANGE_FORMATTING
+	while ( (oc=getopt(argc,argv,"r:s:e:b:n:l:f:hLty?vV")) !=EOF) {
+#endif /* RANGE_FORMATTING */
+	while ( (oc=getopt(argc,argv,"b:n:l:f:hLty?vV")) !=EOF) {
 		switch (oc) {
 		case 'y':
 			withoutprompt=1;
@@ -515,6 +691,18 @@
 			printf("%s version 0.99\n",prog_name);
 			exit(0);
 
+		case 'l':
+			strncpy(label,optarg,LABEL_LENGTH);
+			if (strlen(optarg)<LABEL_LENGTH)
+				label[strlen(optarg)]=' ';
+			labelspec++;
+			break;
+
+		case 'L':
+			writenolabel++;
+			break;
+
+#ifdef RANGE_FORMATTING
 		case 's' :
 			start_param_str=optarg;
 			start_specified++;
@@ -525,6 +713,12 @@
 			end_specified++;
 			break;
 
+		case 'r' :
+			range_param_str=optarg;
+			range_specified++;
+			break;
+#endif /* RANGE_FORMATTING */
+
 		case 'b' :
 			blksize_param_str=optarg;
 			blksize_specified++;
@@ -539,10 +733,6 @@
 			dev_filename=optarg;
 			devfile_specified++;
 			break;
-		case 'r' :
-			range_param_str=optarg;
-			range_specified++;
-			break;
 		}
 	}
 
@@ -594,6 +784,8 @@
 	CHECK_SPEC_MAX_ONCE(start_specified,"start track");
 	CHECK_SPEC_MAX_ONCE(end_specified,"end track");
 	CHECK_SPEC_MAX_ONCE(blksize_specified,"blocksize");
+	CHECK_SPEC_MAX_ONCE(labelspec,"label");
+	CHECK_SPEC_MAX_ONCE(writenolabel,"omit-label-writing flag");
 
 	if (devno_specified)
 		PARSE_PARAM_INTO(devno,devno_param_str,16,"device number");
@@ -616,9 +808,9 @@
 	str=check_param(CHECK_ALL,format_params);
 	if (str!=NULL) ERRMSG_EXIT(EXIT_MISUSE,"%s: %s\n",prog_name,str);
 
-	/*************** issue the real command *****************/
+	/******* issue the real command and reread part table *******/
 	do_format_dasd(dev_name,format_params,testmode,verbosity,
-		withoutprompt);
+		writenolabel,labelspec,label,withoutprompt,devno);
 
 	/*************** cleanup ********************************/
 	if (strncmp(dev_name,TEMPFILENAME,TEMPFILENAMECHARS)==0) {
diff -u --recursive --new-file v2.4.1/linux/arch/s390/tools/silo/Makefile linux/arch/s390/tools/silo/Makefile
--- v2.4.1/linux/arch/s390/tools/silo/Makefile	Fri May 12 11:41:45 2000
+++ linux/arch/s390/tools/silo/Makefile	Tue Feb 13 14:13:44 2001
@@ -1,13 +1,13 @@
 all: silo
 
 silo.o: silo.c
-	$(CROSS_COMPILE)gcc -c -o silo.o -O2 silo.c
+	$(CC) -c -o silo.o -O2 silo.c
 
 cfg.o: cfg.c
-	$(CROSS_COMPILE)gcc -c -o cfg.o -O2 cfg.c
+	$(CC) -c -o cfg.o -O2 cfg.c
 
 silo: silo.o cfg.o
-	$(CROSS_COMPILE)gcc -o $@ $^
+	$(CC) -o $@ $^
 	$(STRIP) $@
 
 clean:
diff -u --recursive --new-file v2.4.1/linux/arch/s390/tools/silo/silo.c linux/arch/s390/tools/silo/silo.c
--- v2.4.1/linux/arch/s390/tools/silo/silo.c	Fri May 12 11:41:45 2000
+++ linux/arch/s390/tools/silo/silo.c	Tue Feb 13 14:13:44 2001
@@ -45,7 +45,7 @@
   
 /* from dasd.h */
 #define DASD_PARTN_BITS 2
-#define BIODASDRWTB _IOWR('D',5,int)
+#define BIODASDRWTB _IOWR('D',0,int)
 /* end */
 
 #define SILO_CFG "/etc/silo.conf"
@@ -554,7 +554,7 @@
 main (int argct, char *argv[])
 {
   int rc = 0;
-  char *save;
+  char *save=NULL;
   char *tmpdir=getenv("TMPDIR");
   if (tmpdir) {
     NTRY( save=(char*)malloc(strlen(tmpdir)));
diff -u --recursive --new-file v2.4.1/linux/arch/s390/vmlinux.lds linux/arch/s390/vmlinux.lds
--- v2.4.1/linux/arch/s390/vmlinux.lds	Fri May 12 11:41:45 2000
+++ linux/arch/s390/vmlinux.lds	Tue Feb 13 14:13:44 2001
@@ -26,6 +26,10 @@
   __ksymtab : { *(__ksymtab) }
   __stop___ksymtab = .;
 
+  __start___kallsyms = .;       /* All kernel symbols */
+  __kallsyms : { *(__kallsyms) }
+  __stop___kallsyms = .;
+
   _etext = .;			/* End of text section */
 
   .data : {			/* Data */
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/Makefile linux/arch/s390x/Makefile
--- v2.4.1/linux/arch/s390x/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,70 @@
+
+# s390/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# 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.
+#
+# Copyright (C) 1994 by Linus Torvalds
+#
+
+LD=$(CROSS_COMPILE)ld -m elf64_s390
+CPP=$(CC) -E
+OBJCOPY=$(CROSS_COMPILE)objcopy -O binary -R .note -R .comment -S
+LDFLAGS=-e start
+LINKFLAGS =-T $(TOPDIR)/arch/s390x/vmlinux.lds $(LDFLAGS)
+MODFLAGS += -fpic
+
+CFLAGS_PIPE := -pipe
+CFLAGS_NSR  := -fno-strength-reduce
+CFLAGS := $(CFLAGS) $(CFLAGS_PIPE) $(CFLAGS_NSR)
+
+HEAD := arch/s390x/kernel/head.o arch/s390x/kernel/init_task.o
+
+SUBDIRS := $(SUBDIRS) arch/s390x/mm arch/s390x/kernel arch/s390x/lib \
+           drivers/s390
+CORE_FILES := arch/s390x/mm/mm.o arch/s390x/kernel/kernel.o $(CORE_FILES) \
+           drivers/s390/io.o
+LIBS := $(TOPDIR)/arch/s390x/lib/lib.a $(LIBS) $(TOPDIR)/arch/s390x/lib/lib.a
+
+all: image listing
+
+listing: vmlinux
+	@$(MAKEBOOT) listing
+
+arch/s390x/kernel: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/s390x/kernel
+
+arch/s390x/mm: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=arch/s390x/mm
+
+drivers/s390: dummy
+	$(MAKE) linuxsubdirs SUBDIRS=drivers/s390
+
+MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+MAKESILO = $(MAKE) -C arch/$(ARCH)/tools/silo
+
+MAKEDASDFMT = $(MAKE) -C arch/$(ARCH)/tools/dasdfmt
+
+silo:
+	@$(MAKE) -C arch/$(ARCH)/tools/silo
+
+dasdfmt:
+	@$(MAKE) -C arch/$(ARCH)/tools/dasdfmt
+
+image: vmlinux 
+	@$(MAKEBOOT) image
+
+archclean:
+	@$(MAKEBOOT) clean
+
+archmrproper:
+
+archdep:
+	@$(MAKEBOOT) dep
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/boot/Makefile linux/arch/s390x/boot/Makefile
--- v2.4.1/linux/arch/s390x/boot/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/boot/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,37 @@
+#
+# Makefile for the linux s390-specific parts of the memory manager.
+#
+# 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...
+
+OBJCOPY = $(CROSS_COMPILE)objcopy
+
+O_TARGET := 
+
+include $(TOPDIR)/Rules.make
+
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+%.lnk: %.o
+	$(LD) -Ttext 0x0 -o $@ $<
+
+%.boot: %.lnk
+	$(OBJCOPY) -O binary $< $@
+
+image: $(CONFIGURE) $(TOPDIR)/vmlinux \
+	iplfba.boot ipleckd.boot ipldump.boot
+	$(OBJCOPY) -O binary $(TOPDIR)/vmlinux image
+	$(NM) $(TOPDIR)/vmlinux | grep -v '\(compiled\)\|\( [aU] \)\|\(\.\)\|\(LASH[RL]DI\)' | sort > $(TOPDIR)/System.map
+
+listing: ../../../vmlinux
+	$(OBJDUMP) --disassemble --disassemble-all --disassemble-zeroes --reloc $(TOPDIR)/vmlinux > listing
+
+dep:
+
+clean:
+	rm -f image listing iplfba.boot ipleckd.boot ipldump.boot
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/boot/ipldump.S linux/arch/s390x/boot/ipldump.S
--- v2.4.1/linux/arch/s390x/boot/ipldump.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/boot/ipldump.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,178 @@
+/*
+ *  arch/s390/boot/ipldump.S
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ *  Tape dump ipl record. Put it on a tape and ipl from it and it will
+ *  write a dump of the real storage after the ipl record on that tape.
+ */
+
+#include <asm/setup.h>
+#include <asm/lowcore.h>
+
+#define IPL_BS 1024
+        .org   0
+        .long  0x00080000,0x80000000+_start    # The first 24 bytes are loaded
+        .long  0x07000000,0x60000001           # by ipl to addresses 0-23.
+        .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
+        .long  0x00000000,0x00000000
+        .long  0x00000000,0x00000000           # svc old psw
+        .long  0x00000000,0x00000000           # program check old psw
+        .long  0x00000000,0x00000000           # machine check old psw
+        .long  0x00000000,0x00000000           # io old psw
+        .long  0x00000000,0x00000000
+        .long  0x00000000,0x00000000
+        .long  0x00000000,0x00000000
+        .long  0x000a0000,0x00000058           # external new psw
+        .long  0x000a0000,0x00000060           # svc new psw
+        .long  0x000a0000,0x00000068           # program check new psw
+        .long  0x000a0000,0x00000070           # machine check new psw
+        .long  0x00080000,0x80000000+.Lioint   # io new psw
+
+        .org   0x100
+        .globl _start
+_start:
+	l     %r1,0xb8                         # load ipl subchannel number
+#
+# find out memory size
+#
+        mvc   104(8),.Lpcmem0            # setup program check handler
+        slr   %r3,%r3
+        lhi   %r2,1
+        sll   %r2,20
+.Lloop0:
+        l     %r0,0(%r3)                 # test page
+        ar    %r3,%r2                    # add 1M
+        jnm   .Lloop0                    # r1 < 0x80000000 -> loop
+.Lchkmem0:
+        n     %r3,.L4malign0             # align to multiples of 4M
+        st    %r3,.Lmemsize              # store memory size
+.Lmemok:
+
+#
+# first write a tape mark
+#
+        bras  %r14,.Ltapemark
+#
+# write real storage to tape
+#	
+ 	slr   %r2,%r2                          # start at address 0
+        bras  %r14,.Lwriter                    # load ramdisk
+#
+# write another tape mark
+#
+        bras  %r14,.Ltapemark
+#
+# everything written, stop processor
+#
+        lpsw  .Lstopped
+#
+# subroutine for writing to tape
+# Paramters:	
+#  R1 = device number
+#  R2 = start address
+#  R3 = length
+.Lwriter:	
+        st    %r14,.Lldret
+        la    %r12,.Lorbread                   # r12 = address of orb 
+	la    %r5,.Lirb                        # r5 = address of irb
+        st    %r2,.Lccwwrite+4                 # initialize CCW data addresses
+        lctl  %c6,%c6,.Lcr6               
+        slr   %r2,%r2
+.Lldlp:
+        lhi   %r6,3                            # 3 retries
+.Lssch:
+        ssch  0(%r12)                          # write chunk of IPL_BS bytes
+        jnz   .Llderr
+.Lw4end:
+        bras  %r14,.Lwait4io
+        tm    8(%r5),0x82                      # do we have a problem ?
+        jnz   .Lrecov
+        l     %r0,.Lccwwrite+4                 # update CCW data addresses
+        ahi   %r0,IPL_BS
+        st    %r0,.Lccwwrite+4
+        clr   %r0,%r3                          # enough ?
+        jl    .Lldlp
+.Ldone:
+        l     %r14,.Lldret
+        br    %r14                             # r2 contains the total size
+.Lrecov:
+        bras  %r14,.Lsense                     # do the sensing
+        brct  %r6,.Lssch                       # dec. retry count & branch
+        j     .Llderr
+.Ltapemark:
+        st    %r14,.Lldret
+        la    %r12,.Lorbmark                   # r12 = address of orb
+        la    %r5,.Lirb                        # r5 = address of irb
+        lctl  %c6,%c6,.Lcr6
+        ssch  0(%r12)                          # write a tape mark
+        jnz   .Llderr
+        bras  %r14,.Lwait4io
+        l     %r14,.Lldret
+        br    %r14
+#
+# Sense subroutine
+#
+.Lsense:
+        st    %r14,.Lsnsret
+        la    %r7,.Lorbsense              
+        ssch  0(%r7)                           # start sense command
+        jnz   .Llderr
+        bras  %r14,.Lwait4io
+        l     %r14,.Lsnsret
+        tm    8(%r5),0x82                      # do we have a problem ?
+        jnz   .Llderr
+        br    %r14
+#
+# Wait for interrupt subroutine
+#
+.Lwait4io:
+        lpsw  .Lwaitpsw                 
+.Lioint:
+        c     %r1,0xb8                         # compare subchannel number
+        jne   .Lwait4io
+        tsch  0(%r5)
+        slr   %r0,%r0
+        tm    8(%r5),0x82                      # do we have a problem ?
+        jnz   .Lwtexit
+        tm    8(%r5),0x04                      # got device end ?
+        jz    .Lwait4io
+.Lwtexit:
+        br    %r14
+.Llderr:
+        lpsw  .Lcrash              
+
+        .align 8
+.Lorbread:
+	.long  0x00000000,0x0080ff00,.Lccwwrite
+        .align 8
+.Lorbsense:
+        .long  0x00000000,0x0080ff00,.Lccwsense
+        .align 8
+.Lorbmark:
+        .long  0x00000000,0x0080ff00,.Lccwmark
+        .align 8
+.Lccwwrite:
+        .long  0x01200000+IPL_BS,0x00000000
+.Lccwsense:
+        .long  0x04200001,0x00000000
+.Lccwmark:
+        .long  0x1f200001,0x00000000
+.Lwaitpsw:
+	.long  0x020a0000,0x80000000+.Lioint
+
+.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6:  .long  0xff000000
+        .align 8
+.Lcrash:.long  0x000a0000,0x00000000
+.Lstopped: .long 0x000a0000,0x00001234
+.Lpcmem0:.long  0x00080000,0x80000000 + .Lchkmem0
+.L4malign0:.long 0xffc00000
+.Lmemsize:.long 0
+.Lldret:.long  0
+.Lsnsret: .long 0
+
+         .org IPL_BS
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/boot/ipleckd.S linux/arch/s390x/boot/ipleckd.S
--- v2.4.1/linux/arch/s390x/boot/ipleckd.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/boot/ipleckd.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,303 @@
+#
+#  arch/s390/boot/ipleckd.S
+#    IPL record for 3380/3390 DASD
+#
+#  S390 version
+#    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+#    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
+#
+#
+# FIXME:	 should use the countarea to determine the blocksize
+# FIXME:	 should insert zeroes into memory when filling holes
+# FIXME:	 calculate blkpertrack from rdc data and blksize
+
+# change 09/20/00       removed obsolete store of ipldevice to textesegment
+
+# Usage of registers
+# r1:	ipl subchannel ( general use, dont overload without save/restore !)
+# r10:
+# r13:	base register 	index to 0x0000
+# r14:	callers address
+# r15:	temporary save register (we have no stack!)
+
+# storage layout:
+
+#include <asm/lowcore.h>
+	
+	.org 0
+.psw:	.long 0x00080000,0x80000000+_start
+.ccw1:	.long 0x06000000,0x00001000     # Re-Read enough of bootsector to start
+.ccw2:	.long 0x00000000,0x00000000	# read countarea of record 1 to s/w.
+
+	.org 0x58
+.Lextn:	.long	0x000a0000,0x00000000+.Lextn
+.Lsvcn:	.long	0x000a0000,0x00000000+.Lsvcn
+.Lprgn:	.long	0x00080000,0x00000000+.Lecs
+.Lmcn:	.long	0x000a0000,0x00000000+.Lmcn
+.Lion:	.long   0x00080000,0x80000000+.Lionewaddr
+
+	.org 0xe0
+.Llstad:.long 	0x00000000,0x00000000	# sectorno + ct of bootlist
+
+	.org 0xf0			# Lets start now...
+_start: .globl _start
+	l  	%r1,__LC_SUBCHANNEL_ID	# get IPL-subchannel from lowcore
+	st	%r1,__LC_IPLDEV         # keep it for reipl
+	stsch	.Lrdcdata
+	oi      .Lrdcdata+5,0x84        # enable ssch and multipath mode
+.Lecs:  xi	.Lrdcdata+27,0x01	# enable concurrent sense
+	msch	.Lrdcdata	
+        xi      .Lprgn,6                # restore Wait and d/a bit in PCnew PSW
+	l	%r2,.Lparm
+	mvc     0x0(8,%r2),.Lnull       # set parmarea to null
+	lctl	%c6,%c6,.Lc6     	# enable all interrupts
+.Lrdc:					# read device characteristics
+	la	%r6,.Lrdcccw     
+	st      %r6,.Lorb+8		# store cp-address to orb
+	bras    %r15,.Lssch		# start I/O
+	oi	.Llodata+1,0x80
+	lh	%r5,.Lcountarea+6	# init r5 from countarea
+	stcm	%r5,3,.Lrdccw+2		# and store into rd template *FIXME*
+	stcm	%r5,3,.Llodata+14	# and store into lodata *FIXME*
+.Lbootlist:	
+	l	%r2,.Llstad	
+	l	%r3,.Lblklst     
+	lhi	%r4,1
+	bras	%r14,.Lreadblks
+.Lloader:	
+	l	%r10,.Lblklst     	# r10 is index to bootlist
+	lhi	%r5,4			# r5:	skip 4 blocks = firstpage....
+.Lkloop:
+	clc	.Lnull(8),0(%r10)	# test blocklist	
+	jz	.Lchkparm		# end of list?
+	l	%r2,0(%r10)		# get startblock to r2
+	slr	%r4,%r4			# erase r4
+	icm	%r4,1,7(%r10)		# get blockcount
+	slr	%r3,%r3			# get address to r3
+	icm 	%r3,0xe,4(%r10)
+	chi	%r5,0			# still blocks to skip?
+	jz	.Ldoread		# no: start reading
+	cr	%r5,%r4			# #skipblocks >= blockct?
+	jm	.L007			# no: skip the blocks one by one
+.L006:	
+	sr	%r5,%r4			# decrease number of blocks to skip
+	j	.Lkcont			# advance to next entry
+.L007:	
+	ahi	%r2,1			# skip 1 block...
+	bctr    %r4,0                   # update blockct
+	ah	%r3,.Lcountarea+6       # increment address
+	bct	%r5,.L007		# 4 blocks skipped?
+.Ldoread:
+	ltr	%r2,%r2			# test startblock
+	jz	.Lzeroes		# startblocks is zero (hole)
+.Ldiskread:	
+	bras	%r14,.Lreadblks
+	j	.Lkcont
+.Lzeroes:
+	lr	%r2,%r3
+.L001:	slr	%r3,%r3
+	icm	%r3,3,.Lcountarea+6     # get blocksize
+	slr	%r5,%r5			# no bytes to move
+.L008:	mvcle	%r2,%r4,0   		# fill zeroes to storage
+	jo	.L008			# until block is filled
+	brct	%r4,.L001   		# skip to next block
+.Lkcont:	
+	ahi	%r10,8
+	j	.Lkloop
+.Lchkparm:
+	lm	%r3,%r4,.Lstart         # load .Lstart and .Lparm
+	clc	0x0(4,%r4),.Lnull     
+	je	.Lrunkern
+	mvc	0x480(128,%r3),0(%r4)	# move 1k-0x80 to parmarea
+	mvc	0x500(256,%r3),0x80(%r4)
+	mvc	0x600(256,%r3),0x180(%r4)
+	mvc	0x700(256,%r3),0x280(%r4)
+.Lrunkern:
+#	lhi	%r2,17
+#	sll	%r2,12
+#	st	%r1,0xc6c(%r2)		# store iplsubchannel to lowcore
+#	st	%r1,0xc6c		# store iplsubchannel to lowcore
+	br	%r3
+# This function does the start IO
+# r2:	number of first block to read ( input by caller )
+# r3:	address to read data to ( input by caller )
+# r4:	number of blocks to read ( input by caller )
+# r5:	destroyed
+# r6:	blocks per track ( input by caller )
+# r7:	number of heads 
+# r8:	
+# r9:	
+# r10:	
+# r11:	temporary register
+# r12:	local use for base address
+# r13:	base address for module
+# r14:	address of caller for subroutine
+# r15:	temporary save register (since we have no stack)
+.Lreadblks:
+	la	%r12,.Ldeccw     
+	st	%r12,8+.Lorb		# store cpaddr to orb
+	ahi	%r12,0x10		# increment r12 to point to rdccw
+	oi	1(%r12),0x40		# set CC in rd template
+	# first setup the read CCWs
+	lr	%r15,%r4		# save number or blocks
+	slr	%r7,%r7
+	icm	%r7,3,.Lrdcdata+14      # load heads to r7
+	lhi     %r6,9
+	clc     .Lrdcdata+3(2),.L9345
+	je	.L011
+	lhi	%r6,10
+	clc	.Lrdcdata+3(2),.L3380
+	je	.L011
+	lhi	%r6,12
+	clc	.Lrdcdata+3(2),.L3390     
+	je	.L011			
+        bras 	%r14,.Ldisab
+.L011:	
+	# loop for nbl times
+.Lrdloop:	
+	mvc	0(8,%r12),.Lrdccw     	# copy template to this ccw
+	st	%r3,4(%r12)		# store target address to this ccw
+	bct	%r4,.L005		# decrement no of blks still to do
+	ni	1(%r12),0x3f		# delete CC from last ccw
+	lr	%r4,%r15		# restore number of blocks
+	# read CCWs are setup now		
+	stcm	%r4,3,.Llodata+2     	# store blockno to lodata clears r4
+	ar	%r4,%r2			# r4 (clear): ebl = blk + nbl
+	bctr    %r4,0			# decrement r4 ( last blk touched 
+	srda	%r2,32			# trk = blk / bpt, bot = blk % bpt 
+	dr	%r2,%r6			# r3: trk, r2: bot
+	ahi	%r2,1			# bot++ ( we start counting at 1 )
+	stcm	%r2,1,.Llodata+12     	# store bot to lodata
+	xr 	%r2,%r2			# cy  = trk / heads, hd  = trk % heads
+	dr	%r2,%r7			# r3: cy, r2: hd
+	sll	%r3,16			# combine to CCHH in r3
+	or	%r3,%r2
+	st	%r3,.Ldedata+8     	# store cchh to dedata	
+	st	%r3,.Llodata+4     	# store cchh to lodata	
+	st	%r3,.Llodata+8     	# store cchh to lodata	
+	lr	%r15,%r5		# save r5
+	srda	%r4,32			# tr2 = ebl / bpt
+	dr	%r4,%r6			# r5: tr2, r4: bot2
+	xr 	%r4,%r4			# cy2 = tr2 / heads, hd2 = hd2 % heads
+	dr	%r4,%r7			# r5: cy2, r4: hd2 
+	stcm	%r5,3,.Ldedata+12     	# store cy2,hd2 to dedata
+	stcm	%r4,3,.Ldedata+14     	# store cy2,hd2 to dedata
+	lr	%r5,%r15		# restore r5
+	# CCWs are setup now, arent they?
+	bras	%r15,.Lssch		# start I/O
+	br	%r14			# return to caller
+.L005:	
+	ah 	%r3,.Lcountarea+6     	# add blocksize to target address
+	ahi	%r12,8			# add sizeof(ccw) to base address
+	j	.Lrdloop
+# end of function
+# This function does the start IO
+# r1:	Subchannel number
+# r8:	ORB address
+# r9:	IRB address
+.Lssch:
+	lhi     %r13,10			# initialize retries
+.L012:	
+	ssch	.Lorb			# start I/O
+	jz	.Ltpi			# ok?
+	bras	%r14,.Ldisab		# error
+.Ltpi:	
+	lpsw	.Lwaitpsw     		# load wait-PSW
+.Lionewaddr:	
+	c	%r1,0xb8     		# compare to ipl subhchannel
+	jnz	.Ltpi			# not equal: loop
+	clc	0xbc(4),.Lorb 		# cross check the intparm
+	jnz	.Ltpi               	# not equal:	loop 
+	tsch    .Lirb			# get status
+	tm	.Lirb+9,0xff		# channel status ?
+	jz	.L003			# CS == 0x00
+	bras	%r14,.Ldisab		# error
+.L003:
+	tm	.Lirb+8,0xf3		# DS different from CE/DE
+	jz	.L004			# ok ?
+	bct	%r13,.L012		# retries <= 5 ?
+	bras	%r14,.Ldisab		# error
+.L004:
+	tm	.Lirb+8,0x04		# DE set?
+	jz	.Ltpi			# DE not set, loop
+.Lsschend:
+	br	%r15			# return to caller
+# end of function
+# In case of error goto disabled wait with %r14 containing the caller
+.Ldisab:
+	st	%r14,.Ldisabpsw+4     
+	lpsw	.Ldisabpsw     
+
+# FIXME pre-initialized data should be listed first
+# NULLed storage can be taken from anywhere ;) 
+.Lblklst:	
+	.long   0x00002000     
+	.align 8
+.Ldisabpsw: 
+	.long 0x000a0000,0x00000000
+.Lwaitpsw:
+	.long 0x020a0000,0x00000000+.Ltpi
+.Lorb:	
+	.long 0x0049504c,0x0080ff00	# intparm is " IPL"
+.Lc6:	.long 0xff000000
+.Lstart:
+	.long	0x00010000              # do not separate .Lstart and .Lparm
+.Lparm:	
+	.long	0x00008000              # they are loaded with a LM
+.L3390:
+	.word 	0x3390
+.L9345:
+	.word	0x9345
+.L3380:
+	.word	0x3380
+.Lnull:	
+	.long 0x00000000,0x00000000
+	.align 4
+.Lrdcdata:
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+.Lirb:
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+	.long 0x00000000,0x00000000
+.Lcountarea:	
+	.word 0x0000			# cyl;
+	.word 0x0000			# head;
+	.byte 0x00			# record;
+	.byte 0x00			# key length;
+	.word 0x0000			# data length == blocksize;
+.Ldedata:
+	.long 0x40c00000,0x00000000
+	.long 0x00000000,0x00000000
+.Llodata:
+	.long 0x06000001,0x00000000
+	.long 0x00000000,0x01000000
+	.long 0x12345678
+	.org 0x7c8
+.Lrdcccw:				# CCW read device characteristics
+	.long 0x64400040,0x00000000+.Lrdcdata
+	.long 0x63400010,0x00000000+.Ldedata
+	.long 0x47400010,0x00000000+.Llodata
+	.long 0x12000008,0x00000000+.Lcountarea
+.Ldeccw:
+	.long 0x63400010,0x00000000+.Ldedata
+.Lloccw:
+	.long 0x47400010,0x00000000+.Llodata
+.Lrdccw:	
+	.long 0x86400000,0x00000000
+	.org 0x800
+# end of pre initialized data is here CCWarea follows
+# from here we load 1k blocklist 
+# end of function
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/boot/iplfba.S linux/arch/s390x/boot/iplfba.S
--- v2.4.1/linux/arch/s390x/boot/iplfba.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/boot/iplfba.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,131 @@
+#
+#  Ipl block for fba devices
+#    Copyright (C) 1998 IBM Corporation
+#    Author(s): Martin Schwidefsky
+#
+#  startup for ipl at address 0
+#  start with restart
+
+# The first 24 byes are loaded by ipl to addresses 0-23 (a PSW and two CCWs).
+# The CCWs on 8-23 are used as a continuation of the implicit ipl channel
+# program. The fba ipl loader only uses the CCW on 8-15 to load the first 512
+# byte block to location 0-511 (the reading starts again at block 0, byte 0).
+# The second CCW is used to store the location of the load list.
+        .org   0
+        .long  0x00080000,0x80000000+_start    # The first 24 byte are loaded
+        .long  0x02000000,0x20000200           # by ipl to addresses 0-23.
+        .long  0x00000001,0x00000001           # (PSW, one CCW & loadlist info).
+
+        .globl _start
+_start:
+	basr  %r13,0
+.LPG0:	
+	l     %r1,0xb8                         # load ipl subchannel number
+        lhi   %r2,0x200                        # location for the loadlist
+        lm    %r3,%r4,0x10                     # blocknr and length of loadlist
+        bras  %r14,.Lloader                    # load loadlist
+
+        lhi   %r11,0x400
+        lhi   %r12,0x200                       # load address of loadlist
+        l     %r3,0(%r12)                      # get first block number
+        l     %r4,4(%r12)                      # get first block count
+        la    %r12,8(%r12)
+        j     .Llistloop
+        .org  0x50
+.Llistloop:
+        lr    %r2,%r11                         # load address
+        lr    %r5,%r4                          # block count
+        mhi   %r5,512
+        la    %r11,0(%r5,%r11)                 # update load address
+        bras  %r14,.Lloader                    # load chunk of the image
+        l     %r3,0(%r12)                      # get next block number
+        icm   %r4,15,4(%r12)                   # get next block count
+        la    %r12,8(%r12)
+        jnz   .Llistloop
+
+#
+# everything loaded, go for it
+#
+        l     %r1,.Lstart-.LPG0(%r13)
+	br    %r1
+
+#
+# subroutine for loading a sequence of block from fba
+# %r2: load address (24 bit address)
+# %r3: number of first block (unsigned long)
+# %r4: number of blocks to load (unsigned short)
+#
+        .org  0xC0
+.Lloader:
+        la    %r5,.Llo-.LPG0(%r13)
+        sth   %r4,2(%r5)                       # initialize block count
+        st    %r3,4(%r5)                       # initialize block number
+        la    %r5,.Lccws-.LPG0(%r13)
+        mhi   %r4,512
+        sth   %r4,22(%r5)                      # initialize byte count
+	icm   %r2,8,16(%r5)
+        st    %r2,16(%r5)                      # initialize CCW data address
+
+        slr   %r2,%r2
+        la    %r3,.Lorb-.LPG0(%r13)            # r2 = address of orb into r2
+        la    %r4,.Ltinfo-.LPG0(%r13)          # r3 = address of tpi info block
+        la    %r5,.Lirb-.LPG0(%r13)            # r4 = address of irb
+
+        lctl  %c6,%c6,.Lc6-.LPG0(%r13)
+.Lldlp:
+        ssch  0(%r3)                           # read blocks
+.Ltpi:
+        tpi   0(%r4)                           # test pending interrupt
+        jz    .Ltpi
+        c     %r1,0(%r4)                       # compare subchannel number
+        jne   .Ltpi
+        tsch  0(%r5)
+        slr   %r0,%r0
+        tm    8(%r5),0x82                      # do we have a problem ?
+        jnz   .Ldwpsw
+        tm    8(%r5),0x04                      # got device end ?
+        jz    .Ltpi
+.Lexit:
+        br    %r14
+
+        .align 8
+.Ldwpsw:.long  0x000a0000,0x00000000
+.Lorb:	.long  0x00000000,0x0000ff00,.Lccws
+.Ltinfo:.long  0
+.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lc6:   .long  0xff000000
+.Lloadp:.long  0,0
+.Lparm:	.long  0x10400
+.Lstart:.long  0x10000
+        .align 8
+.Lccws: .long  0x63000000+.Lde,0x60000010      # define extent
+        .long  0x43000000+.Llo,0x60000008      # locate
+# offset 1 in read CCW: data address (24 bit)
+# offset 6 in read CCW: number of bytes (16 bit)
+        .long  0x42000000,0x20000000           # read
+.Lde:   .long  0x40000200,0x00000000
+        .long  0x00000000,0x00001000
+# offset 2 in .Llo: block count (unsigned short)
+# offset 4 in .Llo: block number (unsigned long)
+.Llo:   .long  0x06000000,0x00000000
+
+        .org   0x200
+        .long  0x00000002,0x0000007f
+        .long  0x00000081,0x0000007f
+        .long  0x00000100,0x0000007f
+        .long  0x0000017f,0x0000007f
+        .long  0x000001fe,0x0000007f
+        .long  0x0000027d,0x0000007f
+        .long  0x000002fc,0x0000007f
+        .long  0x0000037b,0x0000007f
+        .long  0x000003fa,0x0000007f
+        .long  0x00000479,0x0000007f
+        .long  0x000004f8,0x0000007f
+        .long  0x00000577,0x0000007f
+        .long  0x000005f6,0x0000007f
+        .long  0x00000675,0x0000007f
+        .long  0x000006f4,0x0000007f
+        .long  0x00000773,0x0000003f
+        .long  0x00000000,0x00000000
+        .org   0x400
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/config.in linux/arch/s390x/config.in
--- v2.4.1/linux/arch/s390x/config.in	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/config.in	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,73 @@
+#
+# For a description of the syntax of this configuration file,
+# see Documentation/kbuild/config-language.txt.
+#
+
+define_bool CONFIG_ISA n
+define_bool CONFIG_EISA n
+define_bool CONFIG_MCA n
+
+mainmenu_name "Linux Kernel Configuration"
+define_bool CONFIG_ARCH_S390 y
+define_bool CONFIG_ARCH_S390X y
+
+mainmenu_option next_comment
+comment 'Code maturity level options'
+bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+endmenu
+
+mainmenu_option next_comment
+comment 'Processor type and features'
+bool 'Symmetric multi-processing support' CONFIG_SMP
+bool 'Kernel support for 31 bit emulation' CONFIG_S390_SUPPORT
+if [ "$CONFIG_S390_SUPPORT" = "y" ]; then
+  tristate 'Kernel support for 31 bit ELF binaries' CONFIG_BINFMT_ELF32 
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'Loadable module support'
+bool 'Enable loadable module support' CONFIG_MODULES
+if [ "$CONFIG_MODULES" = "y" ]; then
+  bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
+  bool 'Kernel module loader' CONFIG_KMOD
+fi
+endmenu
+
+mainmenu_option next_comment
+comment 'General setup'
+bool 'Fast IRQ handling' CONFIG_FAST_IRQ
+bool 'Builtin IPL record support' CONFIG_IPL
+if [ "$CONFIG_IPL" = "y" ]; then
+  choice 'IPL method generated into head.S' \
+          "tape                   CONFIG_IPL_TAPE \
+           vm_reader              CONFIG_IPL_VM" tape
+fi
+bool 'Networking support' CONFIG_NET
+bool 'System V IPC' CONFIG_SYSVIPC
+bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+bool 'Sysctl support' CONFIG_SYSCTL
+define CONFIG_KCORE ELF
+tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+bool 'Show crashed user process info' CONFIG_PROCESS_DEBUG
+endmenu
+
+source drivers/s390/Config.in
+
+if [ "$CONFIG_NET" = "y" ]; then
+  source net/Config.in
+fi
+
+source fs/Config.in
+
+mainmenu_option next_comment
+comment 'Kernel hacking'
+
+#bool 'Debug kmalloc/kfree' CONFIG_DEBUG_MALLOC
+if [ "$CONFIG_CTC" = "y" ]; then
+  bool 'Remote GDB kernel debugging' CONFIG_REMOTE_DEBUG
+fi
+# this does not work. bool 'Magic SysRq key' CONFIG_MAGIC_SYSRQ
+endmenu
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/defconfig linux/arch/s390x/defconfig
--- v2.4.1/linux/arch/s390x/defconfig	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/defconfig	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,219 @@
+#
+# Automatically generated by make menuconfig: don't edit
+#
+# CONFIG_ISA is not set
+# CONFIG_EISA is not set
+# CONFIG_MCA is not set
+CONFIG_ARCH_S390=y
+CONFIG_ARCH_S390X=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+
+#
+# Processor type and features
+#
+CONFIG_SMP=y
+CONFIG_S390_SUPPORT=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# General setup
+#
+CONFIG_FAST_IRQ=y
+CONFIG_IPL=y
+# CONFIG_IPL_TAPE is not set
+CONFIG_IPL_VM=y
+CONFIG_NET=y
+CONFIG_SYSVIPC=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_PROCESS_DEBUG is not set
+
+#
+# Block device drivers
+#
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=24576
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_BLK_DEV_XPRAM=m
+CONFIG_DASD=y
+CONFIG_DASD_ECKD=y
+CONFIG_DASD_FBA=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+# CONFIG_MD_LINEAR is not set
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID5=m
+CONFIG_BLK_DEV_LVM=m
+CONFIG_LVM_PROC_FS=y
+
+#
+# Character device drivers
+#
+CONFIG_UNIX98_PTYS=y
+CONFIG_UNIX98_PTY_COUNT=256
+CONFIG_3215=y
+CONFIG_3215_CONSOLE=y
+CONFIG_HWC=y
+CONFIG_HWC_CONSOLE=y
+CONFIG_S390_TAPE=m
+CONFIG_S390_TAPE_CHAR=y
+CONFIG_S390_TAPE_BLOCK=y
+CONFIG_S390_TAPE_3490=y
+CONFIG_S390_TAPE_3480=y
+
+#
+# Network device drivers
+#
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_TR=y
+# CONFIG_FDDI is not set
+# CONFIG_CHANDEV is not set
+CONFIG_CTC=m
+CONFIG_IUCV=m
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_NETLINK=y
+# CONFIG_RTNETLINK is not set
+# CONFIG_NETLINK_DEV is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_INET_ECN is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_IPV6 is not set
+# CONFIG_KHTTPD is not set
+# CONFIG_ATM is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_DECNET is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_LLC is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_FASTROUTE is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# File systems
+#
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_ADFS_FS is not set
+# CONFIG_ADFS_FS_RW is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_FAT_FS is not set
+# CONFIG_MSDOS_FS is not set
+# CONFIG_UMSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_RAMFS is not set
+# CONFIG_ISO9660_FS is not set
+# CONFIG_JOLIET is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_NTFS_FS is not set
+# CONFIG_NTFS_RW is not set
+# CONFIG_HPFS_FS is not set
+CONFIG_PROC_FS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX4FS_RW is not set
+# CONFIG_ROMFS_FS is not set
+CONFIG_EXT2_FS=y
+# CONFIG_SYSV_FS is not set
+# CONFIG_SYSV_FS_WRITE is not set
+# CONFIG_UDF_FS is not set
+# CONFIG_UDF_RW is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_UFS_FS_WRITE is not set
+
+#
+# Network File Systems
+#
+# CONFIG_CODA_FS is not set
+CONFIG_NFS_FS=y
+# CONFIG_NFS_V3 is not set
+# CONFIG_ROOT_NFS is not set
+# CONFIG_NFSD is not set
+# CONFIG_NFSD_V3 is not set
+CONFIG_SUNRPC=y
+CONFIG_LOCKD=y
+# CONFIG_SMB_FS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_NCPFS_PACKET_SIGNING is not set
+# CONFIG_NCPFS_IOCTL_LOCKING is not set
+# CONFIG_NCPFS_STRONG is not set
+# CONFIG_NCPFS_NFS_NS is not set
+# CONFIG_NCPFS_OS2_NS is not set
+# CONFIG_NCPFS_SMALLDOS is not set
+# CONFIG_NCPFS_MOUNT_SUBDIR is not set
+# CONFIG_NCPFS_NDS_DOMAINS is not set
+# CONFIG_NCPFS_NLS is not set
+# CONFIG_NCPFS_EXTRAS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_IBM_PARTITION=y
+# CONFIG_MAC_PARTITION is not set
+# CONFIG_MSDOS_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_NLS is not set
+
+#
+# Kernel hacking
+#
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/Makefile linux/arch/s390x/kernel/Makefile
--- v2.4.1/linux/arch/s390x/kernel/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,38 @@
+#
+# 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) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+
+all: kernel.o head.o init_task.o
+
+O_TARGET := kernel.o
+
+export-objs	:= s390_ksyms.o
+obj-y	:= lowcore.o entry.o bitmap.o traps.o time.o process.o irq.o \
+            setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
+            semaphore.o s390fpu.o reipl.o s390_ext.o debug.o
+
+obj-$(CONFIG_MODULES)		+= s390_ksyms.o
+obj-$(CONFIG_SMP)		+= smp.o
+
+#
+# Kernel debugging
+#
+obj-$(CONFIG_REMOTE_DEBUG)	+= gdb-stub.o #gdb-low.o 
+
+obj-$(CONFIG_S390_SUPPORT)	+= linux32.o signal32.o ioctl32.o wrapper32.o exec32.o
+obj-$(CONFIG_BINFMT_ELF32)	+= binfmt_elf32.o
+
+#
+# This is just to get the dependencies...
+#
+binfmt_elf32.o:	$(TOPDIR)/fs/binfmt_elf.c
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/binfmt_elf32.c linux/arch/s390x/kernel/binfmt_elf32.c
--- v2.4.1/linux/arch/s390x/kernel/binfmt_elf32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/binfmt_elf32.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,203 @@
+/*
+ * Support for 32-bit Linux for S390 ELF binaries.
+ *
+ * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Gerhard Tonn (ton@de.ibm.com)
+ *
+ * Heavily inspired by the 32-bit Sparc compat code which is
+ * Copyright (C) 1995, 1996, 1997, 1998 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1995, 1996, 1997, 1998 Jakub Jelinek   (jj@ultra.linux.cz)
+ */
+
+
+#define __ASMS390_ELF_H
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2MSB
+#define ELF_ARCH	EM_S390
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	((x)->e_machine == ELF_ARCH && (x)->e_ident[EI_CLASS] == ELF_CLASS)
+
+/* ELF register definitions */
+#define NUM_GPRS      16
+#define NUM_FPRS      16
+#define NUM_ACRS      16    
+
+#define TASK31_SIZE		(0x80000000UL)
+
+/* For SVR4/S390 the function pointer to be registered with `atexit` is
+   passed in R14. */
+#define ELF_PLAT_INIT(_r) \
+	do { \
+	_r->gprs[14] = 0; \
+	current->thread.flags |= S390_FLAG_31BIT; \
+	} while(0)
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE       4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         ((TASK31_SIZE & 0x80000000) \
+                                ? TASK31_SIZE / 3 * 2 \
+                                : 2 * TASK31_SIZE / 3)     
+
+/* Wow, the "main" arch needs arch dependent functions too.. :) */
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+   now struct_user_regs, they are different) */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs)        \
+	{ \
+	int i; \
+	memcpy(&pr_reg.psw.mask, &regs->psw.mask, 4); \
+	memcpy(&pr_reg.psw.addr, ((char*)&regs->psw.addr)+4, 4); \
+	for(i=0; i<NUM_GPRS; i++) \
+		pr_reg.gprs[i] = regs->gprs[i]; \
+	for(i=0; i<NUM_ACRS; i++) \
+		pr_reg.acrs[i] = regs->acrs[i]; \
+	pr_reg.orig_gpr2 = regs->orig_gpr2; \
+	}
+
+
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this CPU supports. */
+
+#define ELF_HWCAP (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.
+
+   For the moment, we have only optimizations for the Intel generations,
+   but that could change... */
+
+#define ELF_PLATFORM (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#endif 
+
+#include "linux32.h"
+
+typedef _s390_fp_regs32 elf_fpregset_t;
+
+typedef struct
+{
+	
+	_psw_t32	psw;
+	__u32		gprs[__NUM_GPRS]; 
+	__u32		acrs[__NUM_ACRS]; 
+	__u32		orig_gpr2;
+} s390_regs32;
+typedef s390_regs32 elf_gregset_t;
+
+#include <asm/processor.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/elfcore.h>
+
+int setup_arg_pages32(struct linux_binprm *bprm);
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+#define elf_prstatus elf_prstatus32
+struct elf_prstatus32
+{
+	struct elf_siginfo pr_info;	/* Info associated with signal */
+	short	pr_cursig;		/* Current signal */
+	u32	pr_sigpend;	/* Set of pending signals */
+	u32	pr_sighold;	/* Set of held signals */
+	pid_t	pr_pid;
+	pid_t	pr_ppid;
+	pid_t	pr_pgrp;
+	pid_t	pr_sid;
+	struct timeval32 pr_utime;	/* User time */
+	struct timeval32 pr_stime;	/* System time */
+	struct timeval32 pr_cutime;	/* Cumulative user time */
+	struct timeval32 pr_cstime;	/* Cumulative system time */
+	elf_gregset_t pr_reg;	/* GP registers */
+	int pr_fpvalid;		/* True if math co-processor being used.  */
+};
+
+#define elf_prpsinfo elf_prpsinfo32
+struct elf_prpsinfo32
+{
+	char	pr_state;	/* numeric process state */
+	char	pr_sname;	/* char for pr_state */
+	char	pr_zomb;	/* zombie */
+	char	pr_nice;	/* nice val */
+	u32	pr_flag;	/* flags */
+	u16	pr_uid;
+	u16	pr_gid;
+	pid_t	pr_pid, pr_ppid, pr_pgrp, pr_sid;
+	/* Lots missing */
+	char	pr_fname[16];	/* filename of executable */
+	char	pr_psargs[ELF_PRARGSZ];	/* initial part of arg list */
+};
+
+#include <linux/highuid.h>
+
+#undef NEW_TO_OLD_UID
+#undef NEW_TO_OLD_GID
+#define NEW_TO_OLD_UID(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
+#define NEW_TO_OLD_GID(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid) 
+
+#define elf_addr_t	u32
+#define elf_caddr_t	u32
+/*
+#define init_elf_binfmt init_elf32_binfmt
+*/
+#undef CONFIG_BINFMT_ELF
+#ifdef CONFIG_BINFMT_ELF32
+#define CONFIG_BINFMT_ELF CONFIG_BINFMT_ELF32
+#endif
+#undef CONFIG_BINFMT_ELF_MODULE
+#ifdef CONFIG_BINFMT_ELF32_MODULE
+#define CONFIG_BINFMT_ELF_MODULE CONFIG_BINFMT_ELF32_MODULE
+#endif
+
+#undef start_thread
+#define start_thread                    start_thread31 
+#define setup_arg_pages(bprm)           setup_arg_pages32(bprm)
+#define elf_map				elf_map32
+
+MODULE_DESCRIPTION("Binary format loader for compatibility with 32bit Linux for S390 binaries,"
+                   " Copyright 2000 IBM Corporation"); 
+MODULE_AUTHOR("Gerhard Tonn <ton@de.ibm.com>");
+
+#undef MODULE_DESCRIPTION
+#undef MODULE_AUTHOR
+
+#include "../../../fs/binfmt_elf.c"
+
+static unsigned long
+elf_map32 (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+{
+	unsigned long map_addr;
+
+	if(!addr)
+		addr = 0x40000000;
+
+	down(&current->mm->mmap_sem);
+	map_addr = do_mmap(filep, ELF_PAGESTART(addr),
+			   eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,
+			   eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
+	up(&current->mm->mmap_sem);
+	return(map_addr);
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/bitmap.S linux/arch/s390x/kernel/bitmap.S
--- v2.4.1/linux/arch/s390x/kernel/bitmap.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/bitmap.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,37 @@
+/*
+ *  arch/s390/kernel/bitmap.S
+ *    Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
+ *    See include/asm-s390/{bitops.h|posix_types.h} for details
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+         .globl _oi_bitmap
+_oi_bitmap:
+         .byte  0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
+
+         .globl _ni_bitmap
+_ni_bitmap:
+         .byte  0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F
+
+         .globl _zb_findmap
+_zb_findmap:
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4 
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,7
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4
+         .byte  0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/cpcmd.c linux/arch/s390x/kernel/cpcmd.c
--- v2.4.1/linux/arch/s390x/kernel/cpcmd.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/cpcmd.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,49 @@
+/*
+ *  arch/s390/kernel/cpcmd.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <asm/ebcdic.h>
+
+void cpcmd(char *cmd, char *response, int rlen)
+{
+        const int mask = 0x40000000L;
+        char obuffer[128];
+        int olen;
+
+        olen = strlen(cmd);
+        strcpy(obuffer, cmd);
+        ASCEBC(obuffer,olen);
+
+        if (response != NULL && rlen > 0) {
+                asm volatile ("   lrag  2,0(%0)\n"
+                              "   lgr   4,%1\n"
+                              "   o     4,%4\n"
+                              "   lrag  3,0(%2)\n"
+                              "   lgr   5,%3\n"
+                              "   sam31\n"
+                              "   .long 0x83240008 # Diagnose 83\n"
+                              "   sam64"
+                              : /* no output */
+                              : "a" (obuffer), "d" (olen),
+                                "a" (response), "d" (rlen), "m" (mask)
+                              : "2", "3", "4", "5" );
+                EBCASC(response, rlen);
+        } else {
+                asm volatile ("   lrag  2,0(%0)\n"
+                              "   lgr   3,%1\n"
+                              "   sam31\n"
+                              "   .long 0x83230008 # Diagnose 83\n"
+                              "   sam64"
+                              : /* no output */
+                              : "a" (obuffer), "d" (olen)
+                              : "2", "3"  );
+        }
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/cpcmd.h linux/arch/s390x/kernel/cpcmd.h
--- v2.4.1/linux/arch/s390x/kernel/cpcmd.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/cpcmd.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,14 @@
+/*
+ *  arch/s390/kernel/cpcmd.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#ifndef __CPCMD__
+#define __CPCMD__
+
+extern void cpcmd(char *cmd, char *response, int rlen);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/cpprintk.c linux/arch/s390x/kernel/cpprintk.c
--- v2.4.1/linux/arch/s390x/kernel/cpprintk.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/cpprintk.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,25 @@
+#include "cpcmd.h"
+#include <linux/mm.h>
+#include <linux/tty_driver.h>
+#include <linux/smp_lock.h>
+#include <linux/console.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+
+static char buf[1024];
+
+asmlinkage int s390printk(const char *fmt, ...)
+{
+	va_list args;
+	int i;
+	unsigned long flags;
+	spin_lock_irqsave(&console_lock, flags);
+	va_start(args, fmt);
+	i = vsprintf(&buf[0],"MSG * ",args);
+	i = vsprintf(&buf[i], fmt, args); 
+	va_end(args);
+	cpcmd(buf,0,0);
+	spin_unlock_irqrestore(&console_lock, flags);
+	return i;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/debug.c linux/arch/s390x/kernel/debug.c
--- v2.4.1/linux/arch/s390x/kernel/debug.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/debug.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,1167 @@
+/*
+ *  arch/s390/kernel/debug.c
+ *   S/390 debug facility
+ *
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+ *                             IBM Corporation
+ *    Author(s): Michael Holzheu (holzheu@de.ibm.com),
+ *               Holger Smolinski (Holger.Smolinski@de.ibm.com)
+ *
+ *    Bugreports to: <Linux390@de.ibm.com>
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <asm/debug.h>
+
+#define MIN(a,b) (((a)<(b))?(a):(b))
+
+#if defined(CONFIG_ARCH_S390X)
+#define DEBUG_PROC_HEADER_SIZE 46
+#else
+#define DEBUG_PROC_HEADER_SIZE 38
+#endif
+
+#define ADD_BUFFER 1000
+
+/* typedefs */
+
+typedef struct file_private_info {
+	loff_t len;			/* length of output in byte */
+	int size;			/* size of buffer for output */
+	char *data;			/* buffer for output */
+	debug_info_t *debug_info;	/* the debug information struct */
+	struct debug_view *view;	/* used view of debug info */
+} file_private_info_t;
+
+extern void tod_to_timeval(uint64_t todval, struct timeval *xtime);
+
+/* internal function prototyes */
+
+static int debug_init(void);
+static int debug_format_output(debug_info_t * debug_area, char *buf,
+			       int size, struct debug_view *view);
+static ssize_t debug_output(struct file *file, char *user_buf,
+			    size_t user_len, loff_t * offset);
+static ssize_t debug_input(struct file *file, const char *user_buf,
+			   size_t user_len, loff_t * offset);
+static int debug_open(struct inode *inode, struct file *file);
+static int debug_close(struct inode *inode, struct file *file);
+static struct proc_dir_entry 
+*debug_create_proc_dir_entry(struct proc_dir_entry *root,
+			     const char *name, mode_t mode,
+			     struct inode_operations *iops,
+			     struct file_operations *fops);
+static void debug_delete_proc_dir_entry(struct proc_dir_entry *root,
+					struct proc_dir_entry *entry);
+static debug_info_t*  debug_info_create(char *name, int page_order, int nr_areas, int buf_size);
+static void debug_info_get(debug_info_t *);
+static void debug_info_put(debug_info_t *);
+static int debug_prolog_level_fn(debug_info_t * id,
+				 struct debug_view *view, char *out_buf);
+static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
+				struct file *file, const char *user_buf,
+				size_t user_buf_size, loff_t * offset);
+static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
+                                char *out_buf, const char *in_buf);
+static int debug_raw_format_fn(debug_info_t * id,
+				 struct debug_view *view, char *out_buf,
+				 const char *in_buf);
+static int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
+                         int area, debug_entry_t * entry, char *out_buf);
+
+/* globals */
+
+struct debug_view debug_raw_view = {
+	"raw",
+	NULL,
+	&debug_raw_header_fn,
+	&debug_raw_format_fn,
+	NULL
+};
+
+struct debug_view debug_hex_ascii_view = {
+	"hex_ascii",
+	NULL,
+	&debug_dflt_header_fn,
+	&debug_hex_ascii_format_fn,
+	NULL
+};
+
+struct debug_view debug_level_view = {
+	"level",
+	&debug_prolog_level_fn,
+	NULL,
+	NULL,
+	&debug_input_level_fn
+};
+
+/* static globals */
+
+static debug_info_t *debug_area_first = NULL;
+static debug_info_t *debug_area_last = NULL;
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+static struct semaphore debug_lock = MUTEX;
+#else
+DECLARE_MUTEX(debug_lock);
+#endif
+
+static int initialized = 0;
+
+static struct file_operations debug_file_ops = {
+	read:    debug_output,
+	write:   debug_input,	
+	open:    debug_open,
+	release: debug_close,
+};
+
+static struct inode_operations debug_inode_ops = {
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+	default_file_ops: &debug_file_ops,	/* file ops */
+#endif
+};
+
+
+static struct proc_dir_entry *debug_proc_root_entry;
+
+
+/* functions */
+
+/*
+ * debug_info_create
+ * - create new debug-info
+ */
+
+static debug_info_t*  debug_info_create(char *name, int page_order, 
+                                        int nr_areas, int buf_size)
+{
+	debug_info_t* rc;
+	int i;
+
+        /* alloc everything */
+
+        rc = (debug_info_t*) kmalloc(sizeof(debug_info_t), GFP_ATOMIC);
+        if(!rc) 
+		goto fail_malloc_rc;
+	rc->active_entry = (int*)kmalloc(nr_areas * sizeof(int), GFP_ATOMIC);
+	if(!rc->active_entry)
+		goto fail_malloc_active_entry;
+	memset(rc->active_entry, 0, nr_areas * sizeof(int));
+        rc->areas = (debug_entry_t **) kmalloc(nr_areas *
+                                               sizeof(debug_entry_t *),
+                                               GFP_ATOMIC);
+        if (!rc->areas) 
+                goto fail_malloc_areas;
+        for (i = 0; i < nr_areas; i++) {
+                rc->areas[i] =
+                    (debug_entry_t *) __get_free_pages(GFP_ATOMIC,
+                                                       page_order);
+                if (!rc->areas[i]) {
+                        for (i--; i >= 0; i--) {
+                                free_pages((unsigned long) rc->areas[i],
+                                           page_order);
+                        }
+                        goto fail_malloc_areas2;
+                } else {
+                        memset(rc->areas[i], 0, PAGE_SIZE << page_order);
+                }
+        }
+
+        /* initialize members */
+
+        spin_lock_init(&rc->lock);
+        rc->page_order  = page_order;
+        rc->nr_areas    = nr_areas;
+        rc->active_area = 0;
+        rc->level       = DEBUG_DEFAULT_LEVEL;
+        rc->buf_size    = buf_size;
+        rc->entry_size  = sizeof(debug_entry_t) + buf_size;
+        strncpy(rc->name, name, MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1)));
+        rc->name[MIN(strlen(name), (DEBUG_MAX_PROCF_LEN - 1))] = 0;
+        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
+	memset(rc->proc_entries, 0 ,DEBUG_MAX_VIEWS * 
+               sizeof(struct proc_dir_entry*));
+        atomic_set(&(rc->ref_count), 0);
+        rc->proc_root_entry =
+            debug_create_proc_dir_entry(debug_proc_root_entry, rc->name,
+                                        S_IFDIR | S_IRUGO | S_IXUGO |
+                                        S_IWUSR | S_IWGRP, NULL, NULL);
+
+	/* append new element to linked list */
+
+        if(debug_area_first == NULL){
+                /* first element in list */
+                debug_area_first = rc;
+                rc->prev = NULL;
+        }
+        else{
+                /* append element to end of list */
+                debug_area_last->next = rc;
+                rc->prev = debug_area_last;
+        }
+        debug_area_last = rc;
+        rc->next = NULL;
+
+	debug_info_get(rc);
+	return rc;
+
+fail_malloc_areas2:
+	kfree(rc->areas);
+fail_malloc_areas:
+	kfree(rc->active_entry);
+fail_malloc_active_entry:
+	kfree(rc);
+fail_malloc_rc:
+	return NULL;
+}
+
+/*
+ * debug_info_get
+ * - increments reference count for debug-info
+ */
+
+static void debug_info_get(debug_info_t * db_info)
+{
+	if (db_info)
+		atomic_inc(&db_info->ref_count);
+}
+
+/*
+ * debug_info_put:
+ * - decreases reference count for debug-info and frees it if necessary
+ */
+
+static void debug_info_put(debug_info_t *db_info)
+{
+	int i;
+
+	if (!db_info)
+		return;
+	if (atomic_dec_and_test(&db_info->ref_count)) {
+		printk(KERN_INFO "debug: freeing debug area %p (%s)\n",
+		       db_info, db_info->name);
+		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+			if (db_info->views[i] != NULL)
+				debug_delete_proc_dir_entry
+				    (db_info->proc_root_entry,
+				     db_info->proc_entries[i]);
+		}
+		debug_delete_proc_dir_entry(debug_proc_root_entry,
+					    db_info->proc_root_entry);
+		for (i = 0; i < db_info->nr_areas; i++) {
+			free_pages((unsigned long) db_info->areas[i],
+				   db_info->page_order);
+		}
+		kfree(db_info->areas);
+		kfree(db_info->active_entry);
+		if(db_info == debug_area_first)
+			debug_area_first = db_info->next;
+		if(db_info == debug_area_last)
+			debug_area_last = db_info->prev;
+		if(db_info->prev) db_info->prev->next = db_info->next;
+		if(db_info->next) db_info->next->prev = db_info->prev;
+		kfree(db_info);
+	}
+}
+
+
+/*
+ * debug_output:
+ * - called for user read()
+ * - copies formated output form private_data of the file
+ *   handle to the user buffer
+ */
+
+static ssize_t debug_output(struct file *file,	/* file descriptor */
+			    char *user_buf,	/* user buffer */
+			    size_t user_len,	/* length of buffer */
+			    loff_t *offset	/* offset in the file */ )
+{
+	loff_t len;
+	int rc;
+	file_private_info_t *p_info;
+
+	p_info = ((file_private_info_t *) file->private_data);
+	if (*offset >= p_info->len) {
+		return 0;	/* EOF */
+	} else {
+		len = MIN(user_len, (p_info->len - *offset));
+		if ((rc = copy_to_user(user_buf, &(p_info->data[*offset]),len)))
+			return rc;;
+		(*offset) += len;
+		return len;	/* number of bytes "read" */
+	}
+}
+
+/*
+ * debug_input:
+ * - called for user write()
+ * - calls input function of view
+ */
+
+static ssize_t debug_input(struct file *file,
+			   const char *user_buf, size_t length,
+			   loff_t *offset)
+{
+	int rc = 0;
+	file_private_info_t *p_info;
+
+	down(&debug_lock);
+	p_info = ((file_private_info_t *) file->private_data);
+	if (p_info->view->input_proc)
+		rc = p_info->view->input_proc(p_info->debug_info,
+					      p_info->view, file, user_buf,
+					      length, offset);
+	up(&debug_lock);
+	return rc;		/* number of input characters */
+}
+
+/*
+ * debug_format_output:
+ * - calls prolog, header and format functions of view to format output
+ */
+
+static int debug_format_output(debug_info_t * debug_area, char *buf,
+			       int size, struct debug_view *view)
+{
+	int len = 0;
+	int i, j;
+	int nr_of_entries;
+	debug_entry_t *act_entry;
+
+	/* print prolog */
+	if (view->prolog_proc)
+		len += view->prolog_proc(debug_area, view, buf);
+	/* print debug records */
+	if (!(view->format_proc) && !(view->header_proc))
+		goto out;
+	nr_of_entries = PAGE_SIZE / debug_area->entry_size
+			<< debug_area->page_order;
+	for (i = 0; i < debug_area->nr_areas; i++) {
+		act_entry = debug_area->areas[i];
+		for (j = 0; j < nr_of_entries; j++) {
+			if (act_entry->id.fields.used == 0)
+				break;	/* empty entry */
+			if (view->header_proc)
+				len += view->header_proc(debug_area, view, i,
+						         act_entry, buf + len);
+			if (view->format_proc)
+				len += view->format_proc(debug_area, view,
+						         buf + len,
+						         DEBUG_DATA(act_entry));
+			if (len > size) {
+				printk(KERN_ERR
+				"debug: error -- memory exceeded for (%s/%s)\n",
+				debug_area->name, view->name);
+				printk(KERN_ERR "debug: fix view %s!!\n",
+				       view->name);
+				printk(KERN_ERR
+				"debug: area: %i (0 - %i) entry: %i (0 - %i)\n",
+				i, debug_area->nr_areas - 1, j,
+				nr_of_entries - 1);
+				goto out;
+			}
+			act_entry = (debug_entry_t *) (((char *) act_entry) +
+					       debug_area->entry_size);
+		}
+	}
+      out:
+	return len;
+}
+
+
+/*
+ * debug_open:
+ * - called for user open()
+ * - copies formated output to private_data area of the file
+ *   handle
+ */
+
+static int debug_open(struct inode *inode, struct file *file)
+{
+	int i = 0, size = 0, rc = 0, f_entry_size = 0;
+	file_private_info_t *p_info;
+	debug_info_t* debug_info;
+
+#ifdef DEBUG
+	printk("debug_open\n");
+#endif
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	down(&debug_lock);
+
+	/* find debug log and view */
+
+	debug_info = debug_area_first;
+	while(debug_info != NULL){
+		for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+			if (debug_info->views[i] == NULL)
+				continue;
+			else if (debug_info->proc_entries[i]->low_ino ==
+				 file->f_dentry->d_inode->i_ino) {
+				goto found;	/* found view ! */
+			}
+		}
+		debug_info = debug_info->next;
+	}
+	/* no entry found */
+	rc = -EINVAL;
+	goto out;
+      found:
+	if ((file->private_data =
+	     kmalloc(sizeof(file_private_info_t), GFP_ATOMIC)) == 0) {
+		printk(KERN_ERR "debug_open: kmalloc failed\n");
+		rc = -ENOMEM;
+		goto out;
+	}
+	p_info = (file_private_info_t *) file->private_data;
+
+	/*
+	 * the size for the formated output is calculated
+	 * with the following formula:
+	 *
+	 *   prolog-size
+	 *   +
+	 *   (record header size + record data field size)
+	 *   * number of entries per page
+	 *   * number of pages per area
+	 *   * number of areas
+	 */
+
+	if (debug_info->views[i]->prolog_proc)
+		size +=
+		    debug_info->views[i]->prolog_proc(debug_info,
+							 debug_info->
+							 views[i], NULL);
+
+	if (debug_info->views[i]->header_proc)
+		f_entry_size =
+		    debug_info->views[i]->header_proc(debug_info,
+							 debug_info->
+							 views[i], 0, NULL,
+							 NULL);
+	if (debug_info->views[i]->format_proc)
+		f_entry_size +=
+		    debug_info->views[i]->format_proc(debug_info,
+							 debug_info->
+							 views[i], NULL,
+							 NULL);
+
+	size += f_entry_size 
+		* (PAGE_SIZE / debug_info->entry_size
+		<< debug_info->page_order)
+		* debug_info->nr_areas + 1;	/* terminating \0 */
+#ifdef DEBUG
+	printk("debug_open: size: %i\n", size);
+#endif
+
+	/* alloc some bytes more to be safe against bad views */
+	if ((p_info->data = vmalloc(size + ADD_BUFFER)) == 0) {
+		printk(KERN_ERR "debug_open: vmalloc failed\n");
+		vfree(file->private_data);
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	p_info->size = size;
+	p_info->debug_info = debug_info;
+	p_info->view = debug_info->views[i];
+
+	spin_lock_irq(&debug_info->lock);
+
+	p_info->len =
+	    debug_format_output(debug_info, p_info->data, size,
+				debug_info->views[i]);
+#ifdef DEBUG
+	{
+		int ilen = p_info->len;
+		printk("debug_open: len: %i\n", ilen);
+	}
+#endif
+
+	spin_unlock_irq(&debug_info->lock);
+	debug_info_get(debug_info);
+
+      out:
+	up(&debug_lock);
+#ifdef MODULE
+	if (rc != 0)
+		MOD_DEC_USE_COUNT;
+#endif
+	return rc;
+}
+
+/*
+ * debug_close:
+ * - called for user close()
+ * - deletes  private_data area of the file handle
+ */
+
+static int debug_close(struct inode *inode, struct file *file)
+{
+	file_private_info_t *p_info;
+#ifdef DEBUG
+	printk("debug_close\n");
+#endif
+	down(&debug_lock);
+	p_info = (file_private_info_t *) file->private_data;
+	debug_info_put(p_info->debug_info);
+	if (p_info->data) {
+		vfree(p_info->data);
+		kfree(file->private_data);
+	}
+	up(&debug_lock);
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+	return 0;		/* success */
+}
+
+/*
+ * debug_create_proc_dir_entry:
+ * - initializes proc-dir-entry and registers it
+ */
+
+static struct proc_dir_entry *debug_create_proc_dir_entry
+    (struct proc_dir_entry *root, const char *name, mode_t mode,
+     struct inode_operations *iops, struct file_operations *fops) 
+{
+	struct proc_dir_entry *rc = NULL;
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+	const char *fn = name;
+	int len;
+	len = strlen(fn);
+
+	rc = (struct proc_dir_entry *) kmalloc(sizeof(struct proc_dir_entry)
+					       + len + 1, GFP_ATOMIC);
+	if (!rc)
+		goto out;
+
+	memset(rc, 0, sizeof(struct proc_dir_entry));
+	memcpy(((char *) rc) + sizeof(*rc), fn, len + 1);
+	rc->name = ((char *) rc) + sizeof(*rc);
+	rc->namelen = len;
+	rc->low_ino = 0, rc->mode = mode;
+	rc->nlink = 1;
+	rc->uid = 0;
+	rc->gid = 0;
+	rc->size = 0;
+	rc->get_info = NULL;
+	rc->ops = iops;
+
+	proc_register(root, rc);
+#else
+	rc = create_proc_entry(name, mode, root);
+	if (!rc)
+		goto out;
+	if (fops)
+		rc->proc_fops = fops;
+#endif
+
+      out:
+	return rc;
+}
+
+
+/*
+ * delete_proc_dir_entry:
+ */
+
+static void debug_delete_proc_dir_entry
+    (struct proc_dir_entry *root, struct proc_dir_entry *proc_entry) 
+{
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+	proc_unregister(root, proc_entry->low_ino);
+	kfree(proc_entry);
+#else
+	remove_proc_entry(proc_entry->name, root);
+#endif
+}
+
+/*
+ * debug_register:
+ * - creates and initializes debug area for the caller
+ * - returns handle for debug area
+ */
+
+debug_info_t *debug_register
+    (char *name, int page_order, int nr_areas, int buf_size) 
+{
+	debug_info_t *rc = NULL;
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif
+	if (!initialized)
+		debug_init();
+	down(&debug_lock);
+
+        /* create new debug_info */
+
+	rc = debug_info_create(name, page_order, nr_areas, buf_size);
+	if(!rc) 
+		goto out;
+	debug_register_view(rc, &debug_level_view);
+	printk(KERN_INFO
+	       "debug: reserved %d areas of %d pages for debugging %s\n",
+	       nr_areas, 1 << page_order, rc->name);
+      out:
+        if (rc == NULL){
+		printk(KERN_ERR "debug: debug_register failed for %s\n",name);
+#ifdef MODULE
+		MOD_DEC_USE_COUNT;
+#endif
+        }
+	up(&debug_lock);
+	return rc;
+}
+
+/*
+ * debug_unregister:
+ * - give back debug area
+ */
+
+void debug_unregister(debug_info_t * id)
+{
+	if (!id)
+		goto out;
+	down(&debug_lock);
+	printk(KERN_INFO "debug: unregistering %s\n", id->name);
+	debug_info_put(id);
+	up(&debug_lock);
+
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif
+      out:
+	return;
+}
+
+/*
+ * debug_set_level:
+ * - set actual debug level
+ */
+
+void debug_set_level(debug_info_t* id, int new_level)
+{
+	long flags;
+	if(!id)
+		return;	
+	spin_lock_irqsave(&id->lock,flags);
+        if(new_level == DEBUG_OFF_LEVEL){
+                id->level = DEBUG_OFF_LEVEL;
+                printk(KERN_INFO "debug: %s: switched off\n",id->name);
+        } else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
+                printk(KERN_INFO
+                        "debug: %s: level %i is out of range (%i - %i)\n",
+                        id->name, new_level, 0, DEBUG_MAX_LEVEL);
+        } else {
+                id->level = new_level;
+                printk(KERN_INFO 
+			"debug: %s: new level %i\n",id->name,id->level);
+        }
+	spin_unlock_irqrestore(&id->lock,flags);
+}
+
+
+/*
+ * proceed_active_entry:
+ * - set active entry to next in the ring buffer
+ */
+
+static inline void proceed_active_entry(debug_info_t * id)
+{
+	if ((id->active_entry[id->active_area] += id->entry_size)
+	    > ((PAGE_SIZE << (id->page_order)) - id->entry_size))
+		id->active_entry[id->active_area] = 0;
+}
+
+/*
+ * proceed_active_area:
+ * - set active area to next in the ring buffer
+ */
+
+static inline void proceed_active_area(debug_info_t * id)
+{
+	id->active_area++;
+	id->active_area = id->active_area % id->nr_areas;
+}
+
+/*
+ * get_active_entry:
+ */
+
+static inline debug_entry_t *get_active_entry(debug_info_t * id)
+{
+	return (debug_entry_t *) ((char *) id->areas[id->active_area] +
+				  id->active_entry[id->active_area]);
+}
+
+/*
+ * debug_common:
+ * - set timestamp, caller address, cpu number etc.
+ */
+
+static inline debug_entry_t *debug_common(debug_info_t * id)
+{
+	debug_entry_t *active;
+
+	active = get_active_entry(id);
+	STCK(active->id.stck);
+	active->id.fields.cpuid = smp_processor_id();
+	active->id.fields.used = 1;
+	active->caller = __builtin_return_address(0);
+	return active;
+}
+
+/*
+ * debug_event:
+ */
+
+debug_entry_t *debug_event(debug_info_t * id, int level, void *buf,
+			   int len)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 0;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	proceed_active_entry(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_int_event:
+ */
+
+debug_entry_t *debug_int_event(debug_info_t * id, int level,
+			       unsigned int tag)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 0;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), &tag, MIN(sizeof(unsigned int), id->buf_size));
+	proceed_active_entry(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_text_event:
+ */
+
+debug_entry_t *debug_text_event(debug_info_t * id, int level,
+				const char *txt)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	strncpy(DEBUG_DATA(active), txt, MIN(strlen(txt), id->buf_size));
+	active->id.fields.exception = 0;
+	proceed_active_entry(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+
+}
+
+/*
+ * debug_exception:
+ */
+
+debug_entry_t *debug_exception(debug_info_t * id, int level, void *buf,
+			       int len)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 1;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+	proceed_active_entry(id);
+	proceed_active_area(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_int_exception:
+ */
+
+debug_entry_t *debug_int_exception(debug_info_t * id, int level,
+				   unsigned int tag)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	active->id.fields.exception = 1;
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	memcpy(DEBUG_DATA(active), &tag,
+	       MIN(sizeof(unsigned int), id->buf_size));
+	proceed_active_entry(id);
+	proceed_active_area(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+}
+
+/*
+ * debug_text_exception:
+ */
+
+debug_entry_t *debug_text_exception(debug_info_t * id, int level,
+				    const char *txt)
+{
+	long flags;
+	debug_entry_t *active = NULL;
+
+	if ((!id) || (level > id->level))
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	active = debug_common(id);
+	memset(DEBUG_DATA(active), 0, id->buf_size);
+	strncpy(DEBUG_DATA(active), txt, MIN(strlen(txt), id->buf_size));
+	active->id.fields.exception = 1;
+	proceed_active_entry(id);
+	proceed_active_area(id);
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return active;
+
+}
+
+/*
+ * debug_init:
+ * - is called exactly once to initialize the debug feature
+ */
+
+int debug_init(void)
+{
+	int rc = 0;
+
+	down(&debug_lock);
+	if (!initialized) {
+		debug_proc_root_entry =
+		    debug_create_proc_dir_entry(&proc_root, DEBUG_DIR_ROOT,
+						S_IFDIR | S_IRUGO | S_IXUGO
+						| S_IWUSR | S_IWGRP, NULL,
+						NULL);
+		printk(KERN_INFO "debug: Initialization complete\n");
+		initialized = 1;
+	}
+	up(&debug_lock);
+
+	return rc;
+}
+
+/*
+ * debug_register_view:
+ */
+
+int debug_register_view(debug_info_t * id, struct debug_view *view)
+{
+	int rc = 0;
+	int i;
+	long flags;
+	mode_t mode = S_IFREG;
+
+	if (!id)
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+		if (id->views[i] == NULL)
+			break;
+	}
+	if (i == DEBUG_MAX_VIEWS) {
+		printk(KERN_WARNING "debug: cannot register view %s/%s\n",
+			id->name,view->name);
+		printk(KERN_WARNING 
+			"debug: maximum number of views reached (%i)!\n", i);
+		rc = -1;
+	}
+	else {
+		id->views[i] = view;
+		if (view->prolog_proc || view->format_proc || view->header_proc)
+			mode |= S_IRUSR;
+		if (view->input_proc)
+			mode |= S_IWUSR;
+		id->proc_entries[i] =
+		    debug_create_proc_dir_entry(id->proc_root_entry,
+						view->name, mode,
+						&debug_inode_ops,
+						&debug_file_ops);
+		rc = 0;
+	}
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return rc;
+}
+
+/*
+ * debug_unregister_view:
+ */
+
+int debug_unregister_view(debug_info_t * id, struct debug_view *view)
+{
+	int rc = 0;
+	int i;
+	long flags;
+
+	if (!id)
+		goto out;
+	spin_lock_irqsave(&id->lock, flags);
+	for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
+		if (id->views[i] == view)
+			break;
+	}
+	if (i == DEBUG_MAX_VIEWS)
+		rc = -1;
+	else {
+		debug_delete_proc_dir_entry(id->proc_root_entry,
+					    id->proc_entries[i]);		
+		id->views[i] = NULL;
+		rc = 0;
+	}
+	spin_unlock_irqrestore(&id->lock, flags);
+      out:
+	return rc;
+}
+
+/*
+ * functions for debug-views
+ ***********************************
+*/
+
+/*
+ * prints out actual debug level
+ */
+
+static int debug_prolog_level_fn(debug_info_t * id,
+				 struct debug_view *view, char *out_buf)
+{
+	int rc = 0;
+
+	if (out_buf == NULL) {
+		rc = 2;
+		goto out;
+	}
+	if(id->level == -1) rc = sprintf(out_buf,"-\n");
+	else rc = sprintf(out_buf, "%i\n", id->level);
+      out:
+	return rc;
+}
+
+/*
+ * reads new debug level
+ */
+
+static int debug_input_level_fn(debug_info_t * id, struct debug_view *view,
+				struct file *file, const char *user_buf,
+				size_t in_buf_size, loff_t * offset)
+{
+	char input_buf[1];
+	int rc = in_buf_size;
+
+	if (*offset != 0)
+		goto out;
+	if ((rc = copy_from_user(input_buf, user_buf, 1)))
+		goto out;
+	if (isdigit(input_buf[0])) {
+		int new_level = ((int) input_buf[0] - (int) '0');
+		debug_set_level(id, new_level);
+	} else if(input_buf[0] == '-') {
+		debug_set_level(id, DEBUG_OFF_LEVEL);
+	} else {
+		printk(KERN_INFO "debug: level `%c` is not valid\n",
+		       input_buf[0]);
+	}
+      out:
+	*offset += in_buf_size;
+	return rc;		/* number of input characters */
+}
+
+/*
+ * prints debug header in raw format
+ */
+
+int debug_raw_header_fn(debug_info_t * id, struct debug_view *view,
+                         int area, debug_entry_t * entry, char *out_buf)
+{
+        int rc;
+
+	rc = sizeof(debug_entry_t);
+        if (out_buf == NULL)
+                goto out;
+	memcpy(out_buf,entry,sizeof(debug_entry_t));
+      out:
+        return rc;
+}
+
+/*
+ * prints debug data in raw format
+ */
+
+static int debug_raw_format_fn(debug_info_t * id, struct debug_view *view,
+			       char *out_buf, const char *in_buf)
+{
+	int rc;
+
+	rc = id->buf_size;
+	if (out_buf == NULL || in_buf == NULL)
+		goto out;
+	memcpy(out_buf, in_buf, id->buf_size);
+      out:
+	return rc;
+}
+
+/*
+ * prints debug data in hex/ascii format
+ */
+
+static int debug_hex_ascii_format_fn(debug_info_t * id, struct debug_view *view,
+		    		  char *out_buf, const char *in_buf)
+{
+	int i, rc = 0;
+
+	if (out_buf == NULL || in_buf == NULL) {
+		rc = id->buf_size * 4 + 3;
+		goto out;
+	}
+	for (i = 0; i < id->buf_size; i++) {
+                rc += sprintf(out_buf + rc, "%02x ",
+                              ((unsigned char *) in_buf)[i]);
+        }
+	rc += sprintf(out_buf + rc, "| ");
+	for (i = 0; i < id->buf_size; i++) {
+		unsigned char c = in_buf[i];
+		if (!isprint(c))
+			rc += sprintf(out_buf + rc, ".");
+		else
+			rc += sprintf(out_buf + rc, "%c", c);
+	}
+	rc += sprintf(out_buf + rc, "\n");
+      out:
+	return rc;
+}
+
+/*
+ * prints header for debug entry
+ */
+
+int debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
+			 int area, debug_entry_t * entry, char *out_buf)
+{
+	struct timeval time_val;
+	unsigned long long time;
+	char *except_str;
+	unsigned long caller;
+	int rc = 0;
+
+	if (out_buf == NULL) {
+		rc = DEBUG_PROC_HEADER_SIZE;
+		goto out;
+	}
+
+	time = entry->id.stck;
+	/* adjust todclock to 1970 */
+	time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096);
+	tod_to_timeval(time, &time_val);
+
+	if (entry->id.fields.exception)
+		except_str = "*";
+	else
+		except_str = "-";
+	caller = (unsigned long) entry->caller;
+#if defined(CONFIG_ARCH_S390X)
+	rc += sprintf(out_buf, "%02i %011lu:%06lu %1s %02i %016lx  ",
+		      area, time_val.tv_sec,
+		      time_val.tv_usec, except_str,
+		      entry->id.fields.cpuid, caller);
+#else
+	caller &= 0x7fffffff;
+	rc += sprintf(out_buf, "%02i %011lu:%06lu %1s %02i %08lx  ",
+		      area, time_val.tv_sec,
+		      time_val.tv_usec, except_str,
+		      entry->id.fields.cpuid, caller);
+#endif
+      out:
+	return rc;
+}
+
+/*
+ * init_module:
+ */
+
+#ifdef MODULE
+int init_module(void)
+{
+	int rc = 0;
+#ifdef DEBUG
+	printk("debug_module_init: \n");
+#endif
+	rc = debug_init();
+	if (rc) 
+		printk(KERN_INFO "debug: an error occurred with debug_init\n");
+	return rc;
+}
+
+/*
+ * cleanup_module:
+ */
+
+void cleanup_module(void)
+{
+#ifdef DEBUG
+	printk("debug_cleanup_module: \n");
+#endif
+	debug_delete_proc_dir_entry(&proc_root, debug_proc_root_entry);
+	return;
+}
+
+#endif			/* MODULE */
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/ebcdic.c linux/arch/s390x/kernel/ebcdic.c
--- v2.4.1/linux/arch/s390x/kernel/ebcdic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/ebcdic.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,391 @@
+/*
+ *  arch/s390/kernel/ebcdic.c
+ *    ECBDIC -> ASCII, ASCII -> ECBDIC,
+ *    upper to lower case (EBCDIC) conversion tables.
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ *               Martin Peschke <peschke@fh-brandenburg.de>
+ */
+
+#include <asm/types.h>
+
+/*
+ * ASCII (IBM PC 437)  -> EBCDIC 037
+ */
+__u8 _ascebc[256] =
+{
+ /*00 NUL   SOH   STX   ETX   EOT   ENQ   ACK   BEL */
+     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08  BS    HT    LF    VT    FF    CR    SO    SI */
+ /*              ->NL                               */
+     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10 DLE   DC1   DC2   DC3   DC4   NAK   SYN   ETB */
+     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ /*18 CAN    EM   SUB   ESC    FS    GS    RS    US */
+ /*                               ->IGS ->IRS ->IUS */
+     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ /*20  SP     !     "     #     $     %     &     ' */
+     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28   (     )     *     +     ,     -    .      / */
+     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30   0     1     2     3     4     5     6     7 */
+     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38   8     9     :     ;     <     =     >     ? */
+     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40   @     A     B     C     D     E     F     G */
+     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48   H     I     J     K     L     M     N     O */
+     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50   P     Q     R     S     T     U     V     W */
+     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58   X     Y     Z     [     \     ]     ^     _ */
+     0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+ /*60   `     a     b     c     d     e     f     g */
+     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68   h     i     j     k     l     m     n     o */
+     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70   p     q     r     s     t     u     v     w */
+     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78   x     y     z     {     |     }     ~    DL */
+     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ /*80*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*88*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*90*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*98*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E0        sz						*/
+     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F8*/
+     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+/*
+ * EBCDIC 037 -> ASCII (IBM PC 437)
+ */
+__u8 _ebcasc[256] =
+{
+ /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
+          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
+          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
+                                  -ENP  ->LF             */
+          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
+                                                    -IUS */
+          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
+                                  -INP                   */
+          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
+                       -SW                               */ 
+          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
+          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
+          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ /* 0x40    SP   RSP           �ä              ----       */
+          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ /* 0x48                       .     <     (     +     | */
+          0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+ /* 0x50     &                                      ---- */
+          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ /* 0x58           �ß     !     $     *     )     ;       */
+          0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
+ /* 0x60     -     /  ----     �Ä  ----  ----  ----       */
+          0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ /* 0x68              ----     ,     %     _     >     ? */ 
+          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
+          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x78     *     `     :     #     @     '     =     " */
+          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ /* 0x80     *     a     b     c     d     e     f     g */
+          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ /* 0x88     h     i              ----  ----  ----       */
+          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ /* 0x90     �°     j     k     l     m     n     o     p */
+          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ /* 0x98     q     r                    ----        ---- */
+          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ /* 0xA0           ~     s     t     u     v     w     x */
+          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ /* 0xA8     y     z              ----  ----  ----  ---- */
+          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ /* 0xB0     ^                    ----     �§  ----       */
+          0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ /* 0xB8        ----     [     ]  ----  ----  ----  ---- */
+          0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
+ /* 0xC0     {     A     B     C     D     E     F     G */
+          0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ /* 0xC8     H     I  ----           �ö              ---- */
+          0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ /* 0xD0     }     J     K     L     M     N     O     P */
+          0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ /* 0xD8     Q     R  ----           �ü                   */
+          0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ /* 0xE0     \           S     T     U     V     W     X */
+          0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ /* 0xE8     Y     Z        ----     �Ö  ----  ----  ---- */
+          0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ /* 0xF0     0     1     2     3     4     5     6     7 */
+          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ /* 0xF8     8     9  ----  ----     �Ü  ----  ----  ---- */
+          0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
+};
+
+
+/*
+ * ASCII (IBM PC 437)  -> EBCDIC 500
+ */
+__u8 _ascebc_500[256] =
+{
+ /*00 NUL   SOH   STX   ETX   EOT   ENQ   ACK   BEL */
+     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08  BS    HT    LF    VT    FF    CR    SO    SI */
+ /*              ->NL                               */
+     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10 DLE   DC1   DC2   DC3   DC4   NAK   SYN   ETB */
+     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ /*18 CAN    EM   SUB   ESC    FS    GS    RS    US */
+ /*                               ->IGS ->IRS ->IUS */
+     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ /*20  SP     !     "     #     $     %     &     ' */
+     0x40, 0x4F, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28   (     )     *     +     ,     -    .      / */
+     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30   0     1     2     3     4     5     6     7 */
+     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38   8     9     :     ;     <     =     >     ? */
+     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40   @     A     B     C     D     E     F     G */
+     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48   H     I     J     K     L     M     N     O */
+     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50   P     Q     R     S     T     U     V     W */
+     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58   X     Y     Z     [     \     ]     ^     _ */
+     0xE7, 0xE8, 0xE9, 0x4A, 0xE0, 0x5A, 0x5F, 0x6D,
+ /*60   `     a     b     c     d     e     f     g */
+     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68   h     i     j     k     l     m     n     o */
+     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70   p     q     r     s     t     u     v     w */
+     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78   x     y     z     {     |     }     ~    DL */
+     0xA7, 0xA8, 0xA9, 0xC0, 0xBB, 0xD0, 0xA1, 0x07,
+ /*80*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*88*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*90*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*98*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E0        sz						*/
+     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F8*/
+     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+/*
+ * EBCDIC 500 -> ASCII (IBM PC 437)
+ */
+__u8 _ebcasc_500[256] =
+{
+ /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
+          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
+          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
+                                  -ENP  ->LF             */
+          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
+                                                    -IUS */
+          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
+                                  -INP                   */
+          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
+                       -SW                               */ 
+          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
+          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
+          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ /* 0x40    SP   RSP           �ä              ----       */
+          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ /* 0x48                 [     .     <     (     +     ! */
+          0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
+ /* 0x50     &                                      ---- */
+          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ /* 0x58           �ß     ]     $     *     )     ;     ^ */
+          0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
+ /* 0x60     -     /  ----     �Ä  ----  ----  ----       */
+          0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ /* 0x68              ----     ,     %     _     >     ? */ 
+          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
+          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x78     *     `     :     #     @     '     =     " */
+          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ /* 0x80     *     a     b     c     d     e     f     g */
+          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ /* 0x88     h     i              ----  ----  ----       */
+          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ /* 0x90     �°     j     k     l     m     n     o     p */
+          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ /* 0x98     q     r                    ----        ---- */
+          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ /* 0xA0           ~     s     t     u     v     w     x */
+          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ /* 0xA8     y     z              ----  ----  ----  ---- */
+          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ /* 0xB0                          ----     �§  ----       */
+          0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ /* 0xB8        ----           |  ----  ----  ----  ---- */
+          0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
+ /* 0xC0     {     A     B     C     D     E     F     G */
+          0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ /* 0xC8     H     I  ----           �ö              ---- */
+          0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ /* 0xD0     }     J     K     L     M     N     O     P */
+          0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ /* 0xD8     Q     R  ----           �ü                   */
+          0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ /* 0xE0     \           S     T     U     V     W     X */
+          0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ /* 0xE8     Y     Z        ----     �Ö  ----  ----  ---- */
+          0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ /* 0xF0     0     1     2     3     4     5     6     7 */
+          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ /* 0xF8     8     9  ----  ----     �Ü  ----  ----  ---- */
+          0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
+};
+
+
+/*
+ * EBCDIC 037/500 conversion table:
+ * from upper to lower case
+ */
+__u8 _ebc_tolower[256] =
+{
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+	0x60, 0x61, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+	0x48, 0x49, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+	0x70, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+	0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
+	0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9C, 0x9F,
+	0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+	0xA8, 0xA9, 0xAA, 0xAB, 0x8C, 0x8D, 0x8E, 0xAF,
+	0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+	0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+	0xC0, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+	0x88, 0x89, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+	0xD0, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+	0x98, 0x99, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF,
+	0xE0, 0xE1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
+	0xA8, 0xA9, 0xEA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
+	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+	0xF8, 0xF9, 0xFA, 0xDB, 0xDC, 0xDD, 0xDE, 0xFF
+};
+
+
+/*
+ * EBCDIC 037/500 conversion table:
+ * from lower to upper case
+ */
+__u8 _ebc_toupper[256] =
+{
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+	0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+	0x40, 0x41, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+	0x50, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+	0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+	0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
+	0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
+	0x80, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+	0xC8, 0xC9, 0x8A, 0x8B, 0xAC, 0xAD, 0xAE, 0x8F,
+	0x90, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+	0xD8, 0xD9, 0x9A, 0x9B, 0x9E, 0x9D, 0x9E, 0x9F,
+	0xA0, 0xA1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+	0xE8, 0xE9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
+	0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7,
+	0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
+	0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+	0xC8, 0xC9, 0xCA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+	0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
+	0xD8, 0xD9, 0xDA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF,
+	0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
+	0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
+	0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+	0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
+};
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/entry.S linux/arch/s390x/kernel/entry.S
--- v2.4.1/linux/arch/s390x/kernel/entry.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/entry.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,868 @@
+/*
+ *  arch/s390/kernel/entry.S
+ *    S390 low-level entry points.
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Hartmut Penner (hp@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <linux/config.h>
+#include <asm/lowcore.h>
+#include <asm/errno.h>
+#define ASSEMBLY
+#include <asm/smp.h>
+#include <asm/s390-regs-common.h>
+
+
+/*
+ * stack layout for the system_call stack entry
+ * Martin please don't modify these back to hard coded values 
+ * You know how bad I'm at mental arithmetic DJB & it gives 
+ * me grief when I modify the pt_regs
+ */
+SP_PTREGS    =  STACK_FRAME_OVERHEAD 
+SP_PSW       =  SP_PTREGS
+SP_R0        =  (SP_PSW+PSW_MASK_SIZE+PSW_ADDR_SIZE)
+SP_R1        =  (SP_R0+GPR_SIZE)
+SP_R2        =  (SP_R1+GPR_SIZE)
+SP_R3        =  (SP_R2+GPR_SIZE)
+SP_R4        =  (SP_R3+GPR_SIZE)
+SP_R5        =  (SP_R4+GPR_SIZE)
+SP_R6        =  (SP_R5+GPR_SIZE)
+SP_R7        =  (SP_R6+GPR_SIZE)
+SP_R8        =  (SP_R7+GPR_SIZE)
+SP_R9        =  (SP_R8+GPR_SIZE)
+SP_RA        =  (SP_R9+GPR_SIZE)
+SP_RB        =  (SP_RA+GPR_SIZE)
+SP_RC        =  (SP_RB+GPR_SIZE)
+SP_RD        =  (SP_RC+GPR_SIZE)
+SP_RE        =  (SP_RD+GPR_SIZE)
+SP_RF        =  (SP_RE+GPR_SIZE)
+SP_AREGS     =  (SP_RF+GPR_SIZE)
+SP_ORIG_R2   =  (SP_AREGS+(NUM_ACRS*ACR_SIZE))
+SP_TRAP      =  (SP_ORIG_R2+GPR_SIZE)
+#if CONFIG_REMOTE_DEBUG
+SP_CRREGS    =  (SP_TRAP+4)
+/* fpu registers are saved & restored by the gdb stub itself */
+SP_FPC       =  (SP_CRREGS+(NUM_CRS*CR_SIZE))
+SP_FPRS      =  (SP_FPC+FPC_SIZE+FPC_PAD_SIZE)
+/* SP_PGM_OLD_ILC etc are not part of pt_regs & they are not 
+ defined in ptrace.h but space is needed for this too */
+SP_PGM_OLD_ILC= (SP_FPRS+(NUM_FPRS*FPR_SIZE))
+#else
+SP_PGM_OLD_ILC= (SP_TRAP+4)
+#endif
+SP_SVC_STEP   = (SP_PGM_OLD_ILC+4) 
+SP_SIZE      =  (SP_SVC_STEP+4)
+/*
+ * these defines are offsets into the thread_struct
+ */
+_TSS_PTREGS  = 0
+_TSS_FPRS    = (_TSS_PTREGS+8)
+_TSS_AR2     = (_TSS_FPRS+136)
+_TSS_AR4     = (_TSS_AR2+4)
+_TSS_KSP     = (_TSS_AR4+4)
+_TSS_USERSEG = (_TSS_KSP+8)
+_TSS_PROT    = (_TSS_USERSEG+8)
+_TSS_ERROR   = (_TSS_PROT+8)
+_TSS_TRAP    = (_TSS_ERROR+4)
+_TSS_PER     = (_TSS_TRAP+4)
+
+/*
+ * these are offsets into the task-struct.
+ */
+state        =  0
+flags        =  8
+sigpending   = 16
+need_resched = 32
+tsk_ptrace   = 40
+processor    = 100
+
+/* PSW related defines */
+disable      = 0xFC
+enable       = 0x03
+daton        = 0x04
+
+
+#if 0
+/* some code left lying around in case we need a
+ *	printk for debugging purposes
+ */
+  sysc_printk:        .long  printk
+  sysc_msg:	      .string "<2>r15 %X\n"
+	.align 4
+		
+#	basr    %r13,0
+	lg      %r0,SP_PSW+8(%r15)
+	sllg    %r0,%r0,1
+	chi     %r0,0
+	jnz     sysc_dn
+        la      %r2,sysc_msg-sysc_lit(%r13)
+        lgr     %r3,%r15
+        brasl   %r14,sysc_printk
+sysc_dn:
+#endif
+
+/*
+ * Register usage in interrupt handlers:
+ *    R9  - pointer to current task structure
+ *    R13 - pointer to literal pool
+ *    R14 - return register for function calls
+ *    R15 - kernel stack pointer
+ */
+
+#define SAVE_ALL(psworg) \
+	stmg    %r14,%r15,__LC_SAVE_AREA   ; \
+        stam    %a2,%a4,__LC_SAVE_AREA+16 ; \
+        tm      psworg+1,0x01         ; /* test problem state bit */ \
+	jz	0f		      ; /* skip stack setup save */ \
+	lg      %r15,__LC_KERNEL_STACK ; /* problem state -> load ksp */ \
+        slr     %r14,%r14             ; \
+        sar     %a2,%r14              ; /* set ac.reg. 2 to primary space */ \
+        lhi     %r14,1                ; \
+        sar     %a4,%r14              ; /* set access reg. 4 to home space */ \
+0:	aghi    %r15,-SP_SIZE         ; /* make room for registers & psw */ \
+        nill    %r15,0xfff8           ; /* align stack pointer to 8 */ \
+        stmg    %r0,%r14,SP_R0(%r15)  ; /* store gprs 0-14 to kernel stack */ \
+        stg     %r2,SP_ORIG_R2(%r15)  ; /* store original content of gpr 2 */ \
+        mvc     SP_RE(16,%r15),__LC_SAVE_AREA   ; /* move R15 to stack */ \
+        stam    %a0,%a15,SP_AREGS(%r15) ; /* store access registers to kst. */\
+        mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+16 ; /* store ac. regs */ \
+        mvc     SP_PSW(16,%r15),psworg; /* move user PSW to stack */ \
+        lhi     %r0,psworg            ; /* store trap indication */ \
+        st      %r0,SP_TRAP(%r15)     ; \
+        xc      0(8,%r15),0(%r15)     ; /* clear back chain */
+
+#define RESTORE_ALL \
+        mvc     __LC_RETURN_PSW(16),SP_PSW(%r15) ; /* move user PSW to lowcore */ \
+        lam     %a0,%a15,SP_AREGS(%r15) ; /* load the access registers */ \
+        lmg     %r0,%r15,SP_R0(%r15)    ; /* load gprs 0-15 of user */ \
+        ni      __LC_RETURN_PSW+1,0xfd  ; /* clear wait state bit */ \
+        lpswe   __LC_RETURN_PSW           /* back to caller */
+
+#define GET_CURRENT /* load pointer to task_struct to R9 */ \
+        lghi    %r9,-16384            ; \
+        ngr     %r9,15
+
+
+/*
+ * Scheduler resume function, called by switch_to
+ *  grp2 = (thread_struct *) prev->tss
+ *  grp3 = (thread_struct *) next->tss
+ * Returns:
+ *  gpr2 = prev
+ */
+        .globl  resume
+resume:
+        lg      %r4,_TSS_PTREGS(%r3)
+        tm      SP_PSW-SP_PTREGS(%r4),0x40 # is the new process using per ?
+        jz      resume_noper            # if not we're fine
+        stctg   %r9,%r11,48(%r15)       # We are using per stuff
+        clc     _TSS_PER(24,%r3),48(%r15)
+        je      resume_noper            # we got away without bashing TLB's
+        lctlg   %c9,%c11,_TSS_PER(%r3)  # Nope we didn't
+resume_noper:
+        stmg    %r6,%r15,48(%r15)       # store resume registers of prev task
+        stg     %r15,_TSS_KSP(%r2) # store kernel stack ptr to prev->tss.ksp
+        lghi    %r0,-16384
+        ngr     %r0,%r15
+        lg      %r15,_TSS_KSP(%r3) # load kernel stack ptr from next->tss.ksp
+        lghi    %r1,16383
+        ogr     %r1,%r15
+        aghi    %r1,1
+        stg     %r1,__LC_KERNEL_STACK   # __LC_KERNEL_STACK = new kernel stack
+        stam    %a2,%a2,_TSS_AR2(%r2)   # store kernel access reg. 2
+        stam    %a4,%a4,_TSS_AR4(%r2)   # store kernel access reg. 4
+        lam     %a2,%a2,_TSS_AR2(%r3)   # load kernel access reg. 2
+        lam     %a4,%a4,_TSS_AR4(%r3)   # load kernel access reg. 4
+        lgr     %r2,%r0                 # return task_struct of last task
+        lmg     %r6,%r15,48(%r15)       # load resume registers of next task
+        br      %r14
+
+/*
+ * SVC interrupt handler routine. System calls are synchronous events and
+ * are executed with interrupts enabled.
+ */
+
+	.globl  system_call
+system_call:
+        SAVE_ALL(__LC_SVC_OLD_PSW)
+	xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
+pgm_system_call:
+	larl    %r1,sys_call_table
+	llgc    %r8,__LC_SVC_INT_CODE+1 # get svc number from lowcore
+	stosm   48(%r15),0x03     # reenable interrupts
+        sll     %r8,3
+        tm      SP_PSW+3(%r15),0x01  # are we running in 31 bit mode ?
+        jo      sysc_noemu
+	la      %r8,4(%r8)        # use 31 bit emulation system calls
+sysc_noemu:
+        GET_CURRENT               # load pointer to task_struct to R9
+        lgf     %r8,0(%r8,%r1)    # load address of system call routine
+        tm      tsk_ptrace+7(%r9),0x02 # PT_TRACESYS
+        jnz     sysc_tracesys
+        basr    %r14,%r8          # call sys_xxxx
+        stg     %r2,SP_R2(%r15)   # store return value (change R2 on stack)
+                                  # ATTENTION: check sys_execve_glue before
+                                  # changing anything here !!
+
+sysc_return:
+        GET_CURRENT               # load pointer to task_struct to R9
+        tm      SP_PSW+1(%r15),0x01 # returning to user ?
+        jno     sysc_leave        # no-> skip bottom half, resched & signal
+#
+# check, if bottom-half has to be done
+#
+        l       %r0,__LC_IRQ_STAT     # get softirq_active
+        n       %r0,__LC_IRQ_STAT+4   # and it with softirq_mask
+        jnz     sysc_handle_bottom_half
+#
+# check, if reschedule is needed
+#
+sysc_return_bh:
+	lg      %r0,need_resched(%r9) # get need_resched from task_struct
+	ltgr    %r0,%r0
+        jnz     sysc_reschedule
+        icm     %r0,15,sigpending(%r9)   # get sigpending from task_struct
+        jnz     sysc_signal_return
+sysc_leave:
+	icm     %r0,15,SP_SVC_STEP(%r15)   # get sigpending from task_struct
+        jnz     pgm_svcret
+	stnsm   48(%r15),disable  # disable I/O and ext. interrupts
+        RESTORE_ALL
+
+#
+# call do_signal before return
+#
+sysc_signal_return:     
+        la      %r2,SP_PTREGS(%r15) # load pt_regs
+        sgr     %r3,%r3             # clear *oldset
+	larl    %r14,sysc_leave
+	jg      do_signal           # return point is sysc_leave
+
+#
+# call trace before and after sys_call
+#
+sysc_tracesys:
+	lghi    %r2,-ENOSYS
+	stg     %r2,SP_R2(%r15)     # give sysc_trace an -ENOSYS retval
+        brasl   %r14,syscall_trace
+	lmg     %r3,%r6,SP_R3(%r15)
+	lg      %r2,SP_ORIG_R2(%r15)
+        basr    %r14,%r8            # call sys_xxx
+        stg     %r2,SP_R2(%r15)     # store return value
+	larl    %r14,sysc_return
+        jg      syscall_trace       # return point is sysc_return
+
+
+#
+# call do_softirq and return from syscall, if interrupt-level
+# is zero
+#
+sysc_handle_bottom_half:        
+	larl    %r14,sysc_return_bh
+        jg      do_softirq          # return point is sysc_return_bh
+
+#
+# call schedule with sysc_return as return-address
+#
+sysc_reschedule:        
+	larl    %r14,sysc_return
+        jg      schedule            # return point is sysc_return
+
+#
+# a new process exits the kernel with ret_from_fork
+#
+        .globl  ret_from_fork
+ret_from_fork:  
+        GET_CURRENT               # load pointer to task_struct to R9
+        stosm   48(%r15),0x03     # reenable interrupts
+	xc      SP_R2(8,%r15),SP_R2(%r15) # child returns 0
+#ifdef CONFIG_SMP
+	larl    %r14,sysc_return
+        jg      schedule_tail     # return to sysc_return
+#else
+        j       sysc_return
+#endif
+
+#
+# clone, fork, vfork, exec and sigreturn need glue,
+# because they all expect pt_regs as parameter,
+# but are called with different parameter.
+# return-address is set up above
+#
+sys_clone_glue: 
+        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+        jg      sys_clone              # branch to sys_clone
+
+sys_fork_glue:  
+        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+        jg      sys_fork               # branch to sys_fork
+
+sys_vfork_glue: 
+        la      %r2,SP_PTREGS(%r15)    # load pt_regs
+        jg      sys_vfork              # branch to sys_vfork
+
+sys_execve_glue:        
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs
+	lgr     %r12,%r14             # save return address
+        brasl   %r14,sys_execve       # call sys_execve
+        ltgr    %r2,%r2               # check if execve failed
+        bnz     0(%r12)               # it did fail -> store result in gpr2
+        b       6(%r12)               # SKIP STG 2,SP_R2(15) in
+                                      # system_call/sysc_tracesys
+#ifdef CONFIG_S390_SUPPORT
+sys32_execve_glue:        
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs
+	lgr     %r12,%r14             # save return address
+        brasl   %r14,sys32_execve     # call sys32_execve
+        ltgr    %r2,%r2               # check if execve failed
+        bnz     0(%r12)               # it did fail -> store result in gpr2
+        b       6(%r12)               # SKIP STG 2,SP_R2(15) in
+                                      # system_call/sysc_tracesys
+#endif
+
+sys_sigreturn_glue:     
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        jg      sys_sigreturn         # branch to sys_sigreturn
+
+#ifdef CONFIG_S390_SUPPORT
+sys32_sigreturn_glue:     
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        jg      sys32_sigreturn       # branch to sys32_sigreturn
+#endif
+
+sys_rt_sigreturn_glue:     
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        jg      sys_rt_sigreturn      # branch to sys_sigreturn
+
+#ifdef CONFIG_S390_SUPPORT
+sys32_rt_sigreturn_glue:     
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as parameter
+        jg      sys32_rt_sigreturn    # branch to sys32_sigreturn
+#endif
+
+#
+# sigsuspend and rt_sigsuspend need pt_regs as an additional
+# parameter and they have to skip the store of %r2 into the
+# user register %r2 because the return value was set in 
+# sigsuspend and rt_sigsuspend already and must not be overwritten!
+#
+
+sys_sigsuspend_glue:    
+        lgr     %r5,%r4               # move mask back
+        lgr     %r4,%r3               # move history1 parameter
+        lgr     %r3,%r2               # move history0 parameter
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
+	la      %r14,6(%r14)          # skip store of return value
+        jg      sys_sigsuspend        # branch to sys_sigsuspend
+
+#ifdef CONFIG_S390_SUPPORT
+sys32_sigsuspend_glue:    
+	llgfr	%r4,%r4               # unsigned long			
+        lgr     %r5,%r4               # move mask back
+	lgfr	%r3,%r3               # int			
+        lgr     %r4,%r3               # move history1 parameter
+	lgfr	%r2,%r2               # int			
+        lgr     %r3,%r2               # move history0 parameter
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
+	la      %r14,6(%r14)          # skip store of return value
+        jg      sys32_sigsuspend      # branch to sys32_sigsuspend
+#endif
+
+sys_rt_sigsuspend_glue: 
+        lgr     %r4,%r3               # move sigsetsize parameter
+        lgr     %r3,%r2               # move unewset parameter
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
+	la      %r14,6(%r14)          # skip store of return value
+        jg      sys_rt_sigsuspend     # branch to sys_rt_sigsuspend
+
+#ifdef CONFIG_S390_SUPPORT
+sys32_rt_sigsuspend_glue: 
+	llgfr	%r3,%r3               # size_t			
+        lgr     %r4,%r3               # move sigsetsize parameter
+	llgtr	%r2,%r2               # sigset_emu31_t *
+        lgr     %r3,%r2               # move unewset parameter
+        la      %r2,SP_PTREGS(%r15)   # load pt_regs as first parameter
+	la      %r14,6(%r14)          # skip store of return value
+        jg      sys32_rt_sigsuspend   # branch to sys32_rt_sigsuspend
+#endif
+
+sys_sigaltstack_glue:
+        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
+        jg      sys_sigaltstack       # branch to sys_sigreturn
+
+#ifdef CONFIG_S390_SUPPORT
+sys32_sigaltstack_glue:
+        la      %r4,SP_PTREGS(%r15)   # load pt_regs as parameter
+        jg      sys32_sigaltstack_wrapper # branch to sys_sigreturn
+#endif
+
+#ifdef CONFIG_S390_SUPPORT
+#define SYSCALL(esame,esa) esame,esa
+#else
+#define SYSCALL(esame,esa) esame,sys_ni_syscall
+#endif
+
+	.globl  sys_call_table	
+sys_call_table:
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 0 */
+        .long  SYSCALL(sys_exit,sys32_exit_wrapper)
+        .long  SYSCALL(sys_fork_glue,sys_fork_glue)
+        .long  SYSCALL(sys_read,sys32_read_wrapper)
+        .long  SYSCALL(sys_write,sys32_write_wrapper)
+        .long  SYSCALL(sys_open,sys32_open_wrapper)             /* 5 */
+        .long  SYSCALL(sys_close,sys32_close_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old waitpid syscall */
+        .long  SYSCALL(sys_creat,sys32_creat_wrapper)
+        .long  SYSCALL(sys_link,sys32_link_wrapper)
+        .long  SYSCALL(sys_unlink,sys32_unlink_wrapper)         /* 10 */
+        .long  SYSCALL(sys_execve_glue,sys32_execve_glue)
+        .long  SYSCALL(sys_chdir,sys32_chdir_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_time_wrapper) /* old time syscall */
+        .long  SYSCALL(sys_mknod,sys32_mknod_wrapper)
+        .long  SYSCALL(sys_chmod,sys32_chmod_wrapper)           /* 15 */
+        .long  SYSCALL(sys_ni_syscall,sys32_lchown16_wrapper)   /* old lchown16 syscall*/
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old break syscall */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old stat syscall */
+        .long  SYSCALL(sys_lseek,sys32_lseek_wrapper)
+        .long  SYSCALL(sys_getpid,sys_getpid) /* 20 */
+        .long  SYSCALL(sys_mount,sys32_mount_wrapper)
+        .long  SYSCALL(sys_oldumount,sys32_oldumount_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_setuid16_wrapper)   /* old setuid16 syscall*/
+        .long  SYSCALL(sys_ni_syscall,sys32_getuid16)   /* old getuid16 syscall*/
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* 25 old stime syscall */
+        .long  SYSCALL(sys_ptrace,sys32_ptrace_wrapper)
+        .long  SYSCALL(sys_alarm,sys32_alarm_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old fstat syscall */
+        .long  SYSCALL(sys_pause,sys32_pause)
+        .long  SYSCALL(sys_utime,sys32_utime_wrapper)           /* 30 */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old stty syscall */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old gtty syscall */
+        .long  SYSCALL(sys_access,sys32_access_wrapper)
+        .long  SYSCALL(sys_nice,sys32_nice_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old ftime syscall */
+        .long  SYSCALL(sys_sync,sys_sync)
+        .long  SYSCALL(sys_kill,sys32_kill_wrapper)
+        .long  SYSCALL(sys_rename,sys32_rename_wrapper)
+        .long  SYSCALL(sys_mkdir,sys32_mkdir_wrapper)
+        .long  SYSCALL(sys_rmdir,sys32_rmdir_wrapper)           /* 40 */
+        .long  SYSCALL(sys_dup,sys32_dup_wrapper)
+        .long  SYSCALL(sys_pipe,sys32_pipe_wrapper)
+        .long  SYSCALL(sys_times,sys32_times_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old prof syscall */
+        .long  SYSCALL(sys_brk,sys32_brk_wrapper)               /* 45 */
+        .long  SYSCALL(sys_ni_syscall,sys32_setgid16)   /* old setgid16 syscall*/
+        .long  SYSCALL(sys_ni_syscall,sys32_getgid16)   /* old getgid16 syscall*/
+        .long  SYSCALL(sys_signal,sys32_signal_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_geteuid16)  /* old geteuid16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_getegid16)  /* old getegid16 syscall */
+        .long  SYSCALL(sys_acct,sys32_acct_wrapper)
+        .long  SYSCALL(sys_umount,sys32_umount_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old lock syscall */
+        .long  SYSCALL(sys_ioctl,sys32_ioctl_wrapper)
+        .long  SYSCALL(sys_fcntl,sys32_fcntl_wrapper)   /* 55 */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* intel mpx syscall */
+        .long  SYSCALL(sys_setpgid,sys32_setpgid_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old ulimit syscall */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old uname syscall */
+        .long  SYSCALL(sys_umask,sys32_umask_wrapper)           /* 60 */
+        .long  SYSCALL(sys_chroot,sys32_chroot_wrapper)
+        .long  SYSCALL(sys_ustat,sys32_ustat_wrapper)
+        .long  SYSCALL(sys_dup2,sys32_dup2_wrapper)
+        .long  SYSCALL(sys_getppid,sys_getppid)
+        .long  SYSCALL(sys_getpgrp,sys_getpgrp)       /* 65 */
+        .long  SYSCALL(sys_setsid,sys_setsid)
+        .long  SYSCALL(sys_sigaction,sys32_sigaction_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old sgetmask syscall*/
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old ssetmask syscall*/
+        .long  SYSCALL(sys_ni_syscall,sys32_setreuid16_wrapper) /* old setreuid16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_setregid16_wrapper) /* old setregid16 syscall */
+        .long  SYSCALL(sys_sigsuspend_glue,sys32_sigsuspend_glue)
+        .long  SYSCALL(sys_sigpending,sys32_sigpending_wrapper)
+        .long  SYSCALL(sys_sethostname,sys32_sethostname_wrapper)
+        .long  SYSCALL(sys_setrlimit,sys32_setrlimit_wrapper)   /* 75 */
+        .long  SYSCALL(sys_getrlimit,sys32_old_getrlimit_wrapper) 
+        .long  SYSCALL(sys_getrusage,sys32_getrusage_wrapper)
+        .long  SYSCALL(sys_gettimeofday,sys32_gettimeofday_wrapper)
+        .long  SYSCALL(sys_settimeofday,sys32_settimeofday_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_getgroups16_wrapper) /* old getgroups16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_setgroups16_wrapper) /* old setgroups16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old select syscall */
+        .long  SYSCALL(sys_symlink,sys32_symlink_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old lstat syscall */
+        .long  SYSCALL(sys_readlink,sys32_readlink_wrapper)     /* 85 */
+        .long  SYSCALL(sys_uselib,sys32_uselib_wrapper)
+        .long  SYSCALL(sys_swapon,sys32_swapon_wrapper)
+        .long  SYSCALL(sys_reboot,sys32_reboot_wrapper)
+        .long  SYSCALL(sys_ni_syscall,old32_readdir_wrapper) /* old readdir syscall */
+        .long  SYSCALL(old_mmap,old32_mmap_wrapper)       /* 90 */
+        .long  SYSCALL(sys_munmap,sys32_munmap_wrapper)
+        .long  SYSCALL(sys_truncate,sys32_truncate_wrapper)
+        .long  SYSCALL(sys_ftruncate,sys32_ftruncate_wrapper)
+        .long  SYSCALL(sys_fchmod,sys32_fchmod_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_fchown16_wrapper)   /* old fchown16 syscall*/
+        .long  SYSCALL(sys_getpriority,sys32_getpriority_wrapper)
+        .long  SYSCALL(sys_setpriority,sys32_setpriority_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old profil syscall */
+        .long  SYSCALL(sys_statfs,sys32_statfs_wrapper)
+        .long  SYSCALL(sys_fstatfs,sys32_fstatfs_wrapper)   /* 100 */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
+        .long  SYSCALL(sys_socketcall,sys32_socketcall_wrapper)
+        .long  SYSCALL(sys_syslog,sys32_syslog_wrapper)
+        .long  SYSCALL(sys_setitimer,sys32_setitimer_wrapper)
+        .long  SYSCALL(sys_getitimer,sys32_getitimer_wrapper)   /* 105 */
+        .long  SYSCALL(sys_newstat,sys32_newstat_wrapper)
+        .long  SYSCALL(sys_newlstat,sys32_newlstat_wrapper)
+        .long  SYSCALL(sys_newfstat,sys32_newfstat_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old uname syscall */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* iopl for i386 */
+        .long  SYSCALL(sys_vhangup,sys_vhangup)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* old "idle" system call */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* vm86old for i386 */
+        .long  SYSCALL(sys_wait4,sys32_wait4_wrapper)
+        .long  SYSCALL(sys_swapoff,sys32_swapoff_wrapper)       /* 115 */
+        .long  SYSCALL(sys_sysinfo,sys32_sysinfo_wrapper)
+        .long  SYSCALL(sys_ipc,sys32_ipc_wrapper)
+        .long  SYSCALL(sys_fsync,sys32_fsync_wrapper)
+        .long  SYSCALL(sys_sigreturn_glue,sys32_sigreturn_glue)
+        .long  SYSCALL(sys_clone_glue,sys_clone_glue) /* 120 */
+        .long  SYSCALL(sys_setdomainname,sys32_setdomainname_wrapper)
+        .long  SYSCALL(sys_newuname,sys32_newuname_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* modify_ldt for i386 */
+        .long  SYSCALL(sys_adjtimex,sys32_adjtimex_wrapper)
+        .long  SYSCALL(sys_mprotect,sys32_mprotect_wrapper) /* 125 */
+        .long  SYSCALL(sys_sigprocmask,sys32_sigprocmask_wrapper)
+        .long  SYSCALL(sys_create_module,sys32_create_module_wrapper)
+        .long  SYSCALL(sys_init_module,sys32_init_module_wrapper)
+        .long  SYSCALL(sys_delete_module,sys32_delete_module_wrapper)
+        .long  SYSCALL(sys_get_kernel_syms,sys32_get_kernel_syms_wrapper) /* 130 */
+        .long  SYSCALL(sys_quotactl,sys32_quotactl_wrapper)
+        .long  SYSCALL(sys_getpgid,sys32_getpgid_wrapper)
+        .long  SYSCALL(sys_fchdir,sys32_fchdir_wrapper)
+        .long  SYSCALL(sys_bdflush,sys32_bdflush_wrapper)
+        .long  SYSCALL(sys_sysfs,sys32_sysfs_wrapper)           /* 135 */
+        .long  SYSCALL(sys_personality,sys32_personality_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* for afs_syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_setfsuid16_wrapper) /* old setfsuid16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_setfsgid16_wrapper) /* old setfsgid16 syscall */
+        .long  SYSCALL(sys_llseek,sys32_llseek_wrapper)         /* 140 */
+        .long  SYSCALL(sys_getdents,sys32_getdents_wrapper)
+        .long  SYSCALL(sys_select,sys32_select_wrapper)
+        .long  SYSCALL(sys_flock,sys32_flock_wrapper)
+        .long  SYSCALL(sys_msync,sys32_msync_wrapper)
+        .long  SYSCALL(sys_readv,sys32_readv_wrapper)           /* 145 */
+        .long  SYSCALL(sys_writev,sys32_writev_wrapper)
+        .long  SYSCALL(sys_getsid,sys32_getsid_wrapper)
+        .long  SYSCALL(sys_fdatasync,sys32_fdatasync_wrapper)
+        .long  SYSCALL(sys_sysctl,sys_ni_syscall)
+        .long  SYSCALL(sys_mlock,sys32_mlock_wrapper)           /* 150 */
+        .long  SYSCALL(sys_munlock,sys32_munlock_wrapper)
+        .long  SYSCALL(sys_mlockall,sys32_mlockall_wrapper)
+        .long  SYSCALL(sys_munlockall,sys_munlockall)
+        .long  SYSCALL(sys_sched_setparam,sys32_sched_setparam_wrapper)
+        .long  SYSCALL(sys_sched_getparam,sys32_sched_getparam_wrapper) /* 155 */
+        .long  SYSCALL(sys_sched_setscheduler,sys32_sched_setscheduler_wrapper)
+        .long  SYSCALL(sys_sched_getscheduler,sys32_sched_getscheduler_wrapper)
+        .long  SYSCALL(sys_sched_yield,sys_sched_yield)
+        .long  SYSCALL(sys_sched_get_priority_max,sys32_sched_get_priority_max_wrapper)
+        .long  SYSCALL(sys_sched_get_priority_min,sys32_sched_get_priority_min_wrapper)
+        .long  SYSCALL(sys_sched_rr_get_interval,sys32_sched_rr_get_interval_wrapper)
+        .long  SYSCALL(sys_nanosleep,sys32_nanosleep_wrapper)
+        .long  SYSCALL(sys_mremap,sys32_mremap_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_setresuid16_wrapper) /* old setresuid16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_getresuid16_wrapper) /* old getresuid16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* for vm86 */
+        .long  SYSCALL(sys_query_module,sys32_query_module_wrapper)
+        .long  SYSCALL(sys_poll,sys32_poll_wrapper)
+        .long  SYSCALL(sys_nfsservctl,sys32_nfsservctl_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_setresgid16_wrapper) /* old setresgid16 syscall */
+        .long  SYSCALL(sys_ni_syscall,sys32_getresgid16_wrapper) /* old getresgid16 syscall */
+        .long  SYSCALL(sys_prctl,sys32_prctl_wrapper)
+        .long  SYSCALL(sys_rt_sigreturn_glue,sys32_rt_sigreturn_glue)
+        .long  SYSCALL(sys_rt_sigaction,sys32_rt_sigaction_wrapper)
+        .long  SYSCALL(sys_rt_sigprocmask,sys32_rt_sigprocmask_wrapper) /* 175 */
+        .long  SYSCALL(sys_rt_sigpending,sys32_rt_sigpending_wrapper)
+        .long  SYSCALL(sys_rt_sigtimedwait,sys32_rt_sigtimedwait_wrapper)
+        .long  SYSCALL(sys_rt_sigqueueinfo,sys32_rt_sigqueueinfo_wrapper)
+        .long  SYSCALL(sys_rt_sigsuspend_glue,sys32_rt_sigsuspend_glue)
+        .long  SYSCALL(sys_pread,sys32_pread_wrapper)           /* 180 */
+        .long  SYSCALL(sys_pwrite,sys32_pwrite_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_chown16_wrapper)    /* old chown16 syscall */
+        .long  SYSCALL(sys_getcwd,sys32_getcwd_wrapper)
+        .long  SYSCALL(sys_capget,sys32_capget_wrapper)
+        .long  SYSCALL(sys_capset,sys32_capset_wrapper)         /* 185 */
+        .long  SYSCALL(sys_sigaltstack_glue,sys32_sigaltstack_glue)
+        .long  SYSCALL(sys_sendfile,sys32_sendfile_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* streams1 */
+        .long  SYSCALL(sys_ni_syscall,sys_ni_syscall) /* streams2 */
+        .long  SYSCALL(sys_vfork_glue,sys_vfork_glue) /* 190 */
+        .long  SYSCALL(sys_getrlimit,sys32_old_getrlimit_wrapper)
+	.long  SYSCALL(sys_mmap2,sys32_mmap2_wrapper)
+	.long  SYSCALL(sys_ni_syscall,sys32_truncate64_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_ftruncate64_wrapper)
+        .long  SYSCALL(sys_ni_syscall,sys32_stat64)     /* 195 */
+        .long  SYSCALL(sys_ni_syscall,sys32_lstat64)   
+        .long  SYSCALL(sys_ni_syscall,sys32_fstat64)    
+	.long  SYSCALL(sys_lchown,sys32_lchown_wrapper)
+	.long  SYSCALL(sys_getuid,sys_getuid)
+	.long  SYSCALL(sys_getgid,sys_getgid)         /* 200 */
+	.long  SYSCALL(sys_geteuid,sys_geteuid)
+	.long  SYSCALL(sys_getegid,sys_getegid)
+	.long  SYSCALL(sys_setreuid,sys32_setreuid_wrapper)
+	.long  SYSCALL(sys_setregid,sys32_setregid_wrapper)
+	.long  SYSCALL(sys_getgroups,sys32_getgroups_wrapper)  /* 205 */
+	.long  SYSCALL(sys_setgroups,sys32_setgroups_wrapper)
+	.long  SYSCALL(sys_fchown,sys32_fchown_wrapper)
+	.long  SYSCALL(sys_setresuid,sys32_setresuid_wrapper)
+	.long  SYSCALL(sys_getresuid,sys32_getresuid_wrapper)
+	.long  SYSCALL(sys_setresgid,sys32_setresgid_wrapper)  /* 210 */
+	.long  SYSCALL(sys_getresgid,sys32_getresgid_wrapper)
+	.long  SYSCALL(sys_chown,sys32_chown_wrapper)
+	.long  SYSCALL(sys_setuid,sys32_setuid_wrapper)
+	.long  SYSCALL(sys_setgid,sys32_setgid_wrapper)
+	.long  SYSCALL(sys_setfsuid,sys32_setfsuid_wrapper)   /* 215 */
+	.long  SYSCALL(sys_setfsgid,sys32_setfsgid_wrapper)
+        .long  SYSCALL(sys_pivot_root,sys32_pivot_root_wrapper)
+        .long  SYSCALL(sys_mincore,sys32_mincore_wrapper)
+        .long  SYSCALL(sys_madvise,sys32_madvise_wrapper)
+	.long  SYSCALL(sys_ni_syscall,sys32_getdents64_wrapper)/* 220 */
+	.long  SYSCALL(sys_ni_syscall,sys32_fcntl64_wrapper)
+        .rept  255-221
+	.long  SYSCALL(sys_ni_syscall,sys_ni_syscall)
+	.endr
+
+/*
+ * Program check handler routine
+ */
+
+        .globl  pgm_check_handler
+pgm_check_handler:
+/*
+ * First we need to check for a special case:
+ * Single stepping an instruction that disables the PER event mask will
+ * cause a PER event AFTER the mask has been set. Example: SVC or LPSW.
+ * For a single stepped SVC the program check handler gets control after
+ * the SVC new PSW has been loaded. But we want to execute the SVC first and
+ * then handle the PER event. Therefore we update the SVC old PSW to point
+ * to the pgm_check_handler and branch to the SVC handler after we checked
+ * if we have to load the kernel stack register.
+ * For every other possible cause for PER event without the PER mask set
+ * we just ignore the PER event (FIXME: is there anything we have to do
+ * for LPSW?).
+ */
+	stmg    %r14,%r15,__LC_SAVE_AREA
+        stam    %a2,%a4,__LC_SAVE_AREA+16
+        tm      __LC_PGM_INT_CODE+1,0x80 # check whether we got a per exception
+        jz      pgm_sv                   # skip if not
+        tm      __LC_PGM_OLD_PSW,0x40    # test if per event recording is on
+        jnz     pgm_sv                   # skip if it is
+# ok its one of the special cases, now we need to find out which one
+        clc     __LC_PGM_OLD_PSW(16),__LC_SVC_NEW_PSW
+        je      pgm_svcper
+# no interesting special case, ignore PER event
+        lm      %r13,%r15,__LC_SAVE_AREA
+	lpsw    __LC_PGM_OLD_PSW
+# it was a single stepped SVC that is causing all the trouble
+pgm_svcper:
+        tm      __LC_SVC_OLD_PSW+1,0x01  # test problem state bit
+	jz	0f                       # skip stack & access regs setup
+	lg      %r15,__LC_KERNEL_STACK   # problem state -> load ksp
+        slr     %r14,%r14
+        sar     %a2,%r14                 # set ac.reg. 2 to primary space
+        lhi     %r14,1   
+        sar     %a4,%r14                 # and access reg. 4 to home space
+0:	aghi    %r15,-SP_SIZE            # make room for registers & psw
+        nill    %r15,0xfff8              # align stack pointer to 8
+        stmg    %r0,%r14,SP_R0(%r15)     # store gprs 0-14 to kernel stack 
+        stg     %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
+        mvc     SP_RE(16,%r15),__LC_SAVE_AREA         # move R14-R15 to stack
+        stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
+        mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+16 # store ac. regs
+        mvc     SP_PSW(16,%r15),__LC_PGM_OLD_PSW      # move user PSW to stack
+        lhi     %r0,__LC_SVC_OLD_PSW     # store trap indication
+        st      %r0,SP_TRAP(%r15)
+        xc      0(8,%r15),0(%r15)        # clear back chain
+
+        mvi     SP_SVC_STEP(%r15),1 # make SP_SVC_STEP nonzero
+        mvc     SP_PGM_OLD_ILC(4,%r15),__LC_PGM_ILC # save program check information
+        j       pgm_system_call          # now do the svc
+pgm_svcret:
+	lhi     %r0,__LC_PGM_OLD_PSW     # set trap indication back to pgm_chk
+	st      %r0,SP_TRAP(%r15)
+        llgh    %r7,SP_PGM_OLD_ILC(%r15) # get ilc from stack
+        xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
+	j       pgm_no_sv
+pgm_sv:
+        tm      __LC_PGM_OLD_PSW+1,0x01  # test problem state bit
+	jz	1f		         # skip stack setup save
+	lg      %r15,__LC_KERNEL_STACK   # problem state -> load ksp
+        slr     %r14,%r14
+        sar     %a2,%r14                 # set ac.reg. 2 to primary space
+        lhi     %r14,1
+        sar     %a4,%r14                 # set access reg. 4 to home space
+1:	aghi    %r15,-SP_SIZE            # make room for registers & psw
+        nill    %r15,0xfff8              # align stack pointer to 8
+        stmg    %r0,%r14,SP_R0(%r15)     # store gprs 0-14 to kernel stack
+        stg     %r2,SP_ORIG_R2(%r15)     # store original content of gpr 2
+        mvc     SP_RE(16,%r15),__LC_SAVE_AREA         # move R14-R15 to stack
+        stam    %a0,%a15,SP_AREGS(%r15)  # store access registers to kst.
+        mvc     SP_AREGS+8(12,%r15),__LC_SAVE_AREA+16 # store ac. regs
+        mvc     SP_PSW(16,%r15),__LC_PGM_OLD_PSW      # move user PSW to stack
+        lhi     %r0,__LC_PGM_OLD_PSW     # store trap indication
+        st      %r0,SP_TRAP(%r15)
+        xc      0(8,%r15),0(%r15)        # clear back chain
+	xc      SP_SVC_STEP(4,%r15),SP_SVC_STEP(%r15)
+        llgh    %r7,__LC_PGM_ILC  # load instruction length
+pgm_no_sv:
+        llgh    %r8,__LC_PGM_INT_CODE  # N.B. saved int code used later KEEP it
+        stosm   48(%r15),0x03     # reenable interrupts
+	lghi    %r3,0x7f
+        nr      %r3,%r8           # clear per-event-bit & move to r3
+        je      pgm_dn            # none of Martins exceptions occured bypass
+        sll     %r3,3
+        larl    %r9,pgm_check_table
+        lg      %r9,0(%r3,%r9)    # load address of handler routine
+        srl     %r3,3
+        la      %r2,SP_PTREGS(%r15) # address of register-save area
+        chi     %r3,0x4           # protection-exception ?
+        jne     pgm_go            # if not,
+        lg      %r5,SP_PSW+8(15)  # load psw addr
+        slgr    %r5,%r7           # substract ilc from psw
+        stg     %r5,SP_PSW+8(15)  # store corrected psw addr
+pgm_go: basr    %r14,%r9          # branch to interrupt-handler
+pgm_dn: nill    %r8,0x80          # check for per exception
+        je      sysc_return
+        la      %r2,SP_PTREGS(15) # address of register-save area
+        larl    %r14,sysc_return  # load adr. of system return
+        jg      handle_per_exception
+
+/*
+ * IO interrupt handler routine
+ */
+        .globl io_int_handler
+io_int_handler:
+        SAVE_ALL(__LC_IO_OLD_PSW)
+        la      %r2,SP_PTREGS(%r15)    # address of register-save area
+	llgh    %r3,__LC_SUBCHANNEL_NR # load subchannel number
+        llgf    %r4,__LC_IO_INT_PARM   # load interruption parm
+        llgf    %r5,__LC_IO_INT_WORD   # load interruption word
+	brasl   %r14,do_IRQ            # call standard irq handler
+
+io_return:
+        GET_CURRENT                    # load pointer to task_struct to R9
+        tm      SP_PSW+1(%r15),0x01    # returning to user ?
+        jz      io_leave               # no-> skip resched & signal
+        stosm   48(%r15),0x03          # reenable interrupts
+#
+# check, if bottom-half has to be done
+#
+        l       %r0,__LC_IRQ_STAT     # get softirq_active
+        n       %r0,__LC_IRQ_STAT+4   # and it with softirq_mask
+        jnz     io_handle_bottom_half
+io_return_bh:	
+#
+# check, if reschedule is needed
+#
+	lg      %r0,need_resched(%r9)  # get need_resched from task_struct
+	ltgr    %r0,%r0
+        jnz     io_reschedule
+        icm     %r0,15,sigpending(%r9) # get sigpending from task_struct
+        jnz     io_signal_return
+io_leave:
+        stnsm   48(%r15),disable       # disable I/O and ext. interrupts
+        RESTORE_ALL
+
+#
+# call do_softirq and return from syscall, if interrupt-level
+# is zero
+#
+io_handle_bottom_half:        
+	larl    %r14,io_return_bh
+        jg      do_softirq          # return point is io_return_bh
+
+#
+# call schedule with io_return as return-address
+#
+io_reschedule:        
+	larl    %r14,io_return
+        jg      schedule            # call scheduler, return to io_return
+
+#
+# call do_signal before return
+#
+io_signal_return:     
+        la      %r2,SP_PTREGS(%r15) # load pt_regs
+        slgr    %r3,%r3             # clear *oldset
+	larl    %r14,io_leave
+        jg      do_signal           # return point is io_leave
+
+/*
+ * External interrupt handler routine
+ */
+        .globl  ext_int_handler
+ext_int_handler:
+        SAVE_ALL(__LC_EXT_OLD_PSW)
+        la      %r2,SP_PTREGS(%r15)    # address of register-save area
+        llgh    %r3,__LC_EXT_INT_CODE  # error code
+        lgr     %r1,%r3                # calculate index = code & 0xff
+	nill    %r1,0xff
+        sll     %r1,3
+        larl    %r9,ext_int_hash
+        lg      %r9,0(%r1,%r9)         # get first list entry for hash value
+        ltgr    %r9,%r9                # == NULL ?
+        jz      io_return              # yes, nothing to do, exit
+ext_int_loop:
+        ch      %r3,16(%r9)            # compare external interrupt code
+        je      ext_int_found
+        lg      %r9,0(%r9)             # next list entry
+	ltgr    %r9,%r9
+        jnz     ext_int_loop
+        j       io_return
+ext_int_found:
+        lg      %r9,8(%r9)             # get handler address
+        larl    %r14,io_return
+        br      %r9                    # branch to ext call handler
+
+/*
+ * Machine check handler routines
+ */
+        .globl mcck_int_handler
+mcck_int_handler:
+        SAVE_ALL(__LC_MCK_OLD_PSW)
+	brasl   %r14,s390_do_machine_check
+mcck_return:
+        RESTORE_ALL
+
+#ifdef CONFIG_SMP
+/*
+ * Restart interruption handler, kick starter for additional CPUs
+ */
+        .globl restart_int_handler
+restart_int_handler:
+        lg      %r15,__LC_KERNEL_STACK # load ksp
+        lctlg   %c0,%c15,__LC_CREGS_SAVE_AREA # get new ctl regs
+        lam     %a0,%a15,__LC_AREGS_SAVE_AREA
+        stosm   0(%r15),daton          # now we can turn dat on
+        lmg     %r6,%r15,48(%r15)      # load registers from clone
+	jg      start_secondary
+#else
+/*
+ * If we do not run with SMP enabled, let the new CPU crash ...
+ */
+        .globl restart_int_handler
+restart_int_handler:
+        basr    %r1,0
+restart_base:
+        lpswe   restart_crash-restart_base(%r1)
+        .align 8
+restart_crash:
+        .long  0x000a0000,0x00000000,0x00000000,0x00000000
+restart_go:
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/exec32.c linux/arch/s390x/kernel/exec32.c
--- v2.4.1/linux/arch/s390x/kernel/exec32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/exec32.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,85 @@
+/*
+ * Support for 32-bit Linux for S390 ELF binaries.
+ *
+ * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Gerhard Tonn (ton@de.ibm.com)
+ *
+ * Seperated from binfmt_elf32.c to reduce exports for module enablement.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/slab.h>
+#include <linux/file.h>
+#include <linux/mman.h>
+#include <linux/a.out.h>
+#include <linux/stat.h>
+#include <linux/fcntl.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/highmem.h>
+#include <linux/spinlock.h>
+#define __NO_VERSION__
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgalloc.h>
+#include <asm/mmu_context.h>
+
+#ifdef CONFIG_KMOD
+#include <linux/kmod.h>
+#endif
+
+
+extern void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long address);
+
+#undef STACK_TOP
+#define STACK_TOP TASK31_SIZE
+
+int setup_arg_pages32(struct linux_binprm *bprm)
+{
+	unsigned long stack_base;
+	struct vm_area_struct *mpnt;
+	int i;
+
+	stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;
+
+	bprm->p += stack_base;
+	if (bprm->loader)
+		bprm->loader += stack_base;
+	bprm->exec += stack_base;
+
+	mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+	if (!mpnt) 
+		return -ENOMEM; 
+	
+	down(&current->mm->mmap_sem);
+	{
+		mpnt->vm_mm = current->mm;
+		mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p;
+		mpnt->vm_end = STACK_TOP;
+		mpnt->vm_page_prot = PAGE_COPY;
+		mpnt->vm_flags = VM_STACK_FLAGS;
+		mpnt->vm_ops = NULL;
+		mpnt->vm_pgoff = 0;
+		mpnt->vm_file = NULL;
+		mpnt->vm_private_data = (void *) 0;
+		insert_vm_struct(current->mm, mpnt);
+		current->mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+	} 
+
+	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
+		struct page *page = bprm->page[i];
+		if (page) {
+			bprm->page[i] = NULL;
+			current->mm->rss++;
+			put_dirty_page(current,page,stack_base);
+		}
+		stack_base += PAGE_SIZE;
+	}
+	up(&current->mm->mmap_sem);
+	
+	return 0;
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/gdb-stub.c linux/arch/s390x/kernel/gdb-stub.c
--- v2.4.1/linux/arch/s390x/kernel/gdb-stub.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/gdb-stub.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,575 @@
+/*
+ *  arch/s390/kernel/gdb-stub.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ *  Originally written by Glenn Engel, Lake Stevens Instrument Division
+ *
+ *  Contributed by HP Systems
+ *
+ *  Modified for SPARC by Stu Grossman, Cygnus Support.
+ *
+ *  Modified for Linux/MIPS (and MIPS in general) by Andreas Busse
+ *  Send complaints, suggestions etc. to <andy@waldorf-gmbh.de>
+ *
+ *  Copyright (C) 1995 Andreas Busse
+ */
+
+/*
+ *  To enable debugger support, two things need to happen.  One, a
+ *  call to set_debug_traps() is necessary in order to allow any breakpoints
+ *  or error conditions to be properly intercepted and reported to gdb.
+ *  Two, a breakpoint needs to be generated to begin communication.  This
+ *  is most easily accomplished by a call to breakpoint().  Breakpoint()
+ *  simulates a breakpoint by executing a BREAK instruction.
+ *
+ *
+ *    The following gdb commands are supported:
+ *
+ * command          function                               Return value
+ *
+ *    g             return the value of the CPU registers  hex data or ENN
+ *    G             set the value of the CPU registers     OK or ENN
+ *
+ *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
+ *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
+ *
+ *    c             Resume at current address              SNN   ( signal NN)
+ *    cAA..AA       Continue at address AA..AA             SNN
+ *
+ *    s             Step one instruction                   SNN
+ *    sAA..AA       Step one instruction from AA..AA       SNN
+ *
+ *    k             kill
+ *
+ *    ?             What was the last sigval ?             SNN   (signal NN)
+ *
+ *
+ * All commands and responses are sent with a packet which includes a
+ * checksum.  A packet consists of
+ *
+ * $<packet info>#<checksum>.
+ *
+ * where
+ * <packet info> :: <characters representing the command or response>
+ * <checksum>    :: < two hex digits computed as modulo 256 sum of <packetinfo>>
+ *
+ * When a packet is received, it is first acknowledged with either '+' or '-'.
+ * '+' indicates a successful transfer.  '-' indicates a failed transfer.
+ *
+ * Example:
+ *
+ * Host:                  Reply:
+ * $m0,10#2a               +$00010203040506070809101112131415#42
+ *
+ */
+
+#include <asm/gdb-stub.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+
+
+/*
+ * external low-level support routines
+ */
+
+extern int putDebugChar(char c);    /* write a single character      */
+extern char getDebugChar(void);     /* read and return a single char */
+extern void fltr_set_mem_err(void);
+extern void trap_low(void);
+
+/*
+ * breakpoint and test functions
+ */
+extern void breakpoint(void);
+extern void breakinst(void);
+
+/*
+ * local prototypes
+ */
+
+static void getpacket(char *buffer);
+static void putpacket(char *buffer);
+static int hex(unsigned char ch);
+static int hexToInt(char **ptr, int *intValue);
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault);
+
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound buffers
+ * at least NUMREGBYTES*2 are needed for register packets
+ */
+#define BUFMAX 2048
+
+static char input_buffer[BUFMAX];
+static char output_buffer[BUFMAX];
+int gdb_stub_initialised = FALSE;	
+static const char hexchars[]="0123456789abcdef";
+
+
+/*
+ * Convert ch from a hex digit to an int
+ */
+static int hex(unsigned char ch)
+{
+	if (ch >= 'a' && ch <= 'f')
+		return ch-'a'+10;
+	if (ch >= '0' && ch <= '9')
+		return ch-'0';
+	if (ch >= 'A' && ch <= 'F')
+		return ch-'A'+10;
+	return -1;
+}
+
+/*
+ * scan for the sequence $<data>#<checksum>
+ */
+static void getpacket(char *buffer)
+{
+	unsigned char checksum;
+	unsigned char xmitcsum;
+	int i;
+	int count;
+	unsigned char ch;
+
+	do {
+		/*
+		 * wait around for the start character,
+		 * ignore all other characters
+		 */
+		while ((ch = (getDebugChar() & 0x7f)) != '$') ;
+
+		checksum = 0;
+		xmitcsum = -1;
+		count = 0;
+	
+		/*
+		 * now, read until a # or end of buffer is found
+		 */
+		while (count < BUFMAX) {
+			ch = getDebugChar() & 0x7f;
+			if (ch == '#')
+				break;
+			checksum = checksum + ch;
+			buffer[count] = ch;
+			count = count + 1;
+		}
+
+		if (count >= BUFMAX)
+			continue;
+
+		buffer[count] = 0;
+
+		if (ch == '#') {
+			xmitcsum = hex(getDebugChar() & 0x7f) << 4;
+			xmitcsum |= hex(getDebugChar() & 0x7f);
+
+			if (checksum != xmitcsum)
+				putDebugChar('-');	/* failed checksum */
+			else {
+				putDebugChar('+'); /* successful transfer */
+
+				/*
+				 * if a sequence char is present,
+				 * reply the sequence ID
+				 */
+				if (buffer[2] == ':') {
+					putDebugChar(buffer[0]);
+					putDebugChar(buffer[1]);
+
+					/*
+					 * remove sequence chars from buffer
+					 */
+					count = strlen(buffer);
+					for (i=3; i <= count; i++)
+						buffer[i-3] = buffer[i];
+				}
+			}
+		}
+	}
+	while (checksum != xmitcsum);
+}
+
+/*
+ * send the packet in buffer.
+ */
+static void putpacket(char *buffer)
+{
+	unsigned char checksum;
+	int count;
+	unsigned char ch;
+
+	/*
+	 * $<packet info>#<checksum>.
+	 */
+
+	do {
+		putDebugChar('$');
+		checksum = 0;
+		count = 0;
+
+		while ((ch = buffer[count]) != 0) {
+			if (!(putDebugChar(ch)))
+				return;
+			checksum += ch;
+			count += 1;
+		}
+
+		putDebugChar('#');
+		putDebugChar(hexchars[checksum >> 4]);
+		putDebugChar(hexchars[checksum & 0xf]);
+
+	}
+	while ((getDebugChar() & 0x7f) != '+');
+}
+
+
+
+/*
+ * Convert the memory pointed to by mem into hex, placing result in buf.
+ * Return a pointer to the last char put in buf (null), in case of mem fault,
+ * return 0.
+ * If MAY_FAULT is non-zero, then we will handle memory faults by returning
+ * a 0, else treat a fault like any other fault in the stub.
+ */
+static unsigned char *mem2hex(char *mem, char *buf, int count, int may_fault)
+{
+	unsigned char ch;
+
+/*	set_mem_fault_trap(may_fault); */
+
+	while (count-- > 0) {
+		ch = *(mem++);
+		if (mem_err)
+			return 0;
+		*buf++ = hexchars[ch >> 4];
+		*buf++ = hexchars[ch & 0xf];
+	}
+
+	*buf = 0;
+
+/*	set_mem_fault_trap(0); */
+
+	return buf;
+}
+
+/*
+ * convert the hex array pointed to by buf into binary to be placed in mem
+ * return a pointer to the character AFTER the last byte written
+ */
+static char *hex2mem(char *buf, char *mem, int count, int may_fault)
+{
+	int i;
+	unsigned char ch;
+
+/*	set_mem_fault_trap(may_fault); */
+
+	for (i=0; i<count; i++)
+	{
+		ch = hex(*buf++) << 4;
+		ch |= hex(*buf++);
+		*(mem++) = ch;
+		if (mem_err)
+			return 0;
+	}
+
+/*	set_mem_fault_trap(0); */
+
+	return mem;
+}
+
+
+
+/*
+ * Set up exception handlers for tracing and breakpoints
+ */
+void set_debug_traps(void)
+{
+//	unsigned long flags;
+	unsigned char c;
+
+//	save_and_cli(flags);
+	/*
+	 * In case GDB is started before us, ack any packets
+	 * (presumably "$?#xx") sitting there.
+	 */
+	while((c = getDebugChar()) != '$');
+	while((c = getDebugChar()) != '#');
+	c = getDebugChar(); /* eat first csum byte */
+	c = getDebugChar(); /* eat second csum byte */
+	putDebugChar('+'); /* ack it */
+
+	gdb_stub_initialised = TRUE;
+//	restore_flags(flags);
+}
+
+
+/*
+ * Trap handler for memory errors.  This just sets mem_err to be non-zero.  It
+ * assumes that %l1 is non-zero.  This should be safe, as it is doubtful that
+ * 0 would ever contain code that could mem fault.  This routine will skip
+ * past the faulting instruction after setting mem_err.
+ */
+extern void fltr_set_mem_err(void)
+{
+  /* FIXME: Needs to be written... */
+}
+
+
+/*
+ * While we find nice hex chars, build an int.
+ * Return number of chars processed.
+ */
+static int hexToInt(char **ptr, int *intValue)
+{
+	int numChars = 0;
+	int hexValue;
+
+	*intValue = 0;
+
+	while (**ptr)
+	{
+		hexValue = hex(**ptr);
+		if (hexValue < 0)
+			break;
+
+		*intValue = (*intValue << 4) | hexValue;
+		numChars ++;
+
+		(*ptr)++;
+	}
+
+	return (numChars);
+}
+
+void gdb_stub_get_non_pt_regs(gdb_pt_regs *regs)
+{
+	s390_fp_regs *fpregs=&regs->fp_regs;
+	int has_ieee=save_fp_regs1(fpregs);
+
+	if(!has_ieee)
+	{
+		fpregs->fpc=0;
+		fpregs->fprs[1].d=
+		fpregs->fprs[3].d=
+		fpregs->fprs[5].d=
+		fpregs->fprs[7].d=0;
+		memset(&fpregs->fprs[8].d,0,sizeof(freg_t)*8);
+	}
+}
+
+void gdb_stub_set_non_pt_regs(gdb_pt_regs *regs)
+{
+	restore_fp_regs1(&regs->fp_regs);
+}
+
+void gdb_stub_send_signal(int sigval)
+{
+	char *ptr;
+	ptr = output_buffer;
+
+	/*
+	 * Send trap type (converted to signal)
+	 */
+	*ptr++ = 'S';
+	*ptr++ = hexchars[sigval >> 4];
+	*ptr++ = hexchars[sigval & 0xf];
+	*ptr++ = 0;
+	putpacket(output_buffer);	/* send it off... */
+}
+
+/*
+ * This function does all command processing for interfacing to gdb.  It
+ * returns 1 if you should skip the instruction at the trap address, 0
+ * otherwise.
+ */
+void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval)
+{
+	int trap;			/* Trap type */
+	int addr;
+	int length;
+	char *ptr;
+	unsigned long *stack;
+
+	
+	/*
+	 * reply to host that an exception has occurred
+	 */
+	send_signal(sigval);
+
+	/*
+	 * Wait for input from remote GDB
+	 */
+	while (1) {
+		output_buffer[0] = 0;
+		getpacket(input_buffer);
+
+		switch (input_buffer[0])
+		{
+		case '?':
+			send_signal(sigval);
+			continue;
+
+		case 'd':
+			/* toggle debug flag */
+			break;
+
+		/*
+		 * Return the value of the CPU registers
+		 */
+		case 'g':
+			gdb_stub_get_non_pt_regs(regs);
+			ptr = output_buffer;
+			ptr=  mem2hex((char *)regs,ptr,sizeof(s390_regs_common),FALSE);
+			ptr=  mem2hex((char *)&regs->crs[0],ptr,NUM_CRS*CR_SIZE,FALSE);
+			ptr = mem2hex((char *)&regs->fp_regs, ptr,sizeof(s390_fp_regs));
+			break;
+	  
+		/*
+		 * set the value of the CPU registers - return OK
+		 * FIXME: Needs to be written
+		 */
+		case 'G':
+			ptr=input_buffer;
+			hex2mem (ptr, (char *)regs,sizeof(s390_regs_common), FALSE);
+			ptr+=sizeof(s390_regs_common)*2;
+			hex2mem (ptr, (char *)regs->crs[0],NUM_CRS*CR_SIZE, FALSE);
+			ptr+=NUM_CRS*CR_SIZE*2;
+			hex2mem (ptr, (char *)regs->fp_regs,sizeof(s390_fp_regs), FALSE);
+			gdb_stub_set_non_pt_regs(regs);
+			strcpy(output_buffer,"OK");
+		break;
+
+		/*
+		 * mAA..AA,LLLL  Read LLLL bytes at address AA..AA
+		 */
+		case 'm':
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr)
+				&& *ptr++ == ','
+				&& hexToInt(&ptr, &length)) {
+				if (mem2hex((char *)addr, output_buffer, length, 1))
+					break;
+				strcpy (output_buffer, "E03");
+			} else
+				strcpy(output_buffer,"E01");
+			break;
+
+		/*
+		 * MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK
+		 */
+		case 'M': 
+			ptr = &input_buffer[1];
+
+			if (hexToInt(&ptr, &addr)
+				&& *ptr++ == ','
+				&& hexToInt(&ptr, &length)
+				&& *ptr++ == ':') {
+				if (hex2mem(ptr, (char *)addr, length, 1))
+					strcpy(output_buffer, "OK");
+				else
+					strcpy(output_buffer, "E03");
+			}
+			else
+				strcpy(output_buffer, "E02");
+			break;
+
+		/*
+		 * cAA..AA    Continue at address AA..AA(optional)
+		 */
+		case 'c':    
+			/* try to read optional parameter, pc unchanged if no parm */
+
+			ptr = &input_buffer[1];
+			if (hexToInt(&ptr, &addr))
+				regs->cp0_epc = addr;
+	  
+			/*
+			 * Need to flush the instruction cache here, as we may
+			 * have deposited a breakpoint, and the icache probably
+			 * has no way of knowing that a data ref to some location
+			 * may have changed something that is in the instruction
+			 * cache.
+			 * NB: We flush both caches, just to be sure...
+			 */
+
+			flush_cache_all();
+			return;
+			/* NOTREACHED */
+			break;
+
+
+		/*
+		 * kill the program
+		 */
+		case 'k' :
+			break;		/* do nothing */
+
+
+		/*
+		 * Reset the whole machine (FIXME: system dependent)
+		 */
+		case 'r':
+			break;
+
+
+		/*
+		 * Step to next instruction
+		 */
+		case 's':
+			/*
+			 * There is no single step insn in the MIPS ISA, so we
+			 * use breakpoints and continue, instead.
+			 */
+			single_step(regs);
+			flush_cache_all();
+			return;
+			/* NOTREACHED */
+
+		}
+		break;
+
+		}			/* switch */
+
+		/*
+		 * reply to the request
+		 */
+
+		putpacket(output_buffer);
+
+	} /* while */
+}
+
+/*
+ * This function will generate a breakpoint exception.  It is used at the
+ * beginning of a program to sync up with a debugger and can be used
+ * otherwise as a quick means to stop program execution and "break" into
+ * the debugger.
+ */
+void breakpoint(void)
+{
+	if (!gdb_stub_initialised)
+		return;
+	__asm__ __volatile__(
+			".globl	breakinst\n"
+			"breakinst:\t.word   %0\n\t"
+			:
+			: "i" (S390_BREAKPOINT_U16)
+				:
+				);
+}
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/head.S linux/arch/s390x/kernel/head.S
--- v2.4.1/linux/arch/s390x/kernel/head.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/head.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,598 @@
+/*
+ *  arch/s390/kernel/head.S
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Rob van der Heij (rvdhei@iae.nl)
+ *
+ * There are 5 different IPL methods
+ *  1) load the image directly into ram at address 0 and do an PSW restart
+ *  2) linload will load the image from address 0x10000 to memory 0x10000
+ *     and start the code thru LPSW 0x0008000080010000 (VM only, deprecated)
+ *  3) generate the tape ipl header, store the generated image on a tape
+ *     and ipl from it
+ *     In case of SL tape you need to IPL 5 times to get past VOL1 etc
+ *  4) generate the vm reader ipl header, move the generated image to the
+ *     VM reader (use option NOH!) and do a ipl from reader (VM only)
+ *  5) direct call of start by the SALIPL loader
+ *  We use the cpuid to distinguish between VM and native ipl
+ *  params for kernel are pushed to 0x10400 (see setup.h)
+
+    Changes: 
+    Okt 25 2000 <rvdheij@iae.nl>
+	added code to skip HDR and EOF to allow SL tape IPL (5 retries)
+	changed first CCW from rewind to backspace block
+
+ */
+
+#include <linux/config.h>
+#include <asm/setup.h>
+#include <asm/lowcore.h>
+
+#ifndef CONFIG_IPL
+        .org   0
+        .long  0x00080000,0x80000000+startup   # Just a restart PSW
+#else
+#ifdef CONFIG_IPL_TAPE
+#define IPL_BS 1024
+        .org   0
+        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
+        .long  0x27000000,0x60000001           # by ipl to addresses 0-23.
+        .long  0x02000000,0x20000000+IPL_BS    # (a PSW and two CCWs).
+        .long  0x00000000,0x00000000           # external old psw
+        .long  0x00000000,0x00000000           # svc old psw
+        .long  0x00000000,0x00000000           # program check old psw
+        .long  0x00000000,0x00000000           # machine check old psw
+        .long  0x00000000,0x00000000           # io old psw
+        .long  0x00000000,0x00000000
+        .long  0x00000000,0x00000000
+        .long  0x00000000,0x00000000
+        .long  0x000a0000,0x00000058           # external new psw
+        .long  0x000a0000,0x00000060           # svc new psw
+        .long  0x000a0000,0x00000068           # program check new psw
+        .long  0x000a0000,0x00000070           # machine check new psw
+        .long  0x00080000,0x80000000+.Lioint   # io new psw
+
+        .org   0x100
+#
+# subroutine for loading from tape
+# Paramters:	
+#  R1 = device number
+#  R2 = load address
+.Lloader:	
+        st    %r14,.Lldret
+        la    %r3,.Lorbread                    # r3 = address of orb 
+	la    %r5,.Lirb                        # r5 = address of irb
+        st    %r2,.Lccwread+4                  # initialize CCW data addresses
+        lctl  %c6,%c6,.Lcr6               
+        slr   %r2,%r2
+.Lldlp:
+        la    %r6,3                            # 3 retries
+.Lssch:
+        ssch  0(%r3)                           # load chunk of IPL_BS bytes
+        bnz   .Llderr
+.Lw4end:
+        bas   %r14,.Lwait4io
+        tm    8(%r5),0x82                      # do we have a problem ?
+        bnz   .Lrecov
+        slr   %r7,%r7
+        icm   %r7,3,10(%r5)                    # get residual count
+        lcr   %r7,%r7
+        la    %r7,IPL_BS(%r7)                  # IPL_BS-residual=#bytes read
+        ar    %r2,%r7                          # add to total size
+        tm    8(%r5),0x01                      # found a tape mark ?
+        bnz   .Ldone
+        l     %r0,.Lccwread+4                  # update CCW data addresses
+        ar    %r0,%r7
+        st    %r0,.Lccwread+4                
+        b     .Lldlp
+.Ldone:
+        l     %r14,.Lldret
+        br    %r14                             # r2 contains the total size
+.Lrecov:
+        bas   %r14,.Lsense                     # do the sensing
+        bct   %r6,.Lssch                       # dec. retry count & branch
+        b     .Llderr
+#
+# Sense subroutine
+#
+.Lsense:
+        st    %r14,.Lsnsret
+        la    %r7,.Lorbsense              
+        ssch  0(%r7)                           # start sense command
+        bnz   .Llderr
+        bas   %r14,.Lwait4io
+        l     %r14,.Lsnsret
+        tm    8(%r5),0x82                      # do we have a problem ?
+        bnz   .Llderr
+        br    %r14
+#
+# Wait for interrupt subroutine
+#
+.Lwait4io:
+        lpsw  .Lwaitpsw                 
+.Lioint:
+        c     %r1,0xb8                         # compare subchannel number
+        bne   .Lwait4io
+        tsch  0(%r5)
+        slr   %r0,%r0
+        tm    8(%r5),0x82                      # do we have a problem ?
+        bnz   .Lwtexit
+        tm    8(%r5),0x04                      # got device end ?
+        bz    .Lwait4io
+.Lwtexit:
+        br    %r14
+.Llderr:
+        lpsw  .Lcrash              
+
+        .align 8
+.Lorbread:
+	.long  0x00000000,0x0080ff00,.Lccwread
+        .align 8
+.Lorbsense:
+        .long  0x00000000,0x0080ff00,.Lccwsense
+        .align 8
+.Lccwread:
+        .long  0x02200000+IPL_BS,0x00000000
+.Lccwsense:
+        .long  0x04200001,0x00000000
+.Lwaitpsw:
+	.long  0x020a0000,0x80000000+.Lioint
+
+.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6:  .long  0xff000000
+        .align 8
+.Lcrash:.long  0x000a0000,0x00000000
+.Lldret:.long  0
+.Lsnsret: .long 0
+#endif  /* CONFIG_IPL_TAPE */
+
+#ifdef CONFIG_IPL_VM
+#define IPL_BS 0x730
+        .org   0
+        .long  0x00080000,0x80000000+iplstart  # The first 24 bytes are loaded
+        .long  0x02000018,0x60000050           # by ipl to addresses 0-23.
+        .long  0x02000068,0x60000050           # (a PSW and two CCWs).
+        .fill  80-24,1,0x40                    # bytes 24-79 are discarded !!
+        .long  0x020000f0,0x60000050           # The next 160 byte are loaded
+        .long  0x02000140,0x60000050           # to addresses 0x18-0xb7
+        .long  0x02000190,0x60000050           # They form the continuation
+        .long  0x020001e0,0x60000050           # of the CCW program started
+        .long  0x02000230,0x60000050           # by ipl and load the range
+        .long  0x02000280,0x60000050           # 0x0f0-0x730 from the image
+        .long  0x020002d0,0x60000050           # to the range 0x0f0-0x730
+        .long  0x02000320,0x60000050           # in memory. At the end of
+        .long  0x02000370,0x60000050           # the channel program the PSW
+        .long  0x020003c0,0x60000050           # at location 0 is loaded.
+        .long  0x02000410,0x60000050           # Initial processing starts
+        .long  0x02000460,0x60000050           # at 0xf0 = iplstart.
+        .long  0x020004b0,0x60000050
+        .long  0x02000500,0x60000050
+        .long  0x02000550,0x60000050
+        .long  0x020005a0,0x60000050
+        .long  0x020005f0,0x60000050
+        .long  0x02000640,0x60000050
+        .long  0x02000690,0x60000050
+        .long  0x020006e0,0x20000050
+
+        .org   0xf0
+#
+# subroutine for loading cards from the reader
+#
+.Lloader:	
+	la    %r3,.Lorb                        # r2 = address of orb into r2
+	la    %r5,.Lirb                        # r4 = address of irb
+        la    %r6,.Lccws              
+        la    %r7,20
+.Linit:
+        st    %r2,4(%r6)                       # initialize CCW data addresses
+        la    %r2,0x50(%r2)
+        la    %r6,8(%r6)
+        bct   7,.Linit
+
+        lctl  %c6,%c6,.Lcr6                    # set IO subclass mask
+	slr   %r2,%r2
+.Lldlp:
+        ssch  0(%r3)                           # load chunk of 1600 bytes
+        bnz   .Llderr
+.Lwait4irq:
+        mvc   0x78(8),.Lnewpsw                 # set up IO interrupt psw
+        lpsw  .Lwaitpsw              
+.Lioint:
+        c     %r1,0xb8                         # compare subchannel number
+	bne   .Lwait4irq
+	tsch  0(%r5)
+
+	slr   %r0,%r0
+	ic    %r0,8(%r5)                       # get device status
+	chi   %r0,8                            # channel end ?
+	be    .Lcont
+	chi   %r0,12                           # channel end + device end ?
+	be    .Lcont
+
+        l     %r0,4(%r5)
+        s     %r0,8(%r3)                       # r0/8 = number of ccws executed
+        mhi   %r0,10                           # *10 = number of bytes in ccws
+        lh    %r3,10(%r5)                      # get residual count
+        sr    %r0,%r3                          # #ccws*80-residual=#bytes read
+	ar    %r2,%r0
+	
+        br    %r14                             # r2 contains the total size
+
+.Lcont:
+	ahi   %r2,0x640                        # add 0x640 to total size
+        la    %r6,.Lccws             
+        la    %r7,20
+.Lincr:
+        l     %r0,4(%r6)                       # update CCW data addresses
+        ahi   %r0,0x640
+        st    %r0,4(%r6)
+        ahi   %r6,8
+        bct   7,.Lincr
+
+        b     .Lldlp
+.Llderr:
+        lpsw  .Lcrash              
+
+        .align 8
+.Lorb:	.long  0x00000000,0x0080ff00,.Lccws
+.Lirb:	.long  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lcr6:  .long  0xff000000
+.Lloadp:.long  0,0
+        .align 8
+.Lcrash:.long  0x000a0000,0x00000000
+.Lnewpsw:
+        .long  0x00080000,0x80000000+.Lioint
+.Lwaitpsw:
+        .long  0x020a0000,0x80000000+.Lioint
+
+        .align 8
+.Lccws: .rept  19
+        .long  0x02600050,0x00000000
+        .endr
+        .long  0x02200050,0x00000000
+#endif  /* CONFIG_IPL_VM */
+
+iplstart:
+        lh    %r1,0xb8                         # test if subchannel number
+        bct   %r1,.Lnoload                     #  is valid
+	l     %r1,0xb8                         # load ipl subchannel number
+        la    %r2,IPL_BS                       # load start address
+        bas   %r14,.Lloader                    # load rest of ipl image
+        st    %r1,__LC_IPLDEV                  # store ipl device number
+        l     %r12,.Lparm                      # pointer to parameter area
+
+#
+# load parameter file from ipl device
+#
+.Lagain1:
+ 	l     %r2,INITRD_START+4-PARMAREA(%r12)# use ramdisk location as temp
+        bas   %r14,.Lloader                    # load parameter file
+        ltr   %r2,%r2                          # got anything ?
+        bz    .Lnopf
+	chi   %r2,895
+	bnh   .Lnotrunc
+	la    %r2,895
+.Lnotrunc:
+	l     %r4,INITRD_START+4-PARMAREA(%r12)
+ 	clc   0(3,%r4),.L_hdr		       # if it is HDRx
+ 	bz    .Lagain1			       # skip dataset header
+ 	clc   0(3,%r4),.L_eof		       # if it is EOFx
+ 	bz    .Lagain1			       # skip dateset trailer
+        la    %r5,0(%r4,%r2)
+        lr    %r3,%r2
+.Lidebc:
+        tm    0(%r5),0x80                      # high order bit set ?
+        bo    .Ldocv                           #  yes -> convert from EBCDIC
+        ahi   %r5,-1
+        bct   %r3,.Lidebc
+        b     .Lnocv
+.Ldocv:
+        l     %r3,.Lcvtab
+        tr    0(256,%r4),0(%r3)                # convert parameters to ascii
+        tr    256(256,%r4),0(%r3)
+        tr    512(256,%r4),0(%r3)
+        tr    768(122,%r4),0(%r3)
+.Lnocv: la    %r3,COMMAND_LINE-PARMAREA(%r12)  # load adr. of command line
+	mvc   0(256,%r3),0(%r4)
+	mvc   256(256,%r3),256(%r4)
+	mvc   512(256,%r3),512(%r4)
+	mvc   768(122,%r3),768(%r4)
+        slr   %r0,%r0
+        b     .Lcntlp
+.Ldelspc:
+        ic    %r0,0(%r3)
+        ic    %r0,0(%r2,%r3)
+        chi   %r0,0x20                         # is it a space ?
+        be    .Lcntlp
+        ahi   %r2,1
+        b     .Leolp
+.Lcntlp:
+        brct  %r2,.Ldelspc
+.Leolp:
+        slr   %r0,%r0
+        stc   %r0,0(%r2,%r3)                   # terminate buffer
+.Lnopf:
+
+#
+# load ramdisk from ipl device
+#
+.Lagain2:
+ 	l     %r2,INITRD_START+4-PARMAREA(%r12)# load adr. of ramdisk
+        bas   %r14,.Lloader                    # load ramdisk
+ 	st    %r2,INITRD_SIZE+4-PARMAREA(%r12) # store size of ramdisk
+        ltr   %r2,%r2
+        bnz   .Lrdcont
+        st    %r2,INITRD_START+4-PARMAREA(%r12)# no ramdisk found, null it
+.Lrdcont:
+	l     %r2,INITRD_START-PARMAREA(%r12)
+	clc   0(3,%r2),.L_hdr		       # skip HDRx and EOFx 
+	bz    .Lagain2
+	clc   0(3,%r2),.L_eof
+	bz    .Lagain2
+
+#ifdef CONFIG_IPL_VM
+#
+# reset files in VM reader
+#
+        stidp __LC_CPUID                       # store cpuid
+        lh    %r0,__LC_CPUID+4                 # get cpu version
+        chi   %r0,0x7490                       # running on P/390 ?
+        be    start                            #   no -> skip reset
+        la    %r2,.Lreset              
+        lhi   %r3,26
+        .long 0x83230008
+#endif
+	
+#
+# everything loaded, go for it
+#
+.Lnoload:
+        l     %r1,.Lstartup
+        br    %r1
+
+.Lparm:	.long  PARMAREA
+.Lstartup: .long startup
+.Lcvtab:.long  _ebcasc                         # ebcdic to ascii table
+.Lreset:.byte  0xc3,0xc8,0xc1,0xd5,0xc7,0xc5,0x40,0xd9,0xc4,0xd9,0x40
+        .byte  0xc1,0xd3,0xd3,0x40,0xd2,0xc5,0xc5,0xd7,0x40,0xd5,0xd6
+        .byte  0xc8,0xd6,0xd3,0xc4             # "change rdr all keep nohold"
+.L_eof: .long  0xc5d6c600       /* C'EOF' */
+.L_hdr: .long  0xc8c4d900       /* C'HDR' */
+#endif  /* CONFIG_IPL */
+
+#
+# SALIPL loader support. Based on a patch by Rob van der Heij.
+# This entry point is called directly from the SALIPL loader and
+# doesn't need a builtin ipl record.
+#
+        .org  0x800
+	.globl start
+start:
+	stm   %r0,%r15,0x07b0		# store registers
+	basr  %r12,%r0
+.base:
+	l     %r11,.parm
+	l     %r8,.cmd			# pointer to command buffer
+
+	ltr   %r9,%r9			# do we have SALIPL parameters?
+	bp    .sk8x8
+
+	mvc   0(64,%r8),0x00b0		# copy saved registers
+	xc    64(240-64,%r8),0(%r8)	# remainder of buffer
+	tr    0(64,%r8),.lowcase	
+	b     .gotr
+.sk8x8:
+	mvc   0(240,%r8),0(%r9)		# copy iplparms into buffer
+.gotr:
+	l     %r10,.tbl			# EBCDIC to ASCII table
+	tr    0(240,%r8),0(%r10)
+	stidp __LC_CPUID		# Are we running on VM maybe
+	cli   __LC_CPUID,0xff
+	bnz   .test
+	.long 0x83300060		# diag 3,0,x'0060' - storage size
+	b     .done
+.test:
+	mvc   0x68(8),.pgmnw		# set up pgm check handler
+	l     %r2,.fourmeg
+	lr    %r3,%r2
+	bctr  %r3,%r0			# 4M-1
+.loop:  iske  %r0,%r3
+	ar    %r3,%r2
+.pgmx:
+	sr    %r3,%r2
+	la    %r3,1(%r3)
+.done:
+	st    %r3,MEMORY_SIZE-PARMAREA(%r11)	
+	slr   %r0,%r0
+	st    %r0,INITRD_SIZE-PARMAREA(%r11)
+	st    %r0,INITRD_START-PARMAREA(%r11)
+	j     startup                   # continue with startup
+.tbl:	.long _ebcasc			# translate table
+.cmd:	.long COMMAND_LINE		# address of command line buffer
+.parm:	.long PARMAREA
+.fourmeg: .long 0x00400000      	# 4M
+.pgmnw:	.long 0x00080000,.pgmx
+.lowcase:
+	.byte 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07 
+	.byte 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f
+	.byte 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17 
+	.byte 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f
+	.byte 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27 
+	.byte 0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
+	.byte 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37 
+	.byte 0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
+	.byte 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47 
+	.byte 0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
+	.byte 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57 
+	.byte 0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f
+	.byte 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67 
+	.byte 0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
+	.byte 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77 
+	.byte 0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f
+
+	.byte 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87 
+	.byte 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
+	.byte 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97 
+	.byte 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f
+	.byte 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7 
+	.byte 0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
+	.byte 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7 
+	.byte 0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf
+	.byte 0xc0,0x81,0x82,0x83,0x84,0x85,0x86,0x87	# .abcdefg 
+	.byte 0x88,0x89,0xca,0xcb,0xcc,0xcd,0xce,0xcf	# hi
+	.byte 0xd0,0x91,0x92,0x93,0x94,0x95,0x96,0x97 	# .jklmnop
+	.byte 0x98,0x99,0xda,0xdb,0xdc,0xdd,0xde,0xdf	# qr
+	.byte 0xe0,0xe1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7	# ..stuvwx
+	.byte 0xa8,0xa9,0xea,0xeb,0xec,0xed,0xee,0xef	# yz
+	.byte 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7 
+	.byte 0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
+
+#
+# startup-code at 0x10000, running in real mode
+# this is called either by the ipl loader or directly by PSW restart
+# or linload or SALIPL
+#
+        .org  0x10000
+startup:basr  %r13,0                     # get base
+.LPG1:  n     %r13,.Lhighoff-.LPG1(%r13) # remove high order bit
+        lhi   %r1,1                      # mode 1 = esame
+        slr   %r0,%r0                    # set cpuid to zero
+        sigp  %r1,%r0,0x12               # switch to esame mode
+	sam64				 # switch to 64 bit mode
+	lctlg %c0,%c15,.Lctl-.LPG1(%r13) # load control registers
+	lg    %r12,.Lparm1-.LPG1(%r13)   # pointer to parameter area
+
+#
+# find out memory size.
+#
+	mvc   0x1d0(16),.Lpcmem-.LPG1(%r13) # setup program check handler
+        lghi  %r2,1
+        sllg  %r2,%r2,17                 # test in increments of 128KB
+	lgr   %r1,%r2
+	aghi  %r1,-8                     # test last word in the segment
+.Lloop:	
+	lg    %r0,0(%r1)                 # test 128KB segment
+	stg   %r0,0(%r1)
+	agr   %r1,%r2                    # add 128KB
+	bno   .Lloop-.LPG1(%r13)         # r1 < 0x80000000 -> loop
+.Lchkmem:
+	ng    %r1,.L4malign-.LPG1(%r13)  # align to multiples of 4M
+	stg   %r1,MEMORY_SIZE-PARMAREA(%r12)  # store memory size
+#
+# find out if we are running under VM
+#
+        stidp  __LC_CPUID               # store cpuid
+	tm     __LC_CPUID,0xff          # running under VM ?
+	bno    .Lnovm-.LPG1(%r13)
+        oi     MACHINE_FLAGS+7-PARMAREA(%r12),1    # set VM flag
+.Lnovm:
+        lh     %r0,__LC_CPUID+4         # get cpu version
+        chi    %r0,0x7490               # running on a P/390 ?
+        bne    .Lnop390-.LPG1(%r13)
+        oi     MACHINE_FLAGS+7-PARMAREA(%r12),4    # set P/390 flag
+.Lnop390:
+
+        lpswe .Lentry-.LPG1(13)         # jump to _stext in primary-space,
+                                        # virtual and never return ...
+        .align 16
+.Lentry:.quad  0x0000000180000000,_stext
+.Lctl:  .quad  0x04b50002               # cr0: various things
+        .quad  0                        # cr1: primary space segment table
+        .quad  0                        # cr2: access register translation
+        .quad  0                        # cr3: instruction authorization
+        .quad  0                        # cr4: instruction authorization
+        .quad  0                        # cr5:  various things
+        .quad  0                        # cr6:  I/O interrupts
+        .quad  0                        # cr7:  secondary space segment table
+        .quad  0                        # cr8:  access registers translation
+        .quad  0                        # cr9:  tracing off
+        .quad  0                        # cr10: tracing off
+        .quad  0                        # cr11: tracing off
+        .quad  0                        # cr12: tracing off
+        .quad  0                        # cr13: home space segment table
+        .quad  0xc0000000               # cr14: machine check handling off
+        .quad  0                        # cr15: linkage stack operations
+.Lpcmem:.quad  0x0000000180000000,.Lchkmem
+.Lflt0: .double 0
+.Lparm1:.quad  PARMAREA
+.Lhighoff:.long 0x7fffffff
+.L4malign:.quad 0xffffffffffc00000
+.Lbigmem:.quad 0x04000000
+.Lmaxchunk:.quad  0x00ffffff
+
+#
+# params at 10400 (setup.h)
+#
+	.org   PARMAREA
+        .quad  0x0100                   # ORIG_ROOT_DEV: ramdisk major/minor
+        .word  0                        # MOUNT_ROOT_RDONLY: no
+	.quad  0                        # MEMORY_SIZE
+	.quad  0                        # MACHINE_FLAGS (bit 0:VM)
+        .quad  RAMDISK_ORIGIN           # INITRD_START
+        .quad  RAMDISK_SIZE             # INITRD_SIZE
+	.word  0                        # RAMDISK_FLAGS
+
+        .org   COMMAND_LINE
+    	.byte  "root=/dev/ram0 ro"
+        .byte  0
+
+#
+# startup-code, running in virtual mode
+#
+        .org   0x10800
+        .globl _stext
+_stext:	basr  %r13,0                    # get base
+.LPG2:
+#
+# Setup lowcore
+#
+        l     %r1,__LC_IPLDEV           # load ipl device number
+        spx   .Lprefix-.LPG2(%r13)      # set prefix to linux lowcore
+        st    %r1,__LC_IPLDEV           # store ipl device number
+        lg    %r15,.Linittu-.LPG2(%r13)
+        aghi  %r15,16384                # init_task_union + 16384
+        stg   %r15,__LC_KERNEL_STACK    # set end of kernel stack
+        aghi  %r15,-160
+        xc    0(8,%r15),0(%r15)         # set backchain to zero
+        lghi  %r0,-1
+        stg   %r0,__LC_KERNEL_LEVEL     # set interrupt count to -1
+#
+# clear bss memory
+#
+        lg    %r2,.Lbss_bgn-.LPG2(%r13) # start of bss
+        lg    %r3,.Lbss_end-.LPG2(%r13) # end of bss
+        sgr   %r3,%r2                   # length of bss
+        sgr   %r4,%r4                   #
+        sgr   %r5,%r5                   # set src,length and pad to zero
+        mvcle %r2,%r4,0                 # clear mem
+        jo    .-4                       # branch back, if not finish
+# check control registers
+        stctg  %c0,%c15,0(%r15)
+        oc     6(1,%r15),.Locbits+5-.LPG2(%r13) # enable sigp external ints.
+        oc     4(1,%r15),.Locbits+4-.LPG2(%r13) # low addresss proctection
+        lctlg  %c0,%c15,0(%r15)
+
+#
+        lam    0,15,.Laregs-.LPG2(%r13) # load access regs needed by uaccess
+        brasl  %r14,start_kernel        # go to C code
+#
+# We returned from start_kernel ?!? PANIK
+#
+        basr  %r13,0
+	lpswe .Ldw-.(%r13)           # load disabled wait psw
+#
+.Lstart:    .quad  start_kernel
+            .align 8
+.Lprefix:   .long  init_S390_lowcore	
+.Linittu:   .quad  init_task_union
+.Lbss_bgn:  .quad  __bss_start
+.Lbss_end:  .quad  _end
+.Locbits:   .quad  0x0102040810204080
+            .align 4
+.Laregs:    .long  0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0
+	    .align 8
+.Ldw:      .quad  0x0002000180000000,0x0000000000000000
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/ieee.h linux/arch/s390x/kernel/ieee.h
--- v2.4.1/linux/arch/s390x/kernel/ieee.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/ieee.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,90 @@
+/*
+ *  arch/s390/kernel/ieee.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#include <linux/sched.h>
+
+static    inline void _adddf(int R1,int R2)
+{
+  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd +
+                             current->tss.fprs[R2].fd;
+}
+
+static    inline void _subdf(int R1,int R2)
+{
+  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd -
+                             current->tss.fprs[R2].fd;
+}
+
+static    inline void _muldf(int R1,int R2)
+{
+  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd *
+                             current->tss.fprs[R2].fd;
+}
+
+static    inline void _divdf(int R1,int R2)
+{
+  current->tss.fprs[R1].fd = current->tss.fprs[R1].fd /
+                             current->tss.fprs[R2].fd;
+}
+
+static    inline void _negdf(int R1,int R2)
+{
+  current->tss.fprs[R1].fd = -current->tss.fprs[R1].fd;
+}
+
+static    inline void _fixdfsi(int R1,int R2)
+{
+  current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].fd;
+}
+
+static    inline void _extendsidf(int R1,int R2)
+{
+  current->tss.fprs[R1].fd = (double) current->tss.regs->gprs[R2];
+}
+
+
+static    inline  void _addsf(int R1,int R2)
+{
+  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff +
+                             current->tss.fprs[R2].ff;
+}
+
+static    inline  void _subsf(int R1,int R2)
+{
+  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff -
+                             current->tss.fprs[R2].ff;
+}
+
+static    inline void _mulsf(int R1,int R2)
+{
+  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff *
+                             current->tss.fprs[R2].ff;
+}
+
+static    inline void _divsf(int R1,int R2)
+{
+  current->tss.fprs[R1].ff = current->tss.fprs[R1].ff /
+                             current->tss.fprs[R2].ff;
+}
+
+static    inline void _negsf(int R1,int R2)
+{
+  current->tss.fprs[R1].ff = -current->tss.fprs[R1].ff;
+}
+
+static    inline void _fixsfsi(int R1,int R2)
+{
+  current->tss.regs->gprs[R1] = (__u32) current->tss.fprs[R2].ff;
+}
+
+static    inline void _extendsisf(int R1,int R2)
+{
+  current->tss.fprs[R1].ff = (double) current->tss.regs->gprs[R2];
+}
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/init_task.c linux/arch/s390x/kernel/init_task.c
--- v2.4.1/linux/arch/s390x/kernel/init_task.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/init_task.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,32 @@
+/*
+ *  arch/s390/kernel/init_task.c
+ *
+ *  S390 version
+ *
+ *  Derived from "arch/i386/kernel/init_task.c"
+ */
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct vm_area_struct init_mmap = INIT_MMAP;
+static struct fs_struct init_fs = INIT_FS;
+static struct files_struct init_files = INIT_FILES;
+static struct signal_struct init_signals = INIT_SIGNALS;
+struct mm_struct init_mm = INIT_MM(init_mm);
+
+/*
+ * Initial task structure.
+ *
+ * We need to make sure that this is 16384-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ *
+ * The things we do for performance..
+ */
+union task_union init_task_union __attribute__((aligned(16384))) = 
+  { INIT_TASK(init_task_union.task) };
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/ioctl32.c linux/arch/s390x/kernel/ioctl32.c
--- v2.4.1/linux/arch/s390x/kernel/ioctl32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/ioctl32.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,563 @@
+/*
+ * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Gerhard Tonn (ton@de.ibm.com)
+ *
+ * Heavily inspired by the 32-bit Sparc compat code which is  
+ * Copyright (C) 2000 Silicon Graphics, Inc.
+ * Written by Ulf Carlsson (ulfc@engr.sgi.com) 
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/file.h>
+#include <linux/vt.h>
+#include <linux/kd.h>
+#include <linux/netdevice.h>
+#include <linux/route.h>
+#include <linux/ext2_fs.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <asm/dasd.h>
+
+#include "linux32.h"
+
+long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+struct hd_geometry32 {
+	unsigned char	heads;
+	unsigned char	sectors;
+	unsigned short	cylinders;
+	__u32		start;
+};  
+
+static inline int hd_geometry_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct hd_geometry32 *hg32 = (struct hd_geometry32 *) A(arg);
+	struct hd_geometry hg;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, cmd, (long)&hg);
+	set_fs (old_fs);
+
+	if (ret)
+		return ret;
+
+	ret = put_user (hg.heads, &(hg32->heads));
+	ret |= __put_user (hg.sectors, &(hg32->sectors));
+	ret |= __put_user (hg.cylinders, &(hg32->cylinders));
+	ret |= __put_user (hg.start, &(hg32->start));
+
+	return ret;
+}
+
+struct timeval32 {
+	int tv_sec;
+	int tv_usec;
+};
+
+#define EXT2_IOC32_GETFLAGS               _IOR('f', 1, int)
+#define EXT2_IOC32_SETFLAGS               _IOW('f', 2, int)
+#define EXT2_IOC32_GETVERSION             _IOR('v', 1, int)
+#define EXT2_IOC32_SETVERSION             _IOW('v', 2, int)
+
+struct ifmap32 {
+	unsigned int mem_start;
+	unsigned int mem_end;
+	unsigned short base_addr;
+	unsigned char irq;
+	unsigned char dma;
+	unsigned char port;
+};
+
+struct ifreq32 {
+#define IFHWADDRLEN     6
+#define IFNAMSIZ        16
+        union {
+                char    ifrn_name[IFNAMSIZ];	/* if name, e.g. "en0" */
+        } ifr_ifrn;
+        union {
+                struct  sockaddr ifru_addr;
+                struct  sockaddr ifru_dstaddr;
+                struct  sockaddr ifru_broadaddr;
+                struct  sockaddr ifru_netmask;
+                struct  sockaddr ifru_hwaddr;
+                short   ifru_flags;
+                int     ifru_ivalue;
+                int     ifru_mtu;
+                struct  ifmap32 ifru_map;
+                char    ifru_slave[IFNAMSIZ];   /* Just fits the size */
+		char	ifru_newname[IFNAMSIZ];
+                __u32	ifru_data;
+        } ifr_ifru;
+};
+
+struct ifconf32 {
+        int     ifc_len;                        /* size of buffer       */
+        __u32	ifcbuf;
+};
+
+static int dev_ifname32(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct ireq32 *uir32 = (struct ireq32 *) A(arg);
+	struct net_device *dev;
+	struct ifreq32 ifr32;
+
+	if (copy_from_user(&ifr32, uir32, sizeof(struct ifreq32)))
+		return -EFAULT;
+
+	read_lock(&dev_base_lock);
+	dev = __dev_get_by_index(ifr32.ifr_ifindex);
+	if (!dev) {
+		read_unlock(&dev_base_lock);
+		return -ENODEV;
+	}
+
+	strcpy(ifr32.ifr_name, dev->name);
+	read_unlock(&dev_base_lock);
+
+	if (copy_to_user(uir32, &ifr32, sizeof(struct ifreq32)))
+	    return -EFAULT;
+
+	return 0;
+}
+
+static inline int dev_ifconf(unsigned int fd, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct ioconf32 *uifc32 = (struct ioconf32 *) A(arg);
+	struct ifconf32 ifc32;
+	struct ifconf ifc;
+	struct ifreq32 *ifr32;
+	struct ifreq *ifr;
+	mm_segment_t old_fs;
+	int len;
+	int err;
+
+	if (copy_from_user(&ifc32, uifc32, sizeof(struct ifconf32)))
+		return -EFAULT;
+
+	if(ifc32.ifcbuf == 0) {
+		ifc32.ifc_len = 0;
+		ifc.ifc_len = 0;
+		ifc.ifc_buf = NULL;
+	} else {
+		ifc.ifc_len = ((ifc32.ifc_len / sizeof (struct ifreq32))) *
+			sizeof (struct ifreq);
+		ifc.ifc_buf = kmalloc (ifc.ifc_len, GFP_KERNEL);
+		if (!ifc.ifc_buf)
+			return -ENOMEM;
+	}
+	ifr = ifc.ifc_req;
+	ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
+	len = ifc32.ifc_len / sizeof (struct ifreq32);
+	while (len--) {
+		if (copy_from_user(ifr++, ifr32++, sizeof (struct ifreq32))) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, SIOCGIFCONF, (unsigned long)&ifc);	
+	set_fs (old_fs);
+	if (err)
+		goto out;
+
+	ifr = ifc.ifc_req;
+	ifr32 = (struct ifreq32 *) A(ifc32.ifcbuf);
+	len = ifc.ifc_len / sizeof (struct ifreq);
+	ifc32.ifc_len = len * sizeof (struct ifreq32);
+
+	while (len--) {
+		if (copy_to_user(ifr32++, ifr++, sizeof (struct ifreq32))) {
+			err = -EFAULT;
+			goto out;
+		}
+	}
+
+	if (copy_to_user(uifc32, &ifc32, sizeof(struct ifconf32))) {
+		err = -EFAULT;
+		goto out;
+	}
+out:
+	if(ifc.ifc_buf != NULL)
+		kfree (ifc.ifc_buf);
+	return err;
+}
+
+static inline int dev_ifsioc(unsigned int fd, unsigned int cmd,
+			     unsigned long arg)
+{
+	struct ifreq32 *uifr = (struct ifreq32 *) A(arg);
+	struct ifreq ifr;
+	mm_segment_t old_fs;
+	int err;
+	
+	switch (cmd) {
+	case SIOCSIFMAP:
+		err = copy_from_user(&ifr, uifr, sizeof(ifr.ifr_name));
+		err |= __get_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
+		err |= __get_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
+		err |= __get_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
+		err |= __get_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
+		err |= __get_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
+		err |= __get_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
+		if (err)
+			return -EFAULT;
+		break;
+	default:
+		if (copy_from_user(&ifr, uifr, sizeof(struct ifreq32)))
+			return -EFAULT;
+		break;
+	}
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	err = sys_ioctl (fd, cmd, (unsigned long)&ifr);
+	set_fs (old_fs);
+	if (!err) {
+		switch (cmd) {
+		case SIOCGIFFLAGS:
+		case SIOCGIFMETRIC:
+		case SIOCGIFMTU:
+		case SIOCGIFMEM:
+		case SIOCGIFHWADDR:
+		case SIOCGIFINDEX:
+		case SIOCGIFADDR:
+		case SIOCGIFBRDADDR:
+		case SIOCGIFDSTADDR:
+		case SIOCGIFNETMASK:
+		case SIOCGIFTXQLEN:
+			if (copy_to_user(uifr, &ifr, sizeof(struct ifreq32)))
+				return -EFAULT;
+			break;
+		case SIOCGIFMAP:
+			err = copy_to_user(uifr, &ifr, sizeof(ifr.ifr_name));
+			err |= __put_user(ifr.ifr_map.mem_start, &(uifr->ifr_ifru.ifru_map.mem_start));
+			err |= __put_user(ifr.ifr_map.mem_end, &(uifr->ifr_ifru.ifru_map.mem_end));
+			err |= __put_user(ifr.ifr_map.base_addr, &(uifr->ifr_ifru.ifru_map.base_addr));
+			err |= __put_user(ifr.ifr_map.irq, &(uifr->ifr_ifru.ifru_map.irq));
+			err |= __put_user(ifr.ifr_map.dma, &(uifr->ifr_ifru.ifru_map.dma));
+			err |= __put_user(ifr.ifr_map.port, &(uifr->ifr_ifru.ifru_map.port));
+			if (err)
+				err = -EFAULT;
+			break;
+		}
+	}
+	return err;
+}
+
+struct rtentry32
+{
+	unsigned int	rt_pad1;
+	struct sockaddr	rt_dst;		/* target address		*/
+	struct sockaddr	rt_gateway;	/* gateway addr (RTF_GATEWAY)	*/
+	struct sockaddr	rt_genmask;	/* target network mask (IP)	*/
+	unsigned short	rt_flags;
+	short		rt_pad2;
+	unsigned int	rt_pad3;
+	unsigned int	rt_pad4;
+	short		rt_metric;	/* +1 for binary compatibility!	*/
+	unsigned int	rt_dev;		/* forcing the device at add	*/
+	unsigned int	rt_mtu;		/* per route MTU/Window 	*/
+#ifndef __KERNEL__
+#define rt_mss	rt_mtu			/* Compatibility :-(            */
+#endif
+	unsigned int	rt_window;	/* Window clamping 		*/
+	unsigned short	rt_irtt;	/* Initial RTT			*/
+};
+
+static inline int routing_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	struct rtentry32 *ur = (struct rtentry32 *) A(arg);
+	struct rtentry r;
+	char devname[16];
+	u32 rtdev;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	ret = copy_from_user (&r.rt_dst, &(ur->rt_dst), 3 * sizeof(struct sockaddr));
+	ret |= __get_user (r.rt_flags, &(ur->rt_flags));
+	ret |= __get_user (r.rt_metric, &(ur->rt_metric));
+	ret |= __get_user (r.rt_mtu, &(ur->rt_mtu));
+	ret |= __get_user (r.rt_window, &(ur->rt_window));
+	ret |= __get_user (r.rt_irtt, &(ur->rt_irtt));
+	ret |= __get_user (rtdev, &(ur->rt_dev));
+	if (rtdev) {
+		ret |= copy_from_user (devname, (char *) A(rtdev), 15);
+		r.rt_dev = devname; devname[15] = 0;
+	} else
+		r.rt_dev = 0;
+	if (ret)
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_ioctl (fd, cmd, (long)&r);
+	set_fs (old_fs);
+	return ret;
+}
+
+static int do_ext2_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	/* These are just misnamed, they actually get/put from/to user an int */
+	switch (cmd) {
+	case EXT2_IOC32_GETFLAGS: cmd = EXT2_IOC_GETFLAGS; break;
+	case EXT2_IOC32_SETFLAGS: cmd = EXT2_IOC_SETFLAGS; break;
+	case EXT2_IOC32_GETVERSION: cmd = EXT2_IOC_GETVERSION; break;
+	case EXT2_IOC32_SETVERSION: cmd = EXT2_IOC_SETVERSION; break;
+	}
+	return sys_ioctl(fd, cmd, arg);
+}
+
+static int w_long(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	mm_segment_t old_fs = get_fs();
+	int err;
+	unsigned long val;
+	
+	set_fs (KERNEL_DS);
+	err = sys_ioctl(fd, cmd, (unsigned long)&val);
+	set_fs (old_fs);
+	if (!err && put_user((unsigned int) val, (u32 *)arg))
+		return -EFAULT;
+	return err;
+}
+
+struct ioctl32_handler {
+	unsigned int cmd;
+	int (*function)(unsigned int, unsigned int, unsigned long);
+};
+
+struct ioctl32_list {
+	struct ioctl32_handler handler;
+	struct ioctl32_list *next;
+};
+
+#define IOCTL32_DEFAULT(cmd)		{ { cmd, (void *) sys_ioctl }, 0 }
+#define IOCTL32_HANDLER(cmd, handler)	{ { cmd, (void *) handler }, 0 }
+
+static struct ioctl32_list ioctl32_handler_table[] = {
+	IOCTL32_DEFAULT(FIBMAP),
+	IOCTL32_DEFAULT(FIGETBSZ),
+
+	IOCTL32_DEFAULT(BIODASDDISABLE),
+	IOCTL32_DEFAULT(BIODASDENABLE),
+	IOCTL32_DEFAULT(BIODASDRSRV),
+	IOCTL32_DEFAULT(BIODASDRLSE),
+	IOCTL32_DEFAULT(BIODASDSLCK),
+	IOCTL32_DEFAULT(BIODASDRSID),
+	IOCTL32_DEFAULT(BIODASDFORMAT),
+	IOCTL32_DEFAULT(BIODASDRWTB),
+
+	IOCTL32_DEFAULT(BLKRRPART),
+
+	IOCTL32_HANDLER(HDIO_GETGEO, hd_geometry_ioctl),
+
+	IOCTL32_DEFAULT(TCGETA),
+	IOCTL32_DEFAULT(TCSETA),
+	IOCTL32_DEFAULT(TCSETAW),
+	IOCTL32_DEFAULT(TCSETAF),
+	IOCTL32_DEFAULT(TCSBRK),
+	IOCTL32_DEFAULT(TCXONC),
+	IOCTL32_DEFAULT(TCFLSH),
+	IOCTL32_DEFAULT(TCGETS),
+	IOCTL32_DEFAULT(TCSETS),
+	IOCTL32_DEFAULT(TCSETSW),
+	IOCTL32_DEFAULT(TCSETSF),
+	IOCTL32_DEFAULT(TIOCLINUX),
+
+	IOCTL32_DEFAULT(TIOCGETD),
+	IOCTL32_DEFAULT(TIOCSETD),
+	IOCTL32_DEFAULT(TIOCEXCL),
+	IOCTL32_DEFAULT(TIOCNXCL),
+	IOCTL32_DEFAULT(TIOCCONS),
+	IOCTL32_DEFAULT(TIOCGSOFTCAR),
+	IOCTL32_DEFAULT(TIOCSSOFTCAR),
+	IOCTL32_DEFAULT(TIOCSWINSZ),
+	IOCTL32_DEFAULT(TIOCGWINSZ),
+	IOCTL32_DEFAULT(TIOCMGET),
+	IOCTL32_DEFAULT(TIOCMBIC),
+	IOCTL32_DEFAULT(TIOCMBIS),
+	IOCTL32_DEFAULT(TIOCMSET),
+	IOCTL32_DEFAULT(TIOCPKT),
+	IOCTL32_DEFAULT(TIOCNOTTY),
+	IOCTL32_DEFAULT(TIOCSTI),
+	IOCTL32_DEFAULT(TIOCOUTQ),
+	IOCTL32_DEFAULT(TIOCSPGRP),
+	IOCTL32_DEFAULT(TIOCGPGRP),
+	IOCTL32_DEFAULT(TIOCSCTTY),
+	IOCTL32_DEFAULT(TIOCGPTN),
+	IOCTL32_DEFAULT(TIOCSPTLCK),
+	IOCTL32_DEFAULT(TIOCGSERIAL),
+	IOCTL32_DEFAULT(TIOCSSERIAL),
+	IOCTL32_DEFAULT(TIOCSERGETLSR),
+
+	IOCTL32_DEFAULT(FIOCLEX),
+	IOCTL32_DEFAULT(FIONCLEX),
+	IOCTL32_DEFAULT(FIOASYNC),
+	IOCTL32_DEFAULT(FIONBIO),
+	IOCTL32_DEFAULT(FIONREAD),
+
+	IOCTL32_DEFAULT(PIO_FONT),
+	IOCTL32_DEFAULT(GIO_FONT),
+	IOCTL32_DEFAULT(KDSIGACCEPT),
+	IOCTL32_DEFAULT(KDGETKEYCODE),
+	IOCTL32_DEFAULT(KDSETKEYCODE),
+	IOCTL32_DEFAULT(KIOCSOUND),
+	IOCTL32_DEFAULT(KDMKTONE),
+	IOCTL32_DEFAULT(KDGKBTYPE),
+	IOCTL32_DEFAULT(KDSETMODE),
+	IOCTL32_DEFAULT(KDGETMODE),
+	IOCTL32_DEFAULT(KDSKBMODE),
+	IOCTL32_DEFAULT(KDGKBMODE),
+	IOCTL32_DEFAULT(KDSKBMETA),
+	IOCTL32_DEFAULT(KDGKBMETA),
+	IOCTL32_DEFAULT(KDGKBENT),
+	IOCTL32_DEFAULT(KDSKBENT),
+	IOCTL32_DEFAULT(KDGKBSENT),
+	IOCTL32_DEFAULT(KDSKBSENT),
+	IOCTL32_DEFAULT(KDGKBDIACR),
+	IOCTL32_DEFAULT(KDSKBDIACR),
+	IOCTL32_DEFAULT(KDGKBLED),
+	IOCTL32_DEFAULT(KDSKBLED),
+	IOCTL32_DEFAULT(KDGETLED),
+	IOCTL32_DEFAULT(KDSETLED),
+	IOCTL32_DEFAULT(GIO_SCRNMAP),
+	IOCTL32_DEFAULT(PIO_SCRNMAP),
+	IOCTL32_DEFAULT(GIO_UNISCRNMAP),
+	IOCTL32_DEFAULT(PIO_UNISCRNMAP),
+	IOCTL32_DEFAULT(PIO_FONTRESET),
+	IOCTL32_DEFAULT(PIO_UNIMAPCLR),
+
+	IOCTL32_DEFAULT(VT_SETMODE),
+	IOCTL32_DEFAULT(VT_GETMODE),
+	IOCTL32_DEFAULT(VT_GETSTATE),
+	IOCTL32_DEFAULT(VT_OPENQRY),
+	IOCTL32_DEFAULT(VT_ACTIVATE),
+	IOCTL32_DEFAULT(VT_WAITACTIVE),
+	IOCTL32_DEFAULT(VT_RELDISP),
+	IOCTL32_DEFAULT(VT_DISALLOCATE),
+	IOCTL32_DEFAULT(VT_RESIZE),
+	IOCTL32_DEFAULT(VT_RESIZEX),
+	IOCTL32_DEFAULT(VT_LOCKSWITCH),
+	IOCTL32_DEFAULT(VT_UNLOCKSWITCH),
+
+	IOCTL32_HANDLER(SIOCGIFNAME, dev_ifname32),
+	IOCTL32_HANDLER(SIOCGIFCONF, dev_ifconf),
+	IOCTL32_HANDLER(SIOCGIFFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMETRIC, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMETRIC, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMTU, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMTU, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMEM, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMEM, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFHWADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFHWADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCADDMULTI, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCDELMULTI, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFINDEX, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFMAP, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFMAP, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFBRDADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFBRDADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFDSTADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFDSTADDR, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFNETMASK, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFNETMASK, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFPFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFPFLAGS, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCGIFTXQLEN, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCSIFTXQLEN, dev_ifsioc),
+	IOCTL32_HANDLER(SIOCADDRT, routing_ioctl),
+	IOCTL32_HANDLER(SIOCDELRT, routing_ioctl),
+
+	IOCTL32_HANDLER(EXT2_IOC32_GETFLAGS, do_ext2_ioctl),
+	IOCTL32_HANDLER(EXT2_IOC32_SETFLAGS, do_ext2_ioctl),
+	IOCTL32_HANDLER(EXT2_IOC32_GETVERSION, do_ext2_ioctl),
+	IOCTL32_HANDLER(EXT2_IOC32_SETVERSION, do_ext2_ioctl),
+
+	IOCTL32_HANDLER(BLKGETSIZE, w_long)
+
+};
+
+#define NR_IOCTL32_HANDLERS	(sizeof(ioctl32_handler_table) /	\
+				 sizeof(ioctl32_handler_table[0]))
+
+static struct ioctl32_list *ioctl32_hash_table[1024];
+
+static inline int ioctl32_hash(unsigned int cmd)
+{
+	return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
+}
+
+int sys32_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	int (*handler)(unsigned int, unsigned int, unsigned long, struct file * filp);
+	struct file *filp;
+	struct ioctl32_list *l;
+	int error;
+
+	l = ioctl32_hash_table[ioctl32_hash(cmd)];
+
+	error = -EBADF;
+
+	filp = fget(fd);
+	if (!filp)
+		return error;
+
+	if (!filp->f_op || !filp->f_op->ioctl) {
+		error = sys_ioctl (fd, cmd, arg);
+		goto out;
+	}
+
+	while (l && l->handler.cmd != cmd)
+		l = l->next;
+
+	if (l) {
+		handler = (void *)l->handler.function;
+		error = handler(fd, cmd, arg, filp);
+	} else {
+		error = -EINVAL;
+		printk("unknown ioctl: %08x\n", cmd);
+	}
+out:
+	fput(filp);
+	return error;
+}
+
+static void ioctl32_insert(struct ioctl32_list *entry)
+{
+	int hash = ioctl32_hash(entry->handler.cmd);
+	if (!ioctl32_hash_table[hash])
+		ioctl32_hash_table[hash] = entry;
+	else {
+		struct ioctl32_list *l;
+		l = ioctl32_hash_table[hash];
+		while (l->next)
+			l = l->next;
+		l->next = entry;
+		entry->next = 0;
+	}
+}
+
+static int __init init_ioctl32(void)
+{
+	int i;
+	for (i = 0; i < NR_IOCTL32_HANDLERS; i++)
+		ioctl32_insert(&ioctl32_handler_table[i]);
+	return 0;
+}
+
+__initcall(init_ioctl32);
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/irq.c linux/arch/s390x/kernel/irq.c
--- v2.4.1/linux/arch/s390x/kernel/irq.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/irq.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,423 @@
+/*
+ *  arch/s390/kernel/irq.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ *
+ *  Derived from "arch/i386/kernel/irq.c"
+ *    Copyright (C) 1992, 1999 Linus Torvalds, Ingo Molnar
+ *
+ *  S/390 I/O interrupt processing and I/O request processing is
+ *   implemented in arch/s390/kernel/s390io.c
+ */
+#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/string.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/threads.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/lowcore.h>
+
+void          s390_init_IRQ   ( void );
+void          s390_free_irq   ( unsigned int irq, void *dev_id);
+int           s390_request_irq( unsigned int irq,
+                     void           (*handler)(int, void *, struct pt_regs *),
+                     unsigned long  irqflags,
+                     const char    *devname,
+                     void          *dev_id);
+
+#if 0
+/*
+ * 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), via smp_message_pass():
+ */
+BUILD_SMP_INTERRUPT(reschedule_interrupt)
+BUILD_SMP_INTERRUPT(invalidate_interrupt)
+BUILD_SMP_INTERRUPT(stop_cpu_interrupt)
+BUILD_SMP_INTERRUPT(mtrr_interrupt)
+BUILD_SMP_INTERRUPT(spurious_interrupt)
+#endif
+
+#if 0
+int get_irq_list(char *buf)
+{
+	int i, j;
+	struct irqaction * action;
+	char *p = buf;
+
+	p += sprintf(p, "           ");
+
+	for (j=0; j<smp_num_cpus; j++)
+		p += sprintf(p, "CPU%d       ",j);
+
+	*p++ = '\n';
+
+	for (i = 0 ; i < NR_IRQS ; i++)
+	{
+		if (ioinfo[i] == INVALID_STORAGE_AREA)
+			continue;
+
+		action = ioinfo[i]->irq_desc.action;
+		
+  		if (!action)
+			continue;
+
+		p += sprintf(p, "%3d: ",i);
+#ifndef CONFIG_SMP
+		p += sprintf(p, "%10u ", kstat_irqs(i));
+#else
+		for (j=0; j<smp_num_cpus; j++)
+			p += sprintf( p, "%10u ",
+			              kstat.irqs[cpu_logical_map(j)][i]);
+#endif
+		p += sprintf(p, " %14s", ioinfo[i]->irq_desc.handler->typename);
+		p += sprintf(p, "  %s", action->name);
+
+		for (action=action->next; action; action = action->next)
+		{
+			p += sprintf(p, ", %s", action->name);
+
+		} /* endfor */
+
+		*p++ = '\n';
+	
+	} /* endfor */
+
+	p += sprintf(p, "NMI: %10u\n", nmi_counter);
+#ifdef CONFIG_SMP
+	p += sprintf(p, "IPI: %10u\n", atomic_read(&ipi_count));
+#endif
+
+	return p - buf;
+}
+#endif
+
+/*
+ * Global interrupt locks for SMP. Allow interrupts to come in on any
+ * CPU, yet make cli/sti act globally to protect critical regions..
+ */
+#ifdef CONFIG_SMP
+atomic_t global_irq_holder = ATOMIC_INIT(NO_PROC_ID);
+atomic_t global_irq_lock = ATOMIC_INIT(0);
+atomic_t global_irq_count = ATOMIC_INIT(0);
+atomic_t global_bh_count;
+
+/*
+ * "global_cli()" is a special case, in that it can hold the
+ * interrupts disabled for a longish time, and also because
+ * we may be doing TLB invalidates when holding the global
+ * IRQ lock for historical reasons. Thus we may need to check
+ * SMP invalidate events specially by hand here (but not in
+ * any normal spinlocks)
+ *
+ * Thankfully we don't need this as we can deliver flush tlbs with
+ * interrupts disabled DJB :-)
+ */
+#define check_smp_invalidate(cpu)
+
+static void show(char * str)
+{
+	int i;
+	unsigned long *stack;
+	int cpu = smp_processor_id();
+
+	printk("\n%s, CPU %d:\n", str, cpu);
+	printk("irq:  %d [%d]\n",
+	       atomic_read(&global_irq_count),local_irq_count(smp_processor_id()));
+	printk("bh:   %d [%d]\n",
+	       atomic_read(&global_bh_count),local_bh_count(smp_processor_id()));
+	stack = (unsigned long *) &str;
+	for (i = 40; i ; i--) {
+		unsigned long x = *++stack;
+		if (x > (unsigned long) &init_task_union && x < (unsigned long) &vsprintf) {
+			printk("<[%08lx]> ", x);
+		}
+	}
+}
+
+#define MAXCOUNT 100000000
+
+static inline void wait_on_bh(void)
+{
+	int count = MAXCOUNT;
+	do {
+		if (!--count) {
+			show("wait_on_bh");
+			count = ~0;
+		}
+		/* nothing .. wait for the other bh's to go away */
+	} while (atomic_read(&global_bh_count) != 0);
+}
+
+static inline void wait_on_irq(int cpu)
+{
+	int count = MAXCOUNT;
+
+	for (;;) {
+
+		/*
+		 * Wait until all interrupts are gone. Wait
+		 * for bottom half handlers unless we're
+		 * already executing in one..
+		 */
+		if (!atomic_read(&global_irq_count)) {
+			if (local_bh_count(cpu)||
+			    !atomic_read(&global_bh_count))
+				break;
+		}
+
+		/* Duh, we have to loop. Release the lock to avoid deadlocks */
+                atomic_set(&global_irq_lock, 0);
+
+		for (;;) {
+			if (!--count) {
+				show("wait_on_irq");
+				count = ~0;
+			}
+			__sti();
+			SYNC_OTHER_CORES(cpu);
+			__cli();
+			check_smp_invalidate(cpu);
+			if (atomic_read(&global_irq_count))
+				continue;
+			if (atomic_read(&global_irq_lock))
+				continue;
+			if (!local_bh_count(cpu)
+			    && atomic_read(&global_bh_count))
+				continue;
+                        if (!atomic_compare_and_swap(0, 1, &global_irq_lock))
+				break;
+		}
+	}
+}
+
+/*
+ * This is called when we want to synchronize with
+ * bottom half handlers. We need to wait until
+ * no other CPU is executing any bottom half handler.
+ *
+ * Don't wait if we're already running in an interrupt
+ * context or are inside a bh handler.
+ */
+void synchronize_bh(void)
+{
+	if (atomic_read(&global_bh_count) && !in_interrupt())
+		wait_on_bh();
+}
+
+/*
+ * This is called when we want to synchronize with
+ * interrupts. We may for example tell a device to
+ * stop sending interrupts: but to make sure there
+ * are no interrupts that are executing on another
+ * CPU we need to call this function.
+ */
+void synchronize_irq(void)
+{
+	if (atomic_read(&global_irq_count)) {
+		/* Stupid approach */
+		cli();
+		sti();
+	}
+}
+
+static inline void get_irqlock(int cpu)
+{
+	if (atomic_compare_and_swap(0,1,&global_irq_lock) != 0) {
+		/* do we already hold the lock? */
+		if ( cpu == atomic_read(&global_irq_holder))
+			return;
+		/* Uhhuh.. Somebody else got it. Wait.. */
+		do {
+			check_smp_invalidate(cpu);
+		} while (atomic_compare_and_swap(0,1,&global_irq_lock) != 0);
+	}
+	/*
+	 * We also to make sure that nobody else is running
+	 * in an interrupt context.
+	 */
+	wait_on_irq(cpu);
+
+	/*
+	 * Ok, finally..
+	 */
+	atomic_set(&global_irq_holder,cpu);
+}
+
+#define EFLAGS_I_SHIFT 57
+
+/*
+ * A global "cli()" while in an interrupt context
+ * turns into just a local cli(). Interrupts
+ * should use spinlocks for the (very unlikely)
+ * case that they ever want to protect against
+ * each other.
+ *
+ * If we already have local interrupts disabled,
+ * this will not turn a local disable into a
+ * global one (problems with spinlocks: this makes
+ * save_flags+cli+sti usable inside a spinlock).
+ */
+void __global_cli(void)
+{
+	unsigned long flags;
+
+	__save_flags(flags);
+	if (flags & (1UL << EFLAGS_I_SHIFT)) {
+		int cpu = smp_processor_id();
+		__cli();
+		if (!in_irq())
+			get_irqlock(cpu);
+	}
+}
+
+void __global_sti(void)
+{
+
+	if (!in_irq())
+		release_irqlock(smp_processor_id());
+	__sti();
+}
+
+/*
+ * SMP flags value to restore to:
+ * 0 - global cli
+ * 1 - global sti
+ * 2 - local cli
+ * 3 - local sti
+ */
+unsigned long __global_save_flags(void)
+{
+	int retval;
+	int local_enabled;
+	unsigned long flags;
+
+	__save_flags(flags);
+	local_enabled = (flags >> EFLAGS_I_SHIFT) & 1;
+	/* default to local */
+	retval = 2 + local_enabled;
+
+	/* check for global flags if we're not in an interrupt */
+	if (!in_irq())
+	{
+		if (local_enabled)
+			retval = 1;
+		if (atomic_read(&global_irq_holder)== smp_processor_id())
+			retval = 0;
+	}
+	return retval;
+}
+
+void __global_restore_flags(unsigned long flags)
+{
+	switch (flags) {
+	case 0:
+		__global_cli();
+		break;
+	case 1:
+		__global_sti();
+		break;
+	case 2:
+		__cli();
+		break;
+	case 3:
+		__sti();
+		break;
+	default:
+		printk("global_restore_flags: %08lx (%08lx)\n",
+		       flags, (&flags)[-1]);
+	}
+}
+
+#endif
+
+/*
+ * Note : This fuction should be eliminated as it doesn't comply with the
+ *         S/390 irq scheme we have implemented ...
+ */
+int handle_IRQ_event(unsigned int irq, int cpu, struct pt_regs * regs)
+{
+	struct irqaction * action;
+	int                status;
+
+	status = 0;
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
+	action = ioinfo[irq]->irq_desc.action;
+
+	if (action)
+	{
+		status |= 1;
+
+		if (!(action->flags & SA_INTERRUPT))
+			__sti();
+
+		do
+		{
+			status |= action->flags;
+			action->handler(irq, action->dev_id, regs);
+			action = action->next;
+		} while (action);
+
+		if (status & SA_SAMPLE_RANDOM)
+			add_interrupt_randomness(irq);
+		__cli();
+
+	} /* endif */
+
+	return status;
+}
+
+void enable_nop(int irq)
+{
+}
+
+void __init init_IRQ(void)
+{
+   s390_init_IRQ();
+}
+
+
+void free_irq(unsigned int irq, void *dev_id)
+{
+   s390_free_irq( irq, dev_id);
+}
+
+
+int request_irq( unsigned int   irq,
+                 void           (*handler)(int, void *, struct pt_regs *),
+                 unsigned long  irqflags,
+                 const char    *devname,
+                 void          *dev_id)
+{
+   return( s390_request_irq( irq, handler, irqflags, devname, dev_id ) );
+
+}
+
+void init_irq_proc(void)
+{
+        /* For now, nothing... */
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/irqextras390.c linux/arch/s390x/kernel/irqextras390.c
--- v2.4.1/linux/arch/s390x/kernel/irqextras390.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/irqextras390.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,35 @@
+/*
+ *  arch/s390/kernel/irqextras390.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ *  Some channel code by D.J. Barrow
+ */
+
+/*
+	
+*/
+#include<asm/irqextras390.h>
+#include<asm/lowcore.h>
+
+#if 0
+// fixchannelprogram is now obselete
+void fixchannelprogram(orb_bits_t *orbptr)
+{
+	__u32	newAddress=orbptr->ccw_program_address;
+	fixccws(orbptr->ccw_program_address);
+	orbptr->ccw_program_address=newAddress;
+	orbptr->ccw_program_address=(ccw1_t *)(((__u32)orbptr->ccw_program_address));
+}
+#endif
+
+void fixccws(ccw1_bits_t *ccwptr)
+{
+	for(;;ccwptr++)
+	{	// Just hope nobody starts doing prefixing
+		if(!ccwptr->cc)
+			break;
+	}
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/linux32.c linux/arch/s390x/kernel/linux32.c
--- v2.4.1/linux/arch/s390x/kernel/linux32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/linux32.c	Fri Feb 16 16:02:35 2001
@@ -0,0 +1,4326 @@
+/*
+ *  arch/s390x/kernel/linux32.c
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Gerhard Tonn (ton@de.ibm.com)   
+ *
+ *  Conversion between 31bit and 64bit native syscalls.
+ *
+ * Heavily inspired by the 32-bit Sparc compat code which is 
+ * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ *
+ */
+
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/fs.h> 
+#include <linux/mm.h> 
+#include <linux/file.h> 
+#include <linux/signal.h>
+#include <linux/utime.h>
+#include <linux/resource.h>
+#include <linux/times.h>
+#include <linux/utsname.h>
+#include <linux/timex.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/malloc.h>
+#include <linux/uio.h>
+#include <linux/nfs_fs.h>
+#include <linux/smb_fs.h>
+#include <linux/smb_mount.h>
+#include <linux/ncp_fs.h>
+#include <linux/quota.h>
+#include <linux/module.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/cache.h>
+#include <linux/nfsd/xdr.h>
+#include <linux/nfsd/syscall.h>
+#include <linux/poll.h>
+#include <linux/personality.h>
+#include <linux/stat.h>
+#include <linux/filter.h>
+#include <linux/highmem.h>
+#include <linux/highuid.h>
+#include <linux/mman.h>
+#include <linux/ipv6.h>
+#include <linux/in.h>
+#include <linux/icmpv6.h>
+#include <linux/sysctl.h>
+
+#include <asm/types.h>
+#include <asm/ipc.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+
+#include <net/scm.h>
+
+#include "linux32.h"
+
+extern asmlinkage long sys_chown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_lchown(const char *, uid_t,gid_t);
+extern asmlinkage long sys_fchown(unsigned int, uid_t,gid_t);
+extern asmlinkage long sys_setregid(gid_t, gid_t);
+extern asmlinkage long sys_setgid(gid_t);
+extern asmlinkage long sys_setreuid(uid_t, uid_t);
+extern asmlinkage long sys_setuid(uid_t);
+extern asmlinkage long sys_setresuid(uid_t, uid_t, uid_t);
+extern asmlinkage long sys_setresgid(gid_t, gid_t, gid_t);
+extern asmlinkage long sys_setfsuid(uid_t);
+extern asmlinkage long sys_setfsgid(gid_t);
+ 
+/* For this source file, we want overflow handling. */
+
+#undef high2lowuid
+#undef high2lowgid
+#undef low2highuid
+#undef low2highgid
+#undef SET_UID16
+#undef SET_GID16
+#undef NEW_TO_OLD_UID
+#undef NEW_TO_OLD_GID
+#undef SET_OLDSTAT_UID
+#undef SET_OLDSTAT_GID
+#undef SET_STAT_UID
+#undef SET_STAT_GID
+
+#define high2lowuid(uid) ((uid) > 65535) ? (u16)overflowuid : (u16)(uid)
+#define high2lowgid(gid) ((gid) > 65535) ? (u16)overflowgid : (u16)(gid)
+#define low2highuid(uid) ((uid) == (u16)-1) ? (uid_t)-1 : (uid_t)(uid)
+#define low2highgid(gid) ((gid) == (u16)-1) ? (gid_t)-1 : (gid_t)(gid)
+#define SET_UID16(var, uid)	var = high2lowuid(uid)
+#define SET_GID16(var, gid)	var = high2lowgid(gid)
+#define NEW_TO_OLD_UID(uid)	high2lowuid(uid)
+#define NEW_TO_OLD_GID(gid)	high2lowgid(gid)
+#define SET_OLDSTAT_UID(stat, uid)	(stat).st_uid = high2lowuid(uid)
+#define SET_OLDSTAT_GID(stat, gid)	(stat).st_gid = high2lowgid(gid)
+#define SET_STAT_UID(stat, uid)		(stat).st_uid = high2lowuid(uid)
+#define SET_STAT_GID(stat, gid)		(stat).st_gid = high2lowgid(gid)
+
+asmlinkage long sys32_chown16(const char * filename, u16 user, u16 group)
+{
+	return sys_chown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_lchown16(const char * filename, u16 user, u16 group)
+{
+	return sys_lchown(filename, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_fchown16(unsigned int fd, u16 user, u16 group)
+{
+	return sys_fchown(fd, low2highuid(user), low2highgid(group));
+}
+
+asmlinkage long sys32_setregid16(u16 rgid, u16 egid)
+{
+	return sys_setregid(low2highgid(rgid), low2highgid(egid));
+}
+
+asmlinkage long sys32_setgid16(u16 gid)
+{
+	return sys_setgid((gid_t)gid);
+}
+
+asmlinkage long sys32_setreuid16(u16 ruid, u16 euid)
+{
+	return sys_setreuid(low2highuid(ruid), low2highuid(euid));
+}
+
+asmlinkage long sys32_setuid16(u16 uid)
+{
+	return sys_setuid((uid_t)uid);
+}
+
+asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid)
+{
+	return sys_setresuid(low2highuid(ruid), low2highuid(euid),
+		low2highuid(suid));
+}
+
+asmlinkage long sys32_getresuid16(u16 *ruid, u16 *euid, u16 *suid)
+{
+	int retval;
+
+	if (!(retval = put_user(high2lowuid(current->uid), ruid)) &&
+	    !(retval = put_user(high2lowuid(current->euid), euid)))
+		retval = put_user(high2lowuid(current->suid), suid);
+
+	return retval;
+}
+
+asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid)
+{
+	return sys_setresgid(low2highgid(rgid), low2highgid(egid),
+		low2highgid(sgid));
+}
+
+asmlinkage long sys32_getresgid16(u16 *rgid, u16 *egid, u16 *sgid)
+{
+	int retval;
+
+	if (!(retval = put_user(high2lowgid(current->gid), rgid)) &&
+	    !(retval = put_user(high2lowgid(current->egid), egid)))
+		retval = put_user(high2lowgid(current->sgid), sgid);
+
+	return retval;
+}
+
+asmlinkage long sys32_setfsuid16(u16 uid)
+{
+	return sys_setfsuid((uid_t)uid);
+}
+
+asmlinkage long sys32_setfsgid16(u16 gid)
+{
+	return sys_setfsgid((gid_t)gid);
+}
+
+asmlinkage long sys32_getgroups16(int gidsetsize, u16 *grouplist)
+{
+	u16 groups[NGROUPS];
+	int i,j;
+
+	if (gidsetsize < 0)
+		return -EINVAL;
+	i = current->ngroups;
+	if (gidsetsize) {
+		if (i > gidsetsize)
+			return -EINVAL;
+		for(j=0;j<i;j++)
+			groups[j] = current->groups[j];
+		if (copy_to_user(grouplist, groups, sizeof(u16)*i))
+			return -EFAULT;
+	}
+	return i;
+}
+
+asmlinkage long sys32_setgroups16(int gidsetsize, u16 *grouplist)
+{
+	u16 groups[NGROUPS];
+	int i;
+
+	if (!capable(CAP_SETGID))
+		return -EPERM;
+	if ((unsigned) gidsetsize > NGROUPS)
+		return -EINVAL;
+	if (copy_from_user(groups, grouplist, gidsetsize * sizeof(u16)))
+		return -EFAULT;
+	for (i = 0 ; i < gidsetsize ; i++)
+		current->groups[i] = (gid_t)groups[i];
+	current->ngroups = gidsetsize;
+	return 0;
+}
+
+asmlinkage long sys32_getuid16(void)
+{
+	return high2lowuid(current->uid);
+}
+
+asmlinkage long sys32_geteuid16(void)
+{
+	return high2lowuid(current->euid);
+}
+
+asmlinkage long sys32_getgid16(void)
+{
+	return high2lowgid(current->gid);
+}
+
+asmlinkage long sys32_getegid16(void)
+{
+	return high2lowgid(current->egid);
+}
+
+/* 32-bit timeval and related flotsam.  */
+
+struct timeval32
+{
+    int tv_sec, tv_usec;
+};
+
+struct itimerval32
+{
+    struct timeval32 it_interval;
+    struct timeval32 it_value;
+};
+
+static inline long get_tv32(struct timeval *o, struct timeval32 *i)
+{
+	return (!access_ok(VERIFY_READ, tv32, sizeof(*tv32)) ||
+		(__get_user(o->tv_sec, &i->tv_sec) |
+		 __get_user(o->tv_usec, &i->tv_usec)));
+}
+
+static inline long put_tv32(struct timeval32 *o, struct timeval *i)
+{
+	return (!access_ok(VERIFY_WRITE, o, sizeof(*o)) ||
+		(__put_user(i->tv_sec, &o->tv_sec) |
+		 __put_user(i->tv_usec, &o->tv_usec)));
+}
+
+static inline long get_it32(struct itimerval *o, struct itimerval32 *i)
+{
+	return (!access_ok(VERIFY_READ, i32, sizeof(*i32)) ||
+		(__get_user(o->it_interval.tv_sec, &i->it_interval.tv_sec) |
+		 __get_user(o->it_interval.tv_usec, &i->it_interval.tv_usec) |
+		 __get_user(o->it_value.tv_sec, &i->it_value.tv_sec) |
+		 __get_user(o->it_value.tv_usec, &i->it_value.tv_usec)));
+}
+
+static inline long put_it32(struct itimerval32 *o, struct itimerval *i)
+{
+	return (!access_ok(VERIFY_WRITE, i32, sizeof(*i32)) ||
+		(__put_user(i->it_interval.tv_sec, &o->it_interval.tv_sec) |
+		 __put_user(i->it_interval.tv_usec, &o->it_interval.tv_usec) |
+		 __put_user(i->it_value.tv_sec, &o->it_value.tv_sec) |
+		 __put_user(i->it_value.tv_usec, &o->it_value.tv_usec)));
+}
+
+struct msgbuf32 { s32 mtype; char mtext[1]; };
+
+struct ipc_perm32
+{
+	key_t    	  key;
+        __kernel_uid_t32  uid;
+        __kernel_gid_t32  gid;
+        __kernel_uid_t32  cuid;
+        __kernel_gid_t32  cgid;
+        __kernel_mode_t32 mode;
+        unsigned short  seq;
+};
+
+struct semid_ds32 {
+        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */
+        __kernel_time_t32 sem_otime;              /* last semop time */
+        __kernel_time_t32 sem_ctime;              /* last change time */
+        u32 sem_base;              /* ptr to first semaphore in array */
+        u32 sem_pending;          /* pending operations to be processed */
+        u32 sem_pending_last;    /* last pending operation */
+        u32 undo;                  /* undo requests on this array */
+        unsigned short  sem_nsems;              /* no. of semaphores in array */
+};
+
+struct semid64_ds32 {
+	struct ipc64_perm sem_perm;		  /* this structure is the same on sparc32 and sparc64 */
+	unsigned int	  __pad1;
+	__kernel_time_t32 sem_otime;
+	unsigned int	  __pad2;
+	__kernel_time_t32 sem_ctime;
+	u32 sem_nsems;
+	u32 __unused1;
+	u32 __unused2;
+};
+
+struct msqid_ds32
+{
+        struct ipc_perm32 msg_perm;
+        u32 msg_first;
+        u32 msg_last;
+        __kernel_time_t32 msg_stime;
+        __kernel_time_t32 msg_rtime;
+        __kernel_time_t32 msg_ctime;
+        u32 wwait;
+        u32 rwait;
+        unsigned short msg_cbytes;
+        unsigned short msg_qnum;  
+        unsigned short msg_qbytes;
+        __kernel_ipc_pid_t32 msg_lspid;
+        __kernel_ipc_pid_t32 msg_lrpid;
+};
+
+struct msqid64_ds32 {
+	struct ipc64_perm msg_perm;
+	unsigned int   __pad1;
+	__kernel_time_t32 msg_stime;
+	unsigned int   __pad2;
+	__kernel_time_t32 msg_rtime;
+	unsigned int   __pad3;
+	__kernel_time_t32 msg_ctime;
+	unsigned int  msg_cbytes;
+	unsigned int  msg_qnum;
+	unsigned int  msg_qbytes;
+	__kernel_pid_t32 msg_lspid;
+	__kernel_pid_t32 msg_lrpid;
+	unsigned int  __unused1;
+	unsigned int  __unused2;
+};
+
+
+struct shmid_ds32 {
+	struct ipc_perm32       shm_perm;
+	int                     shm_segsz;
+	__kernel_time_t32       shm_atime;
+	__kernel_time_t32       shm_dtime;
+	__kernel_time_t32       shm_ctime;
+	__kernel_ipc_pid_t32    shm_cpid; 
+	__kernel_ipc_pid_t32    shm_lpid; 
+	unsigned short          shm_nattch;
+};
+
+struct shmid64_ds32 {
+	struct ipc64_perm	shm_perm;
+	unsigned int		__pad1;
+	__kernel_time_t32	shm_atime;
+	unsigned int		__pad2;
+	__kernel_time_t32	shm_dtime;
+	unsigned int		__pad3;
+	__kernel_time_t32	shm_ctime;
+	__kernel_size_t32	shm_segsz;
+	__kernel_pid_t32	shm_cpid;
+	__kernel_pid_t32	shm_lpid;
+	unsigned int		shm_nattch;
+	unsigned int		__unused1;
+	unsigned int		__unused2;
+};
+
+                                                        
+/*
+ * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation..
+ *
+ * This is really horribly ugly.
+ */
+#define IPCOP_MASK(__x)	(1UL << (__x))
+static int do_sys32_semctl(int first, int second, int third, void *uptr)
+{
+	union semun fourth;
+	u32 pad;
+	int err = -EINVAL;
+
+	if (!uptr)
+		goto out;
+	err = -EFAULT;
+	if (get_user (pad, (u32 *)uptr))
+		goto out;
+	if(third == SETVAL)
+		fourth.val = (int)pad;
+	else
+		fourth.__pad = (void *)A(pad);
+	if (IPCOP_MASK (third) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SEM_INFO) | IPCOP_MASK (GETVAL) |
+	     IPCOP_MASK (GETPID) | IPCOP_MASK (GETNCNT) | IPCOP_MASK (GETZCNT) |
+	     IPCOP_MASK (GETALL) | IPCOP_MASK (SETALL) | IPCOP_MASK (IPC_RMID))) {
+		err = sys_semctl (first, second, third, fourth);
+	} else if (third & IPC_64) {
+		struct semid64_ds s;
+		struct semid64_ds32 *usp = (struct semid64_ds32 *)A(pad);
+		mm_segment_t old_fs;
+		int need_back_translation;
+
+		if (third == (IPC_SET|IPC_64)) {
+			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
+			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
+			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			if (err)
+				goto out;
+			fourth.__pad = &s;
+		}
+		need_back_translation =
+			(IPCOP_MASK (third) &
+			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
+		if (need_back_translation)
+			fourth.__pad = &s;
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_semctl (first, second, third, fourth);
+		set_fs (old_fs);
+		if (need_back_translation) {
+			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
+			err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
+			err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
+			err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
+			err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
+			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
+			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
+			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
+			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
+			if (err2) err = -EFAULT;
+		}
+	} else {
+		struct semid_ds s;
+		struct semid_ds32 *usp = (struct semid_ds32 *)A(pad);
+		mm_segment_t old_fs;
+		int need_back_translation;
+
+		if (third == IPC_SET) {
+			err = get_user (s.sem_perm.uid, &usp->sem_perm.uid);
+			err |= __get_user (s.sem_perm.gid, &usp->sem_perm.gid);
+			err |= __get_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			if (err)
+				goto out;
+			fourth.__pad = &s;
+		}
+		need_back_translation =
+			(IPCOP_MASK (third) &
+			 (IPCOP_MASK (SEM_STAT) | IPCOP_MASK (IPC_STAT))) != 0;
+		if (need_back_translation)
+			fourth.__pad = &s;
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_semctl (first, second, third, fourth);
+		set_fs (old_fs);
+		if (need_back_translation) {
+			int err2 = put_user (s.sem_perm.key, &usp->sem_perm.key);
+			err2 |= __put_user (high2lowuid(s.sem_perm.uid), &usp->sem_perm.uid);
+			err2 |= __put_user (high2lowgid(s.sem_perm.gid), &usp->sem_perm.gid);
+			err2 |= __put_user (high2lowuid(s.sem_perm.cuid), &usp->sem_perm.cuid);
+			err2 |= __put_user (high2lowgid(s.sem_perm.cgid), &usp->sem_perm.cgid);
+			err2 |= __put_user (s.sem_perm.mode, &usp->sem_perm.mode);
+			err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);
+			err2 |= __put_user (s.sem_otime, &usp->sem_otime);
+			err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);
+			err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);
+			if (err2) err = -EFAULT;
+		}
+	}
+out:
+	return err;
+}
+
+static int do_sys32_msgsnd (int first, int second, int third, void *uptr)
+{
+	struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+	struct msgbuf32 *up = (struct msgbuf32 *)uptr;
+	mm_segment_t old_fs;
+	int err;
+
+	if (!p)
+		return -ENOMEM;
+	err = get_user (p->mtype, &up->mtype);
+	err |= __copy_from_user (p->mtext, &up->mtext, second);
+	if (err)
+		goto out;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_msgsnd (first, p, second, third);
+	set_fs (old_fs);
+out:
+	kfree (p);
+	return err;
+}
+
+static int do_sys32_msgrcv (int first, int second, int msgtyp, int third,
+			    int version, void *uptr)
+{
+	struct msgbuf32 *up;
+	struct msgbuf *p;
+	mm_segment_t old_fs;
+	int err;
+
+	if (!version) {
+		struct ipc_kludge_32 *uipck = (struct ipc_kludge_32 *)uptr;
+		struct ipc_kludge_32 ipck;
+
+		err = -EINVAL;
+		if (!uptr)
+			goto out;
+		err = -EFAULT;
+		if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge_32)))
+			goto out;
+		uptr = (void *)A(ipck.msgp);
+		msgtyp = ipck.msgtyp;
+	}
+	err = -ENOMEM;
+	p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER);
+	if (!p)
+		goto out;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_msgrcv (first, p, second + 4, msgtyp, third);
+	set_fs (old_fs);
+	if (err < 0)
+		goto free_then_out;
+	up = (struct msgbuf32 *)uptr;
+	if (put_user (p->mtype, &up->mtype) ||
+	    __copy_to_user (&up->mtext, p->mtext, err))
+		err = -EFAULT;
+free_then_out:
+	kfree (p);
+out:
+	return err;
+}
+
+static int do_sys32_msgctl (int first, int second, void *uptr)
+{
+	int err;
+
+	if (IPCOP_MASK (second) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (MSG_INFO) |
+	     IPCOP_MASK (IPC_RMID))) {
+		err = sys_msgctl (first, second, (struct msqid_ds *)uptr);
+	} else if (second & IPC_64) {
+		struct msqid64_ds m;
+		struct msqid64_ds32 *up = (struct msqid64_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == (IPC_SET|IPC_64)) {
+			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
+			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
+			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_msgctl (first, second, (struct msqid_ds *)&m);
+		set_fs (old_fs);
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
+			err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
+			err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
+			err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
+			err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
+			err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
+			err2 |= __put_user (m.msg_stime, &up->msg_stime);
+			err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
+			err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
+			err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
+			err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
+			err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
+			err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
+			err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	} else {
+		struct msqid_ds m;
+		struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == IPC_SET) {
+			err = get_user (m.msg_perm.uid, &up->msg_perm.uid);
+			err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid);
+			err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err |= __get_user (m.msg_qbytes, &up->msg_qbytes);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_msgctl (first, second, &m);
+		set_fs (old_fs);
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (MSG_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (m.msg_perm.key, &up->msg_perm.key);
+			err2 |= __put_user (high2lowuid(m.msg_perm.uid), &up->msg_perm.uid);
+			err2 |= __put_user (high2lowgid(m.msg_perm.gid), &up->msg_perm.gid);
+			err2 |= __put_user (high2lowuid(m.msg_perm.cuid), &up->msg_perm.cuid);
+			err2 |= __put_user (high2lowgid(m.msg_perm.cgid), &up->msg_perm.cgid);
+			err2 |= __put_user (m.msg_perm.mode, &up->msg_perm.mode);
+			err2 |= __put_user (m.msg_perm.seq, &up->msg_perm.seq);
+			err2 |= __put_user (m.msg_stime, &up->msg_stime);
+			err2 |= __put_user (m.msg_rtime, &up->msg_rtime);
+			err2 |= __put_user (m.msg_ctime, &up->msg_ctime);
+			err2 |= __put_user (m.msg_cbytes, &up->msg_cbytes);
+			err2 |= __put_user (m.msg_qnum, &up->msg_qnum);
+			err2 |= __put_user (m.msg_qbytes, &up->msg_qbytes);
+			err2 |= __put_user (m.msg_lspid, &up->msg_lspid);
+			err2 |= __put_user (m.msg_lrpid, &up->msg_lrpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	}
+
+out:
+	return err;
+}
+
+static int do_sys32_shmat (int first, int second, int third, int version, void *uptr)
+{
+	unsigned long raddr;
+	u32 *uaddr = (u32 *)A((u32)third);
+	int err = -EINVAL;
+
+	if (version == 1)
+		goto out;
+	err = sys_shmat (first, uptr, second, &raddr);
+	if (err)
+		goto out;
+	err = put_user (raddr, uaddr);
+out:
+	return err;
+}
+
+static int do_sys32_shmctl (int first, int second, void *uptr)
+{
+	int err;
+
+	if (IPCOP_MASK (second) &
+	    (IPCOP_MASK (IPC_INFO) | IPCOP_MASK (SHM_LOCK) | IPCOP_MASK (SHM_UNLOCK) |
+	     IPCOP_MASK (IPC_RMID))) {
+		if (second == (IPC_INFO|IPC_64))
+			second = IPC_INFO; /* So that we don't have to translate it */
+		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
+	} else if ((second & IPC_64) && second != (SHM_INFO|IPC_64)) {
+		struct shmid64_ds s;
+		struct shmid64_ds32 *up = (struct shmid64_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		if (second == (IPC_SET|IPC_64)) {
+			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_shmctl (first, second, (struct shmid_ds *)&s);
+		set_fs (old_fs);
+		if (err < 0)
+			goto out;
+
+		/* Mask it even in this case so it becomes a CSE. */
+		if (IPCOP_MASK (second) &
+		    (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
+			err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
+			err2 |= __put_user (high2lowgid(s.shm_perm.gid), &up->shm_perm.gid);
+			err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
+			err2 |= __put_user (high2lowgid(s.shm_perm.cgid), &up->shm_perm.cgid);
+			err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
+			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
+			err2 |= __put_user (s.shm_atime, &up->shm_atime);
+			err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
+			err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
+			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
+			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
+			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
+			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	} else {
+		struct shmid_ds s;
+		struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
+		mm_segment_t old_fs;
+
+		second &= ~IPC_64;
+		if (second == IPC_SET) {
+			err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
+			err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
+			err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+			if (err)
+				goto out;
+		}
+		old_fs = get_fs ();
+		set_fs (KERNEL_DS);
+		err = sys_shmctl (first, second, &s);
+		set_fs (old_fs);
+		if (err < 0)
+			goto out;
+
+		/* Mask it even in this case so it becomes a CSE. */
+		if (second == SHM_INFO) {
+			struct shm_info32 {
+				int used_ids;
+				u32 shm_tot, shm_rss, shm_swp;
+				u32 swap_attempts, swap_successes;
+			} *uip = (struct shm_info32 *)uptr;
+			struct shm_info *kp = (struct shm_info *)&s;
+			int err2 = put_user (kp->used_ids, &uip->used_ids);
+			err2 |= __put_user (kp->shm_tot, &uip->shm_tot);
+			err2 |= __put_user (kp->shm_rss, &uip->shm_rss);
+			err2 |= __put_user (kp->shm_swp, &uip->shm_swp);
+			err2 |= __put_user (kp->swap_attempts, &uip->swap_attempts);
+			err2 |= __put_user (kp->swap_successes, &uip->swap_successes);
+			if (err2)
+				err = -EFAULT;
+		} else if (IPCOP_MASK (second) &
+			   (IPCOP_MASK (SHM_STAT) | IPCOP_MASK (IPC_STAT))) {
+			int err2 = put_user (s.shm_perm.key, &up->shm_perm.key);
+			err2 |= __put_user (high2lowuid(s.shm_perm.uid), &up->shm_perm.uid);
+			err2 |= __put_user (high2lowgid(s.shm_perm.gid), &up->shm_perm.gid);
+			err2 |= __put_user (high2lowuid(s.shm_perm.cuid), &up->shm_perm.cuid);
+			err2 |= __put_user (high2lowgid(s.shm_perm.cgid), &up->shm_perm.cgid);
+			err2 |= __put_user (s.shm_perm.mode, &up->shm_perm.mode);
+			err2 |= __put_user (s.shm_perm.seq, &up->shm_perm.seq);
+			err2 |= __put_user (s.shm_atime, &up->shm_atime);
+			err2 |= __put_user (s.shm_dtime, &up->shm_dtime);
+			err2 |= __put_user (s.shm_ctime, &up->shm_ctime);
+			err2 |= __put_user (s.shm_segsz, &up->shm_segsz);
+			err2 |= __put_user (s.shm_nattch, &up->shm_nattch);
+			err2 |= __put_user (s.shm_cpid, &up->shm_cpid);
+			err2 |= __put_user (s.shm_lpid, &up->shm_lpid);
+			if (err2)
+				err = -EFAULT;
+		}
+	}
+out:
+	return err;
+}
+
+asmlinkage int sys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth)
+{
+	int version, err;
+
+	version = call >> 16; /* hack for backward compatibility */
+	call &= 0xffff;
+
+	if(version)
+		return -EINVAL;
+
+	if (call <= SEMCTL)
+		switch (call) {
+		case SEMOP:
+			/* struct sembuf is the same on 32 and 64bit :)) */
+			err = sys_semop (first, (struct sembuf *)AA(ptr), second);
+			goto out;
+		case SEMGET:
+			err = sys_semget (first, second, third);
+			goto out;
+		case SEMCTL:
+			err = do_sys32_semctl (first, second, third, (void *)AA(ptr));
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		};
+	if (call <= MSGCTL) 
+		switch (call) {
+		case MSGSND:
+			err = do_sys32_msgsnd (first, second, third, (void *)AA(ptr));
+			goto out;
+		case MSGRCV:
+			err = do_sys32_msgrcv (first, second, 0, third,
+					       version, (void *)AA(ptr));
+			goto out;
+		case MSGGET:
+			err = sys_msgget ((key_t) first, second);
+			goto out;
+		case MSGCTL:
+			err = do_sys32_msgctl (first, second, (void *)AA(ptr));
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+	if (call <= SHMCTL) 
+		switch (call) {
+		case SHMAT:
+			err = do_sys32_shmat (first, second, third,
+					      version, (void *)AA(ptr));
+			goto out;
+		case SHMDT: 
+			err = sys_shmdt ((char *)AA(ptr));
+			goto out;
+		case SHMGET:
+			err = sys_shmget (first, second, third);
+			goto out;
+		case SHMCTL:
+			err = do_sys32_shmctl (first, second, (void *)AA(ptr));
+			goto out;
+		default:
+			err = -EINVAL;
+			goto out;
+		}
+
+	err = -EINVAL;
+
+out:
+	return err;
+}
+
+static inline int get_flock(struct flock *kfl, struct flock32 *ufl)
+{
+	int err;
+	
+	err = get_user(kfl->l_type, &ufl->l_type);
+	err |= __get_user(kfl->l_whence, &ufl->l_whence);
+	err |= __get_user(kfl->l_start, &ufl->l_start);
+	err |= __get_user(kfl->l_len, &ufl->l_len);
+	err |= __get_user(kfl->l_pid, &ufl->l_pid);
+	return err;
+}
+
+static inline int put_flock(struct flock *kfl, struct flock32 *ufl)
+{
+	int err;
+	
+	err = __put_user(kfl->l_type, &ufl->l_type);
+	err |= __put_user(kfl->l_whence, &ufl->l_whence);
+	err |= __put_user(kfl->l_start, &ufl->l_start);
+	err |= __put_user(kfl->l_len, &ufl->l_len);
+	err |= __put_user(kfl->l_pid, &ufl->l_pid);
+	return err;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg);
+
+asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	switch (cmd) {
+	case F_GETLK:
+	case F_SETLK:
+	case F_SETLKW:
+		{
+			struct flock f;
+			mm_segment_t old_fs;
+			long ret;
+			
+			if(get_flock(&f, (struct flock32 *)arg))
+				return -EFAULT;
+			old_fs = get_fs(); set_fs (KERNEL_DS);
+			ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+			set_fs (old_fs);
+			if (ret) return ret;
+			if (f.l_start >= 0x7fffffffUL ||
+			    f.l_len >= 0x7fffffffUL ||
+			    f.l_start + f.l_len >= 0x7fffffffUL)
+				return -EOVERFLOW;
+			if(put_flock(&f, (struct flock32 *)arg))
+				return -EFAULT;
+			return 0;
+		}
+	default:
+		return sys_fcntl(fd, cmd, (unsigned long)arg);
+	}
+}
+
+asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+	if (cmd >= F_GETLK64 && cmd <= F_SETLKW64)
+		return sys_fcntl(fd, cmd + F_GETLK - F_GETLK64, arg);
+	return sys32_fcntl(fd, cmd, arg);
+}
+
+struct dqblk32 {
+    __u32 dqb_bhardlimit;
+    __u32 dqb_bsoftlimit;
+    __u32 dqb_curblocks;
+    __u32 dqb_ihardlimit;
+    __u32 dqb_isoftlimit;
+    __u32 dqb_curinodes;
+    __kernel_time_t32 dqb_btime;
+    __kernel_time_t32 dqb_itime;
+};
+                                
+extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
+
+asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
+{
+	int cmds = cmd >> SUBCMDSHIFT;
+	int err;
+	struct mem_dqblk d;
+	mm_segment_t old_fs;
+	char *spec;
+	
+	switch (cmds) {
+	case Q_GETQUOTA:
+		break;
+	case Q_SETQUOTA:
+	case Q_SETUSE:
+	case Q_SETQLIM:
+		if (copy_from_user (&d, (struct dqblk32 *)addr,
+				    sizeof (struct dqblk32)))
+			return -EFAULT;
+		d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
+		d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
+		break;
+	default:
+		return sys_quotactl(cmd, special,
+				    id, (caddr_t)addr);
+	}
+	spec = getname (special);
+	err = PTR_ERR(spec);
+	if (IS_ERR(spec)) return err;
+	old_fs = get_fs ();
+	set_fs (KERNEL_DS);
+	err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
+	set_fs (old_fs);
+	putname (spec);
+	if (cmds == Q_GETQUOTA) {
+		__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
+		((struct dqblk32 *)&d)->dqb_itime = i;
+		((struct dqblk32 *)&d)->dqb_btime = b;
+		if (copy_to_user ((struct dqblk32 *)addr, &d,
+				  sizeof (struct dqblk32)))
+			return -EFAULT;
+	}
+	return err;
+}
+
+static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
+{
+	int err;
+	
+	err = put_user (kbuf->f_type, &ubuf->f_type);
+	err |= __put_user (kbuf->f_bsize, &ubuf->f_bsize);
+	err |= __put_user (kbuf->f_blocks, &ubuf->f_blocks);
+	err |= __put_user (kbuf->f_bfree, &ubuf->f_bfree);
+	err |= __put_user (kbuf->f_bavail, &ubuf->f_bavail);
+	err |= __put_user (kbuf->f_files, &ubuf->f_files);
+	err |= __put_user (kbuf->f_ffree, &ubuf->f_ffree);
+	err |= __put_user (kbuf->f_namelen, &ubuf->f_namelen);
+	err |= __put_user (kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]);
+	err |= __put_user (kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]);
+	return err;
+}
+
+extern asmlinkage int sys_statfs(const char * path, struct statfs * buf);
+
+asmlinkage int sys32_statfs(const char * path, struct statfs32 *buf)
+{
+	int ret;
+	struct statfs s;
+	mm_segment_t old_fs = get_fs();
+	char *pth;
+	
+	pth = getname (path);
+	ret = PTR_ERR(pth);
+	if (!IS_ERR(pth)) {
+		set_fs (KERNEL_DS);
+		ret = sys_statfs((const char *)pth, &s);
+		set_fs (old_fs);
+		putname (pth);
+		if (put_statfs(buf, &s))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+extern asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf);
+
+asmlinkage int sys32_fstatfs(unsigned int fd, struct statfs32 *buf)
+{
+	int ret;
+	struct statfs s;
+	mm_segment_t old_fs = get_fs();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_fstatfs(fd, &s);
+	set_fs (old_fs);
+	if (put_statfs(buf, &s))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage long sys_truncate(const char * path, unsigned long length);
+extern asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length);
+
+asmlinkage int sys32_truncate64(const char * path, unsigned long high, unsigned long low)
+{
+	if ((int)high < 0)
+		return -EINVAL;
+	else
+		return sys_truncate(path, (high << 32) | low);
+}
+
+asmlinkage int sys32_ftruncate64(unsigned int fd, unsigned long high, unsigned long low)
+{
+	if ((int)high < 0)
+		return -EINVAL;
+	else
+		return sys_ftruncate(fd, (high << 32) | low);
+}
+
+extern asmlinkage int sys_utime(char * filename, struct utimbuf * times);
+
+struct utimbuf32 {
+	__kernel_time_t32 actime, modtime;
+};
+
+asmlinkage int sys32_utime(char * filename, struct utimbuf32 *times)
+{
+	struct utimbuf t;
+	mm_segment_t old_fs;
+	int ret;
+	char *filenam;
+	
+	if (!times)
+		return sys_utime(filename, NULL);
+	if (get_user (t.actime, &times->actime) ||
+	    __get_user (t.modtime, &times->modtime))
+		return -EFAULT;
+	filenam = getname (filename);
+	ret = PTR_ERR(filenam);
+	if (!IS_ERR(filenam)) {
+		old_fs = get_fs();
+		set_fs (KERNEL_DS); 
+		ret = sys_utime(filenam, &t);
+		set_fs (old_fs);
+		putname (filenam);
+	}
+	return ret;
+}
+
+struct iovec32 { u32 iov_base; __kernel_size_t32 iov_len; };
+
+typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *);
+typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *);
+
+static long do_readv_writev32(int type, struct file *file,
+			      const struct iovec32 *vector, u32 count)
+{
+	unsigned long tot_len;
+	struct iovec iovstack[UIO_FASTIOV];
+	struct iovec *iov=iovstack, *ivp;
+	struct inode *inode;
+	long retval, i;
+	io_fn_t fn;
+	iov_fn_t fnv;
+
+	/* First get the "struct iovec" from user memory and
+	 * verify all the pointers
+	 */
+	if (!count)
+		return 0;
+	if (verify_area(VERIFY_READ, vector, sizeof(struct iovec32)*count))
+		return -EFAULT;
+	if (count > UIO_MAXIOV)
+		return -EINVAL;
+	if (count > UIO_FASTIOV) {
+		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);
+		if (!iov)
+			return -ENOMEM;
+	}
+
+	tot_len = 0;
+	i = count;
+	ivp = iov;
+	while(i > 0) {
+		u32 len;
+		u32 buf;
+
+		__get_user(len, &vector->iov_len);
+		__get_user(buf, &vector->iov_base);
+		tot_len += len;
+		ivp->iov_base = (void *)A(buf);
+		ivp->iov_len = (__kernel_size_t) len;
+		vector++;
+		ivp++;
+		i--;
+	}
+
+	inode = file->f_dentry->d_inode;
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	retval = locks_verify_area((type == VERIFY_WRITE
+				    ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE),
+				   inode, file, file->f_pos, tot_len);
+	if (retval)
+		goto out;
+
+	/* VERIFY_WRITE actually means a read, as we write to user space */
+	fnv = (type == VERIFY_WRITE ? file->f_op->readv : file->f_op->writev);
+	if (fnv) {
+		retval = fnv(file, iov, count, &file->f_pos);
+		goto out;
+	}
+
+	fn = (type == VERIFY_WRITE ? file->f_op->read :
+	      (io_fn_t) file->f_op->write);
+
+	ivp = iov;
+	while (count > 0) {
+		void * base;
+		int len, nr;
+
+		base = ivp->iov_base;
+		len = ivp->iov_len;
+		ivp++;
+		count--;
+		nr = fn(file, base, len, &file->f_pos);
+		if (nr < 0) {
+			if (!retval)
+				retval = nr;
+			break;
+		}
+		retval += nr;
+		if (nr != len)
+			break;
+	}
+out:
+	if (iov != iovstack)
+		kfree(iov);
+
+	return retval;
+}
+
+asmlinkage long sys32_readv(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	long ret = -EBADF;
+
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+
+	if (file->f_op && (file->f_mode & FMODE_READ) &&
+	    (file->f_op->readv || file->f_op->read))
+		ret = do_readv_writev32(VERIFY_WRITE, file, vector, count);
+	fput(file);
+
+bad_file:
+	return ret;
+}
+
+asmlinkage long sys32_writev(int fd, struct iovec32 *vector, u32 count)
+{
+	struct file *file;
+	int ret = -EBADF;
+
+	file = fget(fd);
+	if(!file)
+		goto bad_file;
+	if (file->f_op && (file->f_mode & FMODE_WRITE) &&
+	    (file->f_op->writev || file->f_op->write))
+		ret = do_readv_writev32(VERIFY_READ, file, vector, count);
+	fput(file);
+
+bad_file:
+	return ret;
+}
+
+/* readdir & getdents */
+
+#define NAME_OFFSET(de) ((int) ((de)->d_name - (char *) (de)))
+#define ROUND_UP(x) (((x)+sizeof(u32)-1) & ~(sizeof(u32)-1))
+
+struct old_linux_dirent32 {
+	u32		d_ino;
+	u32		d_offset;
+	unsigned short	d_namlen;
+	char		d_name[1];
+};
+
+struct readdir_callback32 {
+	struct old_linux_dirent32 * dirent;
+	int count;
+};
+
+static int fillonedir(void * __buf, const char * name, int namlen,
+		      off_t offset, ino_t ino, unsigned int d_type)
+{
+	struct readdir_callback32 * buf = (struct readdir_callback32 *) __buf;
+	struct old_linux_dirent32 * dirent;
+
+	if (buf->count)
+		return -EINVAL;
+	buf->count++;
+	dirent = buf->dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user(offset, &dirent->d_offset);
+	put_user(namlen, &dirent->d_namlen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	return 0;
+}
+
+asmlinkage int old32_readdir(unsigned int fd, struct old_linux_dirent32 *dirent, unsigned int count)
+{
+	int error = -EBADF;
+	struct file * file;
+	struct readdir_callback32 buf;
+
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.count = 0;
+	buf.dirent = dirent;
+
+	error = vfs_readdir(file, fillonedir, &buf);
+	if (error < 0)
+		goto out_putf;
+	error = buf.count;
+
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+
+struct linux_dirent32 {
+	u32		d_ino;
+	u32		d_off;
+	unsigned short	d_reclen;
+	char		d_name[1];
+};
+
+struct getdents_callback32 {
+	struct linux_dirent32 * current_dir;
+	struct linux_dirent32 * previous;
+	int count;
+	int error;
+};
+
+static int filldir(void * __buf, const char * name, int namlen, off_t offset, ino_t ino,
+		   unsigned int d_type)
+{
+	struct linux_dirent32 * dirent;
+	struct getdents_callback32 * buf = (struct getdents_callback32 *) __buf;
+	int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1);
+
+	buf->error = -EINVAL;	/* only used if we fail.. */
+	if (reclen > buf->count)
+		return -EINVAL;
+	dirent = buf->previous;
+	if (dirent)
+		put_user(offset, &dirent->d_off);
+	dirent = buf->current_dir;
+	buf->previous = dirent;
+	put_user(ino, &dirent->d_ino);
+	put_user(reclen, &dirent->d_reclen);
+	copy_to_user(dirent->d_name, name, namlen);
+	put_user(0, dirent->d_name + namlen);
+	((char *) dirent) += reclen;
+	buf->current_dir = dirent;
+	buf->count -= reclen;
+	return 0;
+}
+
+asmlinkage int sys32_getdents(unsigned int fd, struct linux_dirent32 *dirent, unsigned int count)
+{
+	struct file * file;
+	struct linux_dirent32 * lastdirent;
+	struct getdents_callback32 buf;
+	int error = -EBADF;
+
+	file = fget(fd);
+	if (!file)
+		goto out;
+
+	buf.current_dir = dirent;
+	buf.previous = NULL;
+	buf.count = count;
+	buf.error = 0;
+
+	error = vfs_readdir(file, filldir, &buf);
+	if (error < 0)
+		goto out_putf;
+	lastdirent = buf.previous;
+	error = buf.error;
+	if(lastdirent) {
+		put_user(file->f_pos, &lastdirent->d_off);
+		error = count - buf.count;
+	}
+out_putf:
+	fput(file);
+out:
+	return error;
+}
+
+/* end of readdir & getdents */
+
+/*
+ * Ooo, nasty.  We need here to frob 32-bit unsigned longs to
+ * 64-bit unsigned longs.
+ */
+
+static inline int
+get_fd_set32(unsigned long n, unsigned long *fdset, u32 *ufdset)
+{
+	if (ufdset) {
+		unsigned long odd;
+
+		if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))
+			return -EFAULT;
+
+		odd = n & 1UL;
+		n &= ~1UL;
+		while (n) {
+			unsigned long h, l;
+			__get_user(l, ufdset);
+			__get_user(h, ufdset+1);
+			ufdset += 2;
+			*fdset++ = h << 32 | l;
+			n -= 2;
+		}
+		if (odd)
+			__get_user(*fdset, ufdset);
+	} else {
+		/* Tricky, must clear full unsigned long in the
+		 * kernel fdset at the end, this makes sure that
+		 * actually happens.
+		 */
+		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));
+	}
+	return 0;
+}
+
+static inline void
+set_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset)
+{
+	unsigned long odd;
+
+	if (!ufdset)
+		return;
+
+	odd = n & 1UL;
+	n &= ~1UL;
+	while (n) {
+		unsigned long h, l;
+		l = *fdset++;
+		h = l >> 32;
+		__put_user(l, ufdset);
+		__put_user(h, ufdset+1);
+		ufdset += 2;
+		n -= 2;
+	}
+	if (odd)
+		__put_user(*fdset, ufdset);
+}
+
+#define MAX_SELECT_SECONDS \
+	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+
+asmlinkage int sys32_select(int n, u32 *inp, u32 *outp, u32 *exp, u32 tvp_x)
+{
+	fd_set_bits fds;
+	struct timeval32 *tvp = (struct timeval32 *)AA(tvp_x);
+	char *bits;
+	unsigned long nn;
+	long timeout;
+	int ret, size;
+
+	timeout = MAX_SCHEDULE_TIMEOUT;
+	if (tvp) {
+		time_t sec, usec;
+
+		if ((ret = verify_area(VERIFY_READ, tvp, sizeof(*tvp)))
+		    || (ret = __get_user(sec, &tvp->tv_sec))
+		    || (ret = __get_user(usec, &tvp->tv_usec)))
+			goto out_nofds;
+
+		ret = -EINVAL;
+		if(sec < 0 || usec < 0)
+			goto out_nofds;
+
+		if ((unsigned long) sec < MAX_SELECT_SECONDS) {
+			timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
+			timeout += sec * (unsigned long) HZ;
+		}
+	}
+
+	ret = -EINVAL;
+	if (n < 0)
+		goto out_nofds;
+	if (n > current->files->max_fdset)
+		n = current->files->max_fdset;
+
+	/*
+	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),
+	 * since we used fdset we need to allocate memory in units of
+	 * long-words. 
+	 */
+	ret = -ENOMEM;
+	size = FDS_BYTES(n);
+	bits = kmalloc(6 * size, GFP_KERNEL);
+	if (!bits)
+		goto out_nofds;
+	fds.in      = (unsigned long *)  bits;
+	fds.out     = (unsigned long *) (bits +   size);
+	fds.ex      = (unsigned long *) (bits + 2*size);
+	fds.res_in  = (unsigned long *) (bits + 3*size);
+	fds.res_out = (unsigned long *) (bits + 4*size);
+	fds.res_ex  = (unsigned long *) (bits + 5*size);
+
+	nn = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));
+	if ((ret = get_fd_set32(nn, fds.in, inp)) ||
+	    (ret = get_fd_set32(nn, fds.out, outp)) ||
+	    (ret = get_fd_set32(nn, fds.ex, exp)))
+		goto out;
+	zero_fd_set(n, fds.res_in);
+	zero_fd_set(n, fds.res_out);
+	zero_fd_set(n, fds.res_ex);
+
+	ret = do_select(n, &fds, &timeout);
+
+	if (tvp && !(current->personality & STICKY_TIMEOUTS)) {
+		time_t sec = 0, usec = 0;
+		if (timeout) {
+			sec = timeout / HZ;
+			usec = timeout % HZ;
+			usec *= (1000000/HZ);
+		}
+		put_user(sec, &tvp->tv_sec);
+		put_user(usec, &tvp->tv_usec);
+	}
+
+	if (ret < 0)
+		goto out;
+	if (!ret) {
+		ret = -ERESTARTNOHAND;
+		if (signal_pending(current))
+			goto out;
+		ret = 0;
+	}
+
+	set_fd_set32(nn, inp, fds.res_in);
+	set_fd_set32(nn, outp, fds.res_out);
+	set_fd_set32(nn, exp, fds.res_ex);
+
+out:
+	kfree(bits);
+out_nofds:
+	return ret;
+}
+
+static int cp_new_stat32(struct inode *inode, struct stat32 *statbuf)
+{
+	unsigned long ino, blksize, blocks;
+	kdev_t dev, rdev;
+	umode_t mode;
+	nlink_t nlink;
+	uid_t uid;
+	gid_t gid;
+	off_t size;
+	time_t atime, mtime, ctime;
+	int err;
+
+	/* Stream the loads of inode data into the load buffer,
+	 * then we push it all into the store buffer below.  This
+	 * should give optimal cache performance.
+	 */
+	ino = inode->i_ino;
+	dev = inode->i_dev;
+	mode = inode->i_mode;
+	nlink = inode->i_nlink;
+	uid = inode->i_uid;
+	gid = inode->i_gid;
+	rdev = inode->i_rdev;
+	size = inode->i_size;
+	atime = inode->i_atime;
+	mtime = inode->i_mtime;
+	ctime = inode->i_ctime;
+	blksize = inode->i_blksize;
+	blocks = inode->i_blocks;
+
+	err  = put_user(kdev_t_to_nr(dev), &statbuf->st_dev);
+	err |= put_user(ino, &statbuf->st_ino);
+	err |= put_user(mode, &statbuf->st_mode);
+	err |= put_user(nlink, &statbuf->st_nlink);
+	err |= put_user(high2lowuid(uid), &statbuf->st_uid);
+	err |= put_user(high2lowgid(gid), &statbuf->st_gid);
+	err |= put_user(kdev_t_to_nr(rdev), &statbuf->st_rdev);
+	err |= put_user(size, &statbuf->st_size);
+	err |= put_user(atime, &statbuf->st_atime);
+	err |= put_user(0, &statbuf->__unused1);
+	err |= put_user(mtime, &statbuf->st_mtime);
+	err |= put_user(0, &statbuf->__unused2);
+	err |= put_user(ctime, &statbuf->st_ctime);
+	err |= put_user(0, &statbuf->__unused3);
+	if (blksize) {
+		err |= put_user(blksize, &statbuf->st_blksize);
+		err |= put_user(blocks, &statbuf->st_blocks);
+	} else {
+		unsigned int tmp_blocks;
+
+#define D_B   7
+#define I_B   (BLOCK_SIZE / sizeof(unsigned short))
+		tmp_blocks = (size + BLOCK_SIZE - 1) / BLOCK_SIZE;
+		if (tmp_blocks > D_B) {
+			unsigned int indirect;
+
+			indirect = (tmp_blocks - D_B + I_B - 1) / I_B;
+			tmp_blocks += indirect;
+			if (indirect > 1) {
+				indirect = (indirect - 1 + I_B - 1) / I_B;
+				tmp_blocks += indirect;
+				if (indirect > 1)
+					tmp_blocks++;
+			}
+		}
+		err |= put_user(BLOCK_SIZE, &statbuf->st_blksize);
+		err |= put_user((BLOCK_SIZE / 512) * tmp_blocks, &statbuf->st_blocks);
+#undef D_B
+#undef I_B
+	}
+/* fixme
+	err |= put_user(0, &statbuf->__unused4[0]);
+	err |= put_user(0, &statbuf->__unused4[1]);
+*/
+
+	return err;
+}
+
+/* Perhaps this belongs in fs.h or similar. -DaveM */
+static __inline__ int
+do_revalidate(struct dentry *dentry)
+{
+	struct inode * inode = dentry->d_inode;
+	if (inode->i_op && inode->i_op->revalidate)
+		return inode->i_op->revalidate(dentry);
+	return 0;
+}
+
+asmlinkage int sys32_newstat(char * filename, struct stat32 *statbuf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk(filename, &nd);
+	if (!error) {
+		error = do_revalidate(nd.dentry);
+		if (!error)
+			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage int sys32_newlstat(char * filename, struct stat32 *statbuf)
+{
+	struct nameidata nd;
+	int error;
+
+	error = user_path_walk_link(filename, &nd);
+	if (!error) {
+		error = do_revalidate(nd.dentry);
+		if (!error)
+			error = cp_new_stat32(nd.dentry->d_inode, statbuf);
+
+		path_release(&nd);
+	}
+	return error;
+}
+
+asmlinkage int sys32_newfstat(unsigned int fd, struct stat32 *statbuf)
+{
+	struct file *f;
+	int err = -EBADF;
+
+	f = fget(fd);
+	if (f) {
+		struct dentry * dentry = f->f_dentry;
+
+		err = do_revalidate(dentry);
+		if (!err)
+			err = cp_new_stat32(dentry->d_inode, statbuf);
+		fput(f);
+	}
+	return err;
+}
+
+extern asmlinkage int sys_sysfs(int option, unsigned long arg1, unsigned long arg2);
+
+asmlinkage int sys32_sysfs(int option, u32 arg1, u32 arg2)
+{
+	return sys_sysfs(option, arg1, arg2);
+}
+
+struct ncp_mount_data32 {
+        int version;
+        unsigned int ncp_fd;
+        __kernel_uid_t32 mounted_uid;
+        __kernel_pid_t32 wdog_pid;
+        unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
+        unsigned int time_out;
+        unsigned int retry_count;
+        unsigned int flags;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
+
+static void *do_ncp_super_data_conv(void *raw_data)
+{
+	struct ncp_mount_data *n = (struct ncp_mount_data *)raw_data;
+	struct ncp_mount_data32 *n32 = (struct ncp_mount_data32 *)raw_data;
+
+	n->dir_mode = n32->dir_mode;
+	n->file_mode = n32->file_mode;
+	n->gid = low2highgid(n32->gid);
+	n->uid = low2highuid(n32->uid);
+	memmove (n->mounted_vol, n32->mounted_vol, (sizeof (n32->mounted_vol) + 3 * sizeof (unsigned int)));
+	n->wdog_pid = n32->wdog_pid;
+	n->mounted_uid = low2highuid(n32->mounted_uid);
+	return raw_data;
+}
+
+struct smb_mount_data32 {
+        int version;
+        __kernel_uid_t32 mounted_uid;
+        __kernel_uid_t32 uid;
+        __kernel_gid_t32 gid;
+        __kernel_mode_t32 file_mode;
+        __kernel_mode_t32 dir_mode;
+};
+
+static void *do_smb_super_data_conv(void *raw_data)
+{
+	struct smb_mount_data *s = (struct smb_mount_data *)raw_data;
+	struct smb_mount_data32 *s32 = (struct smb_mount_data32 *)raw_data;
+
+	s->version = s32->version;
+	s->mounted_uid = low2highuid(s32->mounted_uid);
+	s->uid = low2highuid(s32->uid);
+	s->gid = low2highgid(s32->gid);
+	s->file_mode = s32->file_mode;
+	s->dir_mode = s32->dir_mode;
+	return raw_data;
+}
+
+static int copy_mount_stuff_to_kernel(const void *user, unsigned long *kernel)
+{
+	int i;
+	unsigned long page;
+	struct vm_area_struct *vma;
+
+	*kernel = 0;
+	if(!user)
+		return 0;
+	vma = find_vma(current->mm, (unsigned long)user);
+	if(!vma || (unsigned long)user < vma->vm_start)
+		return -EFAULT;
+	if(!(vma->vm_flags & VM_READ))
+		return -EFAULT;
+	i = vma->vm_end - (unsigned long) user;
+	if(PAGE_SIZE <= (unsigned long) i)
+		i = PAGE_SIZE - 1;
+	if(!(page = __get_free_page(GFP_KERNEL)))
+		return -ENOMEM;
+	if(copy_from_user((void *) page, user, i)) {
+		free_page(page);
+		return -EFAULT;
+	}
+	*kernel = page;
+	return 0;
+}
+
+#define SMBFS_NAME	"smbfs"
+#define NCPFS_NAME	"ncpfs"
+
+asmlinkage int sys32_mount(char *dev_name, char *dir_name, char *type, unsigned long new_flags, u32 data)
+{
+	unsigned long type_page = 0;
+	unsigned long data_page = 0;
+	unsigned long dev_page = 0;
+	unsigned long dir_page = 0;
+	int err, is_smb, is_ncp;
+
+	is_smb = is_ncp = 0;
+
+	err = copy_mount_stuff_to_kernel((const void *)type, &type_page);
+	if (err)
+		goto out;
+
+	if (!type_page) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	is_smb = !strcmp((char *)type_page, SMBFS_NAME);
+	is_ncp = !strcmp((char *)type_page, NCPFS_NAME);
+
+	err = copy_mount_stuff_to_kernel((const void *)AA(data), &data_page);
+	if (err)
+		goto type_out;
+
+	err = copy_mount_stuff_to_kernel(dev_name, &dev_page);
+	if (err)
+		goto data_out;
+
+	err = copy_mount_stuff_to_kernel(dir_name, &dir_page);
+	if (err)
+		goto dev_out;
+
+	if (!is_smb && !is_ncp) {
+		lock_kernel();
+		err = do_mount((char*)dev_page, (char*)dir_page,
+				(char*)type_page, new_flags, (char*)data_page);
+		unlock_kernel();
+	} else {
+		if (is_ncp)
+			do_ncp_super_data_conv((void *)data_page);
+		else
+			do_smb_super_data_conv((void *)data_page);
+
+		lock_kernel();
+		err = do_mount((char*)dev_page, (char*)dir_page,
+				(char*)type_page, new_flags, (char*)data_page);
+		unlock_kernel();
+	}
+	free_page(dir_page);
+
+dev_out:
+	free_page(dev_page);
+
+data_out:
+	free_page(data_page);
+
+type_out:
+	free_page(type_page);
+
+out:
+	return err;
+}
+
+struct rusage32 {
+        struct timeval32 ru_utime;
+        struct timeval32 ru_stime;
+        s32    ru_maxrss;
+        s32    ru_ixrss;
+        s32    ru_idrss;
+        s32    ru_isrss;
+        s32    ru_minflt;
+        s32    ru_majflt;
+        s32    ru_nswap;
+        s32    ru_inblock;
+        s32    ru_oublock;
+        s32    ru_msgsnd; 
+        s32    ru_msgrcv; 
+        s32    ru_nsignals;
+        s32    ru_nvcsw;
+        s32    ru_nivcsw;
+};
+
+static int put_rusage (struct rusage32 *ru, struct rusage *r)
+{
+	int err;
+	
+	err = put_user (r->ru_utime.tv_sec, &ru->ru_utime.tv_sec);
+	err |= __put_user (r->ru_utime.tv_usec, &ru->ru_utime.tv_usec);
+	err |= __put_user (r->ru_stime.tv_sec, &ru->ru_stime.tv_sec);
+	err |= __put_user (r->ru_stime.tv_usec, &ru->ru_stime.tv_usec);
+	err |= __put_user (r->ru_maxrss, &ru->ru_maxrss);
+	err |= __put_user (r->ru_ixrss, &ru->ru_ixrss);
+	err |= __put_user (r->ru_idrss, &ru->ru_idrss);
+	err |= __put_user (r->ru_isrss, &ru->ru_isrss);
+	err |= __put_user (r->ru_minflt, &ru->ru_minflt);
+	err |= __put_user (r->ru_majflt, &ru->ru_majflt);
+	err |= __put_user (r->ru_nswap, &ru->ru_nswap);
+	err |= __put_user (r->ru_inblock, &ru->ru_inblock);
+	err |= __put_user (r->ru_oublock, &ru->ru_oublock);
+	err |= __put_user (r->ru_msgsnd, &ru->ru_msgsnd);
+	err |= __put_user (r->ru_msgrcv, &ru->ru_msgrcv);
+	err |= __put_user (r->ru_nsignals, &ru->ru_nsignals);
+	err |= __put_user (r->ru_nvcsw, &ru->ru_nvcsw);
+	err |= __put_user (r->ru_nivcsw, &ru->ru_nivcsw);
+	return err;
+}
+
+asmlinkage int sys32_wait4(__kernel_pid_t32 pid, unsigned int *stat_addr, int options, struct rusage32 *ru)
+{
+	if (!ru)
+		return sys_wait4(pid, stat_addr, options, NULL);
+	else {
+		struct rusage r;
+		int ret;
+		unsigned int status;
+		mm_segment_t old_fs = get_fs();
+		
+		set_fs (KERNEL_DS);
+		ret = sys_wait4(pid, stat_addr ? &status : NULL, options, &r);
+		set_fs (old_fs);
+		if (put_rusage (ru, &r)) return -EFAULT;
+		if (stat_addr && put_user (status, stat_addr))
+			return -EFAULT;
+		return ret;
+	}
+}
+
+struct sysinfo32 {
+        s32 uptime;
+        u32 loads[3];
+        u32 totalram;
+        u32 freeram;
+        u32 sharedram;
+        u32 bufferram;
+        u32 totalswap;
+        u32 freeswap;
+        unsigned short procs;
+        char _f[22];
+};
+
+extern asmlinkage int sys_sysinfo(struct sysinfo *info);
+
+asmlinkage int sys32_sysinfo(struct sysinfo32 *info)
+{
+	struct sysinfo s;
+	int ret, err;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sysinfo(&s);
+	set_fs (old_fs);
+	err = put_user (s.uptime, &info->uptime);
+	err |= __put_user (s.loads[0], &info->loads[0]);
+	err |= __put_user (s.loads[1], &info->loads[1]);
+	err |= __put_user (s.loads[2], &info->loads[2]);
+	err |= __put_user (s.totalram, &info->totalram);
+	err |= __put_user (s.freeram, &info->freeram);
+	err |= __put_user (s.sharedram, &info->sharedram);
+	err |= __put_user (s.bufferram, &info->bufferram);
+	err |= __put_user (s.totalswap, &info->totalswap);
+	err |= __put_user (s.freeswap, &info->freeswap);
+	err |= __put_user (s.procs, &info->procs);
+	if (err)
+		return -EFAULT;
+	return ret;
+}
+
+struct timespec32 {
+	s32    tv_sec;
+	s32    tv_nsec;
+};
+                
+extern asmlinkage int sys_sched_rr_get_interval(pid_t pid, struct timespec *interval);
+
+asmlinkage int sys32_sched_rr_get_interval(__kernel_pid_t32 pid, struct timespec32 *interval)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_sched_rr_get_interval(pid, &t);
+	set_fs (old_fs);
+	if (put_user (t.tv_sec, &interval->tv_sec) ||
+	    __put_user (t.tv_nsec, &interval->tv_nsec))
+		return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_nanosleep(struct timespec *rqtp, struct timespec *rmtp);
+
+asmlinkage int sys32_nanosleep(struct timespec32 *rqtp, struct timespec32 *rmtp)
+{
+	struct timespec t;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	if (get_user (t.tv_sec, &rqtp->tv_sec) ||
+	    __get_user (t.tv_nsec, &rqtp->tv_nsec))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_nanosleep(&t, rmtp ? &t : NULL);
+	set_fs (old_fs);
+	if (rmtp && ret == -EINTR) {
+		if (__put_user (t.tv_sec, &rmtp->tv_sec) ||
+	    	    __put_user (t.tv_nsec, &rmtp->tv_nsec))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+extern asmlinkage int sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset);
+
+asmlinkage int sys32_sigprocmask(int how, old_sigset_t32 *set, old_sigset_t32 *oset)
+{
+	old_sigset_t s;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	if (set && get_user (s, set)) return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL);
+	set_fs (old_fs);
+	if (ret) return ret;
+	if (oset && put_user (s, oset)) return -EFAULT;
+	return 0;
+}
+
+extern asmlinkage int sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigprocmask(int how, sigset_t32 *set, sigset_t32 *oset, __kernel_size_t32 sigsetsize)
+{
+	sigset_t s;
+	sigset_t32 s32;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	if (set) {
+		if (copy_from_user (&s32, set, sizeof(sigset_t32)))
+			return -EFAULT;
+		switch (_NSIG_WORDS) {
+		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
+		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
+		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
+		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
+		}
+	}
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize);
+	set_fs (old_fs);
+	if (ret) return ret;
+	if (oset) {
+		switch (_NSIG_WORDS) {
+		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
+		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
+		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
+		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
+		}
+		if (copy_to_user (oset, &s32, sizeof(sigset_t32)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+extern asmlinkage int sys_sigpending(old_sigset_t *set);
+
+asmlinkage int sys32_sigpending(old_sigset_t32 *set)
+{
+	old_sigset_t s;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_sigpending(&s);
+	set_fs (old_fs);
+	if (put_user (s, set)) return -EFAULT;
+	return ret;
+}
+
+extern asmlinkage int sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
+
+asmlinkage int sys32_rt_sigpending(sigset_t32 *set, __kernel_size_t32 sigsetsize)
+{
+	sigset_t s;
+	sigset_t32 s32;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigpending(&s, sigsetsize);
+	set_fs (old_fs);
+	if (!ret) {
+		switch (_NSIG_WORDS) {
+		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
+		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];
+		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];
+		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];
+		}
+		if (copy_to_user (set, &s32, sizeof(sigset_t32)))
+			return -EFAULT;
+	}
+	return ret;
+}
+
+extern int
+copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from);
+
+asmlinkage int
+sys32_rt_sigtimedwait(sigset_t32 *uthese, siginfo_t32 *uinfo,
+		      struct timespec32 *uts, __kernel_size_t32 sigsetsize)
+{
+	int ret, sig;
+	sigset_t these;
+	sigset_t32 these32;
+	struct timespec ts;
+	siginfo_t info;
+	long timeout = 0;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user (&these32, uthese, sizeof(sigset_t32)))
+		return -EFAULT;
+
+	switch (_NSIG_WORDS) {
+	case 4: these.sig[3] = these32.sig[6] | (((long)these32.sig[7]) << 32);
+	case 3: these.sig[2] = these32.sig[4] | (((long)these32.sig[5]) << 32);
+	case 2: these.sig[1] = these32.sig[2] | (((long)these32.sig[3]) << 32);
+	case 1: these.sig[0] = these32.sig[0] | (((long)these32.sig[1]) << 32);
+	}
+		
+	/*
+	 * Invert the set of allowed signals to get those we
+	 * want to block.
+	 */
+	sigdelsetmask(&these, sigmask(SIGKILL)|sigmask(SIGSTOP));
+	signotset(&these);
+
+	if (uts) {
+		if (get_user (ts.tv_sec, &uts->tv_sec) ||
+		    get_user (ts.tv_nsec, &uts->tv_nsec))
+			return -EINVAL;
+		if (ts.tv_nsec >= 1000000000L || ts.tv_nsec < 0
+		    || ts.tv_sec < 0)
+			return -EINVAL;
+	}
+
+	spin_lock_irq(&current->sigmask_lock);
+	sig = dequeue_signal(&these, &info);
+	if (!sig) {
+		/* None ready -- temporarily unblock those we're interested
+		   in so that we'll be awakened when they arrive.  */
+		sigset_t oldblocked = current->blocked;
+		sigandsets(&current->blocked, &current->blocked, &these);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		timeout = MAX_SCHEDULE_TIMEOUT;
+		if (uts)
+			timeout = (timespec_to_jiffies(&ts)
+				   + (ts.tv_sec || ts.tv_nsec));
+
+		current->state = TASK_INTERRUPTIBLE;
+		timeout = schedule_timeout(timeout);
+
+		spin_lock_irq(&current->sigmask_lock);
+		sig = dequeue_signal(&these, &info);
+		current->blocked = oldblocked;
+		recalc_sigpending(current);
+	}
+	spin_unlock_irq(&current->sigmask_lock);
+
+	if (sig) {
+		ret = sig;
+		if (uinfo) {
+			if (copy_siginfo_to_user32(uinfo, &info))
+				ret = -EFAULT;
+		}
+	} else {
+		ret = -EAGAIN;
+		if (timeout)
+			ret = -EINTR;
+	}
+
+	return ret;
+}
+
+extern asmlinkage int
+sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo);
+
+asmlinkage int
+sys32_rt_sigqueueinfo(int pid, int sig, siginfo_t32 *uinfo)
+{
+	siginfo_t info;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+	
+	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
+		return -EFAULT;
+	set_fs (KERNEL_DS);
+	ret = sys_rt_sigqueueinfo(pid, sig, &info);
+	set_fs (old_fs);
+	return ret;
+}
+
+struct tms32 {
+	__kernel_clock_t32 tms_utime;
+	__kernel_clock_t32 tms_stime;
+	__kernel_clock_t32 tms_cutime;
+	__kernel_clock_t32 tms_cstime;
+};
+                                
+extern asmlinkage long sys_times(struct tms * tbuf);
+
+asmlinkage long sys32_times(struct tms32 *tbuf)
+{
+	struct tms t;
+	long ret;
+	mm_segment_t old_fs = get_fs ();
+	int err;
+	
+	set_fs (KERNEL_DS);
+	ret = sys_times(tbuf ? &t : NULL);
+	set_fs (old_fs);
+	if (tbuf) {
+		err = put_user (t.tms_utime, &tbuf->tms_utime);
+		err |= __put_user (t.tms_stime, &tbuf->tms_stime);
+		err |= __put_user (t.tms_cutime, &tbuf->tms_cutime);
+		err |= __put_user (t.tms_cstime, &tbuf->tms_cstime);
+		if (err)
+			ret = -EFAULT;
+	}
+	return ret;
+}
+
+#define RLIM_INFINITY32	0x7fffffff
+#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)
+
+struct rlimit32 {
+	u32	rlim_cur;
+	u32	rlim_max;
+};
+
+extern asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim);
+
+asmlinkage int sys32_old_getrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit r;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+	
+	set_fs (KERNEL_DS);
+	ret = sys_old_getrlimit(resource, &r);
+	set_fs (old_fs);
+	if (!ret) {
+		ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);
+		ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);
+	}
+	return ret;
+}
+
+extern asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim);
+
+asmlinkage int sys32_setrlimit(unsigned int resource, struct rlimit32 *rlim)
+{
+	struct rlimit r;
+	int ret;
+	mm_segment_t old_fs = get_fs ();
+
+	if (resource >= RLIM_NLIMITS) return -EINVAL;	
+	if (get_user (r.rlim_cur, &rlim->rlim_cur) ||
+	    __get_user (r.rlim_max, &rlim->rlim_max))
+		return -EFAULT;
+	if (r.rlim_cur == RLIM_INFINITY32)
+		r.rlim_cur = RLIM_INFINITY;
+	if (r.rlim_max == RLIM_INFINITY32)
+		r.rlim_max = RLIM_INFINITY;
+	set_fs (KERNEL_DS);
+	ret = sys_setrlimit(resource, &r);
+	set_fs (old_fs);
+	return ret;
+}
+
+extern asmlinkage int sys_getrusage(int who, struct rusage *ru);
+
+asmlinkage int sys32_getrusage(int who, struct rusage32 *ru)
+{
+	struct rusage r;
+	int ret;
+	mm_segment_t old_fs = get_fs();
+		
+	set_fs (KERNEL_DS);
+	ret = sys_getrusage(who, &r);
+	set_fs (old_fs);
+	if (put_rusage (ru, &r)) return -EFAULT;
+	return ret;
+}
+
+/* XXX This really belongs in some header file... -DaveM */
+#define MAX_SOCK_ADDR	128		/* 108 for Unix domain - 
+					   16 for IP, 16 for IPX,
+					   24 for IPv6,
+					   about 80 for AX.25 */
+
+extern struct socket *sockfd_lookup(int fd, int *err);
+
+/* XXX This as well... */
+extern __inline__ void sockfd_put(struct socket *sock)
+{
+	fput(sock->file);
+}
+
+struct msghdr32 {
+        u32               msg_name;
+        int               msg_namelen;
+        u32               msg_iov;
+        __kernel_size_t32 msg_iovlen;
+        u32               msg_control;
+        __kernel_size_t32 msg_controllen;
+        unsigned          msg_flags;
+};
+
+struct cmsghdr32 {
+        __kernel_size_t32 cmsg_len;
+        int               cmsg_level;
+        int               cmsg_type;
+};
+
+/* Bleech... */
+#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))
+#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))
+
+#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )
+
+#define CMSG32_DATA(cmsg)	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))
+#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))
+#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))
+
+#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \
+				    (struct cmsghdr32 *)(ctl) : \
+				    (struct cmsghdr32 *)NULL)
+#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
+
+__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size,
+					      struct cmsghdr32 *__cmsg, int __cmsg_len)
+{
+	struct cmsghdr32 * __ptr;
+
+	__ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) +
+				     CMSG32_ALIGN(__cmsg_len));
+	if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
+		return NULL;
+
+	return __ptr;
+}
+
+__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg,
+					    struct cmsghdr32 *__cmsg,
+					    int __cmsg_len)
+{
+	return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen,
+			       __cmsg, __cmsg_len);
+}
+
+static inline int iov_from_user32_to_kern(struct iovec *kiov,
+					  struct iovec32 *uiov32,
+					  int niov)
+{
+	int tot_len = 0;
+
+	while(niov > 0) {
+		u32 len, buf;
+
+		if(get_user(len, &uiov32->iov_len) ||
+		   get_user(buf, &uiov32->iov_base)) {
+			tot_len = -EFAULT;
+			break;
+		}
+		tot_len += len;
+		kiov->iov_base = (void *)A(buf);
+		kiov->iov_len = (__kernel_size_t) len;
+		uiov32++;
+		kiov++;
+		niov--;
+	}
+	return tot_len;
+}
+
+static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg,
+					     struct msghdr32 *umsg)
+{
+	u32 tmp1, tmp2, tmp3;
+	int err;
+
+	err = get_user(tmp1, &umsg->msg_name);
+	err |= __get_user(tmp2, &umsg->msg_iov);
+	err |= __get_user(tmp3, &umsg->msg_control);
+	if (err)
+		return -EFAULT;
+
+	kmsg->msg_name = (void *)A(tmp1);
+	kmsg->msg_iov = (struct iovec *)A(tmp2);
+	kmsg->msg_control = (void *)A(tmp3);
+
+	err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
+	err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
+	err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen);
+	err |= get_user(kmsg->msg_flags, &umsg->msg_flags);
+	
+	return err;
+}
+
+/* I've named the args so it is easy to tell whose space the pointers are in. */
+static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov,
+			  char *kern_address, int mode)
+{
+	int tot_len;
+
+	if(kern_msg->msg_namelen) {
+		if(mode==VERIFY_READ) {
+			int err = move_addr_to_kernel(kern_msg->msg_name,
+						      kern_msg->msg_namelen,
+						      kern_address);
+			if(err < 0)
+				return err;
+		}
+		kern_msg->msg_name = kern_address;
+	} else
+		kern_msg->msg_name = NULL;
+
+	if(kern_msg->msg_iovlen > UIO_FASTIOV) {
+		kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec),
+				   GFP_KERNEL);
+		if(!kern_iov)
+			return -ENOMEM;
+	}
+
+	tot_len = iov_from_user32_to_kern(kern_iov,
+					  (struct iovec32 *)kern_msg->msg_iov,
+					  kern_msg->msg_iovlen);
+	if(tot_len >= 0)
+		kern_msg->msg_iov = kern_iov;
+	else if(kern_msg->msg_iovlen > UIO_FASTIOV)
+		kfree(kern_iov);
+
+	return tot_len;
+}
+
+/* There is a lot of hair here because the alignment rules (and
+ * thus placement) of cmsg headers and length are different for
+ * 32-bit apps.  -DaveM
+ */
+static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg,
+				       unsigned char *stackbuf, int stackbuf_size)
+{
+	struct cmsghdr32 *ucmsg;
+	struct cmsghdr *kcmsg, *kcmsg_base;
+	__kernel_size_t32 ucmlen;
+	__kernel_size_t kcmlen, tmp;
+
+	kcmlen = 0;
+	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
+	ucmsg = CMSG32_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		if(get_user(ucmlen, &ucmsg->cmsg_len))
+			return -EFAULT;
+
+		/* Catch bogons. */
+		if(CMSG32_ALIGN(ucmlen) <
+		   CMSG32_ALIGN(sizeof(struct cmsghdr32)))
+			return -EINVAL;
+		if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control)
+				   + ucmlen) > kmsg->msg_controllen)
+			return -EINVAL;
+
+		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmlen += tmp;
+		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+	if(kcmlen == 0)
+		return -EINVAL;
+
+	/* The kcmlen holds the 64-bit version of the control length.
+	 * It may not be modified as we do not stick it into the kmsg
+	 * until we have successfully copied over all of the data
+	 * from the user.
+	 */
+	if(kcmlen > stackbuf_size)
+		kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL);
+	if(kcmsg == NULL)
+		return -ENOBUFS;
+
+	/* Now copy them over neatly. */
+	memset(kcmsg, 0, kcmlen);
+	ucmsg = CMSG32_FIRSTHDR(kmsg);
+	while(ucmsg != NULL) {
+		__get_user(ucmlen, &ucmsg->cmsg_len);
+		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +
+		       CMSG_ALIGN(sizeof(struct cmsghdr)));
+		kcmsg->cmsg_len = tmp;
+		__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);
+
+		/* Copy over the data. */
+		if(copy_from_user(CMSG_DATA(kcmsg),
+				  CMSG32_DATA(ucmsg),
+				  (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg)))))
+			goto out_free_efault;
+
+		/* Advance. */
+		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));
+		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);
+	}
+
+	/* Ok, looks like we made it.  Hook it up and return success. */
+	kmsg->msg_control = kcmsg_base;
+	kmsg->msg_controllen = kcmlen;
+	return 0;
+
+out_free_efault:
+	if(kcmsg_base != (struct cmsghdr *)stackbuf)
+		kfree(kcmsg_base);
+	return -EFAULT;
+}
+
+static void put_cmsg32(struct msghdr *kmsg, int level, int type,
+		       int len, void *data)
+{
+	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+	struct cmsghdr32 cmhdr;
+	int cmlen = CMSG32_LEN(len);
+
+	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		return;
+	}
+
+	if(kmsg->msg_controllen < cmlen) {
+		kmsg->msg_flags |= MSG_CTRUNC;
+		cmlen = kmsg->msg_controllen;
+	}
+	cmhdr.cmsg_level = level;
+	cmhdr.cmsg_type = type;
+	cmhdr.cmsg_len = cmlen;
+
+	if(copy_to_user(cm, &cmhdr, sizeof cmhdr))
+		return;
+	if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32)))
+		return;
+	cmlen = CMSG32_SPACE(len);
+	kmsg->msg_control += cmlen;
+	kmsg->msg_controllen -= cmlen;
+}
+
+static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm)
+{
+	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;
+	int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int);
+	int fdnum = scm->fp->count;
+	struct file **fp = scm->fp->fp;
+	int *cmfptr;
+	int err = 0, i;
+
+	if (fdnum < fdmax)
+		fdmax = fdnum;
+
+	for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) {
+		int new_fd;
+		err = get_unused_fd();
+		if (err < 0)
+			break;
+		new_fd = err;
+		err = put_user(new_fd, cmfptr);
+		if (err) {
+			put_unused_fd(new_fd);
+			break;
+		}
+		/* Bump the usage count and install the file. */
+		get_file(fp[i]);
+		fd_install(new_fd, fp[i]);
+	}
+
+	if (i > 0) {
+		int cmlen = CMSG32_LEN(i * sizeof(int));
+		if (!err)
+			err = put_user(SOL_SOCKET, &cm->cmsg_level);
+		if (!err)
+			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
+		if (!err)
+			err = put_user(cmlen, &cm->cmsg_len);
+		if (!err) {
+			cmlen = CMSG32_SPACE(i * sizeof(int));
+			kmsg->msg_control += cmlen;
+			kmsg->msg_controllen -= cmlen;
+		}
+	}
+	if (i < fdnum)
+		kmsg->msg_flags |= MSG_CTRUNC;
+
+	/*
+	 * All of the files that fit in the message have had their
+	 * usage counts incremented, so we just free the list.
+	 */
+	__scm_destroy(scm);
+}
+
+/* In these cases we (currently) can just copy to data over verbatim
+ * because all CMSGs created by the kernel have well defined types which
+ * have the same layout in both the 32-bit and 64-bit API.  One must add
+ * some special cased conversions here if we start sending control messages
+ * with incompatible types.
+ *
+ * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after
+ * we do our work.  The remaining cases are:
+ *
+ * SOL_IP	IP_PKTINFO	struct in_pktinfo	32-bit clean
+ *		IP_TTL		int			32-bit clean
+ *		IP_TOS		__u8			32-bit clean
+ *		IP_RECVOPTS	variable length		32-bit clean
+ *		IP_RETOPTS	variable length		32-bit clean
+ *		(these last two are clean because the types are defined
+ *		 by the IPv4 protocol)
+ *		IP_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in	32-bit clean
+ * SOL_IPV6	IPV6_RECVERR	struct sock_extended_err +
+ *				struct sockaddr_in6	32-bit clean
+ *		IPV6_PKTINFO	struct in6_pktinfo	32-bit clean
+ *		IPV6_HOPLIMIT	int			32-bit clean
+ *		IPV6_FLOWINFO	u32			32-bit clean
+ *		IPV6_HOPOPTS	ipv6 hop exthdr		32-bit clean
+ *		IPV6_DSTOPTS	ipv6 dst exthdr(s)	32-bit clean
+ *		IPV6_RTHDR	ipv6 routing exthdr	32-bit clean
+ *		IPV6_AUTHHDR	ipv6 auth exthdr	32-bit clean
+ */
+static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr)
+{
+	unsigned char *workbuf, *wp;
+	unsigned long bufsz, space_avail;
+	struct cmsghdr *ucmsg;
+
+	bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr;
+	space_avail = kmsg->msg_controllen + bufsz;
+	wp = workbuf = kmalloc(bufsz, GFP_KERNEL);
+	if(workbuf == NULL)
+		goto fail;
+
+	/* To make this more sane we assume the kernel sends back properly
+	 * formatted control messages.  Because of how the kernel will truncate
+	 * the cmsg_len for MSG_TRUNC cases, we need not check that case either.
+	 */
+	ucmsg = (struct cmsghdr *) orig_cmsg_uptr;
+	while(((unsigned long)ucmsg) <=
+	      (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) {
+		struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp;
+		int clen64, clen32;
+
+		/* UCMSG is the 64-bit format CMSG entry in user-space.
+		 * KCMSG32 is within the kernel space temporary buffer
+		 * we use to convert into a 32-bit style CMSG.
+		 */
+		__get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len);
+		__get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level);
+		__get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type);
+
+		clen64 = kcmsg32->cmsg_len;
+		copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg),
+			       clen64 - CMSG_ALIGN(sizeof(*ucmsg)));
+		clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) +
+			  CMSG32_ALIGN(sizeof(struct cmsghdr32)));
+		kcmsg32->cmsg_len = clen32;
+
+		ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64));
+		wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32));
+	}
+
+	/* Copy back fixed up data, and adjust pointers. */
+	bufsz = (wp - workbuf);
+	copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz);
+
+	kmsg->msg_control = (struct cmsghdr *)
+		(((char *)orig_cmsg_uptr) + bufsz);
+	kmsg->msg_controllen = space_avail - bufsz;
+
+	kfree(workbuf);
+	return;
+
+fail:
+	/* If we leave the 64-bit format CMSG chunks in there,
+	 * the application could get confused and crash.  So to
+	 * ensure greater recovery, we report no CMSGs.
+	 */
+	kmsg->msg_controllen += bufsz;
+	kmsg->msg_control = (void *) orig_cmsg_uptr;
+}
+
+asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags)
+{
+	struct socket *sock;
+	char address[MAX_SOCK_ADDR];
+	struct iovec iov[UIO_FASTIOV];
+	unsigned char ctl[sizeof(struct cmsghdr) + 20];
+	unsigned char *ctl_buf = ctl;
+	struct msghdr kern_msg;
+	int err, total_len;
+
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+		return -EFAULT;
+	if(kern_msg.msg_iovlen > UIO_MAXIOV)
+		return -EINVAL;
+	err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ);
+	if (err < 0)
+		goto out;
+	total_len = err;
+
+	if(kern_msg.msg_controllen) {
+		err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl));
+		if(err)
+			goto out_freeiov;
+		ctl_buf = kern_msg.msg_control;
+	}
+	kern_msg.msg_flags = user_flags;
+
+	sock = sockfd_lookup(fd, &err);
+	if (sock != NULL) {
+		if (sock->file->f_flags & O_NONBLOCK)
+			kern_msg.msg_flags |= MSG_DONTWAIT;
+		err = sock_sendmsg(sock, &kern_msg, total_len);
+		sockfd_put(sock);
+	}
+
+	/* N.B. Use kfree here, as kern_msg.msg_controllen might change? */
+	if(ctl_buf != ctl)
+		kfree(ctl_buf);
+out_freeiov:
+	if(kern_msg.msg_iov != iov)
+		kfree(kern_msg.msg_iov);
+out:
+	return err;
+}
+
+asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags)
+{
+	struct iovec iovstack[UIO_FASTIOV];
+	struct msghdr kern_msg;
+	char addr[MAX_SOCK_ADDR];
+	struct socket *sock;
+	struct iovec *iov = iovstack;
+	struct sockaddr *uaddr;
+	int *uaddr_len;
+	unsigned long cmsg_ptr;
+	int err, total_len, len = 0;
+
+	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))
+		return -EFAULT;
+	if(kern_msg.msg_iovlen > UIO_MAXIOV)
+		return -EINVAL;
+
+	uaddr = kern_msg.msg_name;
+	uaddr_len = &user_msg->msg_namelen;
+	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);
+	if (err < 0)
+		goto out;
+	total_len = err;
+
+	cmsg_ptr = (unsigned long) kern_msg.msg_control;
+	kern_msg.msg_flags = 0;
+
+	sock = sockfd_lookup(fd, &err);
+	if (sock != NULL) {
+		struct scm_cookie scm;
+
+		if (sock->file->f_flags & O_NONBLOCK)
+			user_flags |= MSG_DONTWAIT;
+		memset(&scm, 0, sizeof(scm));
+		err = sock->ops->recvmsg(sock, &kern_msg, total_len,
+					 user_flags, &scm);
+		if(err >= 0) {
+			len = err;
+			if(!kern_msg.msg_control) {
+				if(sock->passcred || scm.fp)
+					kern_msg.msg_flags |= MSG_CTRUNC;
+				if(scm.fp)
+					__scm_destroy(&scm);
+			} else {
+				/* If recvmsg processing itself placed some
+				 * control messages into user space, it's is
+				 * using 64-bit CMSG processing, so we need
+				 * to fix it up before we tack on more stuff.
+				 */
+				if((unsigned long) kern_msg.msg_control != cmsg_ptr)
+					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);
+
+				/* Wheee... */
+				if(sock->passcred)
+					put_cmsg32(&kern_msg,
+						   SOL_SOCKET, SCM_CREDENTIALS,
+						   sizeof(scm.creds), &scm.creds);
+				if(scm.fp != NULL)
+					scm_detach_fds32(&kern_msg, &scm);
+			}
+		}
+		sockfd_put(sock);
+	}
+
+	if(uaddr != NULL && err >= 0)
+		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);
+	if(cmsg_ptr != 0 && err >= 0) {
+		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);
+		__kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);
+		err |= __put_user(uclen, &user_msg->msg_controllen);
+	}
+	if(err >= 0)
+		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);
+	if(kern_msg.msg_iov != iov)
+		kfree(kern_msg.msg_iov);
+out:
+	if(err < 0)
+		return err;
+	return len;
+}
+
+extern asmlinkage int sys_setsockopt(int fd, int level, int optname,
+				     char *optval, int optlen);
+
+static int do_set_attach_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct sock_fprog32 {
+		__u16 len;
+		__u32 filter;
+	} *fprog32 = (struct sock_fprog32 *)optval;
+	struct sock_fprog kfprog;
+	struct sock_filter *kfilter;
+	unsigned int fsize;
+	mm_segment_t old_fs;
+	__u32 uptr;
+	int ret;
+
+	if (get_user(kfprog.len, &fprog32->len) ||
+	    __get_user(uptr, &fprog32->filter))
+		return -EFAULT;
+
+	kfprog.filter = (struct sock_filter *)A(uptr);
+	fsize = kfprog.len * sizeof(struct sock_filter);
+
+	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
+	if (kfilter == NULL)
+		return -ENOMEM;
+
+	if (copy_from_user(kfilter, kfprog.filter, fsize)) {
+		kfree(kfilter);
+		return -EFAULT;
+	}
+
+	kfprog.filter = kfilter;
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *)&kfprog, sizeof(kfprog));
+	set_fs(old_fs);
+
+	kfree(kfilter);
+
+	return ret;
+}
+
+static int do_set_icmpv6_filter(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	struct icmp6_filter kfilter;
+	mm_segment_t old_fs;
+	int ret, i;
+
+	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))
+		return -EFAULT;
+
+
+	for (i = 0; i < 8; i += 2) {
+		u32 tmp = kfilter.data[i];
+
+		kfilter.data[i] = kfilter.data[i + 1];
+		kfilter.data[i + 1] = tmp;
+	}
+
+	old_fs = get_fs();
+	set_fs(KERNEL_DS);
+	ret = sys_setsockopt(fd, level, optname,
+			     (char *) &kfilter, sizeof(kfilter));
+	set_fs(old_fs);
+
+	return ret;
+}
+
+asmlinkage int sys32_setsockopt(int fd, int level, int optname,
+				char *optval, int optlen)
+{
+	if (optname == SO_ATTACH_FILTER)
+		return do_set_attach_filter(fd, level, optname,
+					    optval, optlen);
+	if (level == SOL_ICMPV6 && optname == ICMPV6_FILTER)
+		return do_set_icmpv6_filter(fd, level, optname,
+					    optval, optlen);
+
+	return sys_setsockopt(fd, level, optname, optval, optlen);
+}
+
+extern void check_pending(int signum);
+
+/*
+ * count32() counts the number of arguments/envelopes
+ */
+static int count32(u32 * argv)
+{
+	int i = 0;
+
+	if (argv != NULL) {
+		for (;;) {
+			u32 p; int error;
+
+			error = get_user(p,argv);
+			if (error) return error;
+			if (!p) break;
+			argv++; i++;
+		}
+	}
+	return i;
+}
+
+/*
+ * 'copy_string32()' copies argument/envelope strings from user
+ * memory to free pages in kernel mem. These are in a format ready
+ * to be put directly into the top of new user memory.
+ */
+static int copy_strings32(int argc, u32 * argv, struct linux_binprm *bprm)
+{
+	while (argc-- > 0) {
+		u32 str;
+		int len;
+		unsigned long pos;
+
+		if (get_user(str, argv + argc) ||
+		    !str ||
+		    !(len = strnlen_user((char *)A(str), bprm->p)))
+			return -EFAULT;
+
+		if (bprm->p < len)
+			return -E2BIG;
+
+		bprm->p -= len;
+
+		pos = bprm->p;
+		while (len) {
+			char *kaddr;
+			struct page *page;
+			int offset, bytes_to_copy, new, err;
+
+			offset = pos % PAGE_SIZE;
+			page = bprm->page[pos / PAGE_SIZE];
+			new = 0;
+			if (!page) {
+				page = alloc_page(GFP_USER);
+				bprm->page[pos / PAGE_SIZE] = page;
+				if (!page)
+					return -ENOMEM;
+				new = 1;
+			}
+			kaddr = (char *)kmap(page);
+
+			if (new && offset)
+				memset(kaddr, 0, offset);
+			bytes_to_copy = PAGE_SIZE - offset;
+			if (bytes_to_copy > len) {
+				bytes_to_copy = len;
+				if (new)
+					memset(kaddr+offset+len, 0,
+					       PAGE_SIZE-offset-len);
+			}
+
+			err = copy_from_user(kaddr + offset, (char *)A(str),
+					     bytes_to_copy);
+			flush_page_to_ram(page);
+			kunmap((unsigned long)kaddr);
+
+			if (err)
+				return -EFAULT;
+
+			pos += bytes_to_copy;
+			str += bytes_to_copy;
+			len -= bytes_to_copy;
+		}
+	}
+	return 0;
+}
+
+/*
+ * sys32_execve() executes a new program.
+ */
+static inline int 
+do_execve32(char * filename, u32 * argv, u32 * envp, struct pt_regs * regs)
+{
+	struct linux_binprm bprm;
+	struct file * file;
+	int retval;
+	int i;
+
+	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+	memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0]));
+
+	file = open_exec(filename);
+
+	retval = PTR_ERR(file);
+	if (IS_ERR(file))
+		return retval;
+
+	bprm.file = file;
+	bprm.filename = filename;
+	bprm.sh_bang = 0;
+	bprm.loader = 0;
+	bprm.exec = 0;
+	if ((bprm.argc = count32(argv)) < 0) {
+		allow_write_access(file);
+		fput(file);
+		return bprm.argc;
+	}
+	if ((bprm.envc = count32(envp)) < 0) {
+		allow_write_access(file);
+		fput(file);
+		return bprm.envc;
+	}
+
+	retval = prepare_binprm(&bprm);
+	if (retval < 0)
+		goto out;
+	
+	retval = copy_strings_kernel(1, &bprm.filename, &bprm);
+	if (retval < 0)
+		goto out;
+
+	bprm.exec = bprm.p;
+	retval = copy_strings32(bprm.envc, envp, &bprm);
+	if (retval < 0)
+		goto out;
+
+	retval = copy_strings32(bprm.argc, argv, &bprm);
+	if (retval < 0)
+		goto out;
+
+	retval = search_binary_handler(&bprm, regs);
+	if (retval >= 0)
+		/* execve success */
+		return retval;
+
+out:
+	/* Something went wrong, return the inode and free the argument pages*/
+	allow_write_access(bprm.file);
+	if (bprm.file)
+		fput(bprm.file);
+
+	for (i=0 ; i<MAX_ARG_PAGES ; i++)
+		if (bprm.page[i])
+			__free_page(bprm.page[i]);
+
+	return retval;
+}
+
+/*
+ * sys32_execve() executes a new program after the asm stub has set
+ * things up for us.  This should basically do what I want it to.
+ */
+asmlinkage int
+sys32_execve(struct pt_regs regs)
+{
+        int error;
+        char * filename;
+
+        filename = getname((char *)A(regs.orig_gpr2));
+        error = PTR_ERR(filename);
+        if (IS_ERR(filename))
+                goto out;
+        error = do_execve32(filename, (u32 *)A(regs.gprs[3]), (u32 *)A(regs.gprs[4]), &regs);
+	if (error == 0)
+	{
+		current->ptrace &= ~PT_DTRACE;
+		current->thread.fp_regs.fpc=0;
+		__asm__ __volatile__
+		        ("sr  0,0\n\t"
+		         "sfpc 0,0\n\t"
+			 : : :"0");
+	}
+        putname(filename);
+out:
+        return error;
+}
+
+
+#ifdef CONFIG_MODULES
+
+extern asmlinkage unsigned long sys_create_module(const char *name_user, size_t size);
+
+asmlinkage unsigned long sys32_create_module(const char *name_user, __kernel_size_t32 size)
+{
+	return sys_create_module(name_user, (size_t)size);
+}
+
+extern asmlinkage int sys_init_module(const char *name_user, struct module *mod_user);
+
+/* Hey, when you're trying to init module, take time and prepare us a nice 64bit
+ * module structure, even if from 32bit modutils... Why to pollute kernel... :))
+ */
+asmlinkage int sys32_init_module(const char *name_user, struct module *mod_user)
+{
+	return sys_init_module(name_user, mod_user);
+}
+
+extern asmlinkage int sys_delete_module(const char *name_user);
+
+asmlinkage int sys32_delete_module(const char *name_user)
+{
+	return sys_delete_module(name_user);
+}
+
+struct module_info32 {
+	u32 addr;
+	u32 size;
+	u32 flags;
+	s32 usecount;
+};
+
+/* Query various bits about modules.  */
+
+static inline long
+get_mod_name(const char *user_name, char **buf)
+{
+	unsigned long page;
+	long retval;
+
+	if ((unsigned long)user_name >= TASK_SIZE
+	    && !segment_eq(get_fs (), KERNEL_DS))
+		return -EFAULT;
+
+	page = __get_free_page(GFP_KERNEL);
+	if (!page)
+		return -ENOMEM;
+
+	retval = strncpy_from_user((char *)page, user_name, PAGE_SIZE);
+	if (retval > 0) {
+		if (retval < PAGE_SIZE) {
+			*buf = (char *)page;
+			return retval;
+		}
+		retval = -ENAMETOOLONG;
+	} else if (!retval)
+		retval = -EINVAL;
+
+	free_page(page);
+	return retval;
+}
+
+static inline void
+put_mod_name(char *buf)
+{
+	free_page((unsigned long)buf);
+}
+
+static __inline__ struct module *find_module(const char *name)
+{
+	struct module *mod;
+
+	for (mod = module_list; mod ; mod = mod->next) {
+		if (mod->flags & MOD_DELETED)
+			continue;
+		if (!strcmp(mod->name, name))
+			break;
+	}
+
+	return mod;
+}
+
+static int
+qm_modules(char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	struct module *mod;
+	size_t nmod, space, len;
+
+	nmod = space = 0;
+
+	for (mod = module_list; mod->next != NULL; mod = mod->next, ++nmod) {
+		len = strlen(mod->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, mod->name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nmod, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((mod = mod->next)->next != NULL)
+		space += strlen(mod->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_deps(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+	if (!MOD_CAN_QUERY(mod))
+		return put_user(0, ret);
+
+	space = 0;
+	for (i = 0; i < mod->ndeps; ++i) {
+		const char *dep_name = mod->deps[i].dep->name;
+
+		len = strlen(dep_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, dep_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	return put_user(i, ret);
+
+calc_space_needed:
+	space += len;
+	while (++i < mod->ndeps)
+		space += strlen(mod->deps[i].dep->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static int
+qm_refs(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t nrefs, space, len;
+	struct module_ref *ref;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+	if (!MOD_CAN_QUERY(mod))
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = 0;
+	for (nrefs = 0, ref = mod->refs; ref ; ++nrefs, ref = ref->next_ref) {
+		const char *ref_name = ref->ref->name;
+
+		len = strlen(ref_name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+		if (copy_to_user(buf, ref_name, len))
+			return -EFAULT;
+		buf += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(nrefs, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	space += len;
+	while ((ref = ref->next_ref) != NULL)
+		space += strlen(ref->ref->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_symbols(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	size_t i, space, len;
+	struct module_symbol *s;
+	char *strings;
+	unsigned *vals;
+
+	if (!MOD_CAN_QUERY(mod))
+		if (put_user(0, ret))
+			return -EFAULT;
+		else
+			return 0;
+
+	space = mod->nsyms * 2*sizeof(u32);
+
+	i = len = 0;
+	s = mod->syms;
+
+	if (space > bufsize)
+		goto calc_space_needed;
+
+	if (!access_ok(VERIFY_WRITE, buf, space))
+		return -EFAULT;
+
+	bufsize -= space;
+	vals = (unsigned *)buf;
+	strings = buf+space;
+
+	for (; i < mod->nsyms ; ++i, ++s, vals += 2) {
+		len = strlen(s->name)+1;
+		if (len > bufsize)
+			goto calc_space_needed;
+
+		if (copy_to_user(strings, s->name, len)
+		    || __put_user(s->value, vals+0)
+		    || __put_user(space, vals+1))
+			return -EFAULT;
+
+		strings += len;
+		bufsize -= len;
+		space += len;
+	}
+
+	if (put_user(i, ret))
+		return -EFAULT;
+	else
+		return 0;
+
+calc_space_needed:
+	for (; i < mod->nsyms; ++i, ++s)
+		space += strlen(s->name)+1;
+
+	if (put_user(space, ret))
+		return -EFAULT;
+	else
+		return -ENOSPC;
+}
+
+static inline int
+qm_info(struct module *mod, char *buf, size_t bufsize, __kernel_size_t32 *ret)
+{
+	int error = 0;
+
+	if (mod->next == NULL)
+		return -EINVAL;
+
+	if (sizeof(struct module_info32) <= bufsize) {
+		struct module_info32 info;
+		info.addr = (unsigned long)mod;
+		info.size = mod->size;
+		info.flags = mod->flags;
+		info.usecount =
+			((mod_member_present(mod, can_unload)
+			  && mod->can_unload)
+			 ? -1 : atomic_read(&mod->uc.usecount));
+
+		if (copy_to_user(buf, &info, sizeof(struct module_info32)))
+			return -EFAULT;
+	} else
+		error = -ENOSPC;
+
+	if (put_user(sizeof(struct module_info32), ret))
+		return -EFAULT;
+
+	return error;
+}
+
+asmlinkage int sys32_query_module(char *name_user, int which, char *buf, __kernel_size_t32 bufsize, u32 ret)
+{
+	struct module *mod;
+	int err;
+
+	lock_kernel();
+	if (name_user == 0) {
+		/* This finds "kernel_module" which is not exported. */
+		for(mod = module_list; mod->next != NULL; mod = mod->next)
+			;
+	} else {
+		long namelen;
+		char *name;
+
+		if ((namelen = get_mod_name(name_user, &name)) < 0) {
+			err = namelen;
+			goto out;
+		}
+		err = -ENOENT;
+		if (namelen == 0) {
+			/* This finds "kernel_module" which is not exported. */
+			for(mod = module_list; mod->next != NULL; mod = mod->next)
+				;
+		} else if ((mod = find_module(name)) == NULL) {
+			put_mod_name(name);
+			goto out;
+		}
+		put_mod_name(name);
+	}
+
+	switch (which)
+	{
+	case 0:
+		err = 0;
+		break;
+	case QM_MODULES:
+		err = qm_modules(buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_DEPS:
+		err = qm_deps(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_REFS:
+		err = qm_refs(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_SYMBOLS:
+		err = qm_symbols(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	case QM_INFO:
+		err = qm_info(mod, buf, bufsize, (__kernel_size_t32 *)AA(ret));
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+out:
+	unlock_kernel();
+	return err;
+}
+
+struct kernel_sym32 {
+	u32 value;
+	char name[60];
+};
+		 
+extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);
+
+asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table)
+{
+	int len, i;
+	struct kernel_sym *tbl;
+	mm_segment_t old_fs;
+	
+	len = sys_get_kernel_syms(NULL);
+	if (!table) return len;
+	tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);
+	if (!tbl) return -ENOMEM;
+	old_fs = get_fs();
+	set_fs (KERNEL_DS);
+	sys_get_kernel_syms(tbl);
+	set_fs (old_fs);
+	for (i = 0; i < len; i++, table += sizeof (struct kernel_sym32)) {
+		if (put_user (tbl[i].value, &table->value) ||
+		    copy_to_user (table->name, tbl[i].name, 60))
+			break;
+	}
+	kfree (tbl);
+	return i;
+}
+
+#else /* CONFIG_MODULES */
+
+asmlinkage unsigned long
+sys32_create_module(const char *name_user, size_t size)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_init_module(const char *name_user, struct module *mod_user)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_delete_module(const char *name_user)
+{
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_query_module(const char *name_user, int which, char *buf, size_t bufsize,
+		 size_t *ret)
+{
+	/* Let the program know about the new interface.  Not that
+	   it'll do them much good.  */
+	if (which == 0)
+		return 0;
+
+	return -ENOSYS;
+}
+
+asmlinkage int
+sys32_get_kernel_syms(struct kernel_sym *table)
+{
+	return -ENOSYS;
+}
+
+#endif  /* CONFIG_MODULES */
+
+/* Stuff for NFS server syscalls... */
+struct nfsctl_svc32 {
+	u16			svc32_port;
+	s32			svc32_nthreads;
+};
+
+struct nfsctl_client32 {
+	s8			cl32_ident[NFSCLNT_IDMAX+1];
+	s32			cl32_naddr;
+	struct in_addr		cl32_addrlist[NFSCLNT_ADDRMAX];
+	s32			cl32_fhkeytype;
+	s32			cl32_fhkeylen;
+	u8			cl32_fhkey[NFSCLNT_KEYMAX];
+};
+
+struct nfsctl_export32 {
+	s8			ex32_client[NFSCLNT_IDMAX+1];
+	s8			ex32_path[NFS_MAXPATHLEN+1];
+	__kernel_dev_t32	ex32_dev;
+	__kernel_ino_t32	ex32_ino;
+	s32			ex32_flags;
+	__kernel_uid_t32	ex32_anon_uid;
+	__kernel_gid_t32	ex32_anon_gid;
+};
+
+struct nfsctl_uidmap32 {
+	u32			ug32_ident;   /* char * */
+	__kernel_uid_t32	ug32_uidbase;
+	s32			ug32_uidlen;
+	u32			ug32_udimap;  /* uid_t * */
+	__kernel_uid_t32	ug32_gidbase;
+	s32			ug32_gidlen;
+	u32			ug32_gdimap;  /* gid_t * */
+};
+
+struct nfsctl_fhparm32 {
+	struct sockaddr		gf32_addr;
+	__kernel_dev_t32	gf32_dev;
+	__kernel_ino_t32	gf32_ino;
+	s32			gf32_version;
+};
+
+struct nfsctl_fdparm32 {
+	struct sockaddr		gd32_addr;
+	s8			gd32_path[NFS_MAXPATHLEN+1];
+	s32			gd32_version;
+};
+
+struct nfsctl_fsparm32 {
+	struct sockaddr		gd32_addr;
+	s8			gd32_path[NFS_MAXPATHLEN+1];
+	s32			gd32_maxlen;
+};
+
+struct nfsctl_arg32 {
+	s32			ca32_version;	/* safeguard */
+	union {
+		struct nfsctl_svc32	u32_svc;
+		struct nfsctl_client32	u32_client;
+		struct nfsctl_export32	u32_export;
+		struct nfsctl_uidmap32	u32_umap;
+		struct nfsctl_fhparm32	u32_getfh;
+		struct nfsctl_fdparm32	u32_getfd;
+		struct nfsctl_fsparm32	u32_getfs;
+	} u;
+#define ca32_svc	u.u32_svc
+#define ca32_client	u.u32_client
+#define ca32_export	u.u32_export
+#define ca32_umap	u.u32_umap
+#define ca32_getfh	u.u32_getfh
+#define ca32_getfd	u.u32_getfd
+#define ca32_getfs	u.u32_getfs
+#define ca32_authd	u.u32_authd
+};
+
+union nfsctl_res32 {
+	__u8			cr32_getfh[NFS_FHSIZE];
+	struct knfsd_fh		cr32_getfs;
+};
+
+static int nfs_svc32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= __get_user(karg->ca_svc.svc_port, &arg32->ca32_svc.svc32_port);
+	err |= __get_user(karg->ca_svc.svc_nthreads, &arg32->ca32_svc.svc32_nthreads);
+	return err;
+}
+
+static int nfs_clnt32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_client.cl_ident[0],
+			  &arg32->ca32_client.cl32_ident[0],
+			  NFSCLNT_IDMAX);
+	err |= __get_user(karg->ca_client.cl_naddr, &arg32->ca32_client.cl32_naddr);
+	err |= copy_from_user(&karg->ca_client.cl_addrlist[0],
+			  &arg32->ca32_client.cl32_addrlist[0],
+			  (sizeof(struct in_addr) * NFSCLNT_ADDRMAX));
+	err |= __get_user(karg->ca_client.cl_fhkeytype,
+		      &arg32->ca32_client.cl32_fhkeytype);
+	err |= __get_user(karg->ca_client.cl_fhkeylen,
+		      &arg32->ca32_client.cl32_fhkeylen);
+	err |= copy_from_user(&karg->ca_client.cl_fhkey[0],
+			  &arg32->ca32_client.cl32_fhkey[0],
+			  NFSCLNT_KEYMAX);
+	return err;
+}
+
+static int nfs_exp32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_export.ex_client[0],
+			  &arg32->ca32_export.ex32_client[0],
+			  NFSCLNT_IDMAX);
+	err |= copy_from_user(&karg->ca_export.ex_path[0],
+			  &arg32->ca32_export.ex32_path[0],
+			  NFS_MAXPATHLEN);
+	err |= __get_user(karg->ca_export.ex_dev,
+		      &arg32->ca32_export.ex32_dev);
+	err |= __get_user(karg->ca_export.ex_ino,
+		      &arg32->ca32_export.ex32_ino);
+	err |= __get_user(karg->ca_export.ex_flags,
+		      &arg32->ca32_export.ex32_flags);
+	err |= __get_user(karg->ca_export.ex_anon_uid,
+		      &arg32->ca32_export.ex32_anon_uid);
+	err |= __get_user(karg->ca_export.ex_anon_gid,
+		      &arg32->ca32_export.ex32_anon_gid);
+	karg->ca_export.ex_anon_uid = high2lowuid(karg->ca_export.ex_anon_uid);
+	karg->ca_export.ex_anon_gid = high2lowgid(karg->ca_export.ex_anon_gid);
+	return err;
+}
+
+static int nfs_uud32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	u32 uaddr;
+	int i;
+	int err;
+
+	memset(karg, 0, sizeof(*karg));
+	if(__get_user(karg->ca_version, &arg32->ca32_version))
+		return -EFAULT;
+	karg->ca_umap.ug_ident = (char *)get_free_page(GFP_USER);
+	if(!karg->ca_umap.ug_ident)
+		return -ENOMEM;
+	err = __get_user(uaddr, &arg32->ca32_umap.ug32_ident);
+	if(strncpy_from_user(karg->ca_umap.ug_ident,
+			     (char *)A(uaddr), PAGE_SIZE) <= 0)
+		return -EFAULT;
+	err |= __get_user(karg->ca_umap.ug_uidbase,
+		      &arg32->ca32_umap.ug32_uidbase);
+	err |= __get_user(karg->ca_umap.ug_uidlen,
+		      &arg32->ca32_umap.ug32_uidlen);
+	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_udimap);
+	if (err)
+		return -EFAULT;
+	karg->ca_umap.ug_udimap = kmalloc((sizeof(uid_t) * karg->ca_umap.ug_uidlen),
+					  GFP_USER);
+	if(!karg->ca_umap.ug_udimap)
+		return -ENOMEM;
+	for(i = 0; i < karg->ca_umap.ug_uidlen; i++)
+		err |= __get_user(karg->ca_umap.ug_udimap[i],
+			      &(((__kernel_uid_t32 *)A(uaddr))[i]));
+	err |= __get_user(karg->ca_umap.ug_gidbase,
+		      &arg32->ca32_umap.ug32_gidbase);
+	err |= __get_user(karg->ca_umap.ug_uidlen,
+		      &arg32->ca32_umap.ug32_gidlen);
+	err |= __get_user(uaddr, &arg32->ca32_umap.ug32_gdimap);
+	if (err)
+		return -EFAULT;
+	karg->ca_umap.ug_gdimap = kmalloc((sizeof(gid_t) * karg->ca_umap.ug_uidlen),
+					  GFP_USER);
+	if(!karg->ca_umap.ug_gdimap)
+		return -ENOMEM;
+	for(i = 0; i < karg->ca_umap.ug_gidlen; i++)
+		err |= __get_user(karg->ca_umap.ug_gdimap[i],
+			      &(((__kernel_gid_t32 *)A(uaddr))[i]));
+
+	return err;
+}
+
+static int nfs_getfh32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_getfh.gf_addr,
+			  &arg32->ca32_getfh.gf32_addr,
+			  (sizeof(struct sockaddr)));
+	err |= __get_user(karg->ca_getfh.gf_dev,
+		      &arg32->ca32_getfh.gf32_dev);
+	err |= __get_user(karg->ca_getfh.gf_ino,
+		      &arg32->ca32_getfh.gf32_ino);
+	err |= __get_user(karg->ca_getfh.gf_version,
+		      &arg32->ca32_getfh.gf32_version);
+	return err;
+}
+
+static int nfs_getfd32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_getfd.gd_addr,
+			  &arg32->ca32_getfd.gd32_addr,
+			  (sizeof(struct sockaddr)));
+	err |= copy_from_user(&karg->ca_getfd.gd_path,
+			  &arg32->ca32_getfd.gd32_path,
+			  (NFS_MAXPATHLEN+1));
+	err |= __get_user(karg->ca_getfd.gd_version,
+		      &arg32->ca32_getfd.gd32_version);
+	return err;
+}
+
+static int nfs_getfs32_trans(struct nfsctl_arg *karg, struct nfsctl_arg32 *arg32)
+{
+	int err;
+	
+	err = __get_user(karg->ca_version, &arg32->ca32_version);
+	err |= copy_from_user(&karg->ca_getfs.gd_addr,
+			  &arg32->ca32_getfs.gd32_addr,
+			  (sizeof(struct sockaddr)));
+	err |= copy_from_user(&karg->ca_getfs.gd_path,
+			  &arg32->ca32_getfs.gd32_path,
+			  (NFS_MAXPATHLEN+1));
+	err |= __get_user(karg->ca_getfs.gd_maxlen,
+		      &arg32->ca32_getfs.gd32_maxlen);
+	return err;
+}
+
+/* This really doesn't need translations, we are only passing
+ * back a union which contains opaque nfs file handle data.
+ */
+static int nfs_getfh32_res_trans(union nfsctl_res *kres, union nfsctl_res32 *res32)
+{
+	return copy_to_user(res32, kres, sizeof(*res32));
+}
+
+/*
+asmlinkage long sys_ni_syscall(void); 
+*/
+
+int asmlinkage sys32_nfsservctl(int cmd, struct nfsctl_arg32 *arg32, union nfsctl_res32 *res32)
+{
+	struct nfsctl_arg *karg = NULL;
+	union nfsctl_res *kres = NULL;
+	mm_segment_t oldfs;
+	int err;
+
+	karg = kmalloc(sizeof(*karg), GFP_USER);
+	if(!karg)
+		return -ENOMEM;
+	if(res32) {
+		kres = kmalloc(sizeof(*kres), GFP_USER);
+		if(!kres) {
+			kfree(karg);
+			return -ENOMEM;
+		}
+	}
+	switch(cmd) {
+	case NFSCTL_SVC:
+		err = nfs_svc32_trans(karg, arg32);
+		break;
+	case NFSCTL_ADDCLIENT:
+		err = nfs_clnt32_trans(karg, arg32);
+		break;
+	case NFSCTL_DELCLIENT:
+		err = nfs_clnt32_trans(karg, arg32);
+		break;
+	case NFSCTL_EXPORT:
+	case NFSCTL_UNEXPORT:
+		err = nfs_exp32_trans(karg, arg32);
+		break;
+	/* This one is unimplemented, be we're ready for it. */
+	case NFSCTL_UGIDUPDATE:
+		err = nfs_uud32_trans(karg, arg32);
+		break;
+	case NFSCTL_GETFH:
+		err = nfs_getfh32_trans(karg, arg32);
+		break;
+	case NFSCTL_GETFD:
+		err = nfs_getfd32_trans(karg, arg32);
+		break;
+	case NFSCTL_GETFS:
+		err = nfs_getfs32_trans(karg, arg32);
+		break;
+	default:
+		err = -EINVAL;
+		break;
+	}
+	if(err)
+		goto done;
+	oldfs = get_fs();
+	set_fs(KERNEL_DS);
+	err = sys_nfsservctl(cmd, karg, kres);
+	set_fs(oldfs);
+
+	if (err)
+		goto done;
+
+	if((cmd == NFSCTL_GETFH) ||
+	   (cmd == NFSCTL_GETFD) ||
+	   (cmd == NFSCTL_GETFS))
+		err = nfs_getfh32_res_trans(kres, res32);
+
+done:
+	if(karg) {
+		if(cmd == NFSCTL_UGIDUPDATE) {
+			if(karg->ca_umap.ug_ident)
+				kfree(karg->ca_umap.ug_ident);
+			if(karg->ca_umap.ug_udimap)
+				kfree(karg->ca_umap.ug_udimap);
+			if(karg->ca_umap.ug_gdimap)
+				kfree(karg->ca_umap.ug_gdimap);
+		}
+		kfree(karg);
+	}
+	if(kres)
+		kfree(kres);
+	return err;
+}
+
+/* Translations due to time_t size differences.  Which affects all
+   sorts of things, like timeval and itimerval.  */
+
+extern struct timezone sys_tz;
+extern int do_sys_settimeofday(struct timeval *tv, struct timezone *tz);
+
+asmlinkage int sys32_gettimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	if (tv) {
+		struct timeval ktv;
+		do_gettimeofday(&ktv);
+		if (put_tv32(tv, &ktv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))
+			return -EFAULT;
+	}
+	return 0;
+}
+
+asmlinkage int sys32_settimeofday(struct timeval32 *tv, struct timezone *tz)
+{
+	struct timeval ktv;
+	struct timezone ktz;
+
+ 	if (tv) {
+		if (get_tv32(&ktv, tv))
+			return -EFAULT;
+	}
+	if (tz) {
+		if (copy_from_user(&ktz, tz, sizeof(ktz)))
+			return -EFAULT;
+	}
+
+	return do_sys_settimeofday(tv ? &ktv : NULL, tz ? &ktz : NULL);
+}
+
+extern int do_getitimer(int which, struct itimerval *value);
+
+asmlinkage int sys32_getitimer(int which, struct itimerval32 *it)
+{
+	struct itimerval kit;
+	int error;
+
+	error = do_getitimer(which, &kit);
+	if (!error && put_it32(it, &kit))
+		error = -EFAULT;
+
+	return error;
+}
+
+extern int do_setitimer(int which, struct itimerval *, struct itimerval *);
+
+asmlinkage int sys32_setitimer(int which, struct itimerval32 *in, struct itimerval32 *out)
+{
+	struct itimerval kin, kout;
+	int error;
+
+	if (in) {
+		if (get_it32(&kin, in))
+			return -EFAULT;
+	} else
+		memset(&kin, 0, sizeof(kin));
+
+	error = do_setitimer(which, &kin, out ? &kout : NULL);
+	if (error || !out)
+		return error;
+	if (put_it32(out, &kout))
+		return -EFAULT;
+
+	return 0;
+
+}
+
+asmlinkage int sys_utimes(char *, struct timeval *);
+
+asmlinkage int sys32_utimes(char *filename, struct timeval32 *tvs)
+{
+	char *kfilename;
+	struct timeval ktvs[2];
+	mm_segment_t old_fs;
+	int ret;
+
+	kfilename = getname(filename);
+	ret = PTR_ERR(kfilename);
+	if (!IS_ERR(kfilename)) {
+		if (tvs) {
+			if (get_tv32(&ktvs[0], tvs) ||
+			    get_tv32(&ktvs[1], 1+tvs))
+				return -EFAULT;
+		}
+
+		old_fs = get_fs();
+		set_fs(KERNEL_DS);
+		ret = sys_utimes(kfilename, &ktvs[0]);
+		set_fs(old_fs);
+
+		putname(kfilename);
+	}
+	return ret;
+}
+
+/* These are here just in case some old sparc32 binary calls it. */
+asmlinkage int sys32_pause(void)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	return -ERESTARTNOHAND;
+}
+
+extern asmlinkage int sys_prctl(int option, unsigned long arg2, unsigned long arg3,
+				unsigned long arg4, unsigned long arg5);
+
+asmlinkage int sys32_prctl(int option, u32 arg2, u32 arg3, u32 arg4, u32 arg5)
+{
+	return sys_prctl(option,
+			 (unsigned long) arg2,
+			 (unsigned long) arg3,
+			 (unsigned long) arg4,
+			 (unsigned long) arg5);
+}
+
+
+extern asmlinkage ssize_t sys_pread(unsigned int fd, char * buf,
+				    size_t count, loff_t pos);
+
+extern asmlinkage ssize_t sys_pwrite(unsigned int fd, const char * buf,
+				     size_t count, loff_t pos);
+
+typedef __kernel_ssize_t32 ssize_t32;
+
+asmlinkage ssize_t32 sys32_pread(unsigned int fd, char *ubuf,
+				 __kernel_size_t32 count, u32 poshi, u32 poslo)
+{
+	return sys_pread(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+}
+
+asmlinkage ssize_t32 sys32_pwrite(unsigned int fd, char *ubuf,
+				  __kernel_size_t32 count, u32 poshi, u32 poslo)
+{
+	return sys_pwrite(fd, ubuf, count, ((loff_t)AA(poshi) << 32) | AA(poslo));
+}
+
+
+extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count);
+
+asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count)
+{
+	mm_segment_t old_fs = get_fs();
+	int ret;
+	off_t of;
+	
+	if (offset && get_user(of, offset))
+		return -EFAULT;
+		
+	set_fs(KERNEL_DS);
+	ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count);
+	set_fs(old_fs);
+	
+	if (!ret && offset && put_user(of, offset))
+		return -EFAULT;
+		
+	return ret;
+}
+
+/* Handle adjtimex compatability. */
+
+struct timex32 {
+	u32 modes;
+	s32 offset, freq, maxerror, esterror;
+	s32 status, constant, precision, tolerance;
+	struct timeval32 time;
+	s32 tick;
+	s32 ppsfreq, jitter, shift, stabil;
+	s32 jitcnt, calcnt, errcnt, stbcnt;
+	s32  :32; s32  :32; s32  :32; s32  :32;
+	s32  :32; s32  :32; s32  :32; s32  :32;
+	s32  :32; s32  :32; s32  :32; s32  :32;
+};
+
+extern int do_adjtimex(struct timex *);
+
+asmlinkage int sys32_adjtimex(struct timex32 *utp)
+{
+	struct timex txc;
+	int ret;
+
+	memset(&txc, 0, sizeof(struct timex));
+
+	if(get_user(txc.modes, &utp->modes) ||
+	   __get_user(txc.offset, &utp->offset) ||
+	   __get_user(txc.freq, &utp->freq) ||
+	   __get_user(txc.maxerror, &utp->maxerror) ||
+	   __get_user(txc.esterror, &utp->esterror) ||
+	   __get_user(txc.status, &utp->status) ||
+	   __get_user(txc.constant, &utp->constant) ||
+	   __get_user(txc.precision, &utp->precision) ||
+	   __get_user(txc.tolerance, &utp->tolerance) ||
+	   __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+	   __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+	   __get_user(txc.tick, &utp->tick) ||
+	   __get_user(txc.ppsfreq, &utp->ppsfreq) ||
+	   __get_user(txc.jitter, &utp->jitter) ||
+	   __get_user(txc.shift, &utp->shift) ||
+	   __get_user(txc.stabil, &utp->stabil) ||
+	   __get_user(txc.jitcnt, &utp->jitcnt) ||
+	   __get_user(txc.calcnt, &utp->calcnt) ||
+	   __get_user(txc.errcnt, &utp->errcnt) ||
+	   __get_user(txc.stbcnt, &utp->stbcnt))
+		return -EFAULT;
+
+	ret = do_adjtimex(&txc);
+
+	if(put_user(txc.modes, &utp->modes) ||
+	   __put_user(txc.offset, &utp->offset) ||
+	   __put_user(txc.freq, &utp->freq) ||
+	   __put_user(txc.maxerror, &utp->maxerror) ||
+	   __put_user(txc.esterror, &utp->esterror) ||
+	   __put_user(txc.status, &utp->status) ||
+	   __put_user(txc.constant, &utp->constant) ||
+	   __put_user(txc.precision, &utp->precision) ||
+	   __put_user(txc.tolerance, &utp->tolerance) ||
+	   __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||
+	   __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||
+	   __put_user(txc.tick, &utp->tick) ||
+	   __put_user(txc.ppsfreq, &utp->ppsfreq) ||
+	   __put_user(txc.jitter, &utp->jitter) ||
+	   __put_user(txc.shift, &utp->shift) ||
+	   __put_user(txc.stabil, &utp->stabil) ||
+	   __put_user(txc.jitcnt, &utp->jitcnt) ||
+	   __put_user(txc.calcnt, &utp->calcnt) ||
+	   __put_user(txc.errcnt, &utp->errcnt) ||
+	   __put_user(txc.stbcnt, &utp->stbcnt))
+		ret = -EFAULT;
+
+	return ret;
+}
+
+extern asmlinkage long sys_setpriority(int which, int who, int niceval);
+
+asmlinkage int sys_setpriority32(u32 which, u32 who, u32 niceval)
+{
+	return sys_setpriority((int) which,
+			       (int) who,
+			       (int) niceval);
+}
+
+struct __sysctl_args32 {
+	u32 name;
+	int nlen;
+	u32 oldval;
+	u32 oldlenp;
+	u32 newval;
+	u32 newlen;
+	u32 __unused[4];
+};
+
+extern asmlinkage long sys32_sysctl(struct __sysctl_args32 *args)
+{
+	struct __sysctl_args32 tmp;
+	int error;
+	size_t oldlen, *oldlenp = NULL;
+	unsigned long addr = (((long)&args->__unused[0]) + 7) & ~7;
+
+	if (copy_from_user(&tmp, args, sizeof(tmp)))
+		return -EFAULT;
+
+	if (tmp.oldval && tmp.oldlenp) {
+		/* Duh, this is ugly and might not work if sysctl_args
+		   is in read-only memory, but do_sysctl does indirectly
+		   a lot of uaccess in both directions and we'd have to
+		   basically copy the whole sysctl.c here, and
+		   glibc's __sysctl uses rw memory for the structure
+		   anyway.  */
+		if (get_user(oldlen, (u32 *)A(tmp.oldlenp)) ||
+		    put_user(oldlen, (size_t *)addr))
+			return -EFAULT;
+		oldlenp = (size_t *)addr;
+	}
+
+	lock_kernel();
+	error = do_sysctl((int *)A(tmp.name), tmp.nlen, (void *)A(tmp.oldval),
+			  oldlenp, (void *)A(tmp.newval), tmp.newlen);
+	unlock_kernel();
+	if (oldlenp) {
+		if (!error) {
+			if (get_user(oldlen, (size_t *)addr) ||
+			    put_user(oldlen, (u32 *)A(tmp.oldlenp)))
+				error = -EFAULT;
+		}
+		copy_to_user(args->__unused, tmp.__unused, sizeof(tmp.__unused));
+	}
+	return error;
+}
+
+struct stat64_emu31 {
+        unsigned short  st_dev;
+        unsigned char   __pad0[6];
+
+        long long	st_ino;
+        unsigned int    st_mode;
+        unsigned int    st_nlink;
+
+        __u32		st_uid;
+        __u32		st_gid;
+
+        unsigned short  st_rdev;
+        unsigned char   __pad3[10];
+
+        long long       st_size;
+        __u32		st_blksize;
+
+        __u32		st_blocks;      /* Number 512-byte blocks allocated. */
+        __u32		__pad4;         /* future possible st_blocks high bits */
+
+        __u32		st_atime;
+        __u32		__pad5;
+
+        __u32		st_mtime;
+        __u32		__pad6;
+
+        __u32		st_ctime;
+        __u32		__pad7;         /* will be high 32 bits of ctime someday */
+
+        __u32		__unused1;
+        __u32		__unused2;
+};
+
+static inline int
+putstat64 (struct stat64_emu31 *ubuf, struct stat *kbuf)
+{
+    int err;
+    
+    err = put_user (kbuf->st_dev, &ubuf->st_dev);
+    err |= __put_user (kbuf->st_ino, &ubuf->st_ino);
+    err |= __put_user (kbuf->st_mode, &ubuf->st_mode);
+    err |= __put_user (kbuf->st_nlink, &ubuf->st_nlink);
+    err |= __put_user (kbuf->st_uid, &ubuf->st_uid);
+    err |= __put_user (kbuf->st_gid, &ubuf->st_gid);
+    err |= __put_user (kbuf->st_rdev, &ubuf->st_rdev);
+    err |= __put_user (kbuf->st_size, &ubuf->st_size);
+    err |= __put_user (kbuf->st_blksize, &ubuf->st_blksize);
+    err |= __put_user (kbuf->st_blocks, &ubuf->st_blocks);
+    err |= __put_user (kbuf->st_atime, &ubuf->st_atime);
+    err |= __put_user (kbuf->st_mtime, &ubuf->st_mtime);
+    err |= __put_user (kbuf->st_ctime, &ubuf->st_ctime);
+    return err;
+}
+
+extern asmlinkage long sys_newstat(char * filename, struct stat * statbuf);
+
+asmlinkage long sys32_stat64(char * filename, struct stat64_emu31 * statbuf, long flags)
+{
+    int ret;
+    struct stat s;
+    char * tmp;
+    int err;
+    mm_segment_t old_fs = get_fs();
+    
+    tmp = getname(filename);
+    err = PTR_ERR(tmp);
+    if (IS_ERR(tmp))   
+	    return err;
+
+    set_fs (KERNEL_DS);
+    ret = sys_newstat(tmp, &s);
+    set_fs (old_fs);
+    putname(tmp);
+    if (putstat64 (statbuf, &s)) 
+	    return -EFAULT;
+    return ret;
+}
+
+extern asmlinkage long sys_newlstat(char * filename, struct stat * statbuf);
+
+asmlinkage long sys32_lstat64(char * filename, struct stat64_emu31 * statbuf, long flags)
+{
+    int ret;
+    struct stat s;
+    char * tmp;
+    int err;
+    mm_segment_t old_fs = get_fs();
+    
+    tmp = getname(filename);
+    err = PTR_ERR(tmp);
+    if (IS_ERR(tmp))   
+	    return err;
+
+    set_fs (KERNEL_DS);
+    ret = sys_newstat(tmp, &s);
+    set_fs (old_fs);
+    putname(tmp);
+    if (putstat64 (statbuf, &s)) 
+	    return -EFAULT;
+    return ret;
+}
+
+extern asmlinkage long sys_newfstat(unsigned int fd, struct stat * statbuf);
+
+asmlinkage long sys32_fstat64(unsigned long fd, struct stat64_emu31 * statbuf, long flags)
+{
+    int ret;
+    struct stat s;
+    mm_segment_t old_fs = get_fs();
+    
+    set_fs (KERNEL_DS);
+    ret = sys_newfstat(fd, &s);
+    set_fs (old_fs);
+    if (putstat64 (statbuf, &s))
+	    return -EFAULT;
+    return ret;
+}
+
+/*
+ * Linux/i386 didn't use to be able to handle more than
+ * 4 system call parameters, so these system calls used a memory
+ * block for parameter passing..
+ */
+
+struct mmap_arg_struct_emu31 {
+	u32	addr;
+	u32	len;
+	u32	prot;
+	u32	flags;
+	u32	fd;
+	u32	offset;
+};
+
+/* common code for old and new mmaps */
+static inline long do_mmap2(
+	unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags,
+	unsigned long fd, unsigned long pgoff)
+{
+	int error = -EBADF;
+	struct file * file = NULL;
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	if (!(flags & MAP_ANONYMOUS)) {
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+
+	down(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+out:    
+	return error;
+}
+
+
+asmlinkage unsigned long
+old32_mmap(struct mmap_arg_struct_emu31 *arg)
+{
+	struct mmap_arg_struct_emu31 a;
+	int error = -EFAULT;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		goto out;
+
+	error = -EINVAL;
+	if (a.offset & ~PAGE_MASK)
+		goto out;
+
+	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); 
+out:
+	return error;
+}
+
+asmlinkage long 
+sys32_mmap2(struct mmap_arg_struct_emu31 *arg)
+{
+	struct mmap_arg_struct_emu31 a;
+	int error = -EFAULT;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		goto out;
+	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+out:
+	return error;
+}
+
+extern asmlinkage long sys_socket(int family, int type, int protocol);
+extern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);
+extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr, int addrlen);
+extern asmlinkage long sys_listen(int fd, int backlog);
+extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr, int *upeer_addrlen);
+extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
+extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr, int *usockaddr_len);
+extern asmlinkage long sys_socketpair(int family, int type, int protocol, int usockvec[2]);
+extern asmlinkage long sys_send(int fd, void * buff, size_t len, unsigned flags);
+extern asmlinkage long sys_sendto(int fd, void * buff, size_t len, unsigned flags,
+                           struct sockaddr *addr, int addr_len);
+extern asmlinkage long sys_recv(int fd, void * ubuf, size_t size, unsigned flags);
+extern asmlinkage long sys_recvfrom(int fd, void * ubuf, size_t size, unsigned flags,
+                             struct sockaddr *addr, int *addr_len);
+extern asmlinkage long sys_shutdown(int fd, int how);
+extern asmlinkage long sys_getsockopt(int fd, int level, int optname, char *optval, int * optlen);
+
+/* Argument list sizes for sys_socketcall */
+#define AL(x) ((x) * sizeof(u32))
+static unsigned char nas[18] = {AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
+                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
+                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
+#undef AL
+
+asmlinkage long sys32_socketcall(int call, u32 *args)
+{
+	int ret;
+	u32 a[6];
+				 
+	if (call < SYS_SOCKET || call > SYS_RECVMSG)
+		return -EINVAL;
+	if (copy_from_user(a, args, nas[call]))
+		return -EFAULT;
+	switch(call) {
+	case SYS_SOCKET:
+		ret = sys_socket(a[0], a[1], a[2]);
+		break;
+	case SYS_BIND:
+		ret = sys_bind(a[0], (struct sockaddr *) A(a[1]), a[2]);
+		break;
+	case SYS_CONNECT:
+		ret = sys_connect(a[0], (struct sockaddr *) A(a[1]), a[2]);
+		break;
+	case SYS_LISTEN:
+		ret = sys_listen(a[0], a[1]);
+		break;
+	case SYS_ACCEPT:
+		ret = sys_accept(a[0], (struct sockaddr *) A(a[1]),
+				 (int *) A(a[2]));
+		break;
+	case SYS_GETSOCKNAME:
+		ret = sys_getsockname(a[0], (struct sockaddr *) A(a[1]),
+				      (int *) A(a[2]));
+		break;
+	case SYS_GETPEERNAME:
+		ret = sys_getpeername(a[0], (struct sockaddr *) A(a[1]),
+				      (int *) A(a[2]));
+		break;
+	case SYS_SOCKETPAIR:
+		ret = sys_socketpair(a[0], a[1], a[2], (int *) A(a[3]));
+		break;
+	case SYS_SEND:
+		ret = sys_send(a[0], (void *) A(a[1]), a[2], a[3]);
+		break;
+	case SYS_SENDTO:
+		ret = sys_sendto(a[0], (void*) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), a[5]);
+		break;
+	case SYS_RECV:
+		ret = sys_recv(a[0], (void *) A(a[1]), a[2], a[3]);
+		break;
+	case SYS_RECVFROM:
+		ret = sys_recvfrom(a[0], (void *) A(a[1]), a[2], a[3], (struct sockaddr *) A(a[4]), (int *) A(a[5]) );
+		break;
+	case SYS_SHUTDOWN:
+		ret = sys_shutdown(a[0], a[1]);
+		break;
+	case SYS_SETSOCKOPT:
+		ret = sys32_setsockopt(a[0], a[1], a[2], (char *) A(a[3]),
+				     a[4]);
+		break;
+	case SYS_GETSOCKOPT:
+		ret = sys_getsockopt(a[0], a[1], a[2], (char *) A(a[3]), (int *) A(a[4]) );
+		break;
+	case SYS_SENDMSG:
+		ret = sys32_sendmsg(a[0], (struct msghdr32 *) A(a[1]),
+				    a[2]);
+		break;
+	case SYS_RECVMSG:
+		ret = sys32_recvmsg(a[0], (struct msghdr32 *) A(a[1]),
+				    a[2]);
+		break;
+	default:
+		ret = EINVAL;
+		break;
+	}
+	return ret;
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/linux32.h linux/arch/s390x/kernel/linux32.h
--- v2.4.1/linux/arch/s390x/kernel/linux32.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/linux32.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,246 @@
+#ifndef _ASM_S390X_S390_H
+#define _ASM_S390X_S390_H
+
+#include <linux/config.h>
+#include <linux/socket.h>
+#include <linux/nfs_fs.h>
+#include <linux/sunrpc/svc.h>
+#include <linux/nfsd/nfsd.h>
+#include <linux/nfsd/export.h>
+
+#ifdef CONFIG_S390_SUPPORT
+
+/* Macro that masks the high order bit of an 32 bit pointer and converts it*/
+/*       to a 64 bit pointer */
+#define A(__x) ((unsigned long)((__x) & 0x7FFFFFFFUL))
+#define AA(__x)				\
+	((unsigned long)(__x))
+
+/* Now 32bit compatibility types */
+typedef unsigned int           __kernel_size_t32;
+typedef int                    __kernel_ssize_t32;
+typedef int                    __kernel_ptrdiff_t32;
+typedef int                    __kernel_time_t32;
+typedef int                    __kernel_clock_t32;
+typedef int                    __kernel_pid_t32;
+typedef unsigned short         __kernel_ipc_pid_t32;
+typedef unsigned short         __kernel_uid_t32;
+typedef unsigned short         __kernel_gid_t32;
+typedef unsigned short         __kernel_dev_t32;
+typedef unsigned int           __kernel_ino_t32;
+typedef unsigned short         __kernel_mode_t32;
+typedef unsigned short         __kernel_umode_t32;
+typedef short                  __kernel_nlink_t32;
+typedef int                    __kernel_daddr_t32;
+typedef int                    __kernel_off_t32;
+typedef unsigned int           __kernel_caddr_t32;
+typedef long                   __kernel_loff_t32;
+typedef __kernel_fsid_t        __kernel_fsid_t32;  
+
+struct ipc_kludge_32 {
+        __u32   msgp;                           /* pointer              */
+        __s32   msgtyp;
+};
+
+#define F_GETLK64       12
+#define F_SETLK64       13
+#define F_SETLKW64      14    
+
+struct flock32 {
+        short l_type;
+        short l_whence;
+        __kernel_off_t32 l_start;
+        __kernel_off_t32 l_len;
+        __kernel_pid_t32 l_pid;
+        short __unused;
+}; 
+
+struct stat32 {
+	unsigned short	st_dev;
+	unsigned short	__pad1;
+	__u32		st_ino;
+	unsigned short	st_mode;
+	unsigned short	st_nlink;
+	unsigned short	st_uid;
+	unsigned short	st_gid;
+	unsigned short	st_rdev;
+	unsigned short	__pad2;
+	__u32		st_size;
+	__u32		st_blksize;
+	__u32		st_blocks;
+	__u32		st_atime;
+	__u32		__unused1;
+	__u32		st_mtime;
+	__u32		__unused2;
+	__u32		st_ctime;
+	__u32		__unused3;
+	__u32		__unused4;
+	__u32		__unused5;
+};
+
+struct statfs32 {
+	__s32			f_type;
+	__s32			f_bsize;
+	__s32			f_blocks;
+	__s32			f_bfree;
+	__s32			f_bavail;
+	__s32			f_files;
+	__s32			f_ffree;
+	__kernel_fsid_t		f_fsid;
+	__s32			f_namelen;  
+	__s32			f_spare[6];
+};
+
+typedef __u32 old_sigset_t32;       /* at least 32 bits */ 
+
+struct old_sigaction32 {
+       __u32			sa_handler;	/* Really a pointer, but need to deal with 32 bits */
+       old_sigset_t32		sa_mask;	/* A 32 bit mask */
+       __u32			sa_flags;
+       __u32			sa_restorer;	/* Another 32 bit pointer */
+};
+ 
+#define _SIGCONTEXT_NSIG_WORDS32    2 
+typedef struct {
+        __u32   sig[_SIGCONTEXT_NSIG_WORDS32];
+} sigset_t32;  
+
+typedef union sigval32 {
+        int     sival_int;
+        __u32   sival_ptr;
+} sigval_t32;
+                 
+typedef struct siginfo32 {
+	int	si_signo;
+	int	si_errno;
+	int	si_code;
+
+	union {
+		int _pad[((128/sizeof(int)) - 3)];
+
+		/* kill() */
+		struct {
+			pid_t	_pid;	/* sender's pid */
+			uid_t	_uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			unsigned int	_timer1;
+			unsigned int	_timer2;
+                
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			pid_t			_pid;	/* sender's pid */
+			uid_t			_uid;	/* sender's uid */
+			sigval_t32		_sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			pid_t			_pid;	/* which child */
+			uid_t			_uid;	/* sender's uid */
+			int			_status;/* exit code */
+			__kernel_clock_t32	_utime;
+			__kernel_clock_t32	_stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			__u32	_addr;	/* faulting insn/memory ref. - pointer */
+		} _sigfault;
+                          
+		/* SIGPOLL */
+		struct {
+			int	_band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int	_fd;
+		} _sigpoll;
+	} _sifields;
+} siginfo_t32;  
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid		_sifields._kill._pid
+#define si_uid		_sifields._kill._uid
+#define si_status	_sifields._sigchld._status
+#define si_utime	_sifields._sigchld._utime
+#define si_stime	_sifields._sigchld._stime
+#define si_value	_sifields._rt._sigval
+#define si_int		_sifields._rt._sigval.sival_int
+#define si_ptr		_sifields._rt._sigval.sival_ptr
+#define si_addr		_sifields._sigfault._addr
+#define si_band		_sifields._sigpoll._band
+#define si_fd		_sifields._sigpoll._fd    
+
+/* asm/sigcontext.h */
+typedef union
+{
+	__u64   d;
+	__u32   f; 
+} freg_t32;
+
+typedef struct
+{
+	unsigned int	fpc;
+	freg_t32	fprs[__NUM_FPRS];              
+} _s390_fp_regs32;
+
+typedef struct 
+{
+        __u32   mask;
+        __u32	addr;
+} _psw_t32 __attribute__ ((aligned(8)));
+
+typedef struct
+{
+	_psw_t32	psw;
+	__u32		gprs[__NUM_GPRS];
+	__u32		acrs[__NUM_ACRS];
+} _s390_regs_common32;
+
+typedef struct
+{
+	_s390_regs_common32 regs;
+	_s390_fp_regs32     fpregs;
+} _sigregs32;
+
+#define _SIGCONTEXT_NSIG32	64
+#define _SIGCONTEXT_NSIG_BPW32	32
+#define __SIGNAL_FRAMESIZE32	96
+#define _SIGMASK_COPY_SIZE32	(sizeof(u32)*2)
+
+struct sigcontext32
+{
+	__u32	oldmask[_SIGCONTEXT_NSIG_WORDS32];
+	__u32	sregs;				/* pointer */
+};
+
+/* asm/signal.h */
+struct sigaction32 {
+	__u32		sa_handler;		/* pointer */
+	__u32		sa_flags;
+        __u32		sa_restorer;		/* pointer */
+	sigset_t32	sa_mask;        /* mask last for extensibility */
+};
+
+typedef struct {
+	__u32			ss_sp;		/* pointer */
+	int			ss_flags;
+	__kernel_size_t32	ss_size;
+} stack_t32;
+
+/* asm/ucontext.h */
+struct ucontext32 {
+	__u32			uc_flags;
+	__u32			uc_link;	/* pointer */	
+	stack_t32		uc_stack;
+	sigset_t32		uc_sigmask;	/* mask last for extensibility */
+	__u32			sc;		/* pointer */
+};
+
+#endif /* !CONFIG_S390_SUPPORT */
+ 
+#endif /* _ASM_S390X_S390_H */
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/lowcore.S linux/arch/s390x/kernel/lowcore.S
--- v2.4.1/linux/arch/s390x/kernel/lowcore.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/lowcore.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,28 @@
+/*
+ *  arch/s390/kernel/lowcore.S
+ *    S390 lowcore definition.
+ *
+ *  S390 64 bit Version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com)
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+#include <asm/lowcore.h>
+	
+         .align 8192
+         .globl init_S390_lowcore
+init_S390_lowcore:      
+         .fill 0x1a0-0x000,1,0	
+         .quad  _RESTART_PSW_MASK
+         .quad  restart_int_handler 
+         .quad  _EXT_PSW_MASK
+         .quad  ext_int_handler 
+         .quad  _SVC_PSW_MASK
+         .quad  system_call
+         .quad  _PGM_PSW_MASK
+         .quad  pgm_check_handler 
+         .quad  _MCCK_PSW_MASK
+         .quad  mcck_int_handler 
+EXT_PSW: .quad  _IO_PSW_MASK
+         .quad  io_int_handler
+	 .fill  0x2000-0x200,1,0
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/mathemu.c linux/arch/s390x/kernel/mathemu.c
--- v2.4.1/linux/arch/s390x/kernel/mathemu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/mathemu.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,920 @@
+/*
+ *  arch/s390/kernel/mathemu.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ * 'mathemu.c' handles IEEE instructions on a S390 processor
+ * that does not have the IEEE fpu
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+
+#include <asm/uaccess.h>
+#include <asm/mathemu.h>
+
+#ifdef CONFIG_SYSCTL
+int sysctl_ieee_emulation_warnings=1;
+#endif
+
+static void display_emulation_not_implemented(char *instr)
+{
+	struct pt_regs *regs;
+	__u16 *location;
+	
+#if CONFIG_SYSCTL
+	if(sysctl_ieee_emulation_warnings)
+#endif
+	{
+		regs=current->thread.regs;
+		location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+		printk("%s ieee fpu instruction not emulated process name: %s pid: %d \n",
+		       instr,
+		       current->comm, current->pid);
+		printk("%s's PSW:    %08lx %08lx\n",instr,
+		       (unsigned long) regs->psw.mask,
+		       (unsigned long) location);
+	}
+}
+
+
+static void set_CC_df(__u64 val1,__u64 val2) {
+        int rc;
+        rc = __cmpdf2(val1,val2);
+        current->thread.regs->psw.mask &= 0xFFFFCFFFFFFFFFFFL;
+        switch (rc) {
+                case -1:
+                        current->thread.regs->psw.mask |= 0x0000100000000000L;
+                        break;
+                case 1:
+                        current->thread.regs->psw.mask |= 0x0000200000000000L;
+                        break;
+        }
+}
+
+static void set_CC_sf(__u32 val1,__u32 val2) {
+        int rc;
+        rc = __cmpsf2(val1,val2);
+        current->thread.regs->psw.mask &= 0xFFFFCFFFFFFFFFFF;
+        switch (rc) {
+                case -1:
+                        current->thread.regs->psw.mask |= 0x0000100000000000L;
+                        break;
+                case 1:
+                        current->thread.regs->psw.mask |= 0x0000200000000000L;
+                        break;
+        }
+}
+
+
+static void emu_adb (int rx, __u64 val) {
+        current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,val);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_adbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d = __adddf3(current->thread.fp_regs.fprs[rx].d,
+                                         current->thread.fp_regs.fprs[ry].d);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_aeb (int rx, __u32 val) {
+        current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,val);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_aebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = __addsf3(current->thread.fp_regs.fprs[rx].f,
+                                        current->thread.fp_regs.fprs[ry].f);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_axbr (int rx, int ry) {
+        display_emulation_not_implemented("axbr");
+}
+
+static void emu_cdb (int rx, __u64 val) {
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,val);
+}
+
+static void emu_cdbr (int rx, int ry) {
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,current->thread.fp_regs.fprs[ry].d);
+}
+
+static void emu_cdfbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d =
+                     __floatsidf(current->thread.regs->gprs[ry]);
+}
+
+static void emu_ceb (int rx, __u32 val) {
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,val);
+}
+
+static void emu_cebr (int rx, int ry) {
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,current->thread.fp_regs.fprs[ry].f);
+}
+
+static void emu_cefbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f =
+                     __floatsisf(current->thread.regs->gprs[ry]);
+}
+
+static void emu_cfdbr (int rx, int ry, int mask) {
+        current->thread.regs->gprs[rx] =
+                     __fixdfsi(current->thread.fp_regs.fprs[ry].d);
+}
+
+static void emu_cfebr (int rx, int ry, int mask) {
+        current->thread.regs->gprs[rx] =
+                     __fixsfsi(current->thread.fp_regs.fprs[ry].f);
+}
+
+static void emu_cfxbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("cfxbr");
+}
+
+static void emu_cxbr (int rx, int ry) {
+        display_emulation_not_implemented("cxbr");
+}
+
+static void emu_cxfbr (int rx, int ry) {
+        display_emulation_not_implemented("cxfbr");
+}
+
+static void emu_ddb (int rx, __u64 val) {
+        current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,val);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_ddbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d = __divdf3(current->thread.fp_regs.fprs[rx].d,
+                                         current->thread.fp_regs.fprs[ry].d);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_deb (int rx, __u32 val) {
+        current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,val);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_debr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = __divsf3(current->thread.fp_regs.fprs[rx].f,
+                                         current->thread.fp_regs.fprs[ry].f);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_didbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("didbr");
+}
+
+static void emu_diebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("diebr");
+}
+
+static void emu_dxbr (int rx, int ry) {
+        display_emulation_not_implemented("dxbr");
+}
+
+static void emu_efpc (int rx, int ry) {
+        display_emulation_not_implemented("efpc");
+}
+
+static void emu_fidbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("fidbr");
+}
+
+static void emu_fiebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("fiebr");
+}
+
+static void emu_fixbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("fixbr");
+}
+
+static void emu_kdb (int rx, __u64 val) {
+        display_emulation_not_implemented("kdb");
+}
+
+static void emu_kdbr (int rx, int ry) {
+        display_emulation_not_implemented("kdbr");
+}
+
+static void emu_keb (int rx, __u32 val) {
+        display_emulation_not_implemented("keb");
+}
+
+static void emu_kebr (int rx, int ry) {
+        display_emulation_not_implemented("kebr");
+}
+
+static void emu_kxbr (int rx, int ry) {
+        display_emulation_not_implemented("kxbr");
+}
+
+static void emu_lcdbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d =
+        __negdf2(current->thread.fp_regs.fprs[ry].d);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_lcebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f =
+        __negsf2(current->thread.fp_regs.fprs[ry].f);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_lcxbr (int rx, int ry) {
+        display_emulation_not_implemented("lcxbr");
+}
+
+static void emu_ldeb (int rx, __u32 val) {
+        current->thread.fp_regs.fprs[rx].d = __extendsfdf2(val);
+}
+
+static void emu_ldebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d =
+        __extendsfdf2(current->thread.fp_regs.fprs[ry].f);
+}
+
+static void emu_ldxbr (int rx, int ry) {
+        display_emulation_not_implemented("ldxbr");
+}
+
+static void emu_ledbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = __truncdfsf2(current->thread.fp_regs.fprs[ry].d);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_lexbr (int rx, int ry) {
+        display_emulation_not_implemented("lexbr");
+}
+
+static void emu_lndbr (int rx, int ry) {
+        display_emulation_not_implemented("lndbr");
+}
+
+static void emu_lnebr (int rx, int ry) {
+        display_emulation_not_implemented("lnebr");
+}
+
+static void emu_lnxbr (int rx, int ry) {
+        display_emulation_not_implemented("lnxbr");
+}
+
+static void emu_lpdbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d = __absdf2(current->thread.fp_regs.fprs[ry].d);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0);
+}
+
+static void emu_lpebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = __abssf2(current->thread.fp_regs.fprs[ry].f);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_lpxbr (int rx, int ry) {
+        display_emulation_not_implemented("lpxbr");
+}
+
+static void emu_ltdbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d = current->thread.fp_regs.fprs[ry].d;
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_ltebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = current->thread.fp_regs.fprs[ry].f;
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_ltxbr (int rx, int ry) {
+        display_emulation_not_implemented("ltxbr");
+}
+
+static void emu_lxdb (int rx, __u64 val) {
+        display_emulation_not_implemented("lxdb");
+}
+
+static void emu_lxdbr (int rx, int ry) {
+        display_emulation_not_implemented("lxdbr");
+}
+
+static void emu_lxeb (int rx, __u32 val) {
+        display_emulation_not_implemented("lxeb");
+}
+
+static void emu_lxebr (int rx, int ry) {
+        display_emulation_not_implemented("lxebr");
+}
+
+static void emu_madb (int rx, __u64 val, int mask) {
+        display_emulation_not_implemented("madb");
+}
+
+static void emu_madbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("madbr");
+}
+
+static void emu_maeb (int rx, __u32 val, int mask) {
+        display_emulation_not_implemented("maeb");
+}
+
+static void emu_maebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("maebr");
+}
+
+static void emu_mdb (int rx, __u64 val) {
+        current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,val);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_mdbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d = __muldf3(current->thread.fp_regs.fprs[rx].d,
+                                         current->thread.fp_regs.fprs[ry].d);
+        set_CC_df(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_mdeb (int rx, __u32 val) {
+        display_emulation_not_implemented("mdeb");
+}
+
+static void emu_mdebr (int rx, int ry) {
+        display_emulation_not_implemented("mdebr");
+}
+
+static void emu_meeb (int rx, __u32 val) {
+        current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f,
+                                         val);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_meebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = __mulsf3(current->thread.fp_regs.fprs[rx].f,
+                                         current->thread.fp_regs.fprs[ry].f);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_msdb (int rx, __u64 val, int mask) {
+        display_emulation_not_implemented("msdb");
+}
+
+static void emu_msdbr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("msdbr");
+}
+
+static void emu_mseb (int rx, __u32 val, int mask) {
+        display_emulation_not_implemented("mseb");
+}
+
+static void emu_msebr (int rx, int ry, int mask) {
+        display_emulation_not_implemented("msebr");
+}
+
+static void emu_mxbr (int rx, int ry) {
+        display_emulation_not_implemented("mxbr");
+}
+
+static void emu_mxdb (int rx, __u64 val) {
+        display_emulation_not_implemented("mxdb");
+}
+
+static void emu_mxdbr (int rx, int ry) {
+        display_emulation_not_implemented("mxdbr");
+}
+
+static void emu_sdb (int rx, __u64 val) {
+        current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d,
+                                         val);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_sdbr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].d = __subdf3(current->thread.fp_regs.fprs[rx].d,
+                                         current->thread.fp_regs.fprs[ry].d);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].d,0ULL);
+}
+
+static void emu_seb (int rx, __u32 val) {
+        current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f,
+                                         val);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_sebr (int rx, int ry) {
+        current->thread.fp_regs.fprs[rx].f = __subsf3(current->thread.fp_regs.fprs[rx].f,
+                                         current->thread.fp_regs.fprs[ry].f);
+        set_CC_sf(current->thread.fp_regs.fprs[rx].f,0);
+}
+
+static void emu_sfpc (int rx, int ry) {
+        display_emulation_not_implemented("sfpc");
+}
+
+static void emu_sqdb (int rx, __u64 val) {
+        display_emulation_not_implemented("sqdb");
+}
+
+static void emu_sqdbr (int rx, int ry) {
+        display_emulation_not_implemented("sqdbr");
+}
+
+static void emu_sqeb (int rx, __u32 val) {
+        display_emulation_not_implemented("sqeb");
+}
+
+static void emu_sqebr (int rx, int ry) {
+        display_emulation_not_implemented("sqebr");
+}
+
+static void emu_sqxbr (int rx, int ry) {
+        display_emulation_not_implemented("sqxbr");
+}
+
+static void emu_sxbr (int rx, int ry) {
+        display_emulation_not_implemented("sxbr");
+}
+
+static void emu_tcdb (int rx, __u64 val) {
+        display_emulation_not_implemented("tcdb");
+}
+
+static void emu_tceb (int rx, __u32 val) {
+        display_emulation_not_implemented("tceb");
+}
+
+static void emu_tcxb (int rx, __u64 val) {
+        display_emulation_not_implemented("tcxb");
+}
+
+
+static inline void emu_load_regd(int reg) {
+        if ((reg&9) == 0) {                /* test if reg in {0,2,4,6} */
+                __asm__ __volatile (       /* load reg from fp_regs.fprs[reg] */
+                        "     bras  1,0f\n"
+                        "     ld    0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
+                        : "1" );
+        }
+}
+
+static inline void emu_load_rege(int reg) {
+        if ((reg&9) == 0) {                /* test if reg in {0,2,4,6} */
+                __asm__ __volatile (       /* load reg from fp_regs.fprs[reg] */
+                        "     bras  1,0f\n"
+                        "     le    0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+                        : "1" );
+        }
+}
+
+static inline void emu_store_regd(int reg) {
+        if ((reg&9) == 0) {                /* test if reg in {0,2,4,6} */
+                __asm__ __volatile (       /* store reg to fp_regs.fprs[reg] */
+                        "     bras  1,0f\n"
+                        "     std   0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].d)
+                        : "1" );
+        }
+}
+
+
+static inline void emu_store_rege(int reg) {
+        if ((reg&9) == 0) {                /* test if reg in {0,2,4,6} */
+                __asm__ __volatile (       /* store reg to fp_regs.fprs[reg] */
+                        "     bras  1,0f\n"
+                        "     ste   0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" (reg<<4), "a" (&current->thread.fp_regs.fprs[reg].f)
+                        : "1" );
+        }
+}
+
+int math_emu_b3(__u8 *opcode, struct pt_regs * regs) {
+        static const __u8 format_table[] = {
+                2, 2, 2, 2, 9, 1, 2, 1, 2, 2, 2, 2, 9, 2, 4, 4,
+                1, 1, 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 3, 3,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                1, 1, 1, 1,10, 1, 1, 3, 1, 1, 1, 1, 1, 1, 0, 0,
+                0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 3,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
+                0, 0, 0, 0, 5, 6, 6, 0, 7, 8, 8, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        };
+        static const void *jump_table[]= {
+                emu_lpebr, emu_lnebr, emu_ltebr, emu_lcebr,
+                emu_ldebr, emu_lxdbr, emu_lxebr, emu_mxdbr,
+                emu_kebr,  emu_cebr,  emu_aebr,  emu_sebr,
+                emu_mdebr, emu_debr,  emu_maebr, emu_msebr,
+                emu_lpdbr, emu_lndbr, emu_ltdbr, emu_lcdbr,
+                emu_sqebr, emu_sqdbr, emu_sqxbr, emu_meebr,
+                emu_kdbr,  emu_cdbr,  emu_adbr,  emu_sdbr,
+                emu_mdbr,  emu_ddbr,  emu_madbr, emu_msdbr,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                emu_lpxbr, emu_lnxbr, emu_ltxbr, emu_lcxbr,
+                emu_ledbr, emu_ldxbr, emu_lexbr, emu_fixbr,
+                emu_kxbr,  emu_cxbr,  emu_axbr,  emu_sxbr,
+                emu_mxbr,  emu_dxbr,  NULL,      NULL,
+                NULL,      NULL,      NULL,      emu_diebr,
+                NULL,      NULL,      NULL,      emu_fiebr,
+                NULL,      NULL,      NULL,      emu_didbr,
+                NULL,      NULL,      NULL,      emu_fidbr,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                emu_sfpc,  NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                emu_efpc,  NULL,      NULL,      NULL,
+                NULL,      NULL,      NULL,      NULL,
+                emu_cefbr, emu_cdfbr, emu_cxfbr, NULL,
+                emu_cfebr, emu_cfdbr, emu_cfxbr
+        };
+
+        switch (format_table[opcode[1]]) {
+        case 1: /* RRE format, double operation */
+                emu_store_regd((opcode[3]>>4)&15);
+                emu_store_regd(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15);
+                emu_load_regd((opcode[3]>>4)&15);
+                emu_load_regd(opcode[3]&15);
+                return 0;
+        case 2: /* RRE format, float operation */
+                emu_store_rege((opcode[3]>>4)&15);
+                emu_store_rege(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15);
+                emu_load_rege((opcode[3]>>4)&15);
+                emu_load_rege(opcode[3]&15);
+                return 0;
+        case 3: /* RRF format, double operation */
+                emu_store_regd((opcode[3]>>4)&15);
+                emu_store_regd(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
+                emu_load_regd((opcode[3]>>4)&15);
+                emu_load_regd(opcode[3]&15);
+                return 0;
+        case 4: /* RRF format, float operation */
+                emu_store_rege((opcode[3]>>4)&15);
+                emu_store_rege(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
+                emu_load_rege((opcode[3]>>4)&15);
+                emu_load_rege(opcode[3]&15);
+                return 0;
+        case 5: /* RRE format, cefbr instruction */
+                emu_store_rege((opcode[3]>>4)&15);
+                /* call the emulation function */
+                ((void (*)(int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15);
+                emu_load_rege((opcode[3]>>4)&15);
+                return 0;
+        case 6: /* RRE format, cdfbr & cxfbr instruction */
+                emu_store_regd((opcode[3]>>4)&15);
+                /* call the emulation function */
+                ((void (*)(int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15);
+                emu_load_regd((opcode[3]>>4)&15);
+                return 0;
+                /* FIXME !! */
+                return 0;
+        case 7: /* RRF format, cfebr instruction */
+                emu_store_rege(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
+                return 0;
+        case 8: /* RRF format, cfdbr & cfxbr instruction */
+                emu_store_regd(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15,opcode[2]>>4);
+                return 0;
+	case 9: /* RRE format, ldebr & mdebr instruction */
+		/* float store but double load */
+                emu_store_rege((opcode[3]>>4)&15);
+                emu_store_rege(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15);
+                emu_load_regd((opcode[3]>>4)&15);
+                return 0;
+        case 10: /* RRE format, ledbr instruction */
+		/* double store but float load */
+                emu_store_regd((opcode[3]>>4)&15);
+                emu_store_regd(opcode[3]&15);
+                /* call the emulation function */
+                ((void (*)(int, int))jump_table[opcode[1]])
+                        (opcode[3]>>4,opcode[3]&15);
+                emu_load_rege((opcode[3]>>4)&15);
+                return 0;
+        default:
+                return 1;
+        }
+}
+
+static void* calc_addr(struct pt_regs *regs,int rx,int rb,int disp)
+{
+  rx &= 0xf;
+  rb &= 0xf;
+  disp &= 0xfff;
+  return (void*) ((rx != 0 ? regs->gprs[rx] : 0)  + /* index */   
+         (rb != 0 ? regs->gprs[rb] : 0)  + /* base */
+         disp);
+}
+    
+int math_emu_ed(__u8 *opcode, struct pt_regs * regs) {
+        static const __u8 format_table[] = {
+                0, 0, 0, 0, 5, 1, 2, 1, 2, 2, 2, 2, 5, 2, 4, 4,
+                2, 1, 1, 0, 2, 1, 0, 2, 1, 1, 1, 1, 1, 1, 3, 3,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+        };
+        static const void *jump_table[]= {
+                NULL,     NULL,     NULL,     NULL,
+                emu_ldeb, emu_lxdb, emu_lxeb, emu_mxdb,
+                emu_keb,  emu_ceb,  emu_aeb,  emu_seb,
+                emu_mdeb, emu_deb,  emu_maeb, emu_mseb,
+                emu_tceb, emu_tcdb, emu_tcxb, NULL,
+                emu_sqeb, emu_sqdb, NULL,     emu_meeb,
+                emu_kdb,  emu_cdb,  emu_adb,  emu_sdb,
+                emu_mdb,  emu_ddb,  emu_madb, emu_msdb
+        };
+
+        switch (format_table[opcode[5]]) {
+        case 1: /* RXE format, __u64 constant */ {
+                __u64 *dxb, temp;
+                __u32 opc;
+
+                emu_store_regd((opcode[1]>>4)&15);
+                opc = *((__u32 *) opcode);
+                dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
+                /* FIXME: how to react if copy_from_user fails ? */
+                copy_from_user(&temp, dxb, 8);
+                /* call the emulation function */
+                ((void (*)(int, __u64))jump_table[opcode[5]])
+                        (opcode[1]>>4,temp);
+                emu_load_regd((opcode[1]>>4)&15);
+                return 0;
+        }
+        case 2: /* RXE format, __u32 constant */ {
+                __u32 *dxb, temp;
+                __u32 opc;
+
+                emu_store_rege((opcode[1]>>4)&15);
+                opc = *((__u32 *) opcode);
+                dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
+                /* FIXME: how to react if get_user fails ? */
+                get_user(temp, dxb);
+                /* call the emulation function */
+                ((void (*)(int, __u32))jump_table[opcode[5]])
+                        (opcode[1]>>4,temp);
+                emu_load_rege((opcode[1]>>4)&15);
+                return 0;
+        }
+        case 3: /* RXF format, __u64 constant */ {
+                __u32 *dxb, temp;
+                __u32 opc;
+
+                emu_store_regd((opcode[1]>>4)&15);
+                opc = *((__u32 *) opcode);
+                dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
+                /* FIXME: how to react if copy_from_user fails ? */
+                copy_from_user(&temp, dxb, 8);
+                /* call the emulation function */
+                ((void (*)(int, __u32, int))jump_table[opcode[5]])
+                        (opcode[1]>>4,temp,opcode[4]>>4);
+                emu_load_regd((opcode[1]>>4)&15);
+                return 0;
+        }
+        case 4: /* RXF format, __u32 constant */ {
+                __u32 *dxb, temp;
+                __u32 opc;
+
+                emu_store_rege((opcode[1]>>4)&15);
+                opc = *((__u32 *) opcode);
+                dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
+                /* FIXME: how to react if get_user fails ? */
+                get_user(temp, dxb);
+                /* call the emulation function */
+                ((void (*)(int, __u32, int))jump_table[opcode[5]])
+                        (opcode[1]>>4,temp,opcode[4]>>4);
+                emu_load_rege((opcode[1]>>4)&15);
+                return 0;
+        }
+	case 5: /* RXE format, __u32 constant */
+                /* store_rege and load_regd */ 
+		{
+                __u32 *dxb, temp;
+                __u32 opc;
+                emu_store_rege((opcode[1]>>4)&15);
+                opc = *((__u32 *) opcode);
+                dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
+                /* FIXME: how to react if get_user fails ? */
+                get_user(temp, dxb);
+                /* call the emulation function */
+                ((void (*)(int, __u32))jump_table[opcode[5]])
+                        (opcode[1]>>4,temp);
+                emu_load_regd((opcode[1]>>4)&15);
+                return 0;
+        }
+        default:
+                return 1;
+        }
+}
+
+/*
+ * Emulate LDR Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
+ */
+void math_emu_ldr(__u8 *opcode) {
+        __u16 opc = *((__u16 *) opcode);
+
+        if ((opc & 0x0090) == 0) {         /* test if rx in {0,2,4,6} */
+                /* we got an exception therfore ry can't be in {0,2,4,6} */
+                __asm__ __volatile (       /* load rx from fp_regs.fprs[ry] */
+                        "     bras  1,0f\n"
+                        "     ld    0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" (opc&0x00f0),
+                          "a" (&current->thread.fp_regs.fprs[opc&0x000f].d)
+                        : "1" );
+        } else if ((opc & 0x0009) == 0) {  /* test if ry in {0,2,4,6} */
+                __asm__ __volatile (       /* store ry to fp_regs.fprs[rx] */
+                        "     bras  1,0f\n"
+                        "     std   0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" ((opc&0x000f)<<4),
+                          "a" (&current->thread.fp_regs.fprs[(opc&0x00f0)>>4].d)
+                        : "1" );
+        } else {                          /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
+                current->thread.fp_regs.fprs[(opc&0x00f0)>>4] =
+                        current->thread.fp_regs.fprs[opc&0x000f];
+        }
+}
+
+/*
+ * Emulate LER Rx,Ry with Rx or Ry not in {0, 2, 4, 6}
+ */
+void math_emu_ler(__u8 *opcode) {
+        __u16 opc = *((__u16 *) opcode);
+
+        if ((opc & 0x0090) == 0) {         /* test if rx in {0,2,4,6} */
+                /* we got an exception therfore ry can't be in {0,2,4,6} */
+                __asm__ __volatile (       /* load rx from fp_regs.fprs[ry] */
+                        "     bras  1,0f\n"
+                        "     le    0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" (opc&0x00f0),
+                          "a" (&current->thread.fp_regs.fprs[opc&0x000f].f)
+                        : "1" );
+        } else if ((opc & 0x0009) == 0) {  /* test if ry in {0,2,4,6} */
+                __asm__ __volatile (       /* store ry to fp_regs.fprs[rx] */
+                        "     bras  1,0f\n"
+                        "     ste   0,0(%1)\n"
+                        "0:   ex    %0,0(1)"
+                        : /* no output */
+                        : "a" ((opc&0x000f)<<4),
+                          "a" (&current->thread.fp_regs.fprs[(opc&0x00f0)>>4].f)
+                        : "1" );
+        } else {                          /* move fp_regs.fprs[ry] to fp_regs.fprs[rx] */
+                current->thread.fp_regs.fprs[(opc&0x00f0)>>4] =
+                        current->thread.fp_regs.fprs[opc&0x000f];
+        }
+}
+
+/*
+ * Emulate LD R,D(X,B) with R not in {0, 2, 4, 6}
+ */
+void math_emu_ld(__u8 *opcode, struct pt_regs * regs) {
+        __u32 opc = *((__u32 *) opcode);
+        __u64 *dxb;
+
+        dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
+        /* FIXME: how to react if copy_from_user fails ? */
+        copy_from_user(&current->thread.fp_regs.fprs[(opc>>20)&15].d, dxb, 8);
+}
+
+/*
+ * Emulate LE R,D(X,B) with R not in {0, 2, 4, 6}
+ */
+void math_emu_le(__u8 *opcode, struct pt_regs * regs) {
+        __u32 opc = *((__u32 *) opcode);
+        __u32 *mem, *dxb;
+
+        dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
+        /* FIXME: how to react if get_user fails ? */
+        mem = (__u32 *) (&current->thread.fp_regs.fprs[(opc>>20)&15].f);
+        get_user(mem[0], dxb);
+}
+
+/*
+ * Emulate STD R,D(X,B) with R not in {0, 2, 4, 6}
+ */
+void math_emu_std(__u8 *opcode, struct pt_regs * regs) {
+        __u32 opc = *((__u32 *) opcode);
+        __u64 *dxb;
+        dxb = (__u64 *) calc_addr(regs,opc>>16,opc>>12,opc);
+        /* FIXME: how to react if copy_to_user fails ? */
+        copy_to_user(dxb, &current->thread.fp_regs.fprs[(opc>>20)&15].d, 8);
+}
+
+/*
+ * Emulate STE R,D(X,B) with R not in {0, 2, 4, 6}
+ */
+void math_emu_ste(__u8 *opcode, struct pt_regs * regs) {
+        __u32 opc = *((__u32 *) opcode);
+        __u32 *mem, *dxb;
+        dxb = (__u32 *) calc_addr(regs,opc>>16,opc>>12,opc);
+        /* FIXME: how to react if put_user fails ? */
+        mem = (__u32 *) (&current->thread.fp_regs.fprs[(opc>>20)&15].f);
+        put_user(mem[0], dxb);
+}
+
+/*
+ * Emulate LFPC D(B)
+ */
+int math_emu_lfpc(__u8 *opcode, struct pt_regs *regs) {
+        /* FIXME: how to do that ?!? */
+        return 0;
+}
+
+/*
+ * Emulate STFPC D(B)
+ */
+int math_emu_stfpc(__u8 *opcode, struct pt_regs *regs) {
+        /* FIXME: how to do that ?!? */
+        return 0;
+}
+
+/*
+ * Emulate SRNM D(B)
+ */
+int math_emu_srnm(__u8 *opcode, struct pt_regs *regs) {
+        /* FIXME: how to do that ?!? */
+        return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/process.c linux/arch/s390x/kernel/process.c
--- v2.4.1/linux/arch/s390x/kernel/process.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/process.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,516 @@
+/*
+ *  arch/s390/kernel/process.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Hartmut Penner (hp@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ *  Derived from "arch/i386/kernel/process.c"
+ *    Copyright (C) 1995, Linus Torvalds
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#define __KERNEL_SYSCALLS__
+#include <stdarg.h>
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/misc390.h>
+#include <asm/irq.h>
+
+spinlock_t semaphore_wake_lock = SPIN_LOCK_UNLOCKED;
+
+asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+
+/*
+ * The idle loop on a S390...
+ */
+
+static psw_t wait_psw;
+
+int cpu_idle(void *unused)
+{
+	/* endless idle loop with no priority at all */
+        init_idle();
+	current->nice = 20;
+	current->counter = -100;
+	wait_psw.mask = _WAIT_PSW_MASK;
+	wait_psw.addr = (unsigned long) &&idle_wakeup;
+	while(1) {
+                if (softirq_active(smp_processor_id()) &
+		    softirq_mask(smp_processor_id())) {
+                        do_softirq();
+                        __sti();
+                        if (!current->need_resched)
+                                continue;
+                }
+                if (current->need_resched) {
+                        schedule();
+                        check_pgt_cache();
+                        continue;
+                }
+
+		/* load wait psw */
+		asm volatile (
+                        "lpswe %0"
+                        : : "m" (wait_psw) );
+idle_wakeup:
+	}
+}
+
+/*
+  As all the register will only be made displayable to the root
+  user ( via printk ) or checking if the uid of the user is 0 from
+  the /proc filesystem please god this will be secure enough DJB.
+  The lines are given one at a time so as not to chew stack space in
+  printk on a crash & also for the proc filesystem when you get
+  0 returned you know you've got all the lines
+ */
+
+static int sprintf_regs(int line, char *buff, struct task_struct *task, struct pt_regs *regs)
+{
+	int linelen=0;
+	int regno,chaincnt;
+	u64 backchain,prev_backchain,endchain;
+	u64 ksp = 0;
+	char *mode = "???";
+
+	enum
+	{
+		sp_linefeed,
+		sp_psw,
+		sp_ksp,
+		sp_gprs,
+		sp_gprs1,
+		sp_gprs2,
+		sp_gprs3,
+		sp_gprs4,
+		sp_gprs5,
+		sp_gprs6,
+		sp_gprs7,
+		sp_gprs8,
+		sp_acrs,
+		sp_acrs1,
+		sp_acrs2,
+		sp_acrs3,
+		sp_acrs4,
+		sp_kern_backchain,
+		sp_kern_backchain1
+	};
+
+	if (task)
+		ksp = task->thread.ksp;
+	if (regs && !(regs->psw.mask & PSW_PROBLEM_STATE))
+		ksp = regs->gprs[15];
+
+	if (regs)
+		mode = (regs->psw.mask & PSW_PROBLEM_STATE)?
+		       "User" : "Kernel";
+
+	switch(line)
+	{
+	case sp_linefeed: 
+		linelen=sprintf(buff,"\n");
+		break;
+	case sp_psw:
+		if(regs)
+			linelen=sprintf(buff, "%s PSW:    %016lx %016lx\n", mode,
+				(unsigned long) regs->psw.mask,
+				(unsigned long) regs->psw.addr);
+		else
+			linelen=sprintf(buff,"pt_regs=NULL some info unavailable\n");
+		break;
+	case sp_ksp:
+		linelen=sprintf(&buff[linelen],
+				"task: %016lx ksp: %016lx pt_regs: %016lx\n",
+				(addr_t)task, (addr_t)ksp, (addr_t)regs);
+		break;
+	case sp_gprs:
+		if(regs)
+			linelen=sprintf(buff, "%s GPRS:\n", mode);
+		break;
+	case sp_gprs1 ... sp_gprs8:
+		if(regs)
+		{
+			regno=(line-sp_gprs1)*2;
+			linelen = sprintf(buff,"%016lx  %016lx\n",
+					  regs->gprs[regno],
+					  regs->gprs[regno+1]);
+		}
+		break;
+	case sp_acrs:
+		if(regs)
+			linelen=sprintf(buff, "%s ACRS:\n", mode);
+		break;	
+        case sp_acrs1 ... sp_acrs4:
+		if(regs)
+		{
+			regno=(line-sp_acrs1)*4;
+			linelen=sprintf(buff,"%08x  %08x  %08x  %08x\n",
+					regs->acrs[regno],
+					regs->acrs[regno+1],
+					regs->acrs[regno+2],
+					regs->acrs[regno+3]);
+		}
+		break;
+	case sp_kern_backchain:
+		if (regs && (regs->psw.mask & PSW_PROBLEM_STATE))
+			break;
+		if (ksp)
+			linelen=sprintf(buff, "Kernel BackChain          CallChain\n");
+		break;
+	default:
+		if (ksp)
+		{
+			
+			backchain=ksp&PSW_ADDR_MASK;
+			endchain=((backchain&(-THREAD_SIZE))+THREAD_SIZE);
+			prev_backchain=backchain-1;
+			line-=sp_kern_backchain1;
+			for(chaincnt=0;;chaincnt++)
+			{
+				if((backchain==0)||(backchain>=endchain)
+				   ||(chaincnt>=8)||(prev_backchain>=backchain))
+					break;
+				if(chaincnt==line)
+				{
+					linelen+=sprintf(&buff[linelen],"       %016lx   [<%016lx>]\n",
+							 backchain,
+							 *(u64 *)(backchain+112)&PSW_ADDR_MASK);
+					break;
+				}
+				prev_backchain=backchain;
+				backchain=(*((u64 *)backchain))&PSW_ADDR_MASK;
+			}
+		}
+	}
+	return(linelen);
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	char buff[80];
+	int line;
+
+        printk("CPU:    %d\n",smp_processor_id());
+        printk("Process %s (pid: %d, stackpage=%016lX)\n",
+                current->comm, current->pid, 4096+(addr_t)current);
+	
+	for (line = 0; sprintf_regs(line, buff, current, regs); line++)
+		printk(buff);
+}
+
+char *task_show_regs(struct task_struct *task, char *buffer)
+{
+	int line, len;
+
+	for (line = 0; ; line++)
+	{
+		len = sprintf_regs(line, buffer, task, NULL);
+		if (!len) break;
+		buffer += len;
+	}
+	return buffer;
+}
+
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+        int clone_arg = flags | CLONE_VM;
+        int retval;
+
+        __asm__ __volatile__(
+                "     slgr  2,2\n"
+                "     lgr   3,%1\n"
+                "     lg    4,%6\n"     /* load kernel stack ptr of parent */
+                "     svc   %b2\n"                     /* Linux system call*/
+                "     clg   4,%6\n"    /* compare ksp's: child or parent ? */
+                "     je    0f\n"                          /* parent - jump*/
+                "     lg    15,%6\n"            /* fix kernel stack pointer*/
+                "     aghi  15,%7\n"
+                "     xc    0(160,15),0(15)\n"          /* clear save area */
+                "     lgr   2,%4\n"                        /* load argument*/
+                "     basr  14,%5\n"                             /* call fn*/
+                "     svc   %b3\n"                     /* Linux system call*/
+                "0:   lgr   %0,2"
+                : "=a" (retval)
+                : "d" (clone_arg), "i" (__NR_clone), "i" (__NR_exit),
+                  "d" (arg), "a" (fn), "i" (__LC_KERNEL_STACK) ,
+                  "i" (-STACK_FRAME_OVERHEAD)
+                : "2", "3", "4" );
+        return retval;
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+
+        current->used_math = 0;
+        current->flags &= ~PF_USEDFPU;
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+int copy_thread(int nr, unsigned long clone_flags, unsigned long new_stackp,
+	unsigned long unused,
+        struct task_struct * p, struct pt_regs * regs)
+{
+        struct stack_frame
+          {
+            unsigned long back_chain;
+            unsigned long eos;
+            unsigned long glue1;
+            unsigned long glue2;
+            unsigned long scratch[2];
+            unsigned long gprs[10];    /* gprs 6 -15                       */
+            unsigned long fprs[2];     /* fpr 4 and 6                      */
+            unsigned long empty[2];
+#if CONFIG_REMOTE_DEBUG
+	    gdb_pt_regs childregs;
+#else
+            pt_regs childregs;
+#endif
+            __u32   pgm_old_ilc;       /* single step magic from entry.S */
+            __u32   pgm_svc_step;
+          } *frame;
+
+        frame = (struct stack_frame *) (4*PAGE_SIZE + (unsigned long) p) -1;
+        frame = (struct stack_frame *) (((unsigned long) frame)&-8L);
+        p->thread.regs = &frame->childregs;
+        p->thread.ksp = (unsigned long) frame;
+        frame->childregs = *regs;
+        frame->childregs.gprs[15] = new_stackp;
+        frame->eos = 0;
+
+        /* new return point is ret_from_sys_call */
+        frame->gprs[8] = (unsigned long) &ret_from_fork;
+
+        /* fake return stack for resume(), don't go back to schedule */
+        frame->gprs[9]  = (unsigned long) frame;
+	frame->pgm_svc_step = 0; /* Nope we aren't single stepping an svc */
+        /* save fprs, if used in last task */
+	save_fp_regs(&p->thread.fp_regs);
+        p->thread.user_seg = __pa((unsigned long) p->mm->pgd) | _REGION_TABLE;
+        /* Don't copy debug registers */
+        memset(&p->thread.per_info,0,sizeof(p->thread.per_info));
+        return 0;
+}
+
+asmlinkage int sys_fork(struct pt_regs regs)
+{
+        int ret;
+
+        lock_kernel();
+        ret = do_fork(SIGCHLD, regs.gprs[15], &regs, 0);
+        unlock_kernel();
+        return ret;
+}
+
+asmlinkage int sys_clone(struct pt_regs regs)
+{
+        unsigned long clone_flags;
+        unsigned long newsp;
+        int ret;
+
+        lock_kernel();
+        clone_flags = regs.gprs[3];
+        newsp = regs.orig_gpr2;
+        if (!newsp)
+                newsp = regs.gprs[15];
+        ret = do_fork(clone_flags, newsp, &regs, 0);
+        unlock_kernel();
+        return ret;
+}
+
+/*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+asmlinkage int sys_vfork(struct pt_regs regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+                       regs.gprs[15], &regs, 0);
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(struct pt_regs regs)
+{
+        int error;
+        char * filename;
+
+        filename = getname((char *) regs.orig_gpr2);
+        error = PTR_ERR(filename);
+        if (IS_ERR(filename))
+                goto out;
+        error = do_execve(filename, (char **) regs.gprs[3], (char **) regs.gprs[4], &regs);
+	if (error == 0)
+	{
+		current->ptrace &= ~PT_DTRACE;
+		current->thread.fp_regs.fpc=0;
+		__asm__ __volatile__
+		        ("sr  0,0\n\t"
+		         "sfpc 0,0\n\t"
+			 : : :"0");
+	}
+        putname(filename);
+out:
+        return error;
+}
+
+
+/*
+ * fill in the FPU structure for a core dump.
+ */
+int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs)
+{
+	save_fp_regs(fpregs);
+	return 1;
+}
+
+/*
+ * fill in the user structure for a core dump..
+ */
+void dump_thread(struct pt_regs * regs, struct user * dump)
+{
+
+/* changed the size calculations - should hopefully work better. lbt */
+	dump->magic = CMAGIC;
+	dump->start_code = 0;
+	dump->start_stack = regs->gprs[15] & ~(PAGE_SIZE - 1);
+	dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+	dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+	dump->u_dsize -= dump->u_tsize;
+	dump->u_ssize = 0;
+	if (dump->start_stack < TASK_SIZE)
+		dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+	memcpy(&dump->regs.gprs[0],regs,sizeof(s390_regs));
+	dump_fpu (regs, &dump->regs.fp_regs);
+	memcpy(&dump->regs.per_info,&current->thread.per_info,sizeof(per_struct));
+}
+
+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched	((unsigned long) scheduling_functions_start_here)
+#define last_sched	((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+        unsigned long r14, r15, bc;
+        unsigned long stack_page;
+        int count = 0;
+        if (!p || p == current || p->state == TASK_RUNNING)
+                return 0;
+        stack_page = (unsigned long) p;
+        r15 = p->thread.ksp;
+        if (!stack_page || r15 < stack_page || r15 >= 16380+stack_page)
+                return 0;
+        bc = *(unsigned long *) r15;
+        do {
+                if (bc < stack_page || bc >= 16380+stack_page)
+                        return 0;
+                r14 = *(unsigned long *) (bc+112);
+                if (r14 < first_sched || r14 >= last_sched)
+                        return r14;
+                bc = *(unsigned long *) bc;
+        } while (count++ < 16);
+        return 0;
+}
+#undef last_sched
+#undef first_sched
+
+/*
+ * This should be safe even if called from tq_scheduler
+ * A typical mask would be sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM) or 0.
+ *
+ */
+void s390_daemonize(char *name,unsigned long mask,int use_init_fs)
+{
+	struct fs_struct *fs;
+	extern struct task_struct *child_reaper;
+	struct task_struct *this_process=current;
+	
+	/*
+	 * If we were started as result of loading a module, close all of the
+	 * user space pages.  We don't need them, and if we didn't close them
+	 * they would be locked into memory.
+	 */
+	exit_mm(current);
+
+	this_process->session = 1;
+	this_process->pgrp = 1;
+	if(name)
+	{
+		strncpy(current->comm,name,15);
+		current->comm[15]=0;
+	}
+	else
+		current->comm[0]=0;
+	/* set signal mask to what we want to respond */
+        siginitsetinv(&current->blocked,mask);
+	/* exit_signal isn't set up */
+        /* if we inherit from cpu idle  */
+	this_process->exit_signal=SIGCHLD;
+	/* if priority=0 schedule can go into a tight loop */
+	this_process->policy= SCHED_OTHER;
+	/* nice goes priority=20-nice; */
+	this_process->nice=10;
+	if(use_init_fs)
+	{
+		exit_fs(this_process);	/* current->fs->count--; */
+		fs = init_task.fs;
+		current->fs = fs;
+		atomic_inc(&fs->count);
+		exit_files(current);
+	}
+	write_lock_irq(&tasklist_lock);
+	/* We want init as our parent */
+	REMOVE_LINKS(this_process);
+	this_process->p_opptr=this_process->p_pptr=child_reaper;
+	SET_LINKS(this_process);
+	write_unlock_irq(&tasklist_lock);
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/ptrace.c linux/arch/s390x/kernel/ptrace.c
--- v2.4.1/linux/arch/s390x/kernel/ptrace.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/ptrace.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,613 @@
+/*
+ *  arch/s390/kernel/ptrace.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ *  Based on PowerPC version 
+ *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
+ *
+ *  Derived from "arch/m68k/kernel/ptrace.c"
+ *  Copyright (C) 1994 by Hamish Macdonald
+ *  Taken from linux/kernel/ptrace.c and modified for M680x0.
+ *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
+ *
+ * Modified by Cort Dougan (cort@cs.nmt.edu) 
+ *
+ *
+ * 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.
+ */
+
+#include <stddef.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+
+void FixPerRegisters(struct task_struct *task)
+{
+	struct pt_regs *regs = task->thread.regs;
+	per_struct *per_info=
+			(per_struct *)&task->thread.per_info;
+
+	per_info->control_regs.bits.em_instruction_fetch =
+	        per_info->single_step | per_info->instruction_fetch;
+	
+	if (per_info->single_step) {
+		per_info->control_regs.bits.starting_addr=0;
+#ifdef CONFIG_S390_SUPPORT
+		if (current->thread.flags & S390_FLAG_31BIT) {
+			per_info->control_regs.bits.ending_addr=0x7fffffffUL;
+	        }
+		else 
+#endif      
+		{
+		per_info->control_regs.bits.ending_addr=-1L;
+		}
+	} else {
+		per_info->control_regs.bits.starting_addr=
+		        per_info->starting_addr;
+		per_info->control_regs.bits.ending_addr=
+		        per_info->ending_addr;
+	}
+	/* if any of the control reg tracing bits are on 
+	   we switch on per in the psw */
+	if (per_info->control_regs.words.cr[0] & PER_EM_MASK)
+		regs->psw.mask |= PSW_PER_MASK;
+	else
+		regs->psw.mask &= ~PSW_PER_MASK;
+	if (per_info->control_regs.bits.storage_alt_space_ctl)
+		task->thread.user_seg |= USER_STD_MASK;
+	else
+		task->thread.user_seg &= ~USER_STD_MASK;
+}
+
+void set_single_step(struct task_struct *task)
+{
+	per_struct *per_info= (per_struct *) &task->thread.per_info;	
+	
+	per_info->single_step = 1;  /* Single step */
+	FixPerRegisters (task);
+}
+
+void clear_single_step(struct task_struct *task)
+{
+	per_struct *per_info= (per_struct *) &task->thread.per_info;
+
+	per_info->single_step = 0;
+	FixPerRegisters (task);
+}
+
+int ptrace_usercopy(addr_t realuseraddr, addr_t copyaddr, int len,
+                    int tofromuser, int writeuser, unsigned long mask)
+{
+        unsigned long *realuserptr, *copyptr;
+	unsigned long tempuser;
+	int retval;
+
+        retval = 0;
+        realuserptr = (unsigned long *) realuseraddr;
+        copyptr = (unsigned long *) copyaddr;
+
+	if (writeuser && realuserptr == NULL)
+		return 0;
+
+	if (mask != -1L) {
+		tempuser = *realuserptr;
+		if (!writeuser) {
+			tempuser &= mask;
+			realuserptr = &tempuser;
+		}
+	}
+	if (tofromuser) {
+		if (writeuser) {
+			retval = copy_from_user(realuserptr, copyptr, len);
+		} else {
+			if (realuserptr == NULL)
+				retval = clear_user(copyptr, len);
+			else
+				retval = copy_to_user(copyptr,realuserptr,len);
+                        retval = (retval == -EFAULT) ? -EIO : 0;
+		}      
+	} else {
+		if (writeuser)
+			memcpy(realuserptr, copyptr, len);
+		else
+			memcpy(copyptr, realuserptr, len);
+	}
+	if (mask != -1L && writeuser)
+                *realuserptr = (*realuserptr & mask) | (tempuser & ~mask);
+	return retval;
+}
+
+int copy_user(struct task_struct *task,saddr_t useraddr, addr_t copyaddr,
+              int len, int tofromuser, int writingtouser)
+{
+	int copylen=0,copymax;
+	addr_t  realuseraddr;
+	saddr_t enduseraddr;
+	
+	unsigned long mask;
+
+#ifdef CONFIG_S390_SUPPORT
+	if (current->thread.flags & S390_FLAG_31BIT) {
+	/* adjust user offsets to 64 bit structure */
+		if (useraddr < PT_PSWADDR / 2)
+			useraddr = 2 * useraddr;
+		else if(useraddr < PT_ACR0 / 2)
+			useraddr = 2 * useraddr + sizeof(addr_t) / 2;
+		else if(useraddr < PT_ACR0 / 2 + (PT_ORIGGPR2 - PT_ACR0))
+			useraddr = useraddr + PT_ACR0 / 2;
+		else if(useraddr < PT_ACR0 / 2 + (sizeof(user_regs_struct) - sizeof(addr_t) / 2 - PT_ACR0))
+			useraddr = useraddr + PT_ACR0 / 2 + sizeof(addr_t) / 2; 
+        }
+#endif  
+    
+	enduseraddr=useraddr+len;
+
+	if (useraddr < 0 || enduseraddr > sizeof(struct user)||
+	   (useraddr < PT_ENDREGS && (useraddr&3))||
+	   (enduseraddr < PT_ENDREGS && (enduseraddr&3)))
+		return (-EIO);
+	while(len>0)
+	{
+		mask=PSW_ADDR_MASK;
+		if(useraddr<PT_FPC)
+		{
+			realuseraddr=(addr_t)&(((u8 *)task->thread.regs)[useraddr]);
+			if(useraddr<PT_PSWMASK)
+			{
+				copymax=PT_PSWMASK;
+			}
+			else if(useraddr<(PT_PSWMASK+PSW_MASK_SIZE))
+			{
+				copymax=(PT_PSWMASK+PSW_MASK_SIZE);
+				if(writingtouser)
+					mask=PSW_MASK_DEBUGCHANGE;
+			}
+			else if(useraddr<(PT_PSWADDR+PSW_ADDR_SIZE))
+			{
+				copymax=PT_PSWADDR+PSW_ADDR_SIZE;
+				mask=PSW_ADDR_DEBUGCHANGE;
+			}
+			else
+				copymax=PT_FPC;
+			
+		}
+		else if(useraddr<(PT_FPR15+sizeof(freg_t)))
+		{
+			copymax=(PT_FPR15+sizeof(freg_t));
+			realuseraddr=(addr_t)&(((u8 *)&task->thread.fp_regs)[useraddr-PT_FPC]);
+		}
+		else if(useraddr<sizeof(user_regs_struct))
+		{
+			copymax=sizeof(user_regs_struct);
+			realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]);
+		}
+		else 
+		{
+			copymax=sizeof(struct user);
+			realuseraddr=(addr_t)NULL;
+		}
+		copylen=copymax-useraddr;
+		copylen=(copylen>len ? len:copylen);
+		if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask))
+			return (-EIO);
+		copyaddr+=copylen;
+		len-=copylen;
+		useraddr+=copylen;
+	}
+	FixPerRegisters(task);
+	return(0);
+}
+
+asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
+{
+	struct task_struct *child;
+	int ret = -EPERM;
+	unsigned long flags;
+	unsigned long tmp;
+	int copied;
+	ptrace_area   parea; 
+
+	lock_kernel();
+	if (request == PTRACE_TRACEME) 
+	{
+		/* are we already being traced? */
+		if (current->ptrace & PT_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->ptrace |= PT_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
+	if (request == PTRACE_ATTACH) 
+	{
+		if (child == current)
+			goto out;
+		if ((!child->dumpable ||
+		     (current->uid != child->euid) ||
+		     (current->uid != child->suid) ||
+		     (current->uid != child->uid) ||
+		     (current->gid != child->egid) ||
+		     (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE))
+			goto out;
+		/* the same process cannot be attached many times */
+		if (child->ptrace & PT_PTRACED)
+			goto out;
+		child->ptrace |= PT_PTRACED;
+
+		write_lock_irqsave(&tasklist_lock, flags);
+		if (child->p_pptr != current) 
+		{
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+		}
+		write_unlock_irqrestore(&tasklist_lock, flags);
+
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	// printk("child=%lX child->flags=%lX",child,child->flags);
+	/* I added child!=current line so we can get the */
+	/* ieee_instruction_pointer from the user structure DJB */
+	if(child!=current)
+	{
+		if (!(child->ptrace & PT_PTRACED))
+			goto out;
+		if (child->state != TASK_STOPPED) 
+		{
+			if (request != PTRACE_KILL)
+				goto out;
+		}
+		if (child->p_pptr != current)
+			goto out;
+	}
+	switch (request) 
+	{
+		/* If I and D space are separate, these will need to be fixed. */
+	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+	case PTRACE_PEEKDATA: 
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			goto out;
+		ret = put_user(tmp,(unsigned long *) data);
+		goto out;
+
+		/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR:
+		ret=copy_user(child,addr,data,sizeof(unsigned long),1,0);
+		break;
+
+		/* If I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+			goto out;
+		ret = -EIO;
+		goto out;
+		break;
+
+	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+		ret=copy_user(child,addr,(addr_t)&data,sizeof(unsigned long),0,1);
+		break;
+
+	case PTRACE_SYSCALL: 	/* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: 	 /* restart after signal. */
+		ret = -EIO;
+		if ((unsigned long) data >= _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			child->ptrace |= PT_TRACESYS;
+		else
+			child->ptrace &= ~PT_TRACESYS;
+		child->exit_code = data;
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it wants to 
+ * exit.
+ */
+	case PTRACE_KILL:
+		ret = 0;
+		if (child->state == TASK_ZOMBIE) /* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		clear_single_step(child);
+		wake_up_process(child);
+		/* make sure the single step bit is not set. */
+		break;
+
+	case PTRACE_SINGLESTEP:  /* set the trap flag. */
+		ret = -EIO;
+		if ((unsigned long) data >= _NSIG)
+			break;
+		child->ptrace &= ~PT_TRACESYS;
+		child->exit_code = data;
+		set_single_step(child);
+		/* give it a chance to run. */
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+	case PTRACE_DETACH:  /* detach a process that was attached. */
+		ret = -EIO;
+		if ((unsigned long) data >= _NSIG)
+			break;
+		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
+		child->exit_code = data;
+		write_lock_irqsave(&tasklist_lock, flags);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irqrestore(&tasklist_lock, flags);
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	case PTRACE_PEEKUSR_AREA:
+	case PTRACE_POKEUSR_AREA:
+		if((ret=copy_from_user(&parea,(void *)addr,sizeof(parea)))==0)  
+		   ret=copy_user(child,parea.kernel_addr,parea.process_addr,
+				 parea.len,1,(request==PTRACE_POKEUSR_AREA));
+		break;
+	default:
+		ret = -EIO;
+		break;
+	}
+ out:
+	unlock_kernel();
+	return ret;
+}
+
+typedef struct
+{
+__u32	len;
+__u32	kernel_addr;
+__u32	process_addr;
+} ptrace_area_emu31;
+
+asmlinkage int sys32_ptrace(long request, long pid, long addr, s32 data)
+{
+	struct task_struct *child;
+	int ret = -EPERM;
+	unsigned long flags;
+	u32 tmp;
+	int copied;
+	ptrace_area   parea; 
+
+	lock_kernel();
+	if (request == PTRACE_TRACEME) 
+	{
+		/* are we already being traced? */
+		if (current->ptrace & PT_PTRACED)
+			goto out;
+		/* set the ptrace bit in the process flags. */
+		current->ptrace |= PT_PTRACED;
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	read_unlock(&tasklist_lock);
+	if (!child)
+		goto out;
+	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
+	if (request == PTRACE_ATTACH) 
+	{
+		if (child == current)
+			goto out;
+		if ((!child->dumpable ||
+		     (current->uid != child->euid) ||
+		     (current->uid != child->suid) ||
+		     (current->uid != child->uid) ||
+		     (current->gid != child->egid) ||
+		     (current->gid != child->sgid)) && !capable(CAP_SYS_PTRACE))
+			goto out;
+		/* the same process cannot be attached many times */
+		if (child->ptrace & PT_PTRACED)
+			goto out;
+		child->ptrace |= PT_PTRACED;
+
+		write_lock_irqsave(&tasklist_lock, flags);
+		if (child->p_pptr != current) 
+		{
+			REMOVE_LINKS(child);
+			child->p_pptr = current;
+			SET_LINKS(child);
+		}
+		write_unlock_irqrestore(&tasklist_lock, flags);
+
+		send_sig(SIGSTOP, child, 1);
+		ret = 0;
+		goto out;
+	}
+	ret = -ESRCH;
+	// printk("child=%lX child->flags=%lX",child,child->flags);
+	/* I added child!=current line so we can get the */
+	/* ieee_instruction_pointer from the user structure DJB */
+	if(child!=current)
+	{
+		if (!(child->ptrace & PT_PTRACED))
+			goto out;
+		if (child->state != TASK_STOPPED) 
+		{
+			if (request != PTRACE_KILL)
+				goto out;
+		}
+		if (child->p_pptr != current)
+			goto out;
+	}
+	switch (request) 
+	{
+		/* If I and D space are separate, these will need to be fixed. */
+	case PTRACE_PEEKTEXT: /* read word at location addr. */ 
+	case PTRACE_PEEKDATA: 
+		copied = access_process_vm(child, addr, &tmp, sizeof(tmp), 0);
+		ret = -EIO;
+		if (copied != sizeof(tmp))
+			goto out;
+		ret = put_user(tmp,(u32 *)(unsigned long)data);
+		goto out;
+
+		/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR:
+		ret=copy_user(child,addr,data,sizeof(u32),1,0);
+		break;
+
+		/* If I and D space are separate, this will have to be fixed. */
+	case PTRACE_POKETEXT: /* write the word at location addr. */
+	case PTRACE_POKEDATA:
+		ret = 0;
+		if (access_process_vm(child, addr, &data, sizeof(data), 1) == sizeof(data))
+			goto out;
+		ret = -EIO;
+		goto out;
+		break;
+
+	case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+		ret=copy_user(child,addr,(addr_t)&data,sizeof(u32),0,1);
+		break;
+
+	case PTRACE_SYSCALL: 	/* continue and stop at next (return from) syscall */
+	case PTRACE_CONT: 	 /* restart after signal. */
+		ret = -EIO;
+		if ((unsigned long) data >= _NSIG)
+			break;
+		if (request == PTRACE_SYSCALL)
+			child->ptrace |= PT_TRACESYS;
+		else
+			child->ptrace &= ~PT_TRACESYS;
+		child->exit_code = data;
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+/*
+ * make the child exit.  Best I can do is send it a sigkill. 
+ * perhaps it should be put in the status that it wants to 
+ * exit.
+ */
+	case PTRACE_KILL:
+		ret = 0;
+		if (child->state == TASK_ZOMBIE) /* already dead */
+			break;
+		child->exit_code = SIGKILL;
+		clear_single_step(child);
+		wake_up_process(child);
+		/* make sure the single step bit is not set. */
+		break;
+
+	case PTRACE_SINGLESTEP:  /* set the trap flag. */
+		ret = -EIO;
+		if ((unsigned long) data >= _NSIG)
+			break;
+		child->ptrace &= ~PT_TRACESYS;
+		child->exit_code = data;
+		set_single_step(child);
+		/* give it a chance to run. */
+		wake_up_process(child);
+		ret = 0;
+		break;
+
+	case PTRACE_DETACH:  /* detach a process that was attached. */
+		ret = -EIO;
+		if ((unsigned long) data >= _NSIG)
+			break;
+		child->ptrace &= ~(PT_PTRACED|PT_TRACESYS);
+		child->exit_code = data;
+		write_lock_irqsave(&tasklist_lock, flags);
+		REMOVE_LINKS(child);
+		child->p_pptr = child->p_opptr;
+		SET_LINKS(child);
+		write_unlock_irqrestore(&tasklist_lock, flags);
+		/* make sure the single step bit is not set. */
+		clear_single_step(child);
+		wake_up_process(child);
+		ret = 0;
+		break;
+	case PTRACE_PEEKUSR_AREA:
+	case PTRACE_POKEUSR_AREA:
+		{
+		ptrace_area_emu31 * parea31 = (void *)addr;
+		if (!access_ok(VERIFY_READ, parea31, sizeof(*parea31)))
+			return(-EFAULT);
+		ret = __get_user(parea.len, &parea31->len);
+		ret |= __get_user(parea.kernel_addr, &parea31->kernel_addr);
+		ret |= __get_user(parea.process_addr, &parea31->process_addr);
+		if(ret==0)  
+		   ret=copy_user(child,parea.kernel_addr,parea.process_addr,
+				 parea.len,1,(request==PTRACE_POKEUSR_AREA));
+		break;
+		}
+	default:
+		ret = -EIO;
+		break;
+	}
+ out:
+	unlock_kernel();
+	return ret;
+}
+
+asmlinkage void syscall_trace(void)
+{
+	lock_kernel();
+	if ((current->ptrace & (PT_PTRACED|PT_TRACESYS))
+	    != (PT_PTRACED|PT_TRACESYS))
+		goto out;
+	current->exit_code = SIGTRAP;
+	set_current_state(TASK_STOPPED);
+	notify_parent(current, SIGCHLD);
+	schedule();
+	/*
+	 * this isn't the same as continuing with a signal, but it will do
+	 * for normal use.  strace only continues with a signal if the
+	 * stopping signal is not SIGTRAP.  -brl
+	 */
+	if (current->exit_code) {
+		send_sig(current->exit_code, current, 1);
+		current->exit_code = 0;
+	}
+ out:
+	unlock_kernel();
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/reipl.S linux/arch/s390x/kernel/reipl.S
--- v2.4.1/linux/arch/s390x/kernel/reipl.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/reipl.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,94 @@
+/*
+ *  arch/s390/kernel/reipl.S
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
+	         Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#include <asm/lowcore.h>
+		.globl	do_reipl
+do_reipl:	basr	%r13,0
+.Lpg0:		lpswe   .Lnewpsw-.Lpg0(%r13)
+.Lpg1:		lctlg	%c6,%c6,.Lall-.Lpg0(%r13)
+                stctg   %c0,%c0,.Lctlsave-.Lpg0(%r13)
+                ni      .Lctlsave+4-.Lpg0(%r13),0xef
+                lctlg   %c0,%c0,.Lctlsave-.Lpg0(%r13)
+                lgr     %r1,%r2
+        	mvc     __LC_PGM_NEW_PSW(16),.Lpcnew-.Lpg0(%r13)
+                stsch   .Lschib-.Lpg0(%r13)                                    
+	        oi      .Lschib+5-.Lpg0(%r13),0x84 
+.Lecs:  	xi      .Lschib+27-.Lpg0(%r13),0x01 
+        	msch    .Lschib-.Lpg0(%r13) 
+		ssch	.Liplorb-.Lpg0(%r13)           
+		jz	.L001   
+		bas	%r14,.Ldisab-.Lpg0(%r13)
+.L001:		mvc	__LC_IO_NEW_PSW(16),.Lionew-.Lpg0(%r13)	
+.Ltpi:		lpswe	.Lwaitpsw-.Lpg0(%r13)          
+.Lcont:		c	%r1,__LC_SUBCHANNEL_ID
+		jnz	.Ltpi
+		clc	__LC_IO_INT_PARM(4),.Liplorb-.Lpg0(%r13)
+		jnz	.Ltpi
+		tsch	.Liplirb-.Lpg0(%r13)           
+		tm	.Liplirb+9-.Lpg0(%r13),0xbf
+                jz      .L002
+                bas     %r14,.Ldisab-.Lpg0(%r13)    
+.L002:		tm	.Liplirb+8-.Lpg0(%r13),0xf3    
+                jz      .L003
+                bas     %r14,.Ldisab-.Lpg0(%r13)	
+.L003:		spx	.Lnull-.Lpg0(%r13)
+		st 	%r1,__LC_SUBCHANNEL_ID
+                lhi     %r1,0            # mode 0 = esa
+                slr     %r0,%r0          # set cpuid to zero
+                sigp    %r1,%r0,0x12     # switch to esa mode
+                lpsw 	0
+.Ldisab:	sll    %r14,1
+		srl    %r14,1            # need to kill hi bit to avoid specification exceptions.
+		st     %r14,.Ldispsw+12-.Lpg0(%r13)
+		lpswe	.Ldispsw-.Lpg0(%r13)
+                .align 	8
+.Lall:		.quad	0x00000000ff000000
+.Lctlsave:      .quad   0x0000000000000000
+.Lnull:		.long   0x0000000000000000
+                .align 	16
+/*
+ * These addresses have to be 31 bit otherwise
+ * the sigp will throw a specifcation exception
+ * when switching to ESA mode as bit 31 be set
+ * in the ESA psw.
+ * Bit 31 of the addresses has to be 0 for the
+ * 31bit lpswe instruction a fact they appear to have
+ * ommited from the pop.
+ */
+.Lnewpsw:	.quad   0x0000000080000000
+		.quad   .Lpg1
+.Lpcnew:	.quad   0x0000000080000000
+	  	.quad   .Lecs
+.Lionew:	.quad   0x0000000080000000
+		.quad   .Lcont
+.Lwaitpsw:	.quad	0x0202000080000000
+		.quad   .Ltpi
+.Ldispsw:	.quad   0x0002000080000000
+		.quad   0x0000000000000000
+.Liplccws:	.long   0x02000000,0x60000018
+		.long   0x08000008,0x20000001
+.Liplorb:	.long	0x0049504c,0x0000ff80
+		.long	0x00000000+.Liplccws
+.Lschib:        .long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+		.long   0x00000000,0x00000000
+.Liplirb:	.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+		.long	0x00000000,0x00000000
+	
+
+	
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/s390_ext.c linux/arch/s390x/kernel/s390_ext.c
--- v2.4.1/linux/arch/s390x/kernel/s390_ext.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/s390_ext.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,77 @@
+/*
+ *  arch/s390/kernel/s390_ext.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <asm/lowcore.h>
+#include <asm/s390_ext.h>
+
+/*
+ * Simple hash strategy: index = code & 0xff;
+ * ext_int_hash[index] is the start of the list for all external interrupts
+ * that hash to this index. With the current set of external interrupts 
+ * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console and 0x4000
+ * iucv) this is always the first element. 
+ */
+ext_int_info_t *ext_int_hash[256] = { 0, };
+ext_int_info_t ext_int_info_timer;
+ext_int_info_t ext_int_info_hwc;
+
+int register_external_interrupt(__u16 code, ext_int_handler_t handler) {
+        ext_int_info_t *p;
+        int index;
+
+        index = code & 0xff;
+        p = ext_int_hash[index];
+        while (p != NULL) {
+                if (p->code == code)
+                        return -EBUSY;
+                p = p->next;
+        }
+        if (code == 0x1004) /* time_init is done before kmalloc works :-/ */
+                p = &ext_int_info_timer;
+        else if (code == 0x2401) /* hwc_init is done too early too */
+                p = &ext_int_info_hwc;
+        else
+                p = (ext_int_info_t *)
+                          kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC);
+        if (p == NULL)
+                return -ENOMEM;
+        p->code = code;
+        p->handler = handler;
+        p->next = ext_int_hash[index];
+        ext_int_hash[index] = p;
+        return 0;
+}
+
+int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) {
+        ext_int_info_t *p, *q;
+        int index;
+
+        index = code & 0xff;
+        q = NULL;
+        p = ext_int_hash[index];
+        while (p != NULL) {
+                if (p->code == code && p->handler == handler)
+                        break;
+                q = p;
+                p = p->next;
+        }
+        if (p == NULL)
+                return -ENOENT;
+        if (q != NULL)
+                q->next = p->next;
+        else
+                ext_int_hash[index] = p->next;
+        if (code != 0x1004 && code != 0x2401)
+                kfree(p);
+        return 0;
+}
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/s390_ksyms.c linux/arch/s390x/kernel/s390_ksyms.c
--- v2.4.1/linux/arch/s390x/kernel/s390_ksyms.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/s390_ksyms.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,157 @@
+/*
+ *  arch/s390/kernel/s390_ksyms.c
+ *
+ *  S390 version
+ */
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/highuid.h>
+#include <asm/ccwcache.h>
+#include <asm/debug.h>
+#include <asm/irq.h>
+#include <asm/s390_ext.h>
+#include <asm/s390dyn.h>
+#include <asm/ebcdic.h>
+#include <asm/checksum.h>
+#include <asm/delay.h>
+#include <asm/pgalloc.h>
+#include <asm/idals.h>
+#if CONFIG_CHANDEV
+#include <asm/chandev.h>
+#endif
+#if CONFIG_IP_MULTICAST
+#include <net/arp.h>
+#endif
+
+/*
+ * I/O subsystem
+ */
+EXPORT_SYMBOL(halt_IO);
+EXPORT_SYMBOL(clear_IO);
+EXPORT_SYMBOL(do_IO);
+EXPORT_SYMBOL(resume_IO);
+EXPORT_SYMBOL(ioinfo);
+EXPORT_SYMBOL(get_dev_info_by_irq);
+EXPORT_SYMBOL(get_dev_info_by_devno);
+EXPORT_SYMBOL(get_irq_by_devno);
+EXPORT_SYMBOL(get_devno_by_irq);
+EXPORT_SYMBOL(get_irq_first);
+EXPORT_SYMBOL(get_irq_next);
+EXPORT_SYMBOL(read_conf_data);
+EXPORT_SYMBOL(read_dev_chars);
+EXPORT_SYMBOL(s390_request_irq_special);
+EXPORT_SYMBOL(s390_device_register);
+EXPORT_SYMBOL(s390_device_unregister);
+
+EXPORT_SYMBOL(ccw_alloc_request);
+EXPORT_SYMBOL(ccw_free_request);
+
+EXPORT_SYMBOL(register_external_interrupt);
+EXPORT_SYMBOL(unregister_external_interrupt);
+
+/* 
+ * debug feature
+ */
+EXPORT_SYMBOL(debug_register);
+EXPORT_SYMBOL(debug_unregister);
+EXPORT_SYMBOL(debug_set_level);
+EXPORT_SYMBOL(debug_register_view);
+EXPORT_SYMBOL(debug_unregister_view);
+EXPORT_SYMBOL(debug_event);
+EXPORT_SYMBOL(debug_int_event);
+EXPORT_SYMBOL(debug_text_event);
+EXPORT_SYMBOL(debug_exception);
+EXPORT_SYMBOL(debug_int_exception);
+EXPORT_SYMBOL(debug_text_exception);
+EXPORT_SYMBOL(debug_hex_ascii_view);
+EXPORT_SYMBOL(debug_raw_view);
+EXPORT_SYMBOL(debug_dflt_header_fn);
+
+/*
+ * memory management
+ */
+EXPORT_SYMBOL(_oi_bitmap);
+EXPORT_SYMBOL(_ni_bitmap);
+EXPORT_SYMBOL(_zb_findmap);
+EXPORT_SYMBOL(__copy_from_user_fixup);
+EXPORT_SYMBOL(__copy_to_user_fixup);
+
+/*
+ * semaphore ops
+ */
+EXPORT_SYMBOL(__up);
+EXPORT_SYMBOL(__down);
+EXPORT_SYMBOL(__down_interruptible);
+EXPORT_SYMBOL(__down_trylock);
+
+/*
+ * string functions
+ */
+EXPORT_SYMBOL_NOVERS(memcmp);
+EXPORT_SYMBOL_NOVERS(memset);
+EXPORT_SYMBOL_NOVERS(memmove);
+EXPORT_SYMBOL_NOVERS(strlen);
+EXPORT_SYMBOL_NOVERS(strchr);
+EXPORT_SYMBOL_NOVERS(strcmp);
+EXPORT_SYMBOL_NOVERS(strncat);
+EXPORT_SYMBOL_NOVERS(strncmp);
+EXPORT_SYMBOL_NOVERS(strncpy);
+EXPORT_SYMBOL_NOVERS(strnlen);
+EXPORT_SYMBOL_NOVERS(strrchr);
+EXPORT_SYMBOL_NOVERS(strtok);
+EXPORT_SYMBOL_NOVERS(strpbrk);
+
+EXPORT_SYMBOL_NOVERS(_ascebc_500);
+EXPORT_SYMBOL_NOVERS(_ebcasc_500);
+EXPORT_SYMBOL_NOVERS(_ascebc);
+EXPORT_SYMBOL_NOVERS(_ebcasc);
+EXPORT_SYMBOL_NOVERS(_ebc_tolower);
+EXPORT_SYMBOL_NOVERS(_ebc_toupper);
+
+/*
+ * binfmt_elf loader 
+ */
+EXPORT_SYMBOL(get_pte_slow);
+EXPORT_SYMBOL(get_pmd_slow);
+extern int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs);
+EXPORT_SYMBOL(dump_fpu);
+#ifdef CONFIG_S390_SUPPORT
+extern int setup_arg_pages32(struct linux_binprm *bprm);
+EXPORT_SYMBOL(setup_arg_pages32);
+#endif
+EXPORT_SYMBOL(overflowuid);
+EXPORT_SYMBOL(overflowgid);
+
+/*
+ * misc.
+ */
+EXPORT_SYMBOL(module_list);
+EXPORT_SYMBOL(__udelay);
+#ifdef CONFIG_SMP
+#include <asm/smplock.h>
+EXPORT_SYMBOL(__global_cli);
+EXPORT_SYMBOL(__global_sti);
+EXPORT_SYMBOL(__global_save_flags);
+EXPORT_SYMBOL(__global_restore_flags);
+EXPORT_SYMBOL(lowcore_ptr);
+EXPORT_SYMBOL(global_bh_lock);
+EXPORT_SYMBOL(kernel_flag);
+EXPORT_SYMBOL(smp_ctl_set_bit);
+EXPORT_SYMBOL(smp_ctl_clear_bit);
+#endif
+EXPORT_SYMBOL(kernel_thread);
+#if CONFIG_CHANDEV
+EXPORT_SYMBOL(chandev_register_and_probe);
+EXPORT_SYMBOL(chandev_request_irq);
+EXPORT_SYMBOL(chandev_unregister);
+EXPORT_SYMBOL(chandev_initdevice);
+EXPORT_SYMBOL(chandev_initnetdevice);
+#endif
+#if CONFIG_IP_MULTICAST
+/* Required for lcs gigibit ethernet multicast support */
+EXPORT_SYMBOL(arp_mc_map);
+#endif
+EXPORT_SYMBOL(s390_daemonize);
+EXPORT_SYMBOL (set_normalized_cda);
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/s390fpu.c linux/arch/s390x/kernel/s390fpu.c
--- v2.4.1/linux/arch/s390x/kernel/s390fpu.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/s390fpu.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,87 @@
+/*
+ *  arch/s390/kernel/s390fpu.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *  s390fpu.h functions for saving & restoring the fpu state.
+ *
+ *  I couldn't inline these as linux/sched.h included half the world
+ *  & was required to at the task structure.
+ *  & the functions were too complex to make macros from.
+ *  ( & as usual I didn't feel like debugging inline code ).
+ */
+
+#include <linux/sched.h>
+
+void save_fp_regs(s390_fp_regs *fpregs)
+{
+/*
+ * I don't think we can use STE here as this would load
+ * fp registers 0 & 2 into memory locations 0 & 1 etc. 
+ */	
+	asm volatile ("STFPC 0(%0)\n\t"
+		      "STD   0,8(%0)\n\t"
+		      "STD   1,16(%0)\n\t"
+		      "STD   2,24(%0)\n\t"
+		      "STD   3,32(%0)\n\t"
+		      "STD   4,40(%0)\n\t"
+		      "STD   5,48(%0)\n\t"
+		      "STD   6,56(%0)\n\t"
+		      "STD   7,64(%0)\n\t"
+		      "STD   8,72(%0)\n\t"
+		      "STD   9,80(%0)\n\t"
+		      "STD   10,88(%0)\n\t"
+		      "STD   11,96(%0)\n\t"
+		      "STD   12,104(%0)\n\t"
+		      "STD   13,112(%0)\n\t"
+		      "STD   14,120(%0)\n\t"
+		      "STD   15,128(%0)\n\t"
+                      : 
+		      : "a" (fpregs)
+		      : "memory"
+		);
+}
+
+void restore_fp_regs(s390_fp_regs *fpregs)
+{
+	/* If we don't mask with the FPC_VALID_MASK here
+	 * we've got a very quick shutdown -h now command
+         * via a kernel specification exception.
+	 */
+	fpregs->fpc&=FPC_VALID_MASK;
+	asm volatile ("LFPC 0(%0)\n\t"
+		      "LD   0,8(%0)\n\t"
+		      "LD   1,16(%0)\n\t"
+		      "LD   2,24(%0)\n\t"
+		      "LD   3,32(%0)\n\t"
+		      "LD   4,40(%0)\n\t"
+		      "LD   5,48(%0)\n\t"
+		      "LD   6,56(%0)\n\t"
+		      "LD   7,64(%0)\n\t"
+		      "LD   8,72(%0)\n\t"
+		      "LD   9,80(%0)\n\t"
+		      "LD   10,88(%0)\n\t"
+		      "LD   11,96(%0)\n\t"
+		      "LD   12,104(%0)\n\t"
+		      "LD   13,112(%0)\n\t"
+		      "LD   14,120(%0)\n\t"
+		      "LD   15,128(%0)\n\t"
+                      : 
+		      : "a" (fpregs)
+		      : "memory"
+		);
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/semaphore.c linux/arch/s390x/kernel/semaphore.c
--- v2.4.1/linux/arch/s390x/kernel/semaphore.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/semaphore.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,302 @@
+/*
+ *  linux/arch/S390/kernel/semaphore.c
+ *
+ *  S390 version
+ *    Copyright (C) 1998-2000 IBM Corporation
+ *    Author(s): Martin Schwidefsky
+ *
+ *  Derived from "linux/arch/i386/kernel/semaphore.c
+ *    Copyright (C) 1999, Linus Torvalds
+ *
+ */
+#include <linux/sched.h>
+
+#include <asm/semaphore.h>
+
+/*
+ * Semaphores are implemented using a two-way counter:
+ * The "count" variable is decremented for each process
+ * that tries to acquire the semaphore, while the "sleeping"
+ * variable is a count of such acquires.
+ *
+ * Notably, the inline "up()" and "down()" functions can
+ * efficiently test if they need to do any extra work (up
+ * needs to do something only if count was negative before
+ * the increment operation.
+ *
+ * "sleeping" and the contention routine ordering is
+ * protected by the semaphore spinlock.
+ *
+ * Note that these functions are only called when there is
+ * contention on the lock, and as such all this is the
+ * "non-critical" part of the whole semaphore business. The
+ * critical part is the inline stuff in <asm/semaphore.h>
+ * where we want to avoid any extra jumps and calls.
+ */
+
+/*
+ * Logic:
+ *  - only on a boundary condition do we need to care. When we go
+ *    from a negative count to a non-negative, we wake people up.
+ *  - when we go from a non-negative count to a negative do we
+ *    (a) synchronize with the "sleeper" count and (b) make sure
+ *    that we're on the wakeup list before we synchronize so that
+ *    we cannot lose wakeup events.
+ */
+
+void __up(struct semaphore *sem)
+{
+	wake_up(&sem->wait);
+}
+
+static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
+
+void __down(struct semaphore * sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	tsk->state = TASK_UNINTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	spin_lock_irq(&semaphore_lock);
+	sem->sleepers++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irq(&semaphore_lock);
+
+		schedule();
+		tsk->state = TASK_UNINTERRUPTIBLE;
+		spin_lock_irq(&semaphore_lock);
+	}
+	spin_unlock_irq(&semaphore_lock);
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+	wake_up(&sem->wait);
+}
+
+int __down_interruptible(struct semaphore * sem)
+{
+	int retval = 0;
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+	tsk->state = TASK_INTERRUPTIBLE;
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	spin_lock_irq(&semaphore_lock);
+	sem->sleepers ++;
+	for (;;) {
+		int sleepers = sem->sleepers;
+
+		/*
+		 * With signals pending, this turns into
+		 * the trylock failure case - we won't be
+		 * sleeping, and we* can't get the lock as
+		 * it has contention. Just correct the count
+		 * and exit.
+		 */
+		if (signal_pending(current)) {
+			retval = -EINTR;
+			sem->sleepers = 0;
+			atomic_add(sleepers, &sem->count);
+			break;
+		}
+
+		/*
+		 * Add "everybody else" into it. They aren't
+		 * playing, because we own the spinlock. The
+		 * "-1" is because we're still hoping to get
+		 * the lock.
+		 */
+		if (!atomic_add_negative(sleepers - 1, &sem->count)) {
+			sem->sleepers = 0;
+			break;
+		}
+		sem->sleepers = 1;	/* us - see -1 above */
+		spin_unlock_irq(&semaphore_lock);
+
+		schedule();
+		tsk->state = TASK_INTERRUPTIBLE;
+		spin_lock_irq(&semaphore_lock);
+	}
+	spin_unlock_irq(&semaphore_lock);
+	tsk->state = TASK_RUNNING;
+	remove_wait_queue(&sem->wait, &wait);
+	wake_up(&sem->wait);
+	return retval;
+}
+
+/*
+ * Trylock failed - make sure we correct for
+ * having decremented the count.
+ */
+int __down_trylock(struct semaphore * sem)
+{
+        unsigned long flags;
+	int sleepers;
+
+	spin_lock_irqsave(&semaphore_lock, flags);
+	sleepers = sem->sleepers + 1;
+	sem->sleepers = 0;
+
+	/*
+	 * Add "everybody else" and us into it. They aren't
+	 * playing, because we own the spinlock.
+	 */
+	if (!atomic_add_negative(sleepers, &sem->count))
+		wake_up(&sem->wait);
+
+	spin_unlock_irqrestore(&semaphore_lock, flags);
+	return 1;
+}
+
+void down_read_failed_biased(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue(&sem->wait, &wait);	/* put ourselves at the head of the list */
+
+	for (;;) {
+		if (sem->read_bias_granted && xchg(&sem->read_bias_granted, 0))
+			break;
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (!sem->read_bias_granted)
+			schedule();
+	}
+
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+void down_write_failed_biased(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	add_wait_queue_exclusive(&sem->write_bias_wait, &wait);	/* put ourselves at the end of the list */
+
+	for (;;) {
+		if (sem->write_bias_granted && xchg(&sem->write_bias_granted, 0))
+			break;
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (!sem->write_bias_granted)
+			schedule();
+	}
+
+	remove_wait_queue(&sem->write_bias_wait, &wait);
+	tsk->state = TASK_RUNNING;
+
+	/* if the lock is currently unbiased, awaken the sleepers
+	 * FIXME: this wakes up the readers early in a bit of a
+	 * stampede -> bad!
+	 */
+	if (atomic_read(&sem->count) >= 0)
+		wake_up(&sem->wait);
+}
+
+/* Wait for the lock to become unbiased.  Readers
+ * are non-exclusive. =)
+ */
+void down_read_failed(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	up_read(sem);	/* this takes care of granting the lock */
+
+	add_wait_queue(&sem->wait, &wait);
+
+	while (atomic_read(&sem->count) < 0) {
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (atomic_read(&sem->count) >= 0)
+			break;
+		schedule();
+	}
+
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+/* Wait for the lock to become unbiased. Since we're
+ * a writer, we'll make ourselves exclusive.
+ */
+void down_write_failed(struct rw_semaphore *sem)
+{
+	struct task_struct *tsk = current;
+	DECLARE_WAITQUEUE(wait, tsk);
+
+	up_write(sem);	/* this takes care of granting the lock */
+
+	add_wait_queue_exclusive(&sem->wait, &wait);
+
+	while (atomic_read(&sem->count) < 0) {
+		set_task_state(tsk, TASK_UNINTERRUPTIBLE);
+		if (atomic_read(&sem->count) >= 0)
+			break;	/* we must attempt to acquire or bias the lock */
+		schedule();
+	}
+
+	remove_wait_queue(&sem->wait, &wait);
+	tsk->state = TASK_RUNNING;
+}
+
+/* Called when someone has done an up that transitioned from
+ * negative to non-negative, meaning that the lock has been
+ * granted to whomever owned the bias.
+ */
+void rwsem_wake_readers(struct rw_semaphore *sem)
+{
+	if (xchg(&sem->read_bias_granted, 1))
+		BUG();
+	wake_up(&sem->wait);
+}
+
+void rwsem_wake_writers(struct rw_semaphore *sem)
+{
+	if (xchg(&sem->write_bias_granted, 1))
+		BUG();
+	wake_up(&sem->write_bias_wait);
+}
+
+void __down_read_failed(int count, struct rw_semaphore *sem) 
+{
+	do {
+		if (count == -1) {
+			down_read_failed_biased(sem);
+			break;
+		}
+		down_read_failed(sem);
+		count = atomic_dec_return(&sem->count);
+	} while (count != 0);
+}
+
+void __down_write_failed(int count, struct rw_semaphore *sem)
+{
+	do {
+		if (count < 0 && count > -RW_LOCK_BIAS) {
+			down_write_failed_biased(sem);
+			break;
+		}
+		down_write_failed(sem);
+		count = atomic_add_return(-RW_LOCK_BIAS, &sem->count);
+	} while (count != 0);
+}
+
+void __rwsem_wake(int count, struct rw_semaphore *sem)
+{
+	if (count == 0)
+		rwsem_wake_readers(sem);
+	else
+		rwsem_wake_writers(sem);
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/setup.c linux/arch/s390x/kernel/setup.c
--- v2.4.1/linux/arch/s390x/kernel/setup.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/setup.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,380 @@
+/*
+ *  arch/s390/kernel/setup.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "arch/i386/kernel/setup.c"
+ *    Copyright (C) 1995, Linus Torvalds
+ */
+
+/*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/malloc.h>
+#include <linux/user.h>
+#include <linux/a.out.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/config.h>
+#include <linux/init.h>
+#ifdef CONFIG_BLK_DEV_RAM
+#include <linux/blk.h>
+#endif
+#include <linux/bootmem.h>
+#include <linux/console.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/smp.h>
+#include <asm/mmu_context.h>
+
+/*
+ * Machine setup..
+ */
+__u16 boot_cpu_addr;
+int cpus_initialized = 0;
+unsigned long cpu_initialized = 0;
+volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
+
+/*
+ * Setup options
+ */
+
+#ifdef CONFIG_BLK_DEV_RAM
+extern int rd_doload;                  /* 1 = load ramdisk, 0 = don't load */
+extern int rd_prompt;           /* 1 = prompt for ramdisk, 0 = don't prompt*/
+extern int rd_image_start;             /* starting block # of image        */
+#endif
+
+extern int root_mountflags;
+extern int _text,_etext, _edata, _end;
+
+
+/*
+ * This is set up by the setup-routine at boot-time
+ * for S390 need to find out, what we have to setup
+ * using address 0x10400 ...
+ */
+
+#include <asm/setup.h>
+
+static char command_line[COMMAND_LINE_SIZE] = { 0, };
+       char saved_command_line[COMMAND_LINE_SIZE];
+
+static struct resource code_resource = { "Kernel code", 0x100000, 0 };
+static struct resource data_resource = { "Kernel data", 0, 0 };
+
+/*
+ * cpu_init() initializes state that is per-CPU.
+ */
+void __init cpu_init (void)
+{
+        int nr = smp_processor_id();
+        int addr = hard_smp_processor_id();
+
+        if (test_and_set_bit(nr,&cpu_initialized)) {
+                printk("CPU#%d ALREADY INITIALIZED!!!!!!!!!\n", nr);
+                for (;;) __sti();
+        }
+        cpus_initialized++;
+
+        /*
+         * Store processor id in lowcore (used e.g. in timer_interrupt)
+         */
+        asm volatile ("stidp %0": "=m" (S390_lowcore.cpu_data.cpu_id));
+        S390_lowcore.cpu_data.cpu_addr = addr;
+        S390_lowcore.cpu_data.cpu_nr = nr;
+
+        /*
+         * Force FPU initialization:
+         */
+        current->flags &= ~PF_USEDFPU;
+        current->used_math = 0;
+
+        /* Setup active_mm for idle_task  */
+        atomic_inc(&init_mm.mm_count);
+        current->active_mm = &init_mm;
+        if (current->mm)
+                BUG();
+        enter_lazy_tlb(&init_mm, current, nr);
+}
+
+/*
+ * VM halt and poweroff setup routines
+ */
+char vmhalt_cmd[128] = "";
+char vmpoff_cmd[128] = "";
+
+static inline void strncpy_skip_quote(char *dst, char *src, int n)
+{
+        int sx, dx;
+
+        dx = 0;
+        for (sx = 0; src[sx] != 0; sx++) {
+                if (src[sx] == '"') continue;
+                dst[dx++] = src[sx];
+                if (dx >= n) break;
+        }
+}
+
+static int __init vmhalt_setup(char *str)
+{
+        strncpy_skip_quote(vmhalt_cmd, str, 127);
+        vmhalt_cmd[127] = 0;
+        return 1;
+}
+
+__setup("vmhalt=", vmhalt_setup);
+
+static int __init vmpoff_setup(char *str)
+{
+        strncpy_skip_quote(vmpoff_cmd, str, 127);
+        vmpoff_cmd[127] = 0;
+        return 1;
+}
+
+__setup("vmpoff=", vmpoff_setup);
+
+/*
+ * Reboot, halt and power_off routines for non SMP.
+ */
+#ifndef CONFIG_SMP
+void machine_restart(char * __unused)
+{
+	reipl(S390_lowcore.ipl_device);
+}
+
+void machine_halt(void)
+{
+        if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+                cpcmd(vmhalt_cmd, NULL, 0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+}
+
+void machine_power_off(void)
+{
+        if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+                cpcmd(vmpoff_cmd, NULL, 0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+}
+#endif
+
+/*
+ * Setup function called from init/main.c just after the banner
+ * was printed.
+ */
+void __init setup_arch(char **cmdline_p)
+{
+        unsigned long bootmap_size;
+        unsigned long memory_start, memory_end;
+        char c = ' ', cn, *to = command_line, *from = COMMAND_LINE;
+	struct resource *res;
+	unsigned long start_pfn, end_pfn;
+        static unsigned int smptrap=0;
+        unsigned long delay = 0;
+        int len = 0;
+
+        if (smptrap)
+                return;
+        smptrap=1;
+
+        printk("Command line is: %s\n", COMMAND_LINE);
+
+        /*
+         * Setup lowcore information for boot cpu
+         */
+        cpu_init();
+        boot_cpu_addr = S390_lowcore.cpu_data.cpu_addr;
+        __cpu_logical_map[0] = boot_cpu_addr;
+
+        /*
+         * print what head.S has found out about the machine 
+         */
+	printk((MACHINE_IS_VM) ?
+	       "We are running under VM\n" :
+	       "We are running native\n");
+
+        ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
+#ifdef CONFIG_BLK_DEV_RAM
+        rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
+        rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
+        rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
+#endif
+	/* nasty stuff with PARMAREAs. we use head.S or parameterline
+	  if (!MOUNT_ROOT_RDONLY)
+	  root_mountflags &= ~MS_RDONLY;
+	*/
+        memory_start = (unsigned long) &_end;    /* fixit if use $CODELO etc*/
+	memory_end = MEMORY_SIZE;                /* detected in head.s */
+        init_mm.start_code = PAGE_OFFSET;
+        init_mm.end_code = (unsigned long) &_etext;
+        init_mm.end_data = (unsigned long) &_edata;
+        init_mm.brk = (unsigned long) &_end;
+
+	code_resource.start = (unsigned long) &_text;
+	code_resource.end = (unsigned long) &_etext - 1;
+	data_resource.start = (unsigned long) &_etext;
+	data_resource.end = (unsigned long) &_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';
+
+        for (;;) {
+                /*
+                 * "mem=XXX[kKmM]" sets memsize 
+                 */
+                if (c == ' ' && strncmp(from, "mem=", 4) == 0) {
+                        if (to != command_line) to--;
+                        memory_end = simple_strtoul(from+4, &from, 0);
+                        if ( *from == 'K' || *from == 'k' ) {
+                                memory_end = memory_end << 10;
+                                from++;
+                        } else if ( *from == 'M' || *from == 'm' ) {
+                                memory_end = memory_end << 20;
+                                from++;
+                        }
+                }
+                /*
+                 * "ipldelay=XXX[sm]" sets ipl delay in seconds or minutes
+                 */
+                if (c == ' ' && strncmp(from, "ipldelay=", 9) == 0) {
+			if (to != command_line) to--;
+                        delay = simple_strtoul(from+9, &from, 0);
+			if (*from == 's' || *from == 'S') {
+				delay = delay*1000000;
+				from++;
+			} else if (*from == 'm' || *from == 'M') {
+				delay = delay*60*1000000;
+				from++;
+			}
+			/* now wait for the requestion amount of time */
+			udelay(delay);
+                }
+                cn = *(from++);
+                if (!cn)
+                        break;
+                if (cn == '\n')
+                        cn = ' ';  /* replace newlines with space */
+                if (cn == ' ' && c == ' ')
+                        continue;  /* remove additional spaces */
+                c = cn;
+                if (COMMAND_LINE_SIZE <= ++len)
+                        break;
+                *(to++) = c;
+        }
+        if (c == ' ' && to > command_line) to--;
+        *to = '\0';
+        *cmdline_p = command_line;
+
+	/*
+	 * partially used pages are not usable - thus
+	 * we are rounding upwards:
+	 */
+	start_pfn = (__pa(&_end) + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	end_pfn = memory_end >> PAGE_SHIFT;
+
+	/*
+	 * Initialize the boot-time allocator
+	 */
+	bootmap_size = init_bootmem(start_pfn, end_pfn);
+
+	/*
+	 * Register RAM pages with the bootmem allocator.
+	 */
+	free_bootmem(start_pfn << PAGE_SHIFT, 
+		     (end_pfn - start_pfn) << PAGE_SHIFT);
+
+        /*
+         * Reserve the bootmem bitmap itself as well. We do this in two
+         * steps (first step was init_bootmem()) because this catches
+         * the (very unlikely) case of us accidentally initializing the
+         * bootmem allocator with an invalid RAM area.
+         */
+        reserve_bootmem(start_pfn << PAGE_SHIFT, bootmap_size);
+
+
+
+
+#ifdef CONFIG_BLK_DEV_INITRD
+        if (INITRD_START) {
+		if (INITRD_START + INITRD_SIZE <= memory_end) {
+			reserve_bootmem(INITRD_START, INITRD_SIZE);
+			initrd_start = INITRD_START;
+			initrd_end = initrd_start + INITRD_SIZE;
+		} else {
+                        printk("initrd extends beyond end of memory "
+                               "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+                               initrd_start + INITRD_SIZE, memory_end);
+                        initrd_start = initrd_end = 0;
+		}
+        }
+#endif
+
+        paging_init();
+
+	res = alloc_bootmem_low(sizeof(struct resource));
+	res->start = 0;
+	res->end = memory_end;
+	res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+	request_resource(&iomem_resource, res);
+	request_resource(res, &code_resource);
+	request_resource(res, &data_resource);
+}
+
+void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
+{
+   printk("cpu %d "
+#ifdef CONFIG_SMP
+           "phys_idx=%d "
+#endif
+           "vers=%02X ident=%06X machine=%04X unused=%04X\n",
+           cpuinfo->cpu_nr,
+#ifdef CONFIG_SMP
+           cpuinfo->cpu_addr,
+#endif
+           cpuinfo->cpu_id.version,
+           cpuinfo->cpu_id.ident,
+           cpuinfo->cpu_id.machine,
+           cpuinfo->cpu_id.unused);
+}
+
+/*
+ *	Get CPU information for use by the procfs.
+ */
+
+int get_cpuinfo(char * buffer)
+{
+        struct cpuinfo_S390 *cpuinfo;
+        char *p = buffer;
+        int i;
+
+        p += sprintf(p,"vendor_id       : IBM/S390\n"
+                       "# processors    : %i\n"
+                       "bogomips per cpu: %lu.%02lu\n",
+                       smp_num_cpus, loops_per_jiffy/(500000/HZ),
+                       (loops_per_jiffy/(5000/HZ))%100);
+        for (i = 0; i < smp_num_cpus; i++) {
+                cpuinfo = &safe_get_cpu_lowcore(i).cpu_data;
+                p += sprintf(p,"processor %i: "
+                               "version = %02X,  "
+                               "identification = %06X,  "
+                               "machine = %04X\n",
+                               i, cpuinfo->cpu_id.version,
+                               cpuinfo->cpu_id.ident,
+                               cpuinfo->cpu_id.machine);
+        }
+        return p - buffer;
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/signal.c linux/arch/s390x/kernel/signal.c
--- v2.4.1/linux/arch/s390x/kernel/signal.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/signal.c	Fri Feb 16 16:02:35 2001
@@ -0,0 +1,595 @@
+/*
+ *  arch/s390/kernel/signal.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *    Based on Intel version
+ * 
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/* pretcode & sig are used to store the return addr on Intel
+   & the signal no as the first parameter we do this differently
+   using gpr14 & gpr2. */
+
+#define SIGFRAME_COMMON \
+__u8     callee_used_stack[__SIGNAL_FRAMESIZE]; \
+struct sigcontext sc; \
+_sigregs sregs; \
+__u8 retcode[S390_SYSCALL_SIZE];
+
+typedef struct 
+{
+	SIGFRAME_COMMON
+} sigframe;
+
+typedef struct 
+{
+	SIGFRAME_COMMON
+	struct siginfo info;
+	struct ucontext uc;
+} rt_sigframe;
+
+asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
+
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+		return -EFAULT;
+	if (from->si_code < 0)
+		return __copy_to_user(to, from, sizeof(siginfo_t));
+	else {
+		int err;
+
+		/* If you change siginfo_t structure, please be sure
+		   this code is fixed accordingly.
+		   It should never copy any pad contained in the structure
+		   to avoid security leaks, but must copy the generic
+		   3 ints plus the relevant union member.  */
+		err = __put_user(from->si_signo, &to->si_signo);
+		err |= __put_user(from->si_errno, &to->si_errno);
+		err |= __put_user((short)from->si_code, &to->si_code);
+		/* First 32bits of unions are always present.  */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		switch (from->si_code >> 16) {
+		case __SI_FAULT >> 16:
+			break;
+		case __SI_CHLD >> 16:
+			err |= __put_user(from->si_utime, &to->si_utime);
+			err |= __put_user(from->si_stime, &to->si_stime);
+			err |= __put_user(from->si_status, &to->si_status);
+		default:
+			err |= __put_user(from->si_uid, &to->si_uid);
+			break;
+		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		}
+		return err;
+	}
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
+{
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	regs->gprs[2] = -EINTR;
+
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (do_signal(regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int
+sys_rt_sigsuspend(struct pt_regs * regs,sigset_t *unewset, size_t sigsetsize)
+{
+	sigset_t saveset, newset;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&newset, unewset, sizeof(newset)))
+		return -EFAULT;
+	sigdelsetmask(&newset, ~_BLOCKABLE);
+
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	current->blocked = newset;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	regs->gprs[2] = -EINTR;
+
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (do_signal(regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int 
+sys_sigaction(int sig, const struct old_sigaction *act,
+	      struct old_sigaction *oact)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+
+	if (act) {
+		old_sigset_t mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+	}
+
+	return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
+{
+	return do_sigaltstack(uss, uoss, regs->gprs[15]);
+}
+
+
+
+
+static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
+{
+	int err;
+	s390_fp_regs fpregs;
+  
+	err = __copy_to_user(&sregs->regs,regs,sizeof(s390_regs_common));
+	if(!err)
+	{
+		save_fp_regs(&fpregs);
+		err=__copy_to_user(&sregs->fpregs,&fpregs,sizeof(fpregs));
+	}
+	return(err);
+	
+}
+
+static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
+{
+	int err;
+	s390_fp_regs fpregs;
+	psw_t saved_psw=regs->psw;
+	err=__copy_from_user(regs,&sregs->regs,sizeof(s390_regs_common));
+	if(!err)
+	{
+		regs->orig_gpr2 = -1;		/* disable syscall checks */
+		regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
+		(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
+		regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
+		(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
+		err=__copy_from_user(&fpregs,&sregs->fpregs,sizeof(fpregs));
+		if(!err)
+			restore_fp_regs(&fpregs);
+	}
+	return(err);
+}
+
+static int
+restore_sigcontext(struct sigcontext *sc, pt_regs *regs,
+		 _sigregs *sregs,sigset_t *set)
+{
+	unsigned int err;
+
+	err=restore_sigregs(regs,sregs);
+	if(!err)
+		err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE);
+		return(err);
+}
+
+int sigreturn_common(struct pt_regs *regs,int framesize)
+{
+	sigframe *frame = (sigframe *)regs->gprs[15];
+	sigset_t set;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		return -1;
+	if (restore_sigcontext(&frame->sc,regs,&frame->sregs,&set))
+	        return -1;
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	return 0;
+}
+
+asmlinkage long sys_sigreturn(struct pt_regs *regs)
+{
+
+	if (sigreturn_common(regs,sizeof(sigframe)))
+		goto badframe;
+	return regs->gprs[2];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
+{
+	rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
+
+	if (sigreturn_common(regs,sizeof(rt_sigframe)))
+		goto badframe;
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
+	return regs->gprs[2];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+/*
+ * Set up a signal frame.
+ */
+
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+{
+	unsigned long sp;
+
+	/* Default to using normal stack */
+	sp = regs->gprs[15];
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (! on_sig_stack(sp))
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	/* This is the legacy signal stack switching. */
+	else if (!user_mode(regs) &&
+		 !(ka->sa.sa_flags & SA_RESTORER) &&
+		 ka->sa.sa_restorer) {
+		sp = (unsigned long) ka->sa.sa_restorer;
+	}
+
+	return (void *)((sp - frame_size) & -8ul);
+}
+
+static void *setup_frame_common(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs,
+				int frame_size,u16 retcode)
+{
+	sigframe *frame;
+	int err;
+
+	frame = get_sigframe(ka, regs,frame_size);
+	if (!access_ok(VERIFY_WRITE, frame,frame_size))
+		return 0;
+	err = save_sigregs(regs,&frame->sregs);
+	if(!err)
+		err=__put_user(&frame->sregs,&frame->sc.sregs);
+	if(!err)
+
+		err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE);
+	if(!err)
+	{
+		regs->gprs[2]=(current->exec_domain
+		           && current->exec_domain->signal_invmap
+		           && sig < 32
+		           ? current->exec_domain->signal_invmap[sig]
+		           : sig);
+		/* Set up registers for signal handler */
+		regs->gprs[15] = (addr_t)frame;
+		regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+	}
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+                regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+	} else {
+                regs->gprs[14] = FIX_PSW(frame->retcode);
+		err |= __put_user(retcode, (u16 *)(frame->retcode));
+	}
+	return(err ? 0:frame);
+}
+
+static void setup_frame(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs)
+{
+	sigframe *frame;
+
+	if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
+		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
+		goto give_sigsegv;
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+		current->comm, current->pid, frame, regs->eip, frame->pretcode);
+#endif
+	/* Martin wants this for pthreads */
+	regs->gprs[3] = (addr_t)&frame->sc;
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs * regs)
+{
+	rt_sigframe *frame;
+	addr_t      orig_sp=regs->gprs[15];
+	int err;
+
+	if((frame=setup_frame_common(sig,ka,set,regs,sizeof(rt_sigframe),
+		    (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+		goto give_sigsegv;
+	
+	err = copy_siginfo_to_user(&frame->info, info);
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(orig_sp),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= __put_user(&frame->sc,&frame->uc.sc);
+	regs->gprs[3] = (addr_t)&frame->info;
+	regs->gprs[4] = (addr_t)&frame->uc;
+
+	if (err)
+		goto give_sigsegv;
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+		current->comm, current->pid, frame, regs->eip, frame->pretcode);
+#endif
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */	
+
+static void
+handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+	/* Are we from a system call? */
+	if (regs->orig_gpr2 >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->gprs[2]) {
+			case -ERESTARTNOHAND:
+				regs->gprs[2] = -EINTR;
+				break;
+
+			case -ERESTARTSYS:
+				if (!(ka->sa.sa_flags & SA_RESTART)) {
+					regs->gprs[2] = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				regs->gprs[2] = regs->orig_gpr2;
+				regs->psw.addr -= 2;
+		}
+	}
+
+	/* Set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		setup_frame(sig, ka, oldset, regs);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sigmask_lock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigaddset(&current->blocked,sig);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+int do_signal(struct pt_regs *regs, sigset_t *oldset)
+{
+	siginfo_t info;
+	struct k_sigaction *ka;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return 1;
+
+	if (!oldset)
+		oldset = &current->blocked;
+#ifdef CONFIG_S390_SUPPORT 
+	if (current->thread.flags & S390_FLAG_31BIT) {
+		extern asmlinkage int do_signal32(struct pt_regs *regs, sigset_t *oldset); 
+		return do_signal32(regs, oldset);
+        }
+#endif 
+
+	for (;;) {
+		unsigned long signr;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		if (!signr)
+			break;
+
+		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+			/* Let the debugger run.  */
+			current->exit_code = signr;
+			set_current_state(TASK_STOPPED);
+			notify_parent(current, SIGCHLD);
+			schedule();
+
+			/* We're back.  Did the debugger cancel the sig?  */
+			if (!(signr = current->exit_code))
+				continue;
+			current->exit_code = 0;
+
+			/* The debugger continued.  Ignore SIGSTOP.  */
+			if (signr == SIGSTOP)
+				continue;
+
+			/* Update the siginfo structure.  Is this good?  */
+			if (signr != info.si_signo) {
+				info.si_signo = signr;
+				info.si_errno = 0;
+				info.si_code = SI_USER;
+				info.si_pid = current->p_pptr->pid;
+				info.si_uid = current->p_pptr->uid;
+			}
+
+			/* If the (new) signal is now blocked, requeue it.  */
+			if (sigismember(&current->blocked, signr)) {
+				send_sig_info(signr, &info, current);
+				continue;
+			}
+		}
+
+		ka = &current->sig->action[signr-1];
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
+				continue;
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+				/* nothing */;
+			continue;
+		}
+
+		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr;
+
+			/* Init gets no signals it doesn't want.  */
+			if (current->pid == 1)
+				continue;
+
+			switch (signr) {
+			case SIGCONT: case SIGCHLD: case SIGWINCH:
+				continue;
+
+			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+				/* FALLTHRU */
+
+			case SIGSTOP:
+				set_current_state(TASK_STOPPED);
+				current->exit_code = signr;
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+					notify_parent(current, SIGCHLD);
+				schedule();
+				continue;
+
+			case SIGQUIT: case SIGILL: case SIGTRAP:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
+                                if (do_coredump(signr, regs))
+                                        exit_code |= 0x80;
+                                /* FALLTHRU */
+
+			default:
+				lock_kernel();
+				sigaddset(&current->pending.signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
+				/* NOTREACHED */
+			}
+		}
+
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, ka, &info, oldset, regs);
+		return 1;
+	}
+
+	/* Did we come from a system call? */
+	if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
+		/* Restart the system call - no handlers present */
+		if (regs->gprs[2] == -ERESTARTNOHAND ||
+		    regs->gprs[2] == -ERESTARTSYS ||
+		    regs->gprs[2] == -ERESTARTNOINTR) {
+			regs->gprs[2] = regs->orig_gpr2;
+			regs->psw.addr -= 2;
+		}
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/signal32.c linux/arch/s390x/kernel/signal32.c
--- v2.4.1/linux/arch/s390x/kernel/signal32.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/signal32.c	Fri Feb 16 16:02:35 2001
@@ -0,0 +1,725 @@
+/*
+ *  arch/s390/kernel/signal32.c
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *               Gerhard Tonn (ton@de.ibm.com)                  
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ *  1997-11-28  Modified for POSIX.1b signals by Richard Henderson
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <asm/ucontext.h>
+#include <asm/uaccess.h>
+#include "linux32.h"
+
+#define DEBUG_SIG 0
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/* pretcode & sig are used to store the return addr on Intel
+   & the signal no as the first parameter we do this differently
+   using gpr14 & gpr2. */
+
+#define SIGFRAME_COMMON32 \
+__u8     callee_used_stack[__SIGNAL_FRAMESIZE32]; \
+struct sigcontext32 sc; \
+_sigregs32 sregs; \
+__u8 retcode[S390_SYSCALL_SIZE];
+
+typedef struct 
+{
+	SIGFRAME_COMMON32
+} sigframe32;
+
+typedef struct 
+{
+	SIGFRAME_COMMON32
+	struct siginfo32 info;
+	struct ucontext32 uc;
+} rt_sigframe32;
+
+asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
+
+int do_signal32(struct pt_regs *regs, sigset_t *oldset);
+
+int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+{
+	int err;
+
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+		return -EFAULT;
+
+	/* If you change siginfo_t structure, please be sure
+	   this code is fixed accordingly.
+	   It should never copy any pad contained in the structure
+	   to avoid security leaks, but must copy the generic
+	   3 ints plus the relevant union member.  
+	   This routine must convert siginfo from 64bit to 32bit as well
+	   at the same time.  */
+	err = __put_user(from->si_signo, &to->si_signo);
+	err |= __put_user(from->si_errno, &to->si_errno);
+	err |= __put_user((short)from->si_code, &to->si_code);
+	if (from->si_code < 0)
+		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+	else {
+		switch (from->si_code >> 16) {
+		case __SI_KILL >> 16:
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_uid, &to->si_uid);
+			break;
+		case __SI_CHLD >> 16:
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_uid, &to->si_uid);
+			err |= __put_user(from->si_utime, &to->si_utime);
+			err |= __put_user(from->si_stime, &to->si_stime);
+			err |= __put_user(from->si_status, &to->si_status);
+			break;
+		case __SI_FAULT >> 16:
+			err |= __put_user(from->si_addr, &to->si_addr);
+			break;
+		case __SI_POLL >> 16:
+		case __SI_TIMER >> 16:
+			err |= __put_user(from->si_band, &to->si_band);
+			err |= __put_user(from->si_fd, &to->si_fd);
+			break;
+		default:
+			break;
+		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		}
+	}
+	return err;
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
+{
+	sigset_t saveset;
+
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sigmask_lock);
+	saveset = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	regs->gprs[2] = -EINTR;
+
+	while (1) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule();
+		if (do_signal32(regs, &saveset))
+			return -EINTR;
+	}
+}
+
+asmlinkage int
+sys32_rt_sigsuspend(struct pt_regs * regs,sigset_t32 *unewset, size_t sigsetsize)
+{
+	sigset_t saveset, newset;
+	sigset_t32 set32;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t))
+		return -EINVAL;
+
+	if (copy_from_user(&set32, unewset, sizeof(set32)))
+		return -EFAULT;
+	switch (_NSIG_WORDS) {
+	case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
+	case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
+	case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
+	case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
+	}
+        sigdelsetmask(&newset, ~_BLOCKABLE);
+
+        spin_lock_irq(&current->sigmask_lock);
+        saveset = current->blocked;
+        current->blocked = newset;
+        recalc_sigpending(current);
+        spin_unlock_irq(&current->sigmask_lock);
+        regs->gprs[2] = -EINTR;
+
+        while (1) {
+                set_current_state(TASK_INTERRUPTIBLE);
+                schedule();
+                if (do_signal32(regs, &saveset))
+                        return -EINTR;
+        }
+}                                                         
+
+asmlinkage int
+sys32_sigaction(int sig, const struct old_sigaction32 *act,
+		 struct old_sigaction32 *oact)
+{
+        struct k_sigaction new_ka, old_ka;
+        int ret;
+
+        if (act) {
+		old_sigset_t32 mask;
+		if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+		    __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
+		    __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
+			return -EFAULT;
+		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user(mask, &act->sa_mask);
+		siginitset(&new_ka.sa.sa_mask, mask);
+        }
+
+        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+		    __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
+		    __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
+			return -EFAULT;
+		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+        }
+
+	return ret;
+}
+
+int
+do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
+
+asmlinkage long 
+sys32_rt_sigaction(int sig, const struct sigaction32 *act,
+	   struct sigaction32 *oact,  size_t sigsetsize)
+{
+	struct k_sigaction new_ka, old_ka;
+	int ret;
+	sigset_t32 set32;
+
+	/* XXX: Don't preclude handling different sized sigset_t's.  */
+	if (sigsetsize != sizeof(sigset_t32))
+		return -EINVAL;
+
+	if (act) {
+		ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
+		ret |= __copy_from_user(&set32, &act->sa_mask,
+					sizeof(sigset_t32));
+		switch (_NSIG_WORDS) {
+		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
+				| (((long)set32.sig[7]) << 32);
+		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
+				| (((long)set32.sig[5]) << 32);
+		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
+				| (((long)set32.sig[3]) << 32);
+		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
+				| (((long)set32.sig[1]) << 32);
+		}
+		ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
+		
+		if (ret)
+			return -EFAULT;
+	}
+
+	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
+
+	if (!ret && oact) {
+		switch (_NSIG_WORDS) {
+		case 4:
+			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
+			set32.sig[6] = old_ka.sa.sa_mask.sig[3];
+		case 3:
+			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
+			set32.sig[4] = old_ka.sa.sa_mask.sig[2];
+		case 2:
+			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
+			set32.sig[2] = old_ka.sa.sa_mask.sig[1];
+		case 1:
+			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
+			set32.sig[0] = old_ka.sa.sa_mask.sig[0];
+		}
+		ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
+		ret |= __copy_to_user(&oact->sa_mask, &set32,
+				      sizeof(sigset_t32));
+		ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
+	}
+
+	return ret;
+}
+
+asmlinkage int
+sys32_sigaltstack(const stack_t32 *uss, stack_t32 *uoss, struct pt_regs *regs)
+{
+	stack_t kss, koss;
+	int ret, err = 0;
+	mm_segment_t old_fs = get_fs();
+
+	if (uss) {
+		if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
+			return -EFAULT;
+		err |= __get_user(kss.ss_sp, &uss->ss_sp);
+		err |= __get_user(kss.ss_size, &uss->ss_size);
+		err |= __get_user(kss.ss_flags, &uss->ss_flags);
+		if (err)
+			return -EFAULT;
+	}
+
+	set_fs (KERNEL_DS);
+	ret = do_sigaltstack(uss ? &kss : NULL , uoss ? &koss : NULL, regs->gprs[15]);
+	set_fs (old_fs);
+
+	if (!ret && uoss) {
+		if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
+			return -EFAULT;
+		err |= __put_user(koss.ss_sp, &uoss->ss_sp);
+		err |= __put_user(koss.ss_size, &uoss->ss_size);
+		err |= __put_user(koss.ss_flags, &uoss->ss_flags);
+		if (err)
+			return -EFAULT;
+	}
+	return ret;
+}
+
+static int save_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
+{
+	int err = 0;
+	s390_fp_regs fpregs;
+	int i;
+
+	for(i=0; i<NUM_GPRS; i++) 
+		err |= __put_user(regs->gprs[i], &sregs->regs.gprs[i]);  
+	for(i=0; i<NUM_ACRS; i++)
+		err |= __put_user(regs->acrs[i], &sregs->regs.acrs[i]);  
+	err |= __copy_to_user(&sregs->regs.psw.mask, &regs->psw.mask, 4);
+	err |= __copy_to_user(&sregs->regs.psw.addr, ((char*)&regs->psw.addr)+4, 4);
+	if(!err)
+	{
+		save_fp_regs(&fpregs);
+		__put_user(fpregs.fpc, &sregs->fpregs.fpc);
+		for(i=0; i<NUM_FPRS; i++)
+			err |= __put_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d);  
+	}
+	return(err);
+	
+}
+
+static int restore_sigregs32(struct pt_regs *regs,_sigregs32 *sregs)
+{
+	int err = 0;
+	s390_fp_regs fpregs;
+	psw_t saved_psw=regs->psw;
+	int i;
+
+	for(i=0; i<NUM_GPRS; i++)
+		err |= __get_user(regs->gprs[i], &sregs->regs.gprs[i]);  
+	for(i=0; i<NUM_ACRS; i++)
+		err |= __get_user(regs->acrs[i], &sregs->regs.acrs[i]);  
+	err |= __copy_from_user(&regs->psw.mask, &sregs->regs.psw.mask, 4);
+	err |= __copy_from_user(((char*)&regs->psw.addr)+4, &sregs->regs.psw.addr, 4);
+
+	if(!err)
+	{
+		regs->orig_gpr2 = -1;		/* disable syscall checks */
+		regs->psw.mask=(saved_psw.mask&~PSW_MASK_DEBUGCHANGE)|
+		(regs->psw.mask&PSW_MASK_DEBUGCHANGE);
+		regs->psw.addr=(saved_psw.addr&~PSW_ADDR_DEBUGCHANGE)|
+		(regs->psw.addr&PSW_ADDR_DEBUGCHANGE);
+		__get_user(fpregs.fpc, &sregs->fpregs.fpc);
+                for(i=0; i<NUM_FPRS; i++)
+                        err |= __get_user(fpregs.fprs[i].d, &sregs->fpregs.fprs[i].d);              
+		if(!err)
+			restore_fp_regs(&fpregs);
+	}
+	return(err);
+}
+
+static int
+restore_sigcontext32(struct sigcontext32 *sc, pt_regs *regs,
+		 _sigregs32 *sregs,sigset_t *set)
+{
+	unsigned int err;
+
+	err=restore_sigregs32(regs,sregs);
+	if(!err)
+		err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE32);
+	return(err);
+}
+
+int sigreturn_common32(struct pt_regs *regs)
+{
+	sigframe32 *frame = (sigframe32 *)regs->gprs[15];
+	sigset_t set;
+
+	if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+		return -1;
+	if (restore_sigcontext32(&frame->sc,regs,&frame->sregs,&set))
+	        return -1;
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sigmask_lock);
+	current->blocked = set;
+	recalc_sigpending(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	return 0;
+}
+
+asmlinkage long sys32_sigreturn(struct pt_regs *regs)
+{
+
+	if (sigreturn_common32(regs))
+		goto badframe;
+	return regs->gprs[2];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
+{
+	rt_sigframe32 *frame = (rt_sigframe32 *)regs->gprs[15];
+	stack_t st;
+	int err;
+	mm_segment_t old_fs = get_fs();
+
+	if (sigreturn_common32(regs))
+		goto badframe;
+
+	err = __get_user(st.ss_sp, &frame->uc.uc_stack.ss_sp);
+	st.ss_sp = (void *) A((unsigned long)st.ss_sp);
+	err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
+	err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
+	if (err)
+		goto badframe; 
+	set_fs (KERNEL_DS);   
+	/* It is more difficult to avoid calling this function than to
+	   call it and ignore errors.  */
+	do_sigaltstack(&st, NULL, regs->gprs[15]);
+	set_fs (old_fs);
+
+	return regs->gprs[2];
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}	
+
+/*
+ * Set up a signal frame.
+ */
+
+
+/*
+ * Determine which stack to use..
+ */
+static inline void *
+get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
+{
+	unsigned long sp;
+
+	/* Default to using normal stack */
+	sp = (unsigned long) A(regs->gprs[15]);
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (! on_sig_stack(sp))
+			sp = current->sas_ss_sp + current->sas_ss_size;
+	}
+
+	/* This is the legacy signal stack switching. */
+	else if (!user_mode(regs) &&
+		 !(ka->sa.sa_flags & SA_RESTORER) &&
+		 ka->sa.sa_restorer) {
+		sp = (unsigned long) ka->sa.sa_restorer;
+	}
+
+	return (void *)((sp - frame_size) & -8ul);
+}
+
+static void *setup_frame_common32(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs,
+				int frame_size,u16 retcode)
+{
+	sigframe32 *frame;
+	int err;
+
+	frame = get_sigframe(ka, regs,frame_size);
+	if (!access_ok(VERIFY_WRITE, frame,frame_size))
+		return 0;
+	err = save_sigregs32(regs,&frame->sregs);
+	if(!err)
+		err=__put_user(&frame->sregs,&frame->sc.sregs);
+	if(!err)
+
+		err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE32);
+	if(!err)
+	{
+		regs->gprs[2]=(current->exec_domain
+		           && current->exec_domain->signal_invmap
+		           && sig < 32
+		           ? current->exec_domain->signal_invmap[sig]
+		           : sig);
+		/* Set up registers for signal handler */
+		regs->gprs[15] = (addr_t)frame;
+		regs->psw.addr = FIX_PSW(ka->sa.sa_handler);
+	}
+	/* Set up to return from userspace.  If provided, use a stub
+	   already in userspace.  */
+	if (ka->sa.sa_flags & SA_RESTORER) {
+                regs->gprs[14] = FIX_PSW(ka->sa.sa_restorer);
+	} else {
+                regs->gprs[14] = FIX_PSW(frame->retcode);
+		err |= __put_user(retcode, (u16 *)(frame->retcode));
+	}
+	return(err ? 0:frame);
+}
+
+static void setup_frame32(int sig, struct k_sigaction *ka,
+			sigset_t *set, struct pt_regs * regs)
+{
+	sigframe32 *frame;
+         
+	if((frame=setup_frame_common32(sig,ka,set,regs,sizeof(sigframe32),
+		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
+		goto give_sigsegv;
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+		current->comm, current->pid, frame, regs->eip, frame->pretcode);
+#endif
+	 /* Martin wants this for pthreads */
+	regs->gprs[3] = (addr_t)&frame->sc;   
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+			   sigset_t *set, struct pt_regs * regs)
+{
+	rt_sigframe32 *frame;
+	addr_t      orig_sp=regs->gprs[15];
+	int err;
+
+	if((frame=setup_frame_common32(sig,ka,set,regs,sizeof(rt_sigframe32),
+		    (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
+		goto give_sigsegv;
+	
+	err = copy_siginfo_to_user32(&frame->info, info);
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(0, &frame->uc.uc_link);
+	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(orig_sp),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	regs->gprs[3] = (addr_t)&frame->info;
+	regs->gprs[4] = (addr_t)&frame->uc;
+
+	if (err)
+		goto give_sigsegv;
+
+#if DEBUG_SIG
+	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
+		current->comm, current->pid, frame, regs->eip, frame->pretcode);
+#endif
+	return;
+
+give_sigsegv:
+	if (sig == SIGSEGV)
+		ka->sa.sa_handler = SIG_DFL;
+	force_sig(SIGSEGV, current);
+}
+
+/*
+ * OK, we're invoking a handler
+ */	
+
+static void
+handle_signal32(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+{
+	/* Are we from a system call? */
+	if (regs->orig_gpr2 >= 0) {
+		/* If so, check system call restarting.. */
+		switch (regs->gprs[2]) {
+			case -ERESTARTNOHAND:
+				regs->gprs[2] = -EINTR;
+				break;
+
+			case -ERESTARTSYS:
+				if (!(ka->sa.sa_flags & SA_RESTART)) {
+					regs->gprs[2] = -EINTR;
+					break;
+				}
+			/* fallthrough */
+			case -ERESTARTNOINTR:
+				regs->gprs[2] = regs->orig_gpr2;
+				regs->psw.addr -= 2;
+		}
+	}
+
+	/* Set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		setup_rt_frame32(sig, ka, info, oldset, regs);
+	else
+		setup_frame32(sig, ka, oldset, regs);
+
+	if (ka->sa.sa_flags & SA_ONESHOT)
+		ka->sa.sa_handler = SIG_DFL;
+
+	if (!(ka->sa.sa_flags & SA_NODEFER)) {
+		spin_lock_irq(&current->sigmask_lock);
+		sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+		sigaddset(&current->blocked,sig);
+		recalc_sigpending(current);
+		spin_unlock_irq(&current->sigmask_lock);
+	}
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+int do_signal32(struct pt_regs *regs, sigset_t *oldset)
+{
+	siginfo_t info;
+	struct k_sigaction *ka;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return 1;
+
+	if (!oldset)
+		oldset = &current->blocked;
+
+	for (;;) {
+		unsigned long signr;
+
+		spin_lock_irq(&current->sigmask_lock);
+		signr = dequeue_signal(&current->blocked, &info);
+		spin_unlock_irq(&current->sigmask_lock);
+
+		if (!signr)
+			break;
+
+		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
+			/* Let the debugger run.  */
+			current->exit_code = signr;
+			set_current_state(TASK_STOPPED);
+			notify_parent(current, SIGCHLD);
+			schedule();
+
+			/* We're back.  Did the debugger cancel the sig?  */
+			if (!(signr = current->exit_code))
+				continue;
+			current->exit_code = 0;
+
+			/* The debugger continued.  Ignore SIGSTOP.  */
+			if (signr == SIGSTOP)
+				continue;
+
+			/* Update the siginfo structure.  Is this good?  */
+			if (signr != info.si_signo) {
+				info.si_signo = signr;
+				info.si_errno = 0;
+				info.si_code = SI_USER;
+				info.si_pid = current->p_pptr->pid;
+				info.si_uid = current->p_pptr->uid;
+			}
+
+			/* If the (new) signal is now blocked, requeue it.  */
+			if (sigismember(&current->blocked, signr)) {
+				send_sig_info(signr, &info, current);
+				continue;
+			}
+		}
+
+		ka = &current->sig->action[signr-1];
+		if (ka->sa.sa_handler == SIG_IGN) {
+			if (signr != SIGCHLD)
+				continue;
+			/* Check for SIGCHLD: it's special.  */
+			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
+				/* nothing */;
+			continue;
+		}
+
+		if (ka->sa.sa_handler == SIG_DFL) {
+			int exit_code = signr;
+
+			/* Init gets no signals it doesn't want.  */
+			if (current->pid == 1)
+				continue;
+
+			switch (signr) {
+			case SIGCONT: case SIGCHLD: case SIGWINCH:
+				continue;
+
+			case SIGTSTP: case SIGTTIN: case SIGTTOU:
+				if (is_orphaned_pgrp(current->pgrp))
+					continue;
+				/* FALLTHRU */
+
+			case SIGSTOP:
+				set_current_state(TASK_STOPPED);
+				current->exit_code = signr;
+				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
+					notify_parent(current, SIGCHLD);
+				schedule();
+				continue;
+
+			case SIGQUIT: case SIGILL: case SIGTRAP:
+			case SIGABRT: case SIGFPE: case SIGSEGV:
+                                if (do_coredump(signr, regs))
+                                        exit_code |= 0x80;
+                                /* FALLTHRU */
+
+			default:
+				lock_kernel();
+				sigaddset(&current->pending.signal, signr);
+				recalc_sigpending(current);
+				current->flags |= PF_SIGNALED;
+				do_exit(exit_code);
+				/* NOTREACHED */
+			}
+		}
+
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal32(signr, ka, &info, oldset, regs);
+		return 1;
+	}
+
+	/* Did we come from a system call? */
+	if ( regs->trap ==  __LC_SVC_OLD_PSW /* System Call! */ ) {
+		/* Restart the system call - no handlers present */
+		if (regs->gprs[2] == -ERESTARTNOHAND ||
+		    regs->gprs[2] == -ERESTARTSYS ||
+		    regs->gprs[2] == -ERESTARTNOINTR) {
+			regs->gprs[2] = regs->orig_gpr2;
+			regs->psw.addr -= 2;
+		}
+	}
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/smp.c linux/arch/s390x/kernel/smp.c
--- v2.4.1/linux/arch/s390x/kernel/smp.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/smp.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,760 @@
+/*
+ *  arch/s390/kernel/smp.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  based on other smp stuff by 
+ *    (c) 1995 Alan Cox, CymruNET Ltd  <alan@cymru.net>
+ *    (c) 1998 Ingo Molnar
+ *
+ * We work with logical cpu numbering everywhere we can. The only
+ * functions using the real cpu address (got from STAP) are the sigp
+ * functions. For all other functions we use the identity mapping.
+ * That means that cpu_number_map[i] == i for every cpu. cpu_number_map is
+ * used e.g. to find the idle task belonging to a logical cpu. Every array
+ * in the kernel is sorted by the logical cpu number and not by the physical
+ * one which is causing all the confusion with __cpu_logical_map and
+ * cpu_number_map in other architectures.
+ */
+
+#include <linux/init.h>
+
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/kernel_stat.h>
+#include <linux/smp_lock.h>
+
+#include <linux/delay.h>
+
+#include <asm/sigp.h>
+#include <asm/pgalloc.h>
+#include <asm/irq.h>
+#include <asm/s390_ext.h>
+
+#include "cpcmd.h"
+
+/* prototypes */
+extern int cpu_idle(void * unused);
+
+extern __u16 boot_cpu_addr;
+extern volatile int __cpu_logical_map[];
+
+/*
+ * An array with a pointer the lowcore of every CPU.
+ */
+static int       max_cpus = NR_CPUS;	  /* Setup configured maximum number of CPUs to activate	*/
+int              smp_num_cpus;
+struct _lowcore *lowcore_ptr[NR_CPUS];
+unsigned int     prof_multiplier[NR_CPUS];
+unsigned int     prof_old_multiplier[NR_CPUS];
+unsigned int     prof_counter[NR_CPUS];
+cycles_t         cacheflush_time=0;
+int              smp_threads_ready=0;      /* Set when the idlers are all forked. */
+static atomic_t  smp_commenced = ATOMIC_INIT(0);
+
+spinlock_t       kernel_flag = SPIN_LOCK_UNLOCKED;
+
+/*
+ *      Setup routine for controlling SMP activation
+ *
+ *      Command-line option of "nosmp" or "maxcpus=0" will disable SMP
+ *      activation entirely (the MPS table probe still happens, though).
+ *
+ *      Command-line option of "maxcpus=<NUM>", where <NUM> is an integer
+ *      greater than 0, limits the maximum number of CPUs activated in
+ *      SMP mode to <NUM>.
+ */
+
+static int __init nosmp(char *str)
+{
+	max_cpus = 0;
+	return 1;
+}
+
+__setup("nosmp", nosmp);
+
+static int __init maxcpus(char *str)
+{
+	get_option(&str, &max_cpus);
+	return 1;
+}
+
+__setup("maxcpus=", maxcpus);
+
+/*
+ * Reboot, halt and power_off routines for SMP.
+ */
+extern char vmhalt_cmd[];
+extern char vmpoff_cmd[];
+
+extern void reipl(unsigned long devno);
+
+void do_machine_restart(void)
+{
+        smp_send_stop();
+	reipl(S390_lowcore.ipl_device);
+}
+
+void machine_restart(char * __unused) 
+{
+        if (smp_processor_id() != 0) {
+                smp_ext_bitcall(0, ec_restart);
+                for (;;);
+        } else
+                do_machine_restart();
+}
+
+void do_machine_halt(void)
+{
+        smp_send_stop();
+        if (MACHINE_IS_VM && strlen(vmhalt_cmd) > 0)
+                cpcmd(vmhalt_cmd, NULL, 0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+}
+
+void machine_halt(void)
+{
+        if (smp_processor_id() != 0) {
+                smp_ext_bitcall(0, ec_halt);
+                for (;;);
+        } else
+                do_machine_halt();
+}
+
+void do_machine_power_off(void)
+{
+        smp_send_stop();
+        if (MACHINE_IS_VM && strlen(vmpoff_cmd) > 0)
+                cpcmd(vmpoff_cmd, NULL, 0);
+        signal_processor(smp_processor_id(), sigp_stop_and_store_status);
+}
+
+void machine_power_off(void)
+{
+        if (smp_processor_id() != 0) {
+                smp_ext_bitcall(0, ec_power_off);
+                for (;;);
+        } else
+                do_machine_power_off();
+}
+
+/*
+ * This is the main routine where commands issued by other
+ * cpus are handled.
+ */
+
+void do_ext_call_interrupt(struct pt_regs *regs, __u16 code)
+{
+        ec_ext_call *ec, *next;
+        unsigned long bits;
+
+        /*
+         * handle bit signal external calls
+         *
+         * For the ec_schedule signal we have to do nothing. All the work
+         * is done automatically when we return from the interrupt.
+	 * For the ec_restart, ec_halt and ec_power_off we call the
+         * appropriate routine.
+         */
+	bits = xchg(&S390_lowcore.ext_call_fast, 0);
+
+        if (test_bit(ec_restart, &bits))
+		do_machine_restart();
+        if (test_bit(ec_halt, &bits))
+		do_machine_halt();
+        if (test_bit(ec_power_off, &bits))
+		do_machine_power_off();
+
+        /*
+         * Handle external call commands with a parameter area
+         */
+	ec = (ec_ext_call *) xchg(&S390_lowcore.ext_call_queue, 0);
+        if (ec == NULL)
+                return;   /* no command signals */
+
+        /* Make a fifo out of the lifo */
+        next = ec->next;
+        ec->next = NULL;
+        while (next != NULL) {
+                ec_ext_call *tmp = next->next;
+                next->next = ec;
+                ec = next;
+                next = tmp;
+        }
+
+        /* Execute every sigp command on the queue */
+        while (ec != NULL) {
+                switch (ec->cmd) {
+                case ec_callback_async: {
+                        void (*func)(void *info);
+                        void *info;
+
+                        func = ec->func;
+                        info = ec->info;
+                        atomic_set(&ec->status,ec_executing);
+                        (func)(info);
+                        return;
+                }
+                case ec_callback_sync:
+                        atomic_set(&ec->status,ec_executing);
+                        (ec->func)(ec->info);
+                        atomic_set(&ec->status,ec_done);
+                        return;
+                default:
+                }
+                ec = ec->next;
+        }
+}
+
+/*
+ * Swap in a new request to external call queue 
+ */
+static inline void smp_add_ext_call(ec_ext_call *ec, struct _lowcore *lowcore)
+{
+	int success;
+
+	while (1) {
+		ec->next = (ec_ext_call*) lowcore->ext_call_queue;
+		__asm__ __volatile__ (
+                        "   lgr 0,%2\n"
+			"   csg 0,%3,%1\n"
+			"   ipm %0\n"
+			"   srl %0,28\n"
+			: "=d" (success), "+m" (lowcore->ext_call_queue)
+			: "d" (ec->next), "d" (ec)
+			: "cc", "0" );
+		if (success == 0) break;
+	}
+}
+
+/*
+ * Send an external call sigp to another cpu and wait for its completion.
+ */
+sigp_ccode
+smp_ext_call(int cpu, void (*func)(void *info), void *info, int wait)
+{
+        sigp_ccode ccode;
+        ec_ext_call ec;
+
+        ec.cmd = wait ? ec_callback_sync:ec_callback_async;
+        atomic_set(&ec.status, ec_pending);
+        ec.func = func;
+	ec.info = info;
+	/* swap in new request to external call queue */
+	smp_add_ext_call(&ec, &get_cpu_lowcore(cpu));
+        /*
+         * We try once to deliver the signal. There are four possible
+         * return codes:
+         * 0) Order code accepted - can't show up on an external call
+         * 1) Status stored - fine, wait for completion.
+         * 2) Busy - there is another signal pending. Thats fine too, because
+         *    do_ext_call from the pending signal will execute all signals on
+         *    the queue. We wait for completion.
+         * 3) Not operational - something very bad has happened to the cpu.
+         *    do not wait for completion.
+         */
+        ccode = signal_processor(cpu, sigp_external_call);
+
+        if (ccode != sigp_not_operational)
+                /* wait for completion, FIXME: possible seed of a deadlock */
+                while (atomic_read(&ec.status) != (wait?ec_done:ec_executing));
+
+        return ccode;
+}
+
+/*
+ * Send a callback sigp to every other cpu in the system.
+ */
+void smp_ext_call_others(void (*func)(void *info), void *info, int wait)
+{
+        ec_ext_call ec[NR_CPUS];
+        sigp_ccode ccode;
+        int i;
+
+        for (i = 0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() == i)
+                        continue;
+		ec[i].cmd = wait ? ec_callback_sync : ec_callback_async;
+		atomic_set(&ec[i].status, ec_pending);
+		ec[i].func = func;
+		ec[i].info = info;
+		smp_add_ext_call(ec+i, &get_cpu_lowcore(i));
+                ccode = signal_processor(i, sigp_external_call);
+        }
+
+        /* wait for completion, FIXME: possible seed of a deadlock */
+        for (i = 0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() == i)
+                        continue;
+                while (atomic_read(&ec[i].status) != 
+		       (wait ? ec_done:ec_executing));
+        }
+}
+
+/*
+ * Send an external call sigp to another cpu and return without waiting
+ * for its completion.
+ */
+sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig)
+{
+        sigp_ccode ccode;
+
+        /*
+         * Set signaling bit in lowcore of target cpu and kick it
+         */
+	set_bit(sig, &(get_cpu_lowcore(cpu).ext_call_fast));
+        ccode = signal_processor(cpu, sigp_external_call);
+        return ccode;
+}
+
+/*
+ * Send an external call sigp to every other cpu in the system and
+ * return without waiting for its completion.
+ */
+void smp_ext_bitcall_others(ec_bit_sig sig)
+{
+        sigp_ccode ccode;
+        int i;
+
+        for (i = 0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() == i)
+                        continue;
+                /*
+                 * Set signaling bit in lowcore of target cpu and kick it
+                 */
+		set_bit(sig, &(get_cpu_lowcore(i).ext_call_fast));
+                ccode = signal_processor(i, sigp_external_call);
+        }
+}
+
+/*
+ * cycles through all the cpus,
+ * returns early if info is not NULL & the processor has something
+ * of intrest to report in the info structure.
+ * it returns the next cpu to check if it returns early.
+ * i.e. it should be used as follows if you wish to receive info.
+ * next_cpu=0;
+ * do
+ * {
+ *    info->cpu=next_cpu;
+ *    next_cpu=smp_signal_others(order_code,parameter,1,info);
+ *    ... check info here
+ * } while(next_cpu<=smp_num_cpus)
+ *
+ *  if you are lazy just use it like
+ * smp_signal_others(order_code,parameter,0,1,NULL);
+ */
+int smp_signal_others(sigp_order_code order_code, u32 parameter,
+                      int spin, sigp_info *info)
+{
+        sigp_ccode   ccode;
+        u32          dummy;
+        u16          i;
+
+        if (info)
+                info->intresting = 0;
+        for (i = (info ? info->cpu : 0); i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        do {
+                                ccode = signal_processor_ps(
+                                        (info ? &info->status : &dummy),
+                                        parameter, i, order_code);
+                        } while(spin && ccode == sigp_busy);
+                        if (info && ccode != sigp_order_code_accepted) {
+                                info->intresting = 1;
+                                info->cpu = i;
+                                info->ccode = ccode;
+                                i++;
+                                break;
+                        }
+                }
+        }
+        return i;
+}
+
+/*
+ * this function sends a 'stop' sigp to all other CPUs in the system.
+ * it goes straight through.
+ */
+
+void smp_send_stop(void)
+{
+        int i;
+        u32 dummy;
+        unsigned long low_core_addr;
+
+        /* write magic number to zero page (absolute 0) */
+
+        get_cpu_lowcore(smp_processor_id()).panic_magic = __PANIC_MAGIC;
+
+        /* stop all processors */
+
+        smp_signal_others(sigp_stop, 0, TRUE, NULL);
+
+        /* store status of all processors in their lowcores (real 0) */
+
+        for (i =  0; i < smp_num_cpus; i++) {
+                if (smp_processor_id() != i) {
+                        int ccode;
+                        low_core_addr = (unsigned long)&get_cpu_lowcore(i);
+                        do {
+                                ccode = signal_processor_ps(
+                                   &dummy,
+                                   low_core_addr,
+                                   i,
+                                   sigp_store_status_at_address);
+                        } while(ccode == sigp_busy);
+                }
+        }
+}
+
+/*
+ * this function sends a 'reschedule' IPI to another CPU.
+ * it goes straight through and wastes no time serializing
+ * anything. Worst case is that we lose a reschedule ...
+ */
+
+void smp_send_reschedule(int cpu)
+{
+        smp_ext_bitcall(cpu, ec_schedule);
+}
+
+/*
+ * parameter area for the set/clear control bit callbacks
+ */
+typedef struct
+{
+	__u16 start_ctl;
+	__u16 end_ctl;
+	__u64 orvals[16];
+	__u64 andvals[16];
+} ec_creg_mask_parms;
+
+/*
+ * callback for setting/clearing control bits
+ */
+void smp_ctl_bit_callback(void *info) {
+	ec_creg_mask_parms *pp;
+	u64 cregs[16];
+	int i;
+	
+	pp = (ec_creg_mask_parms *) info;
+	asm volatile ("   bras  1,0f\n"
+		      "   stctg 0,0,0(%0)\n"
+		      "0: ex    %1,0(1)\n"
+		      : : "a" (cregs+pp->start_ctl),
+		          "a" ((pp->start_ctl<<4) + pp->end_ctl)
+		      : "memory", "1" );
+	for (i = pp->start_ctl; i <= pp->end_ctl; i++)
+		cregs[i] = (cregs[i] & pp->andvals[i]) | pp->orvals[i];
+	asm volatile ("   bras  1,0f\n"
+		      "   lctlg 0,0,0(%0)\n"
+		      "0: ex    %1,0(1)\n"
+		      : : "a" (cregs+pp->start_ctl),
+		          "a" ((pp->start_ctl<<4) + pp->end_ctl)
+		      : "memory", "1" );
+}
+
+/*
+ * Set a bit in a control register of all cpus
+ */
+void smp_ctl_set_bit(int cr, int bit) {
+        ec_creg_mask_parms parms;
+
+        if (atomic_read(&smp_commenced) != 0) {
+                parms.start_ctl = cr;
+                parms.end_ctl = cr;
+                parms.orvals[cr] = 1 << bit;
+                parms.andvals[cr] = -1L;
+                smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
+        }
+        __ctl_set_bit(cr, bit);
+}
+
+/*
+ * Clear a bit in a control register of all cpus
+ */
+void smp_ctl_clear_bit(int cr, int bit) {
+        ec_creg_mask_parms parms;
+
+        if (atomic_read(&smp_commenced) != 0) {
+                parms.start_ctl = cr;
+                parms.end_ctl = cr;
+                parms.orvals[cr] = 0;
+                parms.andvals[cr] = ~(1L << bit);
+                smp_ext_call_others(smp_ctl_bit_callback, &parms, 1);
+        }
+        __ctl_clear_bit(cr, bit);
+}
+
+/*
+ * Call a function on all other processors
+ */
+
+int
+smp_call_function(void (*func)(void *info), void *info, int retry, int wait)
+/*
+ * [SUMMARY] Run a function on all other CPUs.
+ * <func> The function to run. This must be fast and non-blocking.
+ * <info> An arbitrary pointer to pass to the function.
+ * <retry> currently unused.
+ * <wait> If true, wait (atomically) until function has completed on other CPUs.
+ * [RETURNS] 0 on success, else a negative status code. Does not return until
+ * remote CPUs are nearly ready to execute <<func>> or are or have executed.
+ *
+ * You must not call this function with disabled interrupts or from a
+ * hardware interrupt handler, you may call it from a bottom half handler.
+ */
+{
+        if (atomic_read(&smp_commenced) != 0)
+                smp_ext_call_others(func, info, 1);
+        (func)(info);
+        return 0;
+}
+
+/*
+ * Lets check how many CPUs we have.
+ */
+
+void smp_count_cpus(void)
+{
+        int curr_cpu;
+
+        current->processor = 0;
+        smp_num_cpus = 1;
+        for (curr_cpu = 0;
+             curr_cpu <= 65535 && smp_num_cpus < max_cpus; curr_cpu++) {
+                if ((__u16) curr_cpu == boot_cpu_addr)
+                        continue;
+                __cpu_logical_map[smp_num_cpus] = (__u16) curr_cpu;
+                if (signal_processor(smp_num_cpus, sigp_sense) ==
+                    sigp_not_operational)
+                        continue;
+                smp_num_cpus++;
+        }
+        printk("Detected %d CPU's\n",(int) smp_num_cpus);
+        printk("Boot cpu address %2X\n", boot_cpu_addr);
+}
+
+
+/*
+ *      Activate a secondary processor.
+ */
+extern void init_100hz_timer(void);
+
+int __init start_secondary(void *cpuvoid)
+{
+        /* Setup the cpu */
+        cpu_init();
+        /* Print info about this processor */
+        print_cpu_info(&safe_get_cpu_lowcore(smp_processor_id()).cpu_data);
+        /* Wait for completion of smp startup */
+        while (!atomic_read(&smp_commenced))
+                /* nothing */ ;
+        /* init per CPU 100 hz timer */
+        init_100hz_timer();
+        /* cpu_idle will call schedule for us */
+        return cpu_idle(NULL);
+}
+
+/*
+ * The restart interrupt handler jumps to start_secondary directly
+ * without the detour over initialize_secondary. We defined it here
+ * so that the linker doesn't complain.
+ */
+void __init initialize_secondary(void)
+{
+}
+
+static int __init fork_by_hand(void)
+{
+       struct pt_regs regs;
+       /* don't care about the psw and regs settings since we'll never
+          reschedule the forked task. */
+       memset(&regs,0,sizeof(pt_regs));
+       return do_fork(CLONE_VM|CLONE_PID, 0, &regs, 0);
+}
+
+static void __init do_boot_cpu(int cpu)
+{
+        struct task_struct *idle;
+        struct _lowcore    *cpu_lowcore;
+
+        /* 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", cpu);
+
+        /*
+         * We remove it from the pidhash and the runqueue
+         * once we got the process:
+         */
+        idle = init_task.prev_task;
+        if (!idle)
+                panic("No idle process for CPU %d",cpu);
+        idle->processor = cpu;
+        idle->has_cpu = 1; /* we schedule the first task manually */
+
+        del_from_runqueue(idle);
+        unhash_process(idle);
+        init_tasks[cpu] = idle;
+
+        cpu_lowcore=&get_cpu_lowcore(cpu);
+        cpu_lowcore->kernel_stack=idle->thread.ksp;
+        __asm__ __volatile__("stctg 0,15,%0\n\t"
+                             "stam  0,15,%1"
+                             : "=m" (cpu_lowcore->cregs_save_area[0]),
+                               "=m" (cpu_lowcore->access_regs_save_area[0])
+                             : : "memory");
+
+        eieio();
+        signal_processor(cpu,sigp_restart);
+}
+
+/*
+ *      Architecture specific routine called by the kernel just before init is
+ *      fired off. This allows the BP to have everything in order [we hope].
+ *      At the end of this all the APs will hit the system scheduling and off
+ *      we go. Each AP will load the system gdt's and jump through the kernel
+ *      init into idle(). At this point the scheduler will one day take over
+ *      and give them jobs to do. smp_callin is a standard routine
+ *      we use to track CPUs as they power up.
+ */
+
+void __init smp_commence(void)
+{
+        /*
+         *      Lets the callins below out of their loop.
+         */
+        atomic_set(&smp_commenced,1);
+}
+
+/*
+ *	Cycle through the processors sending restart sigps to boot each.
+ */
+
+void __init smp_boot_cpus(void)
+{
+        struct _lowcore *curr_lowcore;
+        sigp_ccode   ccode;
+        int i;
+
+        /* request the 0x1202 external interrupt */
+        if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
+                panic("Couldn't request external interrupt 0x1202");
+        smp_count_cpus();
+        memset(lowcore_ptr,0,sizeof(lowcore_ptr));  
+        
+        /*
+         *      Initialize the logical to physical CPU number mapping
+         *      and the per-CPU profiling counter/multiplier
+         */
+        
+        for (i = 0; i < NR_CPUS; i++) {
+                prof_counter[i] = 1;
+                prof_old_multiplier[i] = 1;
+                prof_multiplier[i] = 1;
+        }
+
+        print_cpu_info(&safe_get_cpu_lowcore(0).cpu_data);
+
+        for(i = 0; i < smp_num_cpus; i++)
+        {
+                curr_lowcore = (struct _lowcore *)
+                                    __get_free_pages(GFP_KERNEL|GFP_DMA, 1);
+                if (curr_lowcore == NULL) {
+                        printk("smp_boot_cpus failed to allocate prefix memory\n");
+                        break;
+                }
+                lowcore_ptr[i] = curr_lowcore;
+                memcpy(curr_lowcore, &S390_lowcore, sizeof(struct _lowcore));
+                /*
+                 * Most of the parameters are set up when the cpu is
+                 * started up.
+                 */
+                if (smp_processor_id() == i)
+                        set_prefix((u32)(u64)curr_lowcore);
+                else {
+                        ccode = signal_processor_p((u64)(curr_lowcore),
+                                                   i, sigp_set_prefix);
+                        if(ccode) {
+                                /* if this gets troublesome I'll have to do
+                                 * something about it. */
+                                printk("ccode %d for cpu %d  returned when "
+                                       "setting prefix in smp_boot_cpus not good.\n",
+                                       (int) ccode, (int) i);
+                        }
+                        else
+                                do_boot_cpu(i);
+                }
+        }
+}
+
+/*
+ * the frequency of the profiling timer can be changed
+ * by writing a multiplier value into /proc/profile.
+ *
+ * usually you want to run this on all CPUs ;)
+ */
+int setup_profiling_timer(unsigned int multiplier)
+{
+        return 0;
+}
+
+/*
+ * Local timer interrupt handler. It does both profiling and
+ * process statistics/rescheduling.
+ *
+ * We do profiling in every local tick, statistics/rescheduling
+ * happen only every 'profiling multiplier' ticks. The default
+ * multiplier is 1 and it can be changed by writing the new multiplier
+ * value into /proc/profile.
+ */
+
+void smp_local_timer_interrupt(struct pt_regs * regs)
+{
+	int user = (user_mode(regs) != 0);
+        int cpu = smp_processor_id();
+
+        /*
+         * The profiling function is SMP safe. (nothing can mess
+         * around with "current", and the profiling counters are
+         * updated with atomic operations). This is especially
+         * useful with a profiling multiplier != 1
+         */
+        if (!user_mode(regs))
+                s390_do_profile(regs->psw.addr);
+
+        if (!--prof_counter[cpu]) {
+                int system = 1-user;
+                struct task_struct * p = current;
+
+                /*
+                 * The multiplier may have changed since the last time we got
+                 * to this point as a result of the user writing to
+                 * /proc/profile.  In this case we need to adjust the APIC
+                 * timer accordingly.
+                 *
+                 * Interrupts are already masked off at this point.
+                 */
+                prof_counter[cpu] = prof_multiplier[cpu];
+                if (prof_counter[cpu] != prof_old_multiplier[cpu]) {
+                  prof_old_multiplier[cpu] = prof_counter[cpu];
+                }
+
+                /*
+                 * After doing the above, we need to make like
+                 * a normal interrupt - otherwise timer interrupts
+                 * ignore the global interrupt lock, which is the
+                 * WrongThing (tm) to do.
+                 */
+
+                irq_enter(cpu, 0);
+		update_process_times(user);
+                irq_exit(cpu, 0);
+        }
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/sys_s390.c linux/arch/s390x/kernel/sys_s390.c
--- v2.4.1/linux/arch/s390x/kernel/sys_s390.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/sys_s390.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,205 @@
+/*
+ *  arch/s390/kernel/sys_s390.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ *  Derived from "arch/i386/kernel/sys_i386.c"
+ *
+ *  This file contains various random system calls that
+ *  have a non-standard calling sequence on the Linux/s390
+ *  platform.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/utsname.h>
+
+#include <asm/uaccess.h>
+#include <asm/ipc.h>
+
+/*
+ * sys_pipe() is the normal C calling standard for creating
+ * a pipe. It's not the way Unix traditionally does this, though.
+ */
+asmlinkage long sys_pipe(unsigned long * fildes)
+{
+	int fd[2];
+	int error;
+
+	error = do_pipe(fd);
+	if (!error) {
+		if (copy_to_user(fildes, fd, 2*sizeof(int)))
+			error = -EFAULT;
+	}
+	return error;
+}
+
+/* common code for old and new mmaps */
+static inline long do_mmap2(
+	unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags,
+	unsigned long fd, unsigned long pgoff)
+{
+	long error = -EBADF;
+	struct file * file = NULL;
+
+	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+	if (!(flags & MAP_ANONYMOUS)) {
+		file = fget(fd);
+		if (!file)
+			goto out;
+	}
+
+	down(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up(&current->mm->mmap_sem);
+
+	if (file)
+		fput(file);
+out:
+	return error;
+}
+
+/*
+ * Perform the select(nd, in, out, ex, tv) and mmap() system
+ * calls. Linux/i386 didn't use to be able to handle more than
+ * 4 system call parameters, so these system calls used a memory
+ * block for parameter passing..
+ */
+
+struct mmap_arg_struct {
+	unsigned long addr;
+	unsigned long len;
+	unsigned long prot;
+	unsigned long flags;
+	unsigned long fd;
+	unsigned long offset;
+};
+
+asmlinkage long sys_mmap2(struct mmap_arg_struct *arg)
+{
+	struct mmap_arg_struct a;
+	int error = -EFAULT;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		goto out;
+	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset);
+out:
+	return error;
+}
+
+asmlinkage long old_mmap(struct mmap_arg_struct *arg)
+{
+	struct mmap_arg_struct a;
+	long error = -EFAULT;
+
+	if (copy_from_user(&a, arg, sizeof(a)))
+		goto out;
+
+	error = -EINVAL;
+	if (a.offset & ~PAGE_MASK)
+		goto out;
+
+	error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT);
+out:
+	return error;
+}
+
+extern asmlinkage int sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+
+/*
+ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
+ *
+ * This is really horribly ugly.
+ */
+asmlinkage int sys_ipc (uint call, int first, int second, 
+                        unsigned long third, void *ptr)
+{
+        struct ipc_kludge tmp;
+	int ret;
+
+        switch (call) {
+        case SEMOP:
+                return sys_semop (first, (struct sembuf *)ptr, second);
+        case SEMGET:
+                return sys_semget (first, second, third);
+        case SEMCTL: {
+                union semun fourth;
+                if (!ptr)
+                        return -EINVAL;
+                if (get_user(fourth.__pad, (void **) ptr))
+                        return -EFAULT;
+                return sys_semctl (first, second, third, fourth);
+        } 
+        case MSGSND:
+		return sys_msgsnd (first, (struct msgbuf *) ptr, 
+                                   second, third);
+		break;
+        case MSGRCV:
+                if (!ptr)
+                        return -EINVAL;
+                if (copy_from_user (&tmp, (struct ipc_kludge *) ptr,
+                                    sizeof (struct ipc_kludge)))
+                        return -EFAULT;
+                return sys_msgrcv (first, tmp.msgp,
+                                   second, tmp.msgtyp, third);
+        case MSGGET:
+                return sys_msgget ((key_t) first, second);
+        case MSGCTL:
+                return sys_msgctl (first, second, (struct msqid_ds *) ptr);
+                
+	case SHMAT: {
+		ulong raddr;
+		ret = sys_shmat (first, (char *) ptr, second, &raddr);
+		if (ret)
+			return ret;
+		return put_user (raddr, (ulong *) third);
+		break;
+        }
+	case SHMDT: 
+		return sys_shmdt ((char *)ptr);
+	case SHMGET:
+		return sys_shmget (first, second, third);
+	case SHMCTL:
+		return sys_shmctl (first, second,
+                                   (struct shmid_ds *) ptr);
+	default:
+		return -EINVAL;
+
+	}
+        
+	return -EINVAL;
+}
+
+/*
+ * Old cruft
+ */
+asmlinkage int sys_uname(struct old_utsname * name)
+{
+	int err;
+	if (!name)
+		return -EFAULT;
+	down_read(&uts_sem);
+	err=copy_to_user(name, &system_utsname, sizeof (*name));
+	up_read(&uts_sem);
+	return err?-EFAULT:0;
+}
+
+asmlinkage int sys_pause(void)
+{
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule();
+	return -ERESTARTNOHAND;
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/time.c linux/arch/s390x/kernel/time.c
--- v2.4.1/linux/arch/s390x/kernel/time.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/time.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,258 @@
+/*
+ *  arch/s390/kernel/time.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *  Derived from "arch/i386/kernel/time.c"
+ *    Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/time.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/types.h>
+
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+
+#include <linux/timex.h>
+#include <linux/config.h>
+
+#include <asm/irq.h>
+#include <asm/s390_ext.h>
+
+
+/* change this if you have some constant time drift */
+#define USECS_PER_JIFFY ((signed long)1000000/HZ)
+#define CLK_TICKS_PER_JIFFY ((signed long)USECS_PER_JIFFY<<12)
+
+#define TICK_SIZE tick
+
+static uint64_t init_timer_cc, last_timer_cc;
+
+extern rwlock_t xtime_lock;
+extern unsigned long wall_jiffies;
+
+void tod_to_timeval(uint64_t todval, struct timeval *xtime)
+{
+#if 0
+        const int high_bit = 0x80000000L;
+        const int c_f4240 = 0xf4240L;
+        const int c_7a120 = 0x7a120;
+	/* We have to divide the 64 bit value todval by 4096
+	 * (because the 2^12 bit is the one that changes every 
+         * microsecond) and then split it into seconds and
+         * microseconds. A value of max (2^52-1) divided by
+         * the value 0xF4240 can yield a max result of approx
+         * (2^32.068). Thats to big to fit into a signed int
+	 *   ... hacking time!
+         */
+	asm volatile ("L     2,%1\n\t"
+		      "LR    3,2\n\t"
+		      "SRL   2,12\n\t"
+		      "SLL   3,20\n\t"
+		      "L     4,%O1+4(%R1)\n\t"
+		      "SRL   4,12\n\t"
+		      "OR    3,4\n\t"  /* now R2/R3 contain (todval >> 12) */
+		      "SR    4,4\n\t"
+		      "CL    2,%2\n\t"
+		      "JL    .+12\n\t"
+		      "S     2,%2\n\t"
+		      "L     4,%3\n\t"
+                      "D     2,%4\n\t"
+		      "OR    3,4\n\t"
+		      "ST    2,%O0+4(%R0)\n\t"
+		      "ST    3,%0"
+		      : "=m" (*xtime) : "m" (todval),
+		        "m" (c_7a120), "m" (high_bit), "m" (c_f4240)
+		      : "cc", "memory", "2", "3", "4" );
+#else
+    todval >>= 12;
+    xtime->tv_sec = todval / 1000000;
+    xtime->tv_usec = todval % 1000000;
+#endif
+}
+
+unsigned long do_gettimeoffset(void) 
+{
+	__u64 timer_cc;
+
+	asm volatile ("STCK %0" : "=m" (timer_cc));
+        /* We require the offset from the previous interrupt */
+        return ((unsigned long)((timer_cc - last_timer_cc)>>12));
+}
+
+/*
+ * This version of gettimeofday has microsecond resolution.
+ */
+void do_gettimeofday(struct timeval *tv)
+{
+	unsigned long flags;
+	unsigned long usec, sec;
+	unsigned long lost_ticks = jiffies - wall_jiffies;
+
+	read_lock_irqsave(&xtime_lock, flags);
+	usec = do_gettimeoffset();
+	if (lost_ticks)
+		usec +=(USECS_PER_JIFFY*lost_ticks);
+	sec = xtime.tv_sec;
+	usec += xtime.tv_usec;
+	read_unlock_irqrestore(&xtime_lock, flags);
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		sec++;
+	}
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
+}
+
+void do_settimeofday(struct timeval *tv)
+{
+
+	write_lock_irq(&xtime_lock);
+	/* This is revolting. We need to set the xtime.tv_usec
+	 * correctly. However, the value in this location is
+	 * is value at the last tick.
+	 * Discover what correction gettimeofday
+	 * would have done, and then undo it!
+	 */
+	tv->tv_usec -= do_gettimeoffset();
+
+	while (tv->tv_usec < 0) {
+		tv->tv_usec += 1000000;
+		tv->tv_sec--;
+	}
+
+	xtime = *tv;
+	time_adjust = 0;		/* stop active adjtime() */
+	time_status |= STA_UNSYNC;
+	time_maxerror = NTP_PHASE_LIMIT;
+	time_esterror = NTP_PHASE_LIMIT;
+	write_unlock_irq(&xtime_lock);
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "do_timer()" routine every clocktick
+ */
+
+#ifdef CONFIG_SMP
+extern __u16 boot_cpu_addr;
+#endif
+
+void do_timer_interrupt(struct pt_regs *regs,int error_code)
+{
+        unsigned long flags;
+
+        /*
+         * reset timer to 10ms minus time already elapsed
+         * since timer-interrupt pending
+         */
+ 
+        save_flags(flags);
+        cli();
+#ifdef CONFIG_SMP
+	if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr) {
+		write_lock(&xtime_lock);
+		last_timer_cc = S390_lowcore.jiffy_timer_cc;
+	}
+#else
+        last_timer_cc = S390_lowcore.jiffy_timer_cc;
+#endif
+        /* set clock comparator */
+        S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
+        asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
+
+/*
+ * In the SMP case we use the local timer interrupt to do the
+ * profiling, except when we simulate SMP mode on a uniprocessor
+ * system, in that case we have to call the local interrupt handler.
+ */
+#ifdef CONFIG_SMP
+        /* when SMP, do smp_local_timer_interrupt for *all* CPUs,
+           but only do the rest for the boot CPU */
+        smp_local_timer_interrupt(regs);
+#else
+        if (!user_mode(regs))
+                s390_do_profile(regs->psw.addr);
+#endif
+
+#ifdef CONFIG_SMP
+	if(S390_lowcore.cpu_data.cpu_addr==boot_cpu_addr)
+#endif
+	{
+		do_timer(regs);
+#ifdef CONFIG_SMP
+		write_unlock(&xtime_lock);
+#endif
+	}
+        restore_flags(flags);
+
+}
+
+/*
+ * Start the clock comparator on the current CPU
+ */
+static unsigned long cr0 __attribute__ ((aligned (8)));
+
+void init_100hz_timer(void)
+{
+        /* allow clock comparator timer interrupt */
+        asm volatile ("STCTG 0,0,%0" : "=m" (cr0) : : "memory");
+        cr0 |= 0x800;
+        asm volatile ("LCTLG 0,0,%0" : : "m" (cr0) : "memory");
+        /* set clock comparator */
+        /* read the TOD clock */
+        asm volatile ("STCK %0" : "=m" (S390_lowcore.jiffy_timer_cc));
+        S390_lowcore.jiffy_timer_cc += CLK_TICKS_PER_JIFFY;
+        asm volatile ("SCKC %0" : : "m" (S390_lowcore.jiffy_timer_cc));
+}
+
+/*
+ * Initialize the TOD clock and the CPU timer of
+ * the boot cpu.
+ */
+void __init time_init(void)
+{
+	int cc;
+
+        /* kick the TOD clock */
+        asm volatile ("STCK %1\n\t"
+                      "IPM  %0\n\t"
+                      "SRL  %0,28" : "=r" (cc), "=m" (init_timer_cc));
+        switch (cc) {
+        case 0: /* clock in set state: all is fine */
+                break;
+        case 1: /* clock in non-set state: FIXME */
+                printk("time_init: TOD clock in non-set state\n");
+                break;
+        case 2: /* clock in error state: FIXME */
+                printk("time_init: TOD clock in error state\n");
+                break;
+        case 3: /* clock in stopped or not-operational state: FIXME */
+                printk("time_init: TOD clock stopped/non-operational\n");
+                break;
+        }
+        /* request the 0x1004 external interrupt */
+        if (register_external_interrupt(0x1004, do_timer_interrupt) != 0)
+                panic("Couldn't request external interrupts 0x1004");
+        init_100hz_timer();
+        init_timer_cc = S390_lowcore.jiffy_timer_cc;
+        init_timer_cc -= 0x8126d60e46000000LL -
+                         (0x3c26700LL*1000000*4096);
+        tod_to_timeval(init_timer_cc, &xtime);
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/traps.c linux/arch/s390x/kernel/traps.c
--- v2.4.1/linux/arch/s390x/kernel/traps.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/traps.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,248 @@
+/*
+ *  arch/s390/kernel/traps.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ *  Derived from "arch/i386/kernel/traps.c"
+ *    Copyright (C) 1991, 1992 Linus Torvalds
+ */
+
+/*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/atomic.h>
+#include <asm/mathemu.h>
+#if CONFIG_REMOTE_DEBUG
+#include <asm/gdb-stub.h>
+#endif
+
+/* Called from entry.S only */
+extern void handle_per_exception(struct pt_regs *regs);
+
+typedef void pgm_check_handler_t(struct pt_regs *, long);
+pgm_check_handler_t *pgm_check_table[128];
+
+#ifdef CONFIG_SYSCTL
+#ifdef CONFIG_PROCESS_DEBUG
+int sysctl_userprocess_debug = 1;
+#else
+int sysctl_userprocess_debug = 0;
+#endif
+#endif
+
+extern pgm_check_handler_t do_page_fault;
+
+spinlock_t die_lock;
+
+void die(const char * str, struct pt_regs * regs, long err)
+{
+        console_verbose();
+        spin_lock_irq(&die_lock);
+        printk("%s: %04lx\n", str, err & 0xffff);
+        show_regs(regs);
+        spin_unlock_irq(&die_lock);
+        do_exit(SIGSEGV);
+}
+
+#define DO_ERROR(signr, str, name) \
+asmlinkage void name(struct pt_regs * regs, long interruption_code) \
+{ \
+	do_trap(interruption_code, signr, str, regs, NULL); \
+}
+
+#define DO_ERROR_INFO(signr, str, name, sicode, siaddr) \
+asmlinkage void name(struct pt_regs * regs, long interruption_code) \
+{ \
+        siginfo_t info; \
+        info.si_signo = signr; \
+        info.si_errno = 0; \
+        info.si_code = sicode; \
+        info.si_addr = (void *)siaddr; \
+        do_trap(interruption_code, signr, str, regs, &info); \
+}
+
+static void inline do_trap(long interruption_code, int signr, char *str,
+                           struct pt_regs *regs, siginfo_t *info)
+{
+        if (regs->psw.mask & PSW_PROBLEM_STATE) {
+                struct task_struct *tsk = current;
+                tsk->thread.trap_no = interruption_code;
+		if (info)
+			force_sig_info(signr, info, tsk);
+		else
+                	force_sig(signr, tsk);
+#ifndef CONFIG_SYSCTL
+#ifdef CONFIG_PROCESS_DEBUG
+                printk("User process fault: interruption code 0x%lX\n",
+                       interruption_code);
+                show_regs(regs);
+#endif
+#else
+		if (sysctl_userprocess_debug) {
+			printk("User process fault: interruption code 0x%lX\n",
+			       interruption_code);
+			show_regs(regs);
+		}
+#endif
+        } else {
+                unsigned long fixup = search_exception_table(regs->psw.addr);
+                if (fixup)
+                        regs->psw.addr = fixup;
+                else
+                        die(str, regs, interruption_code);
+        }
+}
+
+int do_debugger_trap(struct pt_regs *regs,int signal)
+{
+	if(regs->psw.mask&PSW_PROBLEM_STATE)
+	{
+		if(current->ptrace & PT_PTRACED)
+			force_sig(signal,current);
+		else
+			return 1;
+	}
+	else
+	{
+#if CONFIG_REMOTE_DEBUG
+		if(gdb_stub_initialised)
+		{
+			gdb_stub_handle_exception((gdb_pt_regs *)regs,signal);
+			return 0;
+		}
+#endif
+		return 1;
+	}
+	return 0;
+}
+
+DO_ERROR(SIGSEGV, "Unknown program exception", default_trap_handler)
+DO_ERROR(SIGILL,  "privileged operation", privileged_op)
+DO_ERROR(SIGILL,  "execute exception", execute_exception)
+DO_ERROR(SIGSEGV, "addressing exception", addressing_exception)
+DO_ERROR(SIGFPE,  "fixpoint divide exception", divide_exception)
+DO_ERROR(SIGILL,  "translation exception", translation_exception)
+DO_ERROR(SIGILL,  "special operand exception", special_op_exception)
+DO_ERROR(SIGILL,  "operand exception", operand_exception)
+DO_ERROR(SIGILL,  "specification exception", specification_exception);
+
+asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code)
+{
+        __u8 opcode[6];
+	__u16 *location;
+	int do_sig = 0;
+
+        lock_kernel();
+	location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+	/* WARNING don't change this check back to */
+	/* int problem_state=(regs->psw.mask & PSW_PROBLEM_STATE); */
+	/* & then doing if(problem_state) an int is too small for this */
+	/* check on 64 bit. */
+	if(regs->psw.mask & PSW_PROBLEM_STATE)
+		get_user(*((__u16 *) opcode), location);
+	else
+		*((__u16 *)opcode)=*((__u16 *)location);
+	if(*((__u16 *)opcode)==S390_BREAKPOINT_U16)
+        {
+		if(do_debugger_trap(regs,SIGTRAP))
+			do_sig=1;
+	}
+	else
+		do_sig = 1;
+	if (do_sig)
+		do_trap(interruption_code, SIGILL, "illegal operation", regs, NULL);
+        unlock_kernel();
+}
+
+asmlinkage void data_exception(struct pt_regs * regs, long interruption_code)
+{
+	__u16 *location;
+	int do_sig = 0;
+
+        lock_kernel();
+	location = (__u16 *)(regs->psw.addr-S390_lowcore.pgm_ilc);
+	__asm__ volatile ("stfpc %0\n\t" 
+			  : "=m" (current->thread.fp_regs.fpc));
+	/* Same code should work when we implement fpu emulation */
+	/* provided we call data exception from the fpu emulator */
+	if(current->thread.fp_regs.fpc&FPC_DXC_MASK)
+	{
+		current->thread.ieee_instruction_pointer=(addr_t)location;
+		force_sig(SIGFPE, current);
+	}
+	else
+		do_sig = 1;
+        if (do_sig)
+                do_trap(interruption_code, SIGILL, "data exception", regs, NULL);
+        unlock_kernel();
+}
+
+
+
+/* init is done in lowcore.S and head.S */
+
+void __init trap_init(void)
+{
+        int i;
+
+        for (i = 0; i < 128; i++)
+          pgm_check_table[i] = &default_trap_handler;
+        pgm_check_table[1] = &illegal_op;
+        pgm_check_table[2] = &privileged_op;
+        pgm_check_table[3] = &execute_exception;
+        pgm_check_table[5] = &addressing_exception;
+        pgm_check_table[6] = &specification_exception;
+        pgm_check_table[7] = &data_exception;
+        pgm_check_table[9] = &divide_exception;
+        pgm_check_table[0x12] = &translation_exception;
+        pgm_check_table[0x13] = &special_op_exception;
+        pgm_check_table[0x15] = &operand_exception;
+        pgm_check_table[4] = &do_page_fault;
+        pgm_check_table[0x10] = &do_page_fault;
+        pgm_check_table[0x11] = &do_page_fault;
+        pgm_check_table[0x1C] = &privileged_op;
+        pgm_check_table[0x38] = &addressing_exception;
+        pgm_check_table[0x3B] = &do_page_fault;
+}
+
+
+void handle_per_exception(struct pt_regs *regs)
+{
+	if(regs->psw.mask&PSW_PROBLEM_STATE)
+	{
+		per_struct *per_info=&current->thread.per_info;
+		per_info->lowcore.words.perc_atmid=S390_lowcore.per_perc_atmid;
+		per_info->lowcore.words.address=S390_lowcore.per_address;
+		per_info->lowcore.words.access_id=S390_lowcore.per_access_id;
+	}
+	if(do_debugger_trap(regs,SIGTRAP))
+	{
+		/* I've seen this possibly a task structure being reused ? */
+		printk("Spurious per exception detected\n");
+		printk("switching off per tracing for this task.\n");
+		show_regs(regs);
+		/* Hopefully switching off per tracing will help us survive */
+		regs->psw.mask &= ~PSW_PER_MASK;
+	}
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/kernel/wrapper32.S linux/arch/s390x/kernel/wrapper32.S
--- v2.4.1/linux/arch/s390x/kernel/wrapper32.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/kernel/wrapper32.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,1071 @@
+/*
+*  arch/s390/kernel/sys_wrapper31.S
+*    wrapper for 31 bit compatible system calls.
+*
+*  S390 version
+*    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+*    Author(s): Gerhard Tonn (ton@de.ibm.com),
+*/ 
+
+	.globl  sys32_exit_wrapper 
+sys32_exit_wrapper:
+	lgfr	%r2,%r2			# int
+	jg	sys_exit		# branch to sys_exit
+    
+	.globl  sys32_read_wrapper 
+sys32_read_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# char *
+	llgfr	%r4,%r4			# size_t
+	jg	sys_read		# branch to sys_read
+
+	.globl  sys32_write_wrapper 
+sys32_write_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# const char *
+	llgfr	%r4,%r4			# size_t
+	jg	sys_write		# branch to system call
+
+	.globl  sys32_open_wrapper 
+sys32_open_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int
+	lgfr	%r4,%r4			# int
+	jg	sys_open		# branch to system call
+
+	.globl  sys32_close_wrapper 
+sys32_close_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	jg	sys_close		# branch to system call
+
+	.globl  sys32_creat_wrapper 
+sys32_creat_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int
+	jg	sys_creat		# branch to system call
+
+	.globl  sys32_link_wrapper 
+sys32_link_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# const char *
+	jg	sys_link		# branch to system call
+
+	.globl  sys32_unlink_wrapper 
+sys32_unlink_wrapper:
+	llgtr	%r2,%r2			# const char *
+	jg	sys_unlink		# branch to system call
+
+	.globl  sys32_chdir_wrapper 
+sys32_chdir_wrapper:
+	llgtr	%r2,%r2			# const char *
+	jg	sys_chdir		# branch to system call
+
+	.globl  sys32_time_wrapper 
+sys32_time_wrapper:
+	llgtr	%r2,%r2			# int *
+	jg	sys_time		# branch to system call
+
+	.globl  sys32_mknod_wrapper 
+sys32_mknod_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int 
+	llgfr	%r4,%r4			# dev
+	jg	sys_mknod		# branch to system call
+
+	.globl  sys32_chmod_wrapper 
+sys32_chmod_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# mode_t
+	jg	sys_chmod		# branch to system call
+
+	.globl  sys32_lchown16_wrapper 
+sys32_lchown16_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
+	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t 
+	jg	sys32_lchown16		# branch to system call
+
+	.globl  sys32_lseek_wrapper 
+sys32_lseek_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	lgfr	%r3,%r3			# off_t
+	llgfr	%r4,%r4			# unsigned int
+	jg	sys_lseek		# branch to system call
+
+#sys32_getpid_wrapper				# void 
+
+	.globl  sys32_mount_wrapper 
+sys32_mount_wrapper:
+	llgtr	%r2,%r2			# char *
+	llgtr	%r3,%r3			# char *
+	llgtr	%r4,%r4			# char *
+	llgfr	%r5,%r5			# unsigned long
+	llgtr	%r6,%r6			# void *
+	jg	sys32_mount		# branch to system call
+
+	.globl  sys32_oldumount_wrapper 
+sys32_oldumount_wrapper:
+	llgtr	%r2,%r2			# char *
+	jg	sys_oldumount		# branch to system call
+
+	.globl  sys32_setuid16_wrapper 
+sys32_setuid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
+	jg	sys32_setuid16		# branch to system call
+
+#sys32_getuid16_wrapper			# void 
+
+	.globl  sys32_ptrace_wrapper 
+sys32_ptrace_wrapper:
+	lgfr	%r2,%r2			# long
+	lgfr	%r3,%r3			# long
+	llgtr	%r4,%r4			# long
+	lgfr	%r5,%r5			# long
+	jg	sys32_ptrace		# branch to system call
+
+	.globl  sys32_alarm_wrapper 
+sys32_alarm_wrapper:
+	llgtr	%r2,%r2			# unsigned int
+	jg	sys_alarm		# branch to system call
+
+#sys32_pause_wrapper			# void 
+
+	.globl  sys32_utime_wrapper 
+sys32_utime_wrapper:
+	llgtr	%r2,%r2			# char *
+	llgtr	%r3,%r3			# struct utimbuf_emu31 *
+	jg	sys32_utime		# branch to system call
+
+	.globl  sys32_access_wrapper 
+sys32_access_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int
+	jg	sys_access		# branch to system call
+
+	.globl  sys32_nice_wrapper 
+sys32_nice_wrapper:
+	lgfr	%r2,%r2			# int
+	jg	sys_nice		# branch to system call
+
+#sys32_sync_wrapper			# void 
+
+	.globl  sys32_kill_wrapper 
+sys32_kill_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	jg	sys_kill		# branch to system call
+
+	.globl  sys32_rename_wrapper 
+sys32_rename_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# const char *
+	jg	sys_rename		# branch to system call
+
+	.globl  sys32_mkdir_wrapper 
+sys32_mkdir_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int
+	jg	sys_mkdir		# branch to system call
+
+	.globl  sys32_rmdir_wrapper 
+sys32_rmdir_wrapper:
+	llgtr	%r2,%r2			# const char *
+	jg	sys_rmdir		# branch to system call
+
+	.globl  sys32_dup_wrapper 
+sys32_dup_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	jg	sys_dup			# branch to system call
+
+	.globl  sys32_pipe_wrapper 
+sys32_pipe_wrapper:
+	llgtr	%r2,%r2			# u32 *
+	jg	sys_pipe		# branch to system call
+
+	.globl  sys32_times_wrapper 
+sys32_times_wrapper:
+	llgtr	%r2,%r2			# struct tms_emu31 *
+	jg	sys32_times		# branch to system call
+
+	.globl  sys32_brk_wrapper 
+sys32_brk_wrapper:
+	llgtr	%r2,%r2			# unsigned long
+	jg	sys_brk			# branch to system call
+
+	.globl  sys32_setgid16_wrapper 
+sys32_setgid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
+	jg	sys32_setgid16		# branch to system call
+
+#sys32_getgid16_wrapper			# void 
+
+	.globl sys32_signal_wrapper
+sys32_signal_wrapper:
+	lgfr	%r2,%r2			# int 
+	llgfr	%r3,%r3			# __sighandler_t 
+	jg	sys_signal
+
+#sys32_geteuid16_wrapper		# void 
+
+#sys32_getegid16_wrapper		# void 
+
+	.globl  sys32_acct_wrapper 
+sys32_acct_wrapper:
+	llgtr	%r2,%r2			# char *
+	jg	sys_acct		# branch to system call
+
+	.globl  sys32_umount_wrapper 
+sys32_umount_wrapper:
+	llgtr	%r2,%r2			# char *
+	lgfr	%r3,%r3			# int
+	jg	sys_umount		# branch to system call
+
+	.globl  sys32_ioctl_wrapper 
+sys32_ioctl_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# unsigned int
+	llgfr	%r4,%r4			# unsigned int
+	jg	sys32_ioctl		# branch to system call
+
+	.globl  sys32_fcntl_wrapper 
+sys32_fcntl_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# unsigned int 
+	llgfr	%r4,%r4			# unsigned long
+	jg	sys32_fcntl		# branch to system call
+
+	.globl  sys32_setpgid_wrapper 
+sys32_setpgid_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	lgfr	%r3,%r3			# pid_t
+	jg	sys_setpgid		# branch to system call
+
+	.globl  sys32_umask_wrapper 
+sys32_umask_wrapper:
+	lgfr	%r3,%r3			# int
+	jg	sys_umask		# branch to system call
+
+	.globl  sys32_chroot_wrapper 
+sys32_chroot_wrapper:
+	llgtr	%r2,%r2			# char *
+	jg	sys_chroot		# branch to system call
+
+	.globl sys32_ustat_wrapper
+sys32_ustat_wrapper:
+	llgfr	%r2,%r2			# dev_t 
+	llgtr	%r3,%r3			# struct ustat *
+	jg	sys_ustat
+
+	.globl  sys32_dup2_wrapper 
+sys32_dup2_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# unsigned int
+	jg	sys_dup2		# branch to system call
+
+#sys32_getppid_wrapper			# void 
+
+#sys32_getpgrp_wrapper			# void 
+
+#sys32_setsid_wrapper			# void 
+
+	.globl  sys32_sigaction_wrapper
+sys32_sigaction_wrapper:
+	lgfr	%r2,%r2			# int 
+	llgtr	%r3,%r3			# const struct old_sigaction *
+	jg	sys32_sigaction		# branch to system call
+
+	.globl  sys32_setreuid16_wrapper 
+sys32_setreuid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
+	jg	sys32_setreuid16	# branch to system call
+
+	.globl  sys32_setregid16_wrapper 
+sys32_setregid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
+	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t 
+	jg	sys32_setregid16	# branch to system call
+
+#sys32_sigsuspend_wrapper		# done in sigsuspend_glue 
+
+	.globl  sys32_sigpending_wrapper 
+sys32_sigpending_wrapper:
+	llgtr	%r2,%r2			# old_sigset_emu31_t *
+	jg	sys32_sigpending	# branch to system call
+
+	.globl  sys32_sethostname_wrapper 
+sys32_sethostname_wrapper:
+	llgtr	%r2,%r2			# char *
+	lgfr	%r3,%r3			# int
+	jg	sys_sethostname		# branch to system call
+
+	.globl  sys32_setrlimit_wrapper 
+sys32_setrlimit_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# struct rlimit_emu31 *
+	jg	sys32_setrlimit		# branch to system call
+
+	.globl  sys32_old_getrlimit_wrapper 
+sys32_old_getrlimit_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# struct rlimit_emu31 *
+	jg	sys32_old_getrlimit	# branch to system call
+
+	.globl  sys32_mmap2_wrapper 
+sys32_mmap2_wrapper:
+	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
+	jg	sys32_mmap2			# branch to system call
+
+	.globl  sys32_getrusage_wrapper 
+sys32_getrusage_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# struct rusage_emu31 *
+	jg	sys32_getrusage		# branch to system call
+
+	.globl  sys32_gettimeofday_wrapper 
+sys32_gettimeofday_wrapper:
+	llgtr	%r2,%r2			# struct timeval_emu31 *
+	llgtr	%r3,%r3			# struct timezone *
+	jg	sys32_gettimeofday	# branch to system call
+
+	.globl  sys32_settimeofday_wrapper 
+sys32_settimeofday_wrapper:
+	llgtr	%r2,%r2			# struct timeval_emu31 *
+	llgtr	%r3,%r3			# struct timezone *
+	jg	sys32_settimeofday	# branch to system call
+
+	.globl  sys32_getgroups16_wrapper 
+sys32_getgroups16_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
+	jg	sys32_getgroups16	# branch to system call
+
+	.globl  sys32_setgroups16_wrapper 
+sys32_setgroups16_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
+	jg	sys32_setgroups16	# branch to system call
+
+	.globl  sys32_symlink_wrapper 
+sys32_symlink_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# const char *
+	jg	sys_symlink		# branch to system call
+
+	.globl  sys32_readlink_wrapper 
+sys32_readlink_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# char *
+	lgfr	%r4,%r4			# int
+	jg	sys_readlink		# branch to system call
+
+	.globl  sys32_uselib_wrapper 
+sys32_uselib_wrapper:
+	llgtr	%r2,%r2			# const char *
+	jg	sys_uselib		# branch to system call
+
+	.globl  sys32_swapon_wrapper 
+sys32_swapon_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# int
+	jg	sys_swapon		# branch to system call
+
+	.globl  sys32_reboot_wrapper 
+sys32_reboot_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	llgfr	%r4,%r4			# unsigned int
+	llgtr	%r5,%r5			# void *
+	jg	sys_reboot		# branch to system call
+
+	.globl  old32_readdir_wrapper 
+old32_readdir_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# void *
+	llgfr	%r4,%r4			# unsigned int
+	jg	old32_readdir		# branch to system call
+
+	.globl  old32_mmap_wrapper 
+old32_mmap_wrapper:
+	llgtr	%r2,%r2			# struct mmap_arg_struct_emu31 *
+	jg	old32_mmap		# branch to system call
+
+	.globl  sys32_munmap_wrapper 
+sys32_munmap_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# size_t 
+	jg	sys_munmap		# branch to system call
+
+	.globl  sys32_truncate_wrapper 
+sys32_truncate_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# unsigned long
+	jg	sys_truncate		# branch to system call
+
+	.globl  sys32_ftruncate_wrapper 
+sys32_ftruncate_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# unsigned long
+	jg	sys_ftruncate		# branch to system call
+
+	.globl  sys32_fchmod_wrapper 
+sys32_fchmod_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# mode_t
+	jg	sys_fchmod		# branch to system call
+
+	.globl  sys32_fchown16_wrapper 
+sys32_fchown16_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# __kernel_old_uid_emu31_t *
+	llgtr	%r4,%r4			# __kernel_old_gid_emu31_t *
+	jg	sys32_fchown16		# branch to system call
+
+	.globl  sys32_getpriority_wrapper 
+sys32_getpriority_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	jg	sys_getpriority		# branch to system call
+
+	.globl  sys32_setpriority_wrapper 
+sys32_setpriority_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	lgfr	%r4,%r4			# int
+	jg	sys_setpriority		# branch to system call
+
+	.globl  sys32_statfs_wrapper 
+sys32_statfs_wrapper:
+	llgtr	%r2,%r2			# char *
+	llgtr	%r3,%r3			# struct statfs_emu31 *
+	jg	sys32_statfs		# branch to system call
+
+	.globl  sys32_fstatfs_wrapper 
+sys32_fstatfs_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# struct statfs_emu31 *
+	jg	sys32_fstatfs		# branch to system call
+
+	.globl  sys32_socketcall_wrapper 
+sys32_socketcall_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# u32 *
+	jg	sys32_socketcall	# branch to system call
+
+	.globl  sys32_syslog_wrapper 
+sys32_syslog_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# char *
+	lgfr	%r4,%r4			# int
+	jg	sys_syslog		# branch to system call
+
+	.globl  sys32_setitimer_wrapper 
+sys32_setitimer_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# struct itimerval_emu31 *
+	llgtr	%r4,%r4			# struct itimerval_emu31 *
+	jg	sys32_setitimer		# branch to system call
+
+	.globl  sys32_getitimer_wrapper 
+sys32_getitimer_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# struct itimerval_emu31 *
+	jg	sys32_getitimer		# branch to system call
+
+	.globl  sys32_newstat_wrapper 
+sys32_newstat_wrapper:
+	llgtr	%r2,%r2			# char *
+	llgtr	%r3,%r3			# struct stat_emu31 *
+	jg	sys32_newstat		# branch to system call
+
+	.globl  sys32_newlstat_wrapper 
+sys32_newlstat_wrapper:
+	llgtr	%r2,%r2			# char *
+	llgtr	%r3,%r3			# struct stat_emu31 *
+	jg	sys32_newlstat		# branch to system call
+
+	.globl  sys32_newfstat_wrapper 
+sys32_newfstat_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# struct stat_emu31 *
+	jg	sys32_newfstat		# branch to system call
+
+#sys32_vhangup_wrapper			# void 
+
+	.globl  sys32_wait4_wrapper 
+sys32_wait4_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	llgtr	%r3,%r3			# unsigned int *
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# struct rusage *
+	jg	sys32_wait4		# branch to system call
+
+	.globl  sys32_swapoff_wrapper 
+sys32_swapoff_wrapper:
+	llgtr	%r2,%r2			# const char *
+	jg	sys_swapoff		# branch to system call
+
+	.globl  sys32_sysinfo_wrapper 
+sys32_sysinfo_wrapper:
+	llgtr	%r2,%r2			# struct sysinfo_emu31 *
+	jg	sys32_sysinfo		# branch to system call
+
+	.globl  sys32_ipc_wrapper 
+sys32_ipc_wrapper:
+	llgfr	%r2,%r2			# uint
+	lgfr	%r3,%r3			# int
+	lgfr	%r4,%r4			# int
+	lgfr	%r5,%r5			# int
+	llgtr	%r6,%r6			# void *
+	jg	sys32_ipc		# branch to system call
+
+	.globl  sys32_fsync_wrapper 
+sys32_fsync_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	jg	sys_fsync		# branch to system call
+
+#sys32_sigreturn_wrapper		# done in sigreturn_glue 
+
+#sys32_clone_wrapper			# done in clone_glue 
+
+	.globl  sys32_setdomainname_wrapper 
+sys32_setdomainname_wrapper:
+	llgtr	%r2,%r2			# char *
+	lgfr	%r3,%r3			# int
+	jg	sys_setdomainname	# branch to system call
+
+	.globl  sys32_newuname_wrapper 
+sys32_newuname_wrapper:
+	llgtr	%r2,%r2			# struct new_utsname *
+	jg	sys_newuname		# branch to system call
+
+	.globl  sys32_adjtimex_wrapper 
+sys32_adjtimex_wrapper:
+	llgtr	%r2,%r2			# struct timex_emu31 *
+	jg	sys32_adjtimex		# branch to system call
+
+	.globl  sys32_mprotect_wrapper 
+sys32_mprotect_wrapper:
+	llgtr	%r2,%r2			# unsigned long (actually pointer
+	llgfr	%r3,%r3			# size_t
+	llgfr	%r4,%r4			# unsigned long
+	jg	sys_mprotect		# branch to system call
+
+	.globl  sys32_sigprocmask_wrapper 
+sys32_sigprocmask_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# old_sigset_emu31 *
+	llgtr	%r4,%r4			# old_sigset_emu31 *
+	jg	sys32_sigprocmask		# branch to system call
+
+	.globl  sys32_create_module_wrapper 
+sys32_create_module_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# size_t
+	jg	sys32_create_module	# branch to system call
+
+	.globl  sys32_init_module_wrapper 
+sys32_init_module_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# struct module *
+	jg	sys32_init_module	# branch to system call
+
+	.globl  sys32_delete_module_wrapper 
+sys32_delete_module_wrapper:
+	llgtr	%r2,%r2			# const char *
+	jg	sys32_delete_module	# branch to system call
+
+	.globl  sys32_get_kernel_syms_wrapper 
+sys32_get_kernel_syms_wrapper:
+	llgtr	%r2,%r2			# struct kernel_sym_emu31 *
+	jg	sys32_get_kernel_syms	# branch to system call
+
+	.globl  sys32_quotactl_wrapper 
+sys32_quotactl_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char *
+	lgfr	%r4,%r4			# int
+	llgtr	%r5,%r5			# caddr_t
+	jg	sys32_quotactl		# branch to system call
+
+	.globl  sys32_getpgid_wrapper 
+sys32_getpgid_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	jg	sys_getpgid		# branch to system call
+
+	.globl  sys32_fchdir_wrapper 
+sys32_fchdir_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	jg	sys_fchdir		# branch to system call
+
+	.globl  sys32_bdflush_wrapper 
+sys32_bdflush_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# long
+	jg	sys_bdflush		# branch to system call
+
+	.globl  sys32_sysfs_wrapper 
+sys32_sysfs_wrapper:
+	lgfr	%r2,%r2			# int
+	llgfr	%r3,%r3			# unsigned long
+	llgfr	%r4,%r4			# unsigned long
+	jg	sys_sysfs		# branch to system call
+
+	.globl  sys32_personality_wrapper 
+sys32_personality_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	jg	sys_personality		# branch to system call
+
+	.globl  sys32_setfsuid16_wrapper 
+sys32_setfsuid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
+	jg	sys32_setfsuid16	# branch to system call
+
+	.globl  sys32_setfsgid16_wrapper 
+sys32_setfsgid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
+	jg	sys32_setfsgid16	# branch to system call
+
+	.globl  sys32_llseek_wrapper 
+sys32_llseek_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	lgfr	%r3,%r3			# off_t
+	llgfr	%r4,%r4			# unsigned int
+	jg	sys_llseek		# branch to system call
+
+	.globl  sys32_getdents_wrapper 
+sys32_getdents_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# void *
+	llgfr	%r4,%r4			# unsigned int
+	jg	sys32_getdents		# branch to system call
+
+	.globl  sys32_select_wrapper 
+sys32_select_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# fd_set *
+	llgtr	%r4,%r4			# fd_set *
+	llgtr	%r5,%r5			# fd_set *
+	llgtr	%r6,%r6			# struct timeval_emu31 *
+	jg	sys32_select		# branch to system call
+
+	.globl  sys32_flock_wrapper 
+sys32_flock_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# unsigned int
+	jg	sys_flock		# branch to system call
+
+	.globl  sys32_msync_wrapper 
+sys32_msync_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# size_t
+	lgfr	%r4,%r4			# int
+	jg	sys_msync		# branch to system call
+
+	.globl  sys32_readv_wrapper 
+sys32_readv_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgtr	%r3,%r3			# const struct iovec_emu31 *
+	llgfr	%r4,%r4			# unsigned long
+	jg	sys32_readv		# branch to system call
+
+	.globl  sys32_writev_wrapper 
+sys32_writev_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgtr	%r3,%r3			# const struct iovec_emu31 *
+	llgfr	%r4,%r4			# unsigned long
+	jg	sys32_writev		# branch to system call
+
+	.globl  sys32_getsid_wrapper 
+sys32_getsid_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	jg	sys_getsid		# branch to system call
+
+	.globl  sys32_fdatasync_wrapper 
+sys32_fdatasync_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	jg	sys_fdatasync		# branch to system call
+
+#sys32_sysctl_wrapper			# tbd 
+
+	.globl  sys32_mlock_wrapper 
+sys32_mlock_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# size_t
+	jg	sys_mlock		# branch to system call
+
+	.globl  sys32_munlock_wrapper 
+sys32_munlock_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# size_t
+	jg	sys_munlock		# branch to system call
+
+	.globl  sys32_mlockall_wrapper 
+sys32_mlockall_wrapper:
+	lgfr	%r2,%r2			# int
+	jg	sys_mlockall		# branch to system call
+
+#sys32_munlockall_wrapper		# void 
+
+	.globl  sys32_sched_setparam_wrapper 
+sys32_sched_setparam_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	llgtr	%r3,%r3			# struct sched_param *
+	jg	sys_sched_setparam	# branch to system call
+
+	.globl  sys32_sched_getparam_wrapper 
+sys32_sched_getparam_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	llgtr	%r3,%r3			# struct sched_param *
+	jg	sys_sched_getparam	# branch to system call
+
+	.globl  sys32_sched_setscheduler_wrapper 
+sys32_sched_setscheduler_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	lgfr	%r3,%r3			# int
+	llgtr	%r4,%r4			# struct sched_param *
+	jg	sys_sched_setscheduler	# branch to system call
+
+	.globl  sys32_sched_getscheduler_wrapper 
+sys32_sched_getscheduler_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	jg	sys_sched_getscheduler	# branch to system call
+
+#sys32_sched_yield_wrapper		# void 
+
+	.globl  sys32_sched_get_priority_max_wrapper 
+sys32_sched_get_priority_max_wrapper:
+	lgfr	%r2,%r2			# int
+	jg	sys_sched_get_priority_max	# branch to system call
+
+	.globl  sys32_sched_get_priority_min_wrapper 
+sys32_sched_get_priority_min_wrapper:
+	lgfr	%r2,%r2			# int
+	jg	sys_sched_get_priority_min	# branch to system call
+
+	.globl  sys32_sched_rr_get_interval_wrapper 
+sys32_sched_rr_get_interval_wrapper:
+	lgfr	%r2,%r2			# pid_t
+	llgtr	%r3,%r3			# struct timespec_emu31 *
+	jg	sys32_sched_rr_get_interval	# branch to system call
+
+	.globl  sys32_nanosleep_wrapper 
+sys32_nanosleep_wrapper:
+	llgtr	%r2,%r2			# struct timespec_emu31 *
+	llgtr	%r3,%r3			# struct timespec_emu31 *
+	jg	sys32_nanosleep		# branch to system call
+
+	.globl  sys32_mremap_wrapper 
+sys32_mremap_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# unsigned long
+	llgfr	%r4,%r4			# unsigned long
+	llgfr	%r5,%r5			# unsigned long
+	llgfr	%r6,%r6			# unsigned long
+	jg	sys_mremap		# branch to system call
+
+	.globl  sys32_setresuid16_wrapper 
+sys32_setresuid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_uid_emu31_t 
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
+	llgfr	%r4,%r4			# __kernel_old_uid_emu31_t 
+	jg	sys32_setresuid16	# branch to system call
+
+	.globl  sys32_getresuid16_wrapper 
+sys32_getresuid16_wrapper:
+	llgtr	%r2,%r2			# __kernel_old_uid_emu31_t *
+	llgtr	%r3,%r3			# __kernel_old_uid_emu31_t *
+	llgtr	%r4,%r4			# __kernel_old_uid_emu31_t *
+	jg	sys32_getresuid16	# branch to system call
+
+	.globl  sys32_query_module_wrapper 
+sys32_query_module_wrapper:
+	llgtr	%r2,%r2			# const char * 
+	lgfr	%r3,%r3			# int 
+	llgtr	%r4,%r4			# char * 
+	llgfr	%r5,%r5			# size_t 
+	llgtr	%r6,%r6			# size_t * 
+	jg	sys32_query_module	# branch to system call
+
+	.globl  sys32_poll_wrapper 
+sys32_poll_wrapper:
+	llgtr	%r2,%r2			# struct pollfd * 
+	llgfr	%r3,%r3			# unsigned int 
+	lgfr	%r4,%r4			# long 
+	jg	sys_poll		# branch to system call
+
+	.globl  sys32_nfsservctl_wrapper 
+sys32_nfsservctl_wrapper:
+	lgfr	%r2,%r2			# int 
+	llgtr	%r3,%r3			# struct nfsctl_arg_emu31 * 
+	llgtr	%r4,%r4			# union nfsctl_res_emu31 * 
+	jg	sys32_nfsservctl	# branch to system call
+
+	.globl  sys32_setresgid16_wrapper 
+sys32_setresgid16_wrapper:
+	llgfr	%r2,%r2			# __kernel_old_gid_emu31_t 
+	llgfr	%r3,%r3			# __kernel_old_gid_emu31_t 
+	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t 
+	jg	sys32_setresgid16	# branch to system call
+
+	.globl  sys32_getresgid16_wrapper 
+sys32_getresgid16_wrapper:
+	llgtr	%r2,%r2			# __kernel_old_gid_emu31_t *
+	llgtr	%r3,%r3			# __kernel_old_gid_emu31_t *
+	llgtr	%r4,%r4			# __kernel_old_gid_emu31_t *
+	jg	sys32_getresgid16	# branch to system call
+
+	.globl  sys32_prctl_wrapper 
+sys32_prctl_wrapper:
+	lgfr	%r2,%r2			# int
+	llgfr	%r3,%r3			# unsigned long
+	llgfr	%r4,%r4			# unsigned long
+	llgfr	%r5,%r5			# unsigned long
+	llgfr	%r6,%r6			# unsigned long
+	jg	sys_prctl		# branch to system call
+
+#sys32_rt_sigreturn_wrapper		# done in rt_sigreturn_glue 
+
+	.globl  sys32_rt_sigaction_wrapper 
+sys32_rt_sigaction_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const struct sigaction_emu31 *
+	llgtr	%r4,%r4			# const struct sigaction_emu31 *
+	llgfr	%r5,%r5			# size_t
+	jg	sys32_rt_sigaction	# branch to system call
+
+	.globl  sys32_rt_sigprocmask_wrapper 
+sys32_rt_sigprocmask_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# old_sigset_emu31 *
+	llgtr	%r4,%r4			# old_sigset_emu31 *
+	jg	sys32_rt_sigprocmask	# branch to system call
+
+	.globl  sys32_rt_sigpending_wrapper 
+sys32_rt_sigpending_wrapper:
+	llgtr	%r2,%r2			# sigset_emu31 *
+	llgfr	%r3,%r3			# size_t
+	jg	sys32_rt_sigpending	# branch to system call
+
+	.globl  sys32_rt_sigtimedwait_wrapper 
+sys32_rt_sigtimedwait_wrapper:
+	llgtr	%r2,%r2			# const sigset_emu31_t *
+	llgtr	%r3,%r3			# siginfo_emu31_t *
+	llgtr	%r4,%r4			# const struct timespec_emu31 *
+	llgfr	%r5,%r5			# size_t
+	jg	sys32_rt_sigtimedwait	# branch to system call
+
+	.globl  sys32_rt_sigqueueinfo_wrapper 
+sys32_rt_sigqueueinfo_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	llgtr	%r4,%r4			# siginfo_emu31_t *
+	jg	sys32_rt_sigqueueinfo	# branch to system call
+
+#sys32_rt_sigsuspend_wrapper		# done in rt_sigsuspend_glue 
+
+	.globl  sys32_pread_wrapper 
+sys32_pread_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# char *
+	llgfr	%r4,%r4			# size_t
+	llgfr	%r5,%r5			# u32
+	llgfr	%r6,%r6			# u32
+	jg	sys32_pread		# branch to system call
+
+	.globl  sys32_pwrite_wrapper 
+sys32_pwrite_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# const char *
+	llgfr	%r4,%r4			# size_t
+	llgfr	%r5,%r5			# u32
+	llgfr	%r6,%r6			# u32
+	jg	sys32_pwrite		# branch to system call
+
+	.globl  sys32_chown16_wrapper 
+sys32_chown16_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# __kernel_old_uid_emu31_t 
+	llgfr	%r4,%r4			# __kernel_old_gid_emu31_t 
+	jg	sys32_chown16		# branch to system call
+
+	.globl  sys32_getcwd_wrapper 
+sys32_getcwd_wrapper:
+	llgtr	%r2,%r2			# char *
+	llgfr	%r3,%r3			# unsigned long
+	jg	sys_getcwd		# branch to system call
+
+	.globl  sys32_capget_wrapper 
+sys32_capget_wrapper:
+	llgtr	%r2,%r2			# cap_user_header_t
+	llgtr	%r3,%r3			# cap_user_data_t
+	jg	sys_capget		# branch to system call
+
+	.globl  sys32_capset_wrapper 
+sys32_capset_wrapper:
+	llgtr	%r2,%r2			# cap_user_header_t
+	llgtr	%r3,%r3			# const cap_user_data_t
+	jg	sys_capset		# branch to system call
+
+	.globl sys32_sigaltstack_wrapper
+sys32_sigaltstack_wrapper:
+	llgtr	%r2,%r2			# const stack_emu31_t * 
+	llgtr	%r3,%r3			# stack_emu31_t * 
+	jg	sys32_sigaltstack
+
+	.globl  sys32_sendfile_wrapper 
+sys32_sendfile_wrapper:
+	lgfr	%r2,%r2			# int
+	lgfr	%r3,%r3			# int
+	llgtr	%r4,%r4			# __kernel_off_emu31_t *
+	llgfr	%r5,%r5			# size_t
+	jg	sys32_sendfile		# branch to system call
+
+#sys32_vfork_wrapper			# done in vfork_glue 
+
+	.globl  sys32_truncate64_wrapper 
+sys32_truncate64_wrapper:
+	llgtr	%r2,%r2			# const char *
+	lgfr	%r3,%r3			# s32 
+	llgfr	%r4,%r4			# u32 
+	jg	sys32_truncate64	# branch to system call
+
+	.globl  sys32_ftruncate64_wrapper 
+sys32_ftruncate64_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	lgfr	%r3,%r3			# s32 
+	llgfr	%r4,%r4			# u32 
+	jg	sys32_ftruncate64	# branch to system call
+
+	.globl sys32_lchown_wrapper	
+sys32_lchown_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# uid_t
+	llgfr	%r4,%r4			# gid_t
+	jg	sys_lchown		# branch to system call
+
+#sys32_getuid_wrapper			# void			 
+#sys32_getgid_wrapper			# void 
+#sys32_geteuid_wrapper			# void 
+#sys32_getegid_wrapper			# void 
+
+	.globl sys32_setreuid_wrapper
+sys32_setreuid_wrapper:
+	llgfr	%r2,%r2			# uid_t
+	llgfr	%r3,%r3			# uid_t
+	jg	sys_setreuid		# branch to system call
+
+	.globl sys32_setregid_wrapper
+sys32_setregid_wrapper:
+	llgfr	%r2,%r2			# gid_t
+	llgfr	%r3,%r3			# gid_t
+	jg	sys_setregid		# branch to system call
+
+	.globl  sys32_getgroups_wrapper 
+sys32_getgroups_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# gid_t *
+	jg	sys_getgroups		# branch to system call
+
+	.globl  sys32_setgroups_wrapper 
+sys32_setgroups_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# gid_t *
+	jg	sys_setgroups		# branch to system call
+
+	.globl sys32_fchown_wrapper	
+sys32_fchown_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# uid_t
+	llgfr	%r4,%r4			# gid_t
+	jg	sys_fchown		# branch to system call
+
+	.globl sys32_setresuid_wrapper	
+sys32_setresuid_wrapper:
+	llgfr	%r2,%r2			# uid_t
+	llgfr	%r3,%r3			# uid_t
+	llgfr	%r4,%r4			# uid_t
+	jg	sys_setresuid		# branch to system call
+
+	.globl sys32_getresuid_wrapper	
+sys32_getresuid_wrapper:
+	llgtr	%r2,%r2			# uid_t *
+	llgtr	%r3,%r3			# uid_t *
+	llgtr	%r4,%r4			# uid_t *
+	jg	sys_getresuid		# branch to system call
+
+	.globl sys32_setresgid_wrapper	
+sys32_setresgid_wrapper:
+	llgfr	%r2,%r2			# gid_t
+	llgfr	%r3,%r3			# gid_t
+	llgfr	%r4,%r4			# gid_t
+	jg	sys_setresgid		# branch to system call
+
+	.globl sys32_getresgid_wrapper	
+sys32_getresgid_wrapper:
+	llgtr	%r2,%r2			# gid_t *
+	llgtr	%r3,%r3			# gid_t *
+	llgtr	%r4,%r4			# gid_t *
+	jg	sys_getresgid		# branch to system call
+
+	.globl sys32_chown_wrapper	
+sys32_chown_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgfr	%r3,%r3			# uid_t
+	llgfr	%r4,%r4			# gid_t
+	jg	sys_chown		# branch to system call
+
+	.globl sys32_setuid_wrapper	
+sys32_setuid_wrapper:
+	llgfr	%r2,%r2			# uid_t
+	jg	sys_setuid		# branch to system call
+
+	.globl sys32_setgid_wrapper	
+sys32_setgid_wrapper:
+	llgfr	%r2,%r2			# gid_t
+	jg	sys_setgid		# branch to system call
+
+	.globl sys32_setfsuid_wrapper	
+sys32_setfsuid_wrapper:
+	llgfr	%r2,%r2			# uid_t
+	jg	sys_setfsuid		# branch to system call
+
+	.globl sys32_setfsgid_wrapper	
+sys32_setfsgid_wrapper:
+	llgfr	%r2,%r2			# gid_t
+	jg	sys_setfsgid		# branch to system call
+
+	.globl  sys32_pivot_root_wrapper 
+sys32_pivot_root_wrapper:
+	llgtr	%r2,%r2			# const char *
+	llgtr	%r3,%r3			# const char *
+	jg	sys_pivot_root		# branch to system call
+
+	.globl  sys32_mincore_wrapper 
+sys32_mincore_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# size_t
+	llgtr	%r4,%r4			# unsigned char *
+	jg	sys_mincore		# branch to system call
+
+	.globl  sys32_madvise_wrapper 
+sys32_madvise_wrapper:
+	llgfr	%r2,%r2			# unsigned long
+	llgfr	%r3,%r3			# size_t
+	lgfr	%r4,%r4			# int
+	jg	sys_madvise		# branch to system call
+
+	.globl  sys32_getdents64_wrapper 
+sys32_getdents64_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgtr	%r3,%r3			# void *
+	llgfr	%r4,%r4			# unsigned int
+	jg	sys_getdents64		# branch to system call
+
+	.globl  sys32_fcntl64_wrapper 
+sys32_fcntl64_wrapper:
+	llgfr	%r2,%r2			# unsigned int
+	llgfr	%r3,%r3			# unsigned int 
+	llgfr	%r4,%r4			# unsigned long
+	jg	sys32_fcntl64		# branch to system call
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/Makefile linux/arch/s390x/lib/Makefile
--- v2.4.1/linux/arch/s390x/lib/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,18 @@
+#
+# Makefile for s390-specific library files..
+#
+
+ifdef SMP
+.S.o:
+	$(CC) -D__ASSEMBLY__ $(AFLAGS) -traditional -c $< -o $*.o
+else
+.S.o:
+	$(CC) -D__ASSEMBLY__ -traditional -c $< -o $*.o
+endif
+
+L_TARGET = lib.a
+
+obj-y	 = checksum.o delay.o memset.o strcmp.o strncpy.o uaccess.o
+
+include $(TOPDIR)/Rules.make
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/checksum.c linux/arch/s390x/lib/checksum.c
--- v2.4.1/linux/arch/s390x/lib/checksum.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/checksum.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,40 @@
+/*
+ *  arch/s390/lib/checksum.c
+ *    S390 fast network checksum routines
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ulrich Hild        (first version),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *
+ * This file contains network checksum routines
+ */
+ 
+#include <linux/string.h>
+#include <linux/types.h>
+#include <asm/uaccess.h>
+#include <asm/byteorder.h>
+#include <asm/checksum.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+unsigned int
+csum_partial (const unsigned char *buff, int len, unsigned int sum)
+{
+	  /*
+	   * Experiments with ethernet and slip connections show that buff
+	   * is aligned on either a 2-byte or 4-byte boundary.
+	   */
+        __asm__ __volatile__ (
+                "    lgr  2,%1\n"    /* address in gpr 2 */
+                "    lgfr 3,%2\n"    /* length in gpr 3 */
+                "0:  cksm %0,2\n"    /* do checksum on longs */
+                "    jo   0b\n"
+                : "+&d" (sum)
+                : "d" (buff), "d" (len)
+                : "cc", "2", "3" );
+        return sum;
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/delay.c linux/arch/s390x/lib/delay.c
--- v2.4.1/linux/arch/s390x/lib/delay.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/delay.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,50 @@
+/*
+ *  arch/s390/kernel/delay.c
+ *    Precise Delay Loops for S390
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ *  Derived from "arch/i386/lib/delay.c"
+ *    Copyright (C) 1993 Linus Torvalds
+ *    Copyright (C) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <linux/config.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif
+
+void __delay(unsigned long loops)
+{
+        /*
+         * To end the bloody studid and useless discussion about the
+         * BogoMips number I took the liberty to define the __delay
+         * function in a way that that resulting BogoMips number will
+         * yield the megahertz number of the cpu. The important function
+         * is udelay and that is done using the tod clock. -- martin.
+         */
+        __asm__ __volatile__(
+                "0: brct %0,0b"
+                : /* no outputs */ : "r" (loops/2) );
+}
+
+/*
+ * Waits for 'usecs' microseconds using the tod clock
+ */
+void __udelay(unsigned long usecs)
+{
+        uint64_t start_cc, end_cc;
+
+        if (usecs == 0)
+                return;
+        asm volatile ("STCK %0" : "=m" (start_cc));
+        do {
+                asm volatile ("STCK %0" : "=m" (end_cc));
+        } while (((end_cc - start_cc)/4096) < usecs);
+}
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/memset.S linux/arch/s390x/lib/memset.S
--- v2.4.1/linux/arch/s390x/lib/memset.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/memset.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,30 @@
+/*
+ *  arch/s390/lib/memset.S
+ *    S390 fast memset routine
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address to memory area
+ * R3 = byte to fill memory with
+ * R4 = number of bytes to fill
+ */
+        .globl  memset
+memset:
+        LTGR    4,4
+        JZ      memset_end
+        LGR     0,2                    # save pointer to memory area
+        LGR     1,3                    # move pad byte to R1
+        LGR     3,4
+        SGR     4,4                    # no source for MVCLE, only a pad byte
+        SGR     5,5
+        MVCLE   2,4,0(1)               # thats it, MVCLE is your friend
+        JO      .-4
+        LGR     2,0                    # return pointer to mem.
+memset_end:
+        BR      14
+        
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/strcmp.S linux/arch/s390x/lib/strcmp.S
--- v2.4.1/linux/arch/s390x/lib/strcmp.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/strcmp.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,27 @@
+/*
+ *  arch/s390/lib/strcmp.S
+ *    S390 strcmp routine
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address of compare string
+ * R3 = address of test string
+ */
+        .globl   strcmp
+strcmp:
+        SGR     0,0
+        SGR     1,1
+        CLST    2,3
+        JO      .-4
+        JE      strcmp_equal
+        IC      0,0(3)
+        IC      1,0(2)
+        SGR     1,0
+strcmp_equal:
+        LGR     2,1
+        BR      14
+        
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/strncpy.S linux/arch/s390x/lib/strncpy.S
--- v2.4.1/linux/arch/s390x/lib/strncpy.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/strncpy.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,30 @@
+/*
+ *  arch/s390/kernel/strncpy.S
+ *    S390 strncpy routine
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+/*
+ * R2 = address of destination
+ * R3 = address of source string
+ * R4 = max number of bytes to copy
+ */
+        .globl   strncpy
+strncpy:
+        LGR     1,2            # don't touch address in R2
+	LTR     4,4
+        JZ      strncpy_exit   # 0 bytes -> nothing to do
+	SGR     0,0
+strncpy_loop:
+        ICM     0,1,0(3)       # ICM sets the cc, IC does not
+	LA      3,1(3)
+        STC     0,0(1)
+	LA      1,1(1)
+        JZ      strncpy_exit   # ICM inserted a 0x00
+        BRCTG   4,strncpy_loop # R4 -= 1, jump to strncpy_loop if > 0
+strncpy_exit:
+        BR      14
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/lib/uaccess.S linux/arch/s390x/lib/uaccess.S
--- v2.4.1/linux/arch/s390x/lib/uaccess.S	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/lib/uaccess.S	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,45 @@
+/*
+ *  arch/s390x/lib/uaccess.S
+ *    fixup routines for copy_{from|to}_user functions.
+ *
+ *  S390
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  These functions have a non-standard call interface
+ */
+
+#include <asm/lowcore.h>
+
+        .text
+        .align 4
+        .globl __copy_from_user_fixup
+__copy_from_user_fixup:
+        lg    1,__LC_PGM_OLD_PSW+8
+0:      lghi  3,-4096
+        ng    3,__LC_TRANS_EXC_ADDR
+        sgr   3,4
+        bm    4(1)
+1:      mvcle 2,4,0
+        b     4(1)
+        .section __ex_table,"a"
+        .align 8
+	.quad 1b,0b
+        .previous
+
+        .align 4
+        .text
+        .globl __copy_to_user_fixup
+__copy_to_user_fixup:
+        lg    1,__LC_PGM_OLD_PSW+8
+0:      lghi  5,-4096
+        ng    5,__LC_TRANS_EXC_ADDR
+        sgr   5,4
+        bm    4(1)
+1:      mvcle 4,2,0
+        b     4(1)
+        .section __ex_table,"a"
+        .align 8
+        .quad 1b,0b
+        .previous
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/mm/Makefile linux/arch/s390x/mm/Makefile
--- v2.4.1/linux/arch/s390x/mm/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/mm/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,14 @@
+#
+# Makefile for the linux i386-specific parts of the memory manager.
+#
+# 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 := mm.o
+
+obj-y	 := init.o fault.o ioremap.o extable.o
+
+include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/mm/extable.c linux/arch/s390x/mm/extable.c
--- v2.4.1/linux/arch/s390x/mm/extable.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/mm/extable.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,61 @@
+/*
+ *  arch/s390/mm/extable.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com)
+ *
+ *  Derived from "arch/i386/mm/extable.c"
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <asm/uaccess.h>
+
+extern const struct exception_table_entry __start___ex_table[];
+extern const struct exception_table_entry __stop___ex_table[];
+
+static inline unsigned long
+search_one_table(const struct exception_table_entry *first,
+		 const struct exception_table_entry *last,
+		 unsigned long value)
+{
+        while (first <= last) {
+		const struct exception_table_entry *mid;
+		long diff;
+
+		mid = (last - first) / 2 + first;
+		diff = mid->insn - value;
+                if (diff == 0)
+                        return mid->fixup;
+                else if (diff < 0)
+                        first = mid+1;
+                else
+                        last = mid-1;
+        }
+        return 0;
+}
+
+unsigned long
+search_exception_table(unsigned long addr)
+{
+	unsigned long ret;
+
+#ifndef CONFIG_MODULES
+	/* There is only the kernel to search.  */
+	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
+	if (ret) return FIX_PSW(ret);
+#else
+	/* The kernel is the last "module" -- no need to treat it special.  */
+	struct module *mp;
+	for (mp = module_list; mp != NULL; mp = mp->next) {
+		if (mp->ex_table_start == NULL)
+			continue;
+		ret = search_one_table(mp->ex_table_start,
+				       mp->ex_table_end - 1, addr);
+		if (ret) return FIX_PSW(ret);
+	}
+#endif
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/mm/fault.c linux/arch/s390x/mm/fault.c
--- v2.4.1/linux/arch/s390x/mm/fault.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/mm/fault.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,266 @@
+/*
+ *  arch/s390/mm/fault.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com)
+ *
+ *  Derived from "arch/i386/mm/fault.c"
+ *    Copyright (C) 1995  Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
+
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/hardirq.h>
+
+#ifdef CONFIG_SYSCTL
+extern int sysctl_userprocess_debug;
+#endif
+
+extern void die(const char *,struct pt_regs *,long);
+
+/*
+ * This routine handles page faults.  It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * error_code:
+ *             ****0004       Protection           ->  Write-Protection  (suprression)
+ *             ****0010       Segment translation  ->  Not present       (nullification)
+ *             ****0011       Page translation     ->  Not present       (nullification)
+ *             ****003B       Region third exception ->  Not present       (nullification)
+ */
+asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
+{
+        struct task_struct *tsk;
+        struct mm_struct *mm;
+        struct vm_area_struct * vma;
+        unsigned long address;
+        unsigned long fixup;
+        int write;
+        unsigned long psw_mask;
+        unsigned long psw_addr;
+	int si_code = SEGV_MAPERR;
+	int kernel_address = 0;
+
+        /*
+         *  get psw mask of Program old psw to find out,
+         *  if user or kernel mode
+         */
+
+        psw_mask = S390_lowcore.program_old_psw.mask;
+        psw_addr = S390_lowcore.program_old_psw.addr;
+
+        /* 
+         * get the failing address 
+         * more specific the segment and page table portion of 
+         * the address 
+         */
+
+        address = S390_lowcore.trans_exc_code&-4096L;
+
+        tsk = current;
+        mm = tsk->mm;
+
+        if (in_interrupt() || !mm)
+                goto no_context;
+
+	/*
+	 * Check which address space the address belongs to
+	 */
+	switch (S390_lowcore.trans_exc_code & 3)
+	{
+	case 0: /* Primary Segment Table Descriptor */
+		kernel_address = 1;
+		goto no_context;
+
+	case 1: /* STD determined via access register */
+		if (S390_lowcore.exc_access_id == 0)
+		{
+			kernel_address = 1;
+			goto no_context;
+		}
+		if (regs && S390_lowcore.exc_access_id < NUM_ACRS)
+		{
+			if (regs->acrs[S390_lowcore.exc_access_id] == 0)
+			{
+				kernel_address = 1;
+				goto no_context;
+			}
+			if (regs->acrs[S390_lowcore.exc_access_id] == 1)
+			{
+				/* user space address */
+				break;
+			}
+		}
+		die("page fault via unknown access register", regs, error_code);
+		break;
+
+	case 2: /* Secondary Segment Table Descriptor */
+	case 3: /* Home Segment Table Descriptor */
+		/* user space address */
+		break;
+	}
+
+
+	/*
+	 * When we get here, the fault happened in the current
+	 * task's user address space, so we search the VMAs
+	 */
+
+        down(&mm->mmap_sem);
+
+        vma = find_vma(mm, address);
+        if (!vma) {
+	        printk("no vma for address %lX\n",address);
+                goto bad_area;
+        }
+        if (vma->vm_start <= address) 
+                goto good_area;
+        if (!(vma->vm_flags & VM_GROWSDOWN))
+                goto bad_area;
+        if (expand_stack(vma, address))
+                goto bad_area;
+/*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+good_area:
+        write = 0;
+	si_code = SEGV_ACCERR;
+
+        switch (error_code & 0xFF) {
+                case 0x04:                                /* write, present*/
+                        write = 1;
+                        break;
+                case 0x10:                                   /* not present*/
+                case 0x11:                                   /* not present*/
+                case 0x3B:                                   /* not present*/
+                        if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
+                                goto bad_area;
+                        break;
+                default:
+                       printk("code should be 4, 10 or 11 (%lX) \n",error_code&0xFF);  
+                       goto bad_area;
+        }
+
+	/*
+	 * If for any reason at all we couldn't handle the fault,
+	 * make sure we exit gracefully rather than endlessly redo
+	 * the fault.
+	 */
+	switch (handle_mm_fault(mm, vma, address, write)) {
+	case 1:
+		tsk->min_flt++;
+		break;
+	case 2:
+		tsk->maj_flt++;
+		break;
+	case 0:
+		goto do_sigbus;
+	default:
+		goto out_of_memory;
+	}
+
+        up(&mm->mmap_sem);
+        return;
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+bad_area:
+        up(&mm->mmap_sem);
+
+        /* User mode accesses just cause a SIGSEGV */
+        if (psw_mask & PSW_PROBLEM_STATE) {
+		struct siginfo si;
+                tsk->thread.prot_addr = address;
+                tsk->thread.trap_no = error_code;
+#ifndef CONFIG_SYSCTL
+#ifdef CONFIG_PROCESS_DEBUG
+                printk("User process fault: interruption code 0x%lX\n",error_code);
+                printk("failing address: %lX\n",address);
+		show_regs(regs);
+#endif
+#else
+		if (sysctl_userprocess_debug) {
+			printk("User process fault: interruption code 0x%lX\n",
+			       error_code);
+			printk("failing address: %lX\n", address);
+			show_regs(regs);
+		}
+#endif
+		si.si_signo = SIGSEGV;
+		si.si_code = si_code;
+		si.si_addr = (void*) address;
+		force_sig_info(SIGSEGV, &si, tsk);
+                return;
+	}
+
+no_context:
+        /* Are we prepared to handle this kernel fault?  */
+        if ((fixup = search_exception_table(regs->psw.addr)) != 0) {
+                regs->psw.addr = fixup;
+                return;
+        }
+
+/*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+        if (kernel_address)
+                printk(KERN_ALERT "Unable to handle kernel pointer dereference"
+        	       " at virtual kernel address %016lx\n", address);
+        else
+                printk(KERN_ALERT "Unable to handle kernel paging request"
+		       " at virtual user address %016lx\n", address);
+
+/*
+ * need to define, which information is useful here
+ */
+
+        die("Oops", regs, error_code);
+        do_exit(SIGKILL);
+
+
+/*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+*/
+out_of_memory:
+	up(&mm->mmap_sem);
+	printk("VM: killing process %s\n", tsk->comm);
+	if (psw_mask & PSW_PROBLEM_STATE)
+		do_exit(SIGKILL);
+	goto no_context;
+
+do_sigbus:
+	up(&mm->mmap_sem);
+
+	/*
+	 * Send a sigbus, regardless of whether we were in kernel
+	 * or user mode.
+	 */
+        tsk->thread.prot_addr = address;
+        tsk->thread.trap_no = error_code;
+	force_sig(SIGBUS, tsk);
+
+	/* Kernel mode? Handle exceptions or die */
+	if (!(psw_mask & PSW_PROBLEM_STATE))
+		goto no_context;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/mm/init.c linux/arch/s390x/mm/init.c
--- v2.4.1/linux/arch/s390x/mm/init.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/mm/init.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,405 @@
+/*
+ *  arch/s390/mm/init.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com)
+ *
+ *  Derived from "arch/i386/mm/init.c"
+ *    Copyright (C) 1995  Linus Torvalds
+ */
+
+#include <linux/config.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ptrace.h>
+#include <linux/mman.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#ifdef CONFIG_BLK_DEV_INITRD
+#include <linux/blk.h>
+#endif
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/dma.h>
+#include <asm/lowcore.h>
+
+static unsigned long totalram_pages;
+
+/*
+ * empty_bad_page is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving an inode
+ * unused etc..
+ *
+ * empty_bad_pte_table is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * empty_bad_pmd_table is the accompanying segment table: it is initialized
+ * to point to empty_bad_pte_table page tables.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+
+pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE)));
+char  empty_bad_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+char  empty_zero_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE)));
+pmd_t empty_bad_pmd_table[PTRS_PER_PMD] __attribute__((__aligned__(PAGE_SIZE)));
+pte_t empty_bad_pte_table[PTRS_PER_PTE] __attribute__((__aligned__(PAGE_SIZE)));
+
+static int test_access(unsigned long loc)
+{
+	static const int ssm_mask = 0x07000000L;
+	int rc, i;
+
+        rc = 0;
+	for (i=0; i<2; i++) {
+		__asm__ __volatile__(
+                        "    slgr  %0,%0\n"
+			"    ssm   %1\n"
+			"    tprot 0(%2),0\n"
+			"0:  jne   1f\n"
+			"    lghi  %0,1\n"
+			"1:  ssm   %3\n"
+                        ".section __ex_table,\"a\"\n"
+                        "   .align 8\n"
+                        "   .quad  0b,1b\n"
+                        ".previous"
+			: "+&d" (rc) : "i" (0), "a" (loc), "m" (ssm_mask)
+			: "cc");
+		if (rc == 0)
+			break;
+		loc += 0x100000;
+	}
+	return rc;
+}
+
+static pmd_t *get_bad_pmd_table(void)
+{
+       pmd_t v;
+       int i;
+
+       pmd_set(&v, empty_bad_pte_table);
+
+       for (i = 0; i < PTRS_PER_PMD; i++)
+               empty_bad_pmd_table[i] = v;
+
+       return empty_bad_pmd_table;
+}
+
+static pte_t *get_bad_pte_table(void)
+{
+	pte_t v;
+	int i;
+
+	v = pte_mkdirty(mk_pte_phys(__pa(empty_bad_page), PAGE_SHARED));
+
+	for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
+		empty_bad_pte_table[i] = v;
+
+	return empty_bad_pte_table;
+}
+
+pmd_t *
+get_pmd_slow(pgd_t *pgd, unsigned long offset)
+{
+        pmd_t *pmd;
+        int i;
+
+        pmd = (pmd_t *) __get_free_pages(GFP_KERNEL,2);
+        if (pgd_none(*pgd)) {
+                if (pmd) {
+                        for (i = 0; i < PTRS_PER_PMD; i++)
+                                pmd_clear(pmd+i);
+                        pgd_set(pgd, pmd);
+                        return pmd + offset;
+                }
+                pmd = (pmd_t *) get_bad_pmd_table();
+                pgd_set(pgd, pmd);
+                return NULL;
+        }
+        free_pages((unsigned long)pmd,2);
+        if (pgd_bad(*pgd))
+		BUG();
+        return (pmd_t *) pgd_page(*pgd) + offset;
+}
+
+pte_t *get_pte_slow(pmd_t *pmd, unsigned long offset)
+{
+        pte_t *pte;
+        int i;
+
+        pte = (pte_t*) __get_free_page(GFP_KERNEL);
+        if (pmd_none(*pmd)) {
+                if (pte) {
+                        for (i=0;i<PTRS_PER_PTE;i++)
+                                pte_clear(pte+i);
+                        pmd_set(pmd,pte);
+                        return pte + offset;
+                }
+		pte = (pte_t*) get_bad_pte_table();
+                pmd_set(pmd,pte);
+                return NULL;
+        }
+        free_page(__pa(pte));
+        if (pmd_bad(*pmd))
+		BUG();
+        return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+int do_check_pgt_cache(int low, int high)
+{
+        int freed = 0;
+        if(pgtable_cache_size > high) {
+                do {
+                        if(pgd_quicklist)
+                                free_pgd_slow(get_pgd_fast()), freed += 4;
+                        if(pmd_quicklist)
+                                free_pmd_slow(get_pmd_fast()), freed += 4;
+                        if(pte_quicklist)
+                                free_pte_slow(get_pte_fast()), freed++;
+                } while(pgtable_cache_size > low);
+        }
+        return freed;
+}
+
+void show_mem(void)
+{
+        int i, total = 0,reserved = 0;
+        int shared = 0, cached = 0;
+
+        printk("Mem-info:\n");
+        show_free_areas();
+        printk("Free swap:       %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+        i = max_mapnr;
+        while (i-- > 0) {
+                total++;
+                if (PageReserved(mem_map+i))
+                        reserved++;
+                else if (PageSwapCache(mem_map+i))
+                        cached++;
+                else if (page_count(mem_map+i))
+                        shared += atomic_read(&mem_map[i].count) - 1;
+        }
+        printk("%d pages of RAM\n",total);
+        printk("%d reserved pages\n",reserved);
+        printk("%d pages shared\n",shared);
+        printk("%d pages swap cached\n",cached);
+        printk("%ld pages in page table cache\n",pgtable_cache_size);
+        show_buffers();
+}
+
+/* References to section boundaries */
+
+extern unsigned long _text;
+extern unsigned long _etext;
+extern unsigned long _edata;
+extern unsigned long __bss_start;
+extern unsigned long _end;
+
+extern unsigned long __init_begin;
+extern unsigned long __init_end;
+
+/*
+ * paging_init() sets up the page tables
+ */
+
+unsigned long last_valid_pfn;
+
+void __init paging_init(void)
+{
+        pgd_t * pg_dir;
+	pmd_t * pm_dir;
+        pte_t * pt_dir;
+        pte_t   pte;
+	int     i,j,k;
+        unsigned long address=0;
+        unsigned long pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) |
+          _REGION_TABLE;
+	unsigned long end_mem = (unsigned long) __va(max_low_pfn*PAGE_SIZE);
+	static const int ssm_mask = 0x04000000L;
+
+	unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+	unsigned long dma_pfn, high_pfn;
+
+	dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;
+	high_pfn = max_low_pfn;
+
+	if (dma_pfn > high_pfn)
+		zones_size[ZONE_DMA] = high_pfn;
+	else {
+		zones_size[ZONE_DMA] = dma_pfn;
+		zones_size[ZONE_NORMAL] = high_pfn - dma_pfn;
+	}
+
+	/* Initialize mem_map[].  */
+	free_area_init(zones_size);
+
+
+	/*
+	 * map whole physical memory to virtual memory (identity mapping) 
+	 */
+
+        pg_dir = swapper_pg_dir;
+	
+        for (i = 0 ; i < PTRS_PER_PGD ; i++,pg_dir++) {
+
+                if (address >= end_mem) {
+                  pgd_clear(pg_dir);
+                  continue;
+                }          
+        
+	        pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4);
+                pgd_set(pg_dir,pm_dir);
+
+                for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) {
+                  if (address >= end_mem) {
+                    pmd_clear(pm_dir);
+                    continue; 
+                  }          
+
+                        pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+                        pmd_set(pm_dir,pt_dir);
+	
+                        for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) {
+                          pte = mk_pte_phys(address, PAGE_KERNEL);
+                          if (address >= end_mem) {
+                            pte_clear(&pte); 
+                            continue;
+                          }
+                          set_pte(pt_dir, pte);
+                          address += PAGE_SIZE;
+                        }
+                }
+        }
+
+        /* enable virtual mapping in kernel mode */
+        __asm__ __volatile__("lctlg 1,1,%0\n\t"
+                             "lctlg 7,7,%0\n\t"
+                             "lctlg 13,13,%0\n\t"
+                             "ssm   %1"
+			     : :"m" (pgdir_k), "m" (ssm_mask));
+
+        local_flush_tlb();
+
+        return;
+}
+
+void __init mem_init(void)
+{
+	unsigned long codesize, reservedpages, datasize, initsize;
+        unsigned long tmp;
+
+        max_mapnr = num_physpages = max_low_pfn;
+        high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+
+        /* clear the zero-page */
+        memset(empty_zero_page, 0, PAGE_SIZE);
+
+	/* this will put all low memory onto the freelists */
+	totalram_pages += free_all_bootmem();
+
+        /* mark usable pages in the mem_map[] and count reserved pages */
+	reservedpages = 0;
+	tmp = 0;
+	do {
+		if (tmp && (tmp & 0x1ff) == 0 && 
+                    test_access(tmp * PAGE_SIZE) == 0) {
+                        printk("2M Segment 0x%016lX not available\n",
+                               tmp * PAGE_SIZE);
+			do {
+                                set_bit(PG_reserved, &mem_map[tmp].flags);
+				reservedpages++;
+				tmp++;
+			} while (tmp < max_low_pfn && (tmp & 0x1ff));
+		} else {
+			if (PageReserved(mem_map+tmp))
+				reservedpages++;
+			tmp++;
+		}
+	} while (tmp < max_low_pfn);
+
+	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
+        printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, %ldk data, %ldk init)\n",
+                (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+                max_mapnr << (PAGE_SHIFT-10),
+                codesize >> 10,
+                reservedpages << (PAGE_SHIFT-10),
+                datasize >>10,
+                initsize >> 10);
+}
+
+void free_initmem(void)
+{
+        unsigned long addr;
+
+        addr = (unsigned long)(&__init_begin);
+        for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		set_page_count(virt_to_page(addr), 1);
+		free_page(addr);
+		totalram_pages++;
+        }
+        printk ("Freeing unused kernel memory: %ldk freed\n",
+		(&__init_end - &__init_begin) >> 10);
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+        if (start < end)
+                printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+	for (; start < end; start += PAGE_SIZE) {
+                ClearPageReserved(virt_to_page(start));
+                set_page_count(virt_to_page(start), 1);
+		free_page(start);
+		totalram_pages++;
+	}
+}
+#endif
+
+void si_meminfo(struct sysinfo *val)
+{
+        val->totalram = totalram_pages;
+	val->sharedram = 0;
+	val->freeram = nr_free_pages();
+	val->bufferram = atomic_read(&buffermem_pages);
+	val->totalhigh = 0;
+	val->freehigh = 0;
+	val->mem_unit = PAGE_SIZE;
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/mm/ioremap.c linux/arch/s390x/mm/ioremap.c
--- v2.4.1/linux/arch/s390x/mm/ioremap.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/mm/ioremap.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,129 @@
+/*
+ *  arch/s390/mm/ioremap.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com)
+ *
+ *  Derived from "arch/i386/mm/extable.c"
+ *    (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ * This is needed for high PCI addresses that aren't mapped in the
+ * 640k-1MB IO memory area on PC's
+ */
+
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/pgalloc.h>
+
+static inline void remap_area_pte(pte_t * pte, unsigned long address, unsigned long size,
+        unsigned long phys_addr, unsigned long flags)
+{
+        unsigned long end;
+
+        address &= ~PMD_MASK;
+        end = address + size;
+        if (end > PMD_SIZE)
+                end = PMD_SIZE;
+	if (address >= end)
+		BUG();
+        do {
+                if (!pte_none(*pte)) {
+                        printk("remap_area_pte: page already exists\n");
+			BUG();
+		}
+                set_pte(pte, mk_pte_phys(phys_addr,
+                                         __pgprot(_PAGE_PRESENT | flags)));
+                address += PAGE_SIZE;
+                phys_addr += PAGE_SIZE;
+                pte++;
+        } while (address && (address < end));
+}
+
+static inline int remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size,
+        unsigned long phys_addr, unsigned long flags)
+{
+	unsigned long end;
+
+	address &= ~PGDIR_MASK;
+	end = address + size;
+	if (end > PGDIR_SIZE)
+		end = PGDIR_SIZE;
+	phys_addr -= address;
+	if (address >= end)
+		BUG();
+	do {
+		pte_t * pte = pte_alloc_kernel(pmd, address);
+		if (!pte)
+			return -ENOMEM;
+		remap_area_pte(pte, address, end - address, address + phys_addr, flags);
+		address = (address + PMD_SIZE) & PMD_MASK;
+		pmd++;
+	} while (address && (address < end));
+	return 0;
+}
+
+static int remap_area_pages(unsigned long address, unsigned long phys_addr,
+				 unsigned long size, unsigned long flags)
+{
+	pgd_t * dir;
+	unsigned long end = address + size;
+
+	phys_addr -= address;
+	dir = pgd_offset(&init_mm, address);
+	flush_cache_all();
+	if (address >= end)
+		BUG();
+	do {
+		pmd_t *pmd = pmd_alloc_kernel(dir, address);
+		if (!pmd)
+			return -ENOMEM;
+		if (remap_area_pmd(pmd, address, end - address,
+					 phys_addr + address, flags))
+			return -ENOMEM;
+		set_pgdir(address, *dir);
+		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+		dir++;
+	} while (address && (address < end));
+	flush_tlb_all();
+	return 0;
+}
+
+/*
+ * Generic mapping function (not visible outside):
+ */
+
+/*
+ * Remap an arbitrary physical address space into the kernel virtual
+ * address space. Needed when the kernel wants to access high addresses
+ * directly.
+ */
+void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+{
+	void * addr;
+	struct vm_struct * area;
+
+	if (phys_addr < virt_to_phys(high_memory))
+		return phys_to_virt(phys_addr);
+	if (phys_addr & ~PAGE_MASK)
+		return NULL;
+	size = PAGE_ALIGN(size);
+	if (!size || size > phys_addr + size)
+		return NULL;
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+	addr = area->addr;
+	if (remap_area_pages(VMALLOC_VMADDR(addr), phys_addr, size, flags)) {
+		vfree(addr);
+		return NULL;
+	}
+	return addr;
+}
+
+void iounmap(void *addr)
+{
+	if (addr > high_memory)
+		return vfree(addr);
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/dasdfmt/Makefile linux/arch/s390x/tools/dasdfmt/Makefile
--- v2.4.1/linux/arch/s390x/tools/dasdfmt/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/dasdfmt/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,9 @@
+all: dasdfmt
+
+dasdfmt: dasdfmt.c
+	$(CC) -o $@ $^
+	$(STRIP) $@
+
+clean:
+	rm -f dasdfmt
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/dasdfmt/dasdfmt.8 linux/arch/s390x/tools/dasdfmt/dasdfmt.8
--- v2.4.1/linux/arch/s390x/tools/dasdfmt/dasdfmt.8	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/dasdfmt/dasdfmt.8	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,68 @@
+.TH DASDFMT 8 "Tue Jan 25 2000"
+.UC 4
+.SH NAME
+dasdfmt \- formatting of DSAD (ECKD) disk drives.
+.SH SYNOPSIS
+\fBdasdfmt\fR [-tvyLV] [-b \fIblockSize\fR] [-l \fIdiskLabel\fR] \fIdiskSpec\fR
+.SH DESCRIPTION
+\fBdasdfmt\fR formats a DASD (ECKD) disk drive to prepare it
+for usage with Linux for S/390. \fBWARNING\fR: Incautious usage of
+\fBdasdfmt\fR can result in \fBLOSS OF DATA\fR.
+
+.SH OPTIONS
+.TP
+\fB-t\fR
+Disables any modification of the disk drive. \fBdasdfmt\fR just prints
+out, what it \fBwould\fR do.
+
+.TP
+\fB-v\fR
+Increases verbosity.
+
+.TP
+\fB-y\fR 
+Start formatting without further user-confirmation.
+
+.TP
+\fB-L\fR 
+Omit the writing of a disk label after formatting.
+
+.TP
+\fB-V\fR 
+Print version number and exit.
+
+.TP
+\fB-b\fR \fIblockSize\fR
+Specify blocksize to be used. \fIblocksize\fR must be a positive integer
+and always be a power of two. Due due some limitations in the driver,
+it is \fBstrongly\fR recommended to use a \fIblockSize\fR of \fI4096\fR.
+
+.TP
+\fB-l\fR \fIdiskLabel\fR
+Specify the label to be written to disk after formatting. If no label is
+specified, a sensible default is used. \fIdiskLabel\fR is interpreted as
+ASCII string and is automatically converted to EBCDIC.
+
+.TP
+\fIdiskSpec\fR
+This parameter specified the device to be formatted. It also can be
+given in two variants:
+.sp
+	\fB-f\fR \fB/dev/dasd\fR\fIX\fR
+.br
+or
+.br
+	\fB-n\fR \fIdevnum\fR
+.sp
+The first form uses the commonly used
+.SM UNIX
+device notation where \fIX\fR is a single lowercase letter.
+The second form uses simply the device number.
+
+.SH BUGS
+None so far ;-)
+
+.SH AUTHOR
+.nf
+This man-page was written by Fritz Elfert <felfert@to.com>
+.fi
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/dasdfmt/dasdfmt.c linux/arch/s390x/tools/dasdfmt/dasdfmt.c
--- v2.4.1/linux/arch/s390x/tools/dasdfmt/dasdfmt.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/dasdfmt/dasdfmt.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,830 @@
+/*
+ *
+ * dasdfmt.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Corporation
+ *    Author(s): Utz Bacher, <utz.bacher@de.ibm.com>
+ *
+ *  Device-in-use-checks by Fritz Elfert, <felfert@to.com>
+ *
+ * Still to do:
+ *   detect non-switch parameters ("dasdfmt -n 170 XY") and complain about them 
+ */
+
+/* #define _LINUX_BLKDEV_H */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <mntent.h>
+#define __KERNEL__ /* we want to use kdev_t and not have to define it */
+#include <linux/kdev_t.h>
+#undef __KERNEL__
+
+#include <linux/fs.h>
+#include <asm/dasd.h>
+#include <linux/hdreg.h>
+
+#define EXIT_MISUSE 1
+#define EXIT_BUSY 2
+#define TEMPFILENAME "/tmp/ddfXXXXXX"
+#define TEMPFILENAMECHARS 8  /* 8 characters are fixed in all temp filenames */
+#define SLASHDEV "/dev/"
+#define PROC_DASD_DEVICES "/proc/dasd/devices"
+/* _PATH_MOUNTED is /etc/mtab - /proc/mounts does not show root-fs correctly */
+#define PROC_MOUNTS _PATH_MOUNTED
+#define PROC_SWAPS "/proc/swaps"
+#define DASD_DRIVER_NAME "dasd"
+#define LABEL_LENGTH 10
+#define PROC_LINE_LENGTH 80
+#define ERR_LENGTH 80
+
+#define MAX_FILELEN NAME_MAX+PATH_MAX
+
+#define GIVEN_DEVNO 1
+#define GIVEN_MAJOR 2
+#define GIVEN_MINOR 4
+
+#define CHECK_START 1
+#define CHECK_END 2
+#define CHECK_BLKSIZE 4
+#define CHECK_ALL ~0
+
+#define ERRMSG(x...) {fflush(stdout);fprintf(stderr,x);}
+#define ERRMSG_EXIT(ec,x...) {fflush(stdout);fprintf(stderr,x);exit(ec);}
+
+#define CHECK_SPEC_MAX_ONCE(i,str) \
+	{if (i>1) \
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
+			"can only be specified once\n",prog_name);}
+
+#define PARSE_PARAM_INTO(x,param,base,str) \
+	{x=(int)strtol(param,&endptr,base); \
+	if (*endptr) \
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: " str " " \
+			"is in invalid format\n",prog_name);}
+
+char *prog_name;/*="dasdfmt";*/
+char tempfilename[]=TEMPFILENAME;
+
+__u8 _ascebc[256] =
+{
+ /*00 NUL   SOH   STX   ETX   EOT   ENQ   ACK   BEL */
+     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08  BS    HT    LF    VT    FF    CR    SO    SI */
+ /*              ->NL                               */
+     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10 DLE   DC1   DC2   DC3   DC4   NAK   SYN   ETB */
+     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
+ /*18 CAN    EM   SUB   ESC    FS    GS    RS    US */
+ /*                               ->IGS ->IRS ->IUS */
+     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
+ /*20  SP     !     "     #     $     %     &     ' */
+     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28   (     )     *     +     ,     -    .      / */
+     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30   0     1     2     3     4     5     6     7 */
+     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38   8     9     :     ;     <     =     >     ? */
+     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40   @     A     B     C     D     E     F     G */
+     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48   H     I     J     K     L     M     N     O */
+     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50   P     Q     R     S     T     U     V     W */
+     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58   X     Y     Z     [     \     ]     ^     _ */
+     0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
+ /*60   `     a     b     c     d     e     f     g */
+     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68   h     i     j     k     l     m     n     o */
+     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70   p     q     r     s     t     u     v     w */
+     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78   x     y     z     {     |     }     ~    DL */
+     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+ /*80*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*88*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*90*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*98*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*A8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*B8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*C8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*D8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E0        sz						*/
+     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*E8*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F0*/
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+ /*F8*/
+     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
+};
+
+void convert_label(char *str)
+{
+	int i;
+	for (i=0;i<LABEL_LENGTH;i++) str[i]=_ascebc[str[i]];
+}
+
+void
+exit_usage(int exitcode)
+{
+#ifdef RANGE_FORMATTING
+	printf("Usage: %s [-htvyLV] [-l <label>] [-b <blocksize>] [<range>] " \
+		"<diskspec>\n\n",prog_name);
+#else /* RANGE_FORMATTING */
+	printf("Usage: %s [-htvyLV] [-l <label>] [-b <blocksize>] " \
+		"<diskspec>\n\n",prog_name);
+#endif /* RANGE_FORMATTING */
+	printf("       -t means testmode\n");
+	printf("       -v means verbose mode\n");
+	printf("       -V means print version\n");
+	printf("       -L means don't write disk label\n");
+	printf("       <label> is a label which is converted to EBCDIC and " \
+		"written to disk\n");
+	printf("       <blocksize> has to be power of 2 and at least 512\n");
+#ifdef RANGE_FORMATTING
+	printf("       <range> is either\n");
+	printf("           -s <start_track> -e <end_track>\n");
+	printf("       or\n");
+	printf("           -r <start_track>-<end_track>\n");
+#endif /* RANGE_FORMATTING */
+	printf("       and <diskspec> is either\n");
+	printf("           -f /dev/dasdX\n");
+	printf("       or\n");
+	printf("           -n <s390-devnr>\n");
+	exit(exitcode);
+}
+
+void
+get_xno_from_xno(int *devno,kdev_t *major_no,kdev_t *minor_no,int mode)
+{
+	FILE *file;
+	int d,rc;
+	kdev_t mi,ma;
+	int mi_i,ma_i; /* for scanf :-( */
+	char line[PROC_LINE_LENGTH];
+
+	file=fopen(PROC_DASD_DEVICES,"r");
+	if (file==NULL)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to open " \
+			PROC_DASD_DEVICES ": %s (do you have the /proc " \
+			"filesystem enabled?)\n",prog_name,strerror(errno));
+
+	/*	fgets(line,sizeof(line),file); omit first line */ 
+	while (fgets(line,sizeof(line),file)!=NULL) {
+		rc=sscanf(line,"%X %*[(A-Z)] at (%d:%d)",&d,&ma_i,&mi_i);
+		ma=ma_i;
+		mi=mi_i;
+		if ( (rc==3) &&
+			!((d!=*devno)&&(mode&GIVEN_DEVNO)) &&
+			!((ma!=*major_no)&&(mode&GIVEN_MAJOR)) &&
+			!((mi!=*minor_no)&&(mode&GIVEN_MINOR)) ) {
+			*devno=d;
+			*major_no=ma;
+			*minor_no=mi;
+			/* yes, this is a quick exit, but the easiest way */
+			fclose(file);
+			return;
+		}
+	}
+	fclose(file);
+
+	ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to find device in the /proc " \
+		"filesystem (are you sure to have the right param line?)\n",
+		prog_name);
+}
+
+char *
+get_devname_from_devno(int devno,int verbosity)
+{
+	kdev_t major_no,minor_no;
+	kdev_t file_major,file_minor;
+	struct stat stat_buf;
+	int rc;
+	int found;
+	char *devname;
+	char tmpname[MAX_FILELEN];
+
+	DIR *dp;
+	struct dirent *direntp;
+
+	/**** get minor number ****/
+	get_xno_from_xno(&devno,&major_no,&minor_no,GIVEN_DEVNO);
+
+	/**** get device file ****/
+	if ((dp=opendir(SLASHDEV)) == NULL)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: unable to read " SLASHDEV \
+			"\n",prog_name);
+	found=0;
+	while ((direntp=readdir(dp)) != NULL) {
+		strcpy(tmpname,SLASHDEV);
+		strcat(tmpname,direntp->d_name);
+		rc=stat(tmpname,&stat_buf);
+		if (!rc) {
+			file_major=MAJOR(stat_buf.st_rdev);
+			file_minor=MINOR(stat_buf.st_rdev);
+			if ((file_major==major_no) && (file_minor==minor_no)) {
+				found=1;
+				break;
+			}
+		}
+	}
+	if (found) {
+		devname=malloc(strlen(direntp->d_name));
+		strcpy(devname,tmpname);
+	}
+	rc=closedir(dp);
+	if (rc<0) ERRMSG("%s: unable to close directory " SLASHDEV \
+		"; continuing\n",prog_name);
+	if (found)
+		return devname;
+
+	if (verbosity>=1)
+		printf("I didn't find device node in " SLASHDEV \
+			"; trying to create a temporary node\n");
+
+	/**** get temp file and create device node *****/
+	rc=mkstemp(tempfilename);
+	if (rc==-1)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to get temporary " \
+			"filename: %s\n",prog_name,strerror(errno));
+	close(rc);
+	rc=unlink(tempfilename);
+	
+	rc=mknod(tempfilename,S_IFBLK|0600,MKDEV(major_no,minor_no));
+	if (rc)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: failed to create temporary " \
+			"device node %s: %s\n",prog_name,tempfilename,
+			strerror(errno));
+	return tempfilename;
+}
+
+char *
+check_param(int mode,format_data_t data)
+{
+	char *s;
+
+	if (NULL==(s=malloc(ERR_LENGTH)))
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: not enough memory.\n",prog_name);
+
+	if ((mode&CHECK_START)&&(data.start_unit<0)) {
+		strcpy(s,"start track must be greater than zero");
+		goto exit;
+	}
+	if ((mode&CHECK_END)&&(data.stop_unit<-1)) {
+		strcpy(s,"end track must be -1 or greater than zero");
+		goto exit;
+	}
+	if ((mode&CHECK_END)&&(data.start_unit>data.stop_unit)&&
+		(data.stop_unit!=-1)) {
+		strcpy(s,"end track must be higher than start track");
+		goto exit;
+	}
+
+	if ((mode&CHECK_BLKSIZE)&&(data.blksize<1)) {
+		strcpy(s,"blocksize must be a positive integer");
+		goto exit;
+	}
+	if (mode&CHECK_BLKSIZE) while (data.blksize>0) {
+		if ((data.blksize%2)&&(data.blksize!=1)) {
+			strcpy(s,"blocksize must be a power of 2");
+			goto exit;
+		}
+		data.blksize/=2;
+	}
+
+	free(s);
+	return NULL;
+exit:
+	return s;
+}
+
+#define ASK_PRINTOUT printf("Please enter %s",output)
+#define ASK_GETBUFFER fgets(buffer,sizeof(buffer),stdin)
+#define ASK_SCANFORNUMBER(var) rc=sscanf(buffer,"%d%c",&var,&c)
+#define ASK_COMPLAIN_FORMAT if ((rc==2)&&(c=='\n')) rc=1; \
+	if (rc==-1) rc=1; /* this happens, if enter is pressed */ \
+	if (rc!=1) printf(" -- wrong input, try again.\n")
+#define ASK_CHECK_PARAM(mode) str=check_param(mode,params); \
+		if (str!=NULL) { printf(" -- %s\n",str); rc=0; free(str); }
+
+format_data_t
+ask_user_for_data(format_data_t params)
+{
+	char buffer[20]; /* should be enough for inputing track numbers */
+	char c;
+	int i,rc;
+	char *str;
+	char output[60],o2[12];
+
+#ifdef RANGE_FORMATTING
+	i=params.start_unit;
+	do {
+		params.start_unit=i;
+		sprintf(output,"the start track of the range to format " \
+			"[%d]: ",i);
+		ASK_PRINTOUT;
+		ASK_GETBUFFER;
+		ASK_SCANFORNUMBER(params.start_unit);
+		ASK_COMPLAIN_FORMAT;
+		ASK_CHECK_PARAM(CHECK_START);
+	} while (rc!=1);
+
+	i=params.stop_unit;
+	do {
+		params.stop_unit=i;
+		sprintf(output,"the end track of the range to format [");
+		if (i==-1) sprintf(o2,"END]: "); else
+			sprintf(o2,"%d]: ",i);
+		strcat(output,o2);
+		ASK_PRINTOUT;
+		ASK_GETBUFFER;
+		if ( (!strcasecmp(buffer,"end")) ||
+			(!strcasecmp(buffer,"end\n")) ) {
+			rc=1;
+			params.stop_unit=-1;
+		} else {
+			ASK_SCANFORNUMBER(params.stop_unit);
+			ASK_COMPLAIN_FORMAT;
+			ASK_CHECK_PARAM(CHECK_END);
+		}
+	} while (rc!=1);
+#endif /* RANGE_FORMATTING */
+
+	i=params.blksize;
+	do {
+		params.blksize=i;
+		sprintf(output,"the blocksize of the formatting [%d]: ",i);
+		ASK_PRINTOUT;
+		ASK_GETBUFFER;
+		ASK_SCANFORNUMBER(params.blksize);
+		ASK_COMPLAIN_FORMAT;
+		ASK_CHECK_PARAM(CHECK_BLKSIZE);
+	} while (rc!=1);
+
+	return params;
+}
+
+/* Check if the device we are going to format is mounted.
+ * If true, complain and exit.
+ */
+void
+check_mounted(int major, int minor)
+{
+	FILE *f;
+	int ishift = 0;
+	struct mntent *ment;
+	struct stat stbuf;
+	char line[128];
+
+	/* If whole disk to be formatted ... */
+	if ((minor % (1U << DASD_PARTN_BITS)) == 0) {
+		/* ... ignore partition-selector */
+		minor >>= DASD_PARTN_BITS;
+		ishift = DASD_PARTN_BITS;
+	}
+	/*
+	 * first, check filesystems
+	 */
+	if (!(f = fopen(PROC_MOUNTS, "r")))
+		ERRMSG_EXIT(EXIT_FAILURE, "%s: %s\n", PROC_MOUNTS,
+			strerror(errno));
+	while ((ment = getmntent(f))) {
+		if (stat(ment->mnt_fsname, &stbuf) == 0)
+			if ((major == MAJOR(stbuf.st_rdev)) &&
+				(minor == (MINOR(stbuf.st_rdev)>>ishift))) {
+				ERRMSG("%s: device is mounted on %s!!\n",
+					prog_name,ment->mnt_dir);
+				ERRMSG_EXIT(EXIT_BUSY, "If you really want to "
+					"format it, please unmount it.\n");
+			}
+	}
+	fclose(f);
+	/*
+	 * second, check active swap spaces
+	 */
+	if (!(f = fopen(PROC_SWAPS, "r")))
+		ERRMSG_EXIT(EXIT_FAILURE, PROC_SWAPS " %s", strerror(errno));
+	/*
+	 * skip header line
+	 */
+	fgets(line, sizeof(line), f);
+	while (fgets(line, sizeof(line), f)) {
+		char *p;
+		for (p = line; *p && (!isspace(*p)); p++) ;
+		*p = '\0';
+		if (stat(line, &stbuf) == 0)
+			if ((major == MAJOR(stbuf.st_rdev)) &&
+				(minor == (MINOR(stbuf.st_rdev)>>ishift))) {
+				ERRMSG("%s: the device is in use for "
+					"swapping!!\n",prog_name);
+				ERRMSG_EXIT(EXIT_BUSY, "If you really want to "
+					"format it, please use swapoff %s.\n",
+					line);
+			}
+	}
+	fclose(f);
+}
+
+void
+do_format_dasd(char *dev_name,format_data_t format_params,int testmode,
+	int verbosity,int writenolabel,int labelspec,
+	char *label,int withoutprompt,int devno)
+{
+	int fd,rc;
+	struct stat stat_buf;
+	kdev_t minor_no,major_no;
+	int new_blksize;
+	unsigned int label_position;
+	struct hd_geometry new_geometry;
+	char inp_buffer[5]; /* to contain yes */
+
+	fd=open(dev_name,O_RDWR);
+	if (fd==-1)
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: error opening device %s: " \
+			"%s\n",prog_name,dev_name,strerror(errno));
+
+	if (verbosity>=1) {
+	}
+
+	rc=stat(dev_name,&stat_buf);
+	if (rc) {
+		ERRMSG_EXIT(EXIT_FAILURE,"%s: error occured during stat: " \
+			"%s\n",prog_name,strerror(errno));
+	} else {
+		if (!S_ISBLK(stat_buf.st_mode))
+			ERRMSG_EXIT(EXIT_FAILURE,"%s: file is not a " \
+				"blockdevice.\n",prog_name);
+		major_no=MAJOR(stat_buf.st_rdev);
+		minor_no=MINOR(stat_buf.st_rdev);
+	}
+	check_mounted(major_no, minor_no);
+
+	if ((!writenolabel) && (!labelspec)) {
+		sprintf(label,"LNX1 x%04x",devno);
+	}
+	
+	if ( ((withoutprompt)&&(verbosity>=1)) ||
+		(!withoutprompt) ) {
+		get_xno_from_xno(&devno,&major_no,&minor_no,
+			GIVEN_MAJOR|GIVEN_MINOR);
+		printf("\nI am going to format the device %s in the " \
+			"following way:\n",dev_name);
+		printf("   Device number of device : 0x%x\n",devno);
+		printf("   Major number of device  : %u\n",major_no);
+		printf("   Minor number of device  : %u\n",minor_no);
+		printf("   Labelling device        : %s\n",(writenolabel)?
+			"no":"yes");
+		if (!writenolabel)
+			printf("   Disk label              : %s\n",label);
+#ifdef RANGE_FORMATTING
+		printf("   Start track             : %d\n" \
+			,format_params.start_unit);
+		printf("   End track               : ");
+		if (format_params.stop_unit==-1)
+			printf("last track of disk\n");
+		else
+			printf("%d\n",format_params.stop_unit);
+#endif /* RANGE_FORMATTING */
+		printf("   Blocksize               : %d\n" \
+			,format_params.blksize);
+		if (testmode) printf("Test mode active, omitting ioctl.\n");
+	}
+
+	while (!testmode) {
+		if (!withoutprompt) {
+			printf("\n--->> ATTENTION! <<---\n");
+			printf("All data in the specified range of that " \
+				"device will be lost.\nType \"yes\" to " \
+				"continue, no will leave the disk untouched: ");
+			fgets(inp_buffer,sizeof(inp_buffer),stdin);
+			if (strcasecmp(inp_buffer,"yes") &&
+				strcasecmp(inp_buffer,"yes\n")) {
+				printf("Omitting ioctl call (disk will " \
+					"NOT be formatted).\n");
+				break;
+			}
+		}
+
+		if ( !(  (withoutprompt)&&(verbosity<1) ))
+			printf("Formatting the device. This may take a " \
+				"while (get yourself a coffee).\n");
+		rc=ioctl(fd,BIODASDFORMAT,format_params);
+		if (rc)
+			ERRMSG_EXIT(EXIT_FAILURE,"%s: the dasd driver " \
+				"returned with the following error " \
+				"message:\n%s\n",prog_name,strerror(errno));
+		printf("Finished formatting the device.\n");
+
+		if (!writenolabel) {
+			if (verbosity>0)
+				printf("Retrieving disk geometry... ");
+
+			rc=ioctl(fd,HDIO_GETGEO,&new_geometry);
+			if (rc) {
+				ERRMSG("%s: the ioctl call to get geometry " \
+					"returned with the following error " \
+					"message:\n%s\n",prog_name,
+					strerror(errno));
+				goto reread;
+			}
+	
+
+			rc=ioctl(fd,BLKGETSIZE,&new_blksize);
+			if (rc) {
+				ERRMSG("%s: the ioctl call to get blocksize " \
+					"returned with the following error " \
+					"message:\n%s\n",prog_name,
+					strerror(errno));
+				goto reread;
+			}
+	
+			if (verbosity>0) printf("done\n");
+
+			label_position=new_geometry.start*new_blksize;
+	
+			if (verbosity>0) printf("Writing label... ");
+			convert_label(label);
+			rc=lseek(fd,label_position,SEEK_SET);
+			if (rc!=label_position) {
+				ERRMSG("%s: lseek on the device to %i " \
+					"failed with the following error " \
+					"message:\n%s\n",prog_name,
+					label_position,strerror(errno));
+				goto reread;
+			}
+			rc=write(fd,label,LABEL_LENGTH);
+			if (rc!=LABEL_LENGTH) {
+				ERRMSG("%s: writing the label only wrote %d " \
+					"bytes.\n",prog_name,rc);
+				goto reread;
+			}
+
+			sync();
+			sync();
+
+			if (verbosity>0) printf("done\n");
+		}
+ reread:
+		printf("Rereading the partition table... ");
+		rc=ioctl(fd,BLKRRPART,NULL);
+		if (rc) {
+			ERRMSG("%s: error during rereading the partition " \
+			       "table: %s.\n",prog_name,strerror(errno));
+		} else printf("done.\n");
+
+		break;
+	}
+
+	rc=close(fd);
+	if (rc)
+		ERRMSG("%s: error during close: " \
+			"%s; continuing.\n",prog_name,strerror(errno));
+}
+
+
+
+int main(int argc,char *argv[]) {
+	int verbosity;
+	int testmode;
+	int withoutprompt;
+	int writenolabel,labelspec;
+
+	char *dev_name;
+	int devno;
+	char *dev_filename,*devno_param_str,*range_param_str;
+	char *start_param_str,*end_param_str,*blksize_param_str;
+	char label[LABEL_LENGTH+1];
+	
+	format_data_t format_params;
+
+	int rc;
+	int oc;
+	char *endptr;
+
+	char c1,c2,cbuffer[6]; /* should be able to contain -end plus 1 char */
+	int i,i1,i2;
+	char *str;
+
+	int start_specified,end_specified,blksize_specified;
+	int devfile_specified,devno_specified,range_specified;
+
+	/******************* initialization ********************/
+	prog_name=argv[0];
+
+	endptr=NULL;
+
+	/* set default values */
+	format_params.start_unit=DASD_FORMAT_DEFAULT_START_UNIT;
+	format_params.stop_unit=DASD_FORMAT_DEFAULT_STOP_UNIT;
+	format_params.blksize=DASD_FORMAT_DEFAULT_BLOCKSIZE;
+	format_params.intensity=DASD_FORMAT_DEFAULT_INTENSITY;
+	testmode=0;
+	verbosity=0;
+	withoutprompt=0;
+	writenolabel=0;
+	labelspec=0;
+	for (i=0;i<LABEL_LENGTH;i++) label[i]=' ';
+	label[LABEL_LENGTH]=0;
+
+	start_specified=end_specified=blksize_specified=0;
+	devfile_specified=devno_specified=range_specified=0;
+
+	/*************** parse parameters **********************/
+
+	/* avoid error message generated by getopt */
+	opterr=0;
+
+#ifdef RANGE_FORMATTING
+	while ( (oc=getopt(argc,argv,"r:s:e:b:n:l:f:hLty?vV")) !=EOF) {
+#endif /* RANGE_FORMATTING */
+	while ( (oc=getopt(argc,argv,"b:n:l:f:hLty?vV")) !=EOF) {
+		switch (oc) {
+		case 'y':
+			withoutprompt=1;
+			break;
+
+		case 't':
+			testmode=1;
+			break;
+
+		case 'v':
+			verbosity++;
+			break;
+
+		case '?': /* fall-through */
+		case ':':
+			exit_usage(EXIT_MISUSE);
+
+		case 'h':
+			exit_usage(0);
+
+		case 'V':
+			printf("%s version 0.99\n",prog_name);
+			exit(0);
+
+		case 'l':
+			strncpy(label,optarg,LABEL_LENGTH);
+			if (strlen(optarg)<LABEL_LENGTH)
+				label[strlen(optarg)]=' ';
+			labelspec++;
+			break;
+
+		case 'L':
+			writenolabel++;
+			break;
+
+#ifdef RANGE_FORMATTING
+		case 's' :
+			start_param_str=optarg;
+			start_specified++;
+			break;
+			
+		case 'e' :
+			end_param_str=optarg;
+			end_specified++;
+			break;
+
+		case 'r' :
+			range_param_str=optarg;
+			range_specified++;
+			break;
+#endif /* RANGE_FORMATTING */
+
+		case 'b' :
+			blksize_param_str=optarg;
+			blksize_specified++;
+			break;
+			
+		case 'n' :
+			devno_param_str=optarg;
+			devno_specified++;
+			break;
+		
+		case 'f' :
+			dev_filename=optarg;
+			devfile_specified++;
+			break;
+		}
+	}
+
+	/******************** checking of parameters **************/
+
+	/* convert range into -s and -e */
+	CHECK_SPEC_MAX_ONCE(range_specified,"formatting range");
+
+	while (range_specified) {
+		start_specified++;
+		end_specified++;
+
+		/* scan for 1 or 2 integers, separated by a dash */
+		rc=sscanf(range_param_str,"%d%c%d%c",&i1,&c1,&i2,&c2);
+		if ((rc==3)&&(c1=='-')) {
+			format_params.start_unit=i1;
+			format_params.stop_unit=i2;
+			break;
+		}
+		if (rc==1) {
+			format_params.start_unit=i1;
+			break;
+		}
+
+		/* scan for integer and -END */
+		rc=sscanf(range_param_str,"%d%s",&i1,cbuffer);
+		if ((rc==2)&&(!strcasecmp(cbuffer,"-END"))) {
+			format_params.start_unit=i1;
+			format_params.stop_unit=-1;
+			break;
+		}
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: specified range " \
+			"is in invalid format\n",prog_name);
+	}
+
+	if ((!devfile_specified)&&(!devno_specified))
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \
+			"not specified\n",prog_name);
+
+	if ((devfile_specified+devno_specified)>1)
+		ERRMSG_EXIT(EXIT_MISUSE,"%s: device to format " \
+			"can only be specified once\n",prog_name);
+
+	if ((!start_specified)&&(!end_specified)&&(!range_specified)&&
+		(!blksize_specified)) {
+		format_params=ask_user_for_data(format_params);
+	}
+
+	CHECK_SPEC_MAX_ONCE(start_specified,"start track");
+	CHECK_SPEC_MAX_ONCE(end_specified,"end track");
+	CHECK_SPEC_MAX_ONCE(blksize_specified,"blocksize");
+	CHECK_SPEC_MAX_ONCE(labelspec,"label");
+	CHECK_SPEC_MAX_ONCE(writenolabel,"omit-label-writing flag");
+
+	if (devno_specified)
+		PARSE_PARAM_INTO(devno,devno_param_str,16,"device number");
+	if (start_specified&&!range_specified)
+		PARSE_PARAM_INTO(format_params.start_unit,start_param_str,10,
+			"start track");
+	if (end_specified&&!range_specified)
+		PARSE_PARAM_INTO(format_params.stop_unit,end_param_str,10,
+			"end track");
+	if (blksize_specified)
+		PARSE_PARAM_INTO(format_params.blksize,blksize_param_str,10,
+			"blocksize");
+
+	/***********get dev_name *********************/
+	dev_name=(devno_specified)?
+		get_devname_from_devno(devno,verbosity):
+		dev_filename;
+
+	/*** range checking *********/
+	str=check_param(CHECK_ALL,format_params);
+	if (str!=NULL) ERRMSG_EXIT(EXIT_MISUSE,"%s: %s\n",prog_name,str);
+
+	/******* issue the real command and reread part table *******/
+	do_format_dasd(dev_name,format_params,testmode,verbosity,
+		writenolabel,labelspec,label,withoutprompt,devno);
+
+	/*************** cleanup ********************************/
+	if (strncmp(dev_name,TEMPFILENAME,TEMPFILENAMECHARS)==0) {
+		rc=unlink(dev_name);
+		if ((rc)&&(verbosity>=1))
+			ERRMSG("%s: temporary device node %s could not be " \
+				"removed: %s\n",prog_name,dev_name,
+				strerror(errno));
+	} else {
+		if (devno_specified) {
+			/* so we have allocated space for the filename */
+			free(dev_name);
+		}
+	}
+
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/silo/Makefile linux/arch/s390x/tools/silo/Makefile
--- v2.4.1/linux/arch/s390x/tools/silo/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/silo/Makefile	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,15 @@
+all: silo
+
+silo.o: silo.c
+	$(CC) -c -o silo.o -O2 silo.c
+
+cfg.o: cfg.c
+	$(CC) -c -o cfg.o -O2 cfg.c
+
+silo: silo.o cfg.o
+	$(CC) -o $@ $^
+	$(STRIP) $@
+
+clean:
+	rm -f *.o silo
+
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/silo/cfg.c linux/arch/s390x/tools/silo/cfg.c
--- v2.4.1/linux/arch/s390x/tools/silo/cfg.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/silo/cfg.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,373 @@
+/* cfg.c  -  Configuration file parser */
+
+/* Copyright 1992-1997 Werner Almesberger. See file COPYING for details. */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <string.h>
+
+#include "cfg.h"
+
+#define MAX_TOKEN 200
+#define MAX_VAR_NAME MAX_TOKEN
+
+static FILE *file;
+static char flag_set;
+static char *last_token = NULL,*last_item = NULL,*last_value = NULL;
+static int line_num;
+static char *file_name = NULL;
+static int back = 0; /* can go back by one char */
+
+
+void pdie(char *msg)
+{
+    fflush(stdout);
+    perror(msg);
+    exit(1);
+}
+
+
+void die(char *fmt,...)
+{
+    va_list ap;
+
+    fflush(stdout);
+    va_start(ap,fmt);
+    vfprintf(stderr,fmt,ap);
+    va_end(ap);
+    fputc('\n',stderr);
+    exit(1);
+}
+
+char *pstrdup(const char *str)
+{
+    char *this;
+
+    if ((this = strdup(str)) == NULL) pdie("Out of memory");
+    return this;
+}
+
+int cfg_open(char *name)
+{
+    if (!strcmp(name,"-")) file = stdin;
+    else if (!(file = fopen(file_name = name,"r"))) pdie(name);
+    line_num = 1;
+    return fileno(file);
+}
+
+void cfg_error(char *msg,...)
+{
+    va_list ap;
+
+    fflush(stdout);
+    va_start(ap,msg);
+    vfprintf(stderr,msg,ap);
+    va_end(ap);
+    if (!file_name) fputc('\n',stderr);
+    else fprintf(stderr," near line %d in file %s\n",line_num,file_name);
+    exit(1);
+}
+
+
+static int next_raw(void)
+{
+    int ch;
+
+    if (!back) return getc(file);
+    ch = back;
+    back = 0;
+    return ch;
+}
+
+
+static int next(void)
+{
+    static char *var;
+    char buffer[MAX_VAR_NAME+1];
+    int ch,braced;
+    char *put;
+
+    if (back) {
+	ch = back;
+	back = 0;
+	return ch;
+    }
+    if (var && *var) return *var++;
+    ch = getc(file);
+    if (ch == '\\') {
+	ch = getc(file);
+	if (ch == '$') return ch;
+	ungetc(ch,file);
+	return '\\';
+    }
+    if (ch != '$') return ch;
+    ch = getc(file);
+    braced = ch == '{';
+    put = buffer;
+    if (!braced) *put++ = ch;
+    while (1) {
+	ch = getc(file);
+#if 0
+	if (!braced && ch < ' ') {
+	    ungetc(ch,file);
+	    break;
+	}
+#endif
+	if (ch == EOF) cfg_error("EOF in variable name");
+	if (ch < ' ') cfg_error("control character in variable name");
+	if (braced && ch == '}') break;
+	if (!braced && !isalpha(ch) && !isdigit(ch) && ch != '_') {
+	    ungetc(ch,file);
+	    break;
+	}
+	if (put-buffer == MAX_VAR_NAME) cfg_error("variable name too long");
+	*put++ = ch;
+    }
+    *put = 0;
+    if (!(var = getenv(buffer))) cfg_error("unknown variable \"%s\"",buffer);
+    return next();
+}
+
+
+static void again(int ch)
+{
+    if (back) die("internal error: again invoked twice");
+    back = ch;
+}
+
+
+static char *cfg_get_token(void)
+{
+    char buf[MAX_TOKEN+1];
+    char *here;
+    int ch,escaped;
+
+    if (last_token) {
+	here = last_token;
+	last_token = NULL;
+	return here;
+    }
+    while (1) {
+	while ((ch = next()), ch == ' ' || ch == '\t' || ch == '\n')
+	    if (ch == '\n') line_num++;
+	if (ch == EOF) return NULL;
+	if (ch != '#') break;
+	while ((ch = next_raw()), ch != '\n')
+	    if (ch == EOF) return NULL;
+	line_num++;
+    }
+    if (ch == '=') return pstrdup("=");
+    if (ch == '"') {
+	here = buf;
+	while (here-buf < MAX_TOKEN) {
+	    if ((ch = next()) == EOF) cfg_error("EOF in quoted string");
+	    if (ch == '"') {
+		*here = 0;
+		return pstrdup(buf);
+	    }
+	    if (ch == '\\') {
+		ch = next();
+		if (ch != '"' && ch != '\\' && ch != '\n')
+		    cfg_error("Bad use of \\ in quoted string");
+		if (ch == '\n') {
+		    while ((ch = next()), ch == ' ' || ch == '\t');
+		    if (!ch) continue;
+		    again(ch);
+		    ch = ' ';
+		}
+	    }
+	    if (ch == '\n' || ch == '\t')
+		cfg_error("\\n and \\t are not allowed in quoted strings");
+	    *here++ = ch;
+	}
+	cfg_error("Quoted string is too long");
+	return 0; /* not reached */
+    }
+    here = buf;
+    escaped = 0;
+    while (here-buf < MAX_TOKEN) {
+	if (escaped) {
+	    if (ch == EOF) cfg_error("\\ precedes EOF");
+	    if (ch == '\n') line_num++;
+	    else *here++ = ch == '\t' ? ' ' : ch;
+	    escaped = 0;
+	}
+	else {
+	    if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '#' ||
+	      ch == '=' || ch == EOF) {
+		again(ch);
+		*here = 0;
+		return pstrdup(buf);
+	    }
+	    if (!(escaped = (ch == '\\'))) *here++ = ch;
+	}
+	ch = next();
+    }
+    cfg_error("Token is too long");
+    return 0; /* not reached */
+}
+
+
+static void cfg_return_token(char *token)
+{
+    last_token = token;
+}
+
+
+static int cfg_next(char **item,char **value)
+{
+    char *this;
+
+    if (last_item) {
+	*item = last_item;
+	*value = last_value;
+	last_item = NULL;
+	return 1;
+    }
+    *value = NULL;
+    if (!(*item = cfg_get_token())) return 0;
+    if (!strcmp(*item,"=")) cfg_error("Syntax error");
+    if (!(this = cfg_get_token())) return 1;
+    if (strcmp(this,"=")) {
+	cfg_return_token(this);
+	return 1;
+    }
+    if (!(*value = cfg_get_token())) cfg_error("Value expected at EOF");
+    if (!strcmp(*value,"=")) cfg_error("Syntax error after %s",*item);
+    return 1;
+}
+
+
+static void cfg_return(char *item,char *value)
+{
+    last_item = item;
+    last_value = value;
+}
+
+
+void cfg_init(CONFIG *table)
+{
+    while (table->type != cft_end) {
+	switch (table->type) {
+	    case cft_strg:
+		if (table->data) free(table->data);
+	    case cft_flag:
+		table->data = NULL;
+		break;
+	    case cft_link:
+		table = ((CONFIG *) table->action)-1;
+		break;
+	    default:
+		die("Unknown syntax code %d",table->type);
+	}
+	table++;
+    }
+}
+
+
+static int cfg_do_set(CONFIG *table,char *item,char *value,int copy,
+    void *context)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (value && walk->type != cft_strg)
+		cfg_error("'%s' doesn't have a value",walk->name);
+	    if (!value && walk->type == cft_strg)
+		cfg_error("Value expected for '%s'",walk->name);
+	    if (walk->data) {
+		if (walk->context == context)
+		    cfg_error("Duplicate entry '%s'",walk->name);
+		else {
+		    fprintf(stderr,"Ignoring entry '%s'\n",walk->name);
+		    if (!copy) free(value);
+		    return 1;
+		}
+	    }
+	    if (walk->type == cft_flag) walk->data = &flag_set;
+	    else if (walk->type == cft_strg) {
+		    if (copy) walk->data = pstrdup(value);
+		    else walk->data = value;
+	    }
+	    walk->context = context;
+	    if (walk->action) ((void (*)(void)) walk->action)();
+	    break;
+	}
+	if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    if (walk->type != cft_end) return 1;
+    cfg_return(item,value);
+    return 0;
+}
+
+
+void cfg_set(CONFIG *table,char *item,char *value,void *context)
+{
+    if (!cfg_do_set(table,item,value,1,context))
+	cfg_error("cfg_set: Can't set %s",item);
+}
+
+
+void cfg_unset(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++)
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (!walk->data) die("internal error (cfg_unset %s, unset)",item);
+	    if (walk->type == cft_strg) free(walk->data);
+	    walk->data = NULL;
+	    return;
+	}
+    die("internal error (cfg_unset %s, unknown",item);
+}
+
+
+int cfg_parse(CONFIG *table)
+{
+    char *item,*value;
+
+    while (1) {
+	if (!cfg_next(&item,&value)) return 0;
+	if (!cfg_do_set(table,item,value,0,table)) return 1;
+	free(item);
+    }
+}
+
+
+int cfg_get_flag(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (walk->type != cft_flag)
+		die("cfg_get_flag: operating on non-flag %s",item);
+	    return !!walk->data;
+	}
+	if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    die("cfg_get_flag: unknown item %s",item);
+    return 0; /* not reached */
+}
+
+
+char *cfg_get_strg(CONFIG *table,char *item)
+{
+    CONFIG *walk;
+
+    for (walk = table; walk->type != cft_end; walk++) {
+	if (walk->name && !strcasecmp(walk->name,item)) {
+	    if (walk->type != cft_strg)
+		die("cfg_get_strg: operating on non-string %s",item);
+	    return walk->data;
+	}
+	if (walk->type == cft_link) walk = ((CONFIG *) walk->action)-1;
+    }
+    die("cfg_get_strg: unknown item %s",item);
+    return 0; /* not reached */
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/silo/cfg.h linux/arch/s390x/tools/silo/cfg.h
--- v2.4.1/linux/arch/s390x/tools/silo/cfg.h	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/silo/cfg.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,58 @@
+/* cfg.h  -  Configuration file parser */
+
+/* Copyright 1992-1996 Werner Almesberger. See file COPYING for details. */
+
+
+#ifndef CFG_H
+#define CFG_H
+
+typedef enum { cft_strg, cft_flag, cft_link, cft_end } CFG_TYPE;
+
+typedef struct {
+    CFG_TYPE type;
+    char *name;
+    void *action;
+    void *data;
+    void *context;
+} CONFIG;
+
+extern int cfg_open(char *name);
+
+/* Opens the configuration file. Returns the file descriptor of the open
+   file. */
+
+extern void cfg_error(char *msg,...);
+
+/* Signals an error while parsing the configuration file and terminates the
+   program. */
+
+extern void cfg_init(CONFIG *table);
+
+/* Initializes the specified table. */
+
+extern void cfg_set(CONFIG *table,char *item,char *value,void *context);
+
+/* Sets the specified variable in table. If the variable has already been set
+   since the last call to cfg_init, a warning message is issued if the context
+   keys don't match or a fatal error is reported if they do. */
+
+extern void cfg_unset(CONFIG *table,char *item);
+
+/* Unsets the specified variable in table. It is a fatal error if the variable
+   was not set. */
+
+extern int cfg_parse(CONFIG *table);
+
+/* Parses the configuration file for variables contained in table. A non-zero
+   value is returned if a variable not found in table has been met. Zero is
+   returned if EOF has been reached. */
+
+extern int cfg_get_flag(CONFIG *table,char *item);
+
+/* Returns one if the specified variable is set, zero if it isn't. */
+
+extern char *cfg_get_strg(CONFIG *table,char *item);
+
+/* Returns the value of the specified variable if it is set, NULL otherwise. */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/silo/silo.c linux/arch/s390x/tools/silo/silo.c
--- v2.4.1/linux/arch/s390x/tools/silo/silo.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/silo/silo.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,573 @@
+/*
+ *  arch/s390/boot/silo.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ *    Report bugs to: <linux390@de.ibm.com>
+ *
+ *    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *               Fritz Elfert <felfert@to.com> contributed support for
+ *                	/etc/silo.conf based on Intel's lilo
+ */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <dirent.h>
+#include <linux/fs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <asm/ioctl.h>
+
+#include "cfg.h"
+
+CONFIG cf_options[] = {
+  { cft_strg, "append",		NULL,		NULL,NULL },
+  { cft_strg, "image",		NULL,		NULL,NULL },
+  { cft_strg, "ipldevice",	NULL,		NULL,NULL },
+  { cft_strg, "bootsect",	NULL,		NULL,NULL },
+  { cft_strg, "map",		NULL,		NULL,NULL },
+  { cft_strg, "parmfile",	NULL,		NULL,NULL },
+  { cft_strg, "ramdisk",	NULL,		NULL,NULL },
+  { cft_strg, "root",		NULL,		NULL,NULL },
+  { cft_flag, "readonly",	NULL,		NULL,NULL },
+  { cft_strg, "verbose",	NULL,		NULL,NULL },
+  { cft_strg, "testlevel",	NULL,		NULL,NULL },
+  { cft_end,  NULL,		NULL,		NULL,NULL }
+};
+  
+/* from dasd.h */
+#define DASD_PARTN_BITS 2
+#define BIODASDRWTB _IOWR('D',0,int)
+/* end */
+
+#define SILO_CFG "/etc/silo.conf"
+#define SILO_IMAGE "./image"
+#define SILO_BOOTMAP "./boot.map"
+#define SILO_PARMFILE "./parmfile"
+#define SILO_BOOTSECT "/boot/ipleckd.boot"
+
+#define PRINT_LEVEL(x,y...) if ( silo_options.verbosity >= x ) printf(y)
+#define ERROR_LEVEL(x,y...) if ( silo_options.verbosity >= x ) fprintf(stderr,y)
+#define TOGGLE(x) ((x)=((x)?(0):(1)))
+#define GETARG(x) {int len=strlen(optarg);x=malloc(len);strncpy(x,optarg,len);PRINT_LEVEL(1,"%s set to %s\n",#x,optarg);}
+
+#define ITRY(x) if ( (x) == -1 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
+#define NTRY(x) if ( (x) == 0 ) { ERROR_LEVEL(0,"%s (line:%d) '%s' returned %d='%s'\n", __FILE__,__LINE__,#x,errno,strerror(errno)); usage(); exit(1); }
+
+#define MAX_CLUSTERS 256
+#define PARTN_MASK ((1 << DASD_PARTN_BITS) - 1)
+
+#define SILO_VERSION "1.1"
+
+struct silo_options
+  {
+    short int verbosity;
+    short int testlevel;
+    char *image;
+    char *ipldevice;
+    char *parmfile;
+    char *ramdisk;
+    char *bootsect;
+    char *conffile;
+    char *bootmap;
+  }
+silo_options =
+{
+  1,				/* verbosity */
+  2,				/* testlevel */
+    SILO_IMAGE,			/* image */
+    NULL,			/* ipldevice */
+    SILO_PARMFILE,		/* parmfile */
+    NULL,			/* initrd */
+    SILO_BOOTSECT,		/* bootsector */
+    SILO_CFG,                   /* silo.conf file */
+    SILO_BOOTMAP,               /* boot.map */
+};
+
+struct blockdesc
+  {
+    unsigned long off;
+    unsigned short ct;
+    unsigned long addr;
+  };
+
+struct blocklist
+  {
+    struct blockdesc blk[MAX_CLUSTERS];
+    unsigned short ix;
+  };
+
+void
+usage (void)
+{
+  printf ("Usage:\n");
+  printf ("silo -d ipldevice [additional options]\n");
+  printf ("-d /dev/node : set ipldevice to /dev/node\n");
+  printf ("-f image : set image to image\n");
+  printf ("-F conffile : specify configuration file (/etc/silo.conf)\n");
+  printf ("-p parmfile : set parameter file to parmfile\n");
+  printf ("-b bootsect : set bootsector to bootsect\n");
+  printf ("Additional options\n");
+  printf ("-B bootmap:\n");
+  printf ("-v: increase verbosity level\n");
+  printf ("-v#: set verbosity level to #\n");
+  printf ("-t: decrease testing level\n");
+  printf ("-h: print this message\n");
+  printf ("-?: print this message\n");
+  printf ("-V: print version\n");
+}
+
+int
+read_cfg(struct silo_options *o)
+{
+	char *tmp;
+	if (access(o->conffile, R_OK) && (errno == ENOENT))
+		return 0;
+	/* If errno != ENOENT, let cfg_open report an error */
+	cfg_open(o->conffile);
+	cfg_parse(cf_options);
+	tmp = cfg_get_strg(cf_options, "ipldevice");
+	if ( ! o->ipldevice  && tmp ) 
+		o->ipldevice = tmp;
+	tmp = cfg_get_strg(cf_options, "image");
+	if ( ! strncmp(o-> image,SILO_IMAGE,strlen(SILO_IMAGE)) && tmp ) 
+		o->image = tmp;
+	tmp = cfg_get_strg(cf_options, "parmfile");
+	if ( !strncmp(o->parmfile,SILO_PARMFILE,strlen(SILO_PARMFILE)) && tmp) 
+		o->parmfile = tmp;
+	if ( ! o -> ramdisk ) 
+		o->ramdisk = cfg_get_strg(cf_options, "ramdisk");
+	tmp = cfg_get_strg(cf_options, "bootsect");
+	if ( !strncmp(o -> bootsect,SILO_BOOTSECT,strlen(SILO_BOOTSECT))&&tmp)
+		o->bootsect = tmp;
+	tmp = cfg_get_strg(cf_options, "map") ;
+	if ( !strncmp(o -> bootmap,SILO_BOOTMAP,strlen(SILO_BOOTMAP)) && tmp) 
+		o->bootmap = tmp; 
+	tmp = cfg_get_strg(cf_options, "verbose");
+	if ( tmp ) {
+		unsigned short v;
+		sscanf (tmp, "%hu", &v);
+		o->verbosity = v;
+	}
+	tmp = cfg_get_strg(cf_options, "testlevel");
+	if ( tmp ) {
+		unsigned short t;
+		sscanf (tmp, "%hu", &t);
+		o->testlevel += t;
+	}
+	return 1;
+}
+
+char *
+gen_tmpparm( char *pfile )
+{
+	char *append = cfg_get_strg(cf_options, "append");
+	char *root = cfg_get_strg(cf_options, "root");
+	int ro = cfg_get_flag(cf_options, "readonly");
+	FILE *f,*of;
+	char *fn;
+	char c;
+	char *tmpdir=NULL,*save=NULL;
+
+	if (!append && !root && !ro)
+		return pfile;
+	of = fopen(pfile, "r");
+	if ( of ) {
+		NTRY( fn = tempnam(NULL,"parm."));
+	} else {
+		fn = pfile;
+	}
+	NTRY( f = fopen(fn, "a+"));
+	if ( of ) {
+		while ( ! feof (of) ) {
+		  c=fgetc(of);
+	  	fputc(c,f);
+		}
+	}
+	if (root)
+		fprintf(f, " root=%s", root);
+	if (ro)
+		fprintf(f, " ro");
+	if (append)
+		fprintf(f, " %s", append);
+	fprintf(f, "\n");
+	fclose(f);
+	fclose(of);
+	printf ("tempfile is %s\n",fn);
+	return strdup(fn);
+}
+
+int
+parse_options (struct silo_options *o, int argc, char *argv[])
+{
+  int rc = 0;
+  int oc;
+
+  while ((oc = getopt (argc, argv, "Vf:F:d:p:r:b:B:h?v::t::")) != -1)
+    {
+      switch (oc)
+	{
+	case 'V':
+	  printf("silo version: %s\n",SILO_VERSION);
+	  exit(0);
+	case 'v':
+	  {
+	    unsigned short v;
+	    if (optarg && sscanf (optarg, "%hu", &v))
+	      o->verbosity = v;
+	    else
+	      o->verbosity++;
+	    PRINT_LEVEL (1, "Verbosity value is now %hu\n", o->verbosity);
+	    break;
+	  }
+	case 't':
+	  {
+	    unsigned short t;
+	    if (optarg && sscanf (optarg, "%hu", &t))
+	      o->testlevel -= t;
+	    else
+	      o->testlevel--;
+            PRINT_LEVEL (1, "Testonly flag is now %d\n", o->testlevel);
+	    break;
+	  }
+	case 'h':
+	case '?':
+	  usage ();
+	  exit(0);
+	case 'd':
+	  GETARG (o->ipldevice);
+	  break;
+	case 'f':
+	  GETARG (o->image);
+	  break;
+        case 'F':                         
+ 	   GETARG (o->conffile);              
+ 	   break;                          
+	case 'p':
+	  GETARG (o->parmfile);
+	  break;
+	case 'r':
+	  GETARG (o->ramdisk);
+	  break;
+	case 'b':
+	  GETARG (o->bootsect);
+	  break;
+	case 'B':
+	  GETARG (o->bootmap);
+	default:
+	  rc = EINVAL;
+	  break;
+	}
+    }
+  read_cfg(o);
+  return rc;
+}
+
+int
+verify_device (char *name)
+{
+  int rc = 0;
+  struct stat dst;
+  struct stat st;
+  ITRY (stat (name, &dst));
+  if (S_ISBLK (dst.st_mode))
+    {
+      if (!(MINOR (dst.st_rdev) & PARTN_MASK))
+	{
+	  rc = dst.st_rdev;
+	}
+      else
+	/* invalid MINOR & PARTN_MASK */
+	{
+	  ERROR_LEVEL (1, "Cannot boot from partition %d %d %d",
+		       (int) PARTN_MASK, (int) MINOR (dst.st_rdev), (int) (PARTN_MASK & MINOR (dst.st_rdev)));
+	  rc = -1;
+	  errno = EINVAL;
+	}
+    }
+  else
+    /* error S_ISBLK */
+    {
+      ERROR_LEVEL (1, "%s is no block device\n", name);
+      rc = -1;
+      errno = EINVAL;
+    }
+  return rc;
+}
+
+int
+verify_file (char *name, int dev)
+{
+  int rc = 0;
+  struct stat dst;
+  struct stat st;
+  int bs = 1024;
+  int l;
+
+  ITRY(stat ( name, &dst ));
+  if (S_ISREG (dst.st_mode))
+    {
+      if ((unsigned) MAJOR (dev) == (unsigned) MAJOR (dst.st_dev) && (unsigned) MINOR (dev) == (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK))
+	{
+	  /* whatever to do if all is ok... */
+	}
+      else
+	/* devicenumber doesn't match */
+	{
+	  ERROR_LEVEL (1, "%s is not on device (%d/%d) but on (%d/%d)\n", name, (unsigned) MAJOR (dev), (unsigned) MINOR (dev), (unsigned) MAJOR (dst.st_dev), (unsigned) (MINOR (dst.st_dev) & ~PARTN_MASK));
+	  rc = -1;
+	  errno = EINVAL;
+	}
+    }
+  else
+    /* error S_ISREG */
+    {
+      ERROR_LEVEL (1, "%s is neither regular file nor linkto one\n", name);
+      rc = -1;
+      errno = EINVAL;
+    }
+  return rc;
+}
+
+int
+verify_options (struct silo_options *o)
+{
+  int rc = 0;
+  int dev = 0;
+  int crc = 0;
+  if (!o->ipldevice || !o->image || !o->bootsect)
+    {
+     if (!o->ipldevice)
+       fprintf(stderr,"ipldevice\n");
+     if (!o->image)
+       fprintf(stderr,"image\n");
+     if (!o->bootsect)
+       fprintf(stderr,"bootsect\n");
+
+      usage ();
+      exit (1);
+    }
+  PRINT_LEVEL (1, "Testlevel is set to %d\n",o->testlevel);
+
+  PRINT_LEVEL (1, "IPL device is: '%s'", o->ipldevice);
+  ITRY (dev = verify_device (o->ipldevice));
+  PRINT_LEVEL (2, "...ok...(%d/%d)", (unsigned short) MAJOR (dev), (unsigned short) MINOR (dev));
+  PRINT_LEVEL (1, "\n");
+
+  PRINT_LEVEL (0, "bootsector is: '%s'", o->bootsect);
+  ITRY (verify_file (o->bootsect, dev));
+  PRINT_LEVEL (1, "...ok...");
+  PRINT_LEVEL (0, "\n");
+
+  if ( o -> testlevel > 0  && 
+       ! strncmp( o->bootmap, SILO_BOOTMAP,strlen(SILO_BOOTMAP) )) {
+     NTRY( o -> bootmap = tempnam(NULL,"boot."));
+  }
+  PRINT_LEVEL (0, "bootmap is set to: '%s'", o->bootmap);
+  if ( access ( o->bootmap, O_RDWR ) == -1 ) {
+    if ( errno == ENOENT ) {
+      ITRY (creat ( o-> bootmap, O_RDWR ));
+    } else {
+      PRINT_LEVEL(1,"Cannot acces bootmap file '%s': %s\n",o->bootmap,
+		  strerror(errno));
+    }
+  }
+  ITRY (verify_file (o->bootmap, dev));
+  PRINT_LEVEL (1, "...ok...");
+  PRINT_LEVEL (0, "\n");
+
+  PRINT_LEVEL (0, "Kernel image is: '%s'", o->image);
+  ITRY (verify_file (o->image, dev));
+  PRINT_LEVEL (1, "...ok...");
+  PRINT_LEVEL (0, "\n");
+
+  PRINT_LEVEL (0, "original parameterfile is: '%s'", o->parmfile);
+  ITRY (verify_file (o->parmfile, dev));
+  PRINT_LEVEL (1, "...ok...");
+  o->parmfile = gen_tmpparm(o->parmfile);
+  PRINT_LEVEL (0, "final parameterfile is: '%s'", o->parmfile);
+  ITRY (verify_file (o->parmfile, dev));
+  PRINT_LEVEL (1, "...ok...");
+  PRINT_LEVEL (0, "\n");
+
+  if (o->ramdisk)
+    {
+      PRINT_LEVEL (0, "initialramdisk is: '%s'", o->ramdisk);
+      ITRY (verify_file (o->ramdisk, dev));
+      PRINT_LEVEL (1, "...ok...");
+      PRINT_LEVEL (0, "\n");
+    }
+
+  return crc;
+}
+
+
+int
+add_file_to_blocklist (char *name, struct blocklist *lst, long addr)
+{
+  int fd;
+  int devfd;
+  struct stat fst;
+  int i;
+  int blk;
+  int bs;
+  int blocks;
+
+  int rc = 0;
+
+  ITRY (fd = open (name, O_RDONLY));
+  ITRY (fstat (fd, &fst));
+  ITRY (mknod ("/tmp/silodev", S_IFBLK | S_IRUSR | S_IWUSR, fst.st_dev));
+  ITRY (devfd = open ("/tmp/silodev", O_RDONLY));
+  ITRY (ioctl (fd, FIGETBSZ, &bs));
+  blocks = (fst.st_size + bs - 1) / bs;
+  for (i = 0; i < blocks; i++)
+    {
+      blk = i;
+      ITRY (ioctl (fd, FIBMAP, &blk));
+      if (blk)
+	{
+	  int oldblk = blk;
+	  ITRY (ioctl (devfd, BIODASDRWTB, &blk));
+	  if (blk <= 0)
+	    {
+	      ERROR_LEVEL (0, "BIODASDRWTB on blk %d returned %d\n", oldblk, blk);
+	      break;
+	    }
+	}
+      else
+	{
+	  PRINT_LEVEL (1, "Filled hole on blk %d\n", i);
+	}
+      if (lst->ix == 0 || i == 0  || 
+	  lst->blk[lst->ix - 1].ct >= 128 ||
+	  (lst->blk[lst->ix - 1].off + lst->blk[lst->ix - 1].ct != blk &&
+	   !(lst->blk[lst->ix - 1].off == 0 && blk == 0)))
+	{
+	  if (lst->ix >= MAX_CLUSTERS)
+	    {
+	      rc = 1;
+	      errno = ENOMEM;
+	      break;
+	    }
+	  lst->blk[lst->ix].off = blk;
+	  lst->blk[lst->ix].ct = 1;
+	  lst->blk[lst->ix].addr = addr + i * bs;
+	  lst->ix++;
+	}
+      else
+	{
+	  lst->blk[lst->ix - 1].ct++;
+	}
+    }
+  ITRY(unlink("/tmp/silodev"));
+  return rc;
+}
+
+int
+write_bootsect (struct silo_options *o, struct blocklist *blklst)
+{
+  int i;
+  int s_fd, d_fd, b_fd, bd_fd;
+  struct stat s_st, d_st, b_st;
+  int rc=0;
+  int bs, boots;
+  char *tmpdev;
+  char buffer[4096]={0,};
+  ITRY (d_fd = open (o->ipldevice, O_RDWR | O_SYNC));
+  ITRY (fstat (d_fd, &d_st));
+  ITRY (s_fd = open (o->bootmap, O_RDWR | O_TRUNC | O_CREAT | O_SYNC));
+  ITRY (verify_file (o->bootsect, d_st.st_rdev));
+  for (i = 0; i < blklst->ix; i++)
+    {
+      int offset = blklst->blk[i].off;
+      int addrct = blklst->blk[i].addr | (blklst->blk[i].ct & 0xff);
+      PRINT_LEVEL (1, "ix %i: offset: %06x count: %02x address: 0x%08x\n", i, offset, blklst->blk[i].ct & 0xff, blklst->blk[i].addr);
+	if ( o->testlevel <= 1 ) {
+	      NTRY (write (s_fd, &offset, sizeof (int)));
+	      NTRY (write (s_fd, &addrct, sizeof (int)));
+	}
+    }
+  ITRY (ioctl (s_fd,FIGETBSZ, &bs));
+  ITRY (stat (o->bootmap, &s_st));
+  if (s_st.st_size > bs )
+    {
+      ERROR_LEVEL (0,"%s is larger than one block\n", o->bootmap);
+      rc = -1;
+      errno = EINVAL;
+    }
+  boots=0;
+  NTRY ( tmpdev = tmpnam(NULL) );
+  ITRY (mknod (tmpdev, S_IFBLK | S_IRUSR | S_IWUSR, s_st.st_dev));
+  ITRY (bd_fd = open (tmpdev, O_RDONLY));
+  ITRY (ioctl(s_fd,FIBMAP,&boots));
+  ITRY (ioctl (bd_fd, BIODASDRWTB, &boots));
+  PRINT_LEVEL (1, "Bootmap is in block no: 0x%08x\n", boots);
+  close (bd_fd);
+  close(s_fd);
+  ITRY (unlink(tmpdev));
+  /* Now patch the bootsector */
+  ITRY (b_fd = open (o->bootsect, O_RDONLY));
+  NTRY (read (b_fd, buffer, 4096));
+  memset (buffer + 0xe0, 0, 8);
+  *(int *) (buffer + 0xe0) = boots;
+  if ( o -> testlevel <= 0 ) {
+    NTRY (write (d_fd, buffer, 4096));
+    NTRY (write (d_fd, buffer, 4096));
+  }
+  close (b_fd);
+  close (d_fd);
+  return rc;
+}
+
+int
+do_silo (struct silo_options *o)
+{
+  int rc = 0;
+
+  int device_fd;
+  int image_fd;
+  struct blocklist blklist;
+  memset (&blklist, 0, sizeof (struct blocklist));
+  ITRY (add_file_to_blocklist (o->image, &blklist, 0x00000000));
+  if (o->parmfile)
+    {
+      ITRY (add_file_to_blocklist (o->parmfile, &blklist, 0x00008000));
+    }
+  if (o->ramdisk)
+    {
+      ITRY (add_file_to_blocklist (o->ramdisk, &blklist, 0x00800000));
+    }
+  ITRY (write_bootsect (o, &blklist));
+  return rc;
+}
+
+int
+main (int argct, char *argv[])
+{
+  int rc = 0;
+  char *save=NULL;
+  char *tmpdir=getenv("TMPDIR");
+  if (tmpdir) {
+    NTRY( save=(char*)malloc(strlen(tmpdir)));
+    NTRY( strncpy(save,tmpdir,strlen(tmpdir)));
+  }
+  ITRY( setenv("TMPDIR",".",1));
+  ITRY (parse_options (&silo_options, argct, argv));
+  ITRY (verify_options (&silo_options));
+  if ( silo_options.testlevel > 0 ) {
+    printf ("WARNING: silo does not modify your volume. Use -t2 to change IPL records\n");
+  }
+  ITRY (do_silo (&silo_options));
+  if ( save )
+    ITRY( setenv("TMPDIR",save,1)); 
+  return rc;
+}
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/tools/silo/silo.conf linux/arch/s390x/tools/silo/silo.conf
--- v2.4.1/linux/arch/s390x/tools/silo/silo.conf	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/tools/silo/silo.conf	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,7 @@
+ipldevice = /dev/dasda 
+image = /boot/image
+bootsect = /boot/ipleckd.boot
+map = /boot/boot.map
+root = /dev/dasd01
+readonly
+append = "dasd=200-20f noinitrd"
diff -u --recursive --new-file v2.4.1/linux/arch/s390x/vmlinux.lds linux/arch/s390x/vmlinux.lds
--- v2.4.1/linux/arch/s390x/vmlinux.lds	Wed Dec 31 16:00:00 1969
+++ linux/arch/s390x/vmlinux.lds	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,78 @@
+/* ld script to make s390 Linux kernel
+ * Written by Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390")
+OUTPUT_ARCH(s390)
+ENTRY(_start)
+SECTIONS
+{
+  . = 0x00000000;
+  _text = .;			/* Text and read-only data */
+  .text : {
+	*(.text)
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x0700
+  .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(16384);		/* 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(4096);
+  __init_end = .;
+
+  __setup_start = .;
+  .setup.init : { *(.setup.init) }
+  __setup_end = .;
+  __initcall_start = .;
+  .initcall.init : { *(.initcall.init) }
+  __initcall_end = .;
+  . = ALIGN(4096);
+  __init_end = .;
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  . = ALIGN(4096);
+  .data.page_aligned : { *(.data.idt) }
+
+
+  __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.4.1/linux/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
--- v2.4.1/linux/arch/sh/kernel/irq.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sh/kernel/irq.c	Fri Feb  9 11:29:44 2001
@@ -22,7 +22,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/timex.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c
--- v2.4.1/linux/arch/sh/kernel/process.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sh/kernel/process.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sh/kernel/setup.c linux/arch/sh/kernel/setup.c
--- v2.4.1/linux/arch/sh/kernel/setup.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sh/kernel/setup.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/config.in linux/arch/sparc/config.in
--- v2.4.1/linux/arch/sparc/config.in	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc/config.in	Sun Feb 18 19:49:44 2001
@@ -1,4 +1,4 @@
-# $Id: config.in,v 1.107 2001/01/06 00:46:44 davem Exp $
+# $Id: config.in,v 1.108 2001/02/18 09:02:59 davem Exp $
 # For a description of the syntax of this configuration file,
 # see Documentation/kbuild/config-language.txt.
 #
@@ -183,8 +183,8 @@
    mainmenu_option next_comment
    comment 'SCSI low-level drivers'
 
-   tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
-   tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
+   dep_tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+   dep_tristate 'PTI Qlogic,ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
    endmenu
 fi
 endmenu
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/ebus.c linux/arch/sparc/kernel/ebus.c
--- v2.4.1/linux/arch/sparc/kernel/ebus.c	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc/kernel/ebus.c	Sun Feb 18 19:49:44 2001
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.15 2000/11/08 05:06:21 davem Exp $
+/* $Id: ebus.c,v 1.16 2001/02/13 01:16:43 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/ioport.c linux/arch/sparc/kernel/ioport.c
--- v2.4.1/linux/arch/sparc/kernel/ioport.c	Mon Dec 11 12:37:02 2000
+++ linux/arch/sparc/kernel/ioport.c	Sun Feb 18 19:49:44 2001
@@ -1,4 +1,4 @@
-/* $Id: ioport.c,v 1.42 2000/12/05 00:56:36 anton Exp $
+/* $Id: ioport.c,v 1.44 2001/02/13 04:07:38 davem Exp $
  * ioport.c:  Simple io mapping allocator.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -32,7 +32,7 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>		/* struct pci_dev */
 #include <linux/proc_fs.h>
 
@@ -225,7 +225,7 @@
 	 * XXX Playing with implementation details here.
 	 * On sparc64 Ebus has resources with precise boundaries.
 	 * We share drivers with sparc64. Too clever drivers use
-	 * start of a resource instead of a base adress.
+	 * start of a resource instead of a base address.
 	 *
 	 * XXX-2 This may be not valid anymore, clean when
 	 * interface to sbus_ioremap() is resolved.
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/irq.c linux/arch/sparc/kernel/irq.c
--- v2.4.1/linux/arch/sparc/kernel/irq.c	Thu Sep  7 08:32:00 2000
+++ linux/arch/sparc/kernel/irq.c	Sun Feb 18 19:49:44 2001
@@ -1,4 +1,4 @@
-/*  $Id: irq.c,v 1.109 2000/08/31 10:00:39 anton Exp $
+/*  $Id: irq.c,v 1.110 2001/02/13 01:16:43 davem Exp $
  *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
  *                            Sparc the IRQ's are basically 'cast in stone'
  *                            and you are supposed to probe the prom's device
@@ -19,7 +19,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/smp.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/pcic.c linux/arch/sparc/kernel/pcic.c
--- v2.4.1/linux/arch/sparc/kernel/pcic.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc/kernel/pcic.c	Sun Feb 18 19:49:44 2001
@@ -1,4 +1,4 @@
-/* $Id: pcic.c,v 1.21 2001/01/18 00:23:00 davem Exp $
+/* $Id: pcic.c,v 1.22 2001/02/13 01:16:43 davem Exp $
  * pcic.c: Sparc/PCI controller support
  *
  * Copyright (C) 1998 V. Roganov and G. Raiko
@@ -15,7 +15,7 @@
 #include <linux/types.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/ebus.h>
 #include <asm/sbus.h> /* for sanity check... */
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c
--- v2.4.1/linux/arch/sparc/kernel/process.c	Tue Oct 10 10:33:51 2000
+++ linux/arch/sparc/kernel/process.c	Sun Feb 18 19:49:44 2001
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.154 2000/10/05 06:12:57 anton Exp $
+/*  $Id: process.c,v 1.155 2001/02/13 01:16:43 davem Exp $
  *  linux/arch/sparc/kernel/process.c
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -19,7 +19,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/ptrace.c linux/arch/sparc/kernel/ptrace.c
--- v2.4.1/linux/arch/sparc/kernel/ptrace.c	Mon Jun 19 17:59:38 2000
+++ linux/arch/sparc/kernel/ptrace.c	Fri Feb 16 16:02:35 2001
@@ -5,7 +5,7 @@
  * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
  * and David Mosberger.
  *
- * Added Linux support -miguel (wierd, eh?, the orignal code was meant
+ * Added Linux support -miguel (weird, eh?, the orignal code was meant
  * to emulate SunOS).
  */
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/setup.c linux/arch/sparc/kernel/setup.c
--- v2.4.1/linux/arch/sparc/kernel/setup.c	Mon Jan  1 10:37:41 2001
+++ linux/arch/sparc/kernel/setup.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.122 2001/01/01 01:46:15 davem Exp $
+/*  $Id: setup.c,v 1.123 2001/02/13 01:16:43 davem Exp $
  *  linux/arch/sparc/kernel/setup.c
  *
  *  Copyright (C) 1995  David S. Miller (davem@caip.rutgers.edu)
@@ -12,7 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/smp.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/sun4c_irq.c linux/arch/sparc/kernel/sun4c_irq.c
--- v2.4.1/linux/arch/sparc/kernel/sun4c_irq.c	Mon May  8 22:00:01 2000
+++ linux/arch/sparc/kernel/sun4c_irq.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <asm/ptrace.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/sun4d_irq.c linux/arch/sparc/kernel/sun4d_irq.c
--- v2.4.1/linux/arch/sparc/kernel/sun4d_irq.c	Wed Jul 26 18:36:44 2000
+++ linux/arch/sparc/kernel/sun4d_irq.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/*  $Id: sun4d_irq.c,v 1.26 2000/07/26 01:04:03 davem Exp $
+/*  $Id: sun4d_irq.c,v 1.27 2001/02/13 01:16:43 davem Exp $
  *  arch/sparc/kernel/sun4d_irq.c:
  *			SS1000/SC2000 interrupt handling.
  *
@@ -14,7 +14,7 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/smp.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/sun4d_smp.c linux/arch/sparc/kernel/sun4d_smp.c
--- v2.4.1/linux/arch/sparc/kernel/sun4d_smp.c	Tue Nov 28 21:53:44 2000
+++ linux/arch/sparc/kernel/sun4d_smp.c	Fri Feb  9 11:37:03 2001
@@ -287,11 +287,11 @@
 				smp_highest_cpu = i;
 			}
 		}
-		SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, (bogosum + 2500)/500000, ((bogosum + 2500)/5000)%100));
+		SMP_PRINTK(("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n", cpucount + 1, bogosum/(500000/HZ), (bogosum/(5000/HZ))%100));
 		printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
 		       cpucount + 1,
-		       (bogosum + 2500)/500000,
-		       ((bogosum + 2500)/5000)%100);
+		       bogosum/(500000/HZ),
+		       (bogosum/(5000/HZ))%100);
 		smp_activated = 1;
 		smp_num_cpus = cpucount + 1;
 	}
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/sun4m_irq.c linux/arch/sparc/kernel/sun4m_irq.c
--- v2.4.1/linux/arch/sparc/kernel/sun4m_irq.c	Mon May  8 22:00:01 2000
+++ linux/arch/sparc/kernel/sun4m_irq.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/sched.h>
 #include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/sun4m_smp.c linux/arch/sparc/kernel/sun4m_smp.c
--- v2.4.1/linux/arch/sparc/kernel/sun4m_smp.c	Tue Nov 28 21:53:44 2000
+++ linux/arch/sparc/kernel/sun4m_smp.c	Fri Feb  9 11:37:03 2001
@@ -256,8 +256,8 @@
 		}
 		printk("Total of %d Processors activated (%lu.%02lu BogoMIPS).\n",
 		       cpucount + 1,
-		       (bogosum + 2500)/500000,
-		       ((bogosum + 2500)/5000)%100);
+		       bogosum/(500000/HZ),
+		       (bogosum/(5000/HZ))%100);
 		smp_activated = 1;
 		smp_num_cpus = cpucount + 1;
 	}
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/kernel/sys_sunos.c linux/arch/sparc/kernel/sys_sunos.c
--- v2.4.1/linux/arch/sparc/kernel/sys_sunos.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc/kernel/sys_sunos.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos.c,v 1.131 2001/01/24 21:05:12 davem Exp $
+/* $Id: sys_sunos.c,v 1.132 2001/02/13 01:16:43 davem Exp $
  * sys_sunos.c: SunOS specific syscall compatibility support.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
@@ -28,7 +28,7 @@
 #include <linux/utsname.h>
 #include <linux/major.h>
 #include <linux/stat.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/mm/io-unit.c linux/arch/sparc/mm/io-unit.c
--- v2.4.1/linux/arch/sparc/mm/io-unit.c	Wed Aug  9 13:49:55 2000
+++ linux/arch/sparc/mm/io-unit.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: io-unit.c,v 1.22 2000/08/09 00:00:15 davem Exp $
+/* $Id: io-unit.c,v 1.23 2001/02/13 01:16:43 davem Exp $
  * io-unit.c:  IO-UNIT specific routines for memory management.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek    (jj@sunsite.mff.cuni.cz)
@@ -7,7 +7,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <asm/scatterlist.h>
 #include <asm/pgalloc.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/mm/iommu.c linux/arch/sparc/mm/iommu.c
--- v2.4.1/linux/arch/sparc/mm/iommu.c	Wed Aug  9 13:49:55 2000
+++ linux/arch/sparc/mm/iommu.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: iommu.c,v 1.20 2000/08/09 00:00:15 davem Exp $
+/* $Id: iommu.c,v 1.21 2001/02/13 01:16:43 davem Exp $
  * iommu.c:  IOMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/scatterlist.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.4.1/linux/arch/sparc/mm/srmmu.c	Mon Dec 11 12:37:03 2000
+++ linux/arch/sparc/mm/srmmu.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: srmmu.c,v 1.225 2000/11/30 08:37:31 anton Exp $
+/* $Id: srmmu.c,v 1.226 2001/02/13 01:16:44 davem Exp $
  * srmmu.c:  SRMMU specific routines for memory management.
  *
  * Copyright (C) 1995 David S. Miller  (davem@caip.rutgers.edu)
@@ -11,7 +11,7 @@
 #include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/pagemap.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc/mm/sun4c.c linux/arch/sparc/mm/sun4c.c
--- v2.4.1/linux/arch/sparc/mm/sun4c.c	Mon Dec 11 12:37:03 2000
+++ linux/arch/sparc/mm/sun4c.c	Fri Feb 16 16:02:35 2001
@@ -353,7 +353,7 @@
 			break;
 
 		default:
-			prom_printf("Cannot initialize VAC - wierd sun4 model idprom->id_machtype = %d", idprom->id_machtype);
+			prom_printf("Cannot initialize VAC - weird sun4 model idprom->id_machtype = %d", idprom->id_machtype);
 			prom_halt();
 		};
 	} else {
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/config.in linux/arch/sparc64/config.in
--- v2.4.1/linux/arch/sparc64/config.in	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc64/config.in	Fri Feb 16 16:02:35 2001
@@ -161,15 +161,15 @@
    mainmenu_option next_comment
    comment 'SCSI low-level drivers'
 
-   tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
-   tristate 'PTI Qlogic, ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
+   dep_tristate 'Sparc ESP Scsi Driver' CONFIG_SCSI_SUNESP $CONFIG_SCSI
+   dep_tristate 'PTI Qlogic, ISP Driver' CONFIG_SCSI_QLOGICPTI $CONFIG_SCSI
 
    if [ "$CONFIG_PCI" != "n" ]; then
       dep_tristate 'Adaptec AIC7xxx support' CONFIG_SCSI_AIC7XXX $CONFIG_SCSI
       if [ "$CONFIG_SCSI_AIC7XXX" != "n" ]; then
 	 bool '  Enable tagged command queueing (TCQ) by default' CONFIG_AIC7XXX_TAGGED_QUEUEING
 	 int  '  Maximum number of TCQ commands per device' CONFIG_AIC7XXX_CMDS_PER_DEVICE 8
-  	 bool '  Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS N
+  	 bool '  Collect statistics to report in /proc' CONFIG_AIC7XXX_PROC_STATS
 	 int  '  Delay in seconds after SCSI bus reset' CONFIG_AIC7XXX_RESET_DELAY 5
       fi
       dep_tristate 'NCR53C8XX SCSI support' CONFIG_SCSI_NCR53C8XX $CONFIG_SCSI
@@ -196,6 +196,8 @@
    endmenu
 fi
 endmenu
+
+source drivers/message/fusion/Config.in
 
 source drivers/fc4/Config.in
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/binfmt_aout32.c linux/arch/sparc64/kernel/binfmt_aout32.c
--- v2.4.1/linux/arch/sparc64/kernel/binfmt_aout32.c	Sun Jul  9 22:30:37 2000
+++ linux/arch/sparc64/kernel/binfmt_aout32.c	Fri Feb  9 11:29:44 2001
@@ -23,7 +23,7 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/ebus.c linux/arch/sparc64/kernel/ebus.c
--- v2.4.1/linux/arch/sparc64/kernel/ebus.c	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc64/kernel/ebus.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: ebus.c,v 1.53 2000/11/08 05:08:23 davem Exp $
+/* $Id: ebus.c,v 1.54 2001/02/13 01:16:44 davem Exp $
  * ebus.c: PCI to EBus bridge device.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/ioctl32.c linux/arch/sparc64/kernel/ioctl32.c
--- v2.4.1/linux/arch/sparc64/kernel/ioctl32.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc64/kernel/ioctl32.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: ioctl32.c,v 1.105 2001/01/18 04:47:44 davem Exp $
+/* $Id: ioctl32.c,v 1.107 2001/02/13 01:16:44 davem Exp $
  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
  *
  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
@@ -16,7 +16,7 @@
 #include <linux/smp_lock.h>
 #include <linux/ioctl.h>
 #include <linux/if.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/hdreg.h>
 #include <linux/raid/md.h>
 #include <linux/kd.h>
@@ -3770,7 +3770,7 @@
 
 unsigned int ioctl32_hash_table[1024];
 
-extern inline unsigned long ioctl32_hash(unsigned long cmd)
+static inline unsigned long ioctl32_hash(unsigned long cmd)
 {
 	return ((cmd >> 6) ^ (cmd >> 4) ^ cmd) & 0x3ff;
 }
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/irq.c linux/arch/sparc64/kernel/irq.c
--- v2.4.1/linux/arch/sparc64/kernel/irq.c	Tue Oct  3 09:24:41 2000
+++ linux/arch/sparc64/kernel/irq.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: irq.c,v 1.94 2000/09/21 06:27:10 anton Exp $
+/* $Id: irq.c,v 1.95 2001/02/13 01:16:44 davem Exp $
  * irq.c: UltraSparc IRQ handling/init/registry.
  *
  * Copyright (C) 1997  David S. Miller  (davem@caip.rutgers.edu)
@@ -13,7 +13,7 @@
 #include <linux/signal.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h> /* XXX ADD add_foo_randomness() calls... -DaveM */
 #include <linux/init.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
--- v2.4.1/linux/arch/sparc64/kernel/pci_common.c	Wed May  3 01:47:57 2000
+++ linux/arch/sparc64/kernel/pci_common.c	Sun Feb 18 19:49:54 2001
@@ -1,11 +1,11 @@
-/* $Id: pci_common.c,v 1.12 2000/05/01 06:32:49 davem Exp $
+/* $Id: pci_common.c,v 1.13 2001/02/13 01:16:44 davem Exp $
  * pci_common.c: PCI controller common support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
  */
 
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <asm/pbm.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/pci_psycho.c linux/arch/sparc64/kernel/pci_psycho.c
--- v2.4.1/linux/arch/sparc64/kernel/pci_psycho.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc64/kernel/pci_psycho.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_psycho.c,v 1.18 2001/01/11 16:26:45 davem Exp $
+/* $Id: pci_psycho.c,v 1.19 2001/02/13 01:16:44 davem Exp $
  * pci_psycho.c: PSYCHO/U2P specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/pbm.h>
 #include <asm/iommu.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/pci_sabre.c linux/arch/sparc64/kernel/pci_sabre.c
--- v2.4.1/linux/arch/sparc64/kernel/pci_sabre.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc64/kernel/pci_sabre.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_sabre.c,v 1.22 2001/01/16 13:03:48 anton Exp $
+/* $Id: pci_sabre.c,v 1.23 2001/02/13 01:16:44 davem Exp $
  * pci_sabre.c: Sabre specific PCI controller support.
  *
  * Copyright (C) 1997, 1998, 1999 David S. Miller (davem@caipfs.rutgers.edu)
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/apb.h>
 #include <asm/pbm.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/pci_schizo.c linux/arch/sparc64/kernel/pci_schizo.c
--- v2.4.1/linux/arch/sparc64/kernel/pci_schizo.c	Sat Feb  3 19:51:24 2001
+++ linux/arch/sparc64/kernel/pci_schizo.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: pci_schizo.c,v 1.2 2001/01/12 02:43:30 davem Exp $
+/* $Id: pci_schizo.c,v 1.3 2001/02/13 01:16:44 davem Exp $
  * pci_schizo.c: SCHIZO specific PCI controller support.
  *
  * Copyright (C) 2001 David S. Miller (davem@redhat.com)
@@ -8,7 +8,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/pbm.h>
 #include <asm/iommu.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c
--- v2.4.1/linux/arch/sparc64/kernel/process.c	Thu Nov  9 15:57:41 2000
+++ linux/arch/sparc64/kernel/process.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/*  $Id: process.c,v 1.113 2000/11/08 08:14:58 davem Exp $
+/*  $Id: process.c,v 1.114 2001/02/13 01:16:44 davem Exp $
  *  arch/sparc64/kernel/process.c
  *
  *  Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu)
@@ -22,7 +22,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/ptrace.c linux/arch/sparc64/kernel/ptrace.c
--- v2.4.1/linux/arch/sparc64/kernel/ptrace.c	Mon Jun 19 17:59:38 2000
+++ linux/arch/sparc64/kernel/ptrace.c	Fri Feb 16 16:02:35 2001
@@ -6,7 +6,7 @@
  * Based upon code written by Ross Biro, Linus Torvalds, Bob Manson,
  * and David Mosberger.
  *
- * Added Linux support -miguel (wierd, eh?, the orignal code was meant
+ * Added Linux support -miguel (weird, eh?, the orignal code was meant
  * to emulate SunOS).
  */
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/sbus.c linux/arch/sparc64/kernel/sbus.c
--- v2.4.1/linux/arch/sparc64/kernel/sbus.c	Tue Oct  3 09:24:41 2000
+++ linux/arch/sparc64/kernel/sbus.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: sbus.c,v 1.12 2000/09/21 06:25:14 anton Exp $
+/* $Id: sbus.c,v 1.13 2001/02/13 01:16:44 davem Exp $
  * sbus.c: UltraSparc SBUS controller support.
  *
  * Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -8,7 +8,7 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <asm/page.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/setup.c linux/arch/sparc64/kernel/setup.c
--- v2.4.1/linux/arch/sparc64/kernel/setup.c	Mon Jan  1 10:37:41 2001
+++ linux/arch/sparc64/kernel/setup.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/*  $Id: setup.c,v 1.58 2001/01/01 01:46:15 davem Exp $
+/*  $Id: setup.c,v 1.59 2001/02/13 01:16:44 davem Exp $
  *  linux/arch/sparc64/kernel/setup.c
  *
  *  Copyright (C) 1995,1996  David S. Miller (davem@caip.rutgers.edu)
@@ -12,7 +12,7 @@
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/smp.h>
 #include <linux/user.h>
 #include <linux/a.out.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/starfire.c linux/arch/sparc64/kernel/starfire.c
--- v2.4.1/linux/arch/sparc64/kernel/starfire.c	Mon Oct 30 14:34:12 2000
+++ linux/arch/sparc64/kernel/starfire.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: starfire.c,v 1.8 2000/10/27 18:36:47 anton Exp $
+/* $Id: starfire.c,v 1.9 2001/02/13 01:16:44 davem Exp $
  * starfire.c: Starfire/E10000 support.
  *
  * Copyright (C) 1998 David S. Miller (davem@redhat.com)
@@ -6,7 +6,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/page.h>
 #include <asm/oplib.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/sys_sparc.c linux/arch/sparc64/kernel/sys_sparc.c
--- v2.4.1/linux/arch/sparc64/kernel/sys_sparc.c	Mon Dec 11 12:37:03 2000
+++ linux/arch/sparc64/kernel/sys_sparc.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc.c,v 1.47 2000/11/29 05:56:12 anton Exp $
+/* $Id: sys_sparc.c,v 1.48 2001/02/13 01:16:44 davem Exp $
  * linux/arch/sparc64/kernel/sys_sparc.c
  *
  * This file contains various random system calls that
@@ -21,7 +21,7 @@
 #include <linux/utsname.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ipc.h>
 #include <linux/personality.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/sys_sparc32.c linux/arch/sparc64/kernel/sys_sparc32.c
--- v2.4.1/linux/arch/sparc64/kernel/sys_sparc32.c	Sat Feb  3 19:51:25 2001
+++ linux/arch/sparc64/kernel/sys_sparc32.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sparc32.c,v 1.172 2001/01/24 21:05:13 davem Exp $
+/* $Id: sys_sparc32.c,v 1.173 2001/02/13 01:16:44 davem Exp $
  * sys_sparc32.c: Conversion between 32bit and 64bit native syscalls.
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -25,7 +25,7 @@
 #include <linux/sem.h>
 #include <linux/msg.h>
 #include <linux/shm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/uio.h>
 #include <linux/nfs_fs.h>
 #include <linux/smb_fs.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/sys_sunos32.c linux/arch/sparc64/kernel/sys_sunos32.c
--- v2.4.1/linux/arch/sparc64/kernel/sys_sunos32.c	Sat Feb  3 19:51:25 2001
+++ linux/arch/sparc64/kernel/sys_sunos32.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: sys_sunos32.c,v 1.56 2001/01/04 05:35:48 davem Exp $
+/* $Id: sys_sunos32.c,v 1.57 2001/02/13 01:16:44 davem Exp $
  * sys_sunos32.c: SunOS binary compatability layer on sparc64.
  *
  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
@@ -27,7 +27,7 @@
 #include <linux/utsname.h>
 #include <linux/major.h>
 #include <linux/stat.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/kernel/traps.c linux/arch/sparc64/kernel/traps.c
--- v2.4.1/linux/arch/sparc64/kernel/traps.c	Tue Nov 28 21:53:44 2000
+++ linux/arch/sparc64/kernel/traps.c	Fri Feb  9 11:37:03 2001
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.68 2000/11/22 06:50:37 davem Exp $
+/* $Id: traps.c,v 1.70 2001/02/09 05:46:44 davem Exp $
  * arch/sparc64/kernel/traps.c
  *
  * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -636,6 +636,30 @@
 	printk("Instruction DUMP:");
 	for(i = 0; i < 9; i++)
 		printk("%c%08x%c",i==3?' ':'<',buf[i],i==3?' ':'>');
+	printk("\n");
+}
+
+void show_trace_task(struct task_struct *tsk)
+{
+	unsigned long pc, fp;
+	unsigned long task_base = (unsigned long)tsk;
+	struct reg_window *rw;
+	int count = 0;
+
+	if (!tsk)
+		return;
+
+	fp = tsk->thread.ksp + STACK_BIAS;
+	do {
+		/* Bogus frame pointer? */
+		if (fp < (task_base + sizeof(struct task_struct)) ||
+		    fp >= (task_base + (2 * PAGE_SIZE)))
+			break;
+		rw = (struct reg_window *)fp;
+		pc = rw->ins[7];
+		printk("[%016lx] ", pc);
+		fp = rw->ins[6] + STACK_BIAS;
+	} while (++count < 16);
 	printk("\n");
 }
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/mm/init.c linux/arch/sparc64/mm/init.c
--- v2.4.1/linux/arch/sparc64/mm/init.c	Mon Dec 11 12:37:03 2000
+++ linux/arch/sparc64/mm/init.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/*  $Id: init.c,v 1.161 2000/12/09 20:16:58 davem Exp $
+/*  $Id: init.c,v 1.162 2001/02/13 01:16:44 davem Exp $
  *  arch/sparc64/mm/init.c
  *
  *  Copyright (C) 1996-1999 David S. Miller (davem@caip.rutgers.edu)
@@ -12,7 +12,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/swap.h>
 #include <linux/swapctl.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/mm/modutil.c linux/arch/sparc64/mm/modutil.c
--- v2.4.1/linux/arch/sparc64/mm/modutil.c	Wed Jul  5 12:14:54 2000
+++ linux/arch/sparc64/mm/modutil.c	Sun Feb 18 19:49:54 2001
@@ -1,11 +1,11 @@
-/*  $Id: modutil.c,v 1.6 2000/06/26 23:20:24 davem Exp $
+/*  $Id: modutil.c,v 1.7 2001/02/13 01:16:44 davem Exp $
  *  arch/sparc64/mm/modutil.c
  *
  *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *  Based upon code written by Linus Torvalds and others.
  */
  
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/solaris/fs.c linux/arch/sparc64/solaris/fs.c
--- v2.4.1/linux/arch/sparc64/solaris/fs.c	Tue Aug 29 14:09:15 2000
+++ linux/arch/sparc64/solaris/fs.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: fs.c,v 1.23 2000/08/29 07:01:54 davem Exp $
+/* $Id: fs.c,v 1.24 2001/02/13 01:16:44 davem Exp $
  * fs.c: fs related syscall emulation for Solaris
  *
  * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/solaris/socket.c linux/arch/sparc64/solaris/socket.c
--- v2.4.1/linux/arch/sparc64/solaris/socket.c	Tue Nov 28 21:53:44 2000
+++ linux/arch/sparc64/solaris/socket.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: socket.c,v 1.4 2000/11/18 02:11:00 davem Exp $
+/* $Id: socket.c,v 1.5 2001/02/13 01:16:44 davem Exp $
  * socket.c: Socket syscall emulation for Solaris 2.6+
  *
  * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/smp_lock.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/file.h>
 
diff -u --recursive --new-file v2.4.1/linux/arch/sparc64/solaris/socksys.c linux/arch/sparc64/solaris/socksys.c
--- v2.4.1/linux/arch/sparc64/solaris/socksys.c	Mon Oct 23 15:48:27 2000
+++ linux/arch/sparc64/solaris/socksys.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: socksys.c,v 1.17 2000/10/19 00:49:53 davem Exp $
+/* $Id: socksys.c,v 1.18 2001/02/13 01:16:44 davem Exp $
  * socksys.c: /dev/inet/ stuff for Solaris emulation.
  *
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
@@ -16,7 +16,7 @@
 #include <linux/file.h>
 #include <linux/init.h>
 #include <linux/poll.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/devfs_fs_kernel.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/Makefile linux/drivers/acorn/Makefile
--- v2.4.1/linux/drivers/acorn/Makefile	Wed Oct 20 16:29:08 1999
+++ linux/drivers/acorn/Makefile	Thu Feb  8 16:32:44 2001
@@ -5,8 +5,11 @@
 # removes any old dependencies. DON'T put your own dependencies here
 # unless it's something special (not a .c file).
 
-SUB_DIRS     := block char net scsi
-MOD_SUB_DIRS := $(SUB_DIRS)
-ALL_SUB_DIRS := $(SUB_DIRS)
+subdir-y	:= char
+subdir-m	:= $(subdir-y)
+
+# the BLOCK subdir is included from drivers/block now
+# the SCSI subdir is included from drivers/scsi now
+# the NET subdir is included from drivers/net now
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/block/Makefile linux/drivers/acorn/block/Makefile
--- v2.4.1/linux/drivers/acorn/block/Makefile	Sun Aug 13 09:54:15 2000
+++ linux/drivers/acorn/block/Makefile	Thu Feb  8 16:32:44 2001
@@ -11,7 +11,7 @@
 
 USE_STANDARD_AS_RULE := true
 
-L_TARGET	:= acorn-block.a
+O_TARGET	:= acorn-block.o
 
 obj-y		:=
 obj-m		:=
@@ -24,36 +24,12 @@
 mfmhd_mod-objs	:= mfmhd.o mfm.o
 
 obj-$(CONFIG_BLK_DEV_FD1772)	+= fd1772_mod.o
-obj-$(CONFIG_BLK_DEV_MFM)	+= mfmhd.o mfm.o
-
-# Extract lists of the multi-part drivers.
-# The 'int-*' lists are intermediate files used to build the multi's.
-
-multi-y		:= $(filter $(list-multi), $(obj-y))
-multi-m		:= $(filter $(list-multi), $(obj-m))
-int-y		:= $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
-int-m		:= $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
-
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-int-m		:= $(filter-out $(int-y), $(int-m))
-
-# Take multi-part drivers out of obj-y and put components in.
-
-obj-y		:= $(filter-out $(list-multi), $(obj-y)) $(int-y)
-
-# Translate to Rules.make lists.
-
-L_OBJS		:= $(filter-out $(export-objs), $(obj-y))
-LX_OBJS		:= $(filter     $(export-objs), $(obj-y))
-M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
+obj-$(CONFIG_BLK_DEV_MFM)	+= mfmhd_mod.o
 
 include $(TOPDIR)/Rules.make
 
-fd1772_mod.o: $(FLOPPY)
-	$(LD) -r -o $@ $(FLOPPY)
+fd1772_mod.o: $(fd1772_mod-objs)
+	$(LD) -r -o $@ $(fd1772_mod-objs)
 
-mfmhd_mod.o: mfmhd.o mfm.o
-	$(LD) -r -o $@ mfmhd.o mfm.o
+mfmhd_mod.o: $(mfmhd_mod-objs)
+	$(LD) -r -o $@ $(mfmhd_mod-objs)
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/block/fd1772.c linux/drivers/acorn/block/fd1772.c
--- v2.4.1/linux/drivers/acorn/block/fd1772.c	Sun Oct  1 20:35:15 2000
+++ linux/drivers/acorn/block/fd1772.c	Thu Feb  8 16:32:44 2001
@@ -276,8 +276,8 @@
 static volatile int fdc_busy = 0;
 static DECLARE_WAIT_QUEUE_HEAD(fdc_wait);
 
-
-static unsigned int changed_floppies = 0xff, fake_change = 0;
+/* long req'd for set_bit --RR */
+static unsigned long changed_floppies = 0xff, fake_change = 0;
 #define	CHECK_CHANGE_DELAY	HZ/2
 
 /* DAG - increased to 30*HZ - not sure if this is the correct thing to do */
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/char/Makefile linux/drivers/acorn/char/Makefile
--- v2.4.1/linux/drivers/acorn/char/Makefile	Mon Sep 18 15:15:21 2000
+++ linux/drivers/acorn/char/Makefile	Thu Feb  8 16:32:44 2001
@@ -11,11 +11,6 @@
 
 O_TARGET 	:= acorn-char.o
 
-O_OBJS		:=
-OX_OBJS		:=
-M_OBJS		:=
-MX_OBJS		:=
-
 # Object file lists.
 
 obj-y   	:=
@@ -37,10 +32,5 @@
 
 # Do the i2c and rtc last
 obj-y		+= $(obj-$(MACHINE)) 
-
-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)))
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/char/keyb_arc.c linux/drivers/acorn/char/keyb_arc.c
--- v2.4.1/linux/drivers/acorn/char/keyb_arc.c	Mon Sep 18 15:15:21 2000
+++ linux/drivers/acorn/char/keyb_arc.c	Fri Feb  9 11:30:22 2001
@@ -19,7 +19,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <linux/timer.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/char/keyb_ps2.c linux/drivers/acorn/char/keyb_ps2.c
--- v2.4.1/linux/drivers/acorn/char/keyb_ps2.c	Mon Sep 18 15:15:21 2000
+++ linux/drivers/acorn/char/keyb_ps2.c	Fri Feb  9 11:30:22 2001
@@ -17,7 +17,7 @@
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ptrace.h>
 #include <linux/signal.h>
 #include <linux/timer.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/char/pcf8583.c linux/drivers/acorn/char/pcf8583.c
--- v2.4.1/linux/drivers/acorn/char/pcf8583.c	Mon Sep 18 15:15:21 2000
+++ linux/drivers/acorn/char/pcf8583.c	Fri Feb  9 11:30:22 2001
@@ -10,7 +10,7 @@
  *  Driver for PCF8583 RTC & RAM chip
  */
 #include <linux/i2c.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/mc146818rtc.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/net/Config.in linux/drivers/acorn/net/Config.in
--- v2.4.1/linux/drivers/acorn/net/Config.in	Thu Oct 28 10:16:02 1999
+++ linux/drivers/acorn/net/Config.in	Thu Feb  8 16:32:44 2001
@@ -2,6 +2,6 @@
 # Acorn Network device configuration
 #  These are for Acorn's Expansion card network interfaces
 #
-tristate '  Acorn Ether1 (82586) support' CONFIG_ARM_ETHER1
-tristate '  Acorn/ANT Ether3 (NQ8005) support' CONFIG_ARM_ETHER3
-tristate '  I-cubed EtherH (NS8390) support' CONFIG_ARM_ETHERH
+tristate '  Acorn Ether1 support' CONFIG_ARM_ETHER1
+tristate '  Acorn/ANT Ether3 support' CONFIG_ARM_ETHER3
+tristate '  I-cubed EtherH/ANT EtherM support' CONFIG_ARM_ETHERH
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/net/Makefile linux/drivers/acorn/net/Makefile
--- v2.4.1/linux/drivers/acorn/net/Makefile	Sun Aug  6 11:23:40 2000
+++ linux/drivers/acorn/net/Makefile	Thu Feb  8 16:32:44 2001
@@ -14,7 +14,4 @@
 obj-$(CONFIG_ARM_ETHER3)	+= ether3.o
 obj-$(CONFIG_ARM_ETHER1)	+= ether1.o
 
-O_OBJS	:= $(obj-y)
-M_OBJS	:= $(obj-m)
-
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/net/ether1.c linux/drivers/acorn/net/ether1.c
--- v2.4.1/linux/drivers/acorn/net/ether1.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/net/ether1.c	Fri Feb  9 11:30:22 2001
@@ -40,7 +40,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -74,7 +74,8 @@
 static void ether1_timeout(struct net_device *dev);
 
 /* ------------------------------------------------------------------------- */
-static char *version = "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
+
+static const char version[] __initdata = KERN_INFO "ether1 ethernet driver (c) 2000 Russell King v1.07\n";
 
 #define BUS_16 16
 #define BUS_8  8
@@ -646,18 +647,13 @@
 {
 	struct ether1_priv *priv = (struct ether1_priv *)dev->priv;
 
-	MOD_INC_USE_COUNT;
-
-	if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev)) {
-		MOD_DEC_USE_COUNT;
+	if (request_irq(dev->irq, ether1_interrupt, 0, "ether1", dev))
 		return -EAGAIN;
-	}
 
 	memset (&priv->stats, 0, sizeof (struct net_device_stats));
 
 	if (ether1_init_for_open (dev)) {
 		free_irq (dev->irq, dev);
-		MOD_DEC_USE_COUNT;
 		return -EAGAIN;
 	}
 
@@ -965,8 +961,6 @@
 
 	free_irq(dev->irq, dev);
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -996,7 +990,7 @@
 	static unsigned int version_printed = 0;
 
 	if (net_debug && version_printed++ == 0)
-		printk (KERN_INFO "%s", version);
+		printk (version);
 }
 
 static struct net_device * __init ether1_init_one(struct expansion_card *ec)
@@ -1008,11 +1002,13 @@
 	ether1_banner();
 
 	ecard_claim(ec);
-	
+
 	dev = init_etherdev(NULL, sizeof(struct ether1_priv));
 	if (!dev)
 		goto out;
 
+	SET_MODULE_OWNER(dev);
+
 	dev->base_addr	= ecard_address(ec, ECARD_IOC, ECARD_FAST);
 	dev->irq	= ec->irq;
 
@@ -1024,18 +1020,18 @@
 
 	priv = (struct ether1_priv *)dev->priv;
 	if ((priv->bus_type = ether1_reset(dev)) == 0)
-		goto free_dev;
+		goto release;
 
-	printk(KERN_INFO "%s: ether1 at %lx, IRQ%d, ether address ",
-		dev->name, dev->base_addr, dev->irq);
+	printk(KERN_INFO "%s: ether1 in slot %d, ",
+		dev->name, ec->slot_no);
     
 	for (i = 0; i < 6; i++) {
 		dev->dev_addr[i] = inb(IDPROM_ADDRESS + i);
-		printk (i==0?" %02x":i==5?":%02x\n":":%02x", dev->dev_addr[i]);
+		printk ("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
 	}
 
 	if (ether1_init_2(dev))
-		goto free_dev;
+		goto release;
 
 	dev->open		= ether1_open;
 	dev->stop		= ether1_close;
@@ -1046,9 +1042,10 @@
 	dev->watchdog_timeo	= 5 * HZ / 100;
 	return 0;
 
-free_dev:
+release:
 	release_region(dev->base_addr, 16);
 	release_region(dev->base_addr + 0x800, 4096);
+free:
 	unregister_netdev(dev);
 	kfree(dev);
 out:
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/net/ether3.c linux/drivers/acorn/net/ether3.c
--- v2.4.1/linux/drivers/acorn/net/ether3.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/net/ether3.c	Fri Feb  9 11:30:22 2001
@@ -46,8 +46,6 @@
  * 1.17	RMK	13/05/2000	Updated for 2.3.99-pre8
  */
 
-static char *version = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
-
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
@@ -57,7 +55,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
@@ -72,13 +70,15 @@
 #include <asm/io.h>
 #include <asm/irq.h>
 
+static const char version[] __initdata = "ether3 ethernet driver (c) 1995-2000 R.M.King v1.17\n";
+
 #include "ether3.h"
 
 static unsigned int net_debug = NET_DEBUG;
 static const card_ids __init ether3_cids[] = {
 	{ MANU_ANT2, PROD_ANT_ETHER3 },
 	{ MANU_ANT,  PROD_ANT_ETHER3 },
-	{ MANU_ANT,  PROD_ANT_ETHERB }, /* trial - will etherb work? */
+	{ MANU_ANT,  PROD_ANT_ETHERB },
 	{ 0xffff, 0xffff }
 };
 
@@ -97,12 +97,6 @@
 #define BUS_8		1
 #define BUS_UNKNOWN	0
 
-/*
- * I'm not sure what address we should default to if the internal one
- * is corrupted...
- */
-unsigned char def_eth_addr[6] = {0x00, 'L', 'i', 'n', 'u', 'x'};
-
 /* --------------------------------------------------------------------------- */
 
 typedef enum {
@@ -214,7 +208,7 @@
  * Read the ethernet address string from the on board rom.
  * This is an ascii string!!!
  */
-static void __init
+static int __init
 ether3_addr(char *addr, struct expansion_card *ec)
 {
 	struct in_chunk_dir cd;
@@ -228,13 +222,13 @@
 				break;
 		}
 		if (i == 6)
-			return;
+			return 0;
 	}
 	/* I wonder if we should even let the user continue in this case
 	 *   - no, it would be better to disable the device
 	 */
 	printk(KERN_ERR "ether3: Couldn't read a valid MAC address from card.\n");
-	memcpy(addr, def_eth_addr, 6);
+	return -ENODEV;
 }
 
 /* --------------------------------------------------------------------------- */
@@ -423,12 +417,8 @@
 static int
 ether3_open(struct net_device *dev)
 {
-	MOD_INC_USE_COUNT;
-
-	if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev)) {
-	    	MOD_DEC_USE_COUNT;
+	if (request_irq(dev->irq, ether3_interrupt, 0, "ether3", dev))
 		return -EAGAIN;
-	}
 
 	ether3_init_for_open(dev);
 
@@ -457,7 +447,6 @@
 
 	free_irq(dev->irq, dev);
 
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -807,7 +796,8 @@
 	ec->irqaddr = (volatile unsigned char *)ioaddr(dev->base_addr);
 	ec->irqmask = 0xf0;
 
-	ether3_addr(dev->dev_addr, ec);
+	if (ether3_addr(dev->dev_addr, ec))
+		name = NULL;
 
 	return name;
 }
@@ -827,12 +817,17 @@
 	if (!dev)
 		goto out;
 
+	SET_MODULE_OWNER(dev);
+
 	name = ether3_get_dev(dev, ec);
+	if (!name)
+		goto free;
 
 	/*
 	 * this will not fail - the nature of the bus ensures this
 	 */
-	request_region(dev->base_addr, 128, dev->name);
+	if (!request_region(dev->base_addr, 128, dev->name))
+		goto free;
 
 	priv = (struct dev_priv *) dev->priv;
 
@@ -868,10 +863,9 @@
 		break;
 	}
 
-	printk("%s: %s at %lx, IRQ%d, ether address ",
-		dev->name, name, dev->base_addr, dev->irq);
+	printk("%s: %s in slot %d, ", dev->name, name, ec->slot_no);
 	for (i = 0; i < 6; i++)
-		printk(i == 5 ? "%2.2x\n" : "%2.2x:", dev->dev_addr[i]);
+		printk("%2.2x%c", dev->dev_addr[i], i == 5 ? '\n' : ':');
 
 	if (ether3_init_2(dev))
 		goto failed;
@@ -887,6 +881,7 @@
 
 failed:
 	release_region(dev->base_addr, 128);
+free:
 	unregister_netdev(dev);
 	kfree(dev);
 out:
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/net/etherh.c linux/drivers/acorn/net/etherh.c
--- v2.4.1/linux/drivers/acorn/net/etherh.c	Tue Nov  7 10:59:42 2000
+++ linux/drivers/acorn/net/etherh.c	Fri Feb  9 11:30:22 2001
@@ -36,7 +36,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
@@ -67,7 +67,7 @@
 MODULE_AUTHOR("Russell King");
 MODULE_DESCRIPTION("i3 EtherH driver");
 
-static char version[] __initdata =
+static const char version[] __initdata =
 	"etherh [500/600/600A] ethernet driver (c) 2000 R.M.King v1.07\n";
 
 #define ETHERH500_DATAPORT	0x200	/* MEMC */
@@ -363,12 +363,8 @@
 static int
 etherh_open(struct net_device *dev)
 {
-	MOD_INC_USE_COUNT;
-
-	if (request_irq(dev->irq, ei_interrupt, 0, "etherh", dev)) {
-		MOD_DEC_USE_COUNT;
+	if (request_irq(dev->irq, ei_interrupt, 0, "etherh", dev))
 		return -EAGAIN;
-	}
 
 	/*
 	 * Make sure that we aren't going to change the
@@ -406,8 +402,6 @@
 {
 	ei_close (dev);
 	free_irq (dev->irq, dev);
-
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -424,12 +418,8 @@
 }
 
 static expansioncard_ops_t etherh_ops = {
-	etherh_irq_enable,
-	etherh_irq_disable,
-	NULL,
-	NULL,
-	NULL,
-	NULL
+	irqenable:	etherh_irq_enable,
+	irqdisable:	etherh_irq_disable,
 };
 
 /*
@@ -508,6 +498,8 @@
 	dev = init_etherdev(NULL, 0);
 	if (!dev)
 		goto out;
+
+	SET_MODULE_OWNER(dev);
 
 	etherh_addr(dev->dev_addr, ec);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/Makefile linux/drivers/acorn/scsi/Makefile
--- v2.4.1/linux/drivers/acorn/scsi/Makefile	Sun Aug 13 09:54:15 2000
+++ linux/drivers/acorn/scsi/Makefile	Thu Feb  8 16:32:44 2001
@@ -4,7 +4,7 @@
 
 USE_STANDARD_AS_RULE := true
 
-L_TARGET	:= acorn-scsi.a
+O_TARGET	:= acorn-scsi.o
 
 obj-y		:=
 obj-m		:=
@@ -24,31 +24,7 @@
 obj-$(CONFIG_SCSI_POWERTECSCSI)	+= powertec.o fas216.o queue.o msgqueue.o
 obj-$(CONFIG_SCSI_EESOXSCSI)	+= eesox.o fas216.o queue.o msgqueue.o
 
-# Extract lists of the multi-part drivers.
-# The 'int-*' lists are intermediate files used to build the multi's.
-
-multi-y		:= $(filter $(list-multi), $(obj-y))
-multi-m		:= $(filter $(list-multi), $(obj-m))
-int-y		:= $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
-int-m		:= $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
-
-# Files that are both resident and modular; remove from modular.
-
-obj-m		:= $(filter-out $(obj-y), $(obj-m))
-int-m		:= $(filter-out $(int-y), $(int-m))
-
-# Take multi-part drivers out of obj-y and put components in.
-
-obj-y		:= $(filter-out $(list-multi), $(obj-y)) $(int-y)
-
-# Translate to Rules.make lists.
-
-L_OBJS		:= $(filter-out $(export-objs), $(obj-y))
-LX_OBJS		:= $(filter     $(export-objs), $(obj-y))
-M_OBJS		:= $(sort $(filter-out $(export-objs), $(obj-m)))
-MX_OBJS		:= $(sort $(filter     $(export-objs), $(obj-m)))
-
 include $(TOPDIR)/Rules.make
 
-acornscsi_mod.o: acornscsi.o acornscsi-io.o
-	$(LD) $(LD_RFLAG) -r -o $@ acornscsi.o acornscsi-io.o
+acornscsi_mod.o: $(acornscsi_mod-objs)
+	$(LD) -r -o $@ $(acornscsi_mod-objs)
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/arxescsi.c linux/drivers/acorn/scsi/arxescsi.c
--- v2.4.1/linux/drivers/acorn/scsi/arxescsi.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/arxescsi.c	Thu Feb  8 16:32:44 2001
@@ -16,6 +16,7 @@
  *  01-01-2000	SH	0.1.0   Added *real* pseudo dma writing
  *				(arxescsi_pseudo_dma_write)
  *  02-04-2000	RMK	0.1.1	Updated for new error handling code.
+ *  22-10-2000  SH		Updated for new registering scheme.
  */
 #include <linux/module.h>
 #include <linux/blk.h>
@@ -27,6 +28,7 @@
 #include <linux/unistd.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/dma.h>
 #include <asm/io.h>
@@ -416,8 +418,24 @@
 	return pos;
 }
 
-#ifdef MODULE
-Scsi_Host_Template driver_template = ARXEScsi;
+static Scsi_Host_Template arxescsi_template = ARXEScsi;
+
+static int __init init_arxe_scsi_driver(void)
+{
+        arxescsi_template.module = THIS_MODULE;
+	scsi_register_module(MODULE_SCSI_HA, &arxescsi_template);
+	if (arxescsi_template.present)
+		return 0;
+
+	scsi_unregister_module(MODULE_SCSI_HA, &arxescsi_template);
+	return -ENODEV;
+}
+
+static void __exit exit_arxe_scsi_driver(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &arxescsi_template);
+}
+
+module_init(init_arxe_scsi_driver);
+module_exit(exit_arxe_scsi_driver);
 
-#include "../../scsi/scsi_module.c"
-#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/cumana_1.c linux/drivers/acorn/scsi/cumana_1.c
--- v2.4.1/linux/drivers/acorn/scsi/cumana_1.c	Thu Nov 11 16:57:30 1999
+++ linux/drivers/acorn/scsi/cumana_1.c	Thu Feb  8 16:32:44 2001
@@ -51,24 +51,53 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/ioport.h>
-#include <linux/init.h>
 #include <linux/blk.h>
+#include <linux/init.h>
 
 #include <asm/ecard.h>
 #include <asm/io.h>
+#include <asm/irq.h>
 #include <asm/system.h>
 
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
-#include "cumana_1.h"
-#include "../../scsi/NCR5380.h"
 #include "../../scsi/constants.h"
 
+#include <scsi/scsicam.h>
+
+#define CUMANASCSI_PUBLIC_RELEASE 1
+
 static const card_ids cumanascsi_cids[] = {
 	{ MANU_CUMANA, PROD_CUMANA_SCSI_1 },
 	{ 0xffff, 0xffff }
 };
 
+#define NCR5380_implementation_fields \
+    int port, ctrl
+
+#define NCR5380_local_declare() \
+        struct Scsi_Host *_instance
+
+#define NCR5380_setup(instance) \
+        _instance = instance
+
+#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
+#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
+
+#define do_NCR5380_intr do_cumanascsi_intr
+#define NCR5380_queue_command cumanascsi_queue_command
+#define NCR5380_abort cumanascsi_abort
+#define NCR5380_reset cumanascsi_reset
+#define NCR5380_proc_info cumanascsi_proc_info
+
+int NCR5380_proc_info(char *buffer, char **start, off_t offset,
+		      int length, int hostno, int inout);
+
+#define BOARD_NORMAL	0
+#define BOARD_NCR53C400	1
+
+#include "../../scsi/NCR5380.h"
+
 /*
  * Function : cumanascsi_setup(char *str, int *ints)
  *
@@ -79,7 +108,8 @@
  *
  */
 
-void cumanascsi_setup(char *str, int *ints) {
+void cumanascsi_setup(char *str, int *ints)
+{
 }
 
 #define CUMANA_ADDRESS(card) (ecard_address((card), ECARD_IOC, ECARD_SLOW) + 0x800)
@@ -141,7 +171,7 @@
 	else
 	    printk (" %d", instance->irq);
 	printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d",
-	    CAN_QUEUE, CMD_PER_LUN, CUMANASCSI_PUBLIC_RELEASE);
+	    tpnt->can_queue, tpnt->cmd_per_lun, CUMANASCSI_PUBLIC_RELEASE);
 	printk("\nscsi%d:", instance->host_no);
 	NCR5380_print_options(instance);
 	printk("\n");
@@ -359,9 +389,38 @@
 
 #include "../../scsi/NCR5380.c"
 
-#ifdef MODULE
+static Scsi_Host_Template cumanascsi_template = {
+	module:			THIS_MODULE,
+	name:			"Cumana 16-bit SCSI",
+	detect:			cumanascsi_detect,
+	release:		cumanascsi_release,
+	info:			cumanascsi_info,
+	queuecommand:		cumanascsi_queue_command,
+	abort:			cumanascsi_abort,
+	reset:			cumanascsi_reset,
+	bios_param:		scsicam_bios_param,
+	can_queue:		16,
+	this_id:		7,
+	sg_tablesize:		SG_ALL,
+	cmd_per_lun:		2,
+	unchecked_isa_dma:	0,
+	use_clustering:		DISABLE_CLUSTERING
+};
 
-Scsi_Host_Template driver_template = CUMANA_NCR5380;
+static int __init cumanascsi_init(void)
+{
+	scsi_register_module(MODULE_SCSI_HA, &cumanascsi_template);
+	if (cumanascsi_template.present)
+		return 0;
 
-#include "../../scsi/scsi_module.c"
-#endif
+	scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
+	return -ENODEV;
+}
+
+static void __exit cumanascsi_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi_template);
+}
+
+module_init(cumanascsi_init);
+module_exit(cumanascsi_exit);
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/cumana_1.h linux/drivers/acorn/scsi/cumana_1.h
--- v2.4.1/linux/drivers/acorn/scsi/cumana_1.h	Sat Jul 18 11:55:24 1998
+++ linux/drivers/acorn/scsi/cumana_1.h	Wed Dec 31 16:00:00 1969
@@ -1,105 +0,0 @@
-/*
- * Cumana Generic NCR5380 driver defines
- *
- * Copyright 1993, Drew Eckhardt
- *	Visionary Computing
- *	(Unix and Linux consulting and custom programming)
- *	drew@colorado.edu
- *      +1 (303) 440-4894
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-/*
- * $Log: cumana_1.h,v $
- * Revision 1.1  1998/02/23 02:45:22  davem
- * Merge to 2.1.88
- *
- */
-
-#ifndef CUMANA_NCR5380_H
-#define CUMANA_NCR5380_H
-
-#define CUMANASCSI_PUBLIC_RELEASE 1
-
-
-#ifndef ASM
-int cumanascsi_abort (Scsi_Cmnd *);
-int cumanascsi_detect (Scsi_Host_Template *);
-int cumanascsi_release (struct Scsi_Host *);
-const char *cumanascsi_info (struct Scsi_Host *);
-int cumanascsi_reset(Scsi_Cmnd *, unsigned int);
-int cumanascsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int cumanascsi_proc_info (char *buffer, char **start, off_t offset,
-			int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#include <scsi/scsicam.h>
-
-#define CUMANA_NCR5380 {						\
-name:			"Cumana 16-bit SCSI",				\
-detect:			cumanascsi_detect,				\
-release:		cumanascsi_release,	/* Release */		\
-info:			cumanascsi_info,				\
-queuecommand:		cumanascsi_queue_command,			\
-abort:			cumanascsi_abort,			 	\
-reset:			cumanascsi_reset,				\
-bios_param:		scsicam_bios_param,	/* biosparam */		\
-can_queue:		CAN_QUEUE,		/* can queue */		\
-this_id:		7,			/* id */		\
-sg_tablesize:		SG_ALL,			/* sg_tablesize */	\
-cmd_per_lun:		CMD_PER_LUN,		/* cmd per lun */	\
-unchecked_isa_dma:	0,			/* unchecked_isa_dma */	\
-use_clustering:		DISABLE_CLUSTERING				\
-	}
-
-#ifndef HOSTS_C
-
-#define NCR5380_implementation_fields \
-    int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
-
-#define NCR5380_read(reg) cumanascsi_read(_instance, reg)
-#define NCR5380_write(reg, value) cumanascsi_write(_instance, reg, value)
-
-#define do_NCR5380_intr do_cumanascsi_intr
-#define NCR5380_queue_command cumanascsi_queue_command
-#define NCR5380_abort cumanascsi_abort
-#define NCR5380_reset cumanascsi_reset
-#define NCR5380_proc_info cumanascsi_proc_info
-
-#define BOARD_NORMAL	0
-#define BOARD_NCR53C400	1
-
-#endif /* ndef HOSTS_C */
-#endif /* ndef ASM */
-#endif /* CUMANA_NCR5380_H */
-
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/cumana_2.c linux/drivers/acorn/scsi/cumana_2.c
--- v2.4.1/linux/drivers/acorn/scsi/cumana_2.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/cumana_2.c	Thu Feb  8 16:32:44 2001
@@ -27,6 +27,7 @@
 #include <linux/stat.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
@@ -36,7 +37,9 @@
 
 #include "../../scsi/sd.h"
 #include "../../scsi/hosts.h"
-#include "cumana_2.h"
+#include "fas216.h"
+
+#include <scsi/scsicam.h>
 
 /* Configuration */
 #define CUMANASCSI2_XTALFREQ		40
@@ -89,6 +92,22 @@
  */
 int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
+#define NR_SG	256
+
+typedef struct {
+	FAS216_Info info;
+
+	/* other info... */
+	unsigned int	status;		/* card status register	*/
+	unsigned int	alatch;		/* Control register	*/
+	unsigned int	terms;		/* Terminator state	*/
+	unsigned int	dmaarea;	/* Pseudo DMA area	*/
+	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
+} CumanaScsi2_Info;
+
+#define CSTATUS_IRQ	(1 << 0)
+#define CSTATUS_DRQ	(1 << 1)
+
 /* Prototype: void cumanascsi_2_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on Cumana SCSI 2 card
  * Params   : ec    - expansion card structure
@@ -541,8 +560,42 @@
 	return pos;
 }
 
-#ifdef MODULE
-Scsi_Host_Template driver_template = CUMANASCSI_2;
+static Scsi_Host_Template cumanascsi2_template = {
+	module:				THIS_MODULE,
+	proc_info:			cumanascsi_2_proc_info,
+	name:				"Cumana SCSI II",
+	detect:				cumanascsi_2_detect,
+	release:			cumanascsi_2_release,
+	info:				cumanascsi_2_info,
+	bios_param:			scsicam_bios_param,
+	can_queue:			1,
+	this_id:			7,
+	sg_tablesize:			SG_ALL,
+	cmd_per_lun:			1,
+	use_clustering:			DISABLE_CLUSTERING,
+	command:			fas216_command,
+	queuecommand:			fas216_queue_command,
+	eh_host_reset_handler:		fas216_eh_host_reset,
+	eh_bus_reset_handler:		fas216_eh_bus_reset,
+	eh_device_reset_handler:	fas216_eh_device_reset,
+	eh_abort_handler:		fas216_eh_abort,
+	use_new_eh_code:		1
+};
 
-#include "../../scsi/scsi_module.c"
-#endif
+static int __init cumanascsi2_init(void)
+{
+	scsi_register_module(MODULE_SCSI_HA, &cumanascsi2_template);
+	if (cumanascsi2_template.present)
+		return 0;
+
+	scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi2_template);
+	return -ENODEV;
+}
+
+static void __exit cumanascsi2_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &cumanascsi2_template);
+}
+
+module_init(cumanascsi2_init);
+module_exit(cumanascsi2_exit);
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/cumana_2.h linux/drivers/acorn/scsi/cumana_2.h
--- v2.4.1/linux/drivers/acorn/scsi/cumana_2.h	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/cumana_2.h	Wed Dec 31 16:00:00 1969
@@ -1,93 +0,0 @@
-/*
- *  linux/drivers/acorn/scsi/cumana_2.h
- *
- *  Copyright (C) 1997-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Cumana SCSI II driver
- */
-#ifndef CUMANA_2_H
-#define CUMANA_2_H
-
-extern int cumanascsi_2_detect (Scsi_Host_Template *);
-extern int cumanascsi_2_release (struct Scsi_Host *);
-extern const char *cumanascsi_2_info (struct Scsi_Host *);
-extern int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset,
-					int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#ifndef CAN_QUEUE
-/*
- * Default queue size
- */
-#define CAN_QUEUE	1
-#endif
-
-#ifndef CMD_PER_LUN
-/*
- * Default queue size
- */
-#define CMD_PER_LUN	1
-#endif
-
-#ifndef SCSI_ID
-/*
- * Default SCSI host ID
- */
-#define SCSI_ID		7
-#endif
-
-#include <scsi/scsicam.h>
-
-#include "fas216.h"
-
-#define CUMANASCSI_2 {					\
-proc_info:			cumanascsi_2_proc_info,	\
-name:				"Cumana SCSI II",	\
-detect:				cumanascsi_2_detect,	\
-release:			cumanascsi_2_release,	\
-info:				cumanascsi_2_info,	\
-bios_param:			scsicam_bios_param,	\
-can_queue:			CAN_QUEUE,		\
-this_id:			SCSI_ID,		\
-sg_tablesize:			SG_ALL,			\
-cmd_per_lun:			CMD_PER_LUN,		\
-use_clustering:			DISABLE_CLUSTERING,	\
-command:			fas216_command,		\
-queuecommand:			fas216_queue_command,	\
-eh_host_reset_handler:		fas216_eh_host_reset,	\
-eh_bus_reset_handler:		fas216_eh_bus_reset,	\
-eh_device_reset_handler:	fas216_eh_device_reset,	\
-eh_abort_handler:		fas216_eh_abort,	\
-use_new_eh_code:		1			\
-	}
-
-#ifndef HOSTS_C
-
-#include <asm/dma.h>
-
-#define NR_SG	256
-
-typedef struct {
-	FAS216_Info info;
-
-	/* other info... */
-	unsigned int	status;		/* card status register	*/
-	unsigned int	alatch;		/* Control register	*/
-	unsigned int	terms;		/* Terminator state	*/
-	unsigned int	dmaarea;	/* Pseudo DMA area	*/
-	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
-} CumanaScsi2_Info;
-
-#define CSTATUS_IRQ	(1 << 0)
-#define CSTATUS_DRQ	(1 << 1)
-
-#endif /* HOSTS_C */
-
-#endif /* CUMANASCSI_2_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/ecoscsi.c linux/drivers/acorn/scsi/ecoscsi.c
--- v2.4.1/linux/drivers/acorn/scsi/ecoscsi.c	Thu Nov 11 16:57:30 1999
+++ linux/drivers/acorn/scsi/ecoscsi.c	Thu Feb  8 16:32:44 2001
@@ -53,10 +53,11 @@
 
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
-#include "ecoscsi.h"
 #include "../../scsi/NCR5380.h"
 #include "../../scsi/constants.h"
 
+#define ECOSCSI_PUBLIC_RELEASE 1
+
 static char ecoscsi_read(struct Scsi_Host *instance, int reg)
 {
   int iobase = instance->io_port;
@@ -231,11 +232,63 @@
 #endif
 #undef STAT
 
+#ifndef HOSTS_C
+#define NCR5380_implementation_fields \
+    int port, ctrl
+
+#define NCR5380_local_declare() \
+        struct Scsi_Host *_instance
+
+#define NCR5380_setup(instance) \
+        _instance = instance
+
+#define NCR5380_read(reg) ecoscsi_read(_instance, reg)
+#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
+
+#define do_NCR5380_intr do_ecoscsi_intr
+#define NCR5380_queue_command ecoscsi_queue_command
+#define NCR5380_abort ecoscsi_abort
+#define NCR5380_reset ecoscsi_reset
+#define NCR5380_proc_info ecoscsi_proc_info
+
+int NCR5380_proc_info(char *buffer, char **start, off_t offset,
+		      int length, int hostno, int inout);
+
+#define BOARD_NORMAL	0
+#define BOARD_NCR53C400	1
+
 #include "../../scsi/NCR5380.c"
 
-#ifdef MODULE
+static Scsi_Host_Template ecoscsi_template =  {
+	module:		THIS_MODULE,
+	name:		"Serial Port EcoSCSI NCR5380",
+	detect:		ecoscsi_detect,
+	release:	ecoscsi_release,
+	info:		ecoscsi_info,
+	queuecommand:	ecoscsi_queue_command,
+	abort:		ecoscsi_abort,
+	reset:		ecoscsi_reset,
+	can_queue:	16,
+	this_id:	7,
+	sg_tablesize:	SG_ALL,
+	cmd_per_lun:	2,
+	use_clustering:	DISABLE_CLUSTERING
+};
+
+static int __init ecoscsi_init(void)
+{
+	scsi_register_module(MODULE_SCSI_HA, &ecoscsi_template);
+	if (ecoscsi_template.present)
+		return 0;
+
+	scsi_unregister_module(MODULE_SCSI_HA, &ecoscsi_template);
+	return -ENODEV;
+}
 
-Scsi_Host_Template driver_template = ECOSCSI_NCR5380;
+static void __exit ecoscsi_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &ecoscsi_template);
+}
 
-#include "../../scsi/scsi_module.c"
-#endif
+module_init(ecoscsi_init);
+module_exit(ecoscsi_exit);
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/ecoscsi.h linux/drivers/acorn/scsi/ecoscsi.h
--- v2.4.1/linux/drivers/acorn/scsi/ecoscsi.h	Sat Jul 18 11:55:24 1998
+++ linux/drivers/acorn/scsi/ecoscsi.h	Wed Dec 31 16:00:00 1969
@@ -1,96 +0,0 @@
-/*
- * Cumana Generic NCR5380 driver defines
- *
- * Copyright 1995, Russell King
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-/*
- * $Log: ecoscsi.h,v $
- * Revision 1.1  1998/02/23 02:45:24  davem
- * Merge to 2.1.88
- *
- */
-
-#ifndef ECOSCSI_NCR5380_H
-#define ECOSCSI_NCR5380_H
-
-#define ECOSCSI_PUBLIC_RELEASE 1
-
-
-#ifndef ASM
-int ecoscsi_abort (Scsi_Cmnd *);
-int ecoscsi_detect (Scsi_Host_Template *);
-int ecoscsi_release (struct Scsi_Host *);
-const char *ecoscsi_info (struct Scsi_Host *);
-int ecoscsi_reset(Scsi_Cmnd *, unsigned int);
-int ecoscsi_queue_command (Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int ecoscsi_proc_info (char *buffer, char **start, off_t offset,
-			int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#define ECOSCSI_NCR5380 {					\
-name:		"Serial Port EcoSCSI NCR5380",			\
-detect:		ecoscsi_detect,					\
-release:	ecoscsi_release,				\
-info:		ecoscsi_info,					\
-queuecommand:	ecoscsi_queue_command,				\
-abort:		ecoscsi_abort, 					\
-reset:		ecoscsi_reset,					\
-can_queue:	CAN_QUEUE,		/* can queue */		\
-this_id:	7,			/* id */		\
-sg_tablesize:	SG_ALL,						\
-cmd_per_lun:	CMD_PER_LUN,		/* cmd per lun */	\
-use_clustering:	DISABLE_CLUSTERING				\
-	}
-
-#ifndef HOSTS_C
-#define NCR5380_implementation_fields \
-    int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
-
-#define NCR5380_read(reg) ecoscsi_read(_instance, reg)
-#define NCR5380_write(reg, value) ecoscsi_write(_instance, reg, value)
-
-#define do_NCR5380_intr do_ecoscsi_intr
-#define NCR5380_queue_command ecoscsi_queue_command
-#define NCR5380_abort ecoscsi_abort
-#define NCR5380_reset ecoscsi_reset
-#define NCR5380_proc_info ecoscsi_proc_info
-
-#define BOARD_NORMAL	0
-#define BOARD_NCR53C400	1
-
-#endif /* ndef HOSTS_C */
-#endif /* ndef ASM */
-#endif /* ECOSCSI_NCR5380_H */
-
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/eesox.c linux/drivers/acorn/scsi/eesox.c
--- v2.4.1/linux/drivers/acorn/scsi/eesox.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/eesox.c	Thu Feb  8 16:32:44 2001
@@ -33,6 +33,7 @@
 #include <linux/stat.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
@@ -42,7 +43,9 @@
 
 #include "../../scsi/sd.h"
 #include "../../scsi/hosts.h"
-#include "eesox.h"
+#include "fas216.h"
+
+#include <scsi/scsicam.h>
 
 /* Configuration */
 #define EESOX_XTALFREQ		40
@@ -87,6 +90,22 @@
  */
 int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
+#define NR_SG	256
+
+struct control {
+	unsigned int	io_port;
+	unsigned int	control;
+};
+
+typedef struct {
+	FAS216_Info info;
+
+	struct control control;
+
+	unsigned int	dmaarea;	/* Pseudo DMA area	*/
+	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
+} EESOXScsi_Info;
+
 /* Prototype: void eesoxscsi_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on EESOX SCSI card
  * Params   : ec    - expansion card structure
@@ -543,8 +562,43 @@
 	return pos;
 }
 
-#ifdef MODULE
-Scsi_Host_Template driver_template = EESOXSCSI;
+static Scsi_Host_Template eesox_template = {
+	module:				THIS_MODULE,
+	proc_info:			eesoxscsi_proc_info,
+	name:				"EESOX SCSI",
+	detect:				eesoxscsi_detect,
+	release:			eesoxscsi_release,
+	info:				eesoxscsi_info,
+	bios_param:			scsicam_bios_param,
+	can_queue:			1,
+	this_id:			7,
+	sg_tablesize:			SG_ALL,
+	cmd_per_lun:			1,
+	use_clustering:			DISABLE_CLUSTERING,
+	command:			fas216_command,
+	queuecommand:			fas216_queue_command,
+	eh_host_reset_handler:		fas216_eh_host_reset,
+	eh_bus_reset_handler:		fas216_eh_bus_reset,
+	eh_device_reset_handler:	fas216_eh_device_reset,
+	eh_abort_handler:		fas216_eh_abort,
+	use_new_eh_code:		1
+};
+
+static int __init eesox_init(void)
+{
+	scsi_register_module(MODULE_SCSI_HA, &eesox_template);
+	if (eesox_template.present)
+		return 0;
+
+	scsi_unregister_module(MODULE_SCSI_HA, &eesox_template);
+	return -ENODEV;
+}
+
+static void __exit eesox_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &eesox_template);
+}
+
+module_init(eesox_init);
+module_exit(eesox_exit);
 
-#include "../../scsi/scsi_module.c"
-#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/eesox.h linux/drivers/acorn/scsi/eesox.h
--- v2.4.1/linux/drivers/acorn/scsi/eesox.h	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/eesox.h	Wed Dec 31 16:00:00 1969
@@ -1,90 +0,0 @@
-/*
- *  linux/drivers/acorn/scsi/eesox.h
- *
- *  Copyright (C) 1997-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  EESOX SCSI driver
- */
-#ifndef EESOXSCSI_H
-#define EESOXSCSI_H
-
-extern int eesoxscsi_detect (Scsi_Host_Template *);
-extern int eesoxscsi_release (struct Scsi_Host *);
-extern const char *eesoxscsi_info (struct Scsi_Host *);
-extern int eesoxscsi_proc_info (char *buffer, char **start, off_t offset,
-					int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#ifndef CAN_QUEUE
-/*
- * Default queue size
- */
-#define CAN_QUEUE	1
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN	1
-#endif
-
-#ifndef SCSI_ID
-/*
- * Default SCSI host ID
- */
-#define SCSI_ID		7
-#endif
-
-#include <scsi/scsicam.h>
-
-#include "fas216.h"
-
-#define EESOXSCSI {					\
-proc_info:			eesoxscsi_proc_info,	\
-name:				"EESOX SCSI",		\
-detect:				eesoxscsi_detect,	\
-release:			eesoxscsi_release,	\
-info:				eesoxscsi_info,		\
-bios_param:			scsicam_bios_param,	\
-can_queue:			CAN_QUEUE,		\
-this_id:			SCSI_ID,		\
-sg_tablesize:			SG_ALL,			\
-cmd_per_lun:			CAN_QUEUE,		\
-use_clustering:			DISABLE_CLUSTERING,	\
-command:			fas216_command,		\
-queuecommand:			fas216_queue_command,	\
-eh_host_reset_handler:		fas216_eh_host_reset,	\
-eh_bus_reset_handler:		fas216_eh_bus_reset,	\
-eh_device_reset_handler:	fas216_eh_device_reset,	\
-eh_abort_handler:		fas216_eh_abort,	\
-use_new_eh_code:		1			\
-	}
-
-#ifndef HOSTS_C
-
-#include <asm/dma.h>
-
-#define NR_SG	256
-
-struct control {
-	unsigned int	io_port;
-	unsigned int	control;
-};
-
-typedef struct {
-	FAS216_Info info;
-
-	struct control control;
-
-	unsigned int	dmaarea;	/* Pseudo DMA area	*/
-	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
-} EESOXScsi_Info;
-
-#endif /* HOSTS_C */
-
-#endif /* EESOXSCSI_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/fas216.c linux/drivers/acorn/scsi/fas216.c
--- v2.4.1/linux/drivers/acorn/scsi/fas216.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/fas216.c	Thu Feb  8 16:32:44 2001
@@ -47,6 +47,7 @@
 #include <linux/unistd.h>
 #include <linux/stat.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/dma.h>
 #include <asm/io.h>
@@ -2767,12 +2768,12 @@
 EXPORT_SYMBOL(fas216_print_device);
 
 #ifdef MODULE
-int init_module(void)
+int __init init_module(void)
 {
 	return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
 }
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/msgqueue.c linux/drivers/acorn/scsi/msgqueue.c
--- v2.4.1/linux/drivers/acorn/scsi/msgqueue.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/msgqueue.c	Thu Feb  8 16:32:44 2001
@@ -12,6 +12,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/stddef.h>
+#include <linux/init.h>
 
 #include "msgqueue.h"
 
@@ -128,7 +129,7 @@
 
 		va_start(ap, length);
 		for (i = 0; i < length; i++)
-			mq->msg.msg[i] = va_arg(ap, unsigned char);
+			mq->msg.msg[i] = va_arg(ap, unsigned int);
 		va_end(ap);
 
 		mq->msg.length = length;
@@ -169,12 +170,12 @@
 EXPORT_SYMBOL(msgqueue_flush);
 
 #ifdef MODULE
-int init_module(void)
+int __init init_module(void)
 {
 	return 0;
 }
 
-void cleanup_module(void)
+void __exit cleanup_module(void)
 {
 }
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/oak.c linux/drivers/acorn/scsi/oak.c
--- v2.4.1/linux/drivers/acorn/scsi/oak.c	Thu Nov 11 16:57:30 1999
+++ linux/drivers/acorn/scsi/oak.c	Thu Feb  8 16:32:44 2001
@@ -59,10 +59,35 @@
 
 #include "../../scsi/scsi.h"
 #include "../../scsi/hosts.h"
-#include "oak.h"
-#include "../../scsi/NCR5380.h"
 #include "../../scsi/constants.h"
 
+#define OAKSCSI_PUBLIC_RELEASE 1
+
+#define NCR5380_read(reg)		oakscsi_read(_instance, reg)
+#define NCR5380_write(reg, value)	oakscsi_write(_instance, reg, value)
+#define do_NCR5380_intr			do_oakscsi_intr
+#define NCR5380_queue_command		oakscsi_queue_command
+#define NCR5380_abort			oakscsi_abort
+#define NCR5380_reset			oakscsi_reset
+#define NCR5380_proc_info		oakscsi_proc_info
+
+int NCR5380_proc_info(char *buffer, char **start, off_t offset,
+		      int length, int hostno, int inout);
+
+#define NCR5380_implementation_fields \
+	int port, ctrl
+
+#define NCR5380_local_declare() \
+        struct Scsi_Host *_instance
+
+#define NCR5380_setup(instance) \
+        _instance = instance
+
+#define BOARD_NORMAL	0
+#define BOARD_NCR53C400	1
+
+#include "../../scsi/NCR5380.h"
+
 #undef START_DMA_INITIATOR_RECEIVE_REG
 #define START_DMA_INITIATOR_RECEIVE_REG (7 + 128)
 
@@ -129,7 +154,7 @@
 	else
 	    printk (" %d", instance->irq);
 	printk(" options CAN_QUEUE=%d  CMD_PER_LUN=%d release=%d",
-	    CAN_QUEUE, CMD_PER_LUN, OAKSCSI_PUBLIC_RELEASE);
+	    tpnt->can_queue, tpnt->cmd_per_lun, OAKSCSI_PUBLIC_RELEASE);
 	printk("\nscsi%d:", instance->host_no);
 	NCR5380_print_options(instance);
 	printk("\n");
@@ -226,9 +251,37 @@
 
 #include "../../scsi/NCR5380.c"
 
-#ifdef MODULE
+static Scsi_Host_Template oakscsi_template = {
+	module:		THIS_MODULE,
+	proc_info:	oakscsi_proc_info,
+	name:		"Oak 16-bit SCSI",
+	detect:		oakscsi_detect,
+	release:	oakscsi_release,
+	info:		oakscsi_info,
+	queuecommand:	oakscsi_queue_command,
+	abort:		oakscsi_abort,
+	reset:		oakscsi_reset,
+	can_queue:	16,
+	this_id:	7,
+	sg_tablesize:	SG_ALL,
+	cmd_per_lun:	2,
+	use_clustering:	DISABLE_CLUSTERING
+};
 
-Scsi_Host_Template driver_template = OAK_NCR5380;
+static int __init oakscsi_init(void)
+{
+	scsi_register_module(MODULE_SCSI_HA, &oakscsi_template);
+	if (oakscsi_template.present)
+		return 0;
 
-#include "../../scsi/scsi_module.c"
-#endif
+	scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
+	return -ENODEV;
+}
+
+static void __exit oakscsi_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &oakscsi_template);
+}
+
+module_init(oakscsi_init);
+module_exit(oakscsi_exit);
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/oak.h linux/drivers/acorn/scsi/oak.h
--- v2.4.1/linux/drivers/acorn/scsi/oak.h	Sat Jul 18 11:55:24 1998
+++ linux/drivers/acorn/scsi/oak.h	Wed Dec 31 16:00:00 1969
@@ -1,100 +0,0 @@
-/*
- * Cumana Generic NCR5380 driver defines
- *
- * Copyright 1993, Drew Eckhardt
- *	Visionary Computing
- *	(Unix and Linux consulting and custom programming)
- *	drew@colorado.edu
- *      +1 (303) 440-4894
- *
- * ALPHA RELEASE 1.
- *
- * For more information, please consult
- *
- * NCR 5380 Family
- * SCSI Protocol Controller
- * Databook
- *
- * NCR Microelectronics
- * 1635 Aeroplaza Drive
- * Colorado Springs, CO 80916
- * 1+ (719) 578-3400
- * 1+ (800) 334-5454
- */
-
-/*
- * $Log: oak.h,v $
- * Revision 1.1  1998/02/23 02:45:27  davem
- * Merge to 2.1.88
- *
- */
-
-#ifndef OAK_NCR5380_H
-#define OAK_NCR5380_H
-
-#define OAKSCSI_PUBLIC_RELEASE 1
-
-
-#ifndef ASM
-int oakscsi_abort(Scsi_Cmnd *);
-int oakscsi_detect(Scsi_Host_Template *);
-int oakscsi_release(struct Scsi_Host *);
-const char *oakscsi_info(struct Scsi_Host *);
-int oakscsi_reset(Scsi_Cmnd *, unsigned int);
-int oakscsi_queue_command(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));
-int oakscsi_proc_info (char *buffer, char **start, off_t off,
-		int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN 2
-#endif
-
-#ifndef CAN_QUEUE
-#define CAN_QUEUE 16
-#endif
-
-#define OAK_NCR5380 {						\
-proc_info:	oakscsi_proc_info,				\
-name:		"Oak 16-bit SCSI",				\
-detect:		oakscsi_detect,					\
-release:	oakscsi_release,	/* Release */		\
-info:		oakscsi_info,					\
-queuecommand:	oakscsi_queue_command,				\
-abort:		oakscsi_abort, 					\
-reset:		oakscsi_reset,					\
-can_queue:	CAN_QUEUE,		/* can queue */		\
-this_id:	7,			/* id */		\
-sg_tablesize:	SG_ALL,			/* sg_tablesize */	\
-cmd_per_lun:	CMD_PER_LUN,		/* cmd per lun */	\
-use_clustering:	DISABLE_CLUSTERING				\
-	}
-
-#ifndef HOSTS_C
-#define NCR5380_implementation_fields \
-	int port, ctrl
-
-#define NCR5380_local_declare() \
-        struct Scsi_Host *_instance
-
-#define NCR5380_setup(instance) \
-        _instance = instance
-
-#define NCR5380_read(reg)		oakscsi_read(_instance, reg)
-#define NCR5380_write(reg, value)	oakscsi_write(_instance, reg, value)
-#define do_NCR5380_intr			do_oakscsi_intr
-#define NCR5380_queue_command		oakscsi_queue_command
-#define NCR5380_abort			oakscsi_abort
-#define NCR5380_reset			oakscsi_reset
-#define NCR5380_proc_info		oakscsi_proc_info
-
-#define BOARD_NORMAL	0
-#define BOARD_NCR53C400	1
-
-#endif /* else def HOSTS_C */
-#endif /* ndef ASM */
-#endif /* OAK_NCR5380_H */
-
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/powertec.c linux/drivers/acorn/scsi/powertec.c
--- v2.4.1/linux/drivers/acorn/scsi/powertec.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/powertec.c	Thu Feb  8 16:32:44 2001
@@ -30,6 +30,7 @@
 #include <linux/stat.h>
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <linux/init.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
@@ -39,7 +40,9 @@
 
 #include "../../scsi/sd.h"
 #include "../../scsi/hosts.h"
-#include "powertec.h"
+#include "fas216.h"
+
+#include <scsi/scsicam.h>
 
 /* Configuration */
 #define POWERTEC_XTALFREQ	40
@@ -86,6 +89,20 @@
  */
 int term[MAX_ECARDS] = { 1, 1, 1, 1, 1, 1, 1, 1 };
 
+#define NR_SG	256
+
+typedef struct {
+	FAS216_Info info;
+
+	struct {
+		unsigned int term_port;
+		unsigned int terms;
+	} control;
+
+	/* other info... */
+	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
+} PowerTecScsi_Info;
+
 /* Prototype: void powertecscsi_irqenable(ec, irqnr)
  * Purpose  : Enable interrupts on Powertec SCSI card
  * Params   : ec    - expansion card structure
@@ -445,8 +462,42 @@
 	return pos;
 }
 
-#ifdef MODULE
-Scsi_Host_Template driver_template = POWERTECSCSI;
+static Scsi_Host_Template powertecscsi_template = {
+	module:				THIS_MODULE,
+	proc_info:			powertecscsi_proc_info,
+	name:				"PowerTec SCSI",
+	detect:				powertecscsi_detect,
+	release:			powertecscsi_release,
+	info:				powertecscsi_info,
+	bios_param:			scsicam_bios_param,
+	can_queue:			1,
+	this_id:			7,
+	sg_tablesize:			SG_ALL,
+	cmd_per_lun:			1,
+	use_clustering:			ENABLE_CLUSTERING,
+	command:			fas216_command,
+	queuecommand:			fas216_queue_command,
+	eh_host_reset_handler:		fas216_eh_host_reset,
+	eh_bus_reset_handler:		fas216_eh_bus_reset,
+	eh_device_reset_handler:	fas216_eh_device_reset,
+	eh_abort_handler:		fas216_eh_abort,
+	use_new_eh_code:		1
+};
+
+static int __init powertecscsi_init(void)
+{
+	scsi_register_module(MODULE_SCSI_HA, &powertecscsi_template);
+	if (powertecscsi_template.present)
+		return 0;
+
+	scsi_unregister_module(MODULE_SCSI_HA, &powertecscsi_template);
+	return -ENODEV;
+}
+
+static void __exit powertecscsi_exit(void)
+{
+	scsi_unregister_module(MODULE_SCSI_HA, &powertecscsi_template);
+}
 
-#include "../../scsi/scsi_module.c"
-#endif
+module_init(powertecscsi_init);
+module_exit(powertecscsi_exit);
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/powertec.h linux/drivers/acorn/scsi/powertec.h
--- v2.4.1/linux/drivers/acorn/scsi/powertec.h	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/powertec.h	Wed Dec 31 16:00:00 1969
@@ -1,88 +0,0 @@
-/*
- *  linux/drivers/acorn/scsi/powertec.h
- *
- *  Copyright (C) 1997-2000 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  PowerTec SCSI driver
- */
-#ifndef POWERTECSCSI_H
-#define POWERTECSCSI_H
-
-extern int powertecscsi_detect (Scsi_Host_Template *);
-extern int powertecscsi_release (struct Scsi_Host *);
-extern const char *powertecscsi_info (struct Scsi_Host *);
-extern int powertecscsi_proc_info (char *buffer, char **start, off_t offset,
-					int length, int hostno, int inout);
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#ifndef CAN_QUEUE
-/*
- * Default queue size
- */
-#define CAN_QUEUE	1
-#endif
-
-#ifndef CMD_PER_LUN
-#define CMD_PER_LUN	1
-#endif
-
-#ifndef SCSI_ID
-/*
- * Default SCSI host ID
- */
-#define SCSI_ID		7
-#endif
-
-#include <scsi/scsicam.h>
-
-#include "fas216.h"
-
-#define POWERTECSCSI {					\
-proc_info:			powertecscsi_proc_info,	\
-name:				"PowerTec SCSI",	\
-detect:				powertecscsi_detect,	\
-release:			powertecscsi_release,	\
-info:				powertecscsi_info,	\
-bios_param:			scsicam_bios_param,	\
-can_queue:			CAN_QUEUE,		\
-this_id:			SCSI_ID,		\
-sg_tablesize:			SG_ALL,			\
-cmd_per_lun:			CMD_PER_LUN,		\
-use_clustering:			ENABLE_CLUSTERING,	\
-command:			fas216_command,		\
-queuecommand:			fas216_queue_command,	\
-eh_host_reset_handler:		fas216_eh_host_reset,	\
-eh_bus_reset_handler:		fas216_eh_bus_reset,	\
-eh_device_reset_handler:	fas216_eh_device_reset,	\
-eh_abort_handler:		fas216_eh_abort,	\
-use_new_eh_code:		1			\
-	}
-
-#ifndef HOSTS_C
-
-#include <asm/dma.h>
-
-#define NR_SG	256
-
-typedef struct {
-	FAS216_Info info;
-
-	struct {
-		unsigned int term_port;
-		unsigned int terms;
-	} control;
-
-	/* other info... */
-	struct scatterlist sg[NR_SG];	/* Scatter DMA list	*/
-} PowerTecScsi_Info;
-
-#endif /* HOSTS_C */
-
-#endif /* POWERTECSCSI_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/acorn/scsi/queue.c linux/drivers/acorn/scsi/queue.c
--- v2.4.1/linux/drivers/acorn/scsi/queue.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/acorn/scsi/queue.c	Fri Feb  9 11:30:22 2001
@@ -18,9 +18,10 @@
 #include <linux/blk.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
+#include <linux/init.h>
 
 #include "../../scsi/scsi.h"
 
@@ -295,12 +296,12 @@
 EXPORT_SYMBOL(queue_probetgtlun);
 
 #ifdef MODULE
-int init_module (void)
+int __init init_module (void)
 {
 	return 0;
 }
 
-void cleanup_module (void)
+void __exit cleanup_module (void)
 {
 }
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/cmbatt.c linux/drivers/acpi/cmbatt.c
--- v2.4.1/linux/drivers/acpi/cmbatt.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/cmbatt.c	Fri Feb  9 11:45:58 2001
@@ -24,6 +24,8 @@
  * - parse returned data from _BST and _BIF
  * Andy Grover <andrew.grover@intel.com> 2000-12-8
  * - improved proc interface
+ * Pavel Machek <pavel@suse.cz> 2001-1-31
+ * - fixed oops on NULLs in return from _BIF
  */
 
 #include <linux/kernel.h>
@@ -44,6 +46,8 @@
 #define MAX_CM_BATTERIES	0x8
 #define MAX_BATT_STRLEN		0x20
 
+#define Xstrncpy(a, b, c) if (b) strncpy(a,b,c); else strncpy(a, "unknown", c)
+
 struct cmbatt_info
 {
 	u32  power_unit;
@@ -163,11 +167,11 @@
 	result->battery_capacity_granularity_1=objs[7].integer.value;
 	result->battery_capacity_granularity_2=objs[8].integer.value;
 
-	/* BUG: trailing NULL issue */
-	strncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
-	strncpy(result->serial_number, objs[10].string.pointer, MAX_BATT_STRLEN-1);
-	strncpy(result->battery_type, objs[11].string.pointer, MAX_BATT_STRLEN-1);
-	strncpy(result->oem_info, objs[12].string.pointer, MAX_BATT_STRLEN-1);
+ 	/* BUG: trailing NULL issue */
+	Xstrncpy(result->model_number, objs[9].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->serial_number, objs[10].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->battery_type, objs[11].string.pointer, MAX_BATT_STRLEN-1);
+	Xstrncpy(result->oem_info, objs[12].string.pointer, MAX_BATT_STRLEN-1);
 	
 	kfree(buf.pointer);
 
@@ -246,38 +250,32 @@
 		goto end;
 	}
 
-	if (info->last_full_capacity == ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Unknown last full capacity\n");
-	else
-		p += sprintf(p, "Last Full Capacity %x %s /hr\n", 
+	if (info->last_full_capacity != ACPI_BATT_UNKNOWN)
+		p += sprintf(p, "Last Full Capacity: %d %sh\n", 
 		     info->last_full_capacity, batt_list[batt_num].power_unit);
 
-	if (info->design_capacity == ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Unknown Design Capacity\n");
-	else
-		p += sprintf(p, "Design Capacity %x %s /hr\n", 
+	if (info->design_capacity != ACPI_BATT_UNKNOWN)
+		p += sprintf(p, "Design Capacity:    %d %sh\n", 
 		     info->design_capacity, batt_list[batt_num].power_unit);
 	
 	if (info->battery_technology)
-		p += sprintf(p, "Secondary Battery Technology\n");
+		p += sprintf(p, "Battery Technology: Secondary\n");
 	else
-		p += sprintf(p, "Primary Battery Technology\n");
+		p += sprintf(p, "Battery Technology: Primary\n");
 	
-	if (info->design_voltage == ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Unknown Design Voltage\n");
-	else
-		p += sprintf(p, "Design Voltage %x mV\n", 
+	if (info->design_voltage != ACPI_BATT_UNKNOWN)
+		p += sprintf(p, "Design Voltage:     %d mV\n", 
 		     info->design_voltage);
 	
-	p += sprintf(p, "Design Capacity Warning %d\n",
-		info->design_capacity_warning);
-	p += sprintf(p, "Design Capacity Low %d\n",
-		info->design_capacity_low);
-	p += sprintf(p, "Battery Capacity Granularity 1 %d\n",
+	p += sprintf(p, "Design Capacity Warning:    %d %sh\n",
+		info->design_capacity_warning, batt_list[batt_num].power_unit);
+	p += sprintf(p, "Design Capacity Low:        %d %sh\n",
+		info->design_capacity_low, batt_list[batt_num].power_unit);
+	p += sprintf(p, "Battery Capacity Granularity 1: %d\n",
 		info->battery_capacity_granularity_1);
-	p += sprintf(p, "Battery Capacity Granularity 2 %d\n",
+	p += sprintf(p, "Battery Capacity Granularity 2: %d\n",
 		info->battery_capacity_granularity_2);
-	p += sprintf(p, "model number %s\nserial number %s\nbattery type %s\nOEM info %s\n",
+	p += sprintf(p, "Model number; %s\nSerial number: %s\nBattery type: %s\nOEM info: %s\n",
 		info->model_number,info->serial_number,
 		info->battery_type,info->oem_info);
 end:
@@ -308,38 +306,28 @@
 		goto end;
 	}
 
-	printk("getting batt status\n");
-
 	if (acpi_get_battery_status(batt_list[batt_num].handle, &status) != AE_OK) {
 		printk(KERN_ERR "Cmbatt: acpi_get_battery_status failed\n");
 		goto end;
 	}
 
-	p += sprintf(p, "Remaining Capacity: %x\n", status.remaining_capacity);
+	p += sprintf(p, "Battery discharging:        %s\n",
+		     (status.state & 0x1)?"yes":"no");
+	p += sprintf(p, "Battery charging:           %s\n",
+		     (status.state & 0x2)?"yes":"no");
+	p += sprintf(p, "Battery critically low:     %s\n",
+		     (status.state & 0x4)?"yes":"no");
+
+	if (status.present_rate != ACPI_BATT_UNKNOWN)
+		p += sprintf(p, "Battery rate:               %d %s\n",
+			status.present_rate, batt_list[batt_num].power_unit);
 
-	if (status.state & 0x1)
-		p += sprintf(p, "Battery discharging\n");
-	if (status.state & 0x2)
-		p += sprintf(p, "Battery charging\n");
-	if (status.state & 0x4)
-		p += sprintf(p, "Battery critically low\n");
-
-	if (status.present_rate == ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Battery rate unknown\n");
-	else
-		p += sprintf(p, "Battery rate %x\n",
-			status.present_rate);
-
-	if (status.remaining_capacity == ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Battery capacity unknown\n");
-	else
-		p += sprintf(p, "Battery capacity %x %s\n",
+	if (status.remaining_capacity != ACPI_BATT_UNKNOWN)
+		p += sprintf(p, "Battery capacity:           %d %sh\n",
 			status.remaining_capacity, batt_list[batt_num].power_unit);
 
-	if (status.present_voltage == ACPI_BATT_UNKNOWN)
-		p += sprintf(p, "Battery voltage unknown\n");
-	else
-		p += sprintf(p, "Battery voltage %x volts\n",
+	if (status.present_voltage != ACPI_BATT_UNKNOWN)
+		p += sprintf(p, "Battery voltage:            %d mV\n",
 			status.present_voltage);
 
 end:
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/common/cmcopy.c linux/drivers/acpi/common/cmcopy.c
--- v2.4.1/linux/drivers/acpi/common/cmcopy.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/common/cmcopy.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: cmcopy - Internal to external object translation utilities
- *              $Revision: 62 $
+ *              $Revision: 66 $
  *
  *****************************************************************************/
 
@@ -27,51 +27,39 @@
 #include "acpi.h"
 #include "acinterp.h"
 #include "acnamesp.h"
+#include "amlcode.h"
 
 
 #define _COMPONENT          MISCELLANEOUS
 	 MODULE_NAME         ("cmcopy")
 
 
-typedef struct search_st
-{
-	ACPI_OPERAND_OBJECT         *internal_obj;
-	u32                         index;
-	ACPI_OBJECT                 *external_obj;
-
-} PKG_SEARCH_INFO;
-
-
-/* Used to traverse nested packages */
-
-PKG_SEARCH_INFO                 level[MAX_PACKAGE_DEPTH];
-
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_build_external_simple_object
+ * FUNCTION:    Acpi_cm_copy_isimple_to_esimple
  *
- * PARAMETERS:  *Internal_obj   - Pointer to the object we are examining
- *              *Buffer         - Where the object is returned
- *              *Space_used     - Where the data length is returned
+ * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
+ *              *Buffer             - Where the object is returned
+ *              *Space_used         - Where the data length is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to place a simple object in a user
- *                  buffer.
+ *              buffer.
  *
  *              The buffer is assumed to have sufficient space for the object.
  *
  ******************************************************************************/
 
 static ACPI_STATUS
-acpi_cm_build_external_simple_object (
-	ACPI_OPERAND_OBJECT     *internal_obj,
-	ACPI_OBJECT             *external_obj,
+acpi_cm_copy_isimple_to_esimple (
+	ACPI_OPERAND_OBJECT     *internal_object,
+	ACPI_OBJECT             *external_object,
 	u8                      *data_space,
 	u32                     *buffer_space_used)
 {
 	u32                     length = 0;
-	u8                      *source_ptr = NULL;
+	ACPI_STATUS             status = AE_OK;
 
 
 	/*
@@ -79,116 +67,221 @@
 	 * package element
 	 */
 
-	if (!internal_obj) {
+	if (!internal_object) {
 		*buffer_space_used = 0;
 		return (AE_OK);
 	}
 
 	/* Always clear the external object */
 
-	MEMSET (external_obj, 0, sizeof (ACPI_OBJECT));
+	MEMSET (external_object, 0, sizeof (ACPI_OBJECT));
 
 	/*
 	 * In general, the external object will be the same type as
 	 * the internal object
 	 */
 
-	external_obj->type = internal_obj->common.type;
+	external_object->type = internal_object->common.type;
 
 	/* However, only a limited number of external types are supported */
 
-	switch (external_obj->type)
+	switch (internal_object->common.type)
 	{
 
 	case ACPI_TYPE_STRING:
 
-		length = internal_obj->string.length + 1;
-		external_obj->string.length = internal_obj->string.length;
-		external_obj->string.pointer = (NATIVE_CHAR *) data_space;
-		source_ptr = (u8 *) internal_obj->string.pointer;
+		length = internal_object->string.length + 1;
+		external_object->string.length = internal_object->string.length;
+		external_object->string.pointer = (NATIVE_CHAR *) data_space;
+		MEMCPY ((void *) data_space, (void *) internal_object->string.pointer, length);
 		break;
 
 
 	case ACPI_TYPE_BUFFER:
 
-		length = internal_obj->buffer.length;
-		external_obj->buffer.length = internal_obj->buffer.length;
-		external_obj->buffer.pointer = data_space;
-		source_ptr = (u8 *) internal_obj->buffer.pointer;
+		length = internal_object->buffer.length;
+		external_object->buffer.length = internal_object->buffer.length;
+		external_object->buffer.pointer = data_space;
+		MEMCPY ((void *) data_space, (void *) internal_object->buffer.pointer, length);
 		break;
 
 
 	case ACPI_TYPE_INTEGER:
 
-		external_obj->integer.value= internal_obj->integer.value;
+		external_object->integer.value= internal_object->integer.value;
 		break;
 
 
 	case INTERNAL_TYPE_REFERENCE:
 
 		/*
-		 * This is an object reference.  We use the object type of "Any"
-		 * to indicate a reference object containing a handle to an ACPI
-		 * named object.
+		 * This is an object reference.  Attempt to dereference it.
 		 */
 
-		external_obj->type = ACPI_TYPE_ANY;
-		external_obj->reference.handle = internal_obj->reference.node;
-		break;
+		switch (internal_object->reference.op_code)
+		{
+		case AML_ZERO_OP:
+			external_object->type = ACPI_TYPE_INTEGER;
+			external_object->integer.value = 0;
+			break;
+
+		case AML_ONE_OP:
+			external_object->type = ACPI_TYPE_INTEGER;
+			external_object->integer.value = 1;
+			break;
+
+		case AML_ONES_OP:
+			external_object->type = ACPI_TYPE_INTEGER;
+			external_object->integer.value = ACPI_INTEGER_MAX;
+			break;
 
+		case AML_NAMEPATH_OP:
+			/*
+			 * This is a named reference, get the string.  We already know that
+			 * we have room for it, use max length
+			 */
+			length = MAX_STRING_LENGTH;
+			external_object->type = ACPI_TYPE_STRING;
+			external_object->string.pointer = (NATIVE_CHAR *) data_space;
+			status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) internal_object->reference.node,
+					 &length, (char *) data_space);
+			break;
 
-	case ACPI_TYPE_PROCESSOR:
+		default:
+			/*
+			 * Use the object type of "Any" to indicate a reference
+			 * to object containing a handle to an ACPI named object.
+			 */
+			external_object->type = ACPI_TYPE_ANY;
+			external_object->reference.handle = internal_object->reference.node;
+			break;
+		}
+		break;
 
-		external_obj->processor.proc_id =
-				 internal_obj->processor.proc_id;
 
-		external_obj->processor.pblk_address =
-				 internal_obj->processor.address;
+	case ACPI_TYPE_PROCESSOR:
 
-		external_obj->processor.pblk_length =
-				 internal_obj->processor.length;
+		external_object->processor.proc_id = internal_object->processor.proc_id;
+		external_object->processor.pblk_address = internal_object->processor.address;
+		external_object->processor.pblk_length = internal_object->processor.length;
 		break;
 
+
 	case ACPI_TYPE_POWER:
 
-		external_obj->power_resource.system_level =
-				   internal_obj->power_resource.system_level;
+		external_object->power_resource.system_level =
+				   internal_object->power_resource.system_level;
 
-		external_obj->power_resource.resource_order =
-				   internal_obj->power_resource.resource_order;
+		external_object->power_resource.resource_order =
+				   internal_object->power_resource.resource_order;
 		break;
 
+
 	default:
-		return (AE_CTRL_RETURN_VALUE);
+		/*
+		 * There is no corresponding external object type
+		 */
+		return (AE_SUPPORT);
 		break;
 	}
 
 
-	/* Copy data if necessary (strings or buffers) */
+	*buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length);
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_cm_copy_ielement_to_eelement
+ *
+ * PARAMETERS:  ACPI_PKG_CALLBACK
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Copy one package element to another package element
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_cm_copy_ielement_to_eelement (
+	u8                      object_type,
+	ACPI_OPERAND_OBJECT     *source_object,
+	ACPI_GENERIC_STATE      *state,
+	void                    *context)
+{
+	ACPI_STATUS             status = AE_OK;
+	ACPI_PKG_INFO           *info = (ACPI_PKG_INFO *) context;
+	u32                     object_space;
+	u32                     this_index;
+	ACPI_OBJECT             *target_object;
+
+
+	this_index      = state->pkg.index;
+	target_object   = (ACPI_OBJECT *)
+			   &((ACPI_OBJECT *)(state->pkg.dest_object))->package.elements[this_index];
+
+
+	switch (object_type)
+	{
+	case 0:
 
-	if (length) {
 		/*
-		 * Copy the return data to the caller's buffer
+		 * This is a simple or null object -- get the size
 		 */
-		MEMCPY ((void *) data_space, (void *) source_ptr, length);
+
+		status = acpi_cm_copy_isimple_to_esimple (source_object,
+				  target_object, info->free_space, &object_space);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+
+		break;
+
+	case 1:
+
+		/*
+		 * Build the package object
+		 */
+		target_object->type             = ACPI_TYPE_PACKAGE;
+		target_object->package.count    = source_object->package.count;
+		target_object->package.elements = (ACPI_OBJECT *) info->free_space;
+
+		/*
+		 * Pass the new package object back to the package walk routine
+		 */
+		state->pkg.this_target_obj = target_object;
+
+		/*
+		 * Save space for the array of objects (Package elements)
+		 * update the buffer length counter
+		 */
+		object_space = (u32) ROUND_UP_TO_NATIVE_WORD (
+				   target_object->package.count * sizeof (ACPI_OBJECT));
+		break;
+
+	default:
+		return (AE_BAD_PARAMETER);
 	}
 
 
-	*buffer_space_used = (u32) ROUND_UP_TO_NATIVE_WORD (length);
+	info->free_space  += object_space;
+	info->length      += object_space;
 
-	return (AE_OK);
+	return (status);
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_build_external_package_object
+ * FUNCTION:    Acpi_cm_copy_ipackage_to_epackage
  *
- * PARAMETERS:  *Internal_obj   - Pointer to the object we are returning
- *              *Buffer         - Where the object is returned
- *              *Space_used     - Where the object length is returned
+ * PARAMETERS:  *Internal_object    - Pointer to the object we are returning
+ *              *Buffer             - Where the object is returned
+ *              *Space_used         - Where the object length is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to place a package object in a user
  *              buffer.  A package object by definition contains other objects.
@@ -200,49 +293,33 @@
  ******************************************************************************/
 
 static ACPI_STATUS
-acpi_cm_build_external_package_object (
-	ACPI_OPERAND_OBJECT     *internal_obj,
+acpi_cm_copy_ipackage_to_epackage (
+	ACPI_OPERAND_OBJECT     *internal_object,
 	u8                      *buffer,
 	u32                     *space_used)
 {
-	u8                      *free_space;
-	ACPI_OBJECT             *external_obj;
-	u32                     current_depth = 0;
+	ACPI_OBJECT             *external_object;
 	ACPI_STATUS             status;
-	u32                     length = 0;
-	u32                     this_index;
-	u32                     object_space;
-	ACPI_OPERAND_OBJECT     *this_internal_obj;
-	ACPI_OBJECT             *this_external_obj;
-	PKG_SEARCH_INFO         *level_ptr;
+	ACPI_PKG_INFO           info;
 
 
 	/*
 	 * First package at head of the buffer
 	 */
-	external_obj = (ACPI_OBJECT *) buffer;
+	external_object = (ACPI_OBJECT *) buffer;
 
 	/*
 	 * Free space begins right after the first package
 	 */
-	free_space = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
-
-
-	/*
-	 * Initialize the working variables
-	 */
+	info.length      = 0;
+	info.object_space = 0;
+	info.num_packages = 1;
+	info.free_space  = buffer + ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 
-	MEMSET ((void *) level, 0, sizeof (level));
 
-	level[0].internal_obj   = internal_obj;
-	level[0].external_obj   = external_obj;
-	level[0].index          = 0;
-	level_ptr               = &level[0];
-	current_depth           = 0;
-
-	external_obj->type              = internal_obj->common.type;
-	external_obj->package.count     = internal_obj->package.count;
-	external_obj->package.elements  = (ACPI_OBJECT *) free_space;
+	external_object->type              = internal_object->common.type;
+	external_object->package.count     = internal_object->package.count;
+	external_object->package.elements  = (ACPI_OBJECT *) info.free_space;
 
 
 	/*
@@ -250,136 +327,27 @@
 	 * and move the free space past it
 	 */
 
-	free_space += external_obj->package.count *
+	info.free_space += external_object->package.count *
 			  ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT));
 
 
-	while (1) {
-		this_index      = level_ptr->index;
-		this_internal_obj =
-				(ACPI_OPERAND_OBJECT  *)
-				level_ptr->internal_obj->package.elements[this_index];
-		this_external_obj =
-				(ACPI_OBJECT *)
-				&level_ptr->external_obj->package.elements[this_index];
-
+	status = acpi_cm_walk_package_tree (internal_object, external_object,
+			 acpi_cm_copy_ielement_to_eelement, &info);
 
-		/*
-		 * Check for
-		 * 1) Null object -- OK, this can happen if package
-		 *              element is never initialized
-		 * 2) Not an internal object - can be Node instead
-		 * 3) Any internal object other than a package.
-		 *
-		 * The more complex package case is handled later
-		 */
+	*space_used = info.length;
 
-		if ((!this_internal_obj) ||
-			(!VALID_DESCRIPTOR_TYPE (
-				this_internal_obj, ACPI_DESC_TYPE_INTERNAL)) ||
-			(!IS_THIS_OBJECT_TYPE (
-				this_internal_obj, ACPI_TYPE_PACKAGE)))
-		{
-			/*
-			 * This is a simple or null object -- get the size
-			 */
-
-			status =
-				acpi_cm_build_external_simple_object (this_internal_obj,
-						   this_external_obj,
-						   free_space,
-						   &object_space);
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-
-			free_space  += object_space;
-			length      += object_space;
-
-			level_ptr->index++;
-			while (level_ptr->index >=
-					level_ptr->internal_obj->package.count)
-			{
-				/*
-				 * We've handled all of the objects at this
-				 * level.  This means that we have just
-				 * completed a package.  That package may
-				 * have contained one or more packages
-				 * itself
-				 */
-				if (current_depth == 0) {
-					/*
-					 * We have handled all of the objects
-					 * in the top level package just add
-					 * the length of the package objects
-					 * and get out
-					 */
-					*space_used = length;
-					return (AE_OK);
-				}
-
-				/*
-				 * go back up a level and move the index
-				 * past the just completed package object.
-				 */
-				current_depth--;
-				level_ptr = &level[current_depth];
-				level_ptr->index++;
-			}
-		}
-
-
-		else {
-			/*
-			 * This object is a package
-			 * -- we must go one level deeper
-			 */
-			if (current_depth >= MAX_PACKAGE_DEPTH-1) {
-				/*
-				 * Too many nested levels of packages
-				 * for us to handle
-				 */
-				return (AE_LIMIT);
-			}
-
-			/*
-			 * Build the package object
-			 */
-			this_external_obj->type = ACPI_TYPE_PACKAGE;
-			this_external_obj->package.count =
-					 this_internal_obj->package.count;
-			this_external_obj->package.elements =
-					  (ACPI_OBJECT *) free_space;
+	return (status);
 
-			/*
-			 * Save space for the array of objects (Package elements)
-			 * update the buffer length counter
-			 */
-			object_space = (u32) ROUND_UP_TO_NATIVE_WORD (
-					   this_external_obj->package.count *
-					   sizeof (ACPI_OBJECT));
-
-			free_space              += object_space;
-			length                  += object_space;
-
-			current_depth++;
-			level_ptr               = &level[current_depth];
-			level_ptr->internal_obj = this_internal_obj;
-			level_ptr->external_obj = this_external_obj;
-			level_ptr->index        = 0;
-		}
-	}
 }
 
-
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_build_external_object
+ * FUNCTION:    Acpi_cm_copy_iobject_to_eobject
  *
- * PARAMETERS:  *Internal_obj   - The internal object to be converted
- *              *Buffer_ptr     - Where the object is returned
+ * PARAMETERS:  *Internal_object    - The internal object to be converted
+ *              *Buffer_ptr         - Where the object is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to build an API object to be returned to
  *              the caller.
@@ -387,35 +355,31 @@
  ******************************************************************************/
 
 ACPI_STATUS
-acpi_cm_build_external_object (
-	ACPI_OPERAND_OBJECT     *internal_obj,
+acpi_cm_copy_iobject_to_eobject (
+	ACPI_OPERAND_OBJECT     *internal_object,
 	ACPI_BUFFER             *ret_buffer)
 {
 	ACPI_STATUS             status;
 
 
-	if (IS_THIS_OBJECT_TYPE (internal_obj, ACPI_TYPE_PACKAGE)) {
+	if (IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)) {
 		/*
-		 * Package objects contain other objects (which can be objects)
-		 * buildpackage does it all
+		 * Package object:  Copy all subobjects (including
+		 * nested packages)
 		 */
-		status =
-			acpi_cm_build_external_package_object (internal_obj,
-					 ret_buffer->pointer,
-					 &ret_buffer->length);
+		status = acpi_cm_copy_ipackage_to_epackage (internal_object,
+				  ret_buffer->pointer, &ret_buffer->length);
 	}
 
 	else {
 		/*
 		 * Build a simple object (no nested objects)
 		 */
-		status =
-			acpi_cm_build_external_simple_object (internal_obj,
-					  (ACPI_OBJECT *) ret_buffer->pointer,
-					  ((u8 *) ret_buffer->pointer +
-					  ROUND_UP_TO_NATIVE_WORD (
-							   sizeof (ACPI_OBJECT))),
-							&ret_buffer->length);
+		status = acpi_cm_copy_isimple_to_esimple (internal_object,
+				  (ACPI_OBJECT *) ret_buffer->pointer,
+				  ((u8 *) ret_buffer->pointer +
+				  ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT))),
+				  &ret_buffer->length);
 		/*
 		 * build simple does not include the object size in the length
 		 * so we add it in here
@@ -427,14 +391,14 @@
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_build_internal_simple_object
+ * FUNCTION:    Acpi_cm_copy_esimple_to_isimple
  *
- * PARAMETERS:  *External_obj   - The external object to be converted
- *              *Internal_obj   - Where the internal object is returned
+ * PARAMETERS:  *External_object   - The external object to be converted
+ *              *Internal_object   - Where the internal object is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function copies an external object to an internal one.
  *              NOTE: Pointers can be copied, we don't need to copy data.
@@ -444,28 +408,28 @@
  ******************************************************************************/
 
 ACPI_STATUS
-acpi_cm_build_internal_simple_object (
-	ACPI_OBJECT             *external_obj,
-	ACPI_OPERAND_OBJECT     *internal_obj)
+acpi_cm_copy_esimple_to_isimple (
+	ACPI_OBJECT             *external_object,
+	ACPI_OPERAND_OBJECT     *internal_object)
 {
 
 
-	internal_obj->common.type = (u8) external_obj->type;
+	internal_object->common.type = (u8) external_object->type;
 
-	switch (external_obj->type)
+	switch (external_object->type)
 	{
 
 	case ACPI_TYPE_STRING:
 
-		internal_obj->string.length = external_obj->string.length;
-		internal_obj->string.pointer = external_obj->string.pointer;
+		internal_object->string.length = external_object->string.length;
+		internal_object->string.pointer = external_object->string.pointer;
 		break;
 
 
 	case ACPI_TYPE_BUFFER:
 
-		internal_obj->buffer.length = external_obj->buffer.length;
-		internal_obj->buffer.pointer = external_obj->buffer.pointer;
+		internal_object->buffer.length = external_object->buffer.length;
+		internal_object->buffer.pointer = external_object->buffer.pointer;
 		break;
 
 
@@ -473,7 +437,7 @@
 		/*
 		 * Number is included in the object itself
 		 */
-		internal_obj->integer.value  = external_obj->integer.value;
+		internal_object->integer.value  = external_object->integer.value;
 		break;
 
 
@@ -491,11 +455,11 @@
 
 /* Code to convert packages that are parameters to control methods */
 
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_build_internal_package_object
+ * FUNCTION:    Acpi_cm_copy_epackage_to_ipackage
  *
- * PARAMETERS:  *Internal_obj   - Pointer to the object we are returning
+ * PARAMETERS:  *Internal_object   - Pointer to the object we are returning
  *              *Buffer         - Where the object is returned
  *              *Space_used     - Where the length of the object is returned
  *
@@ -511,26 +475,24 @@
  ******************************************************************************/
 
 static ACPI_STATUS
-acpi_cm_build_internal_package_object (
-	ACPI_OPERAND_OBJECT     *internal_obj,
+acpi_cm_copy_epackage_to_ipackage (
+	ACPI_OPERAND_OBJECT     *internal_object,
 	u8                      *buffer,
 	u32                     *space_used)
 {
 	u8                      *free_space;
-	ACPI_OBJECT             *external_obj;
-	u32                     current_depth = 0;
+	ACPI_OBJECT             *external_object;
 	u32                     length = 0;
 	u32                     this_index;
 	u32                     object_space = 0;
 	ACPI_OPERAND_OBJECT     *this_internal_obj;
 	ACPI_OBJECT             *this_external_obj;
-	PKG_SEARCH_INFO         *level_ptr;
 
 
 	/*
 	 * First package at head of the buffer
 	 */
-	external_obj = (ACPI_OBJECT *)buffer;
+	external_object = (ACPI_OBJECT *)buffer;
 
 	/*
 	 * Free space begins right after the first package
@@ -538,20 +500,9 @@
 	free_space = buffer + sizeof(ACPI_OBJECT);
 
 
-	/*
-	 * Initialize the working variables
-	 */
-
-	MEMSET ((void *) level, 0, sizeof(level));
-
-	level[0].internal_obj   = internal_obj;
-	level[0].external_obj   = external_obj;
-	level_ptr               = &level[0];
-	current_depth           = 0;
-
-	external_obj->type              = internal_obj->common.type;
-	external_obj->package.count     = internal_obj->package.count;
-	external_obj->package.elements  = (ACPI_OBJECT *)free_space;
+	external_object->type              = internal_object->common.type;
+	external_object->package.count     = internal_object->package.count;
+	external_object->package.elements  = (ACPI_OBJECT *)free_space;
 
 
 	/*
@@ -559,100 +510,21 @@
 	 * and move the free space past it
 	 */
 
-	free_space += external_obj->package.count * sizeof(ACPI_OBJECT);
+	free_space += external_object->package.count * sizeof(ACPI_OBJECT);
 
 
-	while (1) {
-		this_index      = level_ptr->index;
-
-		this_internal_obj = (ACPI_OPERAND_OBJECT *)
-				 &level_ptr->internal_obj->package.elements[this_index];
-
-		this_external_obj = (ACPI_OBJECT *)
-				 &level_ptr->external_obj->package.elements[this_index];
-
-		if (IS_THIS_OBJECT_TYPE (this_internal_obj, ACPI_TYPE_PACKAGE)) {
-			/*
-			 * If this object is a package then we go one deeper
-			 */
-			if (current_depth >= MAX_PACKAGE_DEPTH-1) {
-				/*
-				 * Too many nested levels of packages for us to handle
-				 */
-				return (AE_LIMIT);
-			}
-
-			/*
-			 * Build the package object
-			 */
-			this_external_obj->type             = ACPI_TYPE_PACKAGE;
-			this_external_obj->package.count    = this_internal_obj->package.count;
-			this_external_obj->package.elements = (ACPI_OBJECT *) free_space;
-
-			/*
-			 * Save space for the array of objects (Package elements)
-			 * update the buffer length counter
-			 */
-			object_space            = this_external_obj->package.count *
-					   sizeof (ACPI_OBJECT);
-
-			free_space              += object_space;
-			length                  += object_space;
+	/* Call Walk_package */
 
-			current_depth++;
-			level_ptr               = &level[current_depth];
-			level_ptr->internal_obj = this_internal_obj;
-			level_ptr->external_obj = this_external_obj;
-			level_ptr->index        = 0;
-
-		}   /* if object is a package */
-
-		else {
-			free_space  += object_space;
-			length      += object_space;
-
-			level_ptr->index++;
-			while (level_ptr->index >=
-					level_ptr->internal_obj->package.count)
-			{
-				/*
-				 * We've handled all of the objects at
-				 * this level,  This means that we have
-				 * just completed a package.  That package
-				 * may have contained one or more packages
-				 * itself
-				 */
-				if (current_depth == 0) {
-					/*
-					 * We have handled all of the objects
-					 * in the top level package just add
-					 * the length of the package objects
-					 * and get out
-					 */
-					*space_used = length;
-					return (AE_OK);
-				}
-
-				/*
-				 * go back up a level and move the index
-				 * past the just completed package object.
-				 */
-				current_depth--;
-				level_ptr = &level[current_depth];
-				level_ptr->index++;
-			}
-		}   /* else object is NOT a package */
-	}   /* while (1)  */
 }
 
 #endif /* Future implementation */
 
 
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_build_internal_object
+ * FUNCTION:    Acpi_cm_copy_eobject_to_iobject
  *
- * PARAMETERS:  *Internal_obj   - The external object to be converted
+ * PARAMETERS:  *Internal_object   - The external object to be converted
  *              *Buffer_ptr     - Where the internal object is returned
  *
  * RETURN:      Status          - the status of the call
@@ -662,14 +534,14 @@
  ******************************************************************************/
 
 ACPI_STATUS
-acpi_cm_build_internal_object (
-	ACPI_OBJECT             *external_obj,
-	ACPI_OPERAND_OBJECT     *internal_obj)
+acpi_cm_copy_eobject_to_iobject (
+	ACPI_OBJECT             *external_object,
+	ACPI_OPERAND_OBJECT     *internal_object)
 {
 	ACPI_STATUS             status;
 
 
-	if (external_obj->type == ACPI_TYPE_PACKAGE) {
+	if (external_object->type == ACPI_TYPE_PACKAGE) {
 		/*
 		 * Package objects contain other objects (which can be objects)
 		 * buildpackage does it all
@@ -679,7 +551,7 @@
 		 * control methods only.  This is a very, very rare case.
 		 */
 /*
-		Status = Acpi_cm_build_internal_package_object(Internal_obj,
+		Status = Acpi_cm_copy_epackage_to_ipackage(Internal_object,
 				 Ret_buffer->Pointer,
 				 &Ret_buffer->Length);
 */
@@ -690,12 +562,146 @@
 		/*
 		 * Build a simple object (no nested objects)
 		 */
-		status = acpi_cm_build_internal_simple_object (external_obj, internal_obj);
+		status = acpi_cm_copy_esimple_to_isimple (external_object, internal_object);
 		/*
 		 * build simple does not include the object size in the length
 		 * so we add it in here
 		 */
 	}
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_cm_copy_ielement_to_ielement
+ *
+ * PARAMETERS:  ACPI_PKG_CALLBACK
+ *
+ * RETURN:      Status          - the status of the call
+ *
+ * DESCRIPTION: Copy one package element to another package element
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_cm_copy_ielement_to_ielement (
+	u8                      object_type,
+	ACPI_OPERAND_OBJECT     *source_object,
+	ACPI_GENERIC_STATE      *state,
+	void                    *context)
+{
+	ACPI_STATUS             status = AE_OK;
+	u32                     this_index;
+	ACPI_OPERAND_OBJECT     **this_target_ptr;
+	ACPI_OPERAND_OBJECT     *target_object;
+
+
+	this_index    = state->pkg.index;
+	this_target_ptr = (ACPI_OPERAND_OBJECT **)
+			   &state->pkg.dest_object->package.elements[this_index];
+
+	switch (object_type)
+	{
+	case 0:
+
+		/*
+		 * This is a simple object, just copy it
+		 */
+		target_object = acpi_cm_create_internal_object (source_object->common.type);
+		if (!target_object) {
+			return (AE_NO_MEMORY);
+		}
+
+		status = acpi_aml_store_object_to_object (source_object, target_object,
+				  (ACPI_WALK_STATE *) context);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
+
+		*this_target_ptr = target_object;
+		break;
+
+
+	case 1:
+		/*
+		 * This object is a package - go down another nesting level
+		 * Create and build the package object
+		 */
+		target_object = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
+		if (!target_object) {
+			/* TBD: must delete package created up to this point */
+
+			return (AE_NO_MEMORY);
+		}
+
+		target_object->package.count = source_object->package.count;
+
+		/*
+		 * Pass the new package object back to the package walk routine
+		 */
+		state->pkg.this_target_obj = target_object;
+
+		/*
+		 * Store the object pointer in the parent package object
+		 */
+		*this_target_ptr = target_object;
+		break;
+
+	default:
+		return (AE_BAD_PARAMETER);
+	}
+
+
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_cm_copy_ipackage_to_ipackage
+ *
+ * PARAMETERS:  *Source_obj     - Pointer to the source package object
+ *              *Dest_obj       - Where the internal object is returned
+ *
+ * RETURN:      Status          - the status of the call
+ *
+ * DESCRIPTION: This function is called to copy an internal package object
+ *              into another internal package object.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_cm_copy_ipackage_to_ipackage (
+	ACPI_OPERAND_OBJECT     *source_obj,
+	ACPI_OPERAND_OBJECT     *dest_obj,
+	ACPI_WALK_STATE         *walk_state)
+{
+	ACPI_STATUS             status = AE_OK;
+
+
+	dest_obj->common.type   = source_obj->common.type;
+	dest_obj->package.count = source_obj->package.count;
+
+
+	/*
+	 * Create the object array and walk the source package tree
+	 */
+
+	dest_obj->package.elements = acpi_cm_callocate ((source_obj->package.count + 1) *
+			 sizeof (void *));
+	dest_obj->package.next_element = dest_obj->package.elements;
+
+	if (!dest_obj->package.elements) {
+		REPORT_ERROR (
+			("Aml_build_copy_internal_package_object: Package allocation failure\n"));
+		return (AE_NO_MEMORY);
+	}
+
+
+	status = acpi_cm_walk_package_tree (source_obj, dest_obj,
+			 acpi_cm_copy_ielement_to_ielement, walk_state);
 
 	return (status);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/common/cmobject.c linux/drivers/acpi/common/cmobject.c
--- v2.4.1/linux/drivers/acpi/common/cmobject.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/common/cmobject.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: cmobject - ACPI object create/delete/size/cache routines
- *              $Revision: 35 $
+ *              $Revision: 36 $
  *
  *****************************************************************************/
 
@@ -35,7 +35,7 @@
 	 MODULE_NAME         ("cmobject")
 
 
-/******************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    _Cm_create_internal_object
  *
@@ -49,11 +49,11 @@
  *
  * DESCRIPTION: Create and initialize a new internal object.
  *
- * NOTE:
- *      We always allocate the worst-case object descriptor because these
- *      objects are cached, and we want them to be one-size-satisifies-any-request.
- *      This in itself may not be the most memory efficient, but the efficiency
- *      of the object cache should more than make up for this!
+ * NOTE:        We always allocate the worst-case object descriptor because
+ *              these objects are cached, and we want them to be
+ *              one-size-satisifies-any-request.  This in itself may not be
+ *              the most memory efficient, but the efficiency of the object
+ *              cache should more than make up for this!
  *
  ******************************************************************************/
 
@@ -91,7 +91,7 @@
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_valid_internal_object
  *
@@ -99,7 +99,7 @@
  *
  * RETURN:      Validate a pointer to be an ACPI_OPERAND_OBJECT
  *
- *****************************************************************************/
+ ******************************************************************************/
 
 u8
 acpi_cm_valid_internal_object (
@@ -136,7 +136,7 @@
 }
 
 
-/*****************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    _Cm_allocate_object_desc
  *
@@ -150,7 +150,7 @@
  * DESCRIPTION: Allocate a new object descriptor.  Gracefully handle
  *              error conditions.
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 void *
 _cm_allocate_object_desc (
@@ -211,7 +211,7 @@
 }
 
 
-/*****************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_delete_object_desc
  *
@@ -221,7 +221,7 @@
  *
  * DESCRIPTION: Free an ACPI object descriptor or add it to the object cache
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 void
 acpi_cm_delete_object_desc (
@@ -274,7 +274,7 @@
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_delete_object_cache
  *
@@ -317,7 +317,7 @@
 }
 
 
-/*****************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_init_static_object
  *
@@ -329,7 +329,7 @@
  * DESCRIPTION: Initialize a static object.  Sets flags to disallow dynamic
  *              deletion of the object.
  *
- ****************************************************************************/
+ ******************************************************************************/
 
 void
 acpi_cm_init_static_object (
@@ -365,14 +365,14 @@
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_get_simple_object_size
  *
- * PARAMETERS:  *Internal_obj   - Pointer to the object we are examining
- *              *Ret_length     - Where the length is returned
+ * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
+ *              *Ret_length         - Where the length is returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to determine the space required to
  *              contain a simple object for return to an API user.
@@ -384,7 +384,7 @@
 
 ACPI_STATUS
 acpi_cm_get_simple_object_size (
-	ACPI_OPERAND_OBJECT     *internal_obj,
+	ACPI_OPERAND_OBJECT     *internal_object,
 	u32                     *obj_length)
 {
 	u32                     length;
@@ -393,7 +393,7 @@
 
 	/* Handle a null object (Could be a uninitialized package element -- which is legal) */
 
-	if (!internal_obj) {
+	if (!internal_object) {
 		*obj_length = 0;
 		return (AE_OK);
 	}
@@ -403,7 +403,7 @@
 
 	length = sizeof (ACPI_OBJECT);
 
-	if (VALID_DESCRIPTOR_TYPE (internal_obj, ACPI_DESC_TYPE_NAMED)) {
+	if (VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_NAMED)) {
 		/* Object is a named object (reference), just return the length */
 
 		*obj_length = (u32) ROUND_UP_TO_NATIVE_WORD (length);
@@ -419,18 +419,18 @@
 	 * TBD:[Investigate] do strings and buffers require alignment also?
 	 */
 
-	switch (internal_obj->common.type)
+	switch (internal_object->common.type)
 	{
 
 	case ACPI_TYPE_STRING:
 
-		length += internal_obj->string.length + 1;
+		length += internal_object->string.length + 1;
 		break;
 
 
 	case ACPI_TYPE_BUFFER:
 
-		length += internal_obj->buffer.length;
+		length += internal_object->buffer.length;
 		break;
 
 
@@ -450,7 +450,7 @@
 		 * The only type that should be here is opcode AML_NAMEPATH_OP -- since
 		 * this means an object reference
 		 */
-		if (internal_obj->reference.op_code != AML_NAMEPATH_OP) {
+		if (internal_object->reference.op_code != AML_NAMEPATH_OP) {
 			status = AE_TYPE;
 		}
 		break;
@@ -475,149 +475,119 @@
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
- * FUNCTION:    Acpi_cm_get_package_object_size
+ * FUNCTION:    Acpi_cm_copy_package_to_internal
  *
- * PARAMETERS:  *Internal_obj   - Pointer to the object we are examining
- *              *Ret_length     - Where the length is returned
+ * PARAMETERS:  ACPI_PKG_CALLBACK
  *
  * RETURN:      Status          - the status of the call
  *
- * DESCRIPTION: This function is called to determine the space required to contain
- *              a package object for return to an API user.
- *
- *              This is moderately complex since a package contains other objects
- *              including packages.
+ * DESCRIPTION:
  *
  ******************************************************************************/
 
 ACPI_STATUS
-acpi_cm_get_package_object_size (
-	ACPI_OPERAND_OBJECT     *internal_obj,
-	u32                     *obj_length)
+acpi_cm_get_element_length (
+	u8                      object_type,
+	ACPI_OPERAND_OBJECT     *source_object,
+	ACPI_GENERIC_STATE      *state,
+	void                    *context)
 {
-
-	ACPI_OPERAND_OBJECT     *this_internal_obj;
-	ACPI_OPERAND_OBJECT     *parent_obj[MAX_PACKAGE_DEPTH];
-	ACPI_OPERAND_OBJECT     *this_parent;
-	u32                     this_index;
-	u32                     index[MAX_PACKAGE_DEPTH];
-	u32                     length = 0;
+	ACPI_STATUS             status = AE_OK;
+	ACPI_PKG_INFO           *info = (ACPI_PKG_INFO *) context;
 	u32                     object_space;
-	u32                     current_depth = 0;
-	u32                     package_count = 1;
-	ACPI_STATUS             status;
 
 
-	/* Init the package stack TBD: replace with linked list */
+	switch (object_type)
+	{
+	case 0:
 
-	MEMSET(parent_obj, 0, MAX_PACKAGE_DEPTH);
-	MEMSET(index, 0, MAX_PACKAGE_DEPTH);
+		/*
+		 * Simple object - just get the size (Null object/entry is handled
+		 * here also) and sum it into the running package length
+		 */
+		status = acpi_cm_get_simple_object_size (source_object, &object_space);
+		if (ACPI_FAILURE (status)) {
+			return (status);
+		}
 
-	parent_obj[0] = internal_obj;
+		info->length += object_space;
+		break;
 
-	while (1) {
-		this_parent     = parent_obj[current_depth];
-		this_index      = index[current_depth];
-		this_internal_obj = this_parent->package.elements[this_index];
 
+	case 1:
+		/* Package - nothing much to do here, let the walk handle it */
 
-		/*
-		 * Check for 1) An uninitialized package element.  It is completely
-		 *              legal to declare a package and leave it uninitialized
-		 *           2) Any type other than a package.  Packages are handled
-		 *              below.
-		 */
+		info->num_packages++;
+		state->pkg.this_target_obj = NULL;
+		break;
 
-		if ((!this_internal_obj) ||
-			(!IS_THIS_OBJECT_TYPE (this_internal_obj, ACPI_TYPE_PACKAGE)))
-		{
-			/*
-			 * Simple object - just get the size (Null object/entry handled
-			 *  also)
-			 */
-
-			status =
-				acpi_cm_get_simple_object_size (this_internal_obj, &object_space);
-
-			if (ACPI_FAILURE (status)) {
-				return (status);
-			}
-
-			length += object_space;
-
-			index[current_depth]++;
-			while (index[current_depth] >=
-				parent_obj[current_depth]->package.count)
-			{
-				/*
-				 * We've handled all of the objects at
-				 * this level,  This means that we have
-				 * just completed a package.  That package
-				 * may have contained one or more packages
-				 * itself.
-				 */
-				if (current_depth == 0) {
-					/*
-					 * We have handled all of the objects
-					 * in the top level package just add the
-					 * length of the package objects and
-					 * get out. Round up to the next machine
-					 * word.
-					 */
-					length +=
-						ROUND_UP_TO_NATIVE_WORD (
-								sizeof (ACPI_OBJECT)) *
-								package_count;
-
-					*obj_length = length;
-
-					return (AE_OK);
-				}
-
-				/*
-				 * Go back up a level and move the index
-				 * past the just completed package object.
-				 */
-				current_depth--;
-				index[current_depth]++;
-			}
-		}
+	default:
+		return (AE_BAD_PARAMETER);
+	}
 
-		else {
-			/*
-			 * This object is a package
-			 * -- go one level deeper
-			 */
-			package_count++;
-			if (current_depth < MAX_PACKAGE_DEPTH-1) {
-				current_depth++;
-				parent_obj[current_depth] = this_internal_obj;
-				index[current_depth]    = 0;
-			}
-
-			else {
-				/*
-				 * Too many nested levels of packages for us
-				 * to handle
-				 */
 
-				return (AE_LIMIT);
-			}
-		}
-	}
+	return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_cm_get_package_object_size
+ *
+ * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
+ *              *Ret_length         - Where the length is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This function is called to determine the space required to
+ *              contain a package object for return to an API user.
+ *
+ *              This is moderately complex since a package contains other
+ *              objects including packages.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_cm_get_package_object_size (
+	ACPI_OPERAND_OBJECT     *internal_object,
+	u32                     *obj_length)
+{
+	ACPI_STATUS             status;
+	ACPI_PKG_INFO           info;
+
+
+	info.length      = 0;
+	info.object_space = 0;
+	info.num_packages = 1;
+
+	status = acpi_cm_walk_package_tree (internal_object, NULL,
+			 acpi_cm_get_element_length, &info);
+
+	/*
+	 * We have handled all of the objects in all levels of the package.
+	 * just add the length of the package objects themselves.
+	 * Round up to the next machine word.
+	 */
+	info.length += ROUND_UP_TO_NATIVE_WORD (sizeof (ACPI_OBJECT)) *
+			  info.num_packages;
+
+	/* Return the total package length */
+
+	*obj_length = info.length;
+	return (status);
 }
 
 
-/******************************************************************************
+/*******************************************************************************
  *
  * FUNCTION:    Acpi_cm_get_object_size
  *
- * PARAMETERS:  *Internal_obj   - Pointer to the object we are examining
- *              *Ret_length     - Where the length will be returned
+ * PARAMETERS:  *Internal_object    - Pointer to the object we are examining
+ *              *Ret_length         - Where the length will be returned
  *
- * RETURN:      Status          - the status of the call
+ * RETURN:      Status
  *
  * DESCRIPTION: This function is called to determine the space required to
  *              contain an object for return to an API user.
@@ -626,22 +596,20 @@
 
 ACPI_STATUS
 acpi_cm_get_object_size(
-	ACPI_OPERAND_OBJECT     *internal_obj,
+	ACPI_OPERAND_OBJECT     *internal_object,
 	u32                     *obj_length)
 {
 	ACPI_STATUS             status;
 
 
-	if ((VALID_DESCRIPTOR_TYPE (internal_obj, ACPI_DESC_TYPE_INTERNAL)) &&
-		(IS_THIS_OBJECT_TYPE (internal_obj, ACPI_TYPE_PACKAGE)))
+	if ((VALID_DESCRIPTOR_TYPE (internal_object, ACPI_DESC_TYPE_INTERNAL)) &&
+		(IS_THIS_OBJECT_TYPE (internal_object, ACPI_TYPE_PACKAGE)))
 	{
-		status =
-			acpi_cm_get_package_object_size (internal_obj, obj_length);
+		status = acpi_cm_get_package_object_size (internal_object, obj_length);
 	}
 
 	else {
-		status =
-			acpi_cm_get_simple_object_size (internal_obj, obj_length);
+		status = acpi_cm_get_simple_object_size (internal_object, obj_length);
 	}
 
 	return (status);
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/common/cmutils.c linux/drivers/acpi/common/cmutils.c
--- v2.4.1/linux/drivers/acpi/common/cmutils.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/common/cmutils.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: cmutils - common utility procedures
- *              $Revision: 23 $
+ *              $Revision: 27 $
  *
  ******************************************************************************/
 
@@ -340,6 +340,41 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    Acpi_cm_create_pkg_state_and_push
+ *
+ * PARAMETERS:  *Object         - Object to be added to the new state
+ *              Action          - Increment/Decrement
+ *              State_list      - List the state will be added to
+ *
+ * RETURN:      None
+ *
+ * DESCRIPTION: Create a new state and push it
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_cm_create_pkg_state_and_push (
+	void                    *internal_object,
+	void                    *external_object,
+	u16                     index,
+	ACPI_GENERIC_STATE      **state_list)
+{
+	ACPI_GENERIC_STATE       *state;
+
+
+	state = acpi_cm_create_pkg_state (internal_object, external_object, index);
+	if (!state) {
+		return (AE_NO_MEMORY);
+	}
+
+
+	acpi_cm_push_generic_state (state_list, state);
+	return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    Acpi_cm_push_generic_state
  *
  * PARAMETERS:  List_head           - Head of the state stack
@@ -500,6 +535,49 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    Acpi_cm_create_pkg_state
+ *
+ * PARAMETERS:  Object              - Initial Object to be installed in the
+ *                                    state
+ *              Action              - Update action to be performed
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
+ *              to update reference counts and delete complex objects such
+ *              as packages.
+ *
+ ******************************************************************************/
+
+ACPI_GENERIC_STATE *
+acpi_cm_create_pkg_state (
+	void                    *internal_object,
+	void                    *external_object,
+	u16                     index)
+{
+	ACPI_GENERIC_STATE      *state;
+
+
+	/* Create the generic state object */
+
+	state = acpi_cm_create_generic_state ();
+	if (!state) {
+		return (NULL);
+	}
+
+	/* Init fields specific to the update struct */
+
+	state->pkg.source_object = (ACPI_OPERAND_OBJECT *) internal_object;
+	state->pkg.dest_object  = external_object;
+	state->pkg.index        = index;
+	state->pkg.num_packages = 1;
+
+	return (state);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    Acpi_cm_create_control_state
  *
  * PARAMETERS:  None
@@ -632,16 +710,20 @@
 acpi_cm_resolve_package_references (
 	ACPI_OPERAND_OBJECT     *obj_desc)
 {
-	u32                 count;
-	ACPI_OPERAND_OBJECT *sub_object;
+	u32                     count;
+	ACPI_OPERAND_OBJECT     *sub_object;
+
 
 	if (obj_desc->common.type != ACPI_TYPE_PACKAGE) {
-		/* Must be a package */
+		/* The object must be a package */
 
 		REPORT_ERROR (("Must resolve Package Refs on a Package\n"));
 		return(AE_ERROR);
 	}
 
+	/*
+	 * TBD: what about nested packages? */
+
 	for (count = 0; count < obj_desc->package.count; count++) {
 		sub_object = obj_desc->package.elements[count];
 
@@ -667,6 +749,130 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    Acpi_cm_walk_package_tree
+ *
+ * PARAMETERS:  Obj_desc        - The Package object on which to resolve refs
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk through a package
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_cm_walk_package_tree (
+	ACPI_OPERAND_OBJECT     *source_object,
+	void                    *target_object,
+	ACPI_PKG_CALLBACK       walk_callback,
+	void                    *context)
+{
+	ACPI_STATUS             status = AE_OK;
+	ACPI_GENERIC_STATE      *state_list = NULL;
+	ACPI_GENERIC_STATE      *state;
+	u32                     this_index;
+	ACPI_OPERAND_OBJECT     *this_source_obj;
+
+
+	state = acpi_cm_create_pkg_state (source_object, target_object, 0);
+	if (!state) {
+		return (AE_NO_MEMORY);
+	}
+
+	while (state) {
+		this_index       = state->pkg.index;
+		this_source_obj  = (ACPI_OPERAND_OBJECT *)
+				   state->pkg.source_object->package.elements[this_index];
+
+		/*
+		 * Check for
+		 * 1) An uninitialized package element.  It is completely
+		 *      legal to declare a package and leave it uninitialized
+		 * 2) Not an internal object - can be a namespace node instead
+		 * 3) Any type other than a package.  Packages are handled in else case below.
+		 */
+		if ((!this_source_obj) ||
+			(!VALID_DESCRIPTOR_TYPE (
+					this_source_obj, ACPI_DESC_TYPE_INTERNAL)) ||
+			(!IS_THIS_OBJECT_TYPE (
+					this_source_obj, ACPI_TYPE_PACKAGE)))
+		{
+
+			status = walk_callback (0, this_source_obj, state, context);
+			if (ACPI_FAILURE (status)) {
+				/* TBD: must delete package created up to this point */
+
+				return (status);
+			}
+
+			state->pkg.index++;
+			while (state->pkg.index >= state->pkg.source_object->package.count) {
+				/*
+				 * We've handled all of the objects at this level,  This means
+				 * that we have just completed a package.  That package may
+				 * have contained one or more packages itself.
+				 *
+				 * Delete this state and pop the previous state (package).
+				 */
+				acpi_cm_delete_generic_state (state);
+				state = acpi_cm_pop_generic_state (&state_list);
+
+
+				/* Finished when there are no more states */
+
+				if (!state) {
+					/*
+					 * We have handled all of the objects in the top level
+					 * package just add the length of the package objects
+					 * and exit
+					 */
+					return (AE_OK);
+				}
+
+				/*
+				 * Go back up a level and move the index past the just
+				 * completed package object.
+				 */
+				state->pkg.index++;
+			}
+		}
+
+		else {
+			/* This is a sub-object of type package */
+
+			status = walk_callback (1, this_source_obj, state, context);
+			if (ACPI_FAILURE (status)) {
+				/* TBD: must delete package created up to this point */
+
+				return (status);
+			}
+
+
+			/*
+			 * The callback above returned a new target package object.
+			 */
+
+			/*
+			 * Push the current state and create a new one
+			 */
+			acpi_cm_push_generic_state (&state_list, state);
+			state = acpi_cm_create_pkg_state (this_source_obj, state->pkg.this_target_obj, 0);
+			if (!state) {
+				/* TBD: must delete package created up to this point */
+
+				return (AE_NO_MEMORY);
+			}
+		}
+	}
+
+	/* We should never get here */
+
+	return (AE_AML_INTERNAL);
+
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    _Report_error
  *
  * PARAMETERS:  Module_name         - Caller's module name (for error output)
@@ -676,7 +882,7 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Print error message from KD table
+ * DESCRIPTION: Print error message
  *
  ******************************************************************************/
 
@@ -703,7 +909,7 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Print warning message from KD table
+ * DESCRIPTION: Print warning message
  *
  ******************************************************************************/
 
@@ -729,7 +935,7 @@
  *
  * RETURN:      None
  *
- * DESCRIPTION: Print information message from KD table
+ * DESCRIPTION: Print information message
  *
  ******************************************************************************/
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/common/cmxface.c linux/drivers/acpi/common/cmxface.c
--- v2.4.1/linux/drivers/acpi/common/cmxface.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/common/cmxface.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: cmxface - External interfaces for "global" ACPI functions
- *              $Revision: 62 $
+ *              $Revision: 64 $
  *
  *****************************************************************************/
 
@@ -158,8 +158,7 @@
 	if (!(flags & ACPI_NO_ACPI_ENABLE)) {
 		status = acpi_enable ();
 		if (ACPI_FAILURE (status)) {
-			/* TBD: workaround. Old Lions don't enable properly */
-			/*return (Status);*/
+			return (status);
 		}
 	}
 
@@ -180,12 +179,11 @@
 
 	/*
 	 * Initialize all device objects in the namespace
-	 * This runs the _STA, _INI, and _HID methods, and detects
-	 * the PCI root bus(es)
+	 * This runs the _STA and _INI methods.
 	 */
 
 	if (!(flags & ACPI_NO_DEVICE_INIT)) {
-		status = acpi_ns_initialize_devices (flags & ACPI_NO_PCI_INIT);
+		status = acpi_ns_initialize_devices ();
 		if (ACPI_FAILURE (status)) {
 			return (status);
 		}
@@ -193,7 +191,7 @@
 
 
 	/*
-	 * Initialize the objects that remain unitialized.  This
+	 * Initialize the objects that remain uninitialized.  This
 	 * runs the executable AML that is part of the declaration of Op_regions
 	 * and Fields.
 	 */
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/cpu.c linux/drivers/acpi/cpu.c
--- v2.4.1/linux/drivers/acpi/cpu.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/cpu.c	Fri Feb  9 11:45:58 2001
@@ -2,6 +2,7 @@
  *  cpu.c - Processor handling
  *
  *  Copyright (C) 2000 Andrew Henroid
+ *  Copyright (C) 2001 Andrew Grover
  *
  *  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
@@ -28,27 +29,37 @@
 #define _COMPONENT	OS_DEPENDENT
 	MODULE_NAME	("cpu")
 
-unsigned long acpi_c2_exit_latency = ACPI_INFINITE;
-unsigned long acpi_c3_exit_latency = ACPI_INFINITE;
-unsigned long acpi_c2_enter_latency = ACPI_INFINITE;
-unsigned long acpi_c3_enter_latency = ACPI_INFINITE;
+u32 acpi_c2_exit_latency = ACPI_INFINITE;
+u32 acpi_c3_exit_latency = ACPI_INFINITE;
+u32 acpi_c2_enter_latency = ACPI_INFINITE;
+u32 acpi_c3_enter_latency = ACPI_INFINITE;
+u32 acpi_use_idle = TRUE;
+
+u32 acpi_c1_count = 0;
+u32 acpi_c2_count = 0;
+u32 acpi_c3_count = 0;
 
-static unsigned long acpi_pblk = ACPI_INVALID;
+static u32 acpi_pblk = ACPI_INVALID;
 static int acpi_c2_tested = 0;
 static int acpi_c3_tested = 0;
 static int acpi_max_c_state = 1;
-static int acpi_pm_tmr_len;
+static int acpi_pm_tmr_len = 24;
 
+#define CPU_POWER_STATES	3
 #define MAX_C2_LATENCY		100
 #define MAX_C3_LATENCY		1000
 
+#define ACPI_STATE_C1		0
+#define ACPI_STATE_C2		1
+#define ACPI_STATE_C3		2
+
 /*
  * Clear busmaster activity flag
  */
 static inline void
 acpi_clear_bm_activity(void)
 {
-	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 0);
+	acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, BM_STS, 1);
 }
 
 /*
@@ -100,6 +111,7 @@
 	}
 }
 
+
 /*
  * Idle loop (uniprocessor only)
  */
@@ -109,14 +121,9 @@
 	static int sleep_level = 1;
 	FADT_DESCRIPTOR *fadt = &acpi_fadt;
 
-	if (!fadt
-	    || (STRNCMP(fadt->header.signature, ACPI_FADT_SIGNATURE, ACPI_SIG_LEN) != 0)
-	    || !fadt->Xpm_tmr_blk.address
-	    || !acpi_pblk)
-		goto not_initialized;
-
 	/*
-	 * start from the previous sleep level..
+	 * start from the previous sleep level.
+	 * if not initialized, we goto sleep1
 	 */
 	if (sleep_level == 1
 	    || acpi_max_c_state < 2)
@@ -126,7 +133,7 @@
 	    || acpi_max_c_state < 3)
 		goto sleep2;
 
-      sleep3:
+sleep3:
 	sleep_level = 3;
 	if (!acpi_c3_tested) {
 		DEBUG_PRINT(ACPI_INFO, ("C3 works\n"));
@@ -147,6 +154,7 @@
 			goto sleep2;
 
 		time = acpi_read_pm_timer();
+		acpi_c3_count++;
 		inb(acpi_pblk + ACPI_P_LVL3);
 		/* Dummy read, force synchronization with the PMU */
 		acpi_read_pm_timer();
@@ -154,10 +162,10 @@
 
 		__sti();
 		if (diff < acpi_c3_exit_latency)
-			goto sleep2;
+			goto sleep1;
 	}
 
-      sleep3_with_arbiter:
+sleep3_with_arbiter:
 	for (;;) {
 		unsigned long time;
 		unsigned long diff;
@@ -172,6 +180,7 @@
 		
 		/* Disable arbiter, park on CPU */
 		acpi_hw_register_bit_access(ACPI_WRITE, ACPI_MTX_LOCK, ARB_DIS, 1);
+		acpi_c3_count++;
 		inb(acpi_pblk + ACPI_P_LVL3);
 		/* Dummy read, force synchronization with the PMU */
 		acpi_read_pm_timer();
@@ -181,10 +190,10 @@
 
 		__sti();
 		if (diff < acpi_c3_exit_latency)
-			goto sleep2;
+			goto sleep1;
 	}
 
-      sleep2:
+sleep2:
 	sleep_level = 2;
 	if (!acpi_c2_tested) {
 		DEBUG_PRINT(ACPI_INFO, ("C2 works\n"));
@@ -200,6 +209,7 @@
 			goto out;
 
 		time = acpi_read_pm_timer();
+		acpi_c2_count++;
 		inb(acpi_pblk + ACPI_P_LVL2);
 		/* Dummy read, force synchronization with the PMU */
 		acpi_read_pm_timer();
@@ -217,7 +227,7 @@
 			goto sleep3;
 	}
 
-      sleep1:
+sleep1:
 	sleep_level = 1;
 	acpi_sleep_on_busmaster();
 	for (;;) {
@@ -228,6 +238,7 @@
 		if (current->need_resched)
 			goto out;
 		time = acpi_read_pm_timer();
+		acpi_c1_count++;
 		safe_halt();
 		diff = acpi_compare_pm_timers(time, acpi_read_pm_timer());
 		if (diff > acpi_c2_enter_latency
@@ -235,15 +246,7 @@
 			goto sleep2;
 	}
 
-      not_initialized:
-	for (;;) {
-		__cli();
-		if (current->need_resched)
-			goto out;
-		safe_halt();
-	}
-
-      out:
+out:
 	__sti();
 }
 
@@ -278,17 +281,17 @@
 		acpi_c2_exit_latency
 			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat);
 		acpi_c2_enter_latency
-			= ACPI_MICROSEC_TO_TMR_TICKS(ACPI_TMR_HZ / 1000);
+			= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl2_lat * 4);
 		acpi_max_c_state = 2;
 
 		printk(KERN_INFO "ACPI: System firmware supports: C2");
-	
+			
 		if (acpi_fadt.plvl3_lat
 		    && acpi_fadt.plvl3_lat <= MAX_C3_LATENCY) {
 			acpi_c3_exit_latency
 				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat);
 			acpi_c3_enter_latency
-				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 5);
+				= ACPI_MICROSEC_TO_TMR_TICKS(acpi_fadt.plvl3_lat * 12);
 			acpi_max_c_state = 3;
 
 			printk(" C3");
@@ -297,6 +300,10 @@
 		printk("\n");
 	}
 
+	printk(KERN_INFO "ACPI: plvl2lat=%d plvl3lat=%d\n", acpi_fadt.plvl2_lat, acpi_fadt.plvl3_lat);
+	printk(KERN_INFO "ACPI: C2 enter=%d C2 exit=%d\n", acpi_c2_enter_latency, acpi_c2_exit_latency);
+	printk(KERN_INFO "ACPI: C3 enter=%d C3 exit=%d\n", acpi_c3_enter_latency, acpi_c3_exit_latency);
+
 	return AE_OK;
 }
 
@@ -328,13 +335,19 @@
 
 	acpi_pm_timer_init();
 
-
+	if (acpi_use_idle) {
 #ifdef CONFIG_SMP
-	if (smp_num_cpus == 1)
-		pm_idle = acpi_idle;
+		if (smp_num_cpus == 1)
+			pm_idle = acpi_idle;
 #else
-	pm_idle = acpi_idle;
+		pm_idle = acpi_idle;
 #endif
+		printk(KERN_INFO "ACPI: Using ACPI idle\n");
+		printk(KERN_INFO "ACPI: If experiencing system slowness, try adding \"acpi=no-idle\" to cmdline\n");
+	}
+	else {
+		printk(KERN_INFO "ACPI: Not using ACPI idle\n");
+	}
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/dispatcher/dsobject.c linux/drivers/acpi/dispatcher/dsobject.c
--- v2.4.1/linux/drivers/acpi/dispatcher/dsobject.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/dispatcher/dsobject.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dsobject - Dispatcher object management routines
- *              $Revision: 56 $
+ *              $Revision: 57 $
  *
  *****************************************************************************/
 
@@ -101,6 +101,7 @@
 	case ACPI_TYPE_METHOD:
 
 		info->method_count++;
+
 
 		/*
 		 * Set the execution data width (32 or 64) based upon the
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/dispatcher/dsopcode.c linux/drivers/acpi/dispatcher/dsopcode.c
--- v2.4.1/linux/drivers/acpi/dispatcher/dsopcode.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/dispatcher/dsopcode.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
  *
  * Module Name: dsopcode - Dispatcher Op Region support and handling of
  *                         "control" opcodes
- *              $Revision: 30 $
+ *              $Revision: 32 $
  *
  *****************************************************************************/
 
@@ -72,7 +72,6 @@
 
 	extra_desc = obj_desc->field_unit.extra;
 	node = obj_desc->field_unit.node;
-
 
 	/*
 	 * Allocate a new parser op to be the root of the parsed
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/driver.c linux/drivers/acpi/driver.c
--- v2.4.1/linux/drivers/acpi/driver.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/driver.c	Fri Feb  9 11:45:58 2001
@@ -60,6 +60,8 @@
 
 static volatile int acpi_thread_pid = -1;
 
+static int acpi_start = 1;
+
 /************************************************/
 /* DECLARE_TASK_QUEUE is defined in             */
 /* /usr/src/linux/include/linux/tqueue.h        */
@@ -382,6 +384,19 @@
 	 &acpi_c3_enter_latency, sizeof(acpi_c3_enter_latency),
 	 0644, NULL, &acpi_do_ulong},
 
+	{ACPI_C1_COUNT, "c1_count",
+	 &acpi_c1_count, sizeof(acpi_c1_count),
+	 0644, NULL, &acpi_do_ulong},
+
+	{ACPI_C2_COUNT, "c2_count",
+	 &acpi_c2_count, sizeof(acpi_c2_count),
+	 0644, NULL, &acpi_do_ulong},
+
+	{ACPI_C3_COUNT, "c3_count",
+	 &acpi_c3_count, sizeof(acpi_c3_count),
+	 0644, NULL, &acpi_do_ulong},
+
+	
 /* until it actually works */
 /*	{ACPI_SLEEP, "sleep", NULL, 0, 0600, NULL, &acpi_do_sleep},*/
 
@@ -540,10 +555,16 @@
 int __init
 acpi_init(void)
 {
-	acpi_thread_pid = kernel_thread(acpi_thread,
+	if (acpi_start) {
+		acpi_thread_pid = kernel_thread(acpi_thread,
 					NULL,
 					(CLONE_FS | CLONE_FILES
 					 | CLONE_SIGHAND | SIGCHLD));
+	}
+	else {
+		printk(KERN_INFO "ACPI: Disabled\n");
+	}
+
 	return ((acpi_thread_pid >= 0) ? 0:-ENODEV);
 }
 
@@ -571,3 +592,21 @@
 
 module_init(acpi_init);
 module_exit(acpi_exit);
+
+#ifndef MODULE
+static int __init acpi_setup(char *str)
+{
+	while ((str != NULL) && (*str != '\0')) {
+		if (strncmp(str, "no-idle", 7) == 0)
+			acpi_use_idle = 0;
+		if (strncmp(str, "off", 3) == 0)
+			acpi_start = 0;
+		str = strchr(str, ',');
+		if (str != NULL)
+			str += strspn(str, ", \t");
+	}
+	return 1;
+}
+
+__setup("acpi=", acpi_setup);
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/driver.h linux/drivers/acpi/driver.h
--- v2.4.1/linux/drivers/acpi/driver.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/acpi/driver.h	Fri Feb  9 11:45:58 2001
@@ -37,10 +37,14 @@
 int acpi_cpu_init(void);
 u32 acpi_read_pm_timer(void);
 
-extern unsigned long acpi_c2_exit_latency;
-extern unsigned long acpi_c3_exit_latency;
-extern unsigned long acpi_c2_enter_latency;
-extern unsigned long acpi_c3_enter_latency;
+extern u32 acpi_c2_exit_latency;
+extern u32 acpi_c3_exit_latency;
+extern u32 acpi_c2_enter_latency;
+extern u32 acpi_c3_enter_latency;
+extern u32 acpi_use_idle;
+extern u32 acpi_c1_count;
+extern u32 acpi_c2_count;
+extern u32 acpi_c3_count;
 
 /*
  * driver.c
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/ec.c linux/drivers/acpi/ec.c
--- v2.4.1/linux/drivers/acpi/ec.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/ec.c	Fri Feb  9 11:45:58 2001
@@ -554,7 +554,7 @@
 
 	ec_cxt->need_global_lock = obj.integer.value;
 
-	printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,gpe %d GL %d)\n",
+	printk(KERN_INFO "ACPI: found EC @ (0x%02x,0x%02x,GPE %d GL %d)\n",
 		ec_cxt->data_port, ec_cxt->status_port, ec_cxt->gpe_bit,
 		ec_cxt->need_global_lock);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/events/evevent.c linux/drivers/acpi/events/evevent.c
--- v2.4.1/linux/drivers/acpi/events/evevent.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/events/evevent.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
  *
  * Module Name: evevent - Fixed and General Purpose Acpi_event
  *                          handling and dispatch
- *              $Revision: 33 $
+ *              $Revision: 34 $
  *
  *****************************************************************************/
 
@@ -55,7 +55,7 @@
 	ACPI_STATUS             status;
 
 
-	/* Make sure we've got ACPI tables */
+	/* Make sure we have ACPI tables */
 
 	if (!acpi_gbl_DSDT) {
 		return (AE_NO_ACPI_TABLES);
@@ -704,7 +704,7 @@
 acpi_ev_gpe_dispatch (
 	u32                     gpe_number)
 {
-		ACPI_GPE_LEVEL_INFO     gpe_info;
+	ACPI_GPE_LEVEL_INFO     gpe_info;
 
 	/*DEBUG_INCREMENT_EVENT_COUNT (EVENT_GENERAL);*/
 
@@ -720,59 +720,58 @@
 	 */
 	acpi_hw_disable_gpe (gpe_number);
 
-		gpe_info = acpi_gbl_gpe_info [gpe_number];
-
-		/*
-		 * Edge-Triggered?
-		 * ---------------
-		 * If edge-triggered, clear the GPE status bit now.  Note that
-		 * level-triggered events are cleared after the GPE is serviced.
-		 */
-		if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) {
-				acpi_hw_clear_gpe (gpe_number);
-		}
+	gpe_info = acpi_gbl_gpe_info [gpe_number];
 
+	/*
+	 * Edge-Triggered?
+	 * ---------------
+	 * If edge-triggered, clear the GPE status bit now.  Note that
+	 * level-triggered events are cleared after the GPE is serviced.
+	 */
+	if (gpe_info.type & ACPI_EVENT_EDGE_TRIGGERED) {
+		acpi_hw_clear_gpe (gpe_number);
+	}
 		/*
 		 * Function Handler (e.g. EC)?
 		 */
-		if (gpe_info.handler) {
-				/* Invoke function handler (at interrupt level). */
-				gpe_info.handler (gpe_info.context);
-
-				/* Level-Triggered? */
-				if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
-						acpi_hw_clear_gpe (gpe_number);
-				}
-
-				/* Enable GPE */
-				acpi_hw_enable_gpe (gpe_number);
+	if (gpe_info.handler) {
+		/* Invoke function handler (at interrupt level). */
+		gpe_info.handler (gpe_info.context);
+
+		/* Level-Triggered? */
+		if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
+			acpi_hw_clear_gpe (gpe_number);
 		}
-		/*
-		 * Method Handler (e.g. _Exx/_Lxx)?
-		 */
-		else if (gpe_info.method_handle) {
-				if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
+
+		/* Enable GPE */
+		acpi_hw_enable_gpe (gpe_number);
+	}
+	/*
+	 * Method Handler (e.g. _Exx/_Lxx)?
+	 */
+	else if (gpe_info.method_handle) {
+		if (ACPI_FAILURE(acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
 			acpi_ev_asynch_execute_gpe_method, (void*)(NATIVE_UINT)gpe_number)))
-				{
-						/*
-						 * Shoudn't occur, but if it does report an error. Note that
-						 * the GPE will remain disabled until the ACPI Core Subsystem
-						 * is restarted, or the handler is removed/reinstalled.
-						 */
-						REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number));
-				}
+		{
+			/*
+			 * Shoudn't occur, but if it does report an error. Note that
+			 * the GPE will remain disabled until the ACPI Core Subsystem
+			 * is restarted, or the handler is removed/reinstalled.
+			 */
+			REPORT_ERROR (("Acpi_ev_gpe_dispatch: Unable to queue handler for GPE bit [%X]\n", gpe_number));
 		}
-		/*
-		 * No Handler? Report an error and leave the GPE disabled.
-		 */
-		else {
-				REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number));
+	}
+	/*
+	 * No Handler? Report an error and leave the GPE disabled.
+	 */
+	else {
+		REPORT_ERROR (("Acpi_ev_gpe_dispatch: No installed handler for GPE [%X]\n", gpe_number));
 
-				/* Level-Triggered? */
-				if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
-						acpi_hw_clear_gpe (gpe_number);
-				}
+		/* Level-Triggered? */
+		if (gpe_info.type & ACPI_EVENT_LEVEL_TRIGGERED) {
+			acpi_hw_clear_gpe (gpe_number);
 		}
+	}
 
 	return (INTERRUPT_HANDLED);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/events/evregion.c linux/drivers/acpi/events/evregion.c
--- v2.4.1/linux/drivers/acpi/events/evregion.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/events/evregion.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: evregion - ACPI Address_space (Op_region) handler dispatch
- *              $Revision: 94 $
+ *              $Revision: 96 $
  *
  *****************************************************************************/
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/hardware/hwsleep.c linux/drivers/acpi/hardware/hwsleep.c
--- v2.4.1/linux/drivers/acpi/hardware/hwsleep.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/hardware/hwsleep.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
- *              $Revision: 5 $
+ *              $Revision: 7 $
  *
  *****************************************************************************/
 
@@ -175,15 +175,14 @@
 	PM1_acontrol |= (type_a << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
 	PM1_bcontrol |= (type_b << acpi_hw_get_bit_shift (SLP_TYPE_X_MASK));
 
-	/* the old version was disabling interrupts. let's try it without
-	 * and see how that works
-	 */
-	/*disable();*/
+	disable();
 
 	acpi_hw_register_write(ACPI_MTX_LOCK, PM1_a_CONTROL, PM1_acontrol);
 	acpi_hw_register_write(ACPI_MTX_LOCK, PM1_b_CONTROL, PM1_bcontrol);
+	acpi_hw_register_write(ACPI_MTX_LOCK, PM1_CONTROL,
+		(1 << acpi_hw_get_bit_shift (SLP_EN_MASK)));
 
-	/*enable();*/
+	enable();
 
 	return (AE_OK);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/hardware/hwtimer.c linux/drivers/acpi/hardware/hwtimer.c
--- v2.4.1/linux/drivers/acpi/hardware/hwtimer.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/hardware/hwtimer.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Name: hwtimer.c - ACPI Power Management Timer Interface
- *              $Revision: 4 $
+ *              $Revision: 5 $
  *
  *****************************************************************************/
 
@@ -133,7 +133,7 @@
 	/*
 	 * Compute Tick Delta:
 	 * -------------------
-	 * Handle timer rollovers on 24- versus 32-bit timers.
+	 * Handle (max one) timer rollovers on 24- versus 32-bit timers.
 	 */
 	if (start_ticks < end_ticks) {
 		delta_ticks = end_ticks - start_ticks;
@@ -141,12 +141,16 @@
 	else if (start_ticks > end_ticks) {
 		/* 24-bit Timer */
 		if (0 == acpi_gbl_FADT->tmr_val_ext) {
-			delta_ticks = (0x00FFFFFF - start_ticks) + end_ticks;
+			delta_ticks = (((0x00FFFFFF - start_ticks) + end_ticks) & 0x00FFFFFF);
 		}
 		/* 32-bit Timer */
 		else {
 			delta_ticks = (0xFFFFFFFF - start_ticks) + end_ticks;
 		}
+	}
+	else {
+		*time_elapsed = 0;
+		return (AE_OK);
 	}
 
 	/*
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/accommon.h linux/drivers/acpi/include/accommon.h
--- v2.4.1/linux/drivers/acpi/include/accommon.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/accommon.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: accommon.h -- prototypes for the common (subsystem-wide) procedures
- *       $Revision: 87 $
+ *       $Revision: 90 $
  *
  *****************************************************************************/
 
@@ -27,6 +27,30 @@
 #define _ACCOMMON_H
 
 
+typedef
+ACPI_STATUS (*ACPI_PKG_CALLBACK) (
+	u8                      object_type,
+	ACPI_OPERAND_OBJECT     *source_object,
+	ACPI_GENERIC_STATE      *state,
+	void                    *context);
+
+
+ACPI_STATUS
+acpi_cm_walk_package_tree (
+	ACPI_OPERAND_OBJECT     *source_object,
+	void                    *target_object,
+	ACPI_PKG_CALLBACK       walk_callback,
+	void                    *context);
+
+
+typedef struct acpi_pkg_info
+{
+	u8                      *free_space;
+	u32                     length;
+	u32                     object_space;
+	u32                     num_packages;
+} ACPI_PKG_INFO;
+
 #define REF_INCREMENT       (u16) 0
 #define REF_DECREMENT       (u16) 1
 #define REF_FORCE_DELETE    (u16) 2
@@ -194,29 +218,30 @@
 	u32                     *space_used);
 
 ACPI_STATUS
-acpi_cm_build_external_object (
+acpi_cm_copy_iobject_to_eobject (
 	ACPI_OPERAND_OBJECT     *obj,
 	ACPI_BUFFER             *ret_buffer);
 
 ACPI_STATUS
-acpi_cm_build_internal_simple_object(
+acpi_cm_copy_esimple_to_isimple(
 	ACPI_OBJECT             *user_obj,
 	ACPI_OPERAND_OBJECT     *obj);
 
 ACPI_STATUS
-acpi_cm_build_internal_object (
+acpi_cm_copy_eobject_to_iobject (
 	ACPI_OBJECT             *obj,
 	ACPI_OPERAND_OBJECT     *internal_obj);
 
 ACPI_STATUS
-acpi_cm_copy_internal_simple_object (
+acpi_cm_copy_isimple_to_isimple (
 	ACPI_OPERAND_OBJECT     *source_obj,
 	ACPI_OPERAND_OBJECT     *dest_obj);
 
 ACPI_STATUS
-acpi_cm_build_copy_internal_package_object (
+acpi_cm_copy_ipackage_to_ipackage (
 	ACPI_OPERAND_OBJECT     *source_obj,
-	ACPI_OPERAND_OBJECT     *dest_obj);
+	ACPI_OPERAND_OBJECT     *dest_obj,
+	ACPI_WALK_STATE         *walk_state);
 
 
 /*
@@ -526,12 +551,25 @@
 	ACPI_OPERAND_OBJECT     *object,
 	u16                     action);
 
+ACPI_GENERIC_STATE *
+acpi_cm_create_pkg_state (
+	void                    *internal_object,
+	void                    *external_object,
+	u16                     index);
+
 ACPI_STATUS
 acpi_cm_create_update_state_and_push (
 	ACPI_OPERAND_OBJECT     *object,
 	u16                     action,
 	ACPI_GENERIC_STATE      **state_list);
 
+ACPI_STATUS
+acpi_cm_create_pkg_state_and_push (
+	void                    *internal_object,
+	void                    *external_object,
+	u16                     index,
+	ACPI_GENERIC_STATE      **state_list);
+
 ACPI_GENERIC_STATE *
 acpi_cm_create_control_state (
 	void);
@@ -563,6 +601,15 @@
 ACPI_STATUS
 acpi_cm_resolve_package_references (
 	ACPI_OPERAND_OBJECT     *obj_desc);
+
+#ifdef ACPI_DEBUG
+
+void
+acpi_cm_display_init_pathname (
+	ACPI_HANDLE             obj_handle,
+	char                    *path);
+
+#endif
 
 
 /*
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/acconfig.h linux/drivers/acpi/include/acconfig.h
--- v2.4.1/linux/drivers/acpi/include/acconfig.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/acconfig.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acconfig.h - Global configuration constants
- *       $Revision: 53 $
+ *       $Revision: 55 $
  *
  *****************************************************************************/
 
@@ -53,7 +53,7 @@
 
 /* Version string */
 
-#define ACPI_CA_VERSION             0x20010125
+#define ACPI_CA_VERSION             0x20010208
 
 
 /* Maximum objects in the various object caches */
@@ -147,11 +147,6 @@
 #define LO_RSDP_WINDOW_SIZE         0x400
 #define HI_RSDP_WINDOW_SIZE         0x20000
 #define RSDP_SCAN_STEP              16
-
-
-/* Maximum nesting of package objects */
-
-#define MAX_PACKAGE_DEPTH           16
 
 
 #endif /* _ACCONFIG_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/acdebug.h linux/drivers/acpi/include/acdebug.h
--- v2.4.1/linux/drivers/acpi/include/acdebug.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/acdebug.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acdebug.h - ACPI/AML debugger
- *       $Revision: 39 $
+ *       $Revision: 41 $
  *
  *****************************************************************************/
 
@@ -43,6 +43,7 @@
 extern u8                       opt_stats;
 extern u8                       opt_parse_jit;
 extern u8                       opt_verbose;
+extern u8                       opt_ini_methods;
 
 
 extern NATIVE_CHAR              *args[DB_MAX_ARGS];
@@ -196,6 +197,10 @@
 
 void
 acpi_db_find_references (
+	NATIVE_CHAR             *object_arg);
+
+void
+acpi_db_display_resources (
 	NATIVE_CHAR             *object_arg);
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/acgcc.h linux/drivers/acpi/include/acgcc.h
--- v2.4.1/linux/drivers/acpi/include/acgcc.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/acgcc.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acgcc.h - GCC specific defines, etc.
- *       $Revision: 4 $
+ *       $Revision: 5 $
  *
  *****************************************************************************/
 
@@ -26,12 +26,11 @@
 #ifndef __ACGCC_H__
 #define __ACGCC_H__
 
-#define COMPILER_DEPENDENT_UINT64   unsigned long long
-
 
 #ifdef __ia64__
 #define _IA64
 
+#define COMPILER_DEPENDENT_UINT64   unsigned long
 /* Single threaded */
 #define ACPI_APPLICATION
 
@@ -95,8 +94,7 @@
 
 
 #else /* DO IA32 */
-
-
+#define COMPILER_DEPENDENT_UINT64   unsigned long long
 #define ACPI_ASM_MACROS
 #define causeinterrupt(level)
 #define BREAKPOINT3
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/acinterp.h linux/drivers/acpi/include/acinterp.h
--- v2.4.1/linux/drivers/acpi/include/acinterp.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/acinterp.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acinterp.h - Interpreter subcomponent prototypes and defines
- *       $Revision: 91 $
+ *       $Revision: 92 $
  *
  *****************************************************************************/
 
@@ -557,12 +557,6 @@
 acpi_aml_unsigned_integer_to_string (
 	ACPI_INTEGER            value,
 	NATIVE_CHAR             *out_string);
-
-ACPI_STATUS
-acpi_aml_build_copy_internal_package_object (
-	ACPI_OPERAND_OBJECT     *source_obj,
-	ACPI_OPERAND_OBJECT     *dest_obj,
-	ACPI_WALK_STATE         *walk_state);
 
 
 /*
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/aclinux.h linux/drivers/acpi/include/aclinux.h
--- v2.4.1/linux/drivers/acpi/include/aclinux.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/aclinux.h	Fri Feb 16 16:06:17 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: aclinux.h - OS specific defines, etc.
- *       $Revision: 7 $
+ *       $Revision: 9 $
  *
  *****************************************************************************/
 
@@ -26,7 +26,6 @@
 #ifndef __ACLINUX_H__
 #define __ACLINUX_H__
 
-
 #define ACPI_OS_NAME                "Linux"
 
 #include <linux/string.h>
@@ -34,6 +33,7 @@
 #include <linux/ctype.h>
 #include <asm/system.h>
 #include <asm/atomic.h>
+#include <asm/div64.h>
 
 /* Linux uses GCC */
 
@@ -42,9 +42,14 @@
 #undef DEBUGGER_THREADING
 #define DEBUGGER_THREADING          DEBUGGER_SINGLE_THREADED
 
-/* Linux ia32 can't do int64 well */
 #ifndef _IA64
+/* Linux ia32 can't do int64 well */
 #define ACPI_NO_INTEGER64_SUPPORT
+/* And the ia32 kernel doesn't include 64-bit divide support */
+#define ACPI_DIV64(dividend, divisor) do_div(dividend, divisor)
+#else
+#define ACPI_DIV64(dividend, divisor) ACPI_DIVIDE(dividend, divisor)
 #endif
+
 
 #endif /* __ACLINUX_H__ */
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/aclocal.h linux/drivers/acpi/include/aclocal.h
--- v2.4.1/linux/drivers/acpi/include/aclocal.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/aclocal.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: aclocal.h - Internal data types used across the ACPI subsystem
- *       $Revision: 100 $
+ *       $Revision: 104 $
  *
  *****************************************************************************/
 
@@ -368,6 +368,23 @@
 
 } ACPI_UPDATE_STATE;
 
+
+/*
+ * Pkg state - used to traverse nested package structures
+ */
+typedef struct acpi_pkg_state
+{
+	ACPI_STATE_COMMON
+	union acpi_operand_obj  *source_object;
+	union acpi_operand_obj  *dest_object;
+	struct acpi_walk_state  *walk_state;
+	void                    *this_target_obj;
+	u32                     num_packages;
+	u16                     index;
+
+} ACPI_PKG_STATE;
+
+
 /*
  * Control state - one per if/else and while constructs.
  * Allows nesting of these constructs
@@ -428,6 +445,7 @@
 	ACPI_UPDATE_STATE       update;
 	ACPI_SCOPE_STATE        scope;
 	ACPI_PSCOPE_STATE       parse_scope;
+	ACPI_PKG_STATE          pkg;
 	ACPI_RESULT_VALUES      results;
 
 } ACPI_GENERIC_STATE;
@@ -650,7 +668,6 @@
 
 typedef struct acpi_device_walk_info
 {
-	u32                     flags;
 	u16                     device_count;
 	u16                     num_STA;
 	u16                     num_INI;
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/acnamesp.h linux/drivers/acpi/include/acnamesp.h
--- v2.4.1/linux/drivers/acpi/include/acnamesp.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/acnamesp.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acnamesp.h - Namespace subcomponent prototypes and defines
- *       $Revision: 101 $
+ *       $Revision: 103 $
  *
  *****************************************************************************/
 
@@ -72,7 +72,7 @@
 
 ACPI_STATUS
 acpi_ns_initialize_devices (
-	u32                     flags);
+	void);
 
 
 /* Namespace init - nsxfinit */
@@ -316,6 +316,11 @@
 	NATIVE_CHAR             *pathname,
 	ACPI_NAMESPACE_NODE     *in_prefix_node,
 	ACPI_NAMESPACE_NODE     **out_node);
+
+u32
+acpi_ns_get_pathname_length (
+	ACPI_NAMESPACE_NODE     *node);
+
 
 /*
  * Object management for NTEs - nsobject
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/acoutput.h linux/drivers/acpi/include/acoutput.h
--- v2.4.1/linux/drivers/acpi/include/acoutput.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/acoutput.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: acoutput.h -- debug output
- *       $Revision: 69 $
+ *       $Revision: 70 $
  *
  *****************************************************************************/
 
@@ -96,6 +96,7 @@
 #define TRACE_USER_REQUESTS         0x01000000
 #define TRACE_PACKAGE               0x02000000
 #define TRACE_MUTEX                 0x04000000
+#define TRACE_INIT                  0x08000000
 
 #define TRACE_ALL                   0x0FFFFF00
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/include/actypes.h linux/drivers/acpi/include/actypes.h
--- v2.4.1/linux/drivers/acpi/include/actypes.h	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/include/actypes.h	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Name: actypes.h - Common data types for the entire ACPI subsystem
- *       $Revision: 163 $
+ *       $Revision: 165 $
  *
  *****************************************************************************/
 
@@ -237,8 +237,7 @@
 #define ACPI_NO_EVENT_INIT              0x04
 #define ACPI_NO_ACPI_ENABLE             0x08
 #define ACPI_NO_DEVICE_INIT             0x10
-#define ACPI_NO_PCI_INIT                0x20
-#define ACPI_NO_OBJECT_INIT             0x40
+#define ACPI_NO_OBJECT_INIT             0x20
 
 
 /*
@@ -1029,22 +1028,14 @@
  * END: Definitions for Resource Attributes
  */
 
-/*
- * Definitions for PCI Routing tables
- */
-typedef struct
-{
-	ACPI_INTEGER                address;
-	u32                         pin;
-	u32                         source_index;
-	NATIVE_CHAR                 source[1];
-
-} PRT_ENTRY;
 
-typedef struct _prt_tag
+typedef struct pci_routing_table
 {
 	u32                         length;
-	PRT_ENTRY                   data;
+	u32                         pin;
+	ACPI_INTEGER                address;        /* here for 64-bit alignment */
+	u32                         source_index;
+	NATIVE_CHAR                 source[4];      /* pad to 64 bits so sizeof() works in all cases */
 
 } PCI_ROUTING_TABLE;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/interpreter/amfldio.c linux/drivers/acpi/interpreter/amfldio.c
--- v2.4.1/linux/drivers/acpi/interpreter/amfldio.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/interpreter/amfldio.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: amfldio - Aml Field I/O
- *              $Revision: 37 $
+ *              $Revision: 39 $
  *
  *****************************************************************************/
 
@@ -415,7 +415,8 @@
 
 		/* Check if update rule needs to be applied (not if mask is all ones) */
 
-		if (((1 << bit_granularity) -1) & ~mask) {
+		/* The left shift drops the bits we want to ignore. */
+		if ((~mask << (sizeof(mask)*8 - bit_granularity)) != 0) {
 			/*
 			 * Read the current contents of the byte/word/dword containing
 			 * the field, and merge with the new field value.
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/interpreter/amstore.c linux/drivers/acpi/interpreter/amstore.c
--- v2.4.1/linux/drivers/acpi/interpreter/amstore.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/interpreter/amstore.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: amstore - AML Interpreter object store support
- *              $Revision: 121 $
+ *              $Revision: 123 $
  *
  *****************************************************************************/
 
@@ -268,8 +268,7 @@
 				 * If the source is a package, copy the source to the new dest
 				 */
 				if (ACPI_TYPE_PACKAGE == obj_desc->common.type) {
-					status = acpi_aml_build_copy_internal_package_object (
-							 val_desc, obj_desc, walk_state);
+					status = acpi_cm_copy_ipackage_to_ipackage (val_desc, obj_desc, walk_state);
 					if (ACPI_FAILURE (status)) {
 						acpi_cm_remove_reference (obj_desc);
 						return (status);
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/interpreter/amstorob.c linux/drivers/acpi/interpreter/amstorob.c
--- v2.4.1/linux/drivers/acpi/interpreter/amstorob.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/interpreter/amstorob.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: amstorob - AML Interpreter object store support, store to object
- *              $Revision: 22 $
+ *              $Revision: 23 $
  *
  *****************************************************************************/
 
@@ -66,6 +66,19 @@
 	length = source_desc->buffer.length;
 
 	/*
+	 * If target is a buffer of length zero, allocate a new
+	 * buffer of the proper length
+	 */
+	if (target_desc->buffer.length == 0) {
+		target_desc->buffer.pointer = acpi_cm_allocate (length);
+		if (!target_desc->buffer.pointer) {
+			return (AE_NO_MEMORY);
+		}
+
+		target_desc->buffer.length = length;
+	}
+
+	/*
 	 * Buffer is a static allocation,
 	 * only place what will fit in the buffer.
 	 */
@@ -141,11 +154,11 @@
 		}
 
 		target_desc->string.pointer = acpi_cm_allocate (length + 1);
-		target_desc->string.length = length;
-
 		if (!target_desc->string.pointer) {
 			return (AE_NO_MEMORY);
 		}
+		target_desc->string.length = length;
+
 
 		MEMCPY(target_desc->string.pointer, buffer, length);
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/interpreter/amutils.c linux/drivers/acpi/interpreter/amutils.c
--- v2.4.1/linux/drivers/acpi/interpreter/amutils.c	Sat Feb  3 19:51:25 2001
+++ linux/drivers/acpi/interpreter/amutils.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
 /******************************************************************************
  *
  * Module Name: amutils - interpreter/scanner utilities
- *              $Revision: 68 $
+ *              $Revision: 69 $
  *
  *****************************************************************************/
 
@@ -36,21 +36,6 @@
 	 MODULE_NAME         ("amutils")
 
 
-typedef struct internal_search_st
-{
-	ACPI_OPERAND_OBJECT         *dest_obj;
-	u32                         index;
-	ACPI_OPERAND_OBJECT         *source_obj;
-
-} INTERNAL_PKG_SEARCH_INFO;
-
-
-/* Used to traverse nested packages when copying*/
-/* TBD: This must be removed! */
-
-INTERNAL_PKG_SEARCH_INFO        copy_level[MAX_PACKAGE_DEPTH];
-
-
 /*******************************************************************************
  *
  * FUNCTION:    Acpi_aml_enter_interpreter
@@ -380,156 +365,6 @@
 	}
 
 	return (AE_OK);
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION:    Acpi_aml_build_copy_internal_package_object
- *
- * PARAMETERS:  *Source_obj     - Pointer to the source package object
- *              *Dest_obj       - Where the internal object is returned
- *
- * RETURN:      Status          - the status of the call
- *
- * DESCRIPTION: This function is called to copy an internal package object
- *              into another internal package object.
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_aml_build_copy_internal_package_object (
-	ACPI_OPERAND_OBJECT     *source_obj,
-	ACPI_OPERAND_OBJECT     *dest_obj,
-	ACPI_WALK_STATE         *walk_state)
-{
-	u32                         current_depth = 0;
-	ACPI_STATUS                 status = AE_OK;
-	u32                         length = 0;
-	u32                         this_index;
-	u32                         object_space = 0;
-	ACPI_OPERAND_OBJECT         *this_dest_obj;
-	ACPI_OPERAND_OBJECT         *this_source_obj;
-	INTERNAL_PKG_SEARCH_INFO    *level_ptr;
-
-
-	/*
-	 * Initialize the working variables
-	 */
-
-	MEMSET ((void *) copy_level, 0, sizeof(copy_level));
-
-	copy_level[0].dest_obj  = dest_obj;
-	copy_level[0].source_obj = source_obj;
-	level_ptr               = &copy_level[0];
-	current_depth           = 0;
-
-	dest_obj->common.type   = source_obj->common.type;
-	dest_obj->package.count = source_obj->package.count;
-
-
-	/*
-	 * Build an array of ACPI_OBJECTS in the buffer
-	 * and move the free space past it
-	 */
-
-	dest_obj->package.elements  = acpi_cm_callocate (
-			 (dest_obj->package.count + 1) *
-			 sizeof (void *));
-	if (!dest_obj->package.elements) {
-		/* Package vector allocation failure   */
-
-		REPORT_ERROR (("Aml_build_copy_internal_package_object: Package vector allocation failure\n"));
-		return (AE_NO_MEMORY);
-	}
-
-	dest_obj->package.next_element = dest_obj->package.elements;
-
-
-	while (1) {
-		this_index      = level_ptr->index;
-		this_dest_obj   = (ACPI_OPERAND_OBJECT *) level_ptr->dest_obj->package.elements[this_index];
-		this_source_obj = (ACPI_OPERAND_OBJECT *) level_ptr->source_obj->package.elements[this_index];
-
-		if (IS_THIS_OBJECT_TYPE (this_source_obj, ACPI_TYPE_PACKAGE)) {
-			/*
-			 * If this object is a package then we go one deeper
-			 */
-			if (current_depth >= MAX_PACKAGE_DEPTH-1) {
-				/*
-				 * Too many nested levels of packages for us to handle
-				 */
-				return (AE_LIMIT);
-			}
-
-			/*
-			 * Build the package object
-			 */
-			this_dest_obj = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
-			level_ptr->dest_obj->package.elements[this_index] = this_dest_obj;
-
-
-			this_dest_obj->common.type      = ACPI_TYPE_PACKAGE;
-			this_dest_obj->package.count    = this_dest_obj->package.count;
-
-			/*
-			 * Save space for the array of objects (Package elements)
-			 * update the buffer length counter
-			 */
-			object_space            = this_dest_obj->package.count *
-					  sizeof (ACPI_OPERAND_OBJECT);
-			length                  += object_space;
-			current_depth++;
-			level_ptr               = &copy_level[current_depth];
-			level_ptr->dest_obj     = this_dest_obj;
-			level_ptr->source_obj   = this_source_obj;
-			level_ptr->index        = 0;
-
-		}   /* if object is a package */
-
-		else {
-
-			this_dest_obj = acpi_cm_create_internal_object (
-					   this_source_obj->common.type);
-			level_ptr->dest_obj->package.elements[this_index] = this_dest_obj;
-
-			status = acpi_aml_store_object_to_object(this_source_obj, this_dest_obj, walk_state);
-
-			if (ACPI_FAILURE (status)) {
-				/*
-				 * Failure get out
-				 */
-				return (status);
-			}
-
-			length      +=object_space;
-
-			level_ptr->index++;
-			while (level_ptr->index >= level_ptr->dest_obj->package.count) {
-				/*
-				 * We've handled all of the objects at this level,  This means
-				 * that we have just completed a package.  That package may
-				 * have contained one or more packages itself
-				 */
-				if (current_depth == 0) {
-					/*
-					 * We have handled all of the objects in the top level
-					 * package just add the length of the package objects
-					 * and exit
-					 */
-					return (AE_OK);
-				}
-
-				/*
-				 * Go back up a level and move the index past the just
-				 * completed package object.
-				 */
-				current_depth--;
-				level_ptr = &copy_level[current_depth];
-				level_ptr->index++;
-			}
-		}   /* else object is NOT a package */
-	}   /* while (1)  */
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/namespace/nseval.c linux/drivers/acpi/namespace/nseval.c
--- v2.4.1/linux/drivers/acpi/namespace/nseval.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/namespace/nseval.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
  *
  * Module Name: nseval - Object evaluation interfaces -- includes control
  *                       method lookup and execution.
- *              $Revision: 81 $
+ *              $Revision: 83 $
  *
  ******************************************************************************/
 
@@ -253,8 +253,8 @@
 
 	node = acpi_ns_convert_handle_to_entry (handle);
 	if (!node) {
-		status = AE_BAD_PARAMETER;
-		goto unlock_and_exit;
+		acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+		return (AE_BAD_PARAMETER);
 	}
 
 
@@ -316,12 +316,6 @@
 	 * so we just return
 	 */
 	return (status);
-
-
-unlock_and_exit:
-
-	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
-	return (status);
 }
 
 
@@ -354,14 +348,6 @@
 	ACPI_OPERAND_OBJECT     *obj_desc;
 
 
-	/* Verify that there is a method associated with this object */
-
-	obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node);
-	if (!obj_desc) {
-		return (AE_ERROR);
-	}
-
-
 	/*
 	 * Unlock the namespace before execution.  This allows namespace access
 	 * via the external Acpi* interfaces while a method is being executed.
@@ -372,8 +358,16 @@
 
 	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
 
+	/* Verify that there is a method associated with this object */
+
+	obj_desc = acpi_ns_get_attached_object ((ACPI_HANDLE) method_node);
+	if (!obj_desc) {
+		return (AE_ERROR);
+	}
+
+
 	/*
-	 * Excecute the method via the interpreter
+	 * Execute the method via the interpreter
 	 */
 	status = acpi_aml_execute_method (method_node, params, return_obj_desc);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/namespace/nsinit.c linux/drivers/acpi/namespace/nsinit.c
--- v2.4.1/linux/drivers/acpi/namespace/nsinit.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/namespace/nsinit.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: nsinit - namespace initialization
- *              $Revision: 12 $
+ *              $Revision: 15 $
  *
  *****************************************************************************/
 
@@ -89,13 +89,12 @@
 
 ACPI_STATUS
 acpi_ns_initialize_devices (
-	u32                     flags)
+	void)
 {
 	ACPI_STATUS             status;
 	ACPI_DEVICE_WALK_INFO   info;
 
 
-	info.flags = flags;
 	info.device_count = 0;
 	info.num_STA = 0;
 	info.num_INI = 0;
@@ -168,6 +167,7 @@
 		info->op_region_init++;
 		status = acpi_ds_get_region_arguments (obj_desc);
 
+
 		break;
 
 
@@ -180,6 +180,8 @@
 
 		info->field_init++;
 		status = acpi_ds_get_field_unit_arguments (obj_desc);
+
+
 		break;
 
 	default:
@@ -198,7 +200,7 @@
  *
  * FUNCTION:    Acpi_ns_init_one_device
  *
- * PARAMETERS:  The usual "I'm a namespace callback" stuff
+ * PARAMETERS:  WALK_CALLBACK
  *
  * RETURN:      ACPI_STATUS
  *
@@ -221,6 +223,7 @@
 	ACPI_DEVICE_WALK_INFO  *info = (ACPI_DEVICE_WALK_INFO *) context;
 
 
+
 	info->device_count++;
 
 	acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
@@ -250,6 +253,7 @@
 		/* don't look at children of a not present device */
 		return(AE_CTRL_DEPTH);
 	}
+
 
 	/*
 	 * The device is present. Run _INI.
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/namespace/nsnames.c linux/drivers/acpi/namespace/nsnames.c
--- v2.4.1/linux/drivers/acpi/namespace/nsnames.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/namespace/nsnames.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: nsnames - Name manipulation and search
- *              $Revision: 53 $
+ *              $Revision: 54 $
  *
  ******************************************************************************/
 
@@ -115,6 +115,46 @@
 
 /*******************************************************************************
  *
+ * FUNCTION:    Acpi_ns_get_pathname_length
+ *
+ * PARAMETERS:  Node        - Namespace node
+ *
+ * RETURN:      Length of path, including prefix
+ *
+ * DESCRIPTION: Get the length of the pathname string for this node
+ *
+ ******************************************************************************/
+
+u32
+acpi_ns_get_pathname_length (
+	ACPI_NAMESPACE_NODE     *node)
+{
+	u32                     size;
+	ACPI_NAMESPACE_NODE     *next_node;
+
+	/*
+	 * Compute length of pathname as 5 * number of name segments.
+	 * Go back up the parent tree to the root
+	 */
+	for (size = 0, next_node = node;
+		  acpi_ns_get_parent_object (next_node);
+		  next_node = acpi_ns_get_parent_object (next_node))
+	{
+		size += PATH_SEGMENT_LENGTH;
+	}
+
+	/* Special case for size still 0 - no parent for "special" nodes */
+
+	if (!size) {
+		size = PATH_SEGMENT_LENGTH;
+	}
+
+	return (size + 1);
+}
+
+
+/*******************************************************************************
+ *
  * FUNCTION:    Acpi_ns_handle_to_pathname
  *
  * PARAMETERS:  Target_handle           - Handle of named object whose name is
@@ -138,11 +178,10 @@
 {
 	ACPI_STATUS             status = AE_OK;
 	ACPI_NAMESPACE_NODE     *node;
-	ACPI_NAMESPACE_NODE     *next_node;
 	u32                     path_length;
-	u32                     size;
 	u32                     user_buf_size;
 	ACPI_NAME               name;
+	u32                     size;
 
 
 	if (!acpi_gbl_root_node || !target_handle) {
@@ -159,26 +198,12 @@
 		return (AE_BAD_PARAMETER);
 	}
 
-	/*
-	 * Compute length of pathname as 5 * number of name segments.
-	 * Go back up the parent tree to the root
-	 */
-	for (size = 0, next_node = node;
-		  acpi_ns_get_parent_object (next_node);
-		  next_node = acpi_ns_get_parent_object (next_node))
-	{
-		size += PATH_SEGMENT_LENGTH;
-	}
-
-	/* Special case for size still 0 - no parent for "special" nodes */
-
-	if (!size) {
-		size = PATH_SEGMENT_LENGTH;
-	}
 
 	/* Set return length to the required path length */
 
-	path_length = size + 1;
+	path_length = acpi_ns_get_pathname_length (node);
+	size = path_length - 1;
+
 	user_buf_size = *buf_size;
 	*buf_size = path_length;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/namespace/nsxfobj.c linux/drivers/acpi/namespace/nsxfobj.c
--- v2.4.1/linux/drivers/acpi/namespace/nsxfobj.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/namespace/nsxfobj.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
  *
  * Module Name: nsxfobj - Public interfaces to the ACPI subsystem
  *                         ACPI Object oriented interfaces
- *              $Revision: 78 $
+ *              $Revision: 80 $
  *
  ******************************************************************************/
 
@@ -117,9 +117,8 @@
 		 * internal object
 		 */
 		for (i = 0; i < count; i++) {
-			status =
-				acpi_cm_build_internal_object (&param_objects->pointer[i],
-						  param_ptr[i]);
+			status = acpi_cm_copy_eobject_to_iobject (&param_objects->pointer[i],
+					 param_ptr[i]);
 
 			if (ACPI_FAILURE (status)) {
 				acpi_cm_delete_internal_object_list (param_ptr);
@@ -236,7 +235,7 @@
 						/*
 						 *  We have enough space for the object, build it
 						 */
-						status = acpi_cm_build_external_object (return_obj,
+						status = acpi_cm_copy_iobject_to_eobject (return_obj,
 								  return_buffer);
 						return_buffer->length = buffer_space_needed;
 					}
@@ -580,12 +579,12 @@
 	acpi_cm_acquire_mutex (ACPI_MTX_NAMESPACE);
 
 	node = acpi_ns_convert_handle_to_entry (obj_handle);
+
+	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
+
 	if (!node) {
-		acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
 		return (AE_BAD_PARAMETER);
 	}
-
-	acpi_cm_release_mutex (ACPI_MTX_NAMESPACE);
 
 	/*
 	 * Run _STA to determine if device is present
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/resources/rscalc.c linux/drivers/acpi/resources/rscalc.c
--- v2.4.1/linux/drivers/acpi/resources/rscalc.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/resources/rscalc.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
  *
  * Module Name: rscalc - Acpi_rs_calculate_byte_stream_length
  *                       Acpi_rs_calculate_list_length
- *              $Revision: 18 $
+ *              $Revision: 21 $
  *
  ******************************************************************************/
 
@@ -27,6 +27,8 @@
 
 #include "acpi.h"
 #include "acresrc.h"
+#include "amlcode.h"
+#include "acnamesp.h"
 
 #define _COMPONENT          RESOURCE_MANAGER
 	 MODULE_NAME         ("rscalc")
@@ -704,6 +706,7 @@
 				 */
 				bytes_consumed = 2;
 				structure_size = RESOURCE_LENGTH;
+				byte_stream_buffer_length = bytes_parsed;
 				break;
 
 
@@ -810,7 +813,10 @@
 		name_found = FALSE;
 
 		for (table_index = 0; table_index < 4 && !name_found; table_index++) {
-			if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) {
+			if ((ACPI_TYPE_STRING == (*sub_object_list)->common.type) ||
+				((INTERNAL_TYPE_REFERENCE == (*sub_object_list)->common.type) &&
+					((*sub_object_list)->reference.op_code == AML_NAMEPATH_OP)))
+			{
 				name_found = TRUE;
 			}
 
@@ -822,17 +828,22 @@
 			}
 		}
 
-		temp_size_needed += (sizeof (PCI_ROUTING_TABLE) - 1);
+		temp_size_needed += (sizeof (PCI_ROUTING_TABLE) - 4);
 
 		/*
 		 * Was a String type found?
 		 */
 		if (TRUE == name_found) {
-			/*
-			 * The length String.Length field includes the
-			 * terminating NULL
-			 */
-			temp_size_needed += (*sub_object_list)->string.length;
+			if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) {
+				/*
+				 * The length String.Length field includes the
+				 * terminating NULL
+				 */
+				temp_size_needed += (*sub_object_list)->string.length;
+			}
+			else {
+				temp_size_needed += acpi_ns_get_pathname_length ((*sub_object_list)->reference.node);
+			}
 		}
 
 		else {
@@ -855,7 +866,7 @@
 	}
 
 
-	*buffer_size_needed = temp_size_needed + sizeof (PCI_ROUTING_TABLE);
+	*buffer_size_needed = temp_size_needed;
 
 	return (AE_OK);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/resources/rscreate.c linux/drivers/acpi/resources/rscreate.c
--- v2.4.1/linux/drivers/acpi/resources/rscreate.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/resources/rscreate.c	Fri Feb  9 11:45:58 2001
@@ -3,7 +3,7 @@
  * Module Name: rscreate - Acpi_rs_create_resource_list
  *                         Acpi_rs_create_pci_routing_table
  *                         Acpi_rs_create_byte_stream
- *              $Revision: 24 $
+ *              $Revision: 25 $
  *
  ******************************************************************************/
 
@@ -28,6 +28,8 @@
 
 #include "acpi.h"
 #include "acresrc.h"
+#include "amlcode.h"
+#include "acnamesp.h"
 
 #define _COMPONENT          RESOURCE_MANAGER
 	 MODULE_NAME         ("rscreate")
@@ -157,6 +159,7 @@
 	u32                     number_of_elements = 0;
 	u32                     index = 0;
 	PCI_ROUTING_TABLE       *user_prt = NULL;
+	ACPI_NAMESPACE_NODE     *node;
 	ACPI_STATUS             status;
 
 
@@ -203,10 +206,10 @@
 			/*
 			 * Fill in the Length field with the information we
 			 * have at this point.
-			 * The minus one is to subtract the size of the
-			 * u8 Source[1] member because it is added below.
+			 * The minus four is to subtract the size of the
+			 * u8 Source[4] member because it is added below.
 			 */
-			user_prt->length = (sizeof (PCI_ROUTING_TABLE) - 1);
+			user_prt->length = (sizeof (PCI_ROUTING_TABLE) -4);
 
 			/*
 			 * Dereference the sub-package
@@ -221,11 +224,10 @@
 			sub_object_list = package_element->package.elements;
 
 			/*
-			 * Dereference the Address
+			 * 1) First subobject:  Dereference the Address
 			 */
 			if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
-				user_prt->data.address =
-						(*sub_object_list)->integer.value;
+				user_prt->address = (*sub_object_list)->integer.value;
 			}
 
 			else {
@@ -233,12 +235,12 @@
 			}
 
 			/*
-			 * Dereference the Pin
+			 * 2) Second subobject: Dereference the Pin
 			 */
 			sub_object_list++;
 
 			if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
-				user_prt->data.pin =
+				user_prt->pin =
 						(u32) (*sub_object_list)->integer.value;
 			}
 
@@ -247,37 +249,57 @@
 			}
 
 			/*
-			 * Dereference the Source Name
+			 * 3) Third subobject: Dereference the Source Name
 			 */
 			sub_object_list++;
 
-			if (ACPI_TYPE_STRING == (*sub_object_list)->common.type) {
-				STRCPY (user_prt->data.source,
+			switch ((*sub_object_list)->common.type)
+			{
+			case INTERNAL_TYPE_REFERENCE:
+				if ((*sub_object_list)->reference.op_code != AML_NAMEPATH_OP) {
+					return (AE_BAD_DATA);
+				}
+
+				node = (*sub_object_list)->reference.node;
+
+				/* TBD: use *remaining* length of the buffer! */
+
+				status = acpi_ns_handle_to_pathname ((ACPI_HANDLE *) node,
+						 output_buffer_length, user_prt->source);
+
+				user_prt->length += STRLEN (user_prt->source) + 1; /* include null terminator */
+				break;
+
+
+			case ACPI_TYPE_STRING:
+
+				STRCPY (user_prt->source,
 					  (*sub_object_list)->string.pointer);
 
 				/*
 				 * Add to the Length field the length of the string
 				 */
 				user_prt->length += (*sub_object_list)->string.length;
-			}
+				break;
 
-			else {
+
+			case ACPI_TYPE_INTEGER:
 				/*
 				 * If this is a number, then the Source Name
 				 * is NULL, since the entire buffer was zeroed
 				 * out, we can leave this alone.
 				 */
-				if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
-					/*
-					 * Add to the Length field the length of
-					 * the u32 NULL
-					 */
-					user_prt->length += sizeof (u32);
-				}
+				/*
+				 * Add to the Length field the length of
+				 * the u32 NULL
+				 */
+				user_prt->length += sizeof (u32);
+				break;
 
-				else {
-					return (AE_BAD_DATA);
-				}
+
+			default:
+			   return (AE_BAD_DATA);
+			   break;
 			}
 
 			/* Now align the current length */
@@ -285,12 +307,12 @@
 			user_prt->length = ROUND_UP_TO_64_bITS (user_prt->length);
 
 			/*
-			 * Dereference the Source Index
+			 * 4) Fourth subobject: Dereference the Source Index
 			 */
 			sub_object_list++;
 
 			if (ACPI_TYPE_INTEGER == (*sub_object_list)->common.type) {
-				user_prt->data.source_index =
+				user_prt->source_index =
 						(u32) (*sub_object_list)->integer.value;
 			}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/resources/rsdump.c linux/drivers/acpi/resources/rsdump.c
--- v2.4.1/linux/drivers/acpi/resources/rsdump.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/resources/rsdump.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /*******************************************************************************
  *
  * Module Name: rsdump - Functions do dump out the resource structures.
- *              $Revision: 15 $
+ *              $Revision: 16 $
  *
  ******************************************************************************/
 
@@ -910,24 +910,24 @@
 
 
 	if (acpi_dbg_level & TRACE_RESOURCES && _COMPONENT & acpi_dbg_layer) {
-		prt_element = (PCI_ROUTING_TABLE *)buffer;
+		prt_element = (PCI_ROUTING_TABLE *) buffer;
 
 		while (!done) {
 			acpi_os_printf ("\t_pCI IRQ Routing Table structure %X.\n", count++);
 
 			acpi_os_printf ("\t\t_address: %X\n",
-					 prt_element->data.address);
+					 prt_element->address);
 
-			acpi_os_printf ("\t\t_pin: %X\n", prt_element->data.pin);
+			acpi_os_printf ("\t\t_pin: %X\n", prt_element->pin);
 
-			acpi_os_printf ("\t\t_source: %s\n", prt_element->data.source);
+			acpi_os_printf ("\t\t_source: %s\n", prt_element->source);
 
 			acpi_os_printf ("\t\t_source_index: %X\n",
-					 prt_element->data.source_index);
+					 prt_element->source_index);
 
 			buffer += prt_element->length;
 
-			prt_element = (PCI_ROUTING_TABLE *)buffer;
+			prt_element = (PCI_ROUTING_TABLE *) buffer;
 
 			if(0 == prt_element->length) {
 				done = TRUE;
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/resources/rslist.c linux/drivers/acpi/resources/rslist.c
--- v2.4.1/linux/drivers/acpi/resources/rslist.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/resources/rslist.c	Fri Feb  9 11:45:58 2001
@@ -2,7 +2,7 @@
  *
  * Module Name: rslist - Acpi_rs_byte_stream_to_list
  *                       Acpi_list_to_byte_stream
- *              $Revision: 10 $
+ *              $Revision: 11 $
  *
  ******************************************************************************/
 
@@ -302,9 +302,7 @@
 	/*
 	 * Check the reason for exiting the while loop
 	 */
-	if (!(byte_stream_buffer_length == bytes_parsed) ||
-		 (TRUE != end_tag_processed))
-	{
+	if (TRUE != end_tag_processed) {
 		return (AE_AML_ERROR);
 	}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/acpi/tables/tbconvrt.c linux/drivers/acpi/tables/tbconvrt.c
--- v2.4.1/linux/drivers/acpi/tables/tbconvrt.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/acpi/tables/tbconvrt.c	Fri Feb  9 11:45:58 2001
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: tbconvrt - ACPI Table conversion utilities
- *              $Revision: 18 $
+ *              $Revision: 19 $
  *
  *****************************************************************************/
 
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/Config.in linux/drivers/atm/Config.in
--- v2.4.1/linux/drivers/atm/Config.in	Fri Dec 29 14:35:47 2000
+++ linux/drivers/atm/Config.in	Fri Feb 16 16:02:35 2001
@@ -56,7 +56,7 @@
   tristate 'FORE Systems 200E-series' CONFIG_ATM_FORE200E_MAYBE
   if [ "$CONFIG_ATM_FORE200E_MAYBE" != "n" ]; then
     if [ "$CONFIG_PCI" = "y" ]; then
-      bool '  PCA-200E support' CONFIG_ATM_FORE200E_PCA y
+      bool '  PCA-200E support' CONFIG_ATM_FORE200E_PCA
       if [ "$CONFIG_ATM_FORE200E_PCA" = "y" ]; then
 	bool '   Use default PCA-200E firmware (normally enabled)' CONFIG_ATM_FORE200E_PCA_DEFAULT_FW
         if [ "$CONFIG_ATM_FORE200E_PCA_DEFAULT_FW" = "n" ]; then
@@ -65,7 +65,7 @@
       fi
     fi
     if [ "$CONFIG_SBUS" = "y" ]; then
-      bool '  SBA-200E support' CONFIG_ATM_FORE200E_SBA y
+      bool '  SBA-200E support' CONFIG_ATM_FORE200E_SBA
       if [ "$CONFIG_ATM_FORE200E_SBA" = "y" ]; then
         bool '   Use default SBA-200E firmware (normally enabled)' CONFIG_ATM_FORE200E_SBA_DEFAULT_FW
         if [ "$CONFIG_ATM_FORE200E_SBA_DEFAULT_FW" = "n" ]; then
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/firestream.c linux/drivers/atm/firestream.c
--- v2.4.1/linux/drivers/atm/firestream.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/atm/firestream.c	Fri Feb 16 16:02:35 2001
@@ -1441,7 +1441,7 @@
 
 
 /* Check if this gets going again if a pool ever runs out.  -- Yes, it
-   does. I've seen "recieve abort: no buffers" and things started
+   does. I've seen "receive abort: no buffers" and things started
    working again after that...  -- REW */
 
 static void top_off_fp (struct fs_dev *dev, struct freepool *fp, int gfp_flags)
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/fore200e.c linux/drivers/atm/fore200e.c
--- v2.4.1/linux/drivers/atm/fore200e.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/atm/fore200e.c	Fri Feb  9 11:30:22 2001
@@ -28,7 +28,7 @@
 #include <linux/version.h>
 #include <linux/config.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/capability.h>
 #include <linux/sched.h>
@@ -2020,6 +2020,8 @@
     struct prom_data* prom = fore200e_kmalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
     int ok, i;
 
+    if (!prom)
+	return -ENOMEM;
     ok = fore200e->bus->prom_read(fore200e, prom);
     if (ok < 0)
 	return -EBUSY;
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/iphase.c linux/drivers/atm/iphase.c
--- v2.4.1/linux/drivers/atm/iphase.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/atm/iphase.c	Sun Feb  4 10:05:29 2001
@@ -6,7 +6,7 @@
 *******************************************************************************
       
       This software may be used and distributed according to the terms
-      of the GNU Public License (GPL), incorporated herein by reference.
+      of the GNU General Public License (GPL), incorporated herein by reference.
       Drivers based on this skeleton fall under the GPL and must retain
       the authorship (implicit copyright) notice.
 
@@ -78,8 +78,8 @@
 
 static unsigned char ia_phy_get(struct atm_dev *dev, unsigned long addr);
 
-static IADEV *ia_dev[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
-static struct atm_dev *_ia_dev[8] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+static IADEV *ia_dev[8];
+static struct atm_dev *_ia_dev[8];
 static int iadev_count = 0;
 static void ia_led_timer(unsigned long arg);
 static struct timer_list ia_timer = { function: ia_led_timer };
@@ -951,7 +951,7 @@
                                   SUNI_PM7345_PLB);
 #ifdef __SNMP__
    suni_pm7345->suni_rxcp_intr_en_sts |= SUNI_OOCDE;
-#endif __SNMP__
+#endif /* __SNMP__ */
    return;
 }
 
@@ -2130,6 +2130,8 @@
 		memset((caddr_t)evc, 0, sizeof(struct ext_vc));  
                 iadev->testTable[i] = (struct testTable_t *)
                             kmalloc(sizeof(struct testTable_t), GFP_KERNEL);
+		if (!iadev->testTable[i])
+			return -ENOMEM;
               	iadev->testTable[i]->lastTime = 0;
  		iadev->testTable[i]->fract = 0;
                 iadev->testTable[i]->vc_status = VC_UBR;
@@ -2376,7 +2378,10 @@
 	  
 	/* lets try reading the MAC address */  
 	error = get_esi(dev);  
-	if (error) return error;  
+	if (error) {
+	  iounmap((void *) iadev->base);
+	  return error;  
+	}
         printk("IA: ");
 	for (i=0; i < ESI_LEN; i++)  
                 printk("%s%02X",i ? "-" : "",dev->esi[i]);  
@@ -2384,6 +2389,7 @@
   
         /* reset SAR */  
         if (reset_sar(dev)) {
+	   iounmap((void *) iadev->base);
            printk("IA: reset SAR fail, please try again\n");
            return 1;
         }
@@ -2869,8 +2875,11 @@
         iavcc = INPH_IA_VCC(vcc);
         if (!iavcc->txing) {
            printk("discard packet on closed VC\n");
-           if (vcc->pop) vcc->pop(vcc, skb);
-           else dev_kfree_skb_any(skb);
+           if (vcc->pop)
+		vcc->pop(vcc, skb);
+           else
+		dev_kfree_skb_any(skb);
+	   return 0;
         }
 
         if (skb->len > iadev->tx_buf_sz - 8) {
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/iphase.h linux/drivers/atm/iphase.h
--- v2.4.1/linux/drivers/atm/iphase.h	Mon Dec 11 13:22:09 2000
+++ linux/drivers/atm/iphase.h	Sun Feb  4 10:05:29 2001
@@ -7,7 +7,7 @@
 *******************************************************************************
       
       This software may be used and distributed according to the terms
-      of the GNU Public License (GPL), incorporated herein by reference.
+      of the GNU General Public License (GPL), incorporated herein by reference.
       Drivers based on this skeleton fall under the GPL and must retain
       the authorship (implicit copyright) notice.
 
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/nicstar.c linux/drivers/atm/nicstar.c
--- v2.4.1/linux/drivers/atm/nicstar.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/atm/nicstar.c	Fri Feb 16 16:02:35 2001
@@ -121,7 +121,7 @@
 #define ALIGN_ADDRESS(addr, alignment) \
         bus_to_virt(ALIGN_BUS_ADDR(virt_to_bus(addr), alignment))
 
-#undef CEIL(d)
+#undef CEIL
 
 #ifndef ATM_SKB
 #define ATM_SKB(s) (&(s)->atm)
@@ -1360,7 +1360,7 @@
       printk("nicstar%d: Raw cell received and no support yet...\n",
              card->index);
 #endif /* RCQ_SUPPORT */
-      /* NOTE: the following procedure may keep a raw cell pending untill the
+      /* NOTE: the following procedure may keep a raw cell pending until the
                next interrupt. As this preliminary support is only meant to
                avoid buffer leakage, this is not an issue. */
       while (readl(card->membase + RAWCT) != card->rawch)
diff -u --recursive --new-file v2.4.1/linux/drivers/atm/nicstar.h linux/drivers/atm/nicstar.h
--- v2.4.1/linux/drivers/atm/nicstar.h	Mon Dec 11 13:22:02 2000
+++ linux/drivers/atm/nicstar.h	Fri Feb 16 16:02:35 2001
@@ -613,7 +613,7 @@
 #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_48
 #elif (NS_SMBUFSIZE == 96)
 #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_96
-#eliif (NS_SMBUFSIZE == 240)
+#elif (NS_SMBUFSIZE == 240)
 #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_240
 #elif (NS_SMBUFSIZE == 2048)
 #define NS_CFG_SMBUFSIZE NS_CFG_SMBUFSIZE_2048
diff -u --recursive --new-file v2.4.1/linux/drivers/block/Config.in linux/drivers/block/Config.in
--- v2.4.1/linux/drivers/block/Config.in	Fri Sep 22 17:11:37 2000
+++ linux/drivers/block/Config.in	Sat Feb  3 12:13:19 2001
@@ -34,7 +34,7 @@
    source drivers/block/paride/Config.in
 fi
 dep_tristate 'Compaq SMART2 support' CONFIG_BLK_CPQ_DA $CONFIG_PCI
-dep_tristate 'Compaq CISS Array support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
+dep_tristate 'Compaq Smart Array 5xxx support' CONFIG_BLK_CPQ_CISS_DA $CONFIG_PCI 
 dep_tristate 'Mylex DAC960/DAC1100 PCI RAID Controller support' CONFIG_BLK_DEV_DAC960 $CONFIG_PCI
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
diff -u --recursive --new-file v2.4.1/linux/drivers/block/DAC960.c linux/drivers/block/DAC960.c
--- v2.4.1/linux/drivers/block/DAC960.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/DAC960.c	Tue Feb 20 21:26:22 2001
@@ -2,7 +2,7 @@
 
   Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
 
-  Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com>
+  Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
 
   This program is free software; you may redistribute and/or modify it under
   the terms of the GNU General Public License Version 2 as published by the
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.4.9"
-#define DAC960_DriverDate			"7 September 2000"
+#define DAC960_DriverVersion			"2.4.10"
+#define DAC960_DriverDate			"1 February 2001"
 
 
 #include <linux/version.h>
@@ -34,7 +34,7 @@
 #include <linux/ioport.h>
 #include <linux/locks.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
@@ -51,7 +51,7 @@
 */
 
 static int
-  DAC960_ControllerCount;
+  DAC960_ControllerCount =			0;
 
 
 /*
@@ -60,7 +60,7 @@
 */
 
 static int
-  DAC960_ActiveControllerCount;
+  DAC960_ActiveControllerCount =		0;
 
 
 /*
@@ -69,7 +69,7 @@
 */
 
 static DAC960_Controller_T
-  *DAC960_Controllers[DAC960_MaxControllers];
+  *DAC960_Controllers[DAC960_MaxControllers] =	{ NULL };
 
 
 /*
@@ -110,7 +110,7 @@
   DAC960_Announce("***** DAC960 RAID Driver Version "
 		  DAC960_DriverVersion " of "
 		  DAC960_DriverDate " *****\n", Controller);
-  DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff "
+  DAC960_Announce("Copyright 1998-2001 by Leonard N. Zubkoff "
 		  "<lnz@dandelion.com>\n", Controller);
 }
 
@@ -511,7 +511,7 @@
   DAC960_V1_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->Type3.CommandOpcode = CommandOpcode;
-  CommandMailbox->Type3.BusAddress = Virtual_to_Bus(DataPointer);
+  CommandMailbox->Type3.BusAddress = Virtual_to_Bus32(DataPointer);
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -539,7 +539,7 @@
   CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
   CommandMailbox->Type3D.Channel = Channel;
   CommandMailbox->Type3D.TargetID = TargetID;
-  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus(DataPointer);
+  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus32(DataPointer);
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -573,7 +573,7 @@
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentDataPointer =
-    Virtual_to_Bus(DataPointer);
+    Virtual_to_Bus64(DataPointer);
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentByteCount =
@@ -612,7 +612,7 @@
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentDataPointer =
-    Virtual_to_Bus(DataPointer);
+    Virtual_to_Bus64(DataPointer);
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentByteCount =
@@ -655,7 +655,7 @@
   CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 				   .ScatterGatherSegments[0]
 				   .SegmentDataPointer =
-    Virtual_to_Bus(DataPointer);
+    Virtual_to_Bus64(DataPointer);
   CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 				   .ScatterGatherSegments[0]
 				   .SegmentByteCount =
@@ -700,7 +700,7 @@
   CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 				    .ScatterGatherSegments[0]
 				    .SegmentDataPointer =
-    Virtual_to_Bus(DataPointer);
+    Virtual_to_Bus64(DataPointer);
   CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 				    .ScatterGatherSegments[0]
 				    .SegmentByteCount =
@@ -816,9 +816,9 @@
   CommandMailbox.TypeX.CommandIdentifier = 0;
   CommandMailbox.TypeX.CommandOpcode2 = 0x14;
   CommandMailbox.TypeX.CommandMailboxesBusAddress =
-    Virtual_to_Bus(Controller->V1.FirstCommandMailbox);
+    Virtual_to_Bus32(Controller->V1.FirstCommandMailbox);
   CommandMailbox.TypeX.StatusMailboxesBusAddress =
-    Virtual_to_Bus(Controller->V1.FirstStatusMailbox);
+    Virtual_to_Bus32(Controller->V1.FirstStatusMailbox);
   for (i = 0; i < 2; i++)
     switch (Controller->HardwareType)
       {
@@ -940,11 +940,11 @@
   CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox;
   CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1;
   CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress =
-    Virtual_to_Bus(Controller->V2.HealthStatusBuffer);
+    Virtual_to_Bus64(Controller->V2.HealthStatusBuffer);
   CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress =
-    Virtual_to_Bus(Controller->V2.FirstCommandMailbox);
+    Virtual_to_Bus64(Controller->V2.FirstCommandMailbox);
   CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress =
-    Virtual_to_Bus(Controller->V2.FirstStatusMailbox);
+    Virtual_to_Bus64(Controller->V2.FirstStatusMailbox);
   switch (Controller->HardwareType)
     {
     case DAC960_BA_Controller:
@@ -1334,7 +1334,7 @@
 	  Command->CommandType = DAC960_ImmediateCommand;
 	  Command->Semaphore = Semaphore;
 	  Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
-	  Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus(DCDB);
+	  Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus32(DCDB);
 	  DCDB->Channel = Channel;
 	  DCDB->TargetID = TargetID;
 	  DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -1343,7 +1343,7 @@
 	  DCDB->NoAutomaticRequestSense = false;
 	  DCDB->DisconnectPermitted = true;
 	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
-	  DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData);
+	  DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData);
 	  DCDB->CDBLength = 6;
 	  DCDB->TransferLengthHigh4 = 0;
 	  DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -1370,7 +1370,7 @@
 	  Command->Semaphore = Semaphore;
 	  DCDB = &DCDBs[Channel];
 	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	  DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber);
+	  DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber);
 	  DCDB->SenseLength = sizeof(DCDB->SenseData);
 	  DCDB->CDB[0] = 0x12; /* INQUIRY */
 	  DCDB->CDB[1] = 1; /* EVPD = 1 */
@@ -1461,7 +1461,7 @@
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentDataPointer =
-	Virtual_to_Bus(InquiryUnitSerialNumber);
+	Virtual_to_Bus64(InquiryUnitSerialNumber);
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentByteCount =
@@ -1864,7 +1864,7 @@
   int TotalSegments = Request->nr_segments + NextRequest->nr_segments;
   if (Request->bhtail->b_data + Request->bhtail->b_size
       == NextRequest->bh->b_data)
-      TotalSegments--;
+    TotalSegments--;
   if (TotalSegments > MaxSegments ||
       TotalSegments > Controller->DriverScatterGatherLimit)
     return false;
@@ -2602,7 +2602,8 @@
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(Command->RequestBuffer);
+      CommandMailbox->Type5.BusAddress =
+	Virtual_to_Bus32(Command->RequestBuffer);
     }
   else
     {
@@ -2620,7 +2621,7 @@
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-      CommandMailbox->Type5.BusAddress = Virtual_to_Bus(ScatterGatherList);
+      CommandMailbox->Type5.BusAddress = Virtual_to_Bus32(ScatterGatherList);
       CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
       while (BufferHeader != NULL)
 	{
@@ -2633,7 +2634,7 @@
 	  else
 	    {
 	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus(BufferHeader->b_data);
+		Virtual_to_Bus32(BufferHeader->b_data);
 	      ScatterGatherList[SegmentNumber].SegmentByteCount =
 		BufferHeader->b_size;
 	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
@@ -2665,7 +2666,7 @@
   CommandMailbox->SCSI_10.DataTransferSize =
     Command->BlockCount << DAC960_BlockSizeBits;
   CommandMailbox->SCSI_10.RequestSenseBusAddress =
-    Virtual_to_Bus(&Command->V2.RequestSense);
+    Virtual_to_Bus64(&Command->V2.RequestSense);
   CommandMailbox->SCSI_10.PhysicalDevice =
     Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber];
   CommandMailbox->SCSI_10.RequestSenseSize =
@@ -2684,7 +2685,7 @@
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentDataPointer =
-	Virtual_to_Bus(Command->RequestBuffer);
+	Virtual_to_Bus64(Command->RequestBuffer);
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentByteCount =
@@ -2706,7 +2707,7 @@
 	    Command->SegmentCount;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			 .ExtendedScatterGather.ScatterGatherList0Address =
-	    Virtual_to_Bus(ScatterGatherList);
+	    Virtual_to_Bus64(ScatterGatherList);
 	}
       else
 	ScatterGatherList =
@@ -2723,7 +2724,7 @@
 	  else
 	    {
 	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus(BufferHeader->b_data);
+		Virtual_to_Bus64(BufferHeader->b_data);
 	      ScatterGatherList[SegmentNumber].SegmentByteCount =
 		BufferHeader->b_size;
 	      LastDataEndPointer = BufferHeader->b_data + BufferHeader->b_size;
@@ -2950,7 +2951,7 @@
 	  Command->BlockCount = BufferHeader->b_size >> DAC960_BlockSizeBits;
 	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
 	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus(BufferHeader->b_data);
+	    Virtual_to_Bus32(BufferHeader->b_data);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3006,7 +3007,7 @@
 	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
 	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
 	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus(NextBufferHeader->b_data);
+	    Virtual_to_Bus32(NextBufferHeader->b_data);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3019,11 +3020,13 @@
 	{
 	  if (CommandOpcode == DAC960_V1_Enquiry)
 	    memcpy(&Controller->V1.NewEnquiry,
-		   Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress),
+		   Bus32_to_Virtual(Command->V1.CommandMailbox
+					       .Type3.BusAddress),
 		   sizeof(DAC960_V1_Enquiry_T));
 	  else if (CommandOpcode == DAC960_V1_GetRebuildProgress)
 	    memcpy(&Controller->V1.RebuildProgress,
-		   Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress),
+		   Bus32_to_Virtual(Command->V1.CommandMailbox
+					       .Type3.BusAddress),
 		   sizeof(DAC960_V1_RebuildProgress_T));
 	}
       if (CommandOpcode == DAC960_V1_Enquiry &&
@@ -3037,18 +3040,25 @@
 	    NewEnquiry->CriticalLogicalDriveCount;
 	  if (NewEnquiry->NumberOfLogicalDrives > Controller->LogicalDriveCount)
 	    {
-	      int LogicalDriveNumber = Controller->LogicalDriveCount;
-	      while (LogicalDriveNumber < NewEnquiry->NumberOfLogicalDrives)
-		{
-		  DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
-				  "Now Exists\n", Controller,
-				  LogicalDriveNumber,
-				  Controller->ControllerNumber,
-				  LogicalDriveNumber);
-		  LogicalDriveNumber++;
-		}
-	      Controller->LogicalDriveCount = LogicalDriveNumber;
+	      int LogicalDriveNumber = Controller->LogicalDriveCount - 1;
+	      while (++LogicalDriveNumber < NewEnquiry->NumberOfLogicalDrives)
+		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+				"Now Exists\n", Controller,
+				LogicalDriveNumber,
+				Controller->ControllerNumber,
+				LogicalDriveNumber);
+	    }
+	  if (NewEnquiry->NumberOfLogicalDrives < Controller->LogicalDriveCount)
+	    {
+	      int LogicalDriveNumber = NewEnquiry->NumberOfLogicalDrives - 1;
+	      while (++LogicalDriveNumber < Controller->LogicalDriveCount)
+		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+				"No Longer Exists\n", Controller,
+				LogicalDriveNumber,
+				Controller->ControllerNumber,
+				LogicalDriveNumber);
 	    }
+	  Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
 	  if (NewEnquiry->StatusFlags.DeferredWriteError !=
 	      OldEnquiry->StatusFlags.DeferredWriteError)
 	    DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
@@ -3073,8 +3083,7 @@
 		NewEnquiry->EventLogSequenceNumber;
 	      Controller->V1.NeedErrorTableInformation = true;
 	      Controller->V1.NeedDeviceStateInformation = true;
-	      Controller->V1.DeviceStateChannel = 0;
-	      Controller->V1.DeviceStateTargetID = -1;
+	      Controller->V1.StartDeviceStateScan = true;
 	      Controller->SecondaryMonitoringTime = jiffies;
 	    }
 	  if (NewEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress ||
@@ -3133,7 +3142,7 @@
 	      Controller->V1.RebuildFlagPending)
 	    {
 	      DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *)
-		Bus_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress);
+		Bus32_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress);
 	      Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag;
 	      Controller->V1.RebuildFlagPending = false;
 	    }
@@ -3279,6 +3288,9 @@
 	    {
 	      Controller->V1.NeedDeviceInquiryInformation = true;
 	      Controller->V1.NeedDeviceSerialNumberInformation = true;
+	      Controller->V1.DeviceResetCount
+			     [Controller->V1.DeviceStateChannel]
+			     [Controller->V1.DeviceStateTargetID] = 0;
 	    }
 	  memcpy(OldDeviceState, NewDeviceState,
 		 sizeof(DAC960_V1_DeviceState_T));
@@ -3418,7 +3430,7 @@
 	  Command->V1.CommandMailbox.Type3E.SequenceNumber =
 	    Controller->V1.OldEventLogSequenceNumber;
 	  Command->V1.CommandMailbox.Type3E.BusAddress =
-	    Virtual_to_Bus(&Controller->V1.EventLogEntry);
+	    Virtual_to_Bus32(&Controller->V1.EventLogEntry);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3428,7 +3440,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetErrorTable;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->V1.NewErrorTable);
+	    Virtual_to_Bus32(&Controller->V1.NewErrorTable);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3439,7 +3451,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetRebuildProgress;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->V1.RebuildProgress);
+	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3455,7 +3467,7 @@
 	      InquiryStandardData->PeripheralDeviceType = 0x1F;
 	      Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
 	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus(DCDB);
+		Virtual_to_Bus32(DCDB);
 	      DCDB->Channel = Controller->V1.DeviceStateChannel;
 	      DCDB->TargetID = Controller->V1.DeviceStateTargetID;
 	      DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -3464,7 +3476,7 @@
 	      DCDB->NoAutomaticRequestSense = false;
 	      DCDB->DisconnectPermitted = true;
 	      DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
-	      DCDB->BusAddress = Virtual_to_Bus(InquiryStandardData);
+	      DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData);
 	      DCDB->CDBLength = 6;
 	      DCDB->TransferLengthHigh4 = 0;
 	      DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -3488,7 +3500,7 @@
 	      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
 	      Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
 	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus(DCDB);
+		Virtual_to_Bus32(DCDB);
 	      DCDB->Channel = Controller->V1.DeviceStateChannel;
 	      DCDB->TargetID = Controller->V1.DeviceStateTargetID;
 	      DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -3498,7 +3510,7 @@
 	      DCDB->DisconnectPermitted = true;
 	      DCDB->TransferLength =
 		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      DCDB->BusAddress = Virtual_to_Bus(InquiryUnitSerialNumber);
+	      DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber);
 	      DCDB->CDBLength = 6;
 	      DCDB->TransferLengthHigh4 = 0;
 	      DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -3512,35 +3524,31 @@
 	      Controller->V1.NeedDeviceSerialNumberInformation = false;
 	      return;
 	    }
-	  if (++Controller->V1.DeviceStateTargetID == Controller->Targets)
+	  if (Controller->V1.StartDeviceStateScan)
+	    {
+	      Controller->V1.DeviceStateChannel = 0;
+	      Controller->V1.DeviceStateTargetID = 0;
+	      Controller->V1.StartDeviceStateScan = false;
+	    }
+	  else if (++Controller->V1.DeviceStateTargetID == Controller->Targets)
 	    {
 	      Controller->V1.DeviceStateChannel++;
 	      Controller->V1.DeviceStateTargetID = 0;
 	    }
-	  while (Controller->V1.DeviceStateChannel < Controller->Channels)
+	  if (Controller->V1.DeviceStateChannel < Controller->Channels)
 	    {
-	      DAC960_V1_DeviceState_T *OldDeviceState =
-		&Controller->V1.DeviceState[Controller->V1.DeviceStateChannel]
-					   [Controller->V1.DeviceStateTargetID];
-	      if (OldDeviceState->Present &&
-		  OldDeviceState->DeviceType == DAC960_V1_DiskType)
-		{
-		  Command->V1.CommandMailbox.Type3D.CommandOpcode =
-		    DAC960_V1_GetDeviceState;
-		  Command->V1.CommandMailbox.Type3D.Channel =
-		    Controller->V1.DeviceStateChannel;
-		  Command->V1.CommandMailbox.Type3D.TargetID =
-		    Controller->V1.DeviceStateTargetID;
-		  Command->V1.CommandMailbox.Type3D.BusAddress =
-		    Virtual_to_Bus(&Controller->V1.NewDeviceState);
-		  DAC960_QueueCommand(Command);
-		  return;
-		}
-	      if (++Controller->V1.DeviceStateTargetID == Controller->Targets)
-		{
-		  Controller->V1.DeviceStateChannel++;
-		  Controller->V1.DeviceStateTargetID = 0;
-		}
+	      Controller->V1.NewDeviceState.DeviceState =
+		DAC960_V1_Device_Dead;
+	      Command->V1.CommandMailbox.Type3D.CommandOpcode =
+		DAC960_V1_GetDeviceState;
+	      Command->V1.CommandMailbox.Type3D.Channel =
+		Controller->V1.DeviceStateChannel;
+	      Command->V1.CommandMailbox.Type3D.TargetID =
+		Controller->V1.DeviceStateTargetID;
+	      Command->V1.CommandMailbox.Type3D.BusAddress =
+		Virtual_to_Bus32(&Controller->V1.NewDeviceState);
+	      DAC960_QueueCommand(Command);
+	      return;
 	    }
 	  Controller->V1.NeedDeviceStateInformation = false;
 	}
@@ -3550,7 +3558,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetLogicalDriveInformation;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->V1.NewLogicalDriveInformation);
+	    Virtual_to_Bus32(&Controller->V1.NewLogicalDriveInformation);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3560,7 +3568,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetRebuildProgress;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->V1.RebuildProgress);
+	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3570,7 +3578,7 @@
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_RebuildStat;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus(&Controller->V1.RebuildProgress);
+	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3948,7 +3956,7 @@
 	    Command->BlockCount << DAC960_BlockSizeBits;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0].SegmentDataPointer =
-	    Virtual_to_Bus(BufferHeader->b_data);
+	    Virtual_to_Bus64(BufferHeader->b_data);
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0].SegmentByteCount =
 	    CommandMailbox->SCSI_10.DataTransferSize;
@@ -4009,7 +4017,7 @@
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0]
 				 .SegmentDataPointer =
-	    Virtual_to_Bus(NextBufferHeader->b_data);
+	    Virtual_to_Bus64(NextBufferHeader->b_data);
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments[0]
 				 .SegmentByteCount =
@@ -4035,12 +4043,9 @@
 	  Controller->LogicalDriveCount =
 	    NewControllerInfo->LogicalDevicesPresent;
 	  Controller->V2.NeedLogicalDeviceInformation = true;
-	  Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber = 0;
 	  Controller->V2.NeedPhysicalDeviceInformation = true;
-	  Controller->V2.PhysicalDeviceIndex = 0;
-	  Controller->V2.NewPhysicalDeviceInformation.Channel = 0;
-	  Controller->V2.NewPhysicalDeviceInformation.TargetID = 0;
-	  Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0;
+	  Controller->V2.StartLogicalDeviceInformationScan = true;
+	  Controller->V2.StartPhysicalDeviceInformationScan = true;
 	  Controller->MonitoringAlertMode =
 	    (NewControllerInfo->LogicalDevicesCritical > 0 ||
 	     NewControllerInfo->LogicalDevicesOffline > 0 ||
@@ -4063,7 +4068,49 @@
 	  unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex;
 	  DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo =
 	    Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex];
-	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber;
+	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+	    Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex];
+	  unsigned int DeviceIndex;
+	  while (PhysicalDeviceInfo != NULL &&
+		 (NewPhysicalDeviceInfo->Channel >
+		  PhysicalDeviceInfo->Channel ||
+		  (NewPhysicalDeviceInfo->Channel ==
+		   PhysicalDeviceInfo->Channel &&
+		   (NewPhysicalDeviceInfo->TargetID >
+		    PhysicalDeviceInfo->TargetID ||
+		   (NewPhysicalDeviceInfo->TargetID ==
+		    PhysicalDeviceInfo->TargetID &&
+		    NewPhysicalDeviceInfo->LogicalUnit >
+		    PhysicalDeviceInfo->LogicalUnit)))))
+	    {
+	      DAC960_Critical("Physical Device %d:%d No Longer Exists\n",
+			      Controller,
+			      PhysicalDeviceInfo->Channel,
+			      PhysicalDeviceInfo->TargetID);
+	      Controller->V2.PhysicalDeviceInformation
+			     [PhysicalDeviceIndex] = NULL;
+	      Controller->V2.InquiryUnitSerialNumber
+			     [PhysicalDeviceIndex] = NULL;
+	      kfree(PhysicalDeviceInfo);
+	      kfree(InquiryUnitSerialNumber);
+	      for (DeviceIndex = PhysicalDeviceIndex;
+		   DeviceIndex < DAC960_V2_MaxPhysicalDevices - 1;
+		   DeviceIndex++)
+		{
+		  Controller->V2.PhysicalDeviceInformation[DeviceIndex] =
+		    Controller->V2.PhysicalDeviceInformation[DeviceIndex+1];
+		  Controller->V2.InquiryUnitSerialNumber[DeviceIndex] =
+		    Controller->V2.InquiryUnitSerialNumber[DeviceIndex+1];
+		}
+	      Controller->V2.PhysicalDeviceInformation
+			     [DAC960_V2_MaxPhysicalDevices-1] = NULL;
+	      Controller->V2.InquiryUnitSerialNumber
+			     [DAC960_V2_MaxPhysicalDevices-1] = NULL;
+	      PhysicalDeviceInfo =
+		Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex];
+	      InquiryUnitSerialNumber =
+		Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex];
+	    }
 	  if (PhysicalDeviceInfo == NULL ||
 	      (NewPhysicalDeviceInfo->Channel !=
 	       PhysicalDeviceInfo->Channel) ||
@@ -4072,14 +4119,14 @@
 	      (NewPhysicalDeviceInfo->LogicalUnit !=
 	       PhysicalDeviceInfo->LogicalUnit))
 	    {
-	      unsigned int DeviceIndex;
 	      PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
 		kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
 	      InquiryUnitSerialNumber =
 		(DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
 		  kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
 			  GFP_ATOMIC);
-	      if (InquiryUnitSerialNumber == NULL)
+	      if (InquiryUnitSerialNumber == NULL &&
+		  PhysicalDeviceInfo != NULL)
 		{
 		  kfree(PhysicalDeviceInfo);
 		  PhysicalDeviceInfo = NULL;
@@ -4092,21 +4139,6 @@
 			       ? "" : " - Allocation Failed"));
 	      if (PhysicalDeviceInfo != NULL)
 		{
-		  for (DeviceIndex = PhysicalDeviceIndex;
-		       DeviceIndex < DAC960_V2_MaxPhysicalDevices - 1;
-		       DeviceIndex++)
-		    {
-		      Controller->V2.PhysicalDeviceInformation[DeviceIndex+1] =
-			Controller->V2.PhysicalDeviceInformation[DeviceIndex];
-		      Controller->V2.InquiryUnitSerialNumber[DeviceIndex+1] =
-			Controller->V2.InquiryUnitSerialNumber[DeviceIndex];
-		      Controller->V2.PhysicalDeviceInformation
-				     [PhysicalDeviceIndex] =
-			PhysicalDeviceInfo;
-		      Controller->V2.InquiryUnitSerialNumber
-				     [PhysicalDeviceIndex] =
-			InquiryUnitSerialNumber;
-		    }
 		  memset(PhysicalDeviceInfo, 0,
 			 sizeof(DAC960_V2_PhysicalDeviceInfo_T));
 		  PhysicalDeviceInfo->PhysicalDeviceState =
@@ -4114,6 +4146,21 @@
 		  memset(InquiryUnitSerialNumber, 0,
 			 sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
 		  InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+		  for (DeviceIndex = DAC960_V2_MaxPhysicalDevices - 1;
+		       DeviceIndex > PhysicalDeviceIndex;
+		       DeviceIndex--)
+		    {
+		      Controller->V2.PhysicalDeviceInformation[DeviceIndex] =
+			Controller->V2.PhysicalDeviceInformation[DeviceIndex-1];
+		      Controller->V2.InquiryUnitSerialNumber[DeviceIndex] =
+			Controller->V2.InquiryUnitSerialNumber[DeviceIndex-1];
+		    }
+		  Controller->V2.PhysicalDeviceInformation
+				 [PhysicalDeviceIndex] =
+		    PhysicalDeviceInfo;
+		  Controller->V2.InquiryUnitSerialNumber
+				 [PhysicalDeviceIndex] =
+		    InquiryUnitSerialNumber;
 		  Controller->V2.NeedDeviceSerialNumberInformation = true;
 		}
 	    }
@@ -4176,8 +4223,10 @@
 				  NewPhysicalDeviceInfo
 				  ->PredictedFailuresDetected);
 		}
-	      if (PhysicalDeviceInfo->PhysicalDeviceState
-		  == DAC960_V2_Device_Dead &&
+	      if ((PhysicalDeviceInfo->PhysicalDeviceState
+		   == DAC960_V2_Device_Dead ||
+		   PhysicalDeviceInfo->PhysicalDeviceState
+		   == DAC960_V2_Device_InvalidState) &&
 		  NewPhysicalDeviceInfo->PhysicalDeviceState
 		  != DAC960_V2_Device_Dead)
 		Controller->V2.NeedDeviceSerialNumberInformation = true;
@@ -4188,7 +4237,28 @@
 	  Controller->V2.PhysicalDeviceIndex++;
 	}
       else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid)
-	Controller->V2.NeedPhysicalDeviceInformation = false;
+	{
+	  unsigned int DeviceIndex;
+	  for (DeviceIndex = Controller->V2.PhysicalDeviceIndex;
+	       DeviceIndex < DAC960_V2_MaxPhysicalDevices;
+	       DeviceIndex++)
+	    {
+	      DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo =
+		Controller->V2.PhysicalDeviceInformation[DeviceIndex];
+	      DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+		Controller->V2.InquiryUnitSerialNumber[DeviceIndex];
+	      if (PhysicalDeviceInfo == NULL) break;
+	      DAC960_Critical("Physical Device %d:%d No Longer Exists\n",
+			      Controller,
+			      PhysicalDeviceInfo->Channel,
+			      PhysicalDeviceInfo->TargetID);
+	      Controller->V2.PhysicalDeviceInformation[DeviceIndex] = NULL;
+	      Controller->V2.InquiryUnitSerialNumber[DeviceIndex] = NULL;
+	      kfree(PhysicalDeviceInfo);
+	      kfree(InquiryUnitSerialNumber);
+	    }
+	  Controller->V2.NeedPhysicalDeviceInformation = false;
+	}
       else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid &&
 	       CommandStatus == DAC960_V2_NormalCompletion)
 	{
@@ -4295,13 +4365,50 @@
 					 NewLogicalDeviceInfo
 					 ->PatrolOperationBlockNumber,
 					 LogicalDeviceSize);
+	      if (LogicalDeviceInfo->BackgroundInitializationInProgress &&
+		  !NewLogicalDeviceInfo->BackgroundInitializationInProgress)
+		DAC960_Progress("Logical Drive %d (/dev/rd/c%dd%d) "
+				"Background Initialization %s\n",
+				Controller,
+				LogicalDeviceNumber,
+				Controller->ControllerNumber,
+				LogicalDeviceNumber,
+				(NewLogicalDeviceInfo->LogicalDeviceControl
+						      .LogicalDeviceInitialized
+				 ? "Completed" : "Failed"));
 	      memcpy(LogicalDeviceInfo, NewLogicalDeviceInfo,
 		     sizeof(DAC960_V2_LogicalDeviceInfo_T));
 	    }
+	  Controller->V2.LogicalDriveFoundDuringScan
+			 [LogicalDeviceNumber] = true;
 	  NewLogicalDeviceInfo->LogicalDeviceNumber++;
 	}
       else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid)
-	Controller->V2.NeedLogicalDeviceInformation = false;
+	{
+	  int LogicalDriveNumber;
+	  for (LogicalDriveNumber = 0;
+	       LogicalDriveNumber < DAC960_MaxLogicalDrives;
+	       LogicalDriveNumber++)
+	    {
+	      DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
+		Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
+	      if (LogicalDeviceInfo == NULL ||
+		  Controller->V2.LogicalDriveFoundDuringScan
+				 [LogicalDriveNumber])
+		continue;
+	      DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
+			      "No Longer Exists\n", Controller,
+			      LogicalDriveNumber,
+			      Controller->ControllerNumber,
+			      LogicalDriveNumber);
+	      Controller->V2.LogicalDeviceInformation
+			     [LogicalDriveNumber] = NULL;
+	      kfree(LogicalDeviceInfo);
+	      Controller->LogicalDriveInitiallyAccessible
+			  [LogicalDriveNumber] = false;
+	    }
+	  Controller->V2.NeedLogicalDeviceInformation = false;
+	}
       if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
 	  - Controller->V2.NextEventSequenceNumber > 0)
 	{
@@ -4317,7 +4424,7 @@
 	  CommandMailbox->GetEvent.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentDataPointer =
-	    Virtual_to_Bus(&Controller->V2.Event);
+	    Virtual_to_Bus64(&Controller->V2.Event);
 	  CommandMailbox->GetEvent.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -4354,7 +4461,7 @@
 	      CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				     .ScatterGatherSegments[0]
 				     .SegmentDataPointer =
-		Virtual_to_Bus(InquiryUnitSerialNumber);
+		Virtual_to_Bus64(InquiryUnitSerialNumber);
 	      CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				     .ScatterGatherSegments[0]
 				     .SegmentByteCount =
@@ -4363,6 +4470,14 @@
 	      Controller->V2.NeedDeviceSerialNumberInformation = false;
 	      return;
 	    }
+	  if (Controller->V2.StartPhysicalDeviceInformationScan)
+	    {
+	      Controller->V2.PhysicalDeviceIndex = 0;
+	      Controller->V2.NewPhysicalDeviceInformation.Channel = 0;
+	      Controller->V2.NewPhysicalDeviceInformation.TargetID = 0;
+	      Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0;
+	      Controller->V2.StartPhysicalDeviceInformationScan = false;
+	    }
 	  CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferSize =
 	    sizeof(DAC960_V2_PhysicalDeviceInfo_T);
@@ -4377,7 +4492,7 @@
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 					    .ScatterGatherSegments[0]
 					    .SegmentDataPointer =
-	    Virtual_to_Bus(&Controller->V2.NewPhysicalDeviceInformation);
+	    Virtual_to_Bus64(&Controller->V2.NewPhysicalDeviceInformation);
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 					    .ScatterGatherSegments[0]
 					    .SegmentByteCount =
@@ -4387,6 +4502,18 @@
 	}
       if (Controller->V2.NeedLogicalDeviceInformation)
 	{
+	  if (Controller->V2.StartLogicalDeviceInformationScan)
+	    {
+	      int LogicalDriveNumber;
+	      for (LogicalDriveNumber = 0;
+		   LogicalDriveNumber < DAC960_MaxLogicalDrives;
+		   LogicalDriveNumber++)
+		Controller->V2.LogicalDriveFoundDuringScan
+			       [LogicalDriveNumber] = false;
+	      Controller->V2.NewLogicalDeviceInformation
+			    .LogicalDeviceNumber = 0;
+	      Controller->V2.StartLogicalDeviceInformationScan = false;
+	    }
 	  CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferSize =
 	    sizeof(DAC960_V2_LogicalDeviceInfo_T);
@@ -4397,7 +4524,7 @@
 	  CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 					   .ScatterGatherSegments[0]
 					   .SegmentDataPointer =
-	    Virtual_to_Bus(&Controller->V2.NewLogicalDeviceInformation);
+	    Virtual_to_Bus64(&Controller->V2.NewLogicalDeviceInformation);
 	  CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 					   .ScatterGatherSegments[0]
 					   .SegmentByteCount =
@@ -4695,7 +4822,8 @@
   DAC960_V1_ClearCommand(Command);
   Command->CommandType = DAC960_MonitoringCommand;
   CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry;
-  CommandMailbox->Type3.BusAddress = Virtual_to_Bus(&Controller->V1.NewEnquiry);
+  CommandMailbox->Type3.BusAddress =
+    Virtual_to_Bus32(&Controller->V1.NewEnquiry);
   DAC960_QueueCommand(Command);
 }
 
@@ -4723,7 +4851,7 @@
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentDataPointer =
-    Virtual_to_Bus(&Controller->V2.NewControllerInformation);
+    Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentByteCount =
@@ -4766,6 +4894,28 @@
 	&Controller->V2.ControllerInformation;
       unsigned int StatusChangeCounter =
 	Controller->V2.HealthStatusBuffer->StatusChangeCounter;
+      boolean ForceMonitoringCommand = false;
+      if (jiffies - Controller->SecondaryMonitoringTime
+	  > DAC960_SecondaryMonitoringInterval)
+	{
+	  int LogicalDriveNumber;
+	  for (LogicalDriveNumber = 0;
+	       LogicalDriveNumber < DAC960_MaxLogicalDrives;
+	       LogicalDriveNumber++)
+	    {
+	      DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
+		Controller->V2.LogicalDeviceInformation[LogicalDriveNumber];
+	      if (LogicalDeviceInfo == NULL) continue;
+	      if (!LogicalDeviceInfo->LogicalDeviceControl
+				     .LogicalDeviceInitialized &&
+		  Controller->LogicalDriveUsageCount[LogicalDriveNumber] > 0)
+		{
+		  ForceMonitoringCommand = true;
+		  break;
+		}
+	    }
+	  Controller->SecondaryMonitoringTime = jiffies;
+	}
       if (StatusChangeCounter == Controller->V2.StatusChangeCounter &&
 	  Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
 	  == Controller->V2.NextEventSequenceNumber &&
@@ -4776,7 +4926,8 @@
 	   ControllerInfo->RebuildsActive +
 	   ControllerInfo->OnlineExpansionsActive == 0 ||
 	   jiffies - Controller->PrimaryMonitoringTime
-	   < DAC960_MonitoringTimerInterval))
+	   < DAC960_MonitoringTimerInterval) &&
+	  !ForceMonitoringCommand)
 	{
 	  Controller->MonitoringTimer.expires =
 	    jiffies + DAC960_HealthStatusMonitoringInterval;
@@ -4895,8 +5046,7 @@
   DiskGeometry_T Geometry, *UserGeometry;
   DAC960_Controller_T *Controller;
   int PartitionNumber;
-  if (File == NULL) return -EINVAL;
-  if (File->f_flags & O_NONBLOCK)
+  if (File != NULL && (File->f_flags & O_NONBLOCK))
     return DAC960_UserIOCTL(Inode, File, Request, Argument);
   if (ControllerNumber < 0 || ControllerNumber > DAC960_ControllerCount - 1)
     return -ENXIO;
@@ -5136,10 +5286,17 @@
 	if (CommandOpcode == DAC960_V1_DCDB)
 	  {
 	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	    while (Controller->V1.DirectCommandActive[DCDB.Channel]
-						     [DCDB.TargetID] ||
-		   (Command = DAC960_AllocateCommand(Controller)) == NULL)
+	    while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
 	      DAC960_WaitForCommand(Controller);
+	    while (Controller->V1.DirectCommandActive[DCDB.Channel]
+						     [DCDB.TargetID])
+	      {
+		spin_unlock_irq(&io_request_lock);
+		__wait_event(Controller->CommandWaitQueue,
+			     !Controller->V1.DirectCommandActive
+					     [DCDB.Channel][DCDB.TargetID]);
+		spin_lock_irq(&io_request_lock);
+	      }
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = true;
 	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
@@ -5148,8 +5305,8 @@
 	    memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
 		   sizeof(DAC960_V1_CommandMailbox_T));
 	    Command->V1.CommandMailbox.Type3.BusAddress =
-	      Virtual_to_Bus(&DCDB);
-	    DCDB.BusAddress = Virtual_to_Bus(DataTransferBuffer);
+	      Virtual_to_Bus32(&DCDB);
+	    DCDB.BusAddress = Virtual_to_Bus32(DataTransferBuffer);
 	  }
 	else
 	  {
@@ -5163,7 +5320,7 @@
 		   sizeof(DAC960_V1_CommandMailbox_T));
 	    if (DataTransferBuffer != NULL)
 	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus(DataTransferBuffer);
+		Virtual_to_Bus32(DataTransferBuffer);
 	  }
 	DAC960_ExecuteCommand(Command);
 	CommandStatus = Command->V1.CommandStatus;
@@ -5276,7 +5433,7 @@
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentDataPointer =
-	      Virtual_to_Bus(DataTransferBuffer);
+	      Virtual_to_Bus64(DataTransferBuffer);
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -5288,7 +5445,7 @@
 				  .NoAutoRequestSense = false;
 	    CommandMailbox->Common.RequestSenseSize = RequestSenseLength;
 	    CommandMailbox->Common.RequestSenseBusAddress =
-	      Virtual_to_Bus(RequestSenseBuffer);
+	      Virtual_to_Bus64(RequestSenseBuffer);
 	  }
 	DAC960_ExecuteCommand(Command);
 	CommandStatus = Command->V2.CommandStatus;
@@ -5468,9 +5625,9 @@
 	    memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox,
 		   sizeof(DAC960_V1_CommandMailbox_T));
 	    Command->V1.CommandMailbox.Type3.BusAddress =
-	      Virtual_to_Bus(DCDB);
+	      Virtual_to_Bus32(DCDB);
 	    Command->V1.KernelCommand = KernelCommand;
-	    DCDB->BusAddress = Virtual_to_Bus(DataTransferBuffer);
+	    DCDB->BusAddress = Virtual_to_Bus32(DataTransferBuffer);
 	    DAC960_QueueCommand(Command);
 	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	  }
@@ -5489,7 +5646,7 @@
 		   sizeof(DAC960_V1_CommandMailbox_T));
 	    if (DataTransferBuffer != NULL)
 	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus(DataTransferBuffer);
+		Virtual_to_Bus32(DataTransferBuffer);
 	    Command->V1.KernelCommand = KernelCommand;
 	    DAC960_QueueCommand(Command);
 	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
@@ -5566,7 +5723,7 @@
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentDataPointer =
-	      Virtual_to_Bus(DataTransferBuffer);
+	      Virtual_to_Bus64(DataTransferBuffer);
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -5577,7 +5734,7 @@
 	    CommandMailbox->Common.CommandControlBits
 				  .NoAutoRequestSense = false;
 	    CommandMailbox->Common.RequestSenseBusAddress =
-	      Virtual_to_Bus(RequestSenseBuffer);
+	      Virtual_to_Bus64(RequestSenseBuffer);
 	  }
 	Command->V2.KernelCommand = KernelCommand;
 	DAC960_QueueCommand(Command);
@@ -5669,7 +5826,7 @@
 	    }
 	  if (MessageLevel == DAC960_AnnounceLevel)
 	    {
-	      static int AnnouncementLines;
+	      static int AnnouncementLines = 0;
 	      if (++AnnouncementLines <= 2)
 		printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
 		       Buffer);
@@ -6015,7 +6172,7 @@
       CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl;
       CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
       CommandMailbox->Type3R.BusAddress =
-	Virtual_to_Bus(&OldRebuildRateConstant);
+	Virtual_to_Bus32(&OldRebuildRateConstant);
       DAC960_ExecuteCommand(Command);
       switch (Command->V1.CommandStatus)
 	{
@@ -6071,7 +6228,7 @@
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentDataPointer =
-    Virtual_to_Bus(&PhysicalToLogicalDevice);
+    Virtual_to_Bus64(&PhysicalToLogicalDevice);
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentByteCount =
diff -u --recursive --new-file v2.4.1/linux/drivers/block/DAC960.h linux/drivers/block/DAC960.h
--- v2.4.1/linux/drivers/block/DAC960.h	Mon Aug 21 09:23:54 2000
+++ linux/drivers/block/DAC960.h	Tue Feb 20 21:26:22 2001
@@ -2,7 +2,7 @@
 
   Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
 
-  Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com>
+  Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
 
   This program is free software; you may redistribute and/or modify it under
   the terms of the GNU General Public License Version 2 as published by the
@@ -259,6 +259,7 @@
   DAC960_V1_ClearBadDataTable =			0x26,
   DAC960_V1_GetErrorTable =			0x17,
   DAC960_V1_AddCapacityAsync =			0x2A,
+  DAC960_V1_BackgroundInitializationControl =	0x2B,
   /* Configuration Related Commands */
   DAC960_V1_ReadConfig2 =			0x3D,
   DAC960_V1_WriteConfig2 =			0x3C,
@@ -450,14 +451,16 @@
   unsigned int NonVolatileMemorySize;			/* Bytes 36-39 */
   struct {
     enum {
-      DAC960_V1_DRAM =				0x0,
-      DAC960_V1_EDO =				0x1,
-      DAC960_V1_SDRAM =				0x2
+      DAC960_V1_RamType_DRAM =			0x0,
+      DAC960_V1_RamType_EDO =			0x1,
+      DAC960_V1_RamType_SDRAM =			0x2,
+      DAC960_V1_RamType_Last =			0x7
     } __attribute__ ((packed)) RamType:3;		/* Byte 40 Bits 0-2 */
     enum {
-      DAC960_V1_None =				0x0,
-      DAC960_V1_Parity =			0x1,
-      DAC960_V1_ECC =				0x2
+      DAC960_V1_ErrorCorrection_None =		0x0,
+      DAC960_V1_ErrorCorrection_Parity =	0x1,
+      DAC960_V1_ErrorCorrection_ECC =		0x2,
+      DAC960_V1_ErrorCorrection_Last =		0x7
     } __attribute__ ((packed)) ErrorCorrection:3;	/* Byte 40 Bits 3-5 */
     boolean FastPageMode:1;				/* Byte 40 Bit 6 */
     boolean LowPowerMemory:1;				/* Byte 40 Bit 7 */
@@ -523,7 +526,9 @@
   struct {
     boolean Clustering:1;				/* Byte 116 Bit 0 */
     boolean MylexOnlineRAIDExpansion:1;			/* Byte 116 Bit 1 */
-    unsigned int :30;					/* Bytes 116-119 */
+    boolean ReadAhead:1;				/* Byte 116 Bit 2 */
+    boolean BackgroundInitialization:1;			/* Byte 116 Bit 3 */
+    unsigned int :28;					/* Bytes 116-119 */
   } FirmwareFeatures;
   unsigned int :32;					/* Bytes 120-123 */
   unsigned int :32;					/* Bytes 124-127 */
@@ -993,7 +998,8 @@
     DAC960_V2_MemoryType_DRAM =			0x01,
     DAC960_V2_MemoryType_EDRAM =		0x02,
     DAC960_V2_MemoryType_EDO =			0x03,
-    DAC960_V2_MemoryType_SDRAM =		0x04
+    DAC960_V2_MemoryType_SDRAM =		0x04,
+    DAC960_V2_MemoryType_Last =			0x1F
   } __attribute__ ((packed)) MemoryType:5;		/* Byte 0 Bits 0-4 */
   boolean :1;						/* Byte 0 Bit 5 */
   boolean MemoryParity:1;				/* Byte 0 Bit 6 */
@@ -1269,13 +1275,15 @@
       DAC960_V2_ReadCacheDisabled =		0x0,
       DAC960_V2_ReadCacheEnabled =		0x1,
       DAC960_V2_ReadAheadEnabled =		0x2,
-      DAC960_V2_IntelligentReadAheadEnabled =	0x3
+      DAC960_V2_IntelligentReadAheadEnabled =	0x3,
+      DAC960_V2_ReadCache_Last =		0x7
     } __attribute__ ((packed)) ReadCache:3;		/* Byte 8 Bits 0-2 */
     enum {
       DAC960_V2_WriteCacheDisabled =		0x0,
       DAC960_V2_LogicalDeviceReadOnly =		0x1,
       DAC960_V2_WriteCacheEnabled =		0x2,
-      DAC960_V2_IntelligentWriteCacheEnabled =	0x3
+      DAC960_V2_IntelligentWriteCacheEnabled =	0x3,
+      DAC960_V2_WriteCache_Last =		0x7
     } __attribute__ ((packed)) WriteCache:3;		/* Byte 8 Bits 3-5 */
     boolean :1;						/* Byte 8 Bit 6 */
     boolean LogicalDeviceInitialized:1;			/* Byte 8 Bit 7 */
@@ -2336,6 +2344,7 @@
       boolean NeedDeviceSerialNumberInformation;
       boolean NeedRebuildProgress;
       boolean NeedConsistencyCheckProgress;
+      boolean StartDeviceStateScan;
       boolean RebuildProgressFirst;
       boolean RebuildFlagPending;
       boolean RebuildStatusPending;
@@ -2375,6 +2384,8 @@
       boolean NeedLogicalDeviceInformation;
       boolean NeedPhysicalDeviceInformation;
       boolean NeedDeviceSerialNumberInformation;
+      boolean StartLogicalDeviceInformationScan;
+      boolean StartPhysicalDeviceInformationScan;
       DAC960_V2_CommandMailbox_T *FirstCommandMailbox;
       DAC960_V2_CommandMailbox_T *LastCommandMailbox;
       DAC960_V2_CommandMailbox_T *NextCommandMailbox;
@@ -2397,6 +2408,7 @@
       DAC960_V2_PhysicalDevice_T
 	LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives];
       DAC960_V2_Event_T Event;
+      boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives];
     } V2;
   } FW;
   DiskPartition_T DiskPartitions[DAC960_MinorCount];
@@ -2503,26 +2515,39 @@
 
 
 /*
-  Virtual_to_Bus maps from Kernel Virtual Addresses to PCI Bus Addresses.
+  Virtual_to_Bus32 maps from Kernel Virtual Addresses to 32 Bit PCI Bus
+  Addresses.
 */
 
-static inline DAC960_BusAddress32_T Virtual_to_Bus(void *VirtualAddress)
+static inline DAC960_BusAddress32_T Virtual_to_Bus32(void *VirtualAddress)
 {
   return (DAC960_BusAddress32_T) virt_to_bus(VirtualAddress);
 }
 
 
 /*
-  Bus_to_Virtual maps from PCI Bus Addresses to Kernel Virtual Addresses.
+  Bus32_to_Virtual maps from 32 Bit PCI Bus Addresses to Kernel Virtual
+  Addresses.
 */
 
-static inline void *Bus_to_Virtual(DAC960_BusAddress32_T BusAddress)
+static inline void *Bus32_to_Virtual(DAC960_BusAddress32_T BusAddress)
 {
   return (void *) bus_to_virt(BusAddress);
 }
 
 
 /*
+  Virtual_to_Bus64 maps from Kernel Virtual Addresses to 64 Bit PCI Bus
+  Addresses.
+*/
+
+static inline DAC960_BusAddress64_T Virtual_to_Bus64(void *VirtualAddress)
+{
+  return (DAC960_BusAddress64_T) virt_to_bus(VirtualAddress);
+}
+
+
+/*
   Define the DAC960 BA Series Controller Interface Register Offsets.
 */
 
@@ -2789,8 +2814,13 @@
 void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
 				    DAC960_V2_CommandMailbox_T *CommandMailbox)
 {
-  writel(Virtual_to_Bus(CommandMailbox),
+#ifdef __ia64__
+  writeq(Virtual_to_Bus64(CommandMailbox),
 	 ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset);
+#else
+  writel(Virtual_to_Bus32(CommandMailbox),
+	 ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset);
+#endif
 }
 
 static inline DAC960_V2_CommandIdentifier_T
@@ -3090,8 +3120,13 @@
 void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
 				    DAC960_V2_CommandMailbox_T *CommandMailbox)
 {
-  writel(Virtual_to_Bus(CommandMailbox),
+#ifdef __ia64__
+  writeq(Virtual_to_Bus64(CommandMailbox),
+	 ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset);
+#else
+  writel(Virtual_to_Bus32(CommandMailbox),
 	 ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset);
+#endif
 }
 
 static inline DAC960_V2_CommandIdentifier_T
diff -u --recursive --new-file v2.4.1/linux/drivers/block/acsi.c linux/drivers/block/acsi.c
--- v2.4.1/linux/drivers/block/acsi.c	Sun Dec 31 10:31:33 2000
+++ linux/drivers/block/acsi.c	Fri Feb  9 11:30:22 2001
@@ -59,7 +59,7 @@
 #include <linux/mm.h>
 #include <linux/major.h>
 #include <linux/blk.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <scsi/scsi.h> /* for SCSI_IOCTL_GET_IDLUN */
 typedef void Scsi_Device; /* hack to avoid including scsi.h */
diff -u --recursive --new-file v2.4.1/linux/drivers/block/acsi_slm.c linux/drivers/block/acsi_slm.c
--- v2.4.1/linux/drivers/block/acsi_slm.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/block/acsi_slm.c	Fri Feb  9 11:30:22 2001
@@ -64,7 +64,7 @@
 #include <linux/interrupt.h>
 #include <linux/time.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/block/ataflop.c linux/drivers/block/ataflop.c
--- v2.4.1/linux/drivers/block/ataflop.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/block/ataflop.c	Fri Feb  9 11:30:22 2001
@@ -74,7 +74,7 @@
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/block/cciss.c linux/drivers/block/cciss.c
--- v2.4.1/linux/drivers/block/cciss.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/cciss.c	Fri Feb  9 11:30:22 2001
@@ -26,7 +26,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -44,8 +44,8 @@
 #include <linux/genhd.h>
 
 #define CCISS_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
-#define DRIVER_NAME "Compaq CISS Driver (v 2.4.0)"
-#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,0)
+#define DRIVER_NAME "Compaq CISS Driver (v 2.4.2)"
+#define DRIVER_VERSION CCISS_DRIVER_VERSION(2,4,2)
 
 /* Embedded module documentation macros - see modules.h */
 MODULE_AUTHOR("Charles M. White III - Compaq Computer Corporation");
@@ -63,6 +63,8 @@
  */
 static struct board_type products[] = {
 	{ 0x40700E11, "Smart Array 5300",	&SA5_access },
+	{ 0x40800E11, "Smart Array 5i", &SA5B_access},
+	{ 0x40820E11, "Smart Array 532", &SA5B_access},
 };
 
 /* How long to wait (in millesconds) for board to go into simple mode */
@@ -76,23 +78,7 @@
 
 static struct proc_dir_entry *proc_cciss;
 
-static void do_cciss_request(int i);
-/*
- * This is a hack.  This driver eats a major number for each controller, and
- * sets blkdev[xxx].request_fn to each one of these so the real request
- * function knows what controller its working with.
- */
-#define DO_CCISS_REQUEST(x) { do_cciss_request(x); }
-
-static void do_cciss_request0(request_queue_t * q) DO_CCISS_REQUEST(0);
-static void do_cciss_request1(request_queue_t * q) DO_CCISS_REQUEST(1);
-static void do_cciss_request2(request_queue_t * q) DO_CCISS_REQUEST(2);
-static void do_cciss_request3(request_queue_t * q) DO_CCISS_REQUEST(3);
-static void do_cciss_request4(request_queue_t * q) DO_CCISS_REQUEST(4);
-static void do_cciss_request5(request_queue_t * q) DO_CCISS_REQUEST(5);
-static void do_cciss_request6(request_queue_t * q) DO_CCISS_REQUEST(6);
-static void do_cciss_request7(request_queue_t * q) DO_CCISS_REQUEST(7);
-
+static void do_cciss_request(request_queue_t *q);
 static int cciss_open(struct inode *inode, struct file *filep);
 static int cciss_release(struct inode *inode, struct file *filep);
 static int cciss_ioctl(struct inode *inode, struct file *filep, 
@@ -693,7 +679,7 @@
         spin_lock_irqsave(&io_request_lock, flags);
         if (hba[ctlr]->drv[target].usage_count > maxusage) {
                 spin_unlock_irqrestore(&io_request_lock, flags);
-                printk(KERN_WARNING "cpqarray: Device busy for "
+                printk(KERN_WARNING "cciss: Device busy for "
                         "revalidation (usage=%d)\n",
                         hba[ctlr]->drv[target].usage_count);
                 return -EBUSY;
@@ -1175,48 +1161,85 @@
 	}
 	complete_buffers(cmd->bh, status);
 }
+
+
+static inline int cpq_new_segment(request_queue_t *q, struct request *rq,
+                                  int max_segments)
+{
+        if (rq->nr_segments < MAXSGENTRIES) {
+                rq->nr_segments++;
+                return 1;
+        }
+        return 0;
+}
+
+static int cpq_back_merge_fn(request_queue_t *q, struct request *rq,
+                             struct buffer_head *bh, int max_segments)
+{
+        if (rq->bhtail->b_data + rq->bhtail->b_size == bh->b_data)
+                return 1;
+        return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_front_merge_fn(request_queue_t *q, struct request *rq,
+                             struct buffer_head *bh, int max_segments)
+{
+        if (bh->b_data + bh->b_size == rq->bh->b_data)
+                return 1;
+        return cpq_new_segment(q, rq, max_segments);
+}
+
+static int cpq_merge_requests_fn(request_queue_t *q, struct request *rq,
+                                 struct request *nxt, int max_segments)
+{
+        int total_segments = rq->nr_segments + nxt->nr_segments;
+
+        if (rq->bhtail->b_data + rq->bhtail->b_size == nxt->bh->b_data)
+                total_segments--;
+
+        if (total_segments > MAXSGENTRIES)
+                return 0;
+
+        rq->nr_segments = total_segments;
+        return 1;
+}
+
 /* 
  * Get a request and submit it to the controller. 
  * Currently we do one request at a time.  Ideally we would like to send
  * everything to the controller on the first call, but there is a danger
  * of holding the io_request_lock for to long.  
  */
-static void do_cciss_request(int ctlr)
+static void do_cciss_request(request_queue_t *q)
 {
-	ctlr_info_t *h= hba[ctlr];
+	ctlr_info_t *h= q->queuedata; 
 	CommandList_struct *c;
 	int log_unit, start_blk, seg, sect;
 	char *lastdataend;
 	struct buffer_head *bh;
-	struct list_head *queue_head;
+	struct list_head *queue_head = &q->queue_head;
 	struct request *creq;
 	u64bit temp64;
 
-	queue_head = &blk_dev[MAJOR_NR+ctlr].request_queue.queue_head;	
-	if (list_empty(queue_head))
-	{
-		/* nothing to do... */
-		start_io(h);
-		return;
-	}
+	if (q->plugged || list_empty(queue_head)) {
+                start_io(h);
+                return;
+        }
+
 	creq =	blkdev_entry_next_request(queue_head); 
-	if ((creq == NULL) || (creq->rq_status == RQ_INACTIVE))
-	{
-		/* nothing to do... restart processing and return */ 
-		start_io(h);
-		return;
-	}
-	if ((ctlr != (MAJOR(creq->rq_dev)-MAJOR_NR)) || (ctlr > nr_ctlr)
-		|| (h == NULL))
-	{
-#ifdef CCISS_DEBUG
-		printk(KERN_WARNING "cciss: doreq cmd of %d, %x at %p\n",
-			ctlr, creq->rq_dev, creq);
-#endif /* CCISS_DEBUG */
-		complete_buffers(creq->bh, 0);
-		start_io(h); 
-		return;
-	}
+	if (creq->nr_segments > MAXSGENTRIES)
+                BUG();
+
+        if ((h->ctlr != MAJOR(creq->rq_dev)-MAJOR_NR) || (h->ctlr > nr_ctlr))
+        {
+                printk(KERN_WARNING "doreq cmd for %d, %x at %p\n",
+                                h->ctlr, creq->rq_dev, creq);
+                blkdev_dequeue_request(creq);
+                complete_buffers(creq->bh, 0);
+                start_io(h);
+                return;
+        }
+
 	if (( c = cmd_alloc(h)) == NULL)
 	{
 		start_io(h);
@@ -1229,7 +1252,7 @@
 	log_unit = MINOR(creq->rq_dev) >> NWD_SHIFT; 
 	c->Header.ReplyQueue = 0;  // unused in simple mode
 	c->Header.Tag.lower = c->busaddr;  // use the physical address the cmd block for tag
-	c->Header.LUN.LogDev.VolId= hba[ctlr]->drv[log_unit].LunID;
+	c->Header.LUN.LogDev.VolId= hba[h->ctlr]->drv[log_unit].LunID;
 	c->Header.LUN.LogDev.Mode = 1;
 	c->Request.CDBLen = 10; // 12 byte commands not in FW yet;
 	c->Request.Type.Type =  TYPE_CMD; // It is a command. 
@@ -1238,10 +1261,10 @@
 		(creq->cmd == READ) ? XFER_READ: XFER_WRITE; 
 	c->Request.Timeout = 0; // Don't time out	
 	c->Request.CDB[0] = (creq->cmd == READ) ? CCISS_READ : CCISS_WRITE;
-	start_blk = hba[ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector;
+	start_blk = hba[h->ctlr]->hd[MINOR(creq->rq_dev)].start_sect + creq->sector;
+#ifdef CCISS_DEBUG
 	if (bh == NULL)
 		panic("cciss: bh== NULL?");
-#ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n",(int) creq->sector,
 		(int) creq->nr_sectors);	
 #endif /* CCISS_DEBUG */
@@ -1251,28 +1274,21 @@
 	while(bh)
 	{
 		sect += bh->b_size/512;
-		if (bh->b_size % 512)
-		{
-			printk(KERN_CRIT "cciss:  Oh Man.  %d+%d, size=%d\n", 
-				(int) creq->sector, sect, (int) bh->b_size);
-			panic("b_size 512 != 0\n");
-		}
 		if (bh->b_data == lastdataend)
 		{  // tack it on to the last segment 
 			c->SG[seg-1].Len +=bh->b_size;
 			lastdataend += bh->b_size;
 		} else
 		{
+			if (seg == MAXSGENTRIES)
+				BUG();
 			c->SG[seg].Len = bh->b_size;
 			temp64.val = (__u64) virt_to_bus(bh->b_data);
 			c->SG[seg].Addr.lower = temp64.val32.lower;
 			c->SG[seg].Addr.upper = temp64.val32.upper;
 			c->SG[0].Ext = 0;  // we are not chaining
 			lastdataend = bh->b_data + bh->b_size;
-			if( ++seg == MAXSGENTRIES)
-			{
-				break; 
-			}
+			seg++;
 		}
 		bh = bh->b_reqnext;
 	}
@@ -1280,10 +1296,6 @@
 	if( seg > h->maxSG)
 		h->maxSG = seg; 
 
-	/* adjusting the remaining request, if any */ 
-	creq-> sector+= sect;
-	creq->nr_sectors -= sect; 
-
 #ifdef CCISS_DEBUG
 	printk(KERN_DEBUG "cciss: Submitting %d sectors in %d segments\n", sect, seg);
 #endif /* CCISS_DEBUG */
@@ -1295,31 +1307,23 @@
 	c->Request.CDB[4]= (start_blk >>  8) & 0xff;
 	c->Request.CDB[5]= start_blk & 0xff;
 	c->Request.CDB[6]= 0; // (sect >> 24) & 0xff; MSB
-	// c->Request.CDB[7]= (sect >> 16) & 0xff; 
 	c->Request.CDB[7]= (sect >>  8) & 0xff; 
 	c->Request.CDB[8]= sect & 0xff; 
 	c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0;
 
-	/* check to see if we going to complete the entire request */ 
-	/* if so, mark this request as Done and ready the next one */ 
-	if (creq->nr_sectors)
-	{
-#ifdef CCISS_DEBUG
-		printk(KERN_DEBUG "cciss: More to do on the same request %p %ld\n", 
-			creq, creq->nr_sectors);
-#endif /* CCISS_DEBUG */
+			
+	blkdev_dequeue_request(creq);
 
-		creq->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-	} else
-	{
+	
+        /*
+         * ehh, we can't really end the request here since it's not
+         * even started yet. for now it shouldn't hurt though
+         */
 #ifdef CCISS_DEBUG
-		printk("cciss: Done with %p, queueing %p\n", creq);
-#endif /* CCISS_DEBUG */
-			
-		blkdev_dequeue_request(creq);
-		end_that_request_last(creq);
-	}
+	printk("Done with %p\n", creq);
+#endif /* CCISS_DEBUG */ 
+	end_that_request_last(creq);
+
 	addQ(&(h->reqQ),c);
 	h->Qdepth++;
 	if(h->Qdepth > h->maxQsinceinit)
@@ -1352,7 +1356,7 @@
 			a &= ~3;
 			if ((c = h->cmpQ) == NULL)
 			{  
-				printk(KERN_WARNING "cpqarray: Completion of %08lx ignored\n", (unsigned long)a1);
+				printk(KERN_WARNING "cciss: Completion of %08lx ignored\n", (unsigned long)a1);
 				continue;	
 			} 
 			while(c->busaddr != a) {
@@ -1379,7 +1383,7 @@
 	/*
 	 * See if we can queue up some more IO
 	 */
-	do_cciss_request(h->ctlr);
+	do_cciss_request(BLK_DEFAULT_QUEUE(MAJOR_NR + h->ctlr));
 	spin_unlock_irqrestore(&io_request_lock, flags);
 }
 /* 
@@ -1420,7 +1424,7 @@
 	printk("   Heartbeat Counter = 0x%x\n\n\n", 
 			readl(&(tb->HeartBeat)));
 }
-#endif /* CCISS_DEBUG */
+#endif /* CCISS_DEBUG */ 
 
 static int cciss_pci_init(ctlr_info_t *c, unchar bus, unchar device_fn)
 {
@@ -1430,7 +1434,9 @@
 	uint addr[6];
 	__u32 board_id;
 	struct pci_dev *pdev;
-
+	int cfg_offset;
+	int cfg_base_addr;
+	int cfg_base_addr_index;
 	int i;
 
 	pdev = pci_find_slot(bus, device_fn);
@@ -1473,15 +1479,38 @@
 	 * Memory base addr is first addr , the second points to the config
          *   table
 	 */
-	c->paddr = pci_resource_start(pdev, 0);
-	c->vaddr = remap_pci_mem(c->paddr, 128);
-	c->cfgtable = (CfgTable_struct *) remap_pci_mem(addr[1], 
-						sizeof(CfgTable_struct));
+
+	c->paddr = addr[0] & 0xfffffff0; /* remove the addressing mode bits */
+#ifdef CCISS_DEBUG
+	printk("address 0 = %x\n", c->paddr);
+#endif /* CCISS_DEBUG */ 
+	c->vaddr = remap_pci_mem(c->paddr, 200);
+
+	/* get the address index number */
+	cfg_base_addr = readl(c->vaddr + SA5_CTCFG_OFFSET);
+	/* I am not prepared to deal with a 64 bit address value */
+	cfg_base_addr &= 0xffff;
+#ifdef CCISS_DEBUG
+	printk("cfg base address = %x\n", cfg_base_addr);
+#endif /* CCISS_DEBUG */
+	cfg_base_addr_index = (cfg_base_addr  - PCI_BASE_ADDRESS_0)/4;
+#ifdef CCISS_DEBUG
+	printk("cfg base address index = %x\n", cfg_base_addr_index);
+#endif /* CCISS_DEBUG */
+
+	cfg_offset = readl(c->vaddr + SA5_CTMEM_OFFSET);
+#ifdef CCISS_DEBUG
+	printk("cfg offset = %x\n", cfg_offset);
+#endif /* CCISS_DEBUG */
+	c->cfgtable = (CfgTable_struct *) 
+		remap_pci_mem((addr[cfg_base_addr_index] & 0xfffffff0)
+				+ cfg_offset, sizeof(CfgTable_struct));
 	c->board_id = board_id;
 
 #ifdef CCISS_DEBUG
 	print_cfg_table(c->cfgtable); 
 #endif /* CCISS_DEBUG */
+
 	for(i=0; i<NR_PRODUCTS; i++) {
 		if (board_id == products[i].board_id) {
 			c->product_name = products[i].product_name;
@@ -1495,6 +1524,14 @@
 				(unsigned long)board_id);
 		return -1;
 	}
+	if (  (readb(&c->cfgtable->Signature[0]) != 'C') ||
+	      (readb(&c->cfgtable->Signature[1]) != 'I') ||
+	      (readb(&c->cfgtable->Signature[2]) != 'S') ||
+	      (readb(&c->cfgtable->Signature[3]) != 'S') )
+	{
+		printk("Does not appear to be a valid CISS config table\n");
+		return -1;
+	}
 #ifdef CCISS_DEBUG
 	printk("Trying to put board into Simple mode\n");
 #endif /* CCISS_DEBUG */ 
@@ -1536,14 +1573,22 @@
 
 	int index;
 	unchar bus=0, dev_fn=0;
-	
+
+	#define CCISS_BOARD_TYPES 2
+	static int cciss_device_id[CCISS_BOARD_TYPES] = { 
+		PCI_DEVICE_ID_COMPAQ_CISS, PCI_DEVICE_ID_COMPAQ_CISSB};
+	int brdtype;
+
+	/* search for all PCI board types that could be for this driver */
+	for(brdtype=0; brdtype<CCISS_BOARD_TYPES; brdtype++)
+	{
 		for(index=0; ; index++) {
 			if (pcibios_find_device(PCI_VENDOR_ID_COMPAQ,
-			 	PCI_DEVICE_ID_COMPAQ_CISS, 
+			 	cciss_device_id[brdtype], 
 					index, &bus, &dev_fn))
 				break;
 			printk(KERN_DEBUG "cciss: Device %x has been found at %x %x\n",
-				PCI_DEVICE_ID_COMPAQ_CISS, bus, dev_fn);
+				cciss_device_id[brdtype], bus, dev_fn);
 			if (index == 1000000) break;
 			if (nr_ctlr == 8) {
 				printk(KERN_WARNING "cciss: This driver"
@@ -1569,6 +1614,7 @@
 			nr_ctlr++;
 
 		}
+	}
 	return nr_ctlr;
 
 }
@@ -1698,8 +1744,8 @@
 			printk(KERN_WARNING "cciss: read capacity failed\n");
 			total_size = block_size = 0; 
 		}	
-		printk("      blocks= %d block_size= %d\n", total_size,
-					block_size);
+		printk(KERN_INFO "      blocks= %d block_size= %d\n", 
+					total_size, block_size);
 
 		/* Execute the command to read the disk geometry */
 		memset(inq_buff, 0, sizeof(InquiryData_struct));
@@ -1759,13 +1805,7 @@
 {
 	int num_cntlrs_reg = 0;
 	int i,j;
-
-	void (*request_fns[MAX_CTLR])(request_queue_t *) = {
-                do_cciss_request0, do_cciss_request1,
-                do_cciss_request2, do_cciss_request3,
-                do_cciss_request4, do_cciss_request5,
-                do_cciss_request6, do_cciss_request7,
-        };
+	request_queue_t *q;
 
 	/* detect controllers */
 	cciss_pci_detect();
@@ -1834,15 +1874,22 @@
 		hba[i]->access.set_intr_mask(hba[i], CCISS_INTR_ON);
 
 		cciss_procinit(i);
-		
-		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR+i),
-				request_fns[i]);
-		blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR+i), 0);
+
+		q = BLK_DEFAULT_QUEUE(MAJOR_NR + i);
+                q->queuedata = hba[i];
+                blk_init_queue(q, do_cciss_request);
+                blk_queue_headactive(q, 0);		
 
 		/* fill in the other Kernel structs */
 		blksize_size[MAJOR_NR+i] = hba[i]->blocksizes;
                 hardsect_size[MAJOR_NR+i] = hba[i]->hardsizes;
                 read_ahead[MAJOR_NR+i] = READ_AHEAD;
+
+		/* Set the pointers to queue functions */ 
+		q->back_merge_fn = cpq_back_merge_fn;
+                q->front_merge_fn = cpq_front_merge_fn;
+                q->merge_requests_fn = cpq_merge_requests_fn;
+
 
 		/* Fill in the gendisk data */ 	
 		hba[i]->gendisk.major = MAJOR_NR + i;
diff -u --recursive --new-file v2.4.1/linux/drivers/block/cciss.h linux/drivers/block/cciss.h
--- v2.4.1/linux/drivers/block/cciss.h	Mon Dec 11 12:50:40 2000
+++ linux/drivers/block/cciss.h	Sat Feb  3 12:13:19 2001
@@ -94,8 +94,13 @@
 #define SA5_REPLY_PORT_OFFSET		0x44
 #define SA5_INTR_STATUS		0x30
 
+#define SA5_CTCFG_OFFSET	0xB4
+#define SA5_CTMEM_OFFSET	0xB8
+
 #define SA5_INTR_OFF		0x08
+#define SA5B_INTR_OFF		0x04
 #define SA5_INTR_PENDING	0x08
+#define SA5B_INTR_PENDING	0x04
 #define FIFO_EMPTY		0xffffffff	
 
 #define  CISS_ERROR_BIT		0x02
@@ -133,6 +138,22 @@
 	}
 }
 /*
+ *  This card is the oposite of the other cards.
+ *   0 turns interrupts on...
+ *   0x04 turns them off...
+ */
+static void SA5B_intr_mask(ctlr_info_t *h, unsigned long val)
+{
+        if (val)
+        { /* Turn interrupts on */
+                writel(0, h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+        } else /* Turn them off */
+        {
+                writel( SA5B_INTR_OFF,
+                        h->vaddr + SA5_REPLY_INTR_MASK_OFFSET);
+        }
+}
+/*
  *  Returns true if fifo is full.  
  * 
  */ 
@@ -183,6 +204,21 @@
 	return 0 ;
 }
 
+/*
+ *      Returns true if an interrupt is pending..
+ */
+static unsigned long SA5B_intr_pending(ctlr_info_t *h)
+{
+        unsigned long register_value  =
+                readl(h->vaddr + SA5_INTR_STATUS);
+#ifdef CCISS_DEBUG
+        printk("cciss: intr_pending %lx\n", register_value);
+#endif  /* CCISS_DEBUG */
+        if( register_value &  SA5B_INTR_PENDING)
+                return  1;
+        return 0 ;
+}
+
 
 static struct access_method SA5_access = {
 	SA5_submit_command,
@@ -190,6 +226,14 @@
 	SA5_fifo_full,
 	SA5_intr_pending,
 	SA5_completed,
+};
+
+static struct access_method SA5B_access = {
+        SA5_submit_command,
+        SA5B_intr_mask,
+        SA5_fifo_full,
+        SA5B_intr_pending,
+        SA5_completed,
 };
 
 struct board_type {
diff -u --recursive --new-file v2.4.1/linux/drivers/block/cpqarray.c linux/drivers/block/cpqarray.c
--- v2.4.1/linux/drivers/block/cpqarray.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/cpqarray.c	Tue Feb 13 14:13:43 2001
@@ -28,7 +28,7 @@
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/major.h>
 #include <linux/fs.h>
@@ -44,8 +44,8 @@
 
 #define SMART2_DRIVER_VERSION(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
 
-#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.1)"
-#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,1)
+#define DRIVER_NAME "Compaq SMART2 Driver (v 2.4.2)"
+#define DRIVER_VERSION SMART2_DRIVER_VERSION(2,4,2)
 
 /* Embedded module documentation macros - see modules.h */
 /* Original author Chris Frantz - Compaq Computer Corporation */
@@ -1327,7 +1327,7 @@
 	case IDA_WRITE_MEDIA:
 		kfree(p);
 		break;
-	default:
+	default:;
 		/* Nothing to do */
 	}
 
@@ -1528,7 +1528,7 @@
 	ida_gendisk[ctlr].nr_real = 0;
 
 	/*
-	 * Tell the array controller not to give us any interupts while
+	 * Tell the array controller not to give us any interrupts while
 	 * we check the new geometry.  Then turn interrupts back on when
 	 * we're done.
 	 */
diff -u --recursive --new-file v2.4.1/linux/drivers/block/cpqarray.h linux/drivers/block/cpqarray.h
--- v2.4.1/linux/drivers/block/cpqarray.h	Mon Dec 11 12:50:39 2000
+++ linux/drivers/block/cpqarray.h	Fri Feb  9 11:30:22 2001
@@ -28,7 +28,7 @@
 #ifdef __KERNEL__
 #include <linux/blkdev.h>
 #include <linux/locks.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/timer.h>
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/block/elevator.c linux/drivers/block/elevator.c
--- v2.4.1/linux/drivers/block/elevator.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/elevator.c	Thu Feb 15 16:58:34 2001
@@ -27,10 +27,58 @@
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
+/*
+ * This is a bit tricky. It's given that bh and rq are for the same
+ * device, but the next request might of course not be. Run through
+ * the tests below to check if we want to insert here if we can't merge
+ * bh into an existing request
+ */
+inline int bh_rq_in_between(struct buffer_head *bh, struct request *rq,
+			    struct list_head *head)
+{
+	struct list_head *next;
+	struct request *next_rq;
+
+	next = rq->queue.next;
+	if (next == head)
+		return 0;
+
+	/*
+	 * if the device is different (usually on a different partition),
+	 * just check if bh is after rq
+	 */
+	next_rq = blkdev_entry_to_request(next);
+	if (next_rq->rq_dev != rq->rq_dev)
+		return bh->b_rsector > rq->sector;
+
+	/*
+	 * ok, rq, next_rq and bh are on the same device. if bh is in between
+	 * the two, this is the sweet spot
+	 */
+	if (bh->b_rsector < next_rq->sector && bh->b_rsector > rq->sector)
+		return 1;
+
+	/*
+	 * next_rq is ordered wrt rq, but bh is not in between the two
+	 */
+	if (next_rq->sector > rq->sector)
+		return 0;
+
+	/*
+	 * next_rq and rq not ordered, if we happen to be either before
+	 * next_rq or after rq insert here anyway
+	 */
+	if (bh->b_rsector > rq->sector || bh->b_rsector < next_rq->sector)
+		return 1;
+
+	return 0;
+}
+
+
 int elevator_linus_merge(request_queue_t *q, struct request **req,
 			 struct list_head * head,
 			 struct buffer_head *bh, int rw,
-			 int max_sectors, int max_segments)
+			 int max_sectors)
 {
 	struct list_head *entry = &q->queue_head;
 	unsigned int count = bh->b_size >> 9, ret = ELEVATOR_NO_MERGE;
@@ -41,17 +89,17 @@
 		/*
 		 * simply "aging" of requests in queue
 		 */
-		if (__rq->elevator_sequence-- <= 0) {
-			*req = __rq;
+		if (__rq->elevator_sequence-- <= 0)
 			break;
-		}
 
 		if (__rq->sem)
 			continue;
-		if (__rq->cmd != rw)
-			continue;
 		if (__rq->rq_dev != bh->b_rdev)
 			continue;
+		if (!*req && bh_rq_in_between(bh, __rq, &q->queue_head))
+			*req = __rq;
+		if (__rq->cmd != rw)
+			continue;
 		if (__rq->nr_sectors + count > max_sectors)
 			continue;
 		if (__rq->elevator_sequence < count)
@@ -65,8 +113,7 @@
 			__rq->elevator_sequence -= count;
 			*req = __rq;
 			break;
-		} else if (!*req && BHRQ_IN_ORDER(bh, __rq))
-			*req = __rq;
+		}
 	}
 
 	return ret;
@@ -97,7 +144,7 @@
 int elevator_noop_merge(request_queue_t *q, struct request **req,
 			struct list_head * head,
 			struct buffer_head *bh, int rw,
-			int max_sectors, int max_segments)
+			int max_sectors)
 {
 	struct list_head *entry;
 	unsigned int count = bh->b_size >> 9;
diff -u --recursive --new-file v2.4.1/linux/drivers/block/floppy.c linux/drivers/block/floppy.c
--- v2.4.1/linux/drivers/block/floppy.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/block/floppy.c	Fri Feb  9 11:30:22 2001
@@ -152,7 +152,7 @@
 #include <linux/hdreg.h>
 
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/block/ll_rw_blk.c linux/drivers/block/ll_rw_blk.c
--- v2.4.1/linux/drivers/block/ll_rw_blk.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/ll_rw_blk.c	Thu Feb 15 16:58:34 2001
@@ -576,8 +576,6 @@
 static inline void add_request(request_queue_t * q, struct request * req,
 			       struct list_head *insert_here)
 {
-	int major;
-
 	drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1);
 
 	if (!q->plugged && q->head_active && insert_here == &q->queue_head) {
@@ -590,10 +588,6 @@
 	 * inserted at elevator_merge time
 	 */
 	list_add(&req->queue, insert_here);
-
-	major = MAJOR(req->rq_dev);
-	if (major >= DAC960_MAJOR+0 && major <= DAC960_MAJOR+7)
-		q->request_fn(q);
 }
 
 void inline blk_refill_freelist(request_queue_t *q, int rw)
@@ -705,7 +699,7 @@
 {
 	unsigned int sector, count;
 	int max_segments = MAX_SEGMENTS;
-	struct request * req = NULL, *freereq = NULL;
+	struct request * req, *freereq = NULL;
 	int rw_ahead, max_sectors, el_ret;
 	struct list_head *head, *insert_here;
 	int latency;
@@ -751,6 +745,7 @@
 	max_sectors = get_max_sectors(bh->b_rdev);
 
 again:
+	req = NULL;
 	head = &q->queue_head;
 	/*
 	 * Now we acquire the request spinlock, we have to be mega careful
@@ -765,8 +760,7 @@
 	} else if (q->head_active && !q->plugged)
 		head = head->next;
 
-	el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw,
-					     max_sectors, max_segments);
+	el_ret = elevator->elevator_merge_fn(q, &req, head, bh, rw,max_sectors);
 	switch (el_ret) {
 
 		case ELEVATOR_BACK_MERGE:
@@ -851,8 +845,6 @@
 out:
 	if (freereq)
 		blkdev_release_request(freereq);
-	if (!q->plugged)
-		q->request_fn(q);
 	spin_unlock_irq(&io_request_lock);
 	return 0;
 end_io:
diff -u --recursive --new-file v2.4.1/linux/drivers/block/loop.c linux/drivers/block/loop.c
--- v2.4.1/linux/drivers/block/loop.c	Fri Dec 29 14:07:21 2000
+++ linux/drivers/block/loop.c	Fri Feb  9 11:30:22 2001
@@ -4,7 +4,7 @@
  *  Written by Theodore Ts'o, 3/29/93
  * 
  * Copyright 1993 by Theodore Ts'o.  Redistribution of this file is
- * permitted under the GNU Public License.
+ * permitted under the GNU General Public License.
  *
  * DES encryption plus some minor changes by Werner Almesberger, 30-MAY-1993
  * more DES encryption plus IDEA encryption by Nicholas J. Leon, June 20, 1996
@@ -75,7 +75,7 @@
 #define TIMEOUT_VALUE (6 * HZ)
 #include <linux/blk.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 static int max_loop = 8;
 static struct loop_device *loop_dev;
 static int *loop_sizes;
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/aten.c linux/drivers/block/paride/aten.c
--- v2.4.1/linux/drivers/block/paride/aten.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/aten.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         aten.c  (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                            Under the terms of the GNU public license.
+                            Under the terms of the GNU General Public License.
 
 	aten.c is a low-level protocol driver for the ATEN EH-100
 	parallel port adapter.  The EH-100 supports 4-bit and 8-bit
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/bpck.c linux/drivers/block/paride/bpck.c
--- v2.4.1/linux/drivers/block/paride/bpck.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/bpck.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
 	bpck.c	(c) 1996-8  Grant R. Guenther <grant@torque.net>
-		            Under the terms of the GNU public license.
+		            Under the terms of the GNU General Public License.
 
 	bpck.c is a low-level protocol driver for the MicroSolutions 
 	"backpack" parallel port IDE adapter.  
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/comm.c linux/drivers/block/paride/comm.c
--- v2.4.1/linux/drivers/block/paride/comm.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/comm.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         comm.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                              Under the terms of the GNU public license.
+                              Under the terms of the GNU General Public License.
 
 	comm.c is a low-level protocol driver for some older models
 	of the DataStor "Commuter" parallel to IDE adapter.  Some of
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/dstr.c linux/drivers/block/paride/dstr.c
--- v2.4.1/linux/drivers/block/paride/dstr.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/dstr.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         dstr.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                              Under the terms of the GNU public license.
+                              Under the terms of the GNU General Public License.
 
         dstr.c is a low-level protocol driver for the 
         DataStor EP2000 parallel to IDE adapter chip.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/epat.c linux/drivers/block/paride/epat.c
--- v2.4.1/linux/drivers/block/paride/epat.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/epat.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         epat.c  (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                            Under the terms of the GNU public license.
+                            Under the terms of the GNU General Public License.
 
 	This is the low level protocol driver for the EPAT parallel
         to IDE adapter from Shuttle Technologies.  This adapter is
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/epia.c linux/drivers/block/paride/epia.c
--- v2.4.1/linux/drivers/block/paride/epia.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/epia.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         epia.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                              Under the terms of the GNU public license.
+                              Under the terms of the GNU General Public License.
 
         epia.c is a low-level protocol driver for Shuttle Technologies 
 	EPIA parallel to IDE adapter chip.  This device is now obsolete
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/fit2.c linux/drivers/block/paride/fit2.c
--- v2.4.1/linux/drivers/block/paride/fit2.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/fit2.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         fit2.c        (c) 1998  Grant R. Guenther <grant@torque.net>
-                          Under the terms of the GNU public license.
+                          Under the terms of the GNU General Public License.
 
 	fit2.c is a low-level protocol driver for the older version
         of the Fidelity International Technology parallel port adapter.  
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/fit3.c linux/drivers/block/paride/fit3.c
--- v2.4.1/linux/drivers/block/paride/fit3.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/fit3.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         fit3.c        (c) 1998  Grant R. Guenther <grant@torque.net>
-                          Under the terms of the GNU public license.
+                          Under the terms of the GNU General Public License.
 
 	fit3.c is a low-level protocol driver for newer models 
         of the Fidelity International Technology parallel port adapter.  
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/friq.c linux/drivers/block/paride/friq.c
--- v2.4.1/linux/drivers/block/paride/friq.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/friq.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
 	friq.c	(c) 1998    Grant R. Guenther <grant@torque.net>
-		            Under the terms of the GNU public license
+		            Under the terms of the GNU General Public License
 
 	friq.c is a low-level protocol driver for the Freecom "IQ"
 	parallel port IDE adapter.   Early versions of this adapter
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/frpw.c linux/drivers/block/paride/frpw.c
--- v2.4.1/linux/drivers/block/paride/frpw.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/frpw.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
 	frpw.c	(c) 1996-8  Grant R. Guenther <grant@torque.net>
-		            Under the terms of the GNU public license
+		            Under the terms of the GNU General Public License
 
 	frpw.c is a low-level protocol driver for the Freecom "Power"
 	parallel port IDE adapter.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/kbic.c linux/drivers/block/paride/kbic.c
--- v2.4.1/linux/drivers/block/paride/kbic.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/kbic.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /*
         kbic.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                              Under the terms of the GNU public license.
+                              Under the terms of the GNU General Public License.
 
         This is a low-level driver for the KBIC-951A and KBIC-971A
         parallel to IDE adapter chips from KingByte Information Systems.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/ktti.c linux/drivers/block/paride/ktti.c
--- v2.4.1/linux/drivers/block/paride/ktti.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/ktti.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         ktti.c        (c) 1998  Grant R. Guenther <grant@torque.net>
-                          Under the terms of the GNU public license.
+                          Under the terms of the GNU General Public License.
 
 	ktti.c is a low-level protocol driver for the KT Technology
 	parallel port adapter.  This adapter is used in the "PHd" 
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/on20.c linux/drivers/block/paride/on20.c
--- v2.4.1/linux/drivers/block/paride/on20.c	Thu Dec 16 13:57:04 1999
+++ linux/drivers/block/paride/on20.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
 	on20.c	(c) 1996-8  Grant R. Guenther <grant@torque.net>
-		            Under the terms of the GNU public license.
+		            Under the terms of the GNU General Public License.
 
         on20.c is a low-level protocol driver for the
         Onspec 90c20 parallel to IDE adapter. 
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/on26.c linux/drivers/block/paride/on26.c
--- v2.4.1/linux/drivers/block/paride/on26.c	Wed May  3 01:45:18 2000
+++ linux/drivers/block/paride/on26.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         on26.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                              Under the terms of the GNU public license.
+                              Under the terms of the GNU General Public License.
 
         on26.c is a low-level protocol driver for the 
         OnSpec 90c26 parallel to IDE adapter chip.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/paride.c linux/drivers/block/paride/paride.c
--- v2.4.1/linux/drivers/block/paride/paride.c	Wed Jul 12 16:24:33 2000
+++ linux/drivers/block/paride/paride.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         paride.c  (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                              Under the terms of the GNU public license.
+                              Under the terms of the GNU General Public License.
 
 	This is the base module for the family of device drivers
         that support parallel port IDE devices.  
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/pcd.c linux/drivers/block/paride/pcd.c
--- v2.4.1/linux/drivers/block/paride/pcd.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/block/paride/pcd.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
 	pcd.c	(c) 1997-8  Grant R. Guenther <grant@torque.net>
-		            Under the terms of the GNU public license.
+		            Under the terms of the GNU General Public License.
 
 	This is a high-level driver for parallel port ATAPI CD-ROM
         drives based on chips supported by the paride module.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/pd.c linux/drivers/block/paride/pd.c
--- v2.4.1/linux/drivers/block/paride/pd.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/paride/pd.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         pd.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                            Under the terms of the GNU public license.
+                            Under the terms of the GNU General Public License.
 
         This is the high-level driver for parallel port IDE hard
         drives based on chips supported by the paride module.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/pf.c linux/drivers/block/paride/pf.c
--- v2.4.1/linux/drivers/block/paride/pf.c	Sat Feb  3 19:51:26 2001
+++ linux/drivers/block/paride/pf.c	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         pf.c    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                            Under the terms of the GNU public license.
+                            Under the terms of the GNU General Public License.
 
         This is the high-level driver for parallel port ATAPI disk
         drives based on chips supported by the paride module.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/pg.c linux/drivers/block/paride/pg.c
--- v2.4.1/linux/drivers/block/paride/pg.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/block/paride/pg.c	Fri Feb  9 11:30:22 2001
@@ -1,6 +1,6 @@
 /* 
 	pg.c    (c) 1998  Grant R. Guenther <grant@torque.net>
-			  Under the terms of the GNU public license.
+			  Under the terms of the GNU General Public License.
 
 	The pg driver provides a simple character device interface for
 	sending ATAPI commands to a device.  With the exception of the
@@ -167,7 +167,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mtio.h>
 #include <linux/pg.h>
 #include <linux/wait.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/pseudo.h linux/drivers/block/paride/pseudo.h
--- v2.4.1/linux/drivers/block/paride/pseudo.h	Mon Dec 11 12:58:14 2000
+++ linux/drivers/block/paride/pseudo.h	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /* 
         pseudo.h    (c) 1997-8  Grant R. Guenther <grant@torque.net>
-                                Under the terms of the GNU public license.
+                                Under the terms of the GNU General Public License.
 
 	This is the "pseudo-interrupt" logic for parallel port drivers.
 
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/pt.c linux/drivers/block/paride/pt.c
--- v2.4.1/linux/drivers/block/paride/pt.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/block/paride/pt.c	Fri Feb  9 11:30:22 2001
@@ -1,6 +1,6 @@
 /* 
         pt.c    (c) 1998  Grant R. Guenther <grant@torque.net>
-                          Under the terms of the GNU public license.
+                          Under the terms of the GNU General Public License.
 
         This is the high-level driver for parallel port ATAPI tape
         drives based on chips supported by the paride module.
@@ -146,7 +146,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mtio.h>
 #include <linux/wait.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/block/paride/setup.h linux/drivers/block/paride/setup.h
--- v2.4.1/linux/drivers/block/paride/setup.h	Mon Dec 11 12:50:10 2000
+++ linux/drivers/block/paride/setup.h	Sun Feb  4 10:05:29 2001
@@ -1,6 +1,6 @@
 /*
 	setup.h	   (c) 1997-8   Grant R. Guenther <grant@torque.net>
-		                Under the terms of the GNU public license.
+		                Under the terms of the GNU General Public License.
 
         This is a table driven setup function for kernel modules
         using the module.variable=val,... command line notation.
diff -u --recursive --new-file v2.4.1/linux/drivers/block/rd.c linux/drivers/block/rd.c
--- v2.4.1/linux/drivers/block/rd.c	Fri Nov 17 16:46:55 2000
+++ linux/drivers/block/rd.c	Fri Feb  9 11:30:22 2001
@@ -53,7 +53,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioctl.h>
 #include <linux/fd.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/block/xd.c linux/drivers/block/xd.c
--- v2.4.1/linux/drivers/block/xd.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/block/xd.c	Fri Feb 16 16:02:35 2001
@@ -28,6 +28,9 @@
  *   Recovered DMA access. Abridged messages. Added support for DTC5051CX,
  *   WD1002-27X & XEBEC controllers. Driver uses now some jumper settings.
  *   Extended ioctl() support.
+ *
+ * Bugfix: 15/02/01, Paul G. - inform queue layer of tiny xd_maxsect.
+ *
  */
 
 #include <linux/module.h>
@@ -59,7 +62,7 @@
 #define XD_INIT_DISK_DELAY	(30*HZ/1000)  /* 30 ms delay during disk initialization */
 
 /* Above may need to be increased if a problem with the 2nd drive detection
-   (ST11M controller) or resetting a controler (WD) appears */
+   (ST11M controller) or resetting a controller (WD) appears */
 
 XD_INFO xd_info[XD_MAXDRIVES];
 
@@ -118,6 +121,7 @@
 static struct hd_struct xd_struct[XD_MAXDRIVES << 6];
 static int xd_sizes[XD_MAXDRIVES << 6], xd_access[XD_MAXDRIVES];
 static int xd_blocksizes[XD_MAXDRIVES << 6];
+static int xd_maxsect[XD_MAXDRIVES << 6];
 
 extern struct block_device_operations xd_fops;
 
@@ -242,6 +246,10 @@
 			printk("xd: unable to get IRQ%d\n",xd_irq);
 	}
 
+	/* xd_maxsectors depends on controller - so set after detection */
+	for(i=0; i<(XD_MAXDRIVES << 6); i++) xd_maxsect[i] = xd_maxsectors;
+	max_sectors[MAJOR_NR] = xd_maxsect;
+
 	for (i = 0; i < xd_drives; i++) {
 		xd_valid[i] = 1;
 		register_disk(&xd_gendisk, MKDEV(MAJOR_NR,i<<6), 1<<6, &xd_fops,
@@ -877,7 +885,7 @@
 				xd_setparam(CMD_WDSETPARAM,drive,xd_info[drive].heads,xd_info[drive].cylinders,
 					((u_short *) (buf))[0xD8],((u_short *) (buf))[0xDA],buf[0x1B4]);
 		}
-	/* 1002 based RLL controler requests converted addressing, but reports physical 
+	/* 1002 based RLL controller requests converted addressing, but reports physical 
 	   (physical 26 sec., logical 17 sec.) 
 	   1004 based ???? */
 		if (rll & wd_1002) {
@@ -1058,7 +1066,7 @@
 	xd_info[drive].control = 0;
 }
 
-/* xd_setup: initialise controler from command line parameters */
+/* xd_setup: initialise controller from command line parameters */
 void __init do_xd_setup (int *integers)
 {
 	switch (integers[0]) {
diff -u --recursive --new-file v2.4.1/linux/drivers/block/z2ram.c linux/drivers/block/z2ram.c
--- v2.4.1/linux/drivers/block/z2ram.c	Mon Nov 27 17:11:26 2000
+++ linux/drivers/block/z2ram.c	Fri Feb  9 11:30:22 2001
@@ -28,7 +28,7 @@
 #define MAJOR_NR    Z2RAM_MAJOR
 
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/blk.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/cdrom.c linux/drivers/cdrom/cdrom.c
--- v2.4.1/linux/drivers/cdrom/cdrom.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/cdrom/cdrom.c	Fri Feb  9 11:30:22 2001
@@ -259,7 +259,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/malloc.h> 
+#include <linux/slab.h> 
 #include <linux/cdrom.h>
 #include <linux/sysctl.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/cdu31a.c linux/drivers/cdrom/cdu31a.c
--- v2.4.1/linux/drivers/cdrom/cdu31a.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/cdrom/cdu31a.c	Fri Feb  9 11:30:22 2001
@@ -164,7 +164,7 @@
 #include <linux/ioport.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/cm206.c linux/drivers/cdrom/cm206.c
--- v2.4.1/linux/drivers/cdrom/cm206.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/cdrom/cm206.c	Fri Feb  9 11:30:22 2001
@@ -190,7 +190,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 /* #include <linux/ucdrom.h> */
@@ -1283,7 +1283,7 @@
   case 1: 
     kfree(cd);
     release_region(cm206_base, 16);
-  default:
+  default:;
   }
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/cm206.h linux/drivers/cdrom/cm206.h
--- v2.4.1/linux/drivers/cdrom/cm206.h	Tue Dec  2 11:41:44 1997
+++ linux/drivers/cdrom/cm206.h	Sun Feb  4 10:05:29 2001
@@ -166,6 +166,6 @@
 #undef y
 #undef x
 
-#endif STATISTICS
+#endif /* STATISTICS */
 
-#endif LINUX_CM206_H
+#endif /* LINUX_CM206_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/gscd.c linux/drivers/cdrom/gscd.c
--- v2.4.1/linux/drivers/cdrom/gscd.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/cdrom/gscd.c	Fri Feb  9 11:30:22 2001
@@ -50,7 +50,7 @@
 
 #include <linux/module.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/mcd.c linux/drivers/cdrom/mcd.c
--- v2.4.1/linux/drivers/cdrom/mcd.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/cdrom/mcd.c	Sun Feb  4 10:05:29 2001
@@ -1158,7 +1158,7 @@
       return;
     }
     blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));
-  default:
+  default:;
   }
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/mcdx.c linux/drivers/cdrom/mcdx.c
--- v2.4.1/linux/drivers/cdrom/mcdx.c	Thu Oct 26 23:35:47 2000
+++ linux/drivers/cdrom/mcdx.c	Fri Feb  9 11:30:22 2001
@@ -66,7 +66,7 @@
 #include <linux/cdrom.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/optcd.c linux/drivers/cdrom/optcd.c
--- v2.4.1/linux/drivers/cdrom/optcd.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/cdrom/optcd.c	Sun Feb  4 10:05:29 2001
@@ -924,7 +924,7 @@
 		return -EIO;
 	return 0;
 }
-#endif MULTISESSION
+#endif /* MULTISESSION */
 
 
 static int update_toc(void)
@@ -962,7 +962,7 @@
 #ifdef MULTISESSION
  	if (disk_info.xa)
 		get_multi_disk_info();	/* Here disk_info.multi is set */
-#endif MULTISESSION
+#endif /* MULTISESSION */
 	if (disk_info.multi)
 		printk(KERN_WARNING "optcd: Multisession support experimental, "
 			"see linux/Documentation/cdrom/optcd\n");
@@ -1709,11 +1709,11 @@
 			disk_info.last_session.minute,
 			disk_info.last_session.second,
 			disk_info.last_session.frame);
-#endif DEBUG_MULTIS
+#endif /* DEBUG_MULTIS */
 
 	return 0;
 }
-#endif MULTISESSION
+#endif /* MULTISESSION */
 
 
 static int cdromreset(void)
@@ -2026,7 +2026,7 @@
 
 __setup("optcd=", optcd_setup);
 
-#endif MODULE
+#endif /* MODULE */
 
 /* Test for presence of drive and initialize it. Called at boot time
    or during module initialisation. */
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/optcd.h linux/drivers/cdrom/optcd.h
--- v2.4.1/linux/drivers/cdrom/optcd.h	Tue Dec  2 11:41:44 1997
+++ linux/drivers/cdrom/optcd.h	Sun Feb  4 10:05:29 2001
@@ -49,4 +49,4 @@
 #define N_BUFS		6
 
 
-#endif _LINUX_OPTCD_H
+#endif /* _LINUX_OPTCD_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/sbpcd.c linux/drivers/cdrom/sbpcd.c
--- v2.4.1/linux/drivers/cdrom/sbpcd.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/cdrom/sbpcd.c	Fri Feb 16 16:02:35 2001
@@ -322,6 +322,9 @@
  *		CD_AUDIO_COMPLETED state so workman (and other playes) can repeat play.
  *		Andrew J. Kroll <ag784@freenet.buffalo.edu> Wed Jul 26 04:24:10 EDT 2000
  *
+ *  4.64 Fix module parameters - were being completely ignored.
+ *	 Can also specify max_drives=N as a setup int to get rid of
+ *	 "ghost" drives on crap hardware (aren't they all?)   Paul Gortmaker
  *
  *  TODO
  *     implement "read all subchannel data" (96 bytes per frame)
@@ -336,6 +339,15 @@
  *
  */
 
+/*
+ * Trying to merge requests breaks this driver horribly (as in it goes
+ * boom and apparently has done so since 2.3.41).  As it is a legacy 
+ * driver for a horribly slow double speed CD on a hideous interface 
+ * designed for polled operation, I won't loose any sleep in simply 
+ * disallowing merging.				Paul G.  02/2001
+ */
+#define DONT_MERGE_REQUESTS
+
 #ifndef SBPCD_ISSUE
 #define SBPCD_ISSUE 1
 #endif SBPCD_ISSUE
@@ -474,6 +486,7 @@
 static int sbpcd[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */
 #endif
 MODULE_PARM(sbpcd, "2i");
+MODULE_PARM(max_drives, "i");
 
 #define NUM_PROBE  (sizeof(sbpcd) / sizeof(int))
 
@@ -561,7 +574,6 @@
 
 static int sbpcd_ioaddr = CDROM_PORT;	/* default I/O base address */
 static int sbpro_type = SBPRO;
-static unsigned char setup_done;
 static unsigned char f_16bit;
 static unsigned char do_16bit;
 static int CDo_command, CDo_reset;
@@ -578,15 +590,19 @@
 static unsigned char msgnum;
 static char msgbuf[80];
 
-static const char *str_sb = "SoundBlaster";
+static int max_drives = MAX_DRIVES;
+#ifndef MODULE
+static unsigned char setup_done;
 static const char *str_sb_l = "soundblaster";
-static const char *str_lm = "LaserMate";
-static const char *str_sp = "SPEA";
 static const char *str_sp_l = "spea";
-static const char *str_ss = "SoundScape";
 static const char *str_ss_l = "soundscape";
-static const char *str_t16 = "Teac16bit";
 static const char *str_t16_l = "teac16bit";
+static const char *str_ss = "SoundScape";
+#endif
+static const char *str_sb = "SoundBlaster";
+static const char *str_lm = "LaserMate";
+static const char *str_sp = "SPEA";
+static const char *str_t16 = "Teac16bit";
 static const char *type;
 
 #if !(SBPCD_ISSUE-1)
@@ -3739,7 +3755,7 @@
 	
 	msg(DBG_INI,"check_drives entered.\n");
 	ndrives=0;
-	for (j=0;j<MAX_DRIVES;j++)
+	for (j=0;j<max_drives;j++)
 	{
 		D_S[ndrives].drv_id=j;
 		if (sbpro_type==1) D_S[ndrives].drv_sel=(j&0x01)<<1|(j&0x02)>>1;
@@ -5540,6 +5556,7 @@
 int sbpcd_setup(char *s)
 #endif
 {
+#ifndef MODULE
 	int p[4];
 	(void)get_options(s, ARRAY_SIZE(p), p);
 	setup_done++;
@@ -5555,6 +5572,11 @@
 	else if (!strcmp(s,str_t16)) sbpro_type=3;
 	else if (!strcmp(s,str_t16_l)) sbpro_type=3;
 	if (p[0]>0) sbpcd_ioaddr=p[1];
+	if (p[0]>2) max_drives=p[3];
+#else
+	sbpcd_ioaddr = sbpcd[0];
+	sbpro_type = sbpcd[1];
+#endif
 	
 	CDo_command=sbpcd_ioaddr;
 	CDi_info=sbpcd_ioaddr;
@@ -5648,6 +5670,21 @@
 	msg(DBG_SEQ,"found SoundScape interface at %04X.\n", sbpcd_ioaddr);
 	return (0);
 }
+
+#ifdef DONT_MERGE_REQUESTS
+static int dont_merge_requests_fn(request_queue_t *q, struct request *req,
+                                struct request *next, int max_segments)
+{
+	return 0;
+}
+
+static int dont_bh_merge_fn(request_queue_t *q, struct request *req,
+                            struct buffer_head *bh, int max_segments)
+{
+	return 0;
+}
+#endif
+
 /*==========================================================================*/
 /*
  *  Test for presence of drive and initialize it.
@@ -5815,6 +5852,11 @@
 #endif MODULE
 	}
 	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
+#ifdef DONT_MERGE_REQUESTS
+	(BLK_DEFAULT_QUEUE(MAJOR_NR))->back_merge_fn = dont_bh_merge_fn;
+	(BLK_DEFAULT_QUEUE(MAJOR_NR))->front_merge_fn = dont_bh_merge_fn;
+	(BLK_DEFAULT_QUEUE(MAJOR_NR))->merge_requests_fn = dont_merge_requests_fn;
+#endif
 	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);
 	read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512);
 	
diff -u --recursive --new-file v2.4.1/linux/drivers/cdrom/sonycd535.c linux/drivers/cdrom/sonycd535.c
--- v2.4.1/linux/drivers/cdrom/sonycd535.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/cdrom/sonycd535.c	Fri Feb  9 11:30:22 2001
@@ -122,7 +122,7 @@
 #include <linux/hdreg.h>
 #include <linux/genhd.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/devfs_fs_kernel.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/Config.in linux/drivers/char/Config.in
--- v2.4.1/linux/drivers/char/Config.in	Fri Dec 29 14:07:21 2000
+++ linux/drivers/char/Config.in	Tue Feb 13 14:13:43 2001
@@ -183,7 +183,7 @@
    bool '  VIA chipset support' CONFIG_AGP_VIA
    bool '  AMD Irongate support' CONFIG_AGP_AMD
    bool '  Generic SiS support' CONFIG_AGP_SIS
-   bool '  ALI M1541 support' CONFIG_AGP_ALI
+   bool '  ALI chipset support' CONFIG_AGP_ALI
 fi
 
 source drivers/char/drm/Config.in
diff -u --recursive --new-file v2.4.1/linux/drivers/char/README.computone linux/drivers/char/README.computone
--- v2.4.1/linux/drivers/char/README.computone	Mon Apr 24 13:39:34 2000
+++ linux/drivers/char/README.computone	Fri Feb 16 16:02:36 2001
@@ -92,7 +92,7 @@
 to update the character drivers' makefile and configuration file, and other 
 kernel source files. A build script (ip2build) was included which applies 
 the patches if needed, and build any utilities needed.
-What you recieve may be a single patch file in conventional kernel
+What you receive may be a single patch file in conventional kernel
 patch format build script. That form can also be applied by
 running patch -p1 < ThePatchFile.  Otherwise the drivers source may be
 a tar file, then untar and run ip2build if a new installation.
diff -u --recursive --new-file v2.4.1/linux/drivers/char/README.epca linux/drivers/char/README.epca
--- v2.4.1/linux/drivers/char/README.epca	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/README.epca	Fri Feb 16 16:02:36 2001
@@ -319,7 +319,7 @@
 
                         1.  Removed code from pc_close which closes the 
                             drivers line discipline and restores its original
-                            line discipline.  This is currently unecessary,
+                            line discipline.  This is currently unnecessary,
                             though future fast cook enhancements may require
                             this.
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- v2.4.1/linux/drivers/char/acquirewdt.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/acquirewdt.c	Fri Feb  9 11:30:22 2001
@@ -28,7 +28,7 @@
 #include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/agp/agp.h linux/drivers/char/agp/agp.h
--- v2.4.1/linux/drivers/char/agp/agp.h	Fri Dec 29 14:07:21 2000
+++ linux/drivers/char/agp/agp.h	Tue Feb 13 14:13:43 2001
@@ -117,6 +117,8 @@
 	int (*remove_memory) (agp_memory *, off_t, int);
 	agp_memory *(*alloc_by_type) (size_t, int);
 	void (*free_by_type) (agp_memory *);
+	unsigned long (*agp_alloc_page) (void);
+	void (*agp_destroy_page) (unsigned long);
 };
 
 #define OUTREG32(mmap, addr, val)   __raw_writel((val), (mmap)+(addr))
@@ -203,6 +205,24 @@
 #ifndef PCI_DEVICE_ID_AL_M1541_0
 #define PCI_DEVICE_ID_AL_M1541_0	0x1541
 #endif
+#ifndef PCI_DEVICE_ID_AL_M1621_0
+#define PCI_DEVICE_ID_AL_M1621_0	0x1621
+#endif
+#ifndef PCI_DEVICE_ID_AL_M1631_0
+#define PCI_DEVICE_ID_AL_M1631_0	0x1631
+#endif
+#ifndef PCI_DEVICE_ID_AL_M1632_0
+#define PCI_DEVICE_ID_AL_M1632_0	0x1632
+#endif
+#ifndef PCI_DEVICE_ID_AL_M1641_0
+#define PCI_DEVICE_ID_AL_M1641_0	0x1641
+#endif
+#ifndef PCI_DEVICE_ID_AL_M1647_0
+#define PCI_DEVICE_ID_AL_M1647_0	0x1647
+#endif
+#ifndef PCI_DEVICE_ID_AL_M1651_0
+#define PCI_DEVICE_ID_AL_M1651_0	0x1651
+#endif
 
 /* intel register */
 #define INTEL_APBASE    0x10
@@ -267,5 +287,9 @@
 #define ALI_AGPCTRL	0xb8
 #define ALI_ATTBASE	0xbc
 #define ALI_TLBCTRL	0xc0
+#define ALI_TAGCTRL	0xc4
+#define ALI_CACHE_FLUSH_CTRL	0xD0
+#define ALI_CACHE_FLUSH_ADDR_MASK	0xFFFFF000
+#define ALI_CACHE_FLUSH_EN	0x100
 
 #endif				/* _AGP_BACKEND_PRIV_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/char/agp/agpgart_be.c linux/drivers/char/agp/agpgart_be.c
--- v2.4.1/linux/drivers/char/agp/agpgart_be.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/char/agp/agpgart_be.c	Tue Feb 13 14:13:43 2001
@@ -32,7 +32,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -133,45 +133,6 @@
 }
 
 /* 
- * Basic Page Allocation Routines -
- * These routines handle page allocation
- * and by default they reserve the allocated 
- * memory.  They also handle incrementing the
- * current_memory_agp value, Which is checked
- * against a maximum value.
- */
-
-static unsigned long agp_alloc_page(void)
-{
-	void *pt;
-
-	pt = (void *) __get_free_page(GFP_KERNEL);
-	if (pt == NULL) {
-		return 0;
-	}
-	atomic_inc(&virt_to_page(pt)->count);
-	set_bit(PG_locked, &virt_to_page(pt)->flags);
-	atomic_inc(&agp_bridge.current_memory_agp);
-	return (unsigned long) pt;
-}
-
-static void agp_destroy_page(unsigned long page)
-{
-	void *pt = (void *) page;
-
-	if (pt == NULL) {
-		return;
-	}
-	atomic_dec(&virt_to_page(pt)->count);
-	clear_bit(PG_locked, &virt_to_page(pt)->flags);
-	wake_up(&virt_to_page(pt)->wait);
-	free_page((unsigned long) pt);
-	atomic_dec(&agp_bridge.current_memory_agp);
-}
-
-/* End Basic Page Allocation Routines */
-
-/* 
  * Generic routines for handling agp_memory structures -
  * They use the basic page allocation routines to do the
  * brunt of the work.
@@ -245,7 +206,7 @@
 	if (curr->page_count != 0) {
 		for (i = 0; i < curr->page_count; i++) {
 			curr->memory[i] &= ~(0x00000fff);
-			agp_destroy_page((unsigned long)
+			agp_bridge.agp_destroy_page((unsigned long)
 					 phys_to_virt(curr->memory[i]));
 		}
 	}
@@ -290,7 +251,7 @@
 		return NULL;
 	}
 	for (i = 0; i < page_count; i++) {
-		new->memory[i] = agp_alloc_page();
+		new->memory[i] = agp_bridge.agp_alloc_page();
 
 		if (new->memory[i] == 0) {
 			/* Free this structure */
@@ -803,6 +764,45 @@
 	kfree(curr);
 }
 
+/* 
+ * Basic Page Allocation Routines -
+ * These routines handle page allocation
+ * and by default they reserve the allocated 
+ * memory.  They also handle incrementing the
+ * current_memory_agp value, Which is checked
+ * against a maximum value.
+ */
+
+static unsigned long agp_generic_alloc_page(void)
+{
+	void *pt;
+
+	pt = (void *) __get_free_page(GFP_KERNEL);
+	if (pt == NULL) {
+		return 0;
+	}
+	atomic_inc(&virt_to_page(pt)->count);
+	set_bit(PG_locked, &virt_to_page(pt)->flags);
+	atomic_inc(&agp_bridge.current_memory_agp);
+	return (unsigned long) pt;
+}
+
+static void agp_generic_destroy_page(unsigned long page)
+{
+	void *pt = (void *) page;
+
+	if (pt == NULL) {
+		return;
+	}
+	atomic_dec(&virt_to_page(pt)->count);
+	clear_bit(PG_locked, &virt_to_page(pt)->flags);
+	wake_up(&virt_to_page(pt)->wait);
+	free_page((unsigned long) pt);
+	atomic_dec(&agp_bridge.current_memory_agp);
+}
+
+/* End Basic Page Allocation Routines */
+
 void agp_enable(u32 mode)
 {
 	if (agp_bridge.type == NOT_SUPPORTED) return;
@@ -1018,7 +1018,7 @@
 			return NULL;
 		}
 	   	MOD_INC_USE_COUNT;
-		new->memory[0] = agp_alloc_page();
+		new->memory[0] = agp_bridge.agp_alloc_page();
 
 		if (new->memory[0] == 0) {
 			/* Free this structure */
@@ -1043,7 +1043,7 @@
 {
 	agp_free_key(curr->key);
    	if(curr->type == AGP_PHYS_MEMORY) {
-	   	agp_destroy_page((unsigned long)
+	   	agp_bridge.agp_destroy_page((unsigned long)
 				 phys_to_virt(curr->memory[0]));
 		vfree(curr->memory);
 	}
@@ -1081,6 +1081,8 @@
 	agp_bridge.remove_memory = intel_i810_remove_entries;
 	agp_bridge.alloc_by_type = intel_i810_alloc_by_type;
 	agp_bridge.free_by_type = intel_i810_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 }
@@ -1271,6 +1273,8 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 	
@@ -1299,6 +1303,8 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 	
@@ -1327,6 +1333,8 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 	
@@ -1442,6 +1450,8 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 	
@@ -1551,6 +1561,8 @@
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 }
@@ -1924,6 +1936,8 @@
 	agp_bridge.remove_memory = amd_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = agp_generic_alloc_page;
+	agp_bridge.agp_destroy_page = agp_generic_destroy_page;
 
 	return 0;
 	
@@ -1961,10 +1975,9 @@
 	u32 temp;
 
 	pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp);
-	pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL,
-			       ((temp & 0xffffff00) | 0x00000090));
-	pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL,
-			       ((temp & 0xffffff00) | 0x00000010));
+// clear tag
+	pci_write_config_dword(agp_bridge.dev, ALI_TAGCTRL,
+			((temp & 0xfffffff0) | 0x00000001|0x00000002));
 }
 
 static void ali_cleanup(void)
@@ -1975,10 +1988,13 @@
 	previous_size = A_SIZE_32(agp_bridge.previous_size);
 
 	pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp);
-	pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL,
-			       ((temp & 0xffffff00) | 0x00000090));
+// clear tag
+	pci_write_config_dword(agp_bridge.dev, ALI_TAGCTRL,
+			((temp & 0xffffff00) | 0x00000001|0x00000002));
+
+	pci_read_config_dword(agp_bridge.dev,  ALI_ATTBASE, &temp);
 	pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE,
-			       previous_size->size_value);
+			((temp & 0x00000ff0) | previous_size->size_value));
 }
 
 static int ali_configure(void)
@@ -1989,17 +2005,62 @@
 	current_size = A_SIZE_32(agp_bridge.current_size);
 
 	/* aperture size and gatt addr */
-	pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE,
-		    agp_bridge.gatt_bus_addr | current_size->size_value);
+	pci_read_config_dword(agp_bridge.dev, ALI_ATTBASE, &temp);
+	temp = (((temp & 0x00000ff0) | (agp_bridge.gatt_bus_addr & 0xfffff000))
+			| (current_size->size_value & 0xf));
+	pci_write_config_dword(agp_bridge.dev, ALI_ATTBASE, temp);
 
 	/* tlb control */
-	pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp);
-	pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL,
-			       ((temp & 0xffffff00) | 0x00000010));
+
+	/*
+	 *	Question: Jeff, ALi's patch deletes this:
+	 *
+	 *	pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp);
+	 *	pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL,
+	 *			       ((temp & 0xffffff00) | 0x00000010));
+	 *
+	 *	and replaces it with the following, which seems to duplicate the
+	 *	next couple of lines below it. I suspect this was an oversight,
+	 *	but you might want to check up on this?
+	 */
+	
+	pci_read_config_dword(agp_bridge.dev, ALI_APBASE, &temp);
+	agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
 
 	/* address to map to */
 	pci_read_config_dword(agp_bridge.dev, ALI_APBASE, &temp);
 	agp_bridge.gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
+
+#if 0
+	if (agp_bridge.type == ALI_M1541) {
+		u32 nlvm_addr = 0;
+
+		switch (current_size->size_value) {
+			case 0:  break;
+			case 1:  nlvm_addr = 0x100000;break;
+			case 2:  nlvm_addr = 0x200000;break;
+			case 3:  nlvm_addr = 0x400000;break;
+			case 4:  nlvm_addr = 0x800000;break;
+			case 6:  nlvm_addr = 0x1000000;break;
+			case 7:  nlvm_addr = 0x2000000;break;
+			case 8:  nlvm_addr = 0x4000000;break;
+			case 9:  nlvm_addr = 0x8000000;break;
+			case 10: nlvm_addr = 0x10000000;break;
+			default: break;
+		}
+		nlvm_addr--;
+		nlvm_addr&=0xfff00000;
+
+		nlvm_addr+= agp_bridge.gart_bus_addr;
+		nlvm_addr|=(agp_bridge.gart_bus_addr>>12);
+		printk(KERN_INFO PFX "nlvm top &base = %8x\n",nlvm_addr);
+	}
+#endif
+
+	pci_read_config_dword(agp_bridge.dev, ALI_TLBCTRL, &temp);
+	temp &= 0xffffff7f;		//enable TLB
+	pci_write_config_dword(agp_bridge.dev, ALI_TLBCTRL, temp);
+
 	return 0;
 }
 
@@ -2010,6 +2071,74 @@
 	return addr | agp_bridge.masks[0].mask;
 }
 
+static void ali_cache_flush(void)
+{
+	global_cache_flush();
+
+	if (agp_bridge.type == ALI_M1541) {
+		int i, page_count;
+		u32 temp;
+
+		page_count = 1 << A_SIZE_32(agp_bridge.current_size)->page_order;
+		for (i = 0; i < PAGE_SIZE * page_count; i += PAGE_SIZE) {
+			pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp);
+			pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL,
+					(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+					  (agp_bridge.gatt_bus_addr + i)) |
+					    ALI_CACHE_FLUSH_EN));
+		}
+	}
+}
+
+static unsigned long ali_alloc_page(void)
+{
+	void *pt;
+	u32 temp;
+
+	pt = (void *) __get_free_page(GFP_KERNEL);
+	if (pt == NULL)
+		return 0;
+
+	atomic_inc(&virt_to_page(pt)->count);
+	set_bit(PG_locked, &virt_to_page(pt)->flags);
+	atomic_inc(&agp_bridge.current_memory_agp);
+
+	global_cache_flush();
+
+	if (agp_bridge.type == ALI_M1541) {
+		pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp);
+		pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL,
+				(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+				  virt_to_phys((void *)pt)) |
+				    ALI_CACHE_FLUSH_EN ));
+	}
+	return (unsigned long) pt;
+}
+
+static void ali_destroy_page(unsigned long page)
+{
+	u32 temp;
+	void *pt = (void *) page;
+
+	if (pt == NULL)
+		return;
+
+	global_cache_flush();
+
+	if (agp_bridge.type == ALI_M1541) {
+		pci_read_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL, &temp);
+		pci_write_config_dword(agp_bridge.dev, ALI_CACHE_FLUSH_CTRL,
+				(((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
+				  virt_to_phys((void *)pt)) |
+				    ALI_CACHE_FLUSH_EN));
+	}
+
+	atomic_dec(&virt_to_page(pt)->count);
+	clear_bit(PG_locked, &virt_to_page(pt)->flags);
+	wake_up(&virt_to_page(pt)->wait);
+	free_page((unsigned long) pt);
+	atomic_dec(&agp_bridge.current_memory_agp);
+}
 
 /* Setup function */
 static gatt_mask ali_generic_masks[] =
@@ -2043,13 +2172,15 @@
 	agp_bridge.tlb_flush = ali_tlbflush;
 	agp_bridge.mask_memory = ali_mask_memory;
 	agp_bridge.agp_enable = agp_generic_agp_enable;
-	agp_bridge.cache_flush = global_cache_flush;
+	agp_bridge.cache_flush = ali_cache_flush;
 	agp_bridge.create_gatt_table = agp_generic_create_gatt_table;
 	agp_bridge.free_gatt_table = agp_generic_free_gatt_table;
 	agp_bridge.insert_memory = agp_generic_insert_memory;
 	agp_bridge.remove_memory = agp_generic_remove_memory;
 	agp_bridge.alloc_by_type = agp_generic_alloc_by_type;
 	agp_bridge.free_by_type = agp_generic_free_by_type;
+	agp_bridge.agp_alloc_page = ali_alloc_page;
+	agp_bridge.agp_destroy_page = ali_destroy_page;
 
 	return 0;
 	
@@ -2078,6 +2209,42 @@
 		"Ali",
 		"M1541",
 		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1621_0,  
+		PCI_VENDOR_ID_AL,
+		ALI_M1621,
+		"Ali",
+		"M1621",
+		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1631_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1631,
+		"Ali",
+		"M1631",
+		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1632_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1632,
+		"Ali",
+		"M1632",
+		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1641_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1641,
+		"Ali",
+		"M1641",
+		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1647_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1647,
+		"Ali",
+		"M1647",
+		ali_generic_setup },
+	{ PCI_DEVICE_ID_AL_M1651_0,
+		PCI_VENDOR_ID_AL,
+		ALI_M1651,
+		"Ali",
+		"M1651",
+		ali_generic_setup },  
 	{ 0,
 		PCI_VENDOR_ID_AL,
 		ALI_GENERIC,
@@ -2270,6 +2437,35 @@
 	while ((i < ARRAY_SIZE (agp_bridge_info)) &&
 	       (agp_bridge_info[i].vendor_id == pdev->vendor)) {
 		if (pdev->device == agp_bridge_info[i].device_id) {
+#ifdef CONFIG_AGP_ALI
+			if (pdev->device == PCI_DEVICE_ID_AL_M1621_0) {
+				u8 hidden_1621_id;
+
+				pci_read_config_byte(pdev, 0xFB, &hidden_1621_id);
+				switch (hidden_1621_id) {
+				case 0x31:
+					agp_bridge_info[i].chipset_name="M1631";
+					break;
+				case 0x32:
+					agp_bridge_info[i].chipset_name="M1632";
+					break;
+				case 0x41:
+					agp_bridge_info[i].chipset_name="M1641";
+					break;
+				case 0x43:
+					break;
+				case 0x47:
+					agp_bridge_info[i].chipset_name="M1647";
+					break;
+				case 0x51:
+					agp_bridge_info[i].chipset_name="M1651";
+					break;
+				default:
+					break;
+				}
+			}
+#endif
+
 			printk (KERN_INFO PFX "Detected %s %s chipset\n",
 				agp_bridge_info[i].vendor_name,
 				agp_bridge_info[i].chipset_name);
@@ -2375,9 +2571,8 @@
 			if (i810_dev == NULL) {
 				printk(KERN_ERR PFX "agpgart: Detected an "
 				       "Intel i815, but could not find the"
-				       " secondary device.\n"
-				       "Assuming user has added an external AGP"
-				       " card\n");
+				       " secondary device. Assuming a "
+				       "non-integrated video card.\n");
 				break;
 			}
 			printk(KERN_INFO PFX "agpgart: Detected an Intel i815 "
@@ -2486,7 +2681,7 @@
 	}
 
 	if (agp_bridge.needs_scratch_page == TRUE) {
-		agp_bridge.scratch_page = agp_alloc_page();
+		agp_bridge.scratch_page = agp_bridge.agp_alloc_page();
 
 		if (agp_bridge.scratch_page == 0) {
 			printk(KERN_ERR PFX "unable to get memory for "
@@ -2539,7 +2734,7 @@
 err_out:
 	if (agp_bridge.needs_scratch_page == TRUE) {
 		agp_bridge.scratch_page &= ~(0x00000fff);
-		agp_destroy_page((unsigned long)
+		agp_bridge.agp_destroy_page((unsigned long)
 				 phys_to_virt(agp_bridge.scratch_page));
 	}
 	if (got_gatt)
@@ -2559,7 +2754,7 @@
 
 	if (agp_bridge.needs_scratch_page == TRUE) {
 		agp_bridge.scratch_page &= ~(0x00000fff);
-		agp_destroy_page((unsigned long)
+		agp_bridge.agp_destroy_page((unsigned long)
 				 phys_to_virt(agp_bridge.scratch_page));
 	}
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/char/agp/agpgart_fe.c linux/drivers/char/agp/agpgart_fe.c
--- v2.4.1/linux/drivers/char/agp/agpgart_fe.c	Wed Jul 12 21:58:42 2000
+++ linux/drivers/char/agp/agpgart_fe.c	Tue Feb 13 14:13:43 2001
@@ -33,7 +33,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -1105,7 +1105,7 @@
 	return 0;
 }
 
-void __exit agp_frontend_cleanup(void)
+static void __exit agp_frontend_cleanup(void)
 {
 	misc_deregister(&agp_miscdev);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/char/amiserial.c linux/drivers/char/amiserial.c
--- v2.4.1/linux/drivers/char/amiserial.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/char/amiserial.c	Fri Feb 16 16:02:35 2001
@@ -59,9 +59,6 @@
  * End of serial driver configuration section.
  */
 
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 
 #include <linux/types.h>
@@ -85,7 +82,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/applicom.c linux/drivers/char/applicom.c
--- v2.4.1/linux/drivers/char/applicom.c	Sun Dec  3 17:45:20 2000
+++ linux/drivers/char/applicom.c	Fri Feb  9 11:30:22 2001
@@ -22,7 +22,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/errno.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/busmouse.c linux/drivers/char/busmouse.c
--- v2.4.1/linux/drivers/char/busmouse.c	Wed Aug  9 14:11:11 2000
+++ linux/drivers/char/busmouse.c	Fri Feb  9 11:30:22 2001
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/cd1865.h linux/drivers/char/cd1865.h
--- v2.4.1/linux/drivers/char/cd1865.h	Thu Mar  5 11:55:06 1998
+++ linux/drivers/char/cd1865.h	Fri Feb 16 16:02:35 2001
@@ -56,7 +56,7 @@
 #define CD186x_EOIR      0x7f    /* End of Interrupt Register               */
 #define CD186x_MRAR      0x75    /* Modem Request Acknowlege register       */
 #define CD186x_TRAR      0x76    /* Transmit Request Acknowlege register    */
-#define CD186x_RRAR      0x77    /* Recieve Request Acknowlege register     */
+#define CD186x_RRAR      0x77    /* Receive Request Acknowlege register     */
 #define CD186x_SRCR      0x66    /* Service Request Configuration register  */
 
 /* Channel Registers */
diff -u --recursive --new-file v2.4.1/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.4.1/linux/drivers/char/console.c	Fri Nov 10 10:56:47 2000
+++ linux/drivers/char/console.c	Fri Feb  9 11:30:22 2001
@@ -79,7 +79,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/kd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/major.h>
 #include <linux/mm.h>
 #include <linux/console.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/consolemap.c linux/drivers/char/consolemap.c
--- v2.4.1/linux/drivers/char/consolemap.c	Tue Jul  6 19:16:55 1999
+++ linux/drivers/char/consolemap.c	Fri Feb  9 11:30:22 2001
@@ -14,8 +14,9 @@
 #include <linux/kd.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/tty.h>
 #include <asm/uaccess.h>
 #include <linux/consolemap.h>
 #include <linux/console_struct.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/drm/Makefile linux/drivers/char/drm/Makefile
--- v2.4.1/linux/drivers/char/drm/Makefile	Sat Feb  3 19:51:27 2001
+++ linux/drivers/char/drm/Makefile	Sun Feb  4 10:05:29 2001
@@ -10,7 +10,7 @@
 module-list     := gamma.o tdfx.o r128.o ffb.o mga.o i810.o
 export-objs     := $(patsubst %.o,%_drv.o,$(module-list))
 
-# libs-objs are included in every module so that radical changes to the
+# lib-objs are included in every module so that radical changes to the
 # architecture of the DRM support library can be made at a later time.
 #
 # The downside is that each module is larger, and a system that uses
diff -u --recursive --new-file v2.4.1/linux/drivers/char/dsp56k.c linux/drivers/char/dsp56k.c
--- v2.4.1/linux/drivers/char/dsp56k.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/dsp56k.c	Fri Feb  9 11:30:22 2001
@@ -25,7 +25,7 @@
 
 #include <linux/module.h>
 #include <linux/version.h>
-#include <linux/malloc.h>	/* for kmalloc() and kfree() */
+#include <linux/slab.h>	/* for kmalloc() and kfree() */
 #include <linux/sched.h>	/* for struct wait_queue etc */
 #include <linux/major.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/dtlk.c linux/drivers/char/dtlk.c
--- v2.4.1/linux/drivers/char/dtlk.c	Sun Dec 31 10:26:18 2000
+++ linux/drivers/char/dtlk.c	Fri Feb 16 16:02:35 2001
@@ -47,10 +47,6 @@
 
  */
 
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
-
 #include <linux/module.h>
 #include <linux/version.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/dz.c linux/drivers/char/dz.c
--- v2.4.1/linux/drivers/char/dz.c	Thu Oct 12 14:20:47 2000
+++ linux/drivers/char/dz.c	Fri Feb 16 16:02:35 2001
@@ -33,7 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h> 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/major.h>
 #include <linux/param.h>
@@ -230,7 +230,7 @@
 
     ch = UCHAR(status);                /* grab the char */
 
-#ifdef 0
+#if 0
     if (info->is_console) {
       if (ch == 0) return;            /* it's a break ... */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/epca.c linux/drivers/char/epca.c
--- v2.4.1/linux/drivers/char/epca.c	Sun Dec 31 10:26:17 2000
+++ linux/drivers/char/epca.c	Fri Feb 16 16:02:35 2001
@@ -2216,7 +2216,7 @@
 
 	/* -------------------------------------------------------------------
 		This routine is called upon every timer interrupt.  Even though
-		the Digi series cards are capable of generating interupts this 
+		the Digi series cards are capable of generating interrupts this 
 		method of non-looping polling is more efficient.  This routine
 		checks for card generated events (Such as receive data, are transmit
 		buffer empty) and acts on those events.
diff -u --recursive --new-file v2.4.1/linux/drivers/char/esp.c linux/drivers/char/esp.c
--- v2.4.1/linux/drivers/char/esp.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/esp.c	Fri Feb  9 11:30:22 2001
@@ -61,7 +61,7 @@
 #include <asm/bitops.h>
 
 #include <asm/dma.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 
 #include <linux/hayesesp.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ftape/lowlevel/fdc-isr.c linux/drivers/char/ftape/lowlevel/fdc-isr.c
--- v2.4.1/linux/drivers/char/ftape/lowlevel/fdc-isr.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/ftape/lowlevel/fdc-isr.c	Fri Feb 16 16:02:36 2001
@@ -81,7 +81,7 @@
 	case overrun_error:
 		TRACE(ft_t_noise, "overrun error");
 		break;
-	default:
+	default:;
 	}
 	TRACE_EXIT;
 }
@@ -184,7 +184,7 @@
 	case no_data_error:
 		ft_history.no_data_errors++;
 		break;
-	default:
+	default:;
 	}
 }
 
@@ -237,7 +237,7 @@
 
 	switch (cause) {
 	case no_error: 
-		TRACE(ft_t_flow,"%d Sector(s) transfered", buff->sector_count);
+		TRACE(ft_t_flow,"%d Sector(s) transferred", buff->sector_count);
 		break;
 	case no_data_error:
 		TRACE(ft_t_flow, "Sector %d not found",
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ftape/lowlevel/ftape-buffer.c linux/drivers/char/ftape/lowlevel/ftape-buffer.c
--- v2.4.1/linux/drivers/char/ftape/lowlevel/ftape-buffer.c	Tue Aug  8 09:11:04 2000
+++ linux/drivers/char/ftape/lowlevel/ftape-buffer.c	Fri Feb  9 11:30:22 2001
@@ -25,7 +25,7 @@
  */
 
 #include <asm/segment.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/wrapper.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ftape/zftape/zftape-buffers.c linux/drivers/char/ftape/zftape/zftape-buffers.c
--- v2.4.1/linux/drivers/char/ftape/zftape/zftape-buffers.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/ftape/zftape/zftape-buffers.c	Fri Feb  9 11:30:22 2001
@@ -26,7 +26,7 @@
 
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/segment.h>
 
 #include <linux/zftape.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ftape/zftape/zftape-init.c linux/drivers/char/ftape/zftape/zftape-init.c
--- v2.4.1/linux/drivers/char/ftape/zftape/zftape-init.c	Wed Jul 12 21:58:42 2000
+++ linux/drivers/char/ftape/zftape/zftape-init.c	Fri Feb  9 11:30:22 2001
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ftape/zftape/zftape-vtbl.c linux/drivers/char/ftape/zftape/zftape-vtbl.c
--- v2.4.1/linux/drivers/char/ftape/zftape/zftape-vtbl.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/ftape/zftape/zftape-vtbl.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
 
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/segment.h>
 
 #include <linux/zftape.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/i810_rng.c linux/drivers/char/i810_rng.c
--- v2.4.1/linux/drivers/char/i810_rng.c	Mon Oct 16 12:23:12 2000
+++ linux/drivers/char/i810_rng.c	Fri Feb 16 16:02:36 2001
@@ -4,7 +4,7 @@
 	Copyright 2000 Jeff Garzik <jgarzik@mandrakesoft.com>
 	Copyright 2000 Philipp Rumpf <prumpf@tux.org>
 
-	Driver Web site:  http://gtf.org/garzik/drivers/i810_rng/
+	Driver Web site:  http://sourceforge.net/projects/gkernel/
 
 
 
@@ -26,7 +26,7 @@
 	----------------------------------------------------------
 
 	This software may be used and distributed according to the terms
-        of the GNU Public License, incorporated herein by reference.
+        of the GNU General Public License, incorporated herein by reference.
 
 	----------------------------------------------------------
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ip2/i2hw.h linux/drivers/char/ip2/i2hw.h
--- v2.4.1/linux/drivers/char/ip2/i2hw.h	Mon Aug 23 10:23:23 1999
+++ linux/drivers/char/ip2/i2hw.h	Fri Feb 16 16:02:35 2001
@@ -143,7 +143,7 @@
 //
 #define FIFO_DATA 0
 
-// Another way of passing information between the the board and the host is
+// Another way of passing information between the board and the host is
 // through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of
 // data.  Writing data to the mailbox causes a status bit to be set, and
 // potentially interrupting the intended receiver. The sender has some way to
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ip2/i2lib.h linux/drivers/char/ip2/i2lib.h
--- v2.4.1/linux/drivers/char/ip2/i2lib.h	Wed Jul  5 11:00:22 2000
+++ linux/drivers/char/ip2/i2lib.h	Fri Feb 16 16:02:35 2001
@@ -150,7 +150,7 @@
 	// though these are in the channel structure, the channel is also written
 	// here, the easier to send it to the fifo when ready. HOWEVER, individual
 	// packets here are NOT padded to even length: the routines for writing
-	// blocks to the the fifo will pad to even byte counts.
+	// blocks to the fifo will pad to even byte counts.
 	//
 	UCHAR	Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4];
 	volatile
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ip2.c linux/drivers/char/ip2.c
--- v2.4.1/linux/drivers/char/ip2.c	Tue Apr 25 17:52:01 2000
+++ linux/drivers/char/ip2.c	Fri Feb 16 16:02:35 2001
@@ -29,12 +29,6 @@
 ip2_loadmain(int *, int  *, unsigned char *, int ); // ref into ip2main.c
 
 #ifdef MODULE
-#if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
-#	define MODVERSIONS
-#endif
-#ifdef MODVERSIONS
-#	include <linux/modversions.h>
-#endif
 
 static int io[IP2_MAX_BOARDS]= { 0,};
 static int irq[IP2_MAX_BOARDS] = { 0,}; 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/ip2main.c linux/drivers/char/ip2main.c
--- v2.4.1/linux/drivers/char/ip2main.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/ip2main.c	Fri Feb 16 16:02:35 2001
@@ -50,14 +50,6 @@
 /************/
 #include <linux/config.h>
 // Uncomment the following if you want it compiled with modversions
-#ifdef MODULE
-#	if defined(CONFIG_MODVERSIONS) && !defined(MODVERSIONS)
-#		define MODVERSIONS
-#	endif
-#	ifdef MODVERSIONS
-#		include <linux/modversions.h>
-#	endif
-#endif
 
 #include <linux/version.h>
 
@@ -75,7 +67,7 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/major.h>
 #include <linux/wait.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/istallion.c linux/drivers/char/istallion.c
--- v2.4.1/linux/drivers/char/istallion.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/istallion.c	Fri Feb  9 11:30:22 2001
@@ -28,8 +28,9 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/cdk.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/a3d.c linux/drivers/char/joystick/a3d.c
--- v2.4.1/linux/drivers/char/joystick/a3d.c	Thu Jun 22 06:59:58 2000
+++ linux/drivers/char/joystick/a3d.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/adi.c linux/drivers/char/joystick/adi.c
--- v2.4.1/linux/drivers/char/joystick/adi.c	Fri Nov 17 16:52:23 2000
+++ linux/drivers/char/joystick/adi.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/gameport.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/amijoy.c linux/drivers/char/joystick/amijoy.c
--- v2.4.1/linux/drivers/char/joystick/amijoy.c	Mon Aug 14 13:55:01 2000
+++ linux/drivers/char/joystick/amijoy.c	Fri Feb 16 16:02:35 2001
@@ -113,7 +113,7 @@
 	for (i = 0; i < 2; i++)
 		if (amijoy[i]) {
 			if (!request_mem_region(CUSTOM_PHYSADDR+10+i*2, 2,
-						amijoy [Denise]")) {
+						"amijoy [Denise]")) {
 				if (i == 1 && amijoy[0]) {
 					input_unregister_device(amijoy_dev);
 					release_mem_region(CUSTOM_PHYSADDR+10, 2);
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/analog.c linux/drivers/char/joystick/analog.c
--- v2.4.1/linux/drivers/char/joystick/analog.c	Tue Nov 14 13:16:33 2000
+++ linux/drivers/char/joystick/analog.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/bitops.h>
 #include <linux/init.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/cobra.c linux/drivers/char/joystick/cobra.c
--- v2.4.1/linux/drivers/char/joystick/cobra.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/cobra.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/gameport.c linux/drivers/char/joystick/gameport.c
--- v2.4.1/linux/drivers/char/joystick/gameport.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/joystick/gameport.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/isapnp.h>
 #include <linux/stddef.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/gf2k.c linux/drivers/char/joystick/gf2k.c
--- v2.4.1/linux/drivers/char/joystick/gf2k.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/gf2k.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/grip.c linux/drivers/char/joystick/grip.c
--- v2.4.1/linux/drivers/char/joystick/grip.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/grip.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/gameport.h>
 #include <linux/input.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/iforce.c linux/drivers/char/joystick/iforce.c
--- v2.4.1/linux/drivers/char/joystick/iforce.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/char/joystick/iforce.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/interact.c linux/drivers/char/joystick/interact.c
--- v2.4.1/linux/drivers/char/joystick/interact.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/interact.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/lightning.c linux/drivers/char/joystick/lightning.c
--- v2.4.1/linux/drivers/char/joystick/lightning.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/lightning.c	Fri Feb  9 11:30:23 2001
@@ -38,7 +38,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #define L4_PORT			0x201
 #define L4_SELECT_ANALOG	0xa4
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/magellan.c linux/drivers/char/joystick/magellan.c
--- v2.4.1/linux/drivers/char/joystick/magellan.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/magellan.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/serio.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/ns558.c linux/drivers/char/joystick/ns558.c
--- v2.4.1/linux/drivers/char/joystick/ns558.c	Fri Nov 17 16:52:23 2000
+++ linux/drivers/char/joystick/ns558.c	Fri Feb  9 11:30:23 2001
@@ -38,7 +38,7 @@
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/isapnp.h>
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/serport.c linux/drivers/char/joystick/serport.c
--- v2.4.1/linux/drivers/char/joystick/serport.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/serport.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 
 #include <asm/uaccess.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/serio.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/sidewinder.c linux/drivers/char/joystick/sidewinder.c
--- v2.4.1/linux/drivers/char/joystick/sidewinder.c	Fri Nov 17 16:52:23 2000
+++ linux/drivers/char/joystick/sidewinder.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/input.h>
 #include <linux/gameport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/spaceball.c linux/drivers/char/joystick/spaceball.c
--- v2.4.1/linux/drivers/char/joystick/spaceball.c	Mon Aug 14 13:55:01 2000
+++ linux/drivers/char/joystick/spaceball.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/spaceorb.c linux/drivers/char/joystick/spaceorb.c
--- v2.4.1/linux/drivers/char/joystick/spaceorb.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/spaceorb.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/tmdc.c linux/drivers/char/joystick/tmdc.c
--- v2.4.1/linux/drivers/char/joystick/tmdc.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/tmdc.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 
 #include <linux/delay.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/gameport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/joystick/warrior.c linux/drivers/char/joystick/warrior.c
--- v2.4.1/linux/drivers/char/joystick/warrior.c	Wed Jun 21 08:22:21 2000
+++ linux/drivers/char/joystick/warrior.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/serio.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/lp.c linux/drivers/char/lp.c
--- v2.4.1/linux/drivers/char/lp.c	Thu Oct 12 14:20:47 2000
+++ linux/drivers/char/lp.c	Fri Feb  9 11:30:22 2001
@@ -121,7 +121,7 @@
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
 #include <linux/poll.h>
@@ -222,6 +222,21 @@
 	return error;
 }
 
+static int lp_wait_ready(int minor)
+{
+	int error = 0;
+	do {
+		error = lp_check_status (minor);
+		if (error && (LP_F(minor) & LP_ABORT))
+			break;
+		if (signal_pending (current)) {
+			error = -EINTR;
+			break;
+		}
+	} while (error);
+	return error;
+}
+
 static ssize_t lp_write(struct file * file, const char * buf,
 		        size_t count, loff_t *ppos)
 {
@@ -259,7 +274,7 @@
 	parport_set_timeout (lp_table[minor].dev,
 			     lp_table[minor].timeout);
 
-	if ((retv = lp_check_status (minor)) == 0)
+	if ((retv = lp_wait_ready (minor)) == 0)
 	do {
 		/* Write the data. */
 		written = parport_write (port, kbuf, copy_size);
@@ -279,9 +294,9 @@
 
 		if (copy_size > 0) {
 			/* incomplete write -> check error ! */
-			int error = lp_check_status (minor);
+			int error = lp_wait_ready (minor);
 
-			if (LP_F(minor) & LP_ABORT) {
+			if (error) {
 				if (retv == 0)
 					retv = error;
 				break;
diff -u --recursive --new-file v2.4.1/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.4.1/linux/drivers/char/mem.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/char/mem.c	Fri Feb  9 11:30:22 2001
@@ -13,12 +13,13 @@
 #include <linux/miscdevice.h>
 #include <linux/tpqic02.h>
 #include <linux/ftape.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mman.h>
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/raw.h>
+#include <linux/tty.h>
 #include <linux/capability.h>
 
 #include <asm/uaccess.h>
@@ -28,9 +29,6 @@
 #ifdef CONFIG_I2C
 extern int i2c_init_all(void);
 #endif
-#ifdef CONFIG_ISDN
-int isdn_init(void);
-#endif
 #ifdef CONFIG_VIDEO_DEV
 extern int videodev_init(void);
 #endif
@@ -157,9 +155,6 @@
 		prot = (prot & _CACHEMASK040) | _PAGE_NOCACHE_S;
 #elif defined(__mips__)
 	prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
-#elif defined(__arm__) && defined(CONFIG_CPU_32)
-	/* Turn off caching for all I/O areas */
-	prot &= ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE);
 #endif
 
 	return __pgprot(prot);
@@ -643,9 +638,6 @@
 	misc_init();
 #if CONFIG_QIC02_TAPE
 	qic02_tape_init();
-#endif
-#if CONFIG_ISDN
-	isdn_init();
 #endif
 #ifdef CONFIG_FTAPE
 	ftape_init();
diff -u --recursive --new-file v2.4.1/linux/drivers/char/misc.c linux/drivers/char/misc.c
--- v2.4.1/linux/drivers/char/misc.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/char/misc.c	Fri Feb  9 11:30:22 2001
@@ -41,7 +41,7 @@
 #include <linux/miscdevice.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/n_hdlc.c linux/drivers/char/n_hdlc.c
--- v2.4.1/linux/drivers/char/n_hdlc.c	Tue Nov  7 10:36:57 2000
+++ linux/drivers/char/n_hdlc.c	Fri Feb  9 11:30:22 2001
@@ -96,7 +96,7 @@
 
 #include <linux/poll.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>	/* used in new tty drivers */
diff -u --recursive --new-file v2.4.1/linux/drivers/char/n_r3964.c linux/drivers/char/n_r3964.c
--- v2.4.1/linux/drivers/char/n_r3964.c	Mon Dec 11 12:57:28 2000
+++ linux/drivers/char/n_r3964.c	Fri Feb  9 11:30:22 2001
@@ -51,7 +51,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>   /* used in new tty drivers */
diff -u --recursive --new-file v2.4.1/linux/drivers/char/n_tty.c linux/drivers/char/n_tty.c
--- v2.4.1/linux/drivers/char/n_tty.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/char/n_tty.c	Fri Feb  9 11:30:22 2001
@@ -38,7 +38,7 @@
 #include <linux/kd.h>
 #include <linux/mm.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/nvram.c linux/drivers/char/nvram.c
--- v2.4.1/linux/drivers/char/nvram.c	Thu Jan  4 12:50:17 2001
+++ linux/drivers/char/nvram.c	Fri Feb  9 11:40:02 2001
@@ -94,7 +94,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/mc146818rtc.h>
@@ -481,7 +481,8 @@
 #ifdef CONFIG_PROC_FS
 
 static char *floppy_types[] = {
-	"none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M", "3.5'' 2.88M"
+	"none", "5.25'' 360k", "5.25'' 1.2M", "3.5'' 720k", "3.5'' 1.44M",
+	"3.5'' 2.88M", "3.5'' 2.88M"
 };
 
 static char *gfx_types[] = {
diff -u --recursive --new-file v2.4.1/linux/drivers/char/pc110pad.c linux/drivers/char/pc110pad.c
--- v2.4.1/linux/drivers/char/pc110pad.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/pc110pad.c	Sun Feb  4 10:05:29 2001
@@ -42,6 +42,7 @@
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
+#include <linux/init.h>
 
 #include <asm/signal.h>
 #include <asm/io.h>
@@ -54,14 +55,13 @@
 
 
 static struct pc110pad_params default_params = {
-	PC110PAD_PS2,	/* read mode */
-	50 MS,		/* bounce interval */
-	200 MS,		/* tap interval */
-	10,		/* IRQ */
-	0x15E0,		/* I/O port */
+	mode:			PC110PAD_PS2,
+	bounce_interval:	50 MS,
+	tap_interval:		200 MS,
+	irq:			10,
+	io:			0x15E0,
 };
 
-
 static struct pc110pad_params current_params;
 
 
@@ -134,7 +134,7 @@
 {
 	if(!recent_transition)
 	{
-		printk("pc110pad: tap_timeout but no recent transition!\n");
+		printk(KERN_ERR "pc110pad: tap_timeout but no recent transition!\n");
 	}
 	if( transition_count==2 || transition_count==4 || transition_count==6 )
 	{
@@ -783,73 +783,60 @@
 
 
 static struct miscdevice pc110_pad = {
-	PC110PAD_MINOR, "pc110 pad", &pad_fops
+	minor:		PC110PAD_MINOR,
+	name:		"pc110 pad",
+	fops:		&pad_fops,
 };
 
 
 /**
- *	pc110pad_init:
+ *	pc110pad_init_driver:
  *
  *	We configure the pad with the default parameters (that is PS/2 
  *	emulation mode. We then claim the needed I/O and interrupt resources.
  *	Finally as a matter of paranoia we turn the pad off until we are
  *	asked to open it by an application.
  */
- 
-int pc110pad_init(void)
+
+static const char banner[] __initdata = KERN_INFO "PC110 digitizer pad at 0x%X, irq %d.\n";
+
+static int __init pc110pad_init_driver(void)
 {
+	init_MUTEX(&reader_lock);
 	current_params = default_params;
 
-	if(request_irq(current_params.irq, pad_irq, 0, "pc110pad", 0))
-	{
-		printk("pc110pad: Unable to get IRQ.\n");
+	if (request_irq(current_params.irq, pad_irq, 0, "pc110pad", 0)) {
+		printk(KERN_ERR "pc110pad: Unable to get IRQ.\n");
 		return -EBUSY;
 	}
-	if(check_region(current_params.io, 4))
-	{
-		printk("pc110pad: I/O area in use.\n");
+	if (!request_region(current_params.io, 4, "pc110pad"))	{
+		printk(KERN_ERR "pc110pad: I/O area in use.\n");
 		free_irq(current_params.irq,0);
 		return -EBUSY;
 	}
-	request_region(current_params.io, 4, "pc110pad");
 	init_waitqueue_head(&queue);
-	printk("PC110 digitizer pad at 0x%X, irq %d.\n",
-		current_params.io,current_params.irq);
+	printk(banner, current_params.io, current_params.irq);
 	misc_register(&pc110_pad);
 	outb(0x30, current_params.io+2);	/* switch off digitiser */
-	
 	return 0;
 }
 
-#ifdef MODULE
-
-/**
- *	pc110pad_unload:
+/*
+ *	pc110pad_exit_driver:
  *
  *	Free the resources we acquired when the module was loaded. We also
  *	turn the pad off to be sure we don't leave it using power.
  */
- 
-static void pc110pad_unload(void)
+
+static void __exit pc110pad_exit_driver(void)
 {
 	outb(0x30, current_params.io+2);	/* switch off digitiser */
-	if(current_params.irq)
+	if (current_params.irq)
 		free_irq(current_params.irq, 0);
-	current_params.irq=0;
+	current_params.irq = 0;
 	release_region(current_params.io, 4);
 	misc_deregister(&pc110_pad);
 }
 
-
-
-int init_module(void)
-{
-	init_MUTEX(&reader_lock);
-	return pc110pad_init();
-}
-
-void cleanup_module(void)
-{
-	pc110pad_unload();
-}
-#endif
+module_init(pc110pad_init_driver);
+module_exit(pc110pad_exit_driver);
diff -u --recursive --new-file v2.4.1/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.4.1/linux/drivers/char/pc_keyb.c	Mon Oct 23 15:51:36 2000
+++ linux/drivers/char/pc_keyb.c	Fri Feb  9 11:30:22 2001
@@ -29,7 +29,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kbd_kern.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/pcmcia/serial_cb.c linux/drivers/char/pcmcia/serial_cb.c
--- v2.4.1/linux/drivers/char/pcmcia/serial_cb.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/char/pcmcia/serial_cb.c	Fri Feb 16 16:02:35 2001
@@ -7,7 +7,7 @@
     Copyright 1998, 1999 by Donald Becker and David Hinds
     
     This software may be used and distributed according to the terms
-    of the GNU Public License, incorporated herein by reference.
+    of the GNU General Public License, incorporated herein by reference.
     All other rights reserved.
     
     This driver is an activator for CardBus serial cards, as
@@ -24,7 +24,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/tty.h>
 #include <linux/serial.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/pcmcia/serial_cs.c linux/drivers/char/pcmcia/serial_cs.c
--- v2.4.1/linux/drivers/char/pcmcia/serial_cs.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/char/pcmcia/serial_cs.c	Fri Feb 16 16:02:35 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -36,7 +36,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- v2.4.1/linux/drivers/char/pcwd.c	Sun Oct  1 19:45:29 2000
+++ linux/drivers/char/pcwd.c	Fri Feb  9 11:30:22 2001
@@ -53,7 +53,7 @@
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/miscdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/pcxx.c linux/drivers/char/pcxx.c
--- v2.4.1/linux/drivers/char/pcxx.c	Mon Jan  1 10:34:54 2001
+++ linux/drivers/char/pcxx.c	Fri Feb 16 16:02:35 2001
@@ -5,7 +5,7 @@
  *
  *  Copyright (C) 1994,1995 Troy De Jongh
  *  This software may be used and distributed according to the terms 
- *  of the GNU Public License.
+ *  of the GNU General Public License.
  *
  *  This driver is for the DigiBoard PC/Xe and PC/Xi line of products.
  *
@@ -63,7 +63,7 @@
 #include <linux/delay.h>
 #include <linux/serial.h>
 #include <linux/tty_driver.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/version.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/q40_keyb.c linux/drivers/char/q40_keyb.c
--- v2.4.1/linux/drivers/char/q40_keyb.c	Mon Nov 27 17:57:34 2000
+++ linux/drivers/char/q40_keyb.c	Fri Feb  9 11:30:22 2001
@@ -21,7 +21,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/keyboard.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/qpmouse.c linux/drivers/char/qpmouse.c
--- v2.4.1/linux/drivers/char/qpmouse.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/qpmouse.c	Fri Feb  9 11:30:22 2001
@@ -31,7 +31,7 @@
 #include <linux/fcntl.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/miscdevice.h>
 #include <linux/random.h>
 #include <linux/poll.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/random.c linux/drivers/char/random.c
--- v2.4.1/linux/drivers/char/random.c	Sun Nov 12 21:55:50 2000
+++ linux/drivers/char/random.c	Fri Feb 16 16:02:36 2001
@@ -20,7 +20,7 @@
  *    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
+ * the GNU General 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.)
@@ -240,7 +240,7 @@
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/fcntl.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rio.h linux/drivers/char/rio/rio.h
--- v2.4.1/linux/drivers/char/rio/rio.h	Wed May 10 16:56:44 2000
+++ linux/drivers/char/rio/rio.h	Fri Feb 16 16:02:36 2001
@@ -224,7 +224,7 @@
 
 #define	RIO_IPL	5
 #define	RIO_PRI	(PZERO+10)
-#define RIO_CLOSE_PRI	PZERO-1	/* uninteruptible sleeps for close */
+#define RIO_CLOSE_PRI	PZERO-1	/* uninterruptible sleeps for close */
 
 typedef struct DbInf
 {
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rio_linux.c linux/drivers/char/rio/rio_linux.c
--- v2.4.1/linux/drivers/char/rio/rio_linux.c	Thu Nov 16 12:51:27 2000
+++ linux/drivers/char/rio/rio_linux.c	Fri Feb  9 11:30:23 2001
@@ -56,7 +56,7 @@
 #include <linux/tqueue.h>
 #include <linux/version.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/miscdevice.h>
 
 #include <linux/compatmac.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rioboot.c linux/drivers/char/rio/rioboot.c
--- v2.4.1/linux/drivers/char/rio/rioboot.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/rioboot.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/riocmd.c linux/drivers/char/rio/riocmd.c
--- v2.4.1/linux/drivers/char/rio/riocmd.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/riocmd.c	Fri Feb  9 11:30:23 2001
@@ -36,8 +36,9 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/string.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rioctrl.c linux/drivers/char/rio/rioctrl.c
--- v2.4.1/linux/drivers/char/rio/rioctrl.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/rioctrl.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rioinfo.h linux/drivers/char/rio/rioinfo.h
--- v2.4.1/linux/drivers/char/rio/rioinfo.h	Wed May 10 16:56:44 2000
+++ linux/drivers/char/rio/rioinfo.h	Fri Feb 16 16:02:36 2001
@@ -44,7 +44,7 @@
 	long	location;	/* RIO Card Base I/O address */
 	long	vector;		/* RIO Card IRQ vector */
 	int	bus;		/* ISA/EISA/MCA/PCI */
-	int	mode;		/* pointer to host mode - INTERUPT / POLLED */
+	int	mode;		/* pointer to host mode - INTERRUPT / POLLED */
 	struct old_sgttyb
 		* Sg;		/* pointer to default term characteristics */
 };
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rioinit.c linux/drivers/char/rio/rioinit.c
--- v2.4.1/linux/drivers/char/rio/rioinit.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/rioinit.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 #define __NO_VERSION__
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/riointr.c linux/drivers/char/rio/riointr.c
--- v2.4.1/linux/drivers/char/rio/riointr.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/riointr.c	Fri Feb  9 11:30:23 2001
@@ -36,8 +36,9 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/string.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rioparam.c linux/drivers/char/rio/rioparam.c
--- v2.4.1/linux/drivers/char/rio/rioparam.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/rioparam.c	Fri Feb  9 11:30:23 2001
@@ -36,8 +36,9 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/string.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/rioroute.c linux/drivers/char/rio/rioroute.c
--- v2.4.1/linux/drivers/char/rio/rioroute.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/rioroute.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/riotable.c linux/drivers/char/rio/riotable.c
--- v2.4.1/linux/drivers/char/rio/riotable.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/riotable.c	Fri Feb 16 16:02:36 2001
@@ -35,7 +35,7 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -696,7 +696,7 @@
 
 	    /*
 	    ** Now we have a host we need to allocate an ID
-	    ** if the the entry does not already have one.
+	    ** if the entry does not already have one.
 	    */
 	    if (MapP->ID == (ushort)-1)
 	    {
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rio/riotty.c linux/drivers/char/rio/riotty.c
--- v2.4.1/linux/drivers/char/rio/riotty.c	Fri Aug 11 14:51:33 2000
+++ linux/drivers/char/rio/riotty.c	Fri Feb  9 11:30:23 2001
@@ -38,8 +38,9 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
+#include <linux/tty.h>
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/string.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/rocket.c linux/drivers/char/rocket.c
--- v2.4.1/linux/drivers/char/rocket.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/rocket.c	Fri Feb 16 16:02:36 2001
@@ -51,7 +51,7 @@
 #define MODULE
 #endif
 
-#ifdef NEW_MODULES
+#if defined(NEW_MODULES) && defined(LOCAL_ROCKET_H)
 #ifdef MODVERSIONS
 #include <linux/modversions.h>
 #endif
@@ -66,7 +66,7 @@
 #include <linux/major.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c
--- v2.4.1/linux/drivers/char/sbc60xxwdt.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/sbc60xxwdt.c	Fri Feb  9 11:30:22 2001
@@ -63,7 +63,7 @@
 #include <linux/sched.h>
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/scan_keyb.c linux/drivers/char/scan_keyb.c
--- v2.4.1/linux/drivers/char/scan_keyb.c	Mon Dec 11 12:39:44 2000
+++ linux/drivers/char/scan_keyb.c	Fri Feb  9 11:30:22 2001
@@ -16,7 +16,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kbd_kern.h>
 
 struct scan_keyboard {
diff -u --recursive --new-file v2.4.1/linux/drivers/char/selection.c linux/drivers/char/selection.c
--- v2.4.1/linux/drivers/char/selection.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/selection.c	Fri Feb  9 11:30:22 2001
@@ -15,7 +15,7 @@
 #include <linux/tty.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/serial.c linux/drivers/char/serial.c
--- v2.4.1/linux/drivers/char/serial.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/serial.c	Fri Feb 16 16:02:36 2001
@@ -28,7 +28,7 @@
  *        Stanislav V. Voronyi <stas@uanet.kharkov.ua>
  *
  *  3/98: Change the IRQ detection, use of probe_irq_o*(),
- *	  supress TIOCSERGWILD and TIOCSERSWILD
+ *	  suppress TIOCSERGWILD and TIOCSERSWILD
  *	  Etienne Lorrain <etienne.lorrain@ibm.net>
  *
  *  4/98: Added changes to support the ARM architecture proposed by
@@ -54,6 +54,9 @@
  *  7/00: fix some returns on failure not using MOD_DEC_USE_COUNT.
  *	  Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  *
+ * 10/00: add in optional hardware flow control for serial console.
+ *	  Kanoj Sarcar <kanoj@sgi.com>
+ *
  * This module exports the following rs232 io functions:
  *
  *	int rs_init(void);
@@ -162,9 +165,6 @@
  * End of serial driver configuration section.
  */
 
-#ifdef MODVERSIONS
-#include <linux/modversions.h>
-#endif
 #include <linux/module.h>
 
 #include <linux/types.h>
@@ -5252,6 +5252,36 @@
 }
 
 /*
+ * This is for use by architectures that know their serial port
+ * attributes only at run time. Not to be invoked after rs_init().
+ */
+int __init early_serial_setup(struct serial_struct *req)
+{
+	int i = req->line;
+
+	if (i >= NR_IRQS)
+		return(-ENOENT);
+	rs_table[i].magic = 0;
+	rs_table[i].baud_base = req->baud_base;
+	rs_table[i].port = req->port;
+	if (HIGH_BITS_OFFSET)
+		rs_table[i].port += (unsigned long) req->port_high << 
+							HIGH_BITS_OFFSET;
+	rs_table[i].irq = req->irq;
+	rs_table[i].flags = req->flags;
+	rs_table[i].close_delay = req->close_delay;
+	rs_table[i].io_type = req->io_type;
+	rs_table[i].hub6 = req->hub6;
+	rs_table[i].iomem_base = req->iomem_base;
+	rs_table[i].iomem_reg_shift = req->iomem_reg_shift;
+	rs_table[i].type = req->type;
+	rs_table[i].xmit_fifo_size = req->xmit_fifo_size;
+	rs_table[i].custom_divisor = req->custom_divisor;
+	rs_table[i].closing_wait = req->closing_wait;
+	return(0);
+}
+
+/*
  * register_serial and unregister_serial allows for 16x50 serial ports to be
  * configured at run-time, to support PCMCIA modems.
  */
@@ -5461,6 +5491,10 @@
 		if (--tmout == 0)
 			break;
 	} while((status & BOTH_EMPTY) != BOTH_EMPTY);
+	if (info->flags & ASYNC_NO_FLOW)
+		return;
+	tmout = 1000000;
+	while (--tmout && ((serial_in(info, UART_MSR) & UART_MSR_CTS) == 0));
 }
 
 
@@ -5543,7 +5577,7 @@
 }
 
 /*
- *	Setup initial baud/bits/parity. We do two things here:
+ *	Setup initial baud/bits/parity/flow. We do two things here:
  *	- construct a cflag setting for the first rs_open()
  *	- initialize the serial port
  *	Return non-zero if we didn't find a serial port.
@@ -5556,6 +5590,7 @@
 	int	baud = 9600;
 	int	bits = 8;
 	int	parity = 'n';
+	int	doflow = 0;
 	int	cflag = CREAD | HUPCL | CLOCAL;
 	int	quot = 0;
 	char	*s;
@@ -5566,7 +5601,9 @@
 		while(*s >= '0' && *s <= '9')
 			s++;
 		if (*s) parity = *s++;
-		if (*s) bits   = *s - '0';
+		if (*s) bits   = *s++ - '0';
+		if ((*s) && (!strcmp(s, "rtscts")))
+			doflow = 1;
 	}
 
 	/*
@@ -5622,6 +5659,8 @@
 	 *	Divisor, bytesize and parity
 	 */
 	state = rs_table + co->index;
+	if (doflow == 0)
+		state->flags |= ASYNC_NO_FLOW;
 	info = &async_sercons;
 	info->magic = SERIAL_MAGIC;
 	info->state = state;
diff -u --recursive --new-file v2.4.1/linux/drivers/char/serial_21285.c linux/drivers/char/serial_21285.c
--- v2.4.1/linux/drivers/char/serial_21285.c	Thu Oct 12 14:20:47 2000
+++ linux/drivers/char/serial_21285.c	Fri Feb  9 11:30:22 2001
@@ -19,7 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/console.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/serial_amba.c linux/drivers/char/serial_amba.c
--- v2.4.1/linux/drivers/char/serial_amba.c	Thu Oct 12 14:20:47 2000
+++ linux/drivers/char/serial_amba.c	Fri Feb  9 11:30:22 2001
@@ -48,7 +48,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/circ_buf.h>
 #include <linux/serial.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/sh-sci.c linux/drivers/char/sh-sci.c
--- v2.4.1/linux/drivers/char/sh-sci.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/char/sh-sci.c	Fri Feb  9 11:30:22 2001
@@ -29,7 +29,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #ifdef CONFIG_SERIAL_CONSOLE
diff -u --recursive --new-file v2.4.1/linux/drivers/char/softdog.c linux/drivers/char/softdog.c
--- v2.4.1/linux/drivers/char/softdog.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/char/softdog.c	Tue Feb 13 14:13:43 2001
@@ -45,9 +45,7 @@
 
 static int soft_margin = TIMER_MARGIN;	/* in seconds */
 
-#ifdef MODULE
 MODULE_PARM(soft_margin,"i");
-#endif
 
 /*
  *	Our timer
@@ -129,14 +127,10 @@
 static int softdog_ioctl(struct inode *inode, struct file *file,
 	unsigned int cmd, unsigned long arg)
 {
-	static struct watchdog_info ident=
-	{
-		0,
-		0,
-		"Software Watchdog"
+	static struct watchdog_info ident = {
+		identity: "Software Watchdog",
 	};
-	switch(cmd)
-	{
+	switch (cmd) {
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
@@ -152,8 +146,7 @@
 	}
 }
 
-static struct file_operations softdog_fops=
-{
+static struct file_operations softdog_fops = {
 	owner:		THIS_MODULE,
 	write:		softdog_write,
 	ioctl:		softdog_ioctl,
@@ -161,13 +154,14 @@
 	release:	softdog_release,
 };
 
-static struct miscdevice softdog_miscdev=
-{
-	WATCHDOG_MINOR,
-	"watchdog",
-	&softdog_fops
+static struct miscdevice softdog_miscdev = {
+	minor:		WATCHDOG_MINOR,
+	name:		"watchdog",
+	fops:		&softdog_fops,
 };
 
+static const char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n";
+
 static int __init watchdog_init(void)
 {
 	int ret;
@@ -177,10 +171,10 @@
 	if (ret)
 		return ret;
 
-	printk("Software Watchdog Timer: 0.05, timer margin: %d sec\n", soft_margin);
+	printk(banner, soft_margin);
 
 	return 0;
-}	
+}
 
 static void __exit watchdog_exit(void)
 {
diff -u --recursive --new-file v2.4.1/linux/drivers/char/stallion.c linux/drivers/char/stallion.c
--- v2.4.1/linux/drivers/char/stallion.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/char/stallion.c	Fri Feb  9 11:30:22 2001
@@ -29,8 +29,9 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/version.h> /* for linux/stallion.h */
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/tty.h>
 #include <linux/tty_flip.h>
 #include <linux/serial.h>
 #include <linux/cd1400.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/synclink.c linux/drivers/char/synclink.c
--- v2.4.1/linux/drivers/char/synclink.c	Tue Nov  7 10:36:42 2000
+++ linux/drivers/char/synclink.c	Fri Feb  9 11:30:22 2001
@@ -78,7 +78,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/netdevice.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/sysrq.c linux/drivers/char/sysrq.c
--- v2.4.1/linux/drivers/char/sysrq.c	Sun Dec  3 17:48:19 2000
+++ linux/drivers/char/sysrq.c	Fri Feb  9 11:30:22 2001
@@ -13,6 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
+#include <linux/tty.h>
 #include <linux/mount.h>
 #include <linux/kdev_t.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/tpqic02.c linux/drivers/char/tpqic02.c
--- v2.4.1/linux/drivers/char/tpqic02.c	Wed Dec  6 11:46:39 2000
+++ linux/drivers/char/tpqic02.c	Fri Feb  9 11:30:22 2001
@@ -87,7 +87,7 @@
 #include <linux/ioport.h>
 #include <linux/tpqic02.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h> 
diff -u --recursive --new-file v2.4.1/linux/drivers/char/tty_io.c linux/drivers/char/tty_io.c
--- v2.4.1/linux/drivers/char/tty_io.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/char/tty_io.c	Tue Feb 13 13:15:04 2001
@@ -81,7 +81,7 @@
 #include <linux/kd.h>
 #include <linux/mm.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/proc_fs.h>
 #include <linux/init.h>
@@ -139,7 +139,6 @@
 int tty_ioctl(struct inode * inode, struct file * file,
 	      unsigned int cmd, unsigned long arg);
 static int tty_fasync(int fd, struct file * filp, int on);
-extern int sx_init (void);
 extern int vme_scc_init (void);
 extern long vme_scc_console_init(void);
 extern int serial167_init(void);
diff -u --recursive --new-file v2.4.1/linux/drivers/char/vme_scc.c linux/drivers/char/vme_scc.c
--- v2.4.1/linux/drivers/char/vme_scc.c	Mon Nov 27 17:11:26 2000
+++ linux/drivers/char/vme_scc.c	Fri Feb  9 11:30:22 2001
@@ -31,7 +31,7 @@
 #include <linux/delay.h>
 #include <linux/tqueue.h>
 #include <linux/version.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/miscdevice.h>
 #include <linux/console.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/vt.c linux/drivers/char/vt.c
--- v2.4.1/linux/drivers/char/vt.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/char/vt.c	Fri Feb  9 11:30:22 2001
@@ -19,7 +19,7 @@
 #include <linux/kd.h>
 #include <linux/vt.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/major.h>
 #include <linux/fs.h>
 #include <linux/console.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/wd501p.h linux/drivers/char/wd501p.h
--- v2.4.1/linux/drivers/char/wd501p.h	Mon Dec 11 12:59:17 2000
+++ linux/drivers/char/wd501p.h	Fri Feb 16 16:02:36 2001
@@ -11,7 +11,7 @@
  *
  *	http://www.cymru.net
  *
- *	This driver is provided under the GNU public license, incorporated
+ *	This driver is provided under the GNU General Public License, incorporated
  *	herein by reference. The driver is provided without warranty or 
  *	support.
  *
diff -u --recursive --new-file v2.4.1/linux/drivers/char/wdt.c linux/drivers/char/wdt.c
--- v2.4.1/linux/drivers/char/wdt.c	Sun Oct  1 19:45:29 2000
+++ linux/drivers/char/wdt.c	Fri Feb  9 11:30:22 2001
@@ -40,7 +40,7 @@
 #include <linux/miscdevice.h>
 #include <linux/watchdog.h>
 #include "wd501p.h"
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- v2.4.1/linux/drivers/char/wdt_pci.c	Sun Oct  1 19:45:29 2000
+++ linux/drivers/char/wdt_pci.c	Fri Feb  9 11:30:22 2001
@@ -43,7 +43,7 @@
 #include <linux/watchdog.h>
 #define WDT_IS_PCI
 #include "wd501p.h"
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/dio/dio.c linux/drivers/dio/dio.c
--- v2.4.1/linux/drivers/dio/dio.c	Thu Aug  5 14:34:02 1999
+++ linux/drivers/dio/dio.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/dio.h>
-#include <linux/malloc.h>                         /* kmalloc() */
+#include <linux/slab.h>                         /* kmalloc() */
 #include <linux/init.h>
 #include <asm/hwtest.h>                           /* hwreg_present() */
 #include <asm/io.h>                               /* readb() */
diff -u --recursive --new-file v2.4.1/linux/drivers/fc4/fc.c linux/drivers/fc4/fc.c
--- v2.4.1/linux/drivers/fc4/fc.c	Fri Feb 18 15:07:20 2000
+++ linux/drivers/fc4/fc.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/blk.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/fc4/soc.c linux/drivers/fc4/soc.c
--- v2.4.1/linux/drivers/fc4/soc.c	Thu Jan 27 08:58:15 2000
+++ linux/drivers/fc4/soc.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/fc4/socal.c linux/drivers/fc4/socal.c
--- v2.4.1/linux/drivers/fc4/socal.c	Thu Jan 27 08:58:15 2000
+++ linux/drivers/fc4/socal.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-algo-bit.c linux/drivers/i2c/i2c-algo-bit.c
--- v2.4.1/linux/drivers/i2c/i2c-algo-bit.c	Sun Oct  1 20:35:16 2000
+++ linux/drivers/i2c/i2c-algo-bit.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-algo-pcf.c linux/drivers/i2c/i2c-algo-pcf.c
--- v2.4.1/linux/drivers/i2c/i2c-algo-pcf.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/i2c/i2c-algo-pcf.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-core.c linux/drivers/i2c/i2c-core.c
--- v2.4.1/linux/drivers/i2c/i2c-core.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/i2c/i2c-core.c	Fri Feb  9 11:40:02 2001
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/config.h>
 
@@ -1277,31 +1277,14 @@
 }
 
 #ifndef MODULE
-#ifdef CONFIG_I2C_CHARDEV
 	extern int i2c_dev_init(void);
-#endif
-#ifdef CONFIG_I2C_ALGOBIT
 	extern int i2c_algo_bit_init(void);
-#endif
-#ifdef CONFIG_I2C_BITLP
 	extern int i2c_bitlp_init(void);
-#endif
-#ifdef CONFIG_I2C_BITELV
 	extern int i2c_bitelv_init(void);
-#endif
-#ifdef CONFIG_I2C_BITVELLE
 	extern int i2c_bitvelle_init(void);
-#endif
-#ifdef CONFIG_I2C_BITVIA
 	extern int i2c_bitvia_init(void);
-#endif
-
-#ifdef CONFIG_I2C_ALGOPCF
 	extern int i2c_algo_pcf_init(void);	
-#endif
-#ifdef CONFIG_I2C_PCFISA
 	extern int i2c_pcfisa_init(void);
-#endif
 
 /* This is needed for automatic patch generation: sensors code starts here */
 /* This is needed for automatic patch generation: sensors code ends here   */
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-dev.c linux/drivers/i2c/i2c-dev.c
--- v2.4.1/linux/drivers/i2c/i2c-dev.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/i2c/i2c-dev.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-elektor.c linux/drivers/i2c/i2c-elektor.c
--- v2.4.1/linux/drivers/i2c/i2c-elektor.c	Tue Jul 25 18:10:42 2000
+++ linux/drivers/i2c/i2c-elektor.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/init.h>
 #include <asm/irq.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-elv.c linux/drivers/i2c/i2c-elv.c
--- v2.4.1/linux/drivers/i2c/i2c-elv.c	Wed Feb  9 18:48:03 2000
+++ linux/drivers/i2c/i2c-elv.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/i2c/i2c-pcf8584.h linux/drivers/i2c/i2c-pcf8584.h
--- v2.4.1/linux/drivers/i2c/i2c-pcf8584.h	Fri Jan 28 19:36:23 2000
+++ linux/drivers/i2c/i2c-pcf8584.h	Fri Feb  9 11:40:02 2001
@@ -75,4 +75,4 @@
 #define I2C_PCF_INTREG	I2C_PCF_ES2
 #define I2C_PCF_CLKREG	I2C_PCF_ES1
 
-#endif I2C_PCF8584_H
+#endif /* I2C_PCF8584_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/i2o/i2o_block.c linux/drivers/i2o/i2o_block.c
--- v2.4.1/linux/drivers/i2o/i2o_block.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/i2o/i2o_block.c	Fri Feb  9 11:30:23 2001
@@ -51,7 +51,7 @@
 #include <linux/i2o.h>
 #include <linux/blkdev.h>
 #include <linux/blkpg.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/hdreg.h>
 
 #include <linux/notifier.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2o/i2o_config.c linux/drivers/i2o/i2o_config.c
--- v2.4.1/linux/drivers/i2o/i2o_config.c	Wed Jul 12 21:58:42 2000
+++ linux/drivers/i2o/i2o_config.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/i2o.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/miscdevice.h>
 #include <linux/mm.h>
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2o/i2o_core.c linux/drivers/i2o/i2o_core.c
--- v2.4.1/linux/drivers/i2o/i2o_core.c	Wed Nov  8 17:09:50 2000
+++ linux/drivers/i2o/i2o_core.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/i2o/i2o_lan.c linux/drivers/i2o/i2o_lan.c
--- v2.4.1/linux/drivers/i2o/i2o_lan.c	Mon Dec 11 12:39:44 2000
+++ linux/drivers/i2o/i2o_lan.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 
 #include <linux/skbuff.h>
 #include <linux/if_arp.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
 #include <linux/tqueue.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/i2o/i2o_pci.c linux/drivers/i2o/i2o_pci.c
--- v2.4.1/linux/drivers/i2o/i2o_pci.c	Mon Jun 19 13:30:56 2000
+++ linux/drivers/i2o/i2o_pci.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/i2o.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/io.h>
 
 #ifdef CONFIG_MTRR
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/Config.in linux/drivers/ide/Config.in
--- v2.4.1/linux/drivers/ide/Config.in	Fri Dec 29 14:07:22 2000
+++ linux/drivers/ide/Config.in	Thu Feb 15 17:22:08 2001
@@ -78,12 +78,16 @@
 	    bool '    Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105
 	 fi
       fi
-      if [ "$CONFIG_PMAC" = "y" -o "$CONFIG_ALL_PPC" = "y" ]; then
+      if [ "$CONFIG_ALL_PPC" = "y" ]; then
 	 bool '    Builtin PowerMac IDE support' CONFIG_BLK_DEV_IDE_PMAC
 	 dep_bool '      PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC $CONFIG_BLK_DEV_IDE_PMAC
-	 dep_bool '        Use DMA by default' CONFIG_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC
-	 define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PMAC
-	 define_bool CONFIG_BLK_DEV_IDEPCI $CONFIG_BLK_DEV_IDEDMA_PMAC
+	 dep_bool '        Use DMA by default' CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO $CONFIG_BLK_DEV_IDEDMA_PMAC
+	 if [ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" ]; then
+	   define_bool CONFIG_BLK_DEV_IDEDMA $CONFIG_BLK_DEV_IDEDMA_PMAC
+	 fi
+	 if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then
+	   define_bool CONFIG_BLK_DEV_IDEPCI $CONFIG_BLK_DEV_IDEDMA_PMAC
+	 fi
       fi
       if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
 	 dep_bool '    ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE $CONFIG_ARCH_ACORN
@@ -126,7 +130,7 @@
 fi
 
 if [ "$CONFIG_IDEDMA_PCI_AUTO" = "y" -o \
-     "$CONFIG_IDEDMA_PMAC_AUTO" = "y" -o \
+     "$CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO" = "y" -o \
      "$CONFIG_IDEDMA_ICS_AUTO" = "y" ]; then
    define_bool CONFIG_IDEDMA_AUTO y
 else
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/cmd640.c linux/drivers/ide/cmd640.c
--- v2.4.1/linux/drivers/ide/cmd640.c	Thu Apr 13 22:54:26 2000
+++ linux/drivers/ide/cmd640.c	Fri Feb 16 16:02:36 2001
@@ -67,7 +67,7 @@
  *
  *  Version 0.09	Try to be smarter about 2nd port enabling.
  *  Version 0.10	Be nice and don't reset 2nd port.
- *  Version 0.11	Try to handle more wierd situations.
+ *  Version 0.11	Try to handle more weird situations.
  *
  *  Version 0.12	Lots of bug fixes from Laszlo Peter
  *			irq unmasking disabled for reliability.
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/hd.c linux/drivers/ide/hd.c
--- v2.4.1/linux/drivers/ide/hd.c	Thu Jan  4 12:50:17 2001
+++ linux/drivers/ide/hd.c	Fri Feb 16 16:02:36 2001
@@ -22,6 +22,9 @@
  *  This is now a lightweight ST-506 driver. (Paul Gortmaker)
  *
  *  Modified 1995 Russell King for ARM processor.
+ *
+ *  Bugfix: max_sectors must be <= 255 or the wheels tend to come
+ *  off in a hurry once you queue things up - Paul G. 02/2001
  */
   
 /* Uncomment the following if you want verbose error reports. */
@@ -36,7 +39,7 @@
 #include <linux/kernel.h>
 #include <linux/hdreg.h>
 #include <linux/genhd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
 #include <linux/mc146818rtc.h> /* CMOS defines */
@@ -104,6 +107,7 @@
 static int hd_sizes[MAX_HD<<6];
 static int hd_blocksizes[MAX_HD<<6];
 static int hd_hardsectsizes[MAX_HD<<6];
+static int hd_maxsect[MAX_HD<<6];
 
 static struct timer_list device_timer;
 
@@ -730,9 +734,11 @@
 	for(drive=0; drive < (MAX_HD << 6); drive++) {
 		hd_blocksizes[drive] = 1024;
 		hd_hardsectsizes[drive] = 512;
+		hd_maxsect[drive]=255;
 	}
 	blksize_size[MAJOR_NR] = hd_blocksizes;
 	hardsect_size[MAJOR_NR] = hd_hardsectsizes;
+	max_sectors[MAJOR_NR] = hd_maxsect;
 
 #ifdef __i386__
 	if (!NR_HD) {
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/icside.c linux/drivers/ide/icside.c
--- v2.4.1/linux/drivers/ide/icside.c	Tue Nov  7 11:02:24 2000
+++ linux/drivers/ide/icside.c	Fri Feb  9 11:30:23 2001
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/hdreg.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-cd.c linux/drivers/ide/ide-cd.c
--- v2.4.1/linux/drivers/ide/ide-cd.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/ide/ide-cd.c	Fri Feb  9 11:30:23 2001
@@ -302,7 +302,7 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
@@ -1871,6 +1871,9 @@
 	/* Check to see if the existing data is still valid.
 	   If it is, just return. */
 	(void) cdrom_check_status(drive, sense);
+
+	if (CDROM_STATE_FLAGS(drive)->toc_valid)
+		return 0;
 
 	/* First read just the header, so we know how long the TOC is. */
 	stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr,
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-cs.c linux/drivers/ide/ide-cs.c
--- v2.4.1/linux/drivers/ide/ide-cs.c	Tue Jan  2 16:45:36 2001
+++ linux/drivers/ide/ide-cs.c	Fri Feb  9 11:40:02 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -36,7 +36,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
@@ -95,7 +95,7 @@
 static int ide_event(event_t event, int priority,
 		     event_callback_args_t *args);
 
-static dev_info_t dev_info = "ide_cs";
+static dev_info_t dev_info = "ide-cs";
 
 static dev_link_t *ide_attach(void);
 static void ide_detach(dev_link_t *);
@@ -387,6 +387,11 @@
 	ide_unregister(info->hd);
 	MOD_DEC_USE_COUNT;
     }
+
+    request_region(link->io.BasePort1, link->io.NumPorts1,"ide-cs");
+    if (link->io.NumPorts2)
+	request_region(link->io.BasePort2, link->io.NumPorts2,"ide-cs");
+    
     info->ndev = 0;
     link->dev = NULL;
     
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-disk.c linux/drivers/ide/ide-disk.c
--- v2.4.1/linux/drivers/ide/ide-disk.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/ide/ide-disk.c	Fri Feb  9 11:30:23 2001
@@ -44,7 +44,7 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
 
@@ -223,67 +223,53 @@
  * ide_multwrite() transfers a block of up to mcount sectors of data
  * to a drive as part of a disk multiple-sector write operation.
  *
- * Returns 0 if successful;  returns 1 if request had to be aborted due to corrupted buffer list.
+ * Returns 0 on success.
+ *
+ * Note that we may be called from two contexts - the do_rw_disk context
+ * and IRQ context. The IRQ can happen any time after we've output the
+ * full "mcount" number of sectors, so we must make sure we update the
+ * state _before_ we output the final part of the data!
  */
 int ide_multwrite (ide_drive_t *drive, unsigned int mcount)
 {
  	ide_hwgroup_t	*hwgroup= HWGROUP(drive);
-
-	/*
-	 *	This may look a bit odd, but remember wrq is a copy of the
-	 *	request not the original. The pointers are real however so the
-	 *	bh's are not copies. Remember that or bad stuff will happen
-	 *
-	 *	At the point we are called the drive has asked us for the
-	 *	data, and its our job to feed it, walking across bh boundaries
-	 *	if need be.
-	 */
-
  	struct request	*rq = &hwgroup->wrq;
-
+ 
   	do {
- 		unsigned long flags;
-  		unsigned int nsect = rq->current_nr_sectors;
+  		char *buffer;
+  		int nsect = rq->current_nr_sectors;
+ 
 		if (nsect > mcount)
 			nsect = mcount;
 		mcount -= nsect;
+		buffer = rq->buffer;
 
-		idedisk_output_data(drive, rq->buffer, nsect<<7);
-#ifdef DEBUG
-		printk("%s: multwrite: sector %ld, buffer=0x%08lx, count=%d, remaining=%ld\n",
-			drive->name, rq->sector, (unsigned long) rq->buffer,
-			nsect, rq->nr_sectors - nsect);
-#endif
-		spin_lock_irqsave(&io_request_lock, flags);	/* Is this really necessary? */
-#ifdef CONFIG_BLK_DEV_PDC4030
 		rq->sector += nsect;
-#endif
-		if (((long)(rq->nr_sectors -= nsect)) <= 0) {
-#ifdef DEBUG
-			printk("%s: multwrite: count=%d, current=%ld\n",
-				drive->name, nsect, rq->nr_sectors);
-#endif
-			spin_unlock_irqrestore(&io_request_lock, flags);
-			break;
-		}
-		if ((rq->current_nr_sectors -= nsect) == 0) {
-			if ((rq->bh = rq->bh->b_reqnext) != NULL) {
-				rq->current_nr_sectors = rq->bh->b_size>>9;
-				rq->buffer             = rq->bh->b_data;
+		rq->buffer += nsect << 9;
+		rq->nr_sectors -= nsect;
+		rq->current_nr_sectors -= nsect;
+
+		/* Do we move to the next bh after this? */
+		if (!rq->current_nr_sectors) {
+			struct buffer_head *bh = rq->bh->b_reqnext;
+
+			/* end early early we ran out of requests */
+			if (!bh) {
+				mcount = 0;
 			} else {
-				spin_unlock_irqrestore(&io_request_lock, flags);
-				printk("%s: buffer list corrupted (%ld, %ld, %d)\n",
-					drive->name, rq->current_nr_sectors,
-					rq->nr_sectors, nsect);
-				ide_end_request(0, hwgroup);
-				return 1;
+				rq->bh = bh;
+				rq->current_nr_sectors = bh->b_size >> 9;
+				rq->buffer             = bh->b_data;
 			}
-		} else {
-			/* Fix the pointer.. we ate data */
-			rq->buffer += nsect << 9;
 		}
-                spin_unlock_irqrestore(&io_request_lock, flags);
+
+		/*
+		 * Ok, we're all setup for the interrupt
+		 * re-entering us on the last transfer.
+		 */
+		idedisk_output_data(drive, buffer, nsect<<7);
 	} while (mcount);
+
         return 0;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-features.c linux/drivers/ide/ide-features.c
--- v2.4.1/linux/drivers/ide/ide-features.c	Mon Oct 16 12:21:40 2000
+++ linux/drivers/ide/ide-features.c	Fri Feb  9 11:40:02 2001
@@ -27,7 +27,7 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/blkpg.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/hdreg.h>
@@ -189,6 +189,10 @@
 	__cli();		/* local CPU only; some systems need this */
 	SELECT_MASK(HWIF(drive), drive, 0);
 	id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
+	if (!id) {
+		__restore_flags(flags);	/* local CPU only */
+		return 0;
+	}
 	ide_input_data(drive, id, SECTOR_WORDS);
 	(void) GET_STAT();	/* clear drive IRQ */
 	ide__sti();		/* local CPU only */
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-floppy.c linux/drivers/ide/ide-floppy.c
--- v2.4.1/linux/drivers/ide/ide-floppy.c	Sun Dec 31 10:26:17 2000
+++ linux/drivers/ide/ide-floppy.c	Fri Feb  9 11:30:23 2001
@@ -45,7 +45,7 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/cdrom.h>
 #include <linux/ide.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-pmac.c linux/drivers/ide/ide-pmac.c
--- v2.4.1/linux/drivers/ide/ide-pmac.c	Tue Jun 20 07:52:36 2000
+++ linux/drivers/ide/ide-pmac.c	Thu Feb 15 17:22:08 2001
@@ -159,10 +159,7 @@
 		/* Probably a PCI interface... */
 		for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; ++i)
 			hw->io_ports[i] = data_port + i - IDE_DATA_OFFSET;
-		/* XXX is this right? */
-		hw->io_ports[IDE_CONTROL_OFFSET] = 0;
-		if (irq != 0)
-			*irq = 0;
+		hw->io_ports[IDE_CONTROL_OFFSET] = ctrl_port;
 		return;
 	}
 
@@ -175,12 +172,12 @@
 
 	ide_hwifs[ix].tuneproc = pmac_ide_tuneproc;
 	ide_hwifs[ix].selectproc = pmac_ide_selectproc;
+	ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
 	if (pmac_ide[ix].dma_regs && pmac_ide[ix].dma_table) {
 		ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
-#ifdef CONFIG_PMAC_IDEDMA_AUTO
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
 		ide_hwifs[ix].autodma = 1;
 #endif
-//		ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
 	}
 }
 
@@ -219,6 +216,61 @@
 #define SYSCLK_TICKS(t)		(((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
 #define SYSCLK_TICKS_UDMA(t)	(((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
 
+static __inline__ int
+wait_for_ready(ide_drive_t *drive)
+{
+	/* Timeout bumped for some powerbooks */
+	int timeout = 2000;
+	byte stat;
+
+	while(--timeout) {
+		stat = GET_STAT();
+		if(!(stat & BUSY_STAT)) {
+			if (drive->ready_stat == 0)
+				break;
+			else if((stat & drive->ready_stat) || (stat & ERR_STAT))
+				break;
+		}
+		mdelay(1);
+	}
+	if((stat & ERR_STAT) || timeout <= 0) {
+		if (stat & ERR_STAT) {
+			printk("ide_pmace: wait_for_ready, error status: %x\n", stat);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static int
+pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
+{
+	unsigned long flags;
+	int result = 1;
+
+	save_flags(flags);
+	cli();
+	udelay(1);
+	SELECT_DRIVE(HWIF(drive), drive);
+	SELECT_MASK(HWIF(drive), drive, 0);
+	udelay(1);
+	if(wait_for_ready(drive)) {
+		printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
+		goto out;
+	}
+	OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG);
+	OUT_BYTE(command, IDE_NSECTOR_REG);
+	OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG);
+	udelay(1);
+	result = wait_for_ready(drive);
+	if (result)
+		printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
+out:
+	restore_flags(flags);
+	
+	return result;
+}
+
 /* Calculate PIO timings */
 static void
 pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
@@ -266,12 +318,149 @@
 		pmac_ide_selectproc(drive);
 }
 
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+static int
+set_timings_udma(int intf, u32 *timings, byte speed)
+{
+	int cycleTime, accessTime;
+	int rdyToPauseTicks, cycleTicks;
+
+	if (pmac_ide[intf].kind != controller_kl_ata4)
+		return 1;
+		
+	cycleTime = udma_timings[speed & 0xf].cycleTime;
+	accessTime = udma_timings[speed & 0xf].accessTime;
+
+	rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+	cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
+
+	*timings = ((*timings) & 0xe00fffff) |
+			((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+
+	return 0;
+}
+
+static int
+set_timings_mdma(int intf, u32 *timings, byte speed)
+{
+	int cycleTime, accessTime;
+	int accessTicks, recTicks;
+
+	/* Calculate accesstime and cycle time */
+	cycleTime = mdma_timings[speed & 0xf].cycleTime;
+	accessTime = mdma_timings[speed & 0xf].accessTime;
+	if ((pmac_ide[intf].kind == controller_ohare) && (cycleTime < 150))
+		cycleTime = 150;
+
+	/* For ata-4 controller */
+	if (pmac_ide[intf].kind == controller_kl_ata4) {
+		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
+		*timings = ((*timings) & 0xffe003ff) |
+			(accessTicks | (recTicks << 5)) << 10;
+	} else {
+		int halfTick = 0;
+		int origAccessTime = accessTime;
+		int origCycleTime = cycleTime;
+		
+		accessTicks = SYSCLK_TICKS(accessTime);
+		if (accessTicks < 1)
+			accessTicks = 1;
+		accessTime = accessTicks * IDE_SYSCLK_NS;
+		recTicks = SYSCLK_TICKS(cycleTime - accessTime) - 1;
+		if (recTicks < 1)
+			recTicks = 1;
+		cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
+
+		/* KeyLargo ata-3 don't support the half-tick stuff */
+		if ((pmac_ide[intf].kind != controller_kl_ata3) &&
+			(accessTicks > 1) &&
+			((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
+			((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
+            			halfTick    = 1;
+				accessTicks--;
+		}
+		*timings = ((*timings) & 0x7FF) |
+			(accessTicks | (recTicks << 5) | (halfTick << 10)) << 11;
+	}
+	return 0;
+}
+#endif /* #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC */
+
+/* You may notice we don't use this function on normal operation,
+ * our, normal mdma function is supposed to be more precise
+ */
+static int
+pmac_ide_tune_chipset (ide_drive_t *drive, byte speed)
+{
+	int intf		= pmac_ide_find(drive);
+	int unit		= (drive->select.all & 0x10) ? 1:0;
+	int ret			= 0;
+	u32 *timings;
+
+	if (intf < 0)
+		return 1;
+		
+	timings = &pmac_ide[intf].timings[unit];
+	
+	switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
+		case XFER_UDMA_4:
+		case XFER_UDMA_3:
+		case XFER_UDMA_2:
+		case XFER_UDMA_1:
+		case XFER_UDMA_0:
+			ret = set_timings_udma(intf, timings, speed);
+			break;
+		case XFER_MW_DMA_2:
+		case XFER_MW_DMA_1:
+		case XFER_MW_DMA_0:
+		case XFER_SW_DMA_2:
+		case XFER_SW_DMA_1:
+		case XFER_SW_DMA_0:
+			ret = set_timings_mdma(intf, timings, speed);
+			break;
+#endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */
+		case XFER_PIO_4:
+		case XFER_PIO_3:
+		case XFER_PIO_2:
+		case XFER_PIO_1:
+		case XFER_PIO_0:
+			pmac_ide_tuneproc(drive, speed & 0x07);
+			break;
+		default:
+			ret = 1;
+	}
+	if (ret)
+		return ret;
+
+	ret = pmac_ide_do_setfeature(drive, speed);
+	if (ret)
+		return ret;
+		
+	pmac_ide_selectproc(drive);	
+	drive->current_speed = speed;
+
+	return 0;
+}
+
 ide_ioreg_t
 pmac_ide_get_base(int index)
 {
 	return pmac_ide[index].regbase;
 }
 
+int
+pmac_ide_get_irq(ide_ioreg_t base)
+{
+	int ix;
+
+	for (ix = 0; ix < MAX_HWIFS; ++ix)
+		if (base == pmac_ide[ix].regbase)
+			return pmac_ide[ix].irq;
+	return 0;
+}
+
 static int ide_majors[] = { 3, 22, 33, 34, 56, 57 };
 
 kdev_t __init
@@ -337,6 +526,7 @@
 	for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
 		struct device_node *tp;
 		int *bidp;
+		int in_bay = 0;
 
 		/*
 		 * If this node is not under a mac-io or dbdma node,
@@ -395,7 +585,10 @@
 
 		if (np->parent && np->parent->name
 		    && strcasecmp(np->parent->name, "media-bay") == 0) {
+#ifdef CONFIG_PMAC_PBOOK
 			media_bay_set_ide_infos(np->parent,base,irq,i);
+#endif /* CONFIG_PMAC_PBOOK */
+			in_bay = 1;
 		} else if (pmac_ide[i].kind == controller_ohare) {
 			/* The code below is having trouble on some ohare machines
 			 * (timing related ?). Until I can put my hand on one of these
@@ -436,8 +629,11 @@
 		pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);
 		memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
 		hwif->chipset = ide_pmac;
-		hwif->noprobe = (!hwif->io_ports[IDE_DATA_OFFSET]) ||
-			(check_media_bay_by_base(base, MB_CD) == -EINVAL);
+		hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET] || in_bay;
+#ifdef CONFIG_PMAC_PBOOK
+		if (in_bay && check_media_bay_by_base(base, MB_CD) == 0)
+			hwif->noprobe = 0;
+#endif /* CONFIG_PMAC_PBOOK */
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 		if (np->n_addrs >= 2) {
@@ -479,7 +675,7 @@
 	}
 
 	ide_hwifs[ix].dmaproc = &pmac_ide_dmaproc;
-#ifdef CONFIG_PMAC_IDEDMA_AUTO
+#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO
 	ide_hwifs[ix].autodma = 1;
 #endif
 }
@@ -565,99 +761,34 @@
 }
 
 
-/* This is fun.  -DaveM */
-#define IDE_SETXFER		0x03
-#define IDE_SETFEATURE		0xef
-#define IDE_DMA2_ENABLE		0x22
-#define IDE_DMA1_ENABLE		0x21
-#define IDE_DMA0_ENABLE		0x20
-#define IDE_UDMA4_ENABLE	0x44
-#define IDE_UDMA3_ENABLE	0x43
-#define IDE_UDMA2_ENABLE	0x42
-#define IDE_UDMA1_ENABLE	0x41
-#define IDE_UDMA0_ENABLE	0x40
-
 static __inline__ unsigned char
 dma_bits_to_command(unsigned char bits)
 {
 	if(bits & 0x04)
-		return IDE_DMA2_ENABLE;
+		return XFER_MW_DMA_2;
 	if(bits & 0x02)
-		return IDE_DMA1_ENABLE;
-	return IDE_DMA0_ENABLE;
+		return XFER_MW_DMA_1;
+	if(bits & 0x01)
+		return XFER_MW_DMA_0;
+	return 0;
 }
 
 static __inline__ unsigned char
 udma_bits_to_command(unsigned char bits)
 {
 	if(bits & 0x10)
-		return IDE_UDMA4_ENABLE;
+		return XFER_UDMA_4;
 	if(bits & 0x08)
-		return IDE_UDMA3_ENABLE;
+		return XFER_UDMA_3;
 	if(bits & 0x04)
-		return IDE_UDMA2_ENABLE;
+		return XFER_UDMA_2;
 	if(bits & 0x02)
-		return IDE_UDMA1_ENABLE;
+		return XFER_UDMA_1;
 	if(bits & 0x01)
-		return IDE_UDMA0_ENABLE;
-	return 0;
-}
-
-static __inline__ int
-wait_for_ready(ide_drive_t *drive)
-{
-	/* Timeout bumped for some powerbooks */
-	int timeout = 2000;
-	byte stat;
-
-	while(--timeout) {
-		stat = GET_STAT();
-		if(!(stat & BUSY_STAT)) {
-			if (drive->ready_stat == 0)
-				break;
-			else if((stat & drive->ready_stat) || (stat & ERR_STAT))
-				break;
-		}
-		mdelay(1);
-	}
-	if((stat & ERR_STAT) || timeout <= 0) {
-		if (stat & ERR_STAT) {
-			printk("ide_pmace: wait_for_ready, error status: %x\n", stat);
-		}
-		return 1;
-	}
+		return XFER_UDMA_0;
 	return 0;
 }
 
-static int
-pmac_ide_do_setfeature(ide_drive_t *drive, byte command)
-{
-	unsigned long flags;
-	byte old_select;
-	int result = 1;
-
-	save_flags(flags);
-	cli();
-	old_select = IN_BYTE(IDE_SELECT_REG);
-	OUT_BYTE(drive->select.all, IDE_SELECT_REG);
-	udelay(10);
-	OUT_BYTE(IDE_SETXFER, IDE_FEATURE_REG);
-	OUT_BYTE(command, IDE_NSECTOR_REG);
-	if(wait_for_ready(drive)) {
-		printk("pmac_ide_do_setfeature disk not ready before SET_FEATURE!\n");
-		goto out;
-	}
-	OUT_BYTE(IDE_SETFEATURE, IDE_COMMAND_REG);
-	result = wait_for_ready(drive);
-	if (result)
-		printk("pmac_ide_do_setfeature disk not ready after SET_FEATURE !\n");
-out:
-	OUT_BYTE(old_select, IDE_SELECT_REG);
-	restore_flags(flags);
-	
-	return result;
-}
-
 /* Calculate MultiWord DMA timings */
 static int
 pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
@@ -668,10 +799,12 @@
 	int cycleTime, accessTime;
 	int accessTicks, recTicks;
 	struct hd_driveid *id = drive->id;
-	
+	int ret;
+
 	/* Set feature on drive */
     	printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
-	if (pmac_ide_do_setfeature(drive, feature)) {
+	ret = pmac_ide_do_setfeature(drive, feature);
+	if (ret) {
 	    	printk("%s: Failed !\n", drive->name);
 	    	return 0;
 	}
@@ -693,7 +826,7 @@
 	if ((pmac_ide[idx].kind == controller_ohare) && (cycleTime < 150))
 		cycleTime = 150;
 
-	/* For ata-4 controller, we don't know the calculation */
+	/* For ata-4 controller */
 	if (pmac_ide[idx].kind == controller_kl_ata4) {
 		accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
 		recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
@@ -741,10 +874,12 @@
 	int cycleTime, accessTime;
 	int rdyToPauseTicks, cycleTicks;
 	u32 *timings;
-	
+	int ret;
+
 	/* Set feature on drive */
     	printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
-	if (pmac_ide_do_setfeature(drive, feature)) {
+	ret = pmac_ide_do_setfeature(drive, feature);
+	if (ret) {
 		printk("%s: Failed !\n", drive->name);
 		return 0;
 	}
@@ -772,10 +907,11 @@
 }
 
 static int
-pmac_ide_dma_onoff(ide_drive_t *drive, int enable)
+pmac_ide_check_dma(ide_drive_t *drive)
 {
 	int ata4, udma, idx;
 	struct hd_driveid *id = drive->id;
+	int enable = 1;
 
 	drive->using_dma = 0;
 	
@@ -807,15 +943,14 @@
 		 * machines
 		 */
 		OUT_BYTE(0, IDE_CONTROL_REG);
-		if (drive->select.all == IN_BYTE(IDE_SELECT_REG))
-			pmac_ide_selectproc(drive);
+		/* Apply settings to controller */
+		pmac_ide_selectproc(drive);
 	}
 	return 0;
 }
 
 int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	ide_hwif_t *hwif = HWIF(drive);
 	int ix, dstat;
 	volatile struct dbdma_regs *dma;
 
@@ -828,15 +963,14 @@
 	dma = pmac_ide[ix].dma_regs;
 
 	switch (func) {
-	case ide_dma_on:
 	case ide_dma_off:
+		printk("%s: DMA disabled\n", drive->name);
 	case ide_dma_off_quietly:
-		pmac_ide_dma_onoff(drive, (func == ide_dma_on));
+		drive->using_dma = 0;
 		break;
+	case ide_dma_on:
 	case ide_dma_check:
-		printk("IDE-DMA check !\n");
-		if (hwif->autodma)
-			pmac_ide_dma_onoff(drive, 1);
+		pmac_ide_check_dma(drive);
 		break;
 	case ide_dma_read:
 	case ide_dma_write:
@@ -1026,7 +1160,7 @@
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
 			if (hwif->drives[0].present && hwif->drives[0].using_dma)
-				pmac_ide_dma_onoff(&hwif->drives[0], 1);
+				pmac_ide_check_dma(&hwif->drives[0]);
 #endif				
 		}
 		break;
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-probe.c linux/drivers/ide/ide-probe.c
--- v2.4.1/linux/drivers/ide/ide-probe.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/ide/ide-probe.c	Fri Feb  9 11:30:23 2001
@@ -40,7 +40,7 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/ide.h>
 #include <linux/spinlock.h>
@@ -652,6 +652,8 @@
 		hwgroup = match->hwgroup;
 	} else {
 		hwgroup = kmalloc(sizeof(ide_hwgroup_t), GFP_KERNEL);
+		if (!hwgroup)
+			return 1;
 		memset(hwgroup, 0, sizeof(ide_hwgroup_t));
 		hwgroup->hwif     = hwif->next = hwif;
 		hwgroup->rq       = NULL;
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-tape.c linux/drivers/ide/ide-tape.c
--- v2.4.1/linux/drivers/ide/ide-tape.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/ide/ide-tape.c	Fri Feb  9 11:30:23 2001
@@ -399,7 +399,7 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/errno.h>
 #include <linux/genhd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/ide.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide-timing.h linux/drivers/ide/ide-timing.h
--- v2.4.1/linux/drivers/ide/ide-timing.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/ide/ide-timing.h	Sat Feb  3 11:27:43 2001
@@ -0,0 +1,279 @@
+#ifndef _IDE_TIMING_H
+#define _IDE_TIMING_H
+
+/*
+ * $Id: ide-timing.h,v 1.5 2001/01/15 21:48:56 vojtech Exp $
+ *
+ *  Copyright (c) 1999-2000 Vojtech Pavlik
+ *
+ *  Sponsored by SuSE
+ */
+
+/*
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Should you need to contact me, the author, you can do so either by
+ * e-mail - mail your message to <vojtech@suse.cz>, or by paper mail:
+ * Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
+ */
+
+#include <linux/hdreg.h>
+
+#ifndef XFER_PIO_5
+#define XFER_PIO_5		0x0d
+#define XFER_UDMA_SLOW		0x4f
+#endif
+
+struct ide_timing {
+	short mode;
+	short setup;	/* t1 */
+	short act8b;	/* t2 for 8-bit io */
+	short rec8b;	/* t2i for 8-bit io */
+	short cyc8b;	/* t0 for 8-bit io */
+	short active;	/* t2 or tD */
+	short recover;	/* t2i or tK */
+	short cycle;	/* t0 */
+	short udma;	/* t2CYCTYP/2 */
+};
+
+/*
+ * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds).
+ * These were taken from ATA/ATAPI-6 standard, rev 0a, except
+ * for PIO 5, which is a nonstandard extension.
+ */
+
+static struct ide_timing ide_timing[] = {
+
+	{ XFER_UDMA_5,     0,   0,   0,   0,   0,   0,   0,  20 },
+	{ XFER_UDMA_4,     0,   0,   0,   0,   0,   0,   0,  30 },
+	{ XFER_UDMA_3,     0,   0,   0,   0,   0,   0,   0,  45 },
+
+	{ XFER_UDMA_2,     0,   0,   0,   0,   0,   0,   0,  60 },
+	{ XFER_UDMA_1,     0,   0,   0,   0,   0,   0,   0,  80 },
+	{ XFER_UDMA_0,     0,   0,   0,   0,   0,   0,   0, 120 },
+
+	{ XFER_UDMA_SLOW,  0,   0,   0,   0,   0,   0,   0, 150 },
+                                          
+	{ XFER_MW_DMA_2,  25,   0,   0,   0,  70,  25, 120,   0 },
+	{ XFER_MW_DMA_1,  45,   0,   0,   0,  80,  50, 150,   0 },
+	{ XFER_MW_DMA_0,  60,   0,   0,   0, 215, 215, 480,   0 },
+                                          
+	{ XFER_SW_DMA_2,  60,   0,   0,   0, 120, 120, 240,   0 },
+	{ XFER_SW_DMA_1,  90,   0,   0,   0, 240, 240, 480,   0 },
+	{ XFER_SW_DMA_0, 120,   0,   0,   0, 480, 480, 960,   0 },
+
+	{ XFER_PIO_5,     20,  50,  30, 100,  50,  30, 100,   0 },
+	{ XFER_PIO_4,     25,  70,  25, 120,  70,  25, 120,   0 },
+	{ XFER_PIO_3,     30,  80,  70, 180,  80,  70, 180,   0 },
+
+	{ XFER_PIO_2,     30, 290,  40, 330, 100,  90, 240,   0 },
+	{ XFER_PIO_1,     50, 290,  93, 383, 125, 100, 383,   0 },
+	{ XFER_PIO_0,     70, 290, 240, 600, 165, 150, 600,   0 },
+
+	{ XFER_PIO_SLOW, 120, 290, 240, 960, 290, 240, 960,   0 },
+
+	{ -1 }
+};
+
+#define IDE_TIMING_SETUP	0x01
+#define IDE_TIMING_ACT8B	0x02
+#define IDE_TIMING_REC8B	0x04
+#define IDE_TIMING_CYC8B	0x08
+#define IDE_TIMING_8BIT		0x0e
+#define IDE_TIMING_ACTIVE	0x10
+#define IDE_TIMING_RECOVER	0x20
+#define IDE_TIMING_CYCLE	0x40
+#define IDE_TIMING_UDMA		0x80
+#define IDE_TIMING_ALL		0xff
+
+#define MIN(a,b)	((a)<(b)?(a):(b))
+#define MAX(a,b)	((a)>(b)?(a):(b))
+#define FIT(v,min,max)	MAX(MIN(v,max),min)
+#define ENOUGH(v,unit)	(((v)-1)/(unit)+1)
+#define EZ(v,unit)	((v)?ENOUGH(v,unit):0)
+
+#define XFER_MODE	0xf0
+#define XFER_UDMA_100	0x44
+#define XFER_UDMA_66	0x42
+#define XFER_UDMA	0x40
+#define XFER_MWDMA	0x20
+#define XFER_SWDMA	0x10
+#define XFER_EPIO	0x01
+#define XFER_PIO	0x00
+
+static short ide_find_best_mode(ide_drive_t *drive, int map)
+{
+	struct hd_driveid *id = drive->id;
+	short best = 0;
+
+	if (!id)
+		return XFER_PIO_SLOW;
+
+	if ((map & XFER_UDMA) && (id->field_valid & 4)) {	/* Want UDMA and UDMA bitmap valid */
+
+		if ((map & XFER_UDMA_100) == XFER_UDMA_100)
+			if ((best = (id->dma_ultra & 0x0020) ? XFER_UDMA_5 : 0)) return best;
+
+		if ((map & XFER_UDMA_66) == XFER_UDMA_66)
+			if ((best = (id->dma_ultra & 0x0010) ? XFER_UDMA_4 :
+                	    	    (id->dma_ultra & 0x0008) ? XFER_UDMA_3 : 0)) return best;
+
+                if ((best = (id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
+                	    (id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
+                	    (id->dma_ultra & 0x0001) ? XFER_UDMA_0 : 0)) return best;
+	}
+
+	if ((map & XFER_MWDMA) && (id->field_valid & 2)) {	/* Want MWDMA and drive has EIDE fields */
+
+		if ((best = (id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
+                	    (id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
+                	    (id->dma_mword & 0x0001) ? XFER_MW_DMA_0 : 0)) return best;
+	}
+
+	if (map & XFER_SWDMA) {					/* Want SWDMA */
+
+ 		if (id->field_valid & 2) {			/* EIDE SWDMA */
+
+			if ((best = (id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
+      				    (id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
+				    (id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0)) return best;
+		}
+
+		if (id->capability & 1) {			/* Pre-EIDE style SWDMA */
+
+			if ((best = (id->tDMA == 2) ? XFER_SW_DMA_2 :
+				    (id->tDMA == 1) ? XFER_SW_DMA_1 :
+				    (id->tDMA == 0) ? XFER_SW_DMA_0 : 0)) return best;
+		}
+	}
+
+
+	if ((map & XFER_EPIO) && (id->field_valid & 2)) {	/* EIDE PIO modes */
+
+		if ((best = (drive->id->eide_pio_modes & 4) ? XFER_PIO_5 :
+			    (drive->id->eide_pio_modes & 2) ? XFER_PIO_4 :
+			    (drive->id->eide_pio_modes & 1) ? XFER_PIO_3 : 0)) return best;
+	}
+	
+	return  (drive->id->tPIO == 2) ? XFER_PIO_2 :
+		(drive->id->tPIO == 1) ? XFER_PIO_1 :
+		(drive->id->tPIO == 0) ? XFER_PIO_0 : XFER_PIO_SLOW;
+}
+
+static void ide_timing_quantize(struct ide_timing *t, struct ide_timing *q, int T, int UT)
+{
+	q->setup   = EZ(t->setup,   T);
+	q->act8b   = EZ(t->act8b,   T);
+	q->rec8b   = EZ(t->rec8b,   T);
+	q->cyc8b   = EZ(t->cyc8b,   T);
+	q->active  = EZ(t->active,  T);
+	q->recover = EZ(t->recover, T);
+	q->cycle   = EZ(t->cycle,   T);
+	q->udma    = EZ(t->udma,   UT);
+}
+
+static void ide_timing_merge(struct ide_timing *a, struct ide_timing *b, struct ide_timing *m, unsigned int what)
+{
+	if (what & IDE_TIMING_SETUP  ) m->setup   = MAX(a->setup,   b->setup);
+	if (what & IDE_TIMING_ACT8B  ) m->act8b   = MAX(a->act8b,   b->act8b);
+	if (what & IDE_TIMING_REC8B  ) m->rec8b   = MAX(a->rec8b,   b->rec8b);
+	if (what & IDE_TIMING_CYC8B  ) m->cyc8b   = MAX(a->cyc8b,   b->cyc8b);
+	if (what & IDE_TIMING_ACTIVE ) m->active  = MAX(a->active,  b->active);
+	if (what & IDE_TIMING_RECOVER) m->recover = MAX(a->recover, b->recover);
+	if (what & IDE_TIMING_CYCLE  ) m->cycle   = MAX(a->cycle,   b->cycle);
+	if (what & IDE_TIMING_UDMA   ) m->udma    = MAX(a->udma,    b->udma);
+}
+
+static struct ide_timing* ide_timing_find_mode(short speed)
+{
+	struct ide_timing *t;
+
+	for (t = ide_timing; t->mode != speed; t++)
+		if (t->mode < 0)
+			return NULL;
+	return t; 
+}
+
+static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing *t, int T, int UT)
+{
+	struct hd_driveid *id = drive->id;
+	struct ide_timing *s, p;
+
+/*
+ * Find the mode.
+ */
+
+	if (!(s = ide_timing_find_mode(speed)))
+		return -EINVAL;
+
+/*
+ * If the drive is an EIDE drive, it can tell us it needs extended
+ * PIO/MWDMA cycle timing.
+ */
+
+	if (id && id->field_valid & 2) {	/* EIDE drive */
+
+		memset(&p, 0, sizeof(p));
+
+		switch (speed & XFER_MODE) {
+
+			case XFER_PIO:
+				if (speed <= XFER_PIO_2) p.cycle = p.cyc8b = id->eide_pio;
+						    else p.cycle = p.cyc8b = id->eide_pio_iordy;
+				break;
+
+			case XFER_MWDMA:
+				p.cycle = id->eide_dma_min;
+				break;
+		}
+
+		ide_timing_merge(&p, t, t, IDE_TIMING_CYCLE | IDE_TIMING_CYC8B);
+	}
+
+/*
+ * Convert the timing to bus clock counts.
+ */
+
+	ide_timing_quantize(s, t, T, UT);
+
+/*
+ * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
+ * and some other commands. We have to ensure that the DMA cycle timing is
+ * slower/equal than the fastest PIO timing.
+ */
+
+	if ((speed & XFER_MODE) != XFER_PIO) {
+		ide_timing_compute(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO), &p, T, UT);
+		ide_timing_merge(&p, t, t, IDE_TIMING_ALL);
+	}
+
+/*
+ * Lenghten active & recovery time so that cycle time is correct.
+ */
+
+	if (t->act8b + t->rec8b < t->cyc8b) {
+		t->act8b += (t->cyc8b - (t->act8b + t->rec8b)) / 2;
+		t->rec8b = t->cyc8b - t->act8b;
+	}
+
+	if (t->active + t->recover < t->cycle) {
+		t->active += (t->cycle - (t->active + t->recover)) / 2;
+		t->recover = t->cycle - t->active;
+	}
+
+	return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/ide.c linux/drivers/ide/ide.c
--- v2.4.1/linux/drivers/ide/ide.c	Wed Dec  6 12:06:19 2000
+++ linux/drivers/ide/ide.c	Fri Feb  9 11:30:23 2001
@@ -140,7 +140,7 @@
 #include <linux/errno.h>
 #include <linux/genhd.h>
 #include <linux/blkpg.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #ifndef MODULE
 #include <linux/init.h>
 #endif /* MODULE */
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/osb4.c linux/drivers/ide/osb4.c
--- v2.4.1/linux/drivers/ide/osb4.c	Tue Jan  2 16:58:45 2001
+++ linux/drivers/ide/osb4.c	Sun Feb  4 10:05:30 2001
@@ -46,8 +46,8 @@
 #include <linux/hdreg.h>
 #include <linux/ide.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
-#include <asm/delay.h>
 #include <asm/io.h>
 
 #include "ide_modes.h"
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/pdc202xx.c linux/drivers/ide/pdc202xx.c
--- v2.4.1/linux/drivers/ide/pdc202xx.c	Fri Jul 28 12:08:30 2000
+++ linux/drivers/ide/pdc202xx.c	Fri Feb 16 16:02:36 2001
@@ -747,14 +747,11 @@
 {
 	unsigned long high_16	= pci_resource_start(HWIF(drive)->pci_dev, 4);
 	byte udma_speed_flag	= inb(high_16 + 0x001f);
-	int i			= 0;
 
 	OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
-	ide_delay_50ms();
-	ide_delay_50ms();
+	mdelay(100);
 	OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
-	for (i = 0; i < 40; i++)
-		ide_delay_50ms();
+	mdelay(2000);		/* 2 seconds ?! */
 }
 
 unsigned int __init pci_init_pdc202xx (struct pci_dev *dev, const char *name)
@@ -767,7 +764,6 @@
 	if ((dev->device == PCI_DEVICE_ID_PROMISE_20262) ||
 	    (dev->device == PCI_DEVICE_ID_PROMISE_20265) ||
 	    (dev->device == PCI_DEVICE_ID_PROMISE_20267)) {
-		int i = 0;
 		/*
 		 * software reset -  this is required because the bios
 		 * will set UDMA timing on if the hdd supports it. The
@@ -779,11 +775,9 @@
 		 */
 
 		OUT_BYTE(udma_speed_flag | 0x10, high_16 + 0x001f);
-		ide_delay_50ms();
-		ide_delay_50ms();
+		mdelay(100);
 		OUT_BYTE(udma_speed_flag & ~0x10, high_16 + 0x001f);
-		for (i=0; i<40; i++)
-			ide_delay_50ms();
+		mdelay(2000);	/* 2 seconds ?! */
 	}
 
 	if (dev->resource[PCI_ROM_RESOURCE].start) {
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/rapide.c linux/drivers/ide/rapide.c
--- v2.4.1/linux/drivers/ide/rapide.c	Thu Apr 13 22:54:26 2000
+++ linux/drivers/ide/rapide.c	Fri Feb  9 11:30:23 2001
@@ -9,7 +9,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/ide.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/ide/via82cxxx.c linux/drivers/ide/via82cxxx.c
--- v2.4.1/linux/drivers/ide/via82cxxx.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/ide/via82cxxx.c	Sat Feb  3 11:27:43 2001
@@ -1,7 +1,7 @@
 /*
- * $Id: via82cxxx.c,v 2.1e 2000/10/03 10:01:00 vojtech Exp $
+ * $Id: via82cxxx.c,v 3.20 2001/01/27 10:13:60 vojtech Exp $
  *
- *  Copyright (c) 2000 Vojtech Pavlik
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
  *
  *  Based on the work of:
  *	Michel Aubry
@@ -12,23 +12,34 @@
  */
 
 /*
- * VIA vt82c586 IDE driver for Linux. Supports
+ * VIA IDE driver for Linux. Supports
  *
- *   vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b, vt82c686a, vt8231
+ *   vt82c586, vt82c586a, vt82c586b, vt82c596a, vt82c596b,
+ *   vt82c686, vt82c686a, vt82c686b, vt8231, vt8233
  *
  * southbridges, which can be found in
  *
- *  VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4
- *  VIA Apollo Pro, Pro Plus, Pro 133, Pro 133A, ProMedia 601, ProSavage 605
- *  VIA Apollo KX133, KT133
- *  AMD-640, AMD-750 IronGate
- *
- * chipsets. Supports PIO 0-5, MWDMA 0-2, SWDMA 0-2 and
- * UDMA 0-5 (includes UDMA33, 66 and 100) modes. UDMA100 isn't possible
- * on any of the supported chipsets yet.
- *
- * UDMA66 and higher modes are autodetected only in case the BIOS has enabled them.
- * To force UDMA66, use 'ide0=ata66' or 'ide1=ata66' on the kernel command line.
+ *  VIA Apollo VP, VPX, VPX/97, VP2, VP2/97, VP3, MVP3, MVP4, P6, Pro,
+ *  Pro Plus, Pro 133, Pro 133A, ProMedia PM601, ProSavage PM133, PLE133,
+ *  Pro 266, KX133, KT133, ProSavage KM133, KT133A, KT266
+ *  PC-Chips VXPro, VXPro+, TXPro-III, TXPro-AGP, ViaGra, BXToo, BXTel
+ *  AMD 640, 640 AGP, 750 IronGate
+ *  ETEQ 6618, 6628, 6638
+ *  Micron Samurai
+ *
+ * chipsets. Supports
+ *
+ *   PIO 0-5, MWDMA 0-2, SWDMA 0-2 and UDMA 0-5
+ *
+ * (this includes UDMA33, 66 and 100) modes. UDMA66 and higher modes are
+ * autodetected only in case the BIOS has detected a 80 wire cable. To ignore
+ * the BIOS data, use 'ide0=ata66' or 'ide1=ata66' on the kernel command line.
+ *
+ * For correct operation it's needed to tell the driver the speed of the PCI
+ * bus. The default, and most common value is 33 MHz. Most likely, your system
+ * is using this value and you don't need to use any command line options. If
+ * you run your PCI bus speed at 25, 30, 37, 40 or 42 MHz, use the 'idebus=xx'
+ * option of the IDE driver. Note that this has nothing to do with UDMA66.
  */
 
 /*
@@ -52,23 +63,16 @@
  */
 
 #include <linux/config.h>
-#include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/mm.h>
 #include <linux/ioport.h>
-#include <linux/interrupt.h>
 #include <linux/blkdev.h>
-#include <linux/hdreg.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/ide.h>
 #include <asm/io.h>
 
-#include "ide_modes.h"
+#include "ide-timing.h"
 
-#define VIA_BM_BASE		0x20
 #define VIA_IDE_ENABLE		0x40
 #define VIA_IDE_CONFIG		0x41
 #define VIA_FIFO_CONFIG		0x43
@@ -76,90 +80,49 @@
 #define VIA_MISC_2		0x45
 #define VIA_MISC_3		0x46
 #define VIA_DRIVE_TIMING	0x48
+#define VIA_8BIT_TIMING		0x4e
 #define VIA_ADDRESS_SETUP	0x4c
 #define VIA_UDMA_TIMING		0x50
-#define VIA_PRI_SECTOR_SIZE	0x60
-#define VIA_SEC_SECTOR_SIZE	0x68
+
+#define VIA_UDMA		0x07
+#define VIA_UDMA_NONE		0x00
+#define VIA_UDMA_33		0x01
+#define VIA_UDMA_66		0x02
+#define VIA_UDMA_100		0x03
+#define VIA_BAD_PREQ		0x10
+#define VIA_BAD_CLK66		0x20
+#define VIA_SET_FIFO		0x40
+#define VIA_SET_THRESH		0x80
 
 /*
  * VIA SouthBridge chips.
  */
 
-static const struct {
+static struct via_isa_bridge {
 	char *name;
 	unsigned short id;
-	unsigned char speed;
+	unsigned char rev_min;
+	unsigned char rev_max;
+	unsigned char flags;
 } via_isa_bridges[] = {
-	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     XFER_UDMA_4 },
-	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   XFER_UDMA_4 },
-	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   XFER_UDMA_4 },
-	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   XFER_UDMA_2 },
-	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
-	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
-	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, XFER_MW_DMA_2 },
-	{ "Unknown SouthBridge",	0,	    XFER_UDMA_2 },
+	{ "vt8233",	PCI_DEVICE_ID_VIA_8233_0,   0x00, 0x2f, VIA_UDMA_100 },
+	{ "vt8231",	PCI_DEVICE_ID_VIA_8231,     0x00, 0x2f, VIA_UDMA_66 },
+	{ "vt82c686b",	PCI_DEVICE_ID_VIA_82C686,   0x40, 0x4f, VIA_UDMA_100 },
+	{ "vt82c686a",	PCI_DEVICE_ID_VIA_82C686,   0x10, 0x2f, VIA_UDMA_66 },
+	{ "vt82c686",	PCI_DEVICE_ID_VIA_82C686,   0x00, 0x0f, VIA_UDMA_66 },
+	{ "vt82c596b",	PCI_DEVICE_ID_VIA_82C596,   0x10, 0x2f, VIA_UDMA_66 },
+	{ "vt82c596a",	PCI_DEVICE_ID_VIA_82C596,   0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ },
+	{ "vt82c586b",	PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO },
+	{ "vt82c586a",	PCI_DEVICE_ID_VIA_82C586_0, 0x20, 0x2f, VIA_UDMA_33 | VIA_SET_FIFO },
+	{ "vt82c586",	PCI_DEVICE_ID_VIA_82C586_0, 0x00, 0x0f, VIA_UDMA_NONE | VIA_SET_FIFO },
+	{ NULL }
 };
 
-static unsigned char via_config;
+static struct via_isa_bridge *via_config;
 static unsigned char via_enabled;
-static unsigned int via_ata66;
-
-/*
- * PIO 0-5, MWDMA 0-2 and UDMA 0-5 timings (in nanoseconds).
- * These were taken from ATA/ATAPI-6 standard, rev 0a, except
- * for PIO 5, which is a nonstandard extension.
- *
- * Dilemma: 8-bit (register) PIO accesses need more relaxed timing.
- * Hopefully the chipset is taking care of that. If it doesn't
- * do so, define VIA_USE_8_BIT_TIMING to see if it helps.
- */
-
-#ifndef XFER_PIO_5
-#define XFER_PIO_5		0x0d
-#endif
-
-static const struct {
-	int mode;
-	char *name;
-	short setup;	/* t1 */
-	short active;	/* t2  or tD */
-	short recover;	/* t2i or tK */
-	short cycle;	/* t0 */
-	short udma;	/* t2CYCTYP/2 */
-} via_timing[] = {
-	{ XFER_UDMA_5,    "UDMA5", 25,  70,  25, 120,  20 },
-	{ XFER_UDMA_4,    "UDMA4", 25,  70,  25, 120,  30 },
-	{ XFER_UDMA_3,    "UDMA3", 25,  70,  25, 120,  45 },
-
-	{ XFER_UDMA_2,    "UDMA2", 25,  70,  25, 120,  60 },
-	{ XFER_UDMA_1,    "UDMA1", 25,  70,  25, 120,  80 },
-	{ XFER_UDMA_0,    "UDMA0", 25,  70,  25, 120, 120 },
-
-	{ XFER_MW_DMA_2,  "MDMA2", 25,  70,  25, 120,   0 },
-	{ XFER_MW_DMA_1,  "MDMA1", 45,  80,  50, 150,   0 },
-	{ XFER_MW_DMA_0,  "MDMA0", 60, 215, 215, 480,   0 },
-
-	{ XFER_SW_DMA_2,  "SDMA2", 60, 120, 120, 240,   0 },
-	{ XFER_SW_DMA_1,  "SDMA1", 90, 240, 240, 480,   0 },
-	{ XFER_SW_DMA_0,  "SDMA0",120, 480, 480, 960,   0 },
-
-	{ XFER_PIO_5,     "PIO5",  20,  50,  30, 100,   0 },
-	{ XFER_PIO_4,     "PIO4",  25,  70,  25, 120,   0 },
-	{ XFER_PIO_3,     "PIO3",  30,  80,  70, 180,   0 },
-
-#ifdef VIA_USE_8_BIT_TIMING
-	{ XFER_PIO_2,     "PIO2",  30, 290,  60, 330,   0 },
-	{ XFER_PIO_1,     "PIO1",  50, 290, 100, 383,   0 },
-	{ XFER_PIO_0,     "PIO0",  70, 290, 300, 600,   0 },
-#else
-	{ XFER_PIO_2,     "PIO2",  30, 100,  90, 240,   0 },
-	{ XFER_PIO_1,     "PIO1",  50, 125, 100, 383,   0 },
-	{ XFER_PIO_0,     "PIO0",  70, 165, 150, 600,   0 },
-#endif
-
-	{ XFER_PIO_SLOW,  "SLOW", 120, 290, 240, 960,   0 },
-	{ 0 }
-};
+static unsigned int via_80w;
+static unsigned int via_clock;
 
 /*
  * VIA /proc entry.
@@ -170,11 +133,10 @@
 #include <linux/stat.h>
 #include <linux/proc_fs.h>
 
-int via_proc = 0;
+int via_proc, via_base;
 static struct pci_dev *bmide_dev, *isa_dev;
 extern int (*via_display_info)(char *, char **, off_t, int); /* ide-proc.c */
 
-static char *via_fifo[] = { " 1 ", "3/4", "1/2", "1/4" };
 static char *via_control3[] = { "No limit", "64", "128", "192" };
 
 #define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg)
@@ -183,89 +145,89 @@
 
 static int via_get_info(char *buffer, char **addr, off_t offset, int count)
 {
-	short pci_clock, speed[4], cycle[4], setup[4], active[4], recover[4], umul[4], uen[4], udma[4];
+	short speed[4], cycle[4], setup[4], active[4],
+		recover[4], uen[4], udma[4], active8b[4], recover8b[4];
 	struct pci_dev *dev = bmide_dev;
-	unsigned int v, u, i, base;
-	unsigned short c, size0, size1;
-	unsigned char t, c0, c1;
+	unsigned int v, u, i;
+	unsigned short c, w;
+	unsigned char t, x;
 	char *p = buffer;
 
 	via_print("----------VIA BusMastering IDE Configuration----------------");
 
-	via_print("Driver Version:                     2.1e");
+	via_print("Driver Version:                     3.20");
+	via_print("South Bridge:                       VIA %s", via_config->name);
 
 	pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);
-	via_print("South Bridge:                       VIA %s rev %#x", via_isa_bridges[via_config].name, t);
-
-	pci_read_config_word(dev, PCI_COMMAND, &c);
-	via_print("Command register:                   %#x", c);
-
-	pci_read_config_byte(dev, PCI_LATENCY_TIMER, &t);
-	via_print("Latency timer:                      %d", t);
+	pci_read_config_byte(dev, PCI_REVISION_ID, &x);
+	via_print("Revision:                           ISA %#x IDE %#x", t, x);
 
-	pci_clock = system_bus_clock();
-	via_print("PCI clock:                          %dMHz", pci_clock);
+	via_print("BM-DMA base:                        %#x", via_base);
+	via_print("PCI clock:                          %dMHz", via_clock);
 
 	pci_read_config_byte(dev, VIA_MISC_1, &t);
-	via_print("Master Read  Cycle IRDY:            %dws", (t & 64) >>6 );
-	via_print("Master Write Cycle IRDY:            %dws", (t & 32) >> 5 );
-	via_print("FIFO Output Data 1/2 Clock Advance: %s", (t & 16) ? "on" : "off" );
-	via_print("BM IDE Status Register Read Retry:  %s", (t & 8) ? "on" : "off" );
+	via_print("Master Read  Cycle IRDY:            %dws", (t & 64) >> 6);
+	via_print("Master Write Cycle IRDY:            %dws", (t & 32) >> 5);
+	via_print("BM IDE Status Register Read Retry:  %s", (t & 8) ? "yes" : "no");
 
 	pci_read_config_byte(dev, VIA_MISC_3, &t);
-	via_print("Max DRDY Pulse Width:               %s%s", via_control3[(t & 0x03)], (t & 0x03) ? "PCI clocks" : "");
+	via_print("Max DRDY Pulse Width:               %s%s", via_control3[(t & 0x03)], (t & 0x03) ? " PCI clocks" : "");
 
 	via_print("-----------------------Primary IDE-------Secondary IDE------");
-	via_print("Read DMA FIFO flush:   %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x40) ? "on" : "off" );
-	via_print("End Sect. FIFO flush:  %10s%20s", (t & 0x20) ? "on" : "off", (t & 0x10) ? "on" : "off" );
+	via_print("Read DMA FIFO flush:   %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x40) ? "yes" : "no");
+	via_print("End Sector FIFO flush: %10s%20s", (t & 0x20) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
 
 	pci_read_config_byte(dev, VIA_IDE_CONFIG, &t);
-	via_print("Prefetch Buffer:       %10s%20s", (t & 0x80) ? "on" : "off", (t & 0x20) ? "on" : "off" );
-	via_print("Post Write Buffer:     %10s%20s", (t & 0x40) ? "on" : "off", (t & 0x10) ? "on" : "off" );
+	via_print("Prefetch Buffer:       %10s%20s", (t & 0x80) ? "yes" : "no", (t & 0x20) ? "yes" : "no");
+	via_print("Post Write Buffer:     %10s%20s", (t & 0x40) ? "yes" : "no", (t & 0x10) ? "yes" : "no");
 
-	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);
-	via_print("FIFO size:             %10d%20d", 16 - (((t >> 5) & 1) + ((t >> 6) & 1)) * 8,
-							  (((t >> 5) & 1) + ((t >> 6) & 1)) * 8);
-	via_print("Threshold Prim.:       %10s%20s", via_fifo[(t >> 2) & 3], via_fifo[t & 3]);
-
-	pci_read_config_word(dev, VIA_PRI_SECTOR_SIZE, &size0);
-	pci_read_config_word(dev, VIA_SEC_SECTOR_SIZE, &size1);
-	via_print("Bytes Per Sector:      %10d%20d", size0 & 0xfff, size1 & 0xfff);
+	pci_read_config_byte(dev, VIA_IDE_ENABLE, &t);
+	via_print("Enabled:               %10s%20s", (t & 0x02) ? "yes" : "no", (t & 0x01) ? "yes" : "no");
 
-	pci_read_config_dword(dev, VIA_BM_BASE, &base);
-	base = (base & 0xfff0) ;
+	c = inb(via_base + 0x02) | (inb(via_base + 0x0a) << 8);
+	via_print("Simplex only:          %10s%20s", (c & 0x80) ? "yes" : "no", (c & 0x8000) ? "yes" : "no");
 
-	c0 = inb((unsigned short)base + 0x02);
-	c1 = inb((unsigned short)base + 0x0a);
-
-	via_print("Both channels togth:   %10s%20s", (c0 & 0x80) ? "no" : "yes", (c1 & 0x80) ? "no" : "yes" );
+	via_print("Cable Type:            %10s%20s", (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w");
 
 	via_print("-------------------drive0----drive1----drive2----drive3-----");
 
-	via_print("BMDMA enabled: %10s%10s%10s%10s", (c0 & 0x20) ? "yes" : "no", (c0 & 0x40) ? "yes" : "no",
-						     (c1 & 0x20) ? "yes" : "no", (c1 & 0x40) ? "yes" : "no" );
-
 	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
 	pci_read_config_dword(dev, VIA_DRIVE_TIMING, &v);
-	pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+	pci_read_config_word(dev, VIA_8BIT_TIMING, &w);
+
+	if (via_config->flags & VIA_UDMA)
+		pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+	else u = 0;
 
 	for (i = 0; i < 4; i++) {
-		setup[i]   = ((t >>  ((3 - i) << 1)     ) & 0x3) + 1;
-		active[i]  = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
-		recover[i] = ((v >>  ((3 - i) << 3)     ) & 0xf) + 1;
-		udma[i]    = ((u >>  ((3 - i) << 3)     ) & 0x7) + 2;
-		umul[i]    = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 2 : 1;
-		uen[i]     = ((u >> ((3 - i) << 3)) & 0x20) ? 1 : 0;
-		speed[i] = uen[i] ? 20 * pci_clock * umul[i] / udma[i] :
-				    20 * pci_clock / (active[i] + recover[i]);
-		cycle[i] = uen[i] ? 1000 / (pci_clock * umul[i]) * udma[i] :
-				    1000 / pci_clock * (active[i] + recover[i]);
-	}
-
-	via_print_drive("Transfer Mode: ", "%10s", uen[i] ? "UDMA" : "DMA/PIO");
-	via_print_drive("Address Setup: ", "%8dns", (1000 / pci_clock) * setup[i]);
-	via_print_drive("Active Pulse:  ", "%8dns", (1000 / pci_clock) * active[i]);
-	via_print_drive("Recovery Time: ", "%8dns", (1000 / pci_clock) * recover[i]);
+		setup[i]     = ((t >> ((3 - i) << 1)) & 0x3) + 1;
+		recover8b[i] = ((w >> ((1 - (i >> 1)) << 3)) & 0xf) + 1;
+		active8b[i]  = ((w >> (((1 - (i >> 1)) << 3) + 4)) & 0xf) + 1;
+		active[i]    = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1;
+		recover[i]   = ((v >> ((3 - i) << 3)) & 0xf) + 1;
+		udma[i]      = ((u >> ((3 - i) << 3)) & 0x7) + 2;
+
+		if ((via_config->flags & VIA_UDMA) == VIA_UDMA_100) {
+			speed[i] = 2000 / udma[i];
+			cycle[i] = 10 * udma[i];
+			continue;
+		}
+
+		uen[i]   = (u >> ((3 - i) << 3)) & 0x20;
+		udma[i] *= ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2;
+
+		speed[i] = 40 * via_clock / (uen[i] ? udma[i] : (active[i] + recover[i]) * 2);
+		cycle[i] = 1000 / via_clock * (uen[i] ? udma[i] : (active[i] + recover[i]) * 2) / 2;
+	}
+
+	via_print_drive("Transfer Mode: ", "%10s",
+			(c & ((i & 1) ? 0x40 : 0x20) << ((i & 2) << 2)) ? (uen[i] ? "UDMA" : "DMA") : "PIO");
+
+	via_print_drive("Address Setup: ", "%8dns", (1000 / via_clock) * setup[i]);
+	via_print_drive("Cmd Active:    ", "%8dns", (1000 / via_clock) * active8b[i]);
+	via_print_drive("Cmd Recovery:  ", "%8dns", (1000 / via_clock) * recover8b[i]);
+	via_print_drive("Data Active:   ", "%8dns", (1000 / via_clock) * active[i]);
+	via_print_drive("Data Recovery: ", "%8dns", (1000 / via_clock) * recover[i]);
 	via_print_drive("Cycle Time:    ", "%8dns", cycle[i]);
 	via_print_drive("Transfer Rate: ", "%4d.%dMB/s", speed[i] / 10, speed[i] % 10);
 
@@ -274,302 +236,243 @@
 
 #endif
 
-#define FIT(v,min,max) ((v)>(max)?(max):((v)<(min)?(min):(v)))
-#define ENOUGH(v,un) (((v)-1)/(un)+1)
-
-#ifdef DEBUG
-#define via_write_config_byte(dev,number,value) do {\
-		printk(KERN_DEBUG "VP_IDE: Setting register %#x to %#x\n", number, value);\
-		pci_write_config_byte(dev,number,value); } while (0)
-#else
-#define via_write_config_byte	pci_write_config_byte
-#endif
+/*
+ * via_set_speed() writes timing values to the chipset registers
+ */
 
-static int via_set_speed(ide_drive_t *drive, byte speed)
+static void via_set_speed(struct pci_dev *dev, unsigned char dn, struct ide_timing *timing)
 {
-	struct pci_dev *dev = HWIF(drive)->pci_dev;
-	int i, T, err = 0;
-	unsigned char t, setup, active, recover, cycle;
-
-	if (drive->dn > 3) return -1;
-
-	T = 1000 / system_bus_clock();
-
-	if (speed > via_isa_bridges[via_config].speed)
-		speed = via_isa_bridges[via_config].speed;
+	unsigned char t;
 
-	for (i = 0; via_timing[i].mode && via_timing[i].mode != speed; i++);
+	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
+	t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(timing->setup, 1, 4) - 1) << ((3 - dn) << 1));
+	pci_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
 
-#ifdef DEBUG
-	printk(KERN_DEBUG "VP_IDE: Setting drive %d to %s\n", drive->dn, via_timing[i].name);
-#endif
+	pci_write_config_byte(dev, VIA_8BIT_TIMING + (1 - (dn >> 1)),
+		((FIT(timing->act8b, 1, 16) - 1) << 4) | (FIT(timing->rec8b, 1, 16) - 1));
 
-	setup   = ENOUGH(via_timing[i].setup,   T);
-	active  = ENOUGH(via_timing[i].active,  T);
-	recover = ENOUGH(via_timing[i].recover, T);
-	cycle   = ENOUGH(via_timing[i].cycle,   T);
+	pci_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - dn),
+		((FIT(timing->active, 1, 16) - 1) << 4) | (FIT(timing->recover, 1, 16) - 1));
 
-	if (active + recover < cycle) {
-		active += (cycle - (active + recover)) / 2;
-		recover = cycle - active;
+	switch (via_config->flags & VIA_UDMA) {
+		case VIA_UDMA_33:  t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 5) - 2)) : 0x03; break;
+		case VIA_UDMA_66:  t = timing->udma ? (0xe8 | (FIT(timing->udma, 2, 9) - 2)) : 0x0f; break;
+		case VIA_UDMA_100: t = timing->udma ? (0xe0 | (FIT(timing->udma, 2, 9) - 2)) : 0x07; break;
+		default: return;
 	}
 
-/*
- * PIO address setup
- */
-
-	pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t);
-	t = (t & ~(3 << ((3 - drive->dn) << 1))) | (FIT(setup - 1, 0, 3) << ((3 - drive->dn) << 1));
-	via_write_config_byte(dev, VIA_ADDRESS_SETUP, t);
+	pci_write_config_byte(dev, VIA_UDMA_TIMING + (3 - dn), t);
+}
 
 /*
- * PIO active & recover
+ * via_set_drive() computes timing values configures the drive and
+ * the chipset to a desired transfer mode. It also can be called
+ * by upper layers.
  */
 
-	via_write_config_byte(dev, VIA_DRIVE_TIMING + (3 - drive->dn),
-		(FIT(active - 1, 0, 0xf) << 4) | FIT(recover - 1, 0, 0xf));
-
-/*
- * UDMA cycle
- */
+static int via_set_drive(ide_drive_t *drive, unsigned char speed)
+{
+	ide_drive_t *peer = HWIF(drive)->drives + (~drive->dn & 1);
+	struct ide_timing t, p;
+	int T, UT;
+
+	if (speed != XFER_PIO_SLOW && speed != drive->current_speed)
+		if (ide_config_drive_speed(drive, speed))
+			printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n",
+				drive->dn >> 1, drive->dn & 1);
+
+	T = 1000 / via_clock;
+
+	switch (via_config->flags & VIA_UDMA) {
+		case VIA_UDMA_33:   UT = T;   break;
+		case VIA_UDMA_66:   UT = T/2; break;
+		case VIA_UDMA_100:  UT = 10;  break;
+		default:	    UT = T;   break;
+	}
 
-	switch(via_isa_bridges[via_config].speed) {
-		case XFER_UDMA_2: t = via_timing[i].udma ? (0xe0 | (FIT(ENOUGH(via_timing[i].udma, T), 2, 5) - 2)) : 0x03; break;
-		case XFER_UDMA_4: t = via_timing[i].udma ? (0xe8 | (FIT(ENOUGH(via_timing[i].udma, T/2), 2, 9) - 2)) : 0x0f; break;
-        }
+	ide_timing_compute(drive, speed, &t, T, UT);
 
-	if (via_isa_bridges[via_config].speed != XFER_MW_DMA_2)
-		via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t);
+	if (peer->present) {
+		ide_timing_compute(peer, peer->current_speed, &p, T, UT);
+		ide_timing_merge(&p, &t, &t, IDE_TIMING_8BIT);
+	}
 
-/*
- * Drive init
- */
+	via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t);
 
-	if (!drive->init_speed) drive->init_speed = speed;
-	if ((err = ide_config_drive_speed(drive, speed)))
-		return err;
+	if (!drive->init_speed)
+		drive->init_speed = speed;
 	drive->current_speed = speed;
 
 	return 0;
 }
 
-static void config_chipset_for_pio(ide_drive_t *drive)
-{
-	short eide_pio_timing[] = {600, 383, 240, 180, 120, 100};
-	signed char pio, ide_pio;
-
-	if (drive->id->eide_pio_iordy > 0) {	/* Has timing table */
-		for (pio = 5; pio >= 0; pio--)
-			if (drive->id->eide_pio_iordy <= eide_pio_timing[pio])
-				break;
-	} else {				/* No timing table -> use mode capabilities */
-		pio = (drive->id->eide_pio_modes & 4) ? 5 :
-		      (drive->id->eide_pio_modes & 2) ? 4 :
-		      (drive->id->eide_pio_modes & 1) ? 3 :
-		      (drive->id->tPIO == 2) ? 2 :
-		      (drive->id->tPIO == 1) ? 1 : 0;
-	}
-
-	ide_pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
-	pio = (pio >= ide_pio) ? pio : ide_pio;	/* Phew. What about the blacklist? */
-
-	if (!pio) pio = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
-		else pio += XFER_PIO_0;
-
-	/* Fixup because of broken ide-probe.c */
-	drive->dn = HWIF(drive)->channel * 2 + (drive->select.b.unit & 1); 
-
-	via_set_speed(drive, pio);
-}
+/*
+ * via82cxxx_tune_drive() is a callback from upper layers for
+ * PIO-only tuning.
+ */
 
-static void via82cxxx_tune_drive(ide_drive_t *drive, byte pio)
+static void via82cxxx_tune_drive(ide_drive_t *drive, unsigned char pio)
 {
+	if (!((via_enabled >> HWIF(drive)->channel) & 1))
+		return;
+
 	if (pio == 255) {
-		config_chipset_for_pio(drive);
+		via_set_drive(drive, ide_find_best_mode(drive, XFER_PIO | XFER_EPIO));
 		return;
 	}
-	
-	if (pio > 5) pio = 5;
-	
-	via_set_speed(drive, XFER_PIO_0 + pio);
+
+	via_set_drive(drive, XFER_PIO_0 + MIN(pio, 5));
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA
 
-static int config_chipset_for_dma(ide_drive_t *drive)
+/*
+ * via82cxxx_dmaproc() is a callback from upper layers that can do
+ * a lot, but we use it for DMA/PIO tuning only, delegating everything
+ * else to the default ide_dmaproc().
+ */
+
+int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
 {
-	struct hd_driveid *id = drive->id;
-	unsigned char ultra66 = eighty_ninty_three(drive);
-	unsigned char speed =
-
-		((id->dma_ultra & 0x0010) && ultra66) ? XFER_UDMA_4 :
-		((id->dma_ultra & 0x0008) && ultra66) ? XFER_UDMA_3 :
-		(id->dma_ultra & 0x0004) ? XFER_UDMA_2 :
-		(id->dma_ultra & 0x0002) ? XFER_UDMA_1 :
-		(id->dma_ultra & 0x0001) ? XFER_UDMA_0 :
-		(id->dma_mword & 0x0004) ? XFER_MW_DMA_2 :
-		(id->dma_mword & 0x0002) ? XFER_MW_DMA_1 :
-		(id->dma_mword & 0x0001) ? XFER_MW_DMA_0 :
-		(id->dma_1word & 0x0004) ? XFER_SW_DMA_2 :
-		(id->dma_1word & 0x0002) ? XFER_SW_DMA_1 :
-		(id->dma_1word & 0x0001) ? XFER_SW_DMA_0 : 0;
-		
-	if (!speed) return (int) ide_dma_off_quietly;
 
-	via_set_speed(drive, speed);
+	if (func == ide_dma_check) {
 
-	return (int) ide_dma_on;
-}
+		short w80 = HWIF(drive)->udma_four;
 
-/*
- * Almost a library function.
- */
+		short speed = ide_find_best_mode(drive,
+			XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA |
+			(via_config->flags & VIA_UDMA ? XFER_UDMA : 0) |
+			(w80 && (via_config->flags & VIA_UDMA) == VIA_UDMA_66 ? XFER_UDMA_66 : 0) |
+			(w80 && (via_config->flags & VIA_UDMA) == VIA_UDMA_100 ? XFER_UDMA_100 : 0));
 
-static int config_drive_xfer_rate(ide_drive_t *drive)
-{
-	struct hd_driveid *id = drive->id;
-	ide_dma_action_t dma_func = ide_dma_on;
+		func = ((speed & XFER_MODE) != XFER_PIO) ? ide_dma_on : ide_dma_off_quietly;
 
-	if (id && (id->capability & 1) && HWIF(drive)->autodma) {
-		/* Consult the list of known "bad" drives */
-		if (ide_dmaproc(ide_dma_bad_drive, drive)) {
-			dma_func = ide_dma_off;
-			goto fast_ata_pio;
-		}
-		dma_func = ide_dma_off_quietly;
-		if (id->field_valid & 4) {
-			if (id->dma_ultra & 0x002F) {
-				/* Force if Capable UltraDMA */
-				dma_func = config_chipset_for_dma(drive);
-				if ((id->field_valid & 2) &&
-				    (dma_func != ide_dma_on))
-					goto try_dma_modes;
-			}
-		} else if (id->field_valid & 2) {
-try_dma_modes:
-			if (id->dma_mword & 0x0007) {
-				/* Force if Capable regular DMA modes */
-				dma_func = config_chipset_for_dma(drive);
-				if (dma_func != ide_dma_on)
-					goto no_dma_set;
-			}
-		} else if (ide_dmaproc(ide_dma_good_drive, drive)) {
-			if (id->eide_dma_time > 150) {
-				goto no_dma_set;
-			}
-			/* Consult the list of known "good" drives */
-			dma_func = config_chipset_for_dma(drive);
-			if (dma_func != ide_dma_on)
-				goto no_dma_set;
-		} else {
-			goto fast_ata_pio;
-		}
-	} else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
-		dma_func = ide_dma_off_quietly;
-no_dma_set:
-		config_chipset_for_pio(drive);
+		via_set_drive(drive, speed);
 	}
-	return HWIF(drive)->dmaproc(dma_func, drive);
-}
 
-
-int via82cxxx_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
-{
-	if (func == ide_dma_check)
-			return config_drive_xfer_rate(drive);
 	return ide_dmaproc(func, drive);
 }
+
 #endif /* CONFIG_BLK_DEV_IDEDMA */
 
+/*
+ * The initialization callback. Here we determine the IDE chip type
+ * and initialize its drive independent registers.
+ */
+
 unsigned int __init pci_init_via82cxxx(struct pci_dev *dev, const char *name)
 {
 	struct pci_dev *isa = NULL;
-	unsigned char f, t, m;
-	unsigned int u, i;
+	unsigned char t, v;
+	unsigned int u;
+	int i;
 
 /*
- * Find ISA bridge to see how good the IDE is.
+ * Find the ISA bridge to see how good the IDE is.
  */
 
-	for (via_config = 0; via_isa_bridges[via_config].id; via_config++)
-		if ((isa = pci_find_device(PCI_VENDOR_ID_VIA, via_isa_bridges[via_config].id, NULL)))	
-			break;
-/*
- * Read revision.
- */
-
-	if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C586_0) {
-		pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-		if (t < 0x30) via_config++;			/* vt82c586a */
-		if (t < 0x20) via_config++;			/* vt82c586 */
-	}
+	for (via_config = via_isa_bridges; via_config->id; via_config++)
+		if ((isa = pci_find_device(PCI_VENDOR_ID_VIA, via_config->id, NULL))) {
+			pci_read_config_byte(isa, PCI_REVISION_ID, &t);
+			if (t >= via_config->rev_min && t <= via_config->rev_max)
+				break;
+		}
 
-	if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596) {
-		pci_read_config_byte(isa, PCI_REVISION_ID, &t);
-		if (t < 0x10) via_config++;			/* vt82c596a */
+	if (!via_config->id) {
+		printk(KERN_WARNING "VP_IDE: Unknown VIA SouthBridge, contact Vojtech Pavlik <vojtech@suse.cz>\n");
+		return -ENODEV;
 	}
 
 /*
- * Check UDMA66 mode set by BIOS.
+ * Check 80-wire cable presence and setup Clk66.
  */
 
-	pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+	switch (via_config->flags & VIA_UDMA) {
 
-	for (i = 0; i < 4; i++) {
-		pci_read_config_byte(dev, VIA_UDMA_TIMING + (3 - i), &t);
-		if ((u & (0x80000 >> ((i >> 1) << 4))) && ((t & 7) < 2)) via_ata66 |= (1 << (i >> 1));
-	} 
-
-#ifdef DEBUG
-	printk(KERN_DEBUG "VP_IDE: BIOS enabled ATA66: primary: %s, secondary: %s\n",
-		via_ata66 & 1 ? "yes" : "no", via_ata66 & 2 ? "yes" : "no");
-#endif
+		case VIA_UDMA_100:
+
+			pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
+			for (i = 24; i >= 0; i -= 8)
+				if (((u >> i) & 0x10) || (((u >> i) & 0x20) && (((u >> i) & 7) < 3)))
+					via_80w |= (1 << (1 - (i >> 4)));	/* BIOS 80-wire bit or UDMA w/ < 50ns/cycle */
+			break;
+
+		case VIA_UDMA_66:
+
+			pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);	/* Enable Clk66 */
+			pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
+			for (i = 24; i >= 0; i -= 8)
+				if (((u >> (i & 16)) & 8) && ((u >> i) & 0x20) && (((u >> i) & 7) < 2))
+					via_80w |= (1 << (1 - (i >> 4)));	/* 2x PCI clock and UDMA w/ < 3T/cycle */
+			break;
+	}
+
+	if (via_config->flags & VIA_BAD_CLK66) {			/* Disable Clk66 */
+		pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);	/* Would cause trouble on 596a */
+		pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008);
+	}
 
 /*
- * Set UDMA66 double clock bits.
+ * Check whether interfaces are enabled.
  */
-	if (via_isa_bridges[via_config].speed == XFER_UDMA_4)
-		pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
+
+	pci_read_config_byte(dev, VIA_IDE_ENABLE, &v);
+	via_enabled = ((v & 1) ? 2 : 0) | ((v & 2) ? 1 : 0);
 
 /*
- * Set up FIFO, flush, prefetch and post-writes.
+ * Set up FIFO sizes and thresholds.
  */
 
-	pci_read_config_dword(dev, VIA_IDE_ENABLE, &u);
-	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &f);
-	pci_read_config_byte(dev, VIA_IDE_CONFIG, &t);
-	pci_read_config_byte(dev, VIA_MISC_3, &m);
+	pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t);
 
-	f &= 0x90; t &= 0x0f; m &= 0x0f;
+	if (via_config->flags & VIA_BAD_PREQ)				/* Disable PREQ# till DDACK# */
+		t &= 0x7f;						/* Would crash on 586b rev 41 */
 
-	switch (u & 3) {
-		case 2: via_enabled = 1; f |= 0x06; t |= 0xc0; m |= 0xa0; break;	/* primary only, 3/4 */
-		case 1: via_enabled = 2; f |= 0x69; t |= 0x30; m |= 0x50; break;	/* secondary only, 3/4 */
-		case 3: via_enabled = 3;
-		default:                 f |= 0x2a; t |= 0xf0; m |= 0xf0; break;	/* fifo evenly distributed */
+	if (via_config->flags & VIA_SET_FIFO) {				/* Fix FIFO split between channels */
+		t &= (t & 0x9f);
+		switch (via_enabled) {
+			case 1: t |= 0x00; break;			/* 16 on primary */
+			case 2: t |= 0x60; break;			/* 16 on secondary */
+			case 3: t |= 0x20; break;			/* 8 pri 8 sec */
+		}
 	}
 
-	via_write_config_byte(dev, VIA_FIFO_CONFIG, f);
-	via_write_config_byte(dev, VIA_IDE_CONFIG, t);
-	via_write_config_byte(dev, VIA_MISC_3, m);
+	if (via_config->flags & VIA_SET_THRESH)				/* 1/2 FIFO full to trigger xmit */
+		t = (t & 0xf0) | 0x0a;
+
+	pci_write_config_byte(dev, VIA_FIFO_CONFIG, t);
+
+/*
+ * Determine system bus clock.
+ */
+
+	via_clock = system_bus_clock();
+	if (via_clock < 20 || via_clock > 50) {
+		printk(KERN_WARNING "VP_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", via_clock);
+		printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to force UDMA66/UDMA100.\n");
+		via_clock = 33;
+	}
 
 /*
  * Print the boot message.
  */
 
-	printk(KERN_INFO "VP_IDE: VIA %s IDE %s controller on pci%d:%d.%d\n",
-			via_isa_bridges[via_config].name,
-			via_isa_bridges[via_config].speed >= XFER_UDMA_4 ? "UDMA66" :
-			via_isa_bridges[via_config].speed >= XFER_UDMA_2 ? "UDMA33" : "MWDMA16",
-			dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+	pci_read_config_byte(isa, PCI_REVISION_ID, &t);
+	printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s controller on pci%s\n",
+			via_config->name, t,
+			(via_config->flags & VIA_UDMA) == VIA_UDMA_100 ? "UDMA100" :
+			(via_config->flags & VIA_UDMA) == VIA_UDMA_66 ? "UDMA66" :
+			(via_config->flags & VIA_UDMA) == VIA_UDMA_33 ? "UDMA33" : "MWDMA16",
+			dev->slot_name);
+
 /*
- * Register /proc/ide/via entry
+ * Setup /proc/ide/via entry.
  */
 
-#if defined(CONFIG_PROC_FS)
+#ifdef CONFIG_PROC_FS
 	if (!via_proc) {
 		via_proc = 1;
+		via_base = pci_resource_start(dev, 4);
 		bmide_dev = dev;
 		isa_dev = isa;
 		via_display_info = &via_get_info;
@@ -579,26 +482,26 @@
 	return 0;
 }
 
-/*
- * Since we don't have a way to detect the 80-wire ribbon cable
- * we rely on the BIOS detection. We also check the IDENTIFY byte
- * 93 to check the drive's point of view. I think we could return
- * '1' here 
- */
-
 unsigned int __init ata66_via82cxxx(ide_hwif_t *hwif)
 {
-	return ((via_enabled & via_ata66) >> hwif->channel) & 1;
+	return ((via_enabled & via_80w) >> hwif->channel) & 1;
 }
 
 void __init ide_init_via82cxxx(ide_hwif_t *hwif)
 {
+	int i;
+
 	hwif->tuneproc = &via82cxxx_tune_drive;
-	hwif->speedproc = &via_set_speed;
-	hwif->drives[0].autotune = 1;
-	hwif->drives[1].autotune = 1;
+	hwif->speedproc = &via_set_drive;
 	hwif->autodma = 0;
 
+	for (i = 0; i < 2; i++) {
+		hwif->drives[i].io_32bit = 1;
+		hwif->drives[i].unmask = 1;
+		hwif->drives[i].autotune = 1;
+		hwif->drives[i].dn = hwif->channel * 2 + i;
+	}
+
 #ifdef CONFIG_BLK_DEV_IDEDMA
 	if (hwif->dma_base) {
 		hwif->dmaproc = &via82cxxx_dmaproc;
@@ -610,7 +513,7 @@
 }
 
 /*
- * We allow the BM-DMA driver only work on enabled interfaces.
+ * We allow the BM-DMA driver to only work on enabled interfaces.
  */
 
 void __init ide_dmacapable_via82cxxx(ide_hwif_t *hwif, unsigned long dmabase)
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/guid.c linux/drivers/ieee1394/guid.c
--- v2.4.1/linux/drivers/ieee1394/guid.c	Mon Dec 11 12:39:44 2000
+++ linux/drivers/ieee1394/guid.c	Sun Feb  4 21:34:18 2001
@@ -163,7 +163,7 @@
                         return;
                 }
 
-                INIT_LIST_HEAD(&greq->tq.list);
+                INIT_TQ_LINK(greq->tq);
                 greq->tq.sync = 0;
                 greq->tq.routine = (void (*)(void*))pkt_complete;
                 greq->tq.data = greq;
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/hosts.c linux/drivers/ieee1394/hosts.c
--- v2.4.1/linux/drivers/ieee1394/hosts.c	Sun Oct  1 19:53:07 2000
+++ linux/drivers/ieee1394/hosts.c	Sun Feb  4 21:34:18 2001
@@ -106,6 +106,7 @@
         sema_init(&h->tlabel_count, 64);
         spin_lock_init(&h->tlabel_lock);
 
+        INIT_TQ_LINK(h->timeout_tq);
         h->timeout_tq.routine = (void (*)(void*))abort_timedouts;
         h->timeout_tq.data = h;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/ieee1394_core.c linux/drivers/ieee1394/ieee1394_core.c
--- v2.4.1/linux/drivers/ieee1394/ieee1394_core.c	Sun Oct  1 19:53:07 2000
+++ linux/drivers/ieee1394/ieee1394_core.c	Sun Feb  4 21:34:18 2001
@@ -98,6 +98,7 @@
                 packet->data_size = data_size;
         }
 
+        INIT_TQ_HEAD(packet->complete_tq);
         INIT_LIST_HEAD(&packet->list);
         sema_init(&packet->state_change, 0);
         packet->state = unused;
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/ieee1394_types.h linux/drivers/ieee1394/ieee1394_types.h
--- v2.4.1/linux/drivers/ieee1394/ieee1394_types.h	Mon Dec 11 13:20:17 2000
+++ linux/drivers/ieee1394/ieee1394_types.h	Sun Feb  4 21:34:18 2001
@@ -15,6 +15,9 @@
 #define V22_COMPAT_MOD_INC_USE_COUNT do {} while (0)
 #define V22_COMPAT_MOD_DEC_USE_COUNT do {} while (0)
 #define OWNER_THIS_MODULE owner: THIS_MODULE,
+
+#define INIT_TQ_LINK(tq) INIT_LIST_HEAD(&(tq).list)
+#define INIT_TQ_HEAD(tq) INIT_LIST_HEAD(&(tq))
 #endif
 
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,18)
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/ohci1394.c linux/drivers/ieee1394/ohci1394.c
--- v2.4.1/linux/drivers/ieee1394/ohci1394.c	Tue Jan  2 16:45:38 2001
+++ linux/drivers/ieee1394/ohci1394.c	Sun Feb  4 21:34:18 2001
@@ -97,6 +97,81 @@
 #include "ieee1394_core.h"
 #include "ohci1394.h"
 
+
+/* This structure is not properly initialized ... it is taken from
+   the lynx_csr_rom written by Andreas ... Some fields in the root
+   directory and the module dependent info needs to be modified
+   I do not have the proper doc */
+quadlet_t ohci_csr_rom[] = {
+        /* bus info block */
+        0x04040000, /* info/CRC length, CRC */
+        0x31333934, /* 1394 magic number */
+        0xf07da002, /* cyc_clk_acc = 125us, max_rec = 1024 */
+        0x00000000, /* vendor ID, chip ID high (written from card info) */
+        0x00000000, /* chip ID low (written from card info) */
+        /* root directory - FIXME */
+        0x00090000, /* CRC length, CRC */
+        0x03080028, /* vendor ID (Texas Instr.) */
+        0x81000009, /* offset to textual ID */
+        0x0c000200, /* node capabilities */
+        0x8d00000e, /* offset to unique ID */
+        0xc7000010, /* offset to module independent info */
+        0x04000000, /* module hardware version */
+        0x81000026, /* offset to textual ID */
+        0x09000000, /* node hardware version */
+        0x81000026, /* offset to textual ID */
+        /* module vendor ID textual */
+        0x00080000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54455841, /* "Texas Instruments" */
+        0x5320494e,
+        0x53545255,
+        0x4d454e54,
+        0x53000000,
+        /* node unique ID leaf */
+        0x00020000, /* CRC length, CRC */
+        0x08002856, /* vendor ID, chip ID high */
+        0x0000083E, /* chip ID low */
+        /* module dependent info - FIXME */
+        0x00060000, /* CRC length, CRC */
+        0xb8000006, /* ??? offset to module textual ID */
+        0x81000004, /* ??? textual descriptor */
+        0x00000000, /* SRAM size */
+        0x00000000, /* AUXRAM size */
+        0x00000000, /* AUX device */
+        /* module textual ID */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54534231, /* "TSB12LV22" */
+        0x324c5632,
+        0x32000000,
+        /* part number */
+        0x00060000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x39383036, /* "9806000-0001" */
+        0x3030342d,
+        0x30303431,
+        0x20000001,
+        /* module hardware version textual */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x5453424b, /* "TSBKOHCI403" */
+        0x4f484349,
+        0x34303300,
+        /* node hardware version textual */
+        0x00050000, /* CRC length, CRC */
+        0x00000000,
+        0x00000000,
+        0x54534234, /* "TSB41LV03" */
+        0x314c5630,
+        0x33000000
+};
+
+
 #ifdef CONFIG_IEEE1394_VERBOSEDEBUG
 #define OHCI1394_DEBUG
 #endif
@@ -1641,7 +1716,7 @@
 
         /* initialize bottom handler */
         d->task.sync = 0;
-        INIT_LIST_HEAD(&d->task.list);
+        INIT_TQ_LINK(d->task);
         d->task.routine = dma_rcv_bh;
         d->task.data = (void*)d;
 
@@ -1730,6 +1805,7 @@
         spin_lock_init(&d->lock);
 
         /* initialize bottom handler */
+        INIT_TQ_LINK(d->task);
         d->task.routine = dma_trm_bh;
         d->task.data = (void*)d;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/ohci1394.h linux/drivers/ieee1394/ohci1394.h
--- v2.4.1/linux/drivers/ieee1394/ohci1394.h	Tue Jan  2 16:45:38 2001
+++ linux/drivers/ieee1394/ohci1394.h	Tue Feb 13 13:15:04 2001
@@ -251,7 +251,7 @@
 	struct video_template *video_tmpl;
 };
 
-inline static int cross_bound(unsigned long addr, unsigned int size)
+static inline int cross_bound(unsigned long addr, unsigned int size)
 {
 	int cross=0;
 	if (size>PAGE_SIZE) {
@@ -266,88 +266,15 @@
 /*
  * Register read and write helper functions.
  */
-inline static void reg_write(const struct ti_ohci *ohci, int offset, u32 data)
+static inline void reg_write(const struct ti_ohci *ohci, int offset, u32 data)
 {
         writel(data, ohci->registers + offset);
 }
 
-inline static u32 reg_read(const struct ti_ohci *ohci, int offset)
+static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
 {
         return readl(ohci->registers + offset);
 }
-
-/* This structure is not properly initialized ... it is taken from
-   the lynx_csr_rom written by Andreas ... Some fields in the root
-   directory and the module dependent info needs to be modified
-   I do not have the proper doc */
-quadlet_t ohci_csr_rom[] = {
-        /* bus info block */
-        0x04040000, /* info/CRC length, CRC */
-        0x31333934, /* 1394 magic number */
-        0xf07da002, /* cyc_clk_acc = 125us, max_rec = 1024 */
-        0x00000000, /* vendor ID, chip ID high (written from card info) */
-        0x00000000, /* chip ID low (written from card info) */
-        /* root directory - FIXME */
-        0x00090000, /* CRC length, CRC */
-        0x03080028, /* vendor ID (Texas Instr.) */
-        0x81000009, /* offset to textual ID */
-        0x0c000200, /* node capabilities */
-        0x8d00000e, /* offset to unique ID */
-        0xc7000010, /* offset to module independent info */
-        0x04000000, /* module hardware version */
-        0x81000026, /* offset to textual ID */
-        0x09000000, /* node hardware version */
-        0x81000026, /* offset to textual ID */
-        /* module vendor ID textual */
-        0x00080000, /* CRC length, CRC */
-        0x00000000,
-        0x00000000,
-        0x54455841, /* "Texas Instruments" */
-        0x5320494e,
-        0x53545255,
-        0x4d454e54,
-        0x53000000,
-        /* node unique ID leaf */
-        0x00020000, /* CRC length, CRC */
-        0x08002856, /* vendor ID, chip ID high */
-        0x0000083E, /* chip ID low */
-        /* module dependent info - FIXME */
-        0x00060000, /* CRC length, CRC */
-        0xb8000006, /* ??? offset to module textual ID */
-        0x81000004, /* ??? textual descriptor */
-        0x00000000, /* SRAM size */
-        0x00000000, /* AUXRAM size */
-        0x00000000, /* AUX device */
-        /* module textual ID */
-        0x00050000, /* CRC length, CRC */
-        0x00000000,
-        0x00000000,
-        0x54534231, /* "TSB12LV22" */
-        0x324c5632,
-        0x32000000,
-        /* part number */
-        0x00060000, /* CRC length, CRC */
-        0x00000000,
-        0x00000000,
-        0x39383036, /* "9806000-0001" */
-        0x3030342d,
-        0x30303431,
-        0x20000001,
-        /* module hardware version textual */
-        0x00050000, /* CRC length, CRC */
-        0x00000000,
-        0x00000000,
-        0x5453424b, /* "TSBKOHCI403" */
-        0x4f484349,
-        0x34303300,
-        /* node hardware version textual */
-        0x00050000, /* CRC length, CRC */
-        0x00000000,
-        0x00000000,
-        0x54534234, /* "TSB41LV03" */
-        0x314c5630,
-        0x33000000
-};
 
 
 /* 2 KiloBytes of register space */
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/pcilynx.c linux/drivers/ieee1394/pcilynx.c
--- v2.4.1/linux/drivers/ieee1394/pcilynx.c	Tue Nov 28 21:45:16 2000
+++ linux/drivers/ieee1394/pcilynx.c	Tue Feb 13 14:13:44 2001
@@ -289,7 +289,8 @@
         char phyreg[7];
         int i;
 
-        for (i = 0; i < 7; i++) {
+        phyreg[0] = lynx->phy_reg0;
+        for (i = 1; i < 7; i++) {
                 phyreg[i] = get_phy_reg(lynx, i);
         }
 
@@ -317,13 +318,18 @@
         return lsid;
 }
 
-static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host, size_t size)
+static void handle_selfid(struct ti_lynx *lynx, struct hpsb_host *host)
 {
         quadlet_t *q = lynx->rcv_page;
-        int phyid, isroot;
+        int phyid, isroot, size;
         quadlet_t lsid = 0;
         int i;
 
+        if (lynx->phy_reg0 == -1 || lynx->selfid_size == -1) return;
+
+        size = lynx->selfid_size;
+        phyid = lynx->phy_reg0;
+
         i = (size > 16 ? 16 : size) / 4 - 1;
         while (i >= 0) {
                 cpu_to_be32s(&q[i]);
@@ -334,7 +340,6 @@
                 lsid = generate_own_selfid(lynx, host);
         }
 
-        phyid = get_phy_reg(lynx, 0);
         isroot = (phyid & 2) != 0;
         phyid >>= 2;
         PRINT(KERN_INFO, lynx->id, "SelfID process finished (phyid %d, %s)",
@@ -369,9 +374,14 @@
                 hpsb_selfid_received(host, lsid);
         }
 
-        if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER);
-
         hpsb_selfid_complete(host, phyid, isroot);
+
+        if (host->in_bus_reset) return;
+
+        if (isroot) reg_set_bits(lynx, LINK_CONTROL, LINK_CONTROL_CYCMASTER);
+        reg_set_bits(lynx, LINK_CONTROL,
+                     LINK_CONTROL_RCV_CMP_VALID | LINK_CONTROL_TX_ASYNC_EN
+                     | LINK_CONTROL_RX_ASYNC_EN | LINK_CONTROL_CYCTIMEREN);
 }
 
 
@@ -456,6 +466,9 @@
         int i;
         u32 *pcli;
 
+        lynx->selfid_size = -1;
+        lynx->phy_reg0 = -1;
+
         lynx->async.queue = NULL;
         spin_lock_init(&lynx->async.queue_lock);
         spin_lock_init(&lynx->phy_reg_lock);
@@ -531,8 +544,8 @@
         reg_write(lynx, DMA_WORD0_CMP_ENABLE(CHANNEL_ASYNC_RCV), 0xa<<4);
         reg_write(lynx, DMA_WORD1_CMP_VALUE(CHANNEL_ASYNC_RCV), 0);
         reg_write(lynx, DMA_WORD1_CMP_ENABLE(CHANNEL_ASYNC_RCV),
-                  DMA_WORD1_CMP_MATCH_NODE_BCAST | DMA_WORD1_CMP_MATCH_BROADCAST
-                  | DMA_WORD1_CMP_MATCH_LOCAL    | DMA_WORD1_CMP_MATCH_BUS_BCAST
+                  DMA_WORD1_CMP_MATCH_LOCAL_NODE | DMA_WORD1_CMP_MATCH_BROADCAST
+                  | DMA_WORD1_CMP_MATCH_EXACT    | DMA_WORD1_CMP_MATCH_BUS_BCAST
                   | DMA_WORD1_CMP_ENABLE_SELF_ID | DMA_WORD1_CMP_ENABLE_MASTER);
 
         run_pcl(lynx, lynx->rcv_pcl_start, CHANNEL_ASYNC_RCV);
@@ -547,12 +560,21 @@
         reg_write(lynx, LINK_CONTROL, LINK_CONTROL_RCV_CMP_VALID
                   | LINK_CONTROL_TX_ISO_EN   | LINK_CONTROL_RX_ISO_EN
                   | LINK_CONTROL_TX_ASYNC_EN | LINK_CONTROL_RX_ASYNC_EN
-                  | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX
-                  | LINK_CONTROL_CYCTIMEREN);
-        
-        /* attempt to enable contender bit -FIXME- would this work elsewhere? */
-        reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
-        reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); 
+                  | LINK_CONTROL_RESET_TX    | LINK_CONTROL_RESET_RX);
+
+        if (!lynx->phyic.reg_1394a) {
+                /* attempt to enable contender bit -FIXME- would this work
+                 * elsewhere? */
+                reg_set_bits(lynx, GPIO_CTRL_A, 0x1);
+                reg_write(lynx, GPIO_DATA_BASE + 0x3c, 0x1); 
+        } else {
+                /* set the contender bit in the extended PHY register
+                 * set. (Should check that bis 0,1,2 (=0xE0) is set
+                 * in register 2?)
+                 */
+                i = get_phy_reg(lynx, 4);
+                if (i != -1) set_phy_reg(lynx, 4, i | 0x40);
+        }
 
         return 1;
 }
@@ -628,6 +650,11 @@
 
         switch (cmd) {
         case RESET_BUS:
+                if (reg_read(lynx, LINK_INT_STATUS) & LINK_INT_PHY_BUSRESET) {
+                        retval = 0;
+                        break;
+                }
+
                 if (arg) {
                         arg = 3 << 6;
                 } else {
@@ -642,6 +669,8 @@
                       (host->attempt_root ? " and attempting to become root"
                        : ""));
 
+                lynx->selfid_size = -1;
+                lynx->phy_reg0 = -1;
                 set_phy_reg(lynx, 1, arg);
                 break;
 
@@ -1102,14 +1131,28 @@
                 }
                 if (linkint & LINK_INT_PHY_BUSRESET) {
                         PRINT(KERN_INFO, lynx->id, "bus reset interrupt");
-                        if (!host->in_bus_reset) {
+                        lynx->selfid_size = -1;
+                        lynx->phy_reg0 = -1;
+                        if (!host->in_bus_reset)
                                 hpsb_bus_reset(host);
-                        }
                 }
                 if (linkint & LINK_INT_PHY_REG_RCVD) {
+                        u32 reg;
+
+                        spin_lock(&lynx->phy_reg_lock);
+                        reg = reg_read(lynx, LINK_PHY);
+                        spin_unlock(&lynx->phy_reg_lock);
+
                         if (!host->in_bus_reset) {
                                 PRINT(KERN_INFO, lynx->id,
                                       "phy reg received without reset");
+                        } else if (reg & 0xf00) {
+                                PRINT(KERN_INFO, lynx->id,
+                                      "unsolicited phy reg %d received",
+                                      (reg >> 8) & 0xf);
+                        } else {
+                                lynx->phy_reg0 = reg & 0xff;
+                                handle_selfid(lynx, host);
                         }
                 }
                 if (linkint & LINK_INT_ISO_STUCK) {
@@ -1125,6 +1168,10 @@
                         PRINT(KERN_INFO, lynx->id, "invalid transaction code");
                 }
                 if (linkint & LINK_INT_GRF_OVERFLOW) {
+                        /* flush FIFO if overflow happens during reset */
+                        if (host->in_bus_reset)
+                                reg_write(lynx, FIFO_CONTROL,
+                                          FIFO_CONTROL_GRF_FLUSH);
                         PRINT(KERN_INFO, lynx->id, "GRF overflow");
                 }
                 if (linkint & LINK_INT_ITF_UNDERFLOW) {
@@ -1227,11 +1274,8 @@
                        stat & 0x1fff); 
 
                 if (stat & DMA_CHAN_STAT_SELFID) {
-                        handle_selfid(lynx, host, stat & 0x1fff);
-                        reg_set_bits(lynx, LINK_CONTROL,
-                                     LINK_CONTROL_RCV_CMP_VALID
-                                     | LINK_CONTROL_TX_ASYNC_EN
-                                     | LINK_CONTROL_RX_ASYNC_EN);
+                        lynx->selfid_size = stat & 0x1fff;
+                        handle_selfid(lynx, host);
                 } else {
                         quadlet_t *q_data = lynx->rcv_page;
                         if ((*q_data >> 4 & 0xf) == TCODE_READQ_RESPONSE
@@ -1415,13 +1459,15 @@
 
         lynx->lock = SPIN_LOCK_UNLOCKED;
 
-        reg_write(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT | PCI_INT_DMA_ALL);
+        reg_write(lynx, PCI_INT_ENABLE, PCI_INT_DMA_ALL);
 
 #ifdef CONFIG_IEEE1394_PCILYNX_PORTS
+        reg_set_bits(lynx, PCI_INT_ENABLE, PCI_INT_AUX_INT);
         init_waitqueue_head(&lynx->mem_dma_intr_wait);
         init_waitqueue_head(&lynx->aux_intr_wait);
 #endif
 
+        INIT_TQ_LINK(lynx->iso_rcv.tq);
         lynx->iso_rcv.tq.routine = (void (*)(void*))iso_rcv_bh;
         lynx->iso_rcv.tq.data = lynx;
         lynx->iso_rcv.lock = SPIN_LOCK_UNLOCKED;
@@ -1485,7 +1531,7 @@
                 pci_free_consistent(lynx->dev, LOCALRAM_SIZE, lynx->pcl_mem,
                                     lynx->pcl_mem_dma);
 #endif
-        case clear:
+        case clear:;
                 /* do nothing - already freed */
         }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/pcilynx.h linux/drivers/ieee1394/pcilynx.h
--- v2.4.1/linux/drivers/ieee1394/pcilynx.h	Mon Dec 11 13:20:21 2000
+++ linux/drivers/ieee1394/pcilynx.h	Sun Feb  4 21:34:18 2001
@@ -80,6 +80,8 @@
         struct hpsb_host *host;
 
         int phyid, isroot;
+        int selfid_size;
+        int phy_reg0;
 
         spinlock_t phy_reg_lock;
 
@@ -248,9 +250,9 @@
 #define FIFO_SIZES                        0xa00
 
 #define FIFO_CONTROL                      0xa10
-#define GRF_FLUSH                         (1<<4)
-#define ITF_FLUSH                         (1<<3)
-#define ATF_FLUSH                         (1<<2)
+#define FIFO_CONTROL_GRF_FLUSH            (1<<4)
+#define FIFO_CONTROL_ITF_FLUSH            (1<<3)
+#define FIFO_CONTROL_ATF_FLUSH            (1<<2)
 
 #define FIFO_XMIT_THRESHOLD               0xa14
 
@@ -285,8 +287,8 @@
 #define DMA_WORD1_CMP_MATCH_OTHERBUS      (1<<15)
 #define DMA_WORD1_CMP_MATCH_BROADCAST     (1<<14)
 #define DMA_WORD1_CMP_MATCH_BUS_BCAST     (1<<13)
-#define DMA_WORD1_CMP_MATCH_NODE_BCAST    (1<<12)
-#define DMA_WORD1_CMP_MATCH_LOCAL         (1<<11)
+#define DMA_WORD1_CMP_MATCH_LOCAL_NODE    (1<<12)
+#define DMA_WORD1_CMP_MATCH_EXACT         (1<<11)
 #define DMA_WORD1_CMP_ENABLE_SELF_ID      (1<<10)
 #define DMA_WORD1_CMP_ENABLE_MASTER       (1<<8)
 
diff -u --recursive --new-file v2.4.1/linux/drivers/ieee1394/raw1394.c linux/drivers/ieee1394/raw1394.c
--- v2.4.1/linux/drivers/ieee1394/raw1394.c	Tue Nov 28 21:45:16 2000
+++ linux/drivers/ieee1394/raw1394.c	Sun Feb  4 21:34:18 2001
@@ -64,6 +64,7 @@
         if (req != NULL) {
                 memset(req, 0, sizeof(struct pending_request));
                 INIT_LIST_HEAD(&req->list);
+                INIT_TQ_LINK(req->tq);
                 req->tq.routine = (void(*)(void*))queue_complete_cb;
         }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/input/evdev.c linux/drivers/input/evdev.c
--- v2.4.1/linux/drivers/input/evdev.c	Fri Nov 17 16:52:23 2000
+++ linux/drivers/input/evdev.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #define EVDEV_BUFFER_SIZE	64
 
 #include <linux/poll.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/input/joydev.c linux/drivers/input/joydev.c
--- v2.4.1/linux/drivers/input/joydev.c	Fri Nov 17 16:52:23 2000
+++ linux/drivers/input/joydev.c	Fri Feb  9 11:30:23 2001
@@ -38,7 +38,7 @@
 #include <linux/input.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/input/keybdev.c linux/drivers/input/keybdev.c
--- v2.4.1/linux/drivers/input/keybdev.c	Thu Jul 27 18:36:54 2000
+++ linux/drivers/input/keybdev.c	Fri Feb  9 11:30:23 2001
@@ -31,8 +31,9 @@
 #include <linux/config.h>
 #include <linux/kbd_ll.h>
 #include <linux/input.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/kbd_kern.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/input/mousedev.c linux/drivers/input/mousedev.c
--- v2.4.1/linux/drivers/input/mousedev.c	Fri Nov 17 16:52:23 2000
+++ linux/drivers/input/mousedev.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 #define MOUSEDEV_MINORS		32
 #define MOUSEDEV_MIX		31
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/act2000/act2000.h linux/drivers/isdn/act2000/act2000.h
--- v2.4.1/linux/drivers/isdn/act2000/act2000.h	Mon Dec 11 13:21:38 2000
+++ linux/drivers/isdn/act2000/act2000.h	Fri Feb  9 11:30:23 2001
@@ -88,7 +88,7 @@
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/avmb1/avm_cs.c linux/drivers/isdn/avmb1/avm_cs.c
--- v2.4.1/linux/drivers/isdn/avmb1/avm_cs.c	Mon Nov 27 16:53:43 2000
+++ linux/drivers/isdn/avmb1/avm_cs.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/tty.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/avmb1/capi.c linux/drivers/isdn/avmb1/capi.c
--- v2.4.1/linux/drivers/isdn/avmb1/capi.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/isdn/avmb1/capi.c	Fri Feb 16 16:06:17 2001
@@ -1,11 +1,18 @@
 /*
- * $Id: capi.c,v 1.45 2000/12/02 19:47:29 kai Exp $
+ * $Id: capi.c,v 1.44.6.3 2000/12/17 22:45:08 kai Exp $
  *
  * CAPI 2.0 Interface for Linux
  *
  * Copyright 1996 by Carsten Paeth (calle@calle.in-berlin.de)
  *
  * $Log: capi.c,v $
+ * Revision 1.44.6.3  2000/12/17 22:45:08  kai
+ * That's hopefully it for test13-4
+ *
+ * Revision 1.44.6.2  2000/12/14 23:04:12  kai
+ * Makefile changes and the like for 2.4.0-test13-pre1
+ * No compatiblity code for older kernels yet, but note the branch
+ *
  * Revision 1.45  2000/12/02 19:47:29  kai
  * Change the Makefiles to new style.
  * There may be problems there that I missed, so this shouldn't go into
@@ -216,7 +223,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
 #include <linux/signal.h>
@@ -245,9 +252,8 @@
 #if defined(CONFIG_ISDN_CAPI_CAPIFS) || defined(CONFIG_ISDN_CAPI_CAPIFS_MODULE)
 #include "capifs.h"
 #endif
-#include <linux/slab.h>
 
-static char *revision = "$Revision: 1.45 $";
+static char *revision = "$Revision: 1.44.6.3 $";
 
 MODULE_AUTHOR("Carsten Paeth (calle@calle.in-berlin.de)");
 
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/avmb1/capidrv.c linux/drivers/isdn/avmb1/capidrv.c
--- v2.4.1/linux/drivers/isdn/avmb1/capidrv.c	Mon Nov 27 16:53:43 2000
+++ linux/drivers/isdn/avmb1/capidrv.c	Fri Feb  9 11:30:23 2001
@@ -198,7 +198,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/fs.h>
 #include <linux/signal.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/avmb1/capifs.c linux/drivers/isdn/avmb1/capifs.c
--- v2.4.1/linux/drivers/isdn/avmb1/capifs.c	Tue Nov 28 21:44:41 2000
+++ linux/drivers/isdn/avmb1/capifs.c	Fri Feb  9 11:30:23 2001
@@ -86,7 +86,7 @@
 #include <linux/kernel.h>
 #include <linux/locks.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ctype.h>
 #include <asm/bitops.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/divert/isdn_divert.c linux/drivers/isdn/divert/isdn_divert.c
--- v2.4.1/linux/drivers/isdn/divert/isdn_divert.c	Fri Nov 17 11:16:20 2000
+++ linux/drivers/isdn/divert/isdn_divert.c	Thu Feb  8 10:40:25 2001
@@ -1,5 +1,5 @@
 /* 
- * $Id: isdn_divert.c,v 1.6 2000/11/13 22:51:47 kai Exp $
+ * $Id: isdn_divert.c,v 1.6.6.1 2001/02/07 11:31:31 kai Exp $
  *
  * DSS1 main diversion supplementary handling for i4l.
  *
@@ -187,7 +187,7 @@
   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",
+  sprintf(cs->info,"%d 0x%lx %s%s 0 %s %02x %d%s%s\n",
 	  (!mode ) ? DIVERT_DEACTIVATE : (mode == 1) ? DIVERT_ACTIVATE : DIVERT_REPORT,
           cs->ics.parm.dss1_io.ll_id,
           (mode != 2) ? "" : "0 ",
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/eicon/Divas_mod.c linux/drivers/isdn/eicon/Divas_mod.c
--- v2.4.1/linux/drivers/isdn/eicon/Divas_mod.c	Wed Sep 27 13:45:40 2000
+++ linux/drivers/isdn/eicon/Divas_mod.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <errno.h>
 
 #include "adapter.h"
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/eicon/eicon.h linux/drivers/isdn/eicon/eicon.h
--- v2.4.1/linux/drivers/isdn/eicon/eicon.h	Sun Aug 13 10:05:32 2000
+++ linux/drivers/isdn/eicon/eicon.h	Fri Feb  9 11:30:23 2001
@@ -139,7 +139,7 @@
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/eicon/linchr.c linux/drivers/isdn/eicon/linchr.c
--- v2.4.1/linux/drivers/isdn/eicon/linchr.c	Sun Aug 13 10:05:32 2000
+++ linux/drivers/isdn/eicon/linchr.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #undef N_DATA
 
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/eicon/linio.c linux/drivers/isdn/eicon/linio.c
--- v2.4.1/linux/drivers/isdn/eicon/linio.c	Sun Aug 13 10:05:32 2000
+++ linux/drivers/isdn/eicon/linio.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
 
 #include <asm/io.h>
 #include <asm/system.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #undef N_DATA
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/hisax/hisax.h linux/drivers/isdn/hisax/hisax.h
--- v2.4.1/linux/drivers/isdn/hisax/hisax.h	Fri Dec 29 14:07:22 2000
+++ linux/drivers/isdn/hisax/hisax.h	Fri Feb  9 11:30:23 2001
@@ -16,7 +16,7 @@
 #include <linux/delay.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/hisax/netjet.c linux/drivers/isdn/hisax/netjet.c
--- v2.4.1/linux/drivers/isdn/hisax/netjet.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/isdn/hisax/netjet.c	Thu Feb  8 10:40:25 2001
@@ -1,4 +1,4 @@
-/* $Id: netjet.c,v 1.24.6.1 2000/12/06 16:59:20 kai Exp $
+/* $Id: netjet.c,v 1.24.6.2 2000/12/17 22:45:11 kai Exp $
  *
  * netjet.c     low level stuff for Traverse Technologie NETJet ISDN cards
  *
@@ -19,17 +19,10 @@
 #include <linux/pci.h>
 #include <linux/interrupt.h>
 #include <linux/ppp_defs.h>
+#include <asm/io.h>
 #include "netjet.h"
 
-#ifndef bus_to_virt
-#define bus_to_virt (u_int *)
-#endif
-
-#ifndef virt_to_bus
-#define virt_to_bus (u_int)
-#endif
-
-const char *NETjet_revision = "$Revision: 1.24.6.1 $";
+const char *NETjet_revision = "$Revision: 1.24.6.2 $";
 
 /* Interface functions */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/hisax/nj_s.c linux/drivers/isdn/hisax/nj_s.c
--- v2.4.1/linux/drivers/isdn/hisax/nj_s.c	Wed Nov 29 10:12:29 2000
+++ linux/drivers/isdn/hisax/nj_s.c	Thu Feb  8 10:40:25 2001
@@ -1,4 +1,4 @@
-// $Id: nj_s.c,v 2.7.6.1 2000/11/29 16:00:14 kai Exp $
+// $Id: nj_s.c,v 2.7.6.2 2001/02/07 11:31:31 kai Exp $
 //
 // This file is (c) under GNU PUBLIC LICENSE
 //
@@ -14,7 +14,7 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_S_revision = "$Revision: 2.7.6.1 $";
+const char *NETjet_S_revision = "$Revision: 2.7.6.2 $";
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
@@ -171,6 +171,7 @@
 			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
 			if (pci_enable_device(dev_netjet))
 				return(0);
+			pci_set_master(dev_netjet);
 			cs->irq = dev_netjet->irq;
 			if (!cs->irq) {
 				printk(KERN_WARNING "NETjet-S: No IRQ for PCI card found\n");
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/hisax/nj_u.c linux/drivers/isdn/hisax/nj_u.c
--- v2.4.1/linux/drivers/isdn/hisax/nj_u.c	Wed Nov 29 10:12:29 2000
+++ linux/drivers/isdn/hisax/nj_u.c	Thu Feb  8 10:40:25 2001
@@ -1,4 +1,4 @@
-/* $Id: nj_u.c,v 2.8.6.1 2000/11/29 16:00:14 kai Exp $ 
+/* $Id: nj_u.c,v 2.8.6.2 2001/02/07 11:31:31 kai Exp $ 
  *
  * This file is (c) under GNU PUBLIC LICENSE
  *
@@ -15,7 +15,7 @@
 #include <linux/ppp_defs.h>
 #include "netjet.h"
 
-const char *NETjet_U_revision = "$Revision: 2.8.6.1 $";
+const char *NETjet_U_revision = "$Revision: 2.8.6.2 $";
 
 static u_char dummyrr(struct IsdnCardState *cs, int chan, u_char off)
 {
@@ -174,6 +174,7 @@
 			PCI_DEVICE_ID_TIGERJET_300,  dev_netjet))) {
 			if (pci_enable_device(dev_netjet))
 				return(0);
+			pci_set_master(dev_netjet);
 			cs->irq = dev_netjet->irq;
 			if (!cs->irq) {
 				printk(KERN_WARNING "NETspider-U: No IRQ for PCI card found\n");
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/hysdn/hysdn_boot.c linux/drivers/isdn/hysdn/hysdn_boot.c
--- v2.4.1/linux/drivers/isdn/hysdn/hysdn_boot.c	Fri Nov 17 11:16:20 2000
+++ linux/drivers/isdn/hysdn/hysdn_boot.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/vmalloc.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 
 #include "hysdn_defs.h"
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/hysdn/hysdn_init.c linux/drivers/isdn/hysdn/hysdn_init.c
--- v2.4.1/linux/drivers/isdn/hysdn/hysdn_init.c	Tue Nov 28 21:44:41 2000
+++ linux/drivers/isdn/hysdn/hysdn_init.c	Fri Feb  9 11:30:23 2001
@@ -27,7 +27,7 @@
 #include <linux/version.h>
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 
 #include "hysdn_defs.h"
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/icn/icn.h linux/drivers/isdn/icn/icn.h
--- v2.4.1/linux/drivers/isdn/icn/icn.h	Mon Dec 11 13:21:14 2000
+++ linux/drivers/isdn/icn/icn.h	Fri Feb  9 11:30:23 2001
@@ -55,7 +55,7 @@
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/isdn_bsdcomp.c linux/drivers/isdn/isdn_bsdcomp.c
--- v2.4.1/linux/drivers/isdn/isdn_bsdcomp.c	Sun Aug 15 11:49:08 1999
+++ linux/drivers/isdn/isdn_bsdcomp.c	Fri Feb  9 11:30:23 2001
@@ -61,7 +61,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/tty.h>
 #include <linux/errno.h>
 #include <linux/string.h>	/* used in new tty drivers */
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.4.1/linux/drivers/isdn/isdn_common.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/isdn/isdn_common.c	Thu Feb  8 10:40:25 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_common.c,v 1.114 2000/11/25 17:00:59 kai Exp $
+/* $Id: isdn_common.c,v 1.114.6.6 2001/02/07 11:31:30 kai Exp $
 
  * Linux ISDN subsystem, common used functions (linklevel).
  *
@@ -24,6 +24,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/version.h>
 #include <linux/poll.h>
 #include <linux/vmalloc.h>
@@ -51,7 +52,7 @@
 
 isdn_dev *dev;
 
-static char *isdn_revision = "$Revision: 1.114 $";
+static char *isdn_revision = "$Revision: 1.114.6.6 $";
 
 extern char *isdn_net_revision;
 extern char *isdn_tty_revision;
@@ -2004,16 +2005,6 @@
 }
 
 int
-register_isdn_module(isdn_module *m) {
-	return 0;
-}
-
-int
-unregister_isdn_module(isdn_module *m) {
-	return 0;
-}
-
-int
 isdn_add_channels(driver *d, int drvidx, int n, int adding)
 {
 	int j, k, m;
@@ -2173,8 +2164,6 @@
 
 
 EXPORT_SYMBOL(register_isdn);
-EXPORT_SYMBOL(register_isdn_module);
-EXPORT_SYMBOL(unregister_isdn_module);
 #ifdef CONFIG_ISDN_PPP
 EXPORT_SYMBOL(isdn_ppp_register_compressor);
 EXPORT_SYMBOL(isdn_ppp_unregister_compressor);
@@ -2242,12 +2231,6 @@
  *****************************************************************************
  */
 
-extern int printk(const char *fmt,...);
-
-#ifdef MODULE
-#define isdn_init init_module
-#endif
-
 static char *
 isdn_getrev(const char *revision)
 {
@@ -2356,8 +2339,7 @@
 /*
  * Allocate and initialize all data, register modem-devices
  */
-int
-isdn_init(void)
+static int __init isdn_init(void)
 {
 	int i;
 	char tmprev[50];
@@ -2433,12 +2415,10 @@
 	return 0;
 }
 
-#ifdef MODULE
 /*
  * Unload module
  */
-void
-cleanup_module(void)
+static void __exit isdn_exit(void)
 {
 	int flags;
 	int i;
@@ -2482,4 +2462,6 @@
 		printk(KERN_NOTICE "ISDN-subsystem unloaded\n");
 	}
 }
-#endif
+
+module_init(isdn_init);
+module_exit(isdn_exit);
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.4.1/linux/drivers/isdn/isdn_net.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/isdn/isdn_net.c	Thu Feb  8 10:40:25 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_net.c,v 1.140.6.1 2000/12/10 22:01:04 kai Exp $
+/* $Id: isdn_net.c,v 1.140.6.3 2001/02/07 11:31:30 kai Exp $
 
  * Linux ISDN subsystem, network interfaces and related functions (linklevel).
  *
@@ -154,6 +154,7 @@
 	if (!(isdn_net_device_busy(lp))) {
 		if (!skb_queue_empty(&lp->super_tx_queue)) {
 			queue_task(&lp->tqueue, &tq_immediate);
+			mark_bh(IMMEDIATE_BH);
 		} else {
 			isdn_net_device_wake_queue(lp);
 		}
@@ -181,7 +182,7 @@
 int isdn_net_force_dial_lp(isdn_net_local *);
 static int isdn_net_start_xmit(struct sk_buff *, struct net_device *);
 
-char *isdn_net_revision = "$Revision: 1.140.6.1 $";
+char *isdn_net_revision = "$Revision: 1.140.6.3 $";
 
  /*
   * Code for raw-networking over ISDN
@@ -981,11 +982,12 @@
  */
 void isdn_net_write_super(isdn_net_local *lp, struct sk_buff *skb)
 {
-	if (in_interrupt()) {
+	if (in_irq()) {
 		// we can't grab the lock from irq context, 
 		// so we just queue the packet
 		skb_queue_tail(&lp->super_tx_queue, skb); 
 		queue_task(&lp->tqueue, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
 		return;
 	}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.4.1/linux/drivers/isdn/isdn_ppp.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/isdn/isdn_ppp.c	Thu Feb  8 10:40:25 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_ppp.c,v 1.85 2000/11/25 17:00:59 kai Exp $
+/* $Id: isdn_ppp.c,v 1.85.6.2 2001/01/23 17:45:02 kai Exp $
  *
  * Linux ISDN subsystem, functions for synchronous PPP (linklevel).
  *
@@ -83,7 +83,7 @@
 static int isdn_ppp_bundle(struct ippp_struct *, int unit);
 #endif	/* CONFIG_ISDN_MPP */
   
-char *isdn_ppp_revision = "$Revision: 1.85 $";
+char *isdn_ppp_revision = "$Revision: 1.85.6.2 $";
 
 static struct ippp_struct *ippp_table[ISDN_MAX_CHANNELS];
 
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/isdn_v110.c linux/drivers/isdn/isdn_v110.c
--- v2.4.1/linux/drivers/isdn/isdn_v110.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/isdn/isdn_v110.c	Fri Feb  9 11:30:23 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn_v110.c,v 1.5 2000/05/11 22:29:21 kai Exp $
+/* $Id: isdn_v110.c,v 1.5.6.1 2001/01/23 17:45:02 kai Exp $
 
  * Linux ISDN subsystem, V.110 related functions (linklevel).
  *
@@ -22,7 +22,7 @@
 
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 
 #include <linux/isdn.h>
@@ -30,7 +30,7 @@
 
 #undef ISDN_V110_DEBUG
 
-char *isdn_v110_revision = "$Revision: 1.5 $";
+char *isdn_v110_revision = "$Revision: 1.5.6.1 $";
 
 #define V110_38400 255
 #define V110_19200  15
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/isdnloop/isdnloop.h linux/drivers/isdn/isdnloop/isdnloop.h
--- v2.4.1/linux/drivers/isdn/isdnloop/isdnloop.h	Fri Nov 17 11:16:21 2000
+++ linux/drivers/isdn/isdnloop/isdnloop.h	Fri Feb  9 11:30:23 2001
@@ -53,7 +53,7 @@
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/pcbit/callbacks.c linux/drivers/isdn/pcbit/callbacks.c
--- v2.4.1/linux/drivers/isdn/pcbit/callbacks.c	Sun May 23 10:03:42 1999
+++ linux/drivers/isdn/pcbit/callbacks.c	Fri Feb  9 11:30:23 2001
@@ -27,7 +27,7 @@
 #include <linux/kernel.h>
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/tqueue.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/pcbit/capi.c linux/drivers/isdn/pcbit/capi.c
--- v2.4.1/linux/drivers/isdn/pcbit/capi.c	Mon Aug 21 07:49:03 2000
+++ linux/drivers/isdn/pcbit/capi.c	Fri Feb  9 11:30:23 2001
@@ -37,7 +37,7 @@
 #include <linux/kernel.h>
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 
 #include <linux/tqueue.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/pcbit/drv.c linux/drivers/isdn/pcbit/drv.c
--- v2.4.1/linux/drivers/isdn/pcbit/drv.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/isdn/pcbit/drv.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/kernel.h>
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/pcbit/edss1.c linux/drivers/isdn/pcbit/edss1.c
--- v2.4.1/linux/drivers/isdn/pcbit/edss1.c	Sat Aug 31 10:01:58 1996
+++ linux/drivers/isdn/pcbit/edss1.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/kernel.h>
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/tqueue.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/pcbit/layer2.c linux/drivers/isdn/pcbit/layer2.c
--- v2.4.1/linux/drivers/isdn/pcbit/layer2.c	Mon Aug 21 07:49:03 2000
+++ linux/drivers/isdn/pcbit/layer2.c	Fri Feb  9 11:30:23 2001
@@ -40,7 +40,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/tqueue.h>
 #include <linux/mm.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/isdn/sc/includes.h linux/drivers/isdn/sc/includes.h
--- v2.4.1/linux/drivers/isdn/sc/includes.h	Sun Jan 25 10:05:46 1998
+++ linux/drivers/isdn/sc/includes.h	Fri Feb  9 11:30:23 2001
@@ -5,7 +5,7 @@
 #include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/Makefile linux/drivers/macintosh/Makefile
--- v2.4.1/linux/drivers/macintosh/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/macintosh/Makefile	Sun Feb  4 10:21:25 2001
@@ -26,10 +26,7 @@
 
 # Each configuration option enables a list of files.
 
-ifeq ($(CONFIG_PMAC_PBOOK),y)
-	obj-y			+= mediabay.o
-endif
-
+obj-$(CONFIG_PMAC_PBOOK)	+= mediabay.o
 obj-$(CONFIG_MAC_SERIAL)	+= macserial.o
 obj-$(CONFIG_NVRAM)		+= nvram.o
 obj-$(CONFIG_MAC_HID)		+= mac_hid.o
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/adb.c linux/drivers/macintosh/adb.c
--- v2.4.1/linux/drivers/macintosh/adb.c	Sun Sep 17 09:48:05 2000
+++ linux/drivers/macintosh/adb.c	Fri Feb  9 11:30:23 2001
@@ -19,7 +19,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/devfs_fs_kernel.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/adbhid.c linux/drivers/macintosh/adbhid.c
--- v2.4.1/linux/drivers/macintosh/adbhid.c	Sun Sep 17 09:48:05 2000
+++ linux/drivers/macintosh/adbhid.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/notifier.h>
 #include <linux/input.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/macserial.c linux/drivers/macintosh/macserial.c
--- v2.4.1/linux/drivers/macintosh/macserial.c	Thu Oct 12 14:20:47 2000
+++ linux/drivers/macintosh/macserial.c	Sun Feb  4 10:21:25 2001
@@ -952,6 +952,67 @@
 	info->dma_initted = 1;
 }
 
+/*
+ * FixZeroBug....Works around a bug in the SCC receving channel.
+ * Taken from Darwin code, 15 Sept. 2000  -DanM
+ *
+ * The following sequence prevents a problem that is seen with O'Hare ASICs
+ * (most versions -- also with some Heathrow and Hydra ASICs) where a zero
+ * at the input to the receiver becomes 'stuck' and locks up the receiver.
+ * This problem can occur as a result of a zero bit at the receiver input
+ * coincident with any of the following events:
+ *
+ *	The SCC is initialized (hardware or software).
+ *	A framing error is detected.
+ *	The clocking option changes from synchronous or X1 asynchronous
+ *		clocking to X16, X32, or X64 asynchronous clocking.
+ *	The decoding mode is changed among NRZ, NRZI, FM0, or FM1.
+ *
+ * This workaround attempts to recover from the lockup condition by placing
+ * the SCC in synchronous loopback mode with a fast clock before programming
+ * any of the asynchronous modes.
+ */
+static void fix_zero_bug_scc(struct mac_serial * info)
+{
+	write_zsreg(info->zs_channel, 9,
+		    (info->zs_channel == info->zs_chan_a? CHRA: CHRB));
+	udelay(10);
+	write_zsreg(info->zs_channel, 9,
+		    ((info->zs_channel == info->zs_chan_a? CHRA: CHRB) | NV));
+
+	write_zsreg(info->zs_channel, 4, (X1CLK | EXTSYNC));
+
+	/* I think this is wrong....but, I just copying code....
+	*/
+	write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE));
+
+	write_zsreg(info->zs_channel, 5, (8 & ~TxENAB));
+	write_zsreg(info->zs_channel, 9, NV);	/* Didn't we already do this? */
+	write_zsreg(info->zs_channel, 11, (RCBR | TCBR));
+	write_zsreg(info->zs_channel, 12, 0);
+	write_zsreg(info->zs_channel, 13, 0);
+	write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR));
+	write_zsreg(info->zs_channel, 14, (LOOPBAK | SSBR | BRENABL));
+	write_zsreg(info->zs_channel, 3, (8 | RxENABLE));
+	write_zsreg(info->zs_channel, 0, RES_EXT_INT);
+	write_zsreg(info->zs_channel, 0, RES_EXT_INT);	/* to kill some time */
+
+	/* The channel should be OK now, but it is probably receiving
+	 * loopback garbage.
+	 * Switch to asynchronous mode, disable the receiver,
+	 * and discard everything in the receive buffer.
+	 */
+	write_zsreg(info->zs_channel, 9, NV);
+	write_zsreg(info->zs_channel, 4, PAR_ENA);
+	write_zsreg(info->zs_channel, 3, (8 & ~RxENABLE));
+
+	while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV) {
+		(void)read_zsreg(info->zs_channel, 8);
+		write_zsreg(info->zs_channel, 0, RES_EXT_INT);
+		write_zsreg(info->zs_channel, 0, ERR_RES);
+	}
+}
+
 static int setup_scc(struct mac_serial * info)
 {
 	unsigned long flags;
@@ -960,6 +1021,9 @@
 
 	save_flags(flags); cli(); /* Disable interrupts */
 
+	/* Nice buggy HW ... */
+	fix_zero_bug_scc(info);
+
 	/*
 	 * Reset the chip.
 	 */
@@ -1080,7 +1144,7 @@
 
 	info->curregs[5] &= ~TxENAB;
 	if (!info->tty || C_HUPCL(info->tty))
-		info->curregs[5] &= ~(DTR | RTS);
+		info->curregs[5] &= ~DTR;
 	info->pendregs[5] = info->curregs[5];
 	write_zsreg(info->zs_channel, 5, info->curregs[5]);
 
@@ -1252,7 +1316,7 @@
 
 	/* assert DTR, wait 30ms, talk to the chip */
 	write_zsreg(info->zs_channel, 5, Tx8 | TxENAB | RTS | DTR);
-	udelay(30000);
+	mdelay(30);
 	while (read_zsreg(info->zs_channel, 0) & Rx_CH_AV)
 		read_zsdata(info->zs_channel);
 
@@ -1589,17 +1653,35 @@
 	if (C_CRTSCTS(tty)) {
 		/*
 		 * Here we want to turn off the RTS line.  On Macintoshes,
-		 * we only get the DTR line, which goes to both DTR and
-		 * RTS on the modem.  RTS doesn't go out to the serial
-		 * port socket.  So you should make sure your modem is
-		 * set to ignore DTR if you're using CRTSCTS.
+		 * the external serial ports using a DIN-8 or DIN-9
+		 * connector only have the DTR line (which is usually
+		 * wired to both RTS and DTR on an external modem in
+		 * the cable).  RTS doesn't go out to the serial port
+		 * socket, it acts as an output enable for the transmit
+		 * data line.  So in this case we don't drop RTS.
+		 *
+		 * Macs with internal modems generally do have both RTS
+		 * and DTR wired to the modem, so in that case we do
+		 * drop RTS.
 		 */
+		if (info->is_internal_modem) {
+			save_flags(flags); cli();
+			info->curregs[5] &= ~RTS;
+			info->pendregs[5] &= ~RTS;
+			write_zsreg(info->zs_channel, 5, info->curregs[5]);
+			restore_flags(flags);
+		}
+	}
+	
+#ifdef CDTRCTS
+	if (tty->termios->c_cflag & CDTRCTS) {
 		save_flags(flags); cli();
-		info->curregs[5] &= ~(DTR | RTS);
-		info->pendregs[5] &= ~(DTR | RTS);
+		info->curregs[5] &= ~DTR;
+		info->pendregs[5] &= ~DTR;
 		write_zsreg(info->zs_channel, 5, info->curregs[5]);
 		restore_flags(flags);
 	}
+#endif /* CDTRCTS */
 }
 
 static void rs_unthrottle(struct tty_struct * tty)
@@ -1625,14 +1707,25 @@
 		restore_flags(flags);
 	}
 
-	if (C_CRTSCTS(tty)) {
-		/* Assert RTS and DTR lines */
+	if (C_CRTSCTS(tty) && info->is_internal_modem) {
+		/* Assert RTS line */
 		save_flags(flags); cli();
-		info->curregs[5] |= DTR | RTS;
-		info->pendregs[5] |= DTR | RTS;
+		info->curregs[5] |= RTS;
+		info->pendregs[5] |= RTS;
 		write_zsreg(info->zs_channel, 5, info->curregs[5]);
 		restore_flags(flags);
 	}
+
+#ifdef CDTRCTS
+	if (tty->termios->c_cflag & CDTRCTS) {
+		/* Assert DTR line */
+		save_flags(flags); cli();
+		info->curregs[5] |= DTR;
+		info->pendregs[5] |= DTR;
+		write_zsreg(info->zs_channel, 5, info->curregs[5]);
+		restore_flags(flags);
+	}
+#endif
 }
 
 /*
@@ -2196,8 +2289,8 @@
 #endif
 	if (serial_paranoia_check(info, tty->device, "rs_open"))
 		return -ENODEV;
-	OPNDBG("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
-	       info->count);
+	OPNDBG("rs_open %s%d, count = %d, tty=%p\n", tty->driver.name,
+	       info->line, info->count, tty);
 
 	info->count++;
 	tty->driver_data = info;
@@ -2314,8 +2407,12 @@
 	zss->is_irda = conn && (strcmp(conn, "infrared") == 0);
 	/* 1999 Powerbook G3 has slot-names property instead */
 	slots = (struct slot_names_prop *)get_property(ch, "slot-names", &len);
-	if (slots && slots->count > 0 && strcmp(slots->name, "IrDA") == 0)
-		zss->is_irda = 1;
+	if (slots && slots->count > 0) {
+		if (strcmp(slots->name, "IrDA") == 0)
+			zss->is_irda = 1;
+		else if (strcmp(slots->name, "Modem") == 0)
+			zss->is_internal_modem = 1;
+	}
 
 	if (zss->has_dma) {
 		zss->dma_priv = NULL;
@@ -2564,6 +2661,8 @@
 			printk(", port = %s", connector);
 		if (info->is_cobalt_modem)
 			printk(" (cobalt modem)");
+		else if (info->is_internal_modem)
+			printk(" (internal modem)");
 		if (info->is_irda)
 			printk(" (IrDA)");
 		printk("\n");
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/macserial.h linux/drivers/macintosh/macserial.h
--- v2.4.1/linux/drivers/macintosh/macserial.h	Sat May 20 12:07:56 2000
+++ linux/drivers/macintosh/macserial.h	Sun Feb  4 10:21:25 2001
@@ -110,6 +110,7 @@
 	char break_abort;   /* Is serial console in, so process brk/abrt */
 	char kgdb_channel;  /* Kgdb is running on this channel */
 	char is_cons;       /* Is this our console. */
+	char is_internal_modem; /* is connected to an internal modem */
 	char is_cobalt_modem;	/* is a gatwick-based cobalt modem */
 	char is_irda;		/* is connected to an IrDA codec */
 	unsigned char tx_active; /* character is being xmitted */
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/rtc.c linux/drivers/macintosh/rtc.c
--- v2.4.1/linux/drivers/macintosh/rtc.c	Tue Sep 19 08:31:53 2000
+++ linux/drivers/macintosh/rtc.c	Fri Feb  9 11:30:23 2001
@@ -17,7 +17,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/via-pmu.c linux/drivers/macintosh/via-pmu.c
--- v2.4.1/linux/drivers/macintosh/via-pmu.c	Sat Nov 11 18:19:56 2000
+++ linux/drivers/macintosh/via-pmu.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/miscdevice.h>
 #include <linux/blkdev.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
@@ -166,12 +166,6 @@
 extern void sleep_save_intrs(int);
 extern void sleep_restore_intrs(void);
 
-extern int grackle_pcibios_read_config_word(unsigned char bus,
-	unsigned char dev_fn, unsigned char offset, unsigned short *val);
-
-extern int grackle_pcibios_write_config_word(unsigned char bus,
-	unsigned char dev_fn, unsigned char offset, unsigned short val);
-
 /*
  * This table indicates for each PMU opcode:
  * - the number of data bytes to be sent with the command, or -1
@@ -1336,6 +1330,11 @@
 	unsigned short pmcr1;
 	struct adb_request req;
 	int ret, timeout;
+	struct pci_dev *grackle;
+
+	grackle = pci_find_slot(0, 0);
+	if (!grackle)
+		return -ENODEV;
 
 	/* Notify device drivers */
 	ret = broadcast_sleep(PBOOK_SLEEP_REQUEST, PBOOK_SLEEP_REJECT);
@@ -1409,21 +1408,21 @@
 	/* We shut down some HW */
 	feature_prepare_for_sleep();
 
-	grackle_pcibios_read_config_word(0,0,0x70,&pmcr1);
+	pci_read_config_word(grackle, 0x70, &pmcr1);
 	/* Apparently, MacOS uses NAP mode for Grackle ??? */
 	pmcr1 &= ~(GRACKLE_DOZE|GRACKLE_SLEEP); 
 	pmcr1 |= GRACKLE_PM|GRACKLE_NAP;
-	grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
+	pci_write_config_word(grackle, 0x70, pmcr1);
 
 	/* Call low-level ASM sleep handler */
 	low_sleep_handler();
 
 	/* We're awake again, stop grackle PM */
-	grackle_pcibios_read_config_word(0, 0, 0x70, &pmcr1);
+	pci_read_config_word(grackle, 0x70, &pmcr1);
 	pmcr1 &= ~(GRACKLE_PM|GRACKLE_DOZE|GRACKLE_SLEEP|GRACKLE_NAP); 
-	grackle_pcibios_write_config_word(0, 0, 0x70, pmcr1);
-	
-	/* Restore things */
+	pci_write_config_word(grackle, 0x70, pmcr1);
+
+	/* Make sure the PMU is idle */
 	feature_wake_up();
 	restore_via_state();
 	
diff -u --recursive --new-file v2.4.1/linux/drivers/macintosh/via-pmu68k.c linux/drivers/macintosh/via-pmu68k.c
--- v2.4.1/linux/drivers/macintosh/via-pmu68k.c	Tue Feb 29 11:08:16 2000
+++ linux/drivers/macintosh/via-pmu68k.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/miscdevice.h>
 #include <linux/blkdev.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <linux/adb.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/md/linear.c linux/drivers/md/linear.c
--- v2.4.1/linux/drivers/md/linear.c	Mon Dec 11 13:19:35 2000
+++ linux/drivers/md/linear.c	Fri Feb  9 11:30:23 2001
@@ -19,7 +19,7 @@
 #include <linux/module.h>
 
 #include <linux/raid/md.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/raid/linear.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/md/md.c linux/drivers/md/md.c
--- v2.4.1/linux/drivers/md/md.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/md/md.c	Thu Feb  8 20:40:10 2001
@@ -61,6 +61,10 @@
 # define dprintk(x...) do { } while(0)
 #endif
 
+#ifndef MODULE
+static void autostart_arrays (void);
+#endif
+
 static mdk_personality_t *pers[MAX_PERSONALITY];
 
 /*
@@ -2030,70 +2034,6 @@
 #undef AUTOADDING
 #undef AUTORUNNING
 
-struct {
-	int set;
-	int noautodetect;
-} raid_setup_args md__initdata;
-
-void md_setup_drive (void) md__init;
-
-/*
- * Searches all registered partitions for autorun RAID arrays
- * at boot time.
- */
-static int detected_devices[128] md__initdata;
-static int dev_cnt;
-
-void md_autodetect_dev(kdev_t dev)
-{
-	if (dev_cnt >= 0 && dev_cnt < 127)
-		detected_devices[dev_cnt++] = dev;
-}
-
-
-static void autostart_arrays (void)
-{
-	mdk_rdev_t *rdev;
-	int i;
-
-	printk(KERN_INFO "autodetecting RAID arrays\n");
-
-	for (i=0; i<dev_cnt; i++) {
-		kdev_t dev = detected_devices[i];
-
-		if (md_import_device(dev,1)) {
-			printk(KERN_ALERT "could not import %s!\n",
-			       partition_name(dev));
-			continue;
-		}
-		/*
-		 * Sanity checks:
-		 */
-		rdev = find_rdev_all(dev);
-		if (!rdev) {
-			MD_BUG();
-			continue;
-		}
-		if (rdev->faulty) {
-			MD_BUG();
-			continue;
-		}
-		md_list_add(&rdev->pending, &pending_raid_disks);
-	}
-
-	autorun_devices(-1);
-}
-
-int md__init md_run_setup(void)
-{
-	if (raid_setup_args.noautodetect)
-		printk(KERN_INFO "skipping autodetection of RAID arrays\n");
-	else
-		autostart_arrays();
-	dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
-	md_setup_drive();
-	return 0;
-}
 
 static int get_version (void * arg)
 {
@@ -2555,10 +2495,12 @@
 			md_print_devices();
 			goto done_unlock;
 
+#ifndef MODULE
 		case RAID_AUTORUN:
 			err = 0;
 			autostart_arrays();
 			goto done;
+#endif
 
 		case BLKGETSIZE:   /* Return device size */
 			if (!arg) {
@@ -2590,7 +2532,7 @@
 			err = md_put_user (read_ahead[
 				MAJOR(dev)], (long *) arg);
 			goto done;
-		default:
+		default:;
 	}
 
 	/*
@@ -2609,7 +2551,7 @@
 				err = -EEXIST;
 				goto abort;
 			}
-		default:
+		default:;
 	}
 	switch (cmd)
 	{
@@ -2662,7 +2604,7 @@
 			}
 			goto done;
 
-		default:
+		default:;
 	}
 
 	/*
@@ -3556,30 +3498,7 @@
 	NULL,
 	0
 };
-#ifndef MODULE
-static int md__init raid_setup(char *str)
-{
-	int len, pos;
-
-	len = strlen(str) + 1;
-	pos = 0;
-
-	while (pos < len) {
-		char *comma = strchr(str+pos, ',');
-		int wlen;
-		if (comma)
-			wlen = (comma-str)-pos;
-		else	wlen = (len-1)-pos;
 
-		if (strncmp(str, "noautodetect", wlen) == 0)
-			raid_setup_args.noautodetect = 1;
-		pos += wlen+1;
-	}
-	raid_setup_args.set = 1;
-	return 1;
-}
-__setup("raid=", raid_setup);
-#endif
 static void md_geninit (void)
 {
 	int i;
@@ -3641,6 +3560,70 @@
 	return (0);
 }
 
+
+#ifndef MODULE
+
+/*
+ * When md (and any require personalities) are compiled into the kernel
+ * (not a module), arrays can be assembles are boot time using with AUTODETECT
+ * where specially marked partitions are registered with md_autodetect_dev(),
+ * and with MD_BOOT where devices to be collected are given on the boot line
+ * with md=.....
+ * The code for that is here.
+ */
+
+struct {
+	int set;
+	int noautodetect;
+} raid_setup_args md__initdata;
+
+/*
+ * Searches all registered partitions for autorun RAID arrays
+ * at boot time.
+ */
+static int detected_devices[128] md__initdata;
+static int dev_cnt;
+
+void md_autodetect_dev(kdev_t dev)
+{
+	if (dev_cnt >= 0 && dev_cnt < 127)
+		detected_devices[dev_cnt++] = dev;
+}
+
+
+static void autostart_arrays (void)
+{
+	mdk_rdev_t *rdev;
+	int i;
+
+	printk(KERN_INFO "autodetecting RAID arrays\n");
+
+	for (i=0; i<dev_cnt; i++) {
+		kdev_t dev = detected_devices[i];
+
+		if (md_import_device(dev,1)) {
+			printk(KERN_ALERT "could not import %s!\n",
+			       partition_name(dev));
+			continue;
+		}
+		/*
+		 * Sanity checks:
+		 */
+		rdev = find_rdev_all(dev);
+		if (!rdev) {
+			MD_BUG();
+			continue;
+		}
+		if (rdev->faulty) {
+			MD_BUG();
+			continue;
+		}
+		md_list_add(&rdev->pending, &pending_raid_disks);
+	}
+
+	autorun_devices(-1);
+}
+
 static struct {
 	char device_set [MAX_MD_DEVS];
 	int pers[MAX_MD_DEVS];
@@ -3665,6 +3648,7 @@
  *             elements in device-list are read by name_to_kdev_t so can be
  *             a hex number or something like /dev/hda1 /dev/sdb
  */
+#ifndef MODULE
 extern kdev_t name_to_kdev_t(char *line) md__init;
 static int md__init md_setup(char *str)
 {
@@ -3740,6 +3724,7 @@
 	md_setup_args.device_set[minor] = 1;
 	return 1;
 }
+#endif /* !MODULE */
 
 void md__init md_setup_drive(void)
 {
@@ -3807,9 +3792,47 @@
 	}
 }
 
+static int md__init raid_setup(char *str)
+{
+	int len, pos;
+
+	len = strlen(str) + 1;
+	pos = 0;
+
+	while (pos < len) {
+		char *comma = strchr(str+pos, ',');
+		int wlen;
+		if (comma)
+			wlen = (comma-str)-pos;
+		else	wlen = (len-1)-pos;
+
+		if (strncmp(str, "noautodetect", wlen) == 0)
+			raid_setup_args.noautodetect = 1;
+		pos += wlen+1;
+	}
+	raid_setup_args.set = 1;
+	return 1;
+}
+
+int md__init md_run_setup(void)
+{
+	if (raid_setup_args.noautodetect)
+		printk(KERN_INFO "skipping autodetection of RAID arrays\n");
+	else
+		autostart_arrays();
+	dev_cnt = -1; /* make sure further calls to md_autodetect_dev are ignored */
+	md_setup_drive();
+	return 0;
+}
+
+__setup("raid=", raid_setup);
 __setup("md=", md_setup);
 
-#ifdef MODULE
+__initcall(md_init);
+__initcall(md_run_setup);
+
+#else /* It is a MODULE */
+
 int init_module (void)
 {
 	return md_init();
@@ -3857,9 +3880,6 @@
 
 }
 #endif
-
-__initcall(md_init);
-__initcall(md_run_setup);
 
 MD_EXPORT_SYMBOL(md_size);
 MD_EXPORT_SYMBOL(register_md_personality);
diff -u --recursive --new-file v2.4.1/linux/drivers/md/raid1.c linux/drivers/md/raid1.c
--- v2.4.1/linux/drivers/md/raid1.c	Mon Dec 11 13:19:35 2000
+++ linux/drivers/md/raid1.c	Fri Feb  9 11:30:23 2001
@@ -23,7 +23,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/raid/raid1.h>
 #include <asm/atomic.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/md/raid5.c linux/drivers/md/raid5.c
--- v2.4.1/linux/drivers/md/raid5.c	Sat Feb  3 19:51:27 2001
+++ linux/drivers/md/raid5.c	Fri Feb  9 11:30:23 2001
@@ -19,7 +19,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/locks.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/raid/raid5.h>
 #include <asm/bitops.h>
 #include <asm/atomic.h>
@@ -381,7 +381,7 @@
 		if (bh == sh->bh_cache[i])
 			break;
 
-	PRINTK("end_read_request %lu/%d,  %d, count: %d, uptodate %d.\n", sh->sector, i, atomic_read(&sh->count), uptodate);
+	PRINTK("end_read_request %lu/%d, count: %d, uptodate %d.\n", sh->sector, i, atomic_read(&sh->count), uptodate);
 	if (i == disks) {
 		BUG();
 		return;
@@ -680,7 +680,6 @@
 
 	count = 1;
 	bh_ptr[0] = sh->bh_cache[pd_idx];
-	spin_lock_irq(&conf->device_lock);
 	switch(method) {
 	case READ_MODIFY_WRITE:
 		if (!buffer_uptodate(sh->bh_cache[pd_idx]))
@@ -707,13 +706,11 @@
 				sh->bh_write[i] = sh->bh_write[i]->b_reqnext;
 				chosen[i]->b_reqnext = sh->bh_written[i];
 				sh->bh_written[i] = chosen[i];
-				check_xor();
 			}
 		break;
 	case CHECK_PARITY:
 		break;
 	}
-	spin_unlock_irq(&conf->device_lock);
 	if (count>1) {
 		xor_block(count, bh_ptr);
 		count = 1;
@@ -723,7 +720,6 @@
 		if (chosen[i]) {
 			struct buffer_head *bh = sh->bh_cache[i];
 			char *bdata;
-			mark_buffer_clean(chosen[i]); /* NO FIXME */
 			bdata = bh_kmap(chosen[i]);
 			memcpy(bh->b_data,
 			       bdata,sh->size);
@@ -766,6 +762,7 @@
 	PRINTK("adding bh b#%lu to stripe s#%lu\n", bh->b_blocknr, sh->sector);
 
 
+	spin_lock(&sh->lock);
 	spin_lock_irq(&conf->device_lock);
 	bh->b_reqnext = NULL;
 	if (rw == READ)
@@ -778,6 +775,7 @@
 	}
 	*bhp = bh;
 	spin_unlock_irq(&conf->device_lock);
+	spin_unlock(&sh->lock);
 
 	PRINTK("added bh b#%lu to stripe s#%lu, disk %d.\n", bh->b_blocknr, sh->sector, dd_idx);
 }
@@ -827,7 +825,7 @@
 
 	for (i=disks; i--; ) {
 		bh = sh->bh_cache[i];
-		PRINTK("check %d: state %lx read %p write %p written %p\n", i, bh->b_state, sh->bh_read[i], sh->bh_write[i], sh->bh_written[i]);
+		PRINTK("check %d: state 0x%lx read %p write %p written %p\n", i, bh->b_state, sh->bh_read[i], sh->bh_write[i], sh->bh_written[i]);
 		/* maybe we can reply to a read */
 		if (buffer_uptodate(bh) && sh->bh_read[i]) {
 			struct buffer_head *rbh, *rbh2;
@@ -867,7 +865,6 @@
 	 * need to be failed
 	 */
 	if (failed > 1 && to_read+to_write) {
-		spin_lock_irq(&conf->device_lock);
 		for (i=disks; i--; ) {
 			/* fail all writes first */
 			if (sh->bh_write[i]) to_write--;
@@ -878,15 +875,16 @@
 			}
 			/* fail any reads if this device is non-operational */
 			if (!conf->disks[i].operational) {
+				spin_lock_irq(&conf->device_lock);
 				if (sh->bh_read[i]) to_read--;
 				while ((bh = sh->bh_read[i])) {
 					sh->bh_read[i] = bh->b_reqnext;
 					bh->b_reqnext = return_fail;
 					return_fail = bh;
 				}
+				spin_unlock_irq(&conf->device_lock);
 			}
 		}
-		spin_unlock_irq(&conf->device_lock);
 		if (syncing) {
 			md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,0);
 			clear_bit(STRIPE_SYNCING, &sh->state);
@@ -911,10 +909,8 @@
 			/* maybe we can return some write requests */
 			struct buffer_head *wbh, *wbh2;
 			PRINTK("Return write for disc %d\n", i);
-			spin_lock_irq(&conf->device_lock);
 			wbh = sh->bh_written[i];
 			sh->bh_written[i] = NULL;
-			spin_unlock_irq(&conf->device_lock);
 			while (wbh) {
 			    wbh2 = wbh->b_reqnext;
 			    wbh->b_reqnext = return_ok;
@@ -1076,7 +1072,7 @@
 		bh->b_end_io(bh, 1);
 	}
 	while ((bh=return_fail)) {
-		return_ok = bh->b_reqnext;
+		return_fail = bh->b_reqnext;
 		bh->b_reqnext = NULL;
 		bh->b_end_io(bh, 0);
 	}
@@ -1092,8 +1088,6 @@
 				bh->b_dev = conf->disks[i].dev;
 			else if (conf->spare && action[i] == WRITE+1)
 				bh->b_dev = conf->spare->dev;
-			else if (action[i] == READ+1)
-				BUG();
 			else skip=1;
 			if (!skip) {
 				PRINTK("for %ld schedule op %d on disc %d\n", sh->sector, action[i]-1, i);
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/Config.in linux/drivers/media/video/Config.in
--- v2.4.1/linux/drivers/media/video/Config.in	Wed Aug 23 14:59:55 2000
+++ linux/drivers/media/video/Config.in	Fri Feb 16 16:02:36 2001
@@ -23,7 +23,7 @@
 fi
 dep_tristate '  CPiA Video For Linux' CONFIG_VIDEO_CPIA $CONFIG_VIDEO_DEV
 if [ "$CONFIG_VIDEO_CPIA" != "n" ]; then
-  if [ "CONFIG_PARPORT_1284" != "n" ]; then
+  if [ "$CONFIG_PARPORT_1284" != "n" ]; then
     dep_tristate '    CPiA Parallel Port Lowlevel Support' CONFIG_VIDEO_CPIA_PP $CONFIG_VIDEO_CPIA $CONFIG_PARPORT
   fi
   if [ "$CONFIG_USB" != "n" ]; then
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/bttv-cards.c linux/drivers/media/video/bttv-cards.c
--- v2.4.1/linux/drivers/media/video/bttv-cards.c	Sat Dec 30 11:23:13 2000
+++ linux/drivers/media/video/bttv-cards.c	Mon Feb 19 14:43:36 2001
@@ -6,7 +6,7 @@
 
     Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
                            & Marcus Metzler (mocm@thp.uni-koeln.de)
-    (c) 1999,2000 Gerd Knorr <kraxel@goldbach.in-berlin.de>
+    (c) 1999-2001 Gerd Knorr <kraxel@goldbach.in-berlin.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
@@ -53,6 +53,7 @@
 
 /* config variables */
 static int triton1=0;
+int no_overlay=-1;
 static unsigned int card[4]  = { -1, -1, -1, -1 };
 static unsigned int pll[4]   = { -1, -1, -1, -1 };
 static unsigned int tuner[4] = { -1, -1, -1, -1 };
@@ -67,6 +68,7 @@
 
 /* insmod options */
 MODULE_PARM(triton1,"i");
+MODULE_PARM(no_overlay,"i");
 MODULE_PARM(card,"1-4i");
 MODULE_PARM_DESC(card,"specify TV/grabber card model, see CARDLIST file for a list");
 MODULE_PARM(pll,"1-4i");
@@ -115,10 +117,11 @@
 	{ 0x00031002, BTTV_HAUPPAUGE878,  "ATI TV Wonder/VE" },
 	{ 0x00031461, BTTV_AVPHONE98,     "AVerMedia TVPhone98" },
 	{ 0x00041461, BTTV_AVERMEDIA98,   "AVerMedia TVCapture 98" },
+	{ 0x010114c7, 16 /* FIXME */,     "Modular Technology PCTV" },
 	{ 0x10b42636, BTTV_HAUPPAUGE878,  "STB ???" },
 	{ 0x1118153b, BTTV_TERRATVALUE,   "Terratec TV Value" },
 	{ 0x1123153b, BTTV_TERRATVRADIO,  "Terratec TV/Radio+" },
-	{ 0x1200bd11, BTTV_PINNACLERAVE,  "Pinnacle PCTV Rave" },
+	{ 0x1200bd11, BTTV_PINNACLE,      "Pinnacle PCTV" },
 	{ 0x13eb0070, BTTV_HAUPPAUGE878,  "Hauppauge WinTV" },
 	{ 0x18501851, BTTV_CHRONOS_VS2,   "Chronos Video Shuttle II" },
 	{ 0x18521852, BTTV_TYPHOON_TVIEW, "Typhoon TView TV/FM Tuner" },
@@ -131,6 +134,7 @@
 	{ 0x300214ff, BTTV_PHOEBE_TVMAS,  "Phoebe TV Master" },
 	{ 0x39000070, BTTV_HAUPPAUGE878,  "Hauppauge WinTV-D" },
 	{ 0x400a15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV" },
+	{ 0x400d15b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
 	{ 0x401015b0, BTTV_ZOLTRIX_GENIE, "Zoltrix Genie TV / Radio" },
  	{ 0x402010fc, BTTV_GVBCTV3PCI,    "I-O Data Co. GV-BCV3/PCI" },
 	{ 0xff000070, BTTV_HAUPPAUGE878,  "Osprey-100" },
@@ -219,12 +223,16 @@
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		3,
+	/* old 
 	gpiomask:	15,
-	muxsel:		{ 2, 3, 1, 1},
 	audiomux:	{12, 4,11,11, 0},
+	*/
+	muxsel:		{ 2, 3, 1, 1},
+	gpiomask:	0x0f,
+	audiomux:	{ 0x04, 0x04, 0x08, 0x04, 0},
 	needs_tvaudio:	1,
-	pll:		PLL_28,
 	tuner_type:	-1,
+	audio_hook:	avermedia_tvphone_audio,
 },{
 	name:		"MATRIX-Vision MV-Delta",
 	video_inputs:	5,
@@ -278,9 +286,9 @@
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		2,
-	gpiomask:	65551,
+	gpiomask:	0x3000f,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{1,65537, 0, 0,10},
+	audiomux:	{ 1,0x10001, 0, 0,10},
 	needs_tvaudio:	1,
 	tuner_type:	-1,
 },{
@@ -421,8 +429,8 @@
 	muxsel:		{ 2, 3 },
 	audiomux:	{ 0, 0, 0, 0, 0 },
 	no_msp34xx:	1,
-	needs_tvaudio:	1,
-	tuner_type:	-1,
+	pll:            PLL_28,
+	tuner_type:     TUNER_ALPS_TSBB5_PAL_I,
 },{
 
 /* ---- card 0x18 ---------------------------------- */
@@ -480,16 +488,17 @@
 	svhs:		2,
 	gpiomask:	0x70000,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 0x20000, 0x30000, 0x00000, 0x10000, 0x40000},
+	audiomux:	{ 0x20000, 0x30000, 0x10000, 0x00000, 0x40000},
 	needs_tvaudio:	1,
 	tuner_type:	-1,
 	audio_hook:	terratv_audio,
 },{
+	/* Jannik Fritsch <jannik@techfak.uni-bielefeld.de> */
 	name:		"Imagenation PXC200",
 	video_inputs:	5,
 	audio_inputs:	1,
 	tuner:		-1,
-	svhs:		4,
+	svhs:		1, /* was: 4 */
 	gpiomask:	0,
 	muxsel:		{ 2, 3, 1, 0, 0},
 	audiomux:	{ 0 },
@@ -539,7 +548,8 @@
 	muxsel:		{ 2, 3, 1, 1},
 	audiomux:	{ 0x500, 0, 0x300, 0x900, 0x900},
 	needs_tvaudio:	1,
-	tuner_type:	-1,
+	pll:		PLL_28,
+	tuner_type:	TUNER_PHILIPS_PAL,
 },{
 	name:		"Leadtek WinFast 2000",
 	video_inputs:	3,
@@ -603,7 +613,7 @@
 	pll:		PLL_28,
 	tuner_type:	-1,
 },{
-	name:		"Pinnacle PCTV Rave",
+	name:		"Pinnacle PCTV Studio/Rave",
 	video_inputs:	3,
 	audio_inputs:	1,
 	tuner:		0,
@@ -636,11 +646,10 @@
 	svhs:		2,
 	gpiomask:	12,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 13, 14, 11, 7, 0, 0},
+	audiomux:	{ 13, 4, 11, 7, 0, 0},
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	5,
-	audio_hook:	avermedia_tvphone_audio,
 },{
 	name:		"ProVideo PV951", /* pic16c54 */
 	video_inputs:	3,
@@ -691,17 +700,17 @@
 	pll:		PLL_28,
 	tuner_type:	-1,
 },{
-	name:		"Zoltrix Genie TV",
+	name:		"Zoltrix Genie TV/FM",
 	video_inputs:	3,
 	audio_inputs:	1,
 	tuner:		0,
 	svhs:		2,
 	gpiomask:	0xbcf03f,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 0xbc803f, 0, 0xbcb03f, 0, 0xbcb03f},
+	audiomux:	{ 0xbc803f, 0xbc903f, 0xbcb03f, 0, 0xbcb03f},
 	no_msp34xx:	1,
 	pll:		PLL_28,
-	tuner_type:	5,
+	tuner_type:	21,
 },{
 	name:		"Terratec TV/Radio+",
 	video_inputs:	3,
@@ -767,29 +776,105 @@
 },{
 
 /* ---- card 0x34 ---------------------------------- */
-	name:           "Pinnacle Studio PCTV Pro", /* David Härdeman <david@2gen.com> */
+	/* David Härdeman <david@2gen.com> */
+	name:           "Pinnacle PCTV Studio Pro",
 	video_inputs:   3,
 	audio_inputs:   1,
 	tuner:          0,
 	svhs:           2,
 	gpiomask:       0x03000F,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 1, 65537, 0, 0, 10},
+	audiomux:	{ 1, 0x10001, 0, 0, 10},
 	needs_tvaudio:  1,
 	pll:            PLL_28,
 	tuner_type:     -1,
 },{
-	name:		"Typhoon TView RDS", /* Claas Langbehn <claas@bigfoot.com> */
+	/* Claas Langbehn <claas@bigfoot.com>,
+	   Sven Grothklags <sven@upb.de> */
+	name:		"Typhoon TView RDS / FM Stereo",
 	video_inputs:	3,
 	audio_inputs:	3,
 	tuner:		0,
 	svhs:		2,
-	gpiomask:	0xffff,
+	gpiomask:	0x1c,
 	muxsel:		{ 2, 3, 1, 1},
-	audiomux:	{ 0xb002, 0, 0x12, 0x12, 0x3007 },
+	audiomux:	{ 0, 0, 0x10, 8, 4 },
 	needs_tvaudio:	1,
 	pll:		PLL_28,
 	tuner_type:	TUNER_PHILIPS_PAL_I,
+},{
+	/* Tim Röstermundt <rosterm@uni-muenster.de>
+	   in de.comp.os.unix.linux.hardware:
+		options bttv card=0 pll=1 radio=1 gpiomask=0x18e0
+		audiomux=0x44c71f,0x44d71f,0,0x44d71f,0x44dfff
+		options tuner type=5 */
+	name:		"Livetec 9415 TV",
+	video_inputs:	4,
+	audio_inputs:	1,
+	tuner:		0,
+	svhs:		2,
+	gpiomask:	0x18e0,
+	muxsel:		{ 2, 3, 1, 1},
+	audiomux:	{ 0x0000,0x0800,0x1000,0x1000,0x18e0 },
+	pll:		PLL_28,
+	tuner_type:	TUNER_PHILIPS_PAL,
+},{
+	/* Miguel Angel Alvarez <maacruz@navegalia.com> */
+	name:           "BESTBUY Easy TV",
+	video_inputs:	4,
+	audio_inputs:   1,
+	tuner:          0,
+	svhs:           2,
+	gpiomask:       0xF,
+	muxsel:         { 2, 3, 1, 0},
+	audiomux:       { 2, 0, 0, 0, 10},
+	needs_tvaudio:  0,
+	pll:		PLL_28,
+	tuner_type:	TUNER_TEMIC_PAL_I,
+},{
+
+/* ---- card 0x38 ---------------------------------- */
+	/* Gordon Heydon <gjheydon@bigfoot.com */
+	name:           "FlyVideo '98/FM",
+	video_inputs:   3,
+	audio_inputs:   3,
+	tuner:          0,
+	svhs:           2,
+	gpiomask:       0x1800,
+	muxsel:         { 2, 3, 1, 1},
+	audiomux:       { 0, 0x800, 0, 0, 0x1800, 0 },
+	needs_tvaudio:  1,
+	pll:            PLL_28,
+	tuner_type:     -1,
+},{
+	/* This is the ultimate cheapo capture card 
+	 * just a BT848A on a small PCB!
+	 * Steve Hosgood <steve@equiinet.com> */
+	name:           "GrandTec 'Grand Video Capture'",
+	video_inputs:   2,
+	audio_inputs:   0,
+	tuner:          -1,
+	svhs:           1,
+	gpiomask:       0,
+	muxsel:         { 3, 1 },
+	audiomux:       { 0 },
+	needs_tvaudio:  0,
+	no_msp34xx:     1,
+	pll:            PLL_35,
+	tuner_type:     -1,
+},{
+        /* Daniel Herrington <daniel.herrington@home.com> */
+        name:           "Phoebe TV Master Only (No FM)",
+        video_inputs:   3,
+        audio_inputs:   1,
+        tuner:          0,
+        svhs:           2,
+        gpiomask:       0x0e00,
+        muxsel:         { 2, 3, 1, 1},
+        audiomux:       { 0x400, 0x400, 0x400, 0x400, 0x800, 0x400 },
+        needs_tvaudio:  1,
+        pll:            PLL_NONE,
+        tuner_type:     TUNER_TEMIC_4036FY5_NTSC,
 }};
 
 const int bttv_num_tvcards = (sizeof(bttv_tvcards)/sizeof(struct tvcard));
@@ -876,32 +961,76 @@
 /*
  * (most) board specific initialisations goes here
  */
+
+int miro_tunermap[] = { 0,6,2,3,   4,5,6,0,  3,0,4,5,  5,2,16,1,
+			14,2,17,1, 4,1,4,3,  1,2,16,1, 4,4,4,4 };
+int miro_fmtuner[]  = { 0,0,0,0,   0,0,0,0,  0,0,0,0,  0,0,0,1,
+			1,1,1,1,   1,1,1,0,  0,0,0,0,  0,0,0,0 };
+
 void __devinit bttv_init_card(struct bttv *btv)
 {
-	int eeprom = 0;
-
-        if (btv->type == BTTV_MIRO || btv->type == BTTV_MIROPRO) {
-                /* auto detect tuner for MIRO cards */
-                btv->tuner_type=((btread(BT848_GPIO_DATA)>>10)-1)&7;
+	/* miro/pinnacle */
+        if (btv->type == BTTV_MIRO      ||
+	    btv->type == BTTV_MIROPRO   ||
+	    btv->type == BTTV_PINNACLE  ||
+	    btv->type == BTTV_PINNACLEPRO) {
+		int id,msp;
+		id  = ((btread(BT848_GPIO_DATA)>>10) & 31) -1;
+		msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx");
+		btv->tuner_type = miro_tunermap[id];
+		if (0 == (btread(BT848_GPIO_DATA) & 0x20)) {
+			btv->has_radio = 1;
+			if (!miro_fmtuner[id]) {
+				btv->has_matchbox = 1;
+				btv->mbox_we    = (1<<6);
+				btv->mbox_most  = (1<<7);
+				btv->mbox_clk   = (1<<8);
+				btv->mbox_data  = (1<<9);
+				btv->mbox_mask  = (1<<6)|(1<<7)|(1<<8)|(1<<9);
+			}
+		} else {
+			btv->has_radio = 0;
+		}
+		if (-1 != msp) {
+			if (btv->type == BTTV_MIRO)
+				btv->type = BTTV_MIROPRO;
+			if (btv->type == BTTV_PINNACLE)
+				btv->type = BTTV_PINNACLEPRO;
+		}
+		if (bttv_verbose)
+			printk("bttv%d: miro: id=%d tuner=%d radio=%s stereo=%s\n",
+			       btv->nr, id+1, btv->tuner_type,
+			       !btv->has_radio ? "no" :
+				   (btv->has_matchbox ? "matchbox" : "fmtuner"),
+			       (-1 == msp) ? "no" : "yes");
 #if 0
-		if (btv->type == BTTV_MIROPRO) {
+		if (btv->has_matchbox) {
 			if (bttv_verbose)
 				printk(KERN_INFO "Initializing TEA5757...\n");
 			init_tea5757(btv);
 		}
 #endif
-        }
+	}
+
         if (btv->type == BTTV_HAUPPAUGE || btv->type == BTTV_HAUPPAUGE878) {
 		/* pick up some config infos from the eeprom */
-		if (0xa0 != eeprom) {
-			eeprom = 0xa0;
-			bttv_readee(btv,eeprom_data,0xa0);
-		}
+		bttv_readee(btv,eeprom_data,0xa0);
                 hauppauge_eeprom(btv);
         }
+
  	if (btv->type == BTTV_PXC200)
 		init_PXC200(btv);
 
+	if (btv->type == BTTV_VHX) {
+		btv->has_radio    = 1;
+		btv->has_matchbox = 1;
+		btv->mbox_we      = 0x20;
+		btv->mbox_most    = 0;
+		btv->mbox_clk     = 0x08;
+		btv->mbox_data    = 0x10;
+		btv->mbox_mask    = 0x38;
+	}
+
 	/* pll configuration */
         if (!(btv->id==848 && btv->revision==0x11)) {
 		/* defaults from card list */
@@ -985,59 +1114,80 @@
         { TUNER_ABSENT,        "" },
         { TUNER_ABSENT,        "External" },
         { TUNER_ABSENT,        "Unspecified" },
-        { TUNER_ABSENT,        "Philips FI1216" },
+        { TUNER_PHILIPS_PAL,   "Philips FI1216" },
         { TUNER_PHILIPS_SECAM, "Philips FI1216MF" },
         { TUNER_PHILIPS_NTSC,  "Philips FI1236" },
-        { TUNER_ABSENT,        "Philips FI1246" },
-        { TUNER_ABSENT,        "Philips FI1256" },
+        { TUNER_PHILIPS_PAL_I, "Philips FI1246" },
+        { TUNER_PHILIPS_PAL_DK,"Philips FI1256" },
         { TUNER_PHILIPS_PAL,   "Philips FI1216 MK2" },
         { TUNER_PHILIPS_SECAM, "Philips FI1216MF MK2" },
         { TUNER_PHILIPS_NTSC,  "Philips FI1236 MK2" },
         { TUNER_PHILIPS_PAL_I, "Philips FI1246 MK2" },
-        { TUNER_ABSENT,        "Philips FI1256 MK2" },
-        { TUNER_ABSENT,        "Temic 4032FY5" },
+        { TUNER_PHILIPS_PAL_DK,"Philips FI1256 MK2" },
+        { TUNER_TEMIC_NTSC,    "Temic 4032FY5" },
         { TUNER_TEMIC_PAL,     "Temic 4002FH5" },
         { TUNER_TEMIC_PAL_I,   "Temic 4062FY5" },
-        { TUNER_ABSENT,        "Philips FR1216 MK2" },
+        { TUNER_PHILIPS_PAL,   "Philips FR1216 MK2" },
         { TUNER_PHILIPS_SECAM, "Philips FR1216MF MK2" },
         { TUNER_PHILIPS_NTSC,  "Philips FR1236 MK2" },
         { TUNER_PHILIPS_PAL_I, "Philips FR1246 MK2" },
-        { TUNER_ABSENT,        "Philips FR1256 MK2" },
+        { TUNER_PHILIPS_PAL_DK,"Philips FR1256 MK2" },
         { TUNER_PHILIPS_PAL,   "Philips FM1216" },
-        { TUNER_ABSENT,        "Philips FM1216MF" },
+        { TUNER_PHILIPS_SECAM, "Philips FM1216MF" },
         { TUNER_PHILIPS_NTSC,  "Philips FM1236" },
         { TUNER_PHILIPS_PAL_I, "Philips FM1246" },
-        { TUNER_ABSENT,        "Philips FM1256" },
-        { TUNER_TEMIC_4036FY5_NTSC,  "Temic 4036FY5" },
+        { TUNER_PHILIPS_PAL_DK,"Philips FM1256" },
+        { TUNER_TEMIC_4036FY5_NTSC, "Temic 4036FY5" },
         { TUNER_ABSENT,        "Samsung TCPN9082D" },
         { TUNER_ABSENT,        "Samsung TCPM9092P" },
-        { TUNER_TEMIC_PAL,     "Temic 4006FH5" },
+        { TUNER_TEMIC_4006FH5_PAL, "Temic 4006FH5" },
         { TUNER_ABSENT,        "Samsung TCPN9085D" },
         { TUNER_ABSENT,        "Samsung TCPB9085P" },
         { TUNER_ABSENT,        "Samsung TCPL9091P" },
-        { TUNER_ABSENT,        "Temic 4039FR5" },
-        { TUNER_ABSENT,        "Philips FQ1216 ME" },
-        { TUNER_TEMIC_PAL_I,   "Temic 4066FY5" },
+        { TUNER_TEMIC_4039FR5_NTSC, "Temic 4039FR5" },
+        { TUNER_PHILIPS_FQ1216ME,   "Philips FQ1216 ME" },
+        { TUNER_TEMIC_4066FY5_PAL_I, "Temic 4066FY5" },
         { TUNER_ABSENT,        "Philips TD1536" },
         { TUNER_ABSENT,        "Philips TD1536D" },
         { TUNER_ABSENT,        "Philips FMR1236" },
         { TUNER_ABSENT,        "Philips FI1256MP" },
         { TUNER_ABSENT,        "Samsung TCPQ9091P" },
-        { TUNER_ABSENT,        "Temic 4006FN5" },
-        { TUNER_ABSENT,        "Temic 4009FR5" },
-        { TUNER_ABSENT,        "Temic 4046FM5" },
+        { TUNER_TEMIC_4006FN5_MULTI_PAL, "Temic 4006FN5" },
+        { TUNER_TEMIC_4009FR5_PAL, "Temic 4009FR5" },
+        { TUNER_TEMIC_4046FM5,     "Temic 4046FM5" },
+	{ TUNER_ABSENT,        "Temic 4009FN5" },
+	{ TUNER_ABSENT,        "Philips TD1536D_FH_44"},
+	{ TUNER_ABSENT,	       "LG TP18NSR01F"},
+	{ TUNER_ABSENT,        "LG TP18PSB01D"},
+	{ TUNER_ABSENT,        "LG TP18PSB11D"},	
+	{ TUNER_ABSENT,        "LG TAPC_l001D"},
+	{ TUNER_ABSENT,        "LG TAPC_l701D"}
 };
 
 static void __devinit hauppauge_eeprom(struct bttv *btv)
 {
-        if (eeprom_data[9] < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER)) 
-        {
-                btv->tuner_type = hauppauge_tuner[eeprom_data[9]].id;
-		if (bttv_verbose)
-			printk("bttv%d: Hauppauge eeprom: model=%d, tuner=%s (%d)\n",btv->nr,
-			       eeprom_data[12] << 8 | eeprom_data[11],
-			       hauppauge_tuner[eeprom_data[9]].name,btv->tuner_type);
-        }
+	int blk2,tuner,radio,model;
+
+	if (eeprom_data[0] != 0x84 || eeprom_data[2] != 0)
+		printk("bttv%d: Hauppauge eeprom: invalid\n",btv->nr);
+
+	/* Block 2 starts after len+3 bytes header */
+	blk2 = eeprom_data[1] + 3;
+
+	/* decode + use some config infos */
+	model = eeprom_data[12] << 8 | eeprom_data[11];
+	tuner = eeprom_data[9];
+	radio = eeprom_data[blk2-1] & 0x01;
+	
+        if (tuner < sizeof(hauppauge_tuner)/sizeof(struct HAUPPAUGE_TUNER))
+                btv->tuner_type = hauppauge_tuner[tuner].id;
+	if (radio)
+		btv->has_radio = 1;
+	
+	if (bttv_verbose)
+		printk("bttv%d: Hauppauge eeprom: model=%d, tuner=%s (%d), radio=%s\n",
+		       btv->nr, model, hauppauge_tuner[tuner].name,
+		       btv->tuner_type, radio ? "yes" : "no");
 }
 
 void __devinit bttv_hauppauge_boot_msp34xx(struct bttv *btv)
@@ -1117,15 +1267,17 @@
  * Brutally hacked by Dan Sheridan <dan.sheridan@contact.org.uk> djs52 8/3/00
  */
 
+#if 0
 /* bus bits on the GPIO port */
 #define TEA_WE			6
 #define TEA_DATA		9
 #define TEA_CLK			8
 #define TEA_MOST		7
+#endif
 
-#define BUS_LOW(bit) 	btand(~(1<<TEA_##bit), BT848_GPIO_DATA)
-#define BUS_HIGH(bit)	btor((1<<TEA_##bit), BT848_GPIO_DATA)
-#define BUS_IN(bit)	((btread(BT848_GPIO_DATA) >> TEA_##bit) & 1)
+#define BUS_LOW(bit) 	btand(~(bit), BT848_GPIO_DATA)
+#define BUS_HIGH(bit)	btor((bit), BT848_GPIO_DATA)
+#define BUS_IN(bit)	(btread(BT848_GPIO_DATA) & (bit))
 
 /* TEA5757 register bits */
 #define TEA_FREQ		0:14
@@ -1155,93 +1307,83 @@
 #define TEA_STATUS_SEARCHING	1
 
 /* Low-level stuff */
-static int tea_read(struct bttv *btv)
+static int tea5757_read(struct bttv *btv)
 {
 	int value = 0;
 	long timeout;
 	int i;
 	
 	/* better safe than sorry */
-	btaor((1<<TEA_CLK) | (1<<TEA_WE), ~((1<<TEA_CLK) | (1<<TEA_DATA) | (1<<TEA_WE) | (1<<TEA_MOST)), BT848_GPIO_OUT_EN);
+	btaor((btv->mbox_clk | btv->mbox_we),
+	      ~btv->mbox_mask, BT848_GPIO_OUT_EN);
 	if (bttv_gpio)
-		bttv_gpio_tracking(btv,"miro tea read");
+		bttv_gpio_tracking(btv,"tea5757 read");
 	
-	BUS_LOW(WE);
-	BUS_LOW(CLK);
+	BUS_LOW(btv->mbox_we);
+	BUS_LOW(btv->mbox_clk);
 	
 	udelay(10);
 	for(timeout = jiffies + 10 * HZ;
-	    BUS_IN(DATA) == 1 && time_before(jiffies, timeout);
+	    BUS_IN(btv->mbox_data) && time_before(jiffies, timeout);
 	    schedule());	/* 10 s */
-	if (BUS_IN(DATA) == 1) {
-		printk("tea5757: read timeout\n");
+	if (BUS_IN(btv->mbox_data)) {
+		printk("bttv%d: tea5757: read timeout\n",btv->nr);
 		return -1;
 	}
 	for(timeout = jiffies + HZ/5;
-	    BUS_IN(MOST) == 1 && time_before(jiffies, timeout);
+	    BUS_IN(btv->mbox_data) == 1 && time_before(jiffies, timeout);
 	    schedule());	/* 0.2 s */
-	if (bttv_debug) printk("tea5757:");
+	dprintk("bttv%d: tea5757:",btv->nr);
 	for(i = 0; i < 24; i++)
 	{
-		udelay(10);
-		BUS_HIGH(CLK);
-		udelay(10);
-		if (bttv_debug) printk("%c", (BUS_IN(MOST) == 0)?'T':'-');
-		BUS_LOW(CLK);
-		value <<= 1;					
-		value |= (BUS_IN(DATA) == 0)?0:1;	/* MSB first */
-		if (bttv_debug) printk("%c", (BUS_IN(MOST) == 0)?'S':'M');
+		udelay(5);
+		BUS_HIGH(btv->mbox_clk);
+		udelay(5);
+		dprintk("%c",(BUS_IN(btv->mbox_most) == 0)?'T':'-');
+		BUS_LOW(btv->mbox_clk);
+		value <<= 1;
+		value |= (BUS_IN(btv->mbox_data) == 0)?0:1;  /* MSB first */
+		dprintk("%c", (BUS_IN(btv->mbox_most) == 0)?'S':'M');
 	}
-	if (bttv_debug) printk("\ntea5757: read 0x%X\n", value);
+	dprintk("\nbttv%d: tea5757: read 0x%X\n", btv->nr, value);
 	return value;
 }
 
-static int tea_write(struct bttv *btv, int value)
+static int tea5757_write(struct bttv *btv, int value)
 {
 	int i;
 	int reg = value;
 	
-	btaor((1<<TEA_CLK) | (1<<TEA_WE) | (1<<TEA_DATA), ~((1<<TEA_CLK) | (1<<TEA_DATA) | (1<<TEA_WE) | (1<<TEA_MOST)), BT848_GPIO_OUT_EN);
+	btaor(btv->mbox_clk | btv->mbox_we | btv->mbox_data,
+	      ~btv->mbox_mask, BT848_GPIO_OUT_EN);
 	if (bttv_gpio)
-		bttv_gpio_tracking(btv,"miro tea write");
-	if (bttv_debug)
-		printk("tea5757: write 0x%X\n", value);
-	BUS_LOW(CLK);
-	BUS_HIGH(WE);
+		bttv_gpio_tracking(btv,"tea5757 write");
+	dprintk("bttv%d: tea5757: write 0x%X\n", btv->nr, value);
+	BUS_LOW(btv->mbox_clk);
+	BUS_HIGH(btv->mbox_we);
 	for(i = 0; i < 25; i++)
 	{
 		if (reg & 0x1000000)
-			BUS_HIGH(DATA);
+			BUS_HIGH(btv->mbox_data);
 		else
-			BUS_LOW(DATA);
+			BUS_LOW(btv->mbox_data);
 		reg <<= 1;
-		BUS_HIGH(CLK);
+		BUS_HIGH(btv->mbox_clk);
 		udelay(10);
-		BUS_LOW(CLK);
+		BUS_LOW(btv->mbox_clk);
 		udelay(10);
 	}
-	BUS_LOW(WE);	/* unmute !!! */
+	BUS_LOW(btv->mbox_we);  /* unmute !!! */
 	return 0;
 }
 
 void tea5757_set_freq(struct bttv *btv, unsigned short freq)
 {
-	tea_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
-	if (bttv_debug) tea_read(btv);
+	tea5757_write(btv, 5 * freq + 0x358); /* add 10.7MHz (see docs) */
+	if (bttv_debug)
+		tea5757_read(btv);
 }
 
-#if 0
-void init_tea5757(struct bttv *btv)
-{
-	BUS_LOW(CLK);
-	BUS_LOW(WE); /* just to be on the safe side... */
-
-	/* software CLK (unused) */
-	btaor(0, BT848_GPIO_DMA_CTL_GPCLKMODE, BT848_GPIO_DMA_CTL);
-	/* normal mode for GPIO */
-	btaor(0, BT848_GPIO_DMA_CTL_GPIOMODE, BT848_GPIO_DMA_CTL);
-}
-#endif
 
 /* ----------------------------------------------------------------------- */
 /* winview                                                                 */
@@ -1297,7 +1439,7 @@
 	unsigned int con = 0;
 
 	if (set) {
-		btor(0x100, BT848_GPIO_OUT_EN);
+		btor(0x300, BT848_GPIO_OUT_EN);
 		if (v->mode & VIDEO_SOUND_LANG1)
 			con = 0x000;
 		if (v->mode & VIDEO_SOUND_LANG2)
@@ -1322,21 +1464,22 @@
  *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
  *  input/output sound connection, so both must be set for output mode.
  *
+ * Looks like it's needed only for the "tvphone", the "tvphone 98"
+ * handles this with a tda9840
+ *
  */
 static void
 avermedia_tvphone_audio(struct bttv *btv, struct video_audio *v, int set)
 {
-#if 0 /* needs more testing -- might be we need two versions for PAL/NTSC */
 	int val = 0;
 
 	if (set) {
 		if (v->mode & VIDEO_SOUND_LANG1)   /* SAP */
-			val = 0xce;
+			val = 0x02;
 		if (v->mode & VIDEO_SOUND_STEREO)
-			val = 0xcd;
+			val = 0x01;
 		if (val) {
-			btaor(val, 0xff, BT848_GPIO_OUT_EN);
-			btaor(val, 0xff, BT848_GPIO_DATA);
+			btaor(val, ~0x03, BT848_GPIO_DATA);
 			if (bttv_gpio)
 				bttv_gpio_tracking(btv,"avermedia");
 		}
@@ -1345,7 +1488,6 @@
 			VIDEO_SOUND_LANG1;
 		return;
 	}
-#endif
 }
 
 static void
@@ -1372,27 +1514,31 @@
 /* ----------------------------------------------------------------------- */
 /* motherboard chipset specific stuff                                      */
 
-static struct {
-	char            *name;
-	unsigned short  vendor;
-	unsigned short  device;
-} needs_etbf[] __devinitdata = {
-	{ "Intel 82437FX [Triton PIIX]",
-	  PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82437  },
-	{ "VIA VT82C597 [Apollo VP3]",
-	  PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0 },
-	{ NULL, 0, 0 }
-};
-
 void __devinit bttv_check_chipset(void)
 {
-	int i;
+	int pcipci_fail = 0;
 	struct pci_dev *dev = NULL;
 
-	if(pci_pci_problems & PCIPCI_FAIL)
-		printk(KERN_WARNING "BT848 and your chipset may not work together.\n");
+	/* for 2.4.x we'll use the pci quirks (drivers/pci/quirks.c) */
+	if (pci_pci_problems & PCIPCI_FAIL)
+		pcipci_fail = 1;
+
+	if (pci_pci_problems & (PCIPCI_TRITON|PCIPCI_NATOMA|PCIPCI_VIAETBF))
+		triton1 = 1;
 
-        while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+	/* print warnings about quirks found */
+	if (triton1)
+		printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
+
+	if (pcipci_fail) {
+		printk(KERN_WARNING "bttv: BT848 and your chipset may not work together.\n");
+		if (-1 == no_overlay) {
+			printk(KERN_WARNING "bttv: going to disable overlay.\n");
+			no_overlay = 1;
+		}
+	}
+
+	while ((dev = pci_find_device(PCI_VENDOR_ID_INTEL,
 				      PCI_DEVICE_ID_INTEL_82441, dev))) {
                 unsigned char b;
                 pci_read_config_byte(dev, 0x53, &b);
@@ -1401,11 +1547,6 @@
 			       "bufcon=0x%02x\n",b);
 	}
 
-	if(pci_pci_problems & (PCIPCI_TRITON|PCIPCI_VIAETBF))
-	{
-		printk(KERN_INFO "bttv: Host bridge needs ETBF enabled.\n");
-		triton1=1;
-	}
 }
 
 int __devinit bttv_handle_chipset(struct bttv *btv)
@@ -1435,24 +1576,6 @@
 	return 0;
 }
 
-
-#ifndef MODULE
-
-static int __init bttv_card_setup(char *str)
-{
-	int i,number,res = 2;
-
-	for (i = 0; res == 2 && i < BTTV_MAX; i++) {
-		res = get_option(&str,&number);
-		if (res)
-			card[i] = number;
-	}
-	return 1;
-}
-
-__setup("bttv_card=", bttv_card_setup);
-
-#endif /* not MODULE */
 
 /*
  * Local variables:
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/bttv-driver.c linux/drivers/media/video/bttv-driver.c
--- v2.4.1/linux/drivers/media/video/bttv-driver.c	Sat Dec 30 11:23:13 2000
+++ linux/drivers/media/video/bttv-driver.c	Mon Feb 19 14:43:36 2001
@@ -27,7 +27,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/poll.h>
 #include <linux/pci.h>
@@ -253,29 +253,6 @@
 	return 0;
 }
 
-
-/* init + register i2c algo-bit adapter */
-static int __devinit init_bttv_i2c(struct bttv *btv)
-{
-	memcpy(&btv->i2c_adap, &bttv_i2c_adap_template, sizeof(struct i2c_adapter));
-	memcpy(&btv->i2c_algo, &bttv_i2c_algo_template, sizeof(struct i2c_algo_bit_data));
-	memcpy(&btv->i2c_client, &bttv_i2c_client_template, sizeof(struct i2c_client));
-
-	sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name),
-		" #%d", btv->nr);
-        btv->i2c_algo.data = btv;
-        btv->i2c_adap.data = btv;
-        btv->i2c_adap.algo_data = &btv->i2c_algo;
-        btv->i2c_client.adapter = &btv->i2c_adap;
-
-	bttv_bit_setscl(btv,1);
-	bttv_bit_setsda(btv,1);
-
-	btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
-	return btv->i2c_rc;
-}
-
-
 /* ----------------------------------------------------------------------- */
 
 void bttv_gpio_tracking(struct bttv *btv, char *comment)
@@ -1589,8 +1566,10 @@
 		struct video_tuner v;
 		if(copy_from_user(&v,arg,sizeof(v))!=0)
 			return -EFAULT;
+#if 0 /* tuner.signal might be of intrest for non-tuner sources too ... */
 		if(v.tuner||btv->channel)	/* Only tuner 0 */
 			return -EINVAL;
+#endif
 		strcpy(v.name, "Television");
 		v.rangelow=0;
 		v.rangehigh=0xFFFFFFFF;
@@ -1753,6 +1732,8 @@
 			return -EINVAL;
 		if (btv->win.width==0 || btv->win.height==0)
 			return -EINVAL;
+		if (1 == no_overlay)
+			return -EIO;
 		spin_lock_irqsave(&btv->s_lock, irq_flags);
 		if (v == 1 && btv->win.vidadr != 0)
 			btv->scr_on = 1;
@@ -1796,14 +1777,18 @@
 		btv->win.depth=v.depth;
 		btv->win.bpl=v.bytesperline;
 
+#if 0 /* was broken for ages and nobody noticed.  Looks like we don't need
+	 it any more as everybody explicitly sets the palette using VIDIOCSPICT
+	 these days */
 		/* set sefault color format */
-		switch (btv->win.bpp) {
+		switch (v.depth) {
 		case  8: btv->picture.palette = VIDEO_PALETTE_HI240;  break;
 		case 15: btv->picture.palette = VIDEO_PALETTE_RGB555; break;
 		case 16: btv->picture.palette = VIDEO_PALETTE_RGB565; break;
 		case 24: btv->picture.palette = VIDEO_PALETTE_RGB24;  break;
 		case 32: btv->picture.palette = VIDEO_PALETTE_RGB32;  break;
 		}
+#endif
 	
 		if (bttv_debug)
 			printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n",
@@ -1833,8 +1818,8 @@
 			return -EFAULT;
 		btv->win.freq=v;
 		bttv_call_i2c_clients(btv,cmd,&v);
-#if 0
-		if (btv->type == BTTV_MIROPRO && btv->radio)
+#if 1
+		if (btv->radio && btv->has_matchbox)
 			tea5757_set_freq(btv,v);
 #endif
 		return 0;
@@ -1882,7 +1867,7 @@
 		
 		/* card specific hooks */
 		if (bttv_tvcards[btv->type].audio_hook)
-			bttv_tvcards[btv->type].audio_hook(btv,&v,0);
+			bttv_tvcards[btv->type].audio_hook(btv,&v,1);
 
 		btv->audio_dev=v;
 		up(&btv->lock);
@@ -2184,7 +2169,7 @@
 
 static int vbi_ioctl(struct video_device *dev, unsigned int cmd, void *arg)
 {
-	struct bttv *btv=(struct bttv *)dev;
+	struct bttv *btv=(struct bttv *)(dev-2);
 
 	switch (cmd) {	
 	case VIDIOCGCAP:
@@ -2206,7 +2191,7 @@
 	case VIDIOCGFREQ:
 	case VIDIOCSFREQ:
 	case BTTV_VERSION:
-		return bttv_ioctl(dev,cmd,arg);
+		return bttv_ioctl(dev-2,cmd,arg);
 	case BTTV_VBISIZE:
 		/* make alevt happy :-) */
 		return VBIBUF_SIZE;
@@ -2462,7 +2447,7 @@
 	        video_unregister_device(&btv->video_dev);
 		return -1;
 	}
-	if (radio[btv->nr])
+	if (btv->has_radio)
 	{
 		if(video_register_device(&btv->radio_dev, VFL_TYPE_RADIO)<0) 
                 {
@@ -2523,6 +2508,7 @@
 
 	btv->errors=0;
 	btv->needs_restart=0;
+	btv->has_radio=radio[btv->nr];
 
 	if (!(btv->risc_scr_odd=(unsigned int *) kmalloc(RISCMEM_LEN/2, GFP_KERNEL)))
 		return -1;
@@ -2854,11 +2840,11 @@
         if (btv->bt848_mem)
                 iounmap(btv->bt848_mem);
 
-        if(btv->video_dev.minor!=-1)
+        if (btv->video_dev.minor!=-1)
                 video_unregister_device(&btv->video_dev);
-        if(btv->vbi_dev.minor!=-1)
+        if (btv->vbi_dev.minor!=-1)
                 video_unregister_device(&btv->vbi_dev);
-        if (radio[btv->nr] && btv->radio_dev.minor != -1)
+        if (btv->radio_dev.minor != -1)
                 video_unregister_device(&btv->radio_dev);
 
         release_mem_region(pci_resource_start(btv->dev,0),
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/bttv-if.c linux/drivers/media/video/bttv-if.c
--- v2.4.1/linux/drivers/media/video/bttv-if.c	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/bttv-if.c	Mon Feb 19 14:43:36 2001
@@ -36,6 +36,9 @@
 #include "bttvp.h"
 #include "tuner.h"
 
+static struct i2c_algo_bit_data bttv_i2c_algo_template;
+static struct i2c_adapter bttv_i2c_adap_template;
+static struct i2c_client bttv_i2c_client_template;
 
 EXPORT_SYMBOL(bttv_get_cardinfo);
 EXPORT_SYMBOL(bttv_get_id);
@@ -240,17 +243,17 @@
 	}
 }
 
-struct i2c_algo_bit_data bttv_i2c_algo_template = {
+static struct i2c_algo_bit_data bttv_i2c_algo_template = {
 	setsda:  bttv_bit_setsda,
 	setscl:  bttv_bit_setscl,
 	getsda:  bttv_bit_getsda,
 	getscl:  bttv_bit_getscl,
-	udelay:  40,
+	udelay:  16,
 	mdelay:  10,
 	timeout: 200,
 };
 
-struct i2c_adapter bttv_i2c_adap_template = {
+static struct i2c_adapter bttv_i2c_adap_template = {
 	name:              "bt848",
 	id:                I2C_HW_B_BT848,
 	inc_use:           bttv_inc_use,
@@ -259,7 +262,7 @@
 	client_unregister: detach_inform,
 };
 
-struct i2c_client bttv_i2c_client_template = {
+static struct i2c_client bttv_i2c_client_template = {
         name: "bttv internal use only",
         id:   -1,
 };
@@ -323,6 +326,30 @@
 			break;
 		}
 	}
+}
+
+/* init + register i2c algo-bit adapter */
+int __devinit init_bttv_i2c(struct bttv *btv)
+{
+	memcpy(&btv->i2c_adap, &bttv_i2c_adap_template,
+	       sizeof(struct i2c_adapter));
+	memcpy(&btv->i2c_algo, &bttv_i2c_algo_template,
+	       sizeof(struct i2c_algo_bit_data));
+	memcpy(&btv->i2c_client, &bttv_i2c_client_template,
+	       sizeof(struct i2c_client));
+
+	sprintf(btv->i2c_adap.name+strlen(btv->i2c_adap.name),
+		" #%d", btv->nr);
+        btv->i2c_algo.data = btv;
+        btv->i2c_adap.data = btv;
+        btv->i2c_adap.algo_data = &btv->i2c_algo;
+        btv->i2c_client.adapter = &btv->i2c_adap;
+
+	bttv_bit_setscl(btv,1);
+	bttv_bit_setsda(btv,1);
+
+	btv->i2c_rc = i2c_bit_add_bus(&btv->i2c_adap);
+	return btv->i2c_rc;
 }
 
 /*
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/bttv.h linux/drivers/media/video/bttv.h
--- v2.4.1/linux/drivers/media/video/bttv.h	Sat Dec 30 11:23:13 2000
+++ linux/drivers/media/video/bttv.h	Mon Feb 19 14:44:16 2001
@@ -57,7 +57,7 @@
 #define BTTV_TYPHOON_TVIEW 0x24
 #define BTTV_PXELVWPLTVPRO 0x25
 #define BTTV_MAGICTVIEW063 0x26
-#define BTTV_PINNACLERAVE  0x27
+#define BTTV_PINNACLE      0x27
 #define BTTV_STB2          0x28
 #define BTTV_AVPHONE98     0x29
 #define BTTV_PV951         0x2a
@@ -70,7 +70,11 @@
 #define BTTV_GVBCTV3PCI    0x31
 #define BTTV_PXELVWPLTVPAK 0x32
 #define BTTV_EAGLE         0x33
-#define BTTV_PINNACLESTUDIO 0x34
+#define BTTV_PINNACLEPRO   0x34
+#define BTTV_TVIEW_RDS_FM  0x35
+#define BTTV_LIVETEC_9415  0x36
+#define BTTV_BESTBUY_EASYTV 0x37
+#define BTTV_FLYVIDEO_98FM 0x38
 
 /* i2c address list */
 #define I2C_TSA5522        0xc2
@@ -186,15 +190,12 @@
 
 /* i2c */
 #define I2C_CLIENTS_MAX 8
-struct i2c_algo_bit_data bttv_i2c_algo_template;
-struct i2c_adapter bttv_i2c_adap_template;
-struct i2c_client bttv_i2c_client_template;
-void bttv_bit_setscl(void *data, int state);
-void bttv_bit_setsda(void *data, int state);
-void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
-int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
-int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
+extern void bttv_bit_setscl(void *data, int state);
+extern void bttv_bit_setsda(void *data, int state);
+extern void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg);
+extern int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for);
+extern int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1,
 	     unsigned char b2, int both);
-void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
+extern void bttv_readee(struct bttv *btv, unsigned char *eedata, int addr);
 
 #endif /* _BTTV_H_ */
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/bttvp.h linux/drivers/media/video/bttvp.h
--- v2.4.1/linux/drivers/media/video/bttvp.h	Sat Dec 30 11:23:13 2000
+++ linux/drivers/media/video/bttvp.h	Mon Feb 19 14:43:36 2001
@@ -25,7 +25,7 @@
 #ifndef _BTTVP_H_
 #define _BTTVP_H_
 
-#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,50)
+#define BTTV_VERSION_CODE KERNEL_VERSION(0,7,57)
 
 
 #include <linux/types.h>
@@ -43,10 +43,14 @@
 /* bttv-driver.c                                              */
 
 /* insmod options / kernel args */
+extern int no_overlay;
 extern unsigned int bttv_verbose;
 extern unsigned int bttv_debug;
 extern unsigned int bttv_gpio;
 extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
+extern int init_bttv_i2c(struct bttv *btv);
+
+#define dprintk		if (bttv_debug) printk
 
 /* Anybody who uses more than four? */
 #define BTTV_MAX 4
@@ -143,6 +147,16 @@
 	int audio;           /* audio mode */
 	int audio_chip;      /* set to one of the chips supported by bttv.c */
 	int radio;
+	int has_radio;
+
+	/* miro/pinnacle + Aimslab VHX
+	   philips matchbox (tea5757 radio tuner) support */
+	int has_matchbox;
+	int mbox_we;
+	int mbox_data;
+	int mbox_clk;
+	int mbox_most;
+	int mbox_mask;
 
 	u32 *risc_jmp;
 	u32 *vbi_odd;
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/buz.c linux/drivers/media/video/buz.c
--- v2.4.1/linux/drivers/media/video/buz.c	Fri Nov 17 17:56:51 2000
+++ linux/drivers/media/video/buz.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/signal.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/bw-qcam.c linux/drivers/media/video/bw-qcam.c
--- v2.4.1/linux/drivers/media/video/bw-qcam.c	Mon Nov 27 17:47:38 2000
+++ linux/drivers/media/video/bw-qcam.c	Fri Feb  9 11:30:23 2001
@@ -70,7 +70,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/parport.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/c-qcam.c linux/drivers/media/video/c-qcam.c
--- v2.4.1/linux/drivers/media/video/c-qcam.c	Mon Nov 27 17:47:38 2000
+++ linux/drivers/media/video/c-qcam.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/parport.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/cpia_usb.c linux/drivers/media/video/cpia_usb.c
--- v2.4.1/linux/drivers/media/video/cpia_usb.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/media/video/cpia_usb.c	Mon Feb 19 10:18:18 2001
@@ -558,6 +558,7 @@
 
 static struct usb_device_id cpia_id_table [] = {
 	{ USB_DEVICE(0x0553, 0x0002) },
+	{ USB_DEVICE(0x0813, 0x0001) },
 	{ }					/* Terminating entry */
 };
 
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/i2c-old.c linux/drivers/media/video/i2c-old.c
--- v2.4.1/linux/drivers/media/video/i2c-old.c	Mon Aug 14 11:56:53 2000
+++ linux/drivers/media/video/i2c-old.c	Fri Feb  9 11:30:23 2001
@@ -14,7 +14,7 @@
 #include <linux/delay.h>
 #include <linux/locks.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/i2c-old.h>
 
 #define REGPRINT(x)   if (verbose)   (x)
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/msp3400.c linux/drivers/media/video/msp3400.c
--- v2.4.1/linux/drivers/media/video/msp3400.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/media/video/msp3400.c	Mon Feb 19 14:43:36 2001
@@ -42,7 +42,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/videodev.h>
 #include <asm/semaphore.h>
@@ -90,6 +90,7 @@
 	int nicam_on;
 	int acb;
 	int main, second;	/* sound carrier */
+	int scart;              /* input is scart */
 
 	int muted;
 	int left, right;	/* volume */
@@ -733,6 +734,8 @@
 
 		if (VIDEO_MODE_RADIO == msp->norm)
 			continue;  /* nothing to do */
+		if (msp->scart)
+			continue;  /* nothing to do */
 	
 		msp->active = 1;
 
@@ -749,6 +752,10 @@
 			goto done;
 		
 	restart:
+		if (msp->scart)
+			continue;
+		if (VIDEO_MODE_RADIO == msp->norm)
+			continue;
 		msp->restart = 0;
 		msp3400c_setvolume(client, msp->muted, 0, 0);
 		msp3400c_setmode(client, MSP_MODE_AM_DETECT /* +1 */ );
@@ -912,7 +919,7 @@
 	msp->thread = NULL;
 
 	if(msp->notify != NULL)
-		up_and_exit(msp->notify, 0);
+		up(msp->notify);
 	return 0;
 }
 
@@ -982,6 +989,9 @@
 		if (msp->rmmod || signal_pending(current))
 			goto done;
 
+		if (msp->scart)
+			continue;
+		
 		msp->active = 1;
 
 		if (msp->watch_stereo) {
@@ -997,6 +1007,8 @@
 			goto done;
 
 	restart:
+		if (msp->scart)
+			continue;
 		msp->restart = 0;
 		del_timer(&msp->wake_stereo);
 		msp->watch_stereo = 0;
@@ -1004,11 +1016,6 @@
 		/* put into sane state (and mute) */
 		msp3400c_reset(client);
 
-		/* set various prescales */
-		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */
-		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
-		msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */
-
 		/* start autodetect */
 		switch (msp->norm) {
 		case VIDEO_MODE_PAL:
@@ -1081,6 +1088,11 @@
 			msp3400c_write(client, I2C_MSP3400C_DEM, 0x20, val);
 		}
 
+		/* set various prescales */
+		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0d, 0x1900); /* scart */
+		msp3400c_write(client, I2C_MSP3400C_DFP, 0x0e, 0x2403); /* FM */
+		msp3400c_write(client, I2C_MSP3400C_DFP, 0x10, 0x5a00); /* nicam */
+
 		/* set stereo */
 		switch (val) {
 		case 0x0008: /* B/G NICAM */
@@ -1320,19 +1332,25 @@
 
 	case AUDC_SET_INPUT:
 #if 1
+		dprintk(KERN_DEBUG "msp34xx: AUDC_SET_INPUT(%d)\n",*sarg);
 		/* hauppauge 44xxx scart switching */
+		msp->scart = 0;
 		switch (*sarg) {
 		case AUDIO_RADIO:
 			msp3400c_set_scart(client,SCART_IN2,0);
 			break;
 		case AUDIO_EXTERN:
+			msp->scart   = 1;
 			msp3400c_set_scart(client,SCART_IN1,0);
+			msp3400c_write(client,I2C_MSP3400C_DFP,0x0008,0x0220);
 			break;
 		default:
 			if (*sarg & AUDIO_MUTE)
 				msp3400c_set_scart(client,SCART_MUTE,0);
 			break;
 		}
+		if (msp->active)
+			msp->restart = 1;
 #endif
 		break;
 
@@ -1344,8 +1362,6 @@
 		if (msp->simple) {
 			/* the thread will do for us */
 			msp3400c_setvolume(client,msp->muted,0,0);
-			if (msp->active)
-				msp->restart = 1;
 			wake_up_interruptible(&msp->wq);
 		} else {
 			/* set msp3400 to FM radio mode */
@@ -1353,6 +1369,8 @@
 			msp3400c_setcarrier(client, MSP_CARRIER(10.7),MSP_CARRIER(10.7));
 			msp3400c_setvolume(client,msp->muted,msp->left,msp->right);			
 		}
+		if (msp->active)
+			msp->restart = 1;
 		break;
 
 	/* --- v4l ioctls --- */
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/planb.c linux/drivers/media/video/planb.c
--- v2.4.1/linux/drivers/media/video/planb.c	Fri Nov 17 17:56:51 2000
+++ linux/drivers/media/video/planb.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/pms.c linux/drivers/media/video/pms.c
--- v2.4.1/linux/drivers/media/video/pms.c	Fri Nov 17 17:56:51 2000
+++ linux/drivers/media/video/pms.c	Fri Feb  9 11:30:23 2001
@@ -19,7 +19,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/saa7111.c linux/drivers/media/video/saa7111.c
--- v2.4.1/linux/drivers/media/video/saa7111.c	Wed Dec 29 17:08:55 1999
+++ linux/drivers/media/video/saa7111.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/signal.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/saa7185.c linux/drivers/media/video/saa7185.c
--- v2.4.1/linux/drivers/media/video/saa7185.c	Wed Dec 29 17:08:55 1999
+++ linux/drivers/media/video/saa7185.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/signal.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/stradis.c linux/drivers/media/video/stradis.c
--- v2.4.1/linux/drivers/media/video/stradis.c	Fri Nov 17 17:56:51 2000
+++ linux/drivers/media/video/stradis.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <linux/poll.h>
@@ -2067,11 +2067,15 @@
 	if (result == -EBUSY)
 		printk(KERN_ERR "stradis%d: IRQ %ld busy, change your PnP"
 		       " config in BIOS\n", num, saa->irq);
-	if (result < 0)
+	if (result < 0) {
+		iounmap(saa->saa7146_mem);
 		return result;
+	}
 	pci_set_master(dev);
-	if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0)
+	if (video_register_device(&saa->video_dev, VFL_TYPE_GRABBER) < 0) {
+		iounmap(saa->saa7146_mem);
 		return -1;
+	}
 #if 0
 	/* i2c generic interface is currently BROKEN */
 	i2c_register_bus(&saa->i2c);
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tda7432.c linux/drivers/media/video/tda7432.c
--- v2.4.1/linux/drivers/media/video/tda7432.c	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/tda7432.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/videodev.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tda9875.c linux/drivers/media/video/tda9875.c
--- v2.4.1/linux/drivers/media/video/tda9875.c	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/tda9875.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/videodev.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tuner-3036.c linux/drivers/media/video/tuner-3036.c
--- v2.4.1/linux/drivers/media/video/tuner-3036.c	Mon Feb 28 14:56:10 2000
+++ linux/drivers/media/video/tuner-3036.c	Fri Feb  9 11:30:23 2001
@@ -20,7 +20,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tuner.c linux/drivers/media/video/tuner.c
--- v2.4.1/linux/drivers/media/video/tuner.c	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/tuner.c	Mon Feb 19 14:43:36 2001
@@ -5,7 +5,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/i2c.h>
 #include <linux/types.h>
@@ -34,6 +34,7 @@
 static int type  = -1; /* insmod parameter */
 
 static int addr  =  0;
+static char *pal =  "b";
 static int this_adap;
 
 #define dprintk     if (debug) printk
@@ -41,6 +42,7 @@
 MODULE_PARM(debug,"i");
 MODULE_PARM(type,"i");
 MODULE_PARM(addr,"i");
+MODULE_PARM(pal,"s");
 
 struct tuner
 {
@@ -55,6 +57,44 @@
 static struct i2c_driver driver;
 static struct i2c_client client_template;
 
+/* tv standard selection for Temic 4046 FM5
+   this value takes the low bits of control byte 2
+   from datasheet Rev.01, Feb.00 
+     standard     BG      I       L       L2      D
+     picture IF   38.9    38.9    38.9    33.95   38.9
+     sound 1      33.4    32.9    32.4    40.45   32.4
+     sound 2      33.16   
+     NICAM        33.05   32.348  33.05           33.05
+ */
+#define TEMIC_SET_PAL_I         0x05
+#define TEMIC_SET_PAL_DK        0x09
+#define TEMIC_SET_PAL_L         0x0a // SECAM ?
+#define TEMIC_SET_PAL_L2        0x0b // change IF !
+#define TEMIC_SET_PAL_BG        0x0c
+
+/* tv tuner system standard selection for Philips FQ1216ME
+   this value takes the low bits of control byte 2
+   from datasheet "1999 Nov 16" (supersedes "1999 Mar 23")
+     standard 		BG	DK	I	L	L`
+     picture carrier	38.90	38.90	38.90	38.90	33.95
+     colour		34.47	34.47	34.47	34.47	38.38
+     sound 1		33.40	32.40	32.90	32.40	40.45
+     sound 2		33.16	-	-	-	-
+     NICAM		33.05	33.05	32.35	33.05	39.80
+ */
+#define PHILIPS_SET_PAL_I	0x01 /* Bit 2 always zero !*/
+#define PHILIPS_SET_PAL_BGDK	0x09
+#define PHILIPS_SET_PAL_L2	0x0a
+#define PHILIPS_SET_PAL_L	0x0b	
+
+/* system switching for Philips FI1216MF MK2
+   from datasheet "1996 Jul 09",
+ */
+#define PHILIPS_MF_SET_BG	0x01 /* Bit 2 must be zero, Bit 3 is system output */
+#define PHILIPS_MF_SET_PAL_L	0x03
+#define PHILIPS_MF_SET_PAL_L2	0x02
+
+
 /* ---------------------------------------------------------------------- */
 
 struct tunertype 
@@ -63,18 +103,13 @@
 	unsigned char Vendor;
 	unsigned char Type;
   
-	unsigned short thresh1; /* frequency Range for UHF,VHF-L, VHF_H */   
-	unsigned short thresh2;  
+	unsigned short thresh1;  /*  band switch VHF_LO <=> VHF_HI  */
+	unsigned short thresh2;  /*  band switch VHF_HI <=> UHF     */
 	unsigned char VHF_L;
 	unsigned char VHF_H;
 	unsigned char UHF;
 	unsigned char config; 
-	unsigned short IFPCoff;
-	unsigned char mode; /* mode change value (tested PHILIPS_SECAM only) */
-			/* 0x01 -> ??? no change ??? */
-			/* 0x02 -> PAL BDGHI / SECAM L */
-			/* 0x04 -> ??? PAL others / SECAM others ??? */
-	int capability;
+	unsigned short IFPCoff; /* 622.4=16*38.90 MHz PAL, 732=16*45.75 NTSC */
 };
 
 /*
@@ -83,23 +118,25 @@
  *	"no float in kernel" rule.
  */
 static struct tunertype tuners[] = {
-        { "Temic PAL", TEMIC, PAL,
+        { "Temic PAL (4002 FH5)", TEMIC, PAL,
 	  16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623},
 	{ "Philips PAL_I", Philips, PAL_I,
 	  16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623},
 	{ "Philips NTSC", Philips, NTSC,
 	  16*157.25,16*451.25,0xA0,0x90,0x30,0x8e,732},
 	{ "Philips SECAM", Philips, SECAM,
-	  16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623,0x02},
+	  16*168.25,16*447.25,0xA7,0x97,0x37,0x8e,623},
+
 	{ "NoTuner", NoTuner, NOTUNER,
-	  0,0,0x00,0x00,0x00,0x00,0x00,000},
+	  0,0,0x00,0x00,0x00,0x00,0x00},
 	{ "Philips PAL", Philips, PAL,
 	  16*168.25,16*447.25,0xA0,0x90,0x30,0x8e,623},
-	{ "Temic NTSC", TEMIC, NTSC,
+	{ "Temic NTSC (4032 FY5)", TEMIC, NTSC,
 	  16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732},
-	{ "Temic PAL_I", TEMIC, PAL_I,
+	{ "Temic PAL_I (4062 FY5)", TEMIC, PAL_I,
 	  16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623},
- 	{ "Temic 4036 FY5 NTSC", TEMIC, NTSC,
+
+ 	{ "Temic NTSC (4036 FY5)", TEMIC, NTSC,
 	  16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732},
         { "Alps HSBH1", TEMIC, NTSC,
 	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
@@ -107,14 +144,36 @@
 	  16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732},
         { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modtec MM205 */
 	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632},
+
         { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
 	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622},
         { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */
 	  16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608},
-	{ "Temic 4006FH5", TEMIC, PAL_I,
+	{ "Temic PAL_I (4006FH5)", TEMIC, PAL_I,
 	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, 
   	{ "Alps TSCH6",Alps,NTSC,
   	  16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732},
+
+  	{ "Temic PAL_DK (4016 FY5)",TEMIC,PAL,
+  	  16*136.25,16*456.25,0xa0,0x90,0x30,0x8e,623},
+  	{ "Philips NTSC_M (MK2)",Philips,NTSC,
+  	  16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732},
+        { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I,
+          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+        { "Temic PAL* auto (4006 FN5)", TEMIC, PAL,
+          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+
+        { "Temic PAL (4009 FR5)", TEMIC, PAL,
+          16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623},
+        { "Temic NTSC (4039 FR5)", TEMIC, NTSC,
+          16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732},
+        { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL,
+          16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623},
+        { "Philips PAL_DK", Philips, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623},
+
+	{ "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL,
+	  16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}
 };
 #define TUNERS (sizeof(tuners)/sizeof(struct tunertype))
 
@@ -165,6 +224,7 @@
 }
 #endif
 
+// Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz
 static void set_tv_freq(struct i2c_client *c, int freq)
 {
 	u8 config;
@@ -174,6 +234,15 @@
         unsigned char buffer[4];
 	int rc;
 
+	if (freq < 45*16 || freq > 890*16) {
+		/* FIXME: better do that chip-specific, but
+		   right now we don't have that in the config
+		   struct and this way is still better than no
+		   check at all */
+		printk("tuner: TV freq out of range\n");
+		return;
+	}
+
 	if (t->type == -1) {
 		printk("tuner: tuner type not set\n");
 		return;
@@ -187,32 +256,81 @@
 	else
 		config = tun->UHF;
 
-#if 1   // Fix colorstandard mode change
-	if (t->type == TUNER_PHILIPS_SECAM && t->mode)
-		config |= tun->mode;
-	else
-		config &= ~tun->mode;
-#else
-		config &= ~tun->mode;
-#endif
 
-	div=freq + tun->IFPCoff;
+	/* tv norm specific stuff for multi-norm tuners */
+	switch (t->type) {
+	case TUNER_PHILIPS_SECAM:
+		/* 0x01 -> ??? no change ??? */
+		/* 0x02 -> PAL BDGHI / SECAM L */
+		/* 0x04 -> ??? PAL others / SECAM others ??? */
+		config &= ~0x02;
+		if (t->mode)
+			config |= 0x02;
+		break;
 
-    /*
-     * Philips FI1216MK2 remark from specification :
-     * for channel selection involving band switching, and to ensure
-     * smooth tuning to the desired channel without causing
-     * unnecessary charge pump action, it is recommended to consider
-     * the difference between wanted channel frequency and the
-     * current channel frequency.  Unnecessary charge pump action
-     * will result in very low tuning voltage which may drive the
-     * oscillator to extreme conditions.
-     */
-    /*
-     * Progfou: specification says to send config data before
-     * frequency in case (wanted frequency < current frequency).
-     */
+	case TUNER_TEMIC_4046FM5:
+		config &= ~0x0f;
+		switch (pal[0]) {
+		case 'i':
+		case 'I':
+			config |= TEMIC_SET_PAL_I;
+			break;
+		case 'd':
+		case 'D':
+			config |= TEMIC_SET_PAL_DK;
+			break;
+		case 'l':
+		case 'L':
+			config |= TEMIC_SET_PAL_L;
+			break;
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+		default:
+			config |= TEMIC_SET_PAL_BG;
+			break;
+		break;
+		}
+	case TUNER_PHILIPS_FQ1216ME:
+		config &= ~0x0f;
+		switch (pal[0]) {
+		case 'i':
+		case 'I':
+			config |= PHILIPS_SET_PAL_I;
+			break;
+		case 'l':
+		case 'L':
+			config |= PHILIPS_SET_PAL_L;
+			break;
+		case 'd':
+		case 'D':
+		case 'b':
+		case 'B':
+		case 'g':
+		case 'G':
+			config |= PHILIPS_SET_PAL_BGDK;
+			break;
+		break;
+		}
+	}
 
+	
+	/*
+	 * Philips FI1216MK2 remark from specification :
+	 * for channel selection involving band switching, and to ensure
+	 * smooth tuning to the desired channel without causing
+	 * unnecessary charge pump action, it is recommended to consider
+	 * the difference between wanted channel frequency and the
+	 * current channel frequency.  Unnecessary charge pump action
+	 * will result in very low tuning voltage which may drive the
+	 * oscillator to extreme conditions.
+	 *
+	 * Progfou: specification says to send config data before
+	 * frequency in case (wanted frequency < current frequency).
+	 */
+
+	div=freq + tun->IFPCoff;
 	if (t->type == TUNER_PHILIPS_SECAM && freq < t->freq) {
 		buffer[0] = tun->config;
 		buffer[1] = config;
@@ -239,6 +357,10 @@
         unsigned char buffer[4];
 	int rc;
 
+	if (freq < 76*16 || freq > 108*16) {
+		printk("tuner: radio freq out of range\n");
+		return;
+	}
 	if (t->type == -1) {
 		printk("tuner: tuner type not set\n");
 		return;
@@ -378,16 +500,16 @@
 	{
 		unsigned long *v = arg;
 
-		t->freq = *v;
 		if (t->radio) {
 			dprintk("tuner: radio freq set to %d.%02d\n",
 				(*iarg)/16,(*iarg)%16*100/16);
-			set_radio_freq(client,t->freq);
+			set_radio_freq(client,*v);
 		} else {
 			dprintk("tuner: tv freq set to %d.%02d\n",
 				(*iarg)/16,(*iarg)%16*100/16);
-			set_tv_freq(client,t->freq);
+			set_tv_freq(client,*v);
 		}
+		t->freq = *v;
 		return 0;
 	}
 	case VIDIOCGTUNER:
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tuner.h linux/drivers/media/video/tuner.h
--- v2.4.1/linux/drivers/media/video/tuner.h	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/tuner.h	Mon Feb 19 14:43:36 2001
@@ -22,22 +22,32 @@
 #ifndef _TUNER_H
 #define _TUNER_H
 
-#define TUNER_TEMIC_PAL     0  /*  Miro Gpio Coding -1 */
+#define TUNER_TEMIC_PAL     0        /* 4002 FH5_9483 */
 #define TUNER_PHILIPS_PAL_I 1
 #define TUNER_PHILIPS_NTSC  2
-#define TUNER_PHILIPS_SECAM 3
+#define TUNER_PHILIPS_SECAM 3		/* you must actively select B/G, L, L` */
 #define TUNER_ABSENT        4
 #define TUNER_PHILIPS_PAL   5
-#define TUNER_TEMIC_NTSC    6
-#define TUNER_TEMIC_PAL_I   7
-#define TUNER_TEMIC_4036FY5_NTSC	8
-#define TUNER_ALPS_TSBH1_NTSC 	9
+#define TUNER_TEMIC_NTSC    6        /* 4032 FY5_7004 */
+#define TUNER_TEMIC_PAL_I   7        /* 4062 FY5_9957 */
+#define TUNER_TEMIC_4036FY5_NTSC 8   /* 4036 FY5      */
+#define TUNER_ALPS_TSBH1_NTSC 	 9
 #define TUNER_ALPS_TSBE1_PAL 	10
 #define TUNER_ALPS_TSBB5_PAL_I 	11
 #define TUNER_ALPS_TSBE5_PAL 	12
 #define TUNER_ALPS_TSBC5_PAL 	13
-#define TUNER_TEMIC_4006FH5_PAL	14
+#define TUNER_TEMIC_4006FH5_PAL	14   /* 4006 FH5      */
 #define TUNER_ALPS_TSHC6_NTSC 	15
+#define TUNER_TEMIC_PAL_DK	16   /* 4016 FY5      */
+#define TUNER_PHILIPS_NTSC_M	17
+#define TUNER_TEMIC_4066FY5_PAL_I       18
+#define TUNER_TEMIC_4006FN5_MULTI_PAL   19  /* B/G, I and D/K autodetected */
+#define TUNER_TEMIC_4009FR5_PAL         20  /* incl. FM radio */
+#define TUNER_TEMIC_4039FR5_NTSC        21  /* incl. FM radio */
+#define TUNER_TEMIC_4046FM5             22  /* you must actively select B/G, D/K, I, L, L` !  */
+#define TUNER_PHILIPS_PAL_DK		23
+#define TUNER_PHILIPS_FQ1216ME		24  /* you must actively select B/G/D/K, I, L, L` */
+
 
 #define NOTUNER 0
 #define PAL     1
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tvaudio.c linux/drivers/media/video/tvaudio.c
--- v2.4.1/linux/drivers/media/video/tvaudio.c	Tue Dec  5 12:43:47 2000
+++ linux/drivers/media/video/tvaudio.c	Mon Feb 19 14:43:36 2001
@@ -22,7 +22,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/videodev.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
@@ -112,13 +112,14 @@
 	audiocmd   shadow;
 
 	/* current settings */
-	__u16 left,right,treble,bass;
+	__u16 left,right,treble,bass,mode;
 
 	/* thread */
 	struct task_struct  *thread;
 	struct semaphore    *notify;
 	wait_queue_head_t    wq;
-	int                  wake,done;
+	struct timer_list    wt;
+	int                  done;
 };
 
 
@@ -245,6 +246,12 @@
  *   if available, ...
  */
 
+static void chip_thread_wake(unsigned long data)
+{
+        struct CHIPSTATE *chip = (struct CHIPSTATE*)data;
+	wake_up_interruptible(&chip->wq);
+}
+
 static int chip_thread(void *data)
 {
         struct CHIPSTATE *chip = data;
@@ -266,37 +273,44 @@
 		up(chip->notify);
 
 	for (;;) {
-		if (chip->done)
-			break;
-		if (!chip->wake) {
-			interruptible_sleep_on(&chip->wq);
-			dprintk("%s: thread wakeup\n", chip->c.name);
-			if (chip->done || signal_pending(current))
-				break;
-		}
-		chip->wake = 0;
-
-		/* wait some time -- let the audio hardware
-		   figure the current mode */
-		current->state   = TASK_INTERRUPTIBLE;
-		schedule_timeout(HZ);
-		if (signal_pending(current))
+		interruptible_sleep_on(&chip->wq);
+		dprintk("%s: thread wakeup\n", chip->c.name);
+		if (chip->done || signal_pending(current))
 			break;
-		if (chip->wake)
+		
+		if (0 != chip->mode)
+			/* don't do anything if mode != auto */
 			continue;
-
+		
+		/* have a look what's going on */
 		dprintk("%s: thread checkmode\n", chip->c.name);
 		desc->checkmode(chip);
+		
+		/* schedule next check */
+		mod_timer(&chip->wt, jiffies+2*HZ);
 	}
 
 	chip->thread = NULL;
 	dprintk("%s: thread exiting\n", chip->c.name);
 	if(chip->notify != NULL)
-		up_and_exit(chip->notify,0);
+		up(chip->notify);
 
 	return 0;
 }
 
+void generic_checkmode(struct CHIPSTATE *chip)
+{
+	struct CHIPDESC  *desc = chiplist + chip->type;
+	int mode = desc->getmode(chip);
+
+	if (mode & VIDEO_SOUND_STEREO)
+		desc->setmode(chip,VIDEO_SOUND_STEREO);
+	else if (mode & VIDEO_SOUND_LANG1)
+		desc->setmode(chip,VIDEO_SOUND_LANG1);
+	else
+		desc->setmode(chip,VIDEO_SOUND_MONO);
+}
+
 /* ---------------------------------------------------------------------- */
 /* audio chip descriptions - defines+functions for tda9840                */
 
@@ -313,10 +327,24 @@
 #define TDA9840_DUALBA     0x16
 #define TDA9840_EXTERNAL   0x7a
 
+#define TDA9840_DS_DUAL    0x20 /* Dual sound identified          */
+#define TDA9840_ST_STEREO  0x40 /* Stereo sound identified        */
+#define TDA9840_PONRES     0x80 /* Power-on reset detected if = 1 */
+
 int  tda9840_getmode(struct CHIPSTATE *chip)
 {
-	return VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO |
-		VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+	int val, mode;
+	
+	val = chip_read(chip);
+	mode = VIDEO_SOUND_MONO;
+	if (val & TDA9840_DS_DUAL)
+		mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
+	if (val & TDA9840_ST_STEREO)
+		mode |= VIDEO_SOUND_STEREO;
+	
+	dprintk ("tda9840_getmode(): raw chip read: %d, return: %d\n",
+		 val, mode);
+	return mode;
 }
 
 void tda9840_setmode(struct CHIPSTATE *chip, int mode)
@@ -617,6 +645,12 @@
 {
 	int sw_data  = chip->shadow.bytes[TDA9873_SW+1] & 0xe3;
 	/*	int adj_data = chip->shadow.bytes[TDA9873_AD+1] ; */
+
+	if (sw_data & 3) {
+		dprintk("tda9873_setmode(): external input\n");
+		return;
+	}
+	
 	dprintk("tda9873_setmode(): chip->shadow.bytes[%d] = %d\n", TDA9873_SW+1, chip->shadow.bytes[TDA9873_SW+1]);
 	dprintk("tda9873_setmode(): sw_data  = %d\n", sw_data);
 
@@ -638,16 +672,6 @@
 	chip_write(chip,TDA9873_SW,sw_data);
 }
 
-void tda9873_checkmode(struct CHIPSTATE *chip)
-{
-	int mode = tda9873_getmode(chip);
-
-	if (mode & VIDEO_SOUND_STEREO)
-		tda9873_setmode(chip,VIDEO_SOUND_STEREO);
-	if (mode & VIDEO_SOUND_LANG1)
-		tda9873_setmode(chip,VIDEO_SOUND_LANG1);
-}
-
 int tda9873_checkit(struct CHIPSTATE *chip)
 {
 	int rc;
@@ -751,6 +775,7 @@
 
 		getmode:    tda9840_getmode,
 		setmode:    tda9840_setmode,
+		checkmode:  generic_checkmode,
 
 		init:       { 2, { TDA9840_SW, 0x2a } }
 	},
@@ -762,12 +787,17 @@
 		addr_lo:    I2C_TDA985x_L >> 1,
 		addr_hi:    I2C_TDA985x_H >> 1,
 		registers:  3,
+		flags:      CHIP_HAS_INPUTSEL,
 
 		getmode:    tda9873_getmode,
 		setmode:    tda9873_setmode,
-		checkmode:  tda9873_checkmode,
+		checkmode:  generic_checkmode,
 
-		init:       { 4, { TDA9873_SW, 0xa0, 0x06, 0x03 } }
+		init:       { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } },
+		inputreg:   TDA9873_SW,
+		inputmute:  0xc0,
+		inputmap:   {0xa4, 0xa2, 0xa4, 0xa4, 0xc0}
+		
 	},
 	{
 		name:       "tda9850",
@@ -873,7 +903,10 @@
 
 		inputreg:   PIC16C54_REG_MISC,
 		inputmap:   {PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_TUNER,
-			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE},
+			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
+			     PIC16C54_MISC_SND_NOTMUTE|PIC16C54_MISC_SWITCH_LINE,
+			     PIC16C54_MISC_SND_MUTE,PIC16C54_MISC_SND_MUTE,
+			     PIC16C54_MISC_SND_NOTMUTE},
 		inputmute:  PIC16C54_MISC_SND_MUTE,
 	},
 	{ name: NULL } /* EOF */
@@ -947,11 +980,12 @@
 		/* start async thread */
 		DECLARE_MUTEX_LOCKED(sem);
 		chip->notify = &sem;
+		chip->wt.function = chip_thread_wake;
+		chip->wt.data     = (unsigned long)chip;
 		init_waitqueue_head(&chip->wq);
 		kernel_thread(chip_thread,(void *)chip,0);
 		down(&sem);
 		chip->notify = NULL;
-		chip->wake++;
 		wake_up_interruptible(&chip->wq);
 	}
 	return 0;
@@ -1048,17 +1082,19 @@
 			chip_write(chip,desc->bassreg,desc->bassfunc(chip->bass));
 			chip_write(chip,desc->treblereg,desc->treblefunc(chip->treble));
 		}
-		if (desc->setmode && va->mode)
+		if (desc->setmode && va->mode) {
+			chip->mode = va->mode;
 			desc->setmode(chip,va->mode);
+		}
 		break;
 	}
 	case VIDIOCSFREQ:
 	{
+		chip->mode = 0; /* automatic */
 		if (desc->checkmode) {
 			desc->setmode(chip,VIDEO_SOUND_MONO);
-			chip->wake++;
-			wake_up_interruptible(&chip->wq);
-			/* the thread will call checkmode() a second later */
+			mod_timer(&chip->wt, jiffies+2*HZ);
+			/* the thread will call checkmode() later */
 		}
 	}
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/tvmixer.c linux/drivers/media/video/tvmixer.c
--- v2.4.1/linux/drivers/media/video/tvmixer.c	Sun Nov 12 20:47:19 2000
+++ linux/drivers/media/video/tvmixer.c	Fri Feb  9 11:30:23 2001
@@ -5,7 +5,7 @@
 #include <linux/timer.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/videodev.h>
 #include <asm/semaphore.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/media/video/zr36120.c linux/drivers/media/video/zr36120.c
--- v2.4.1/linux/drivers/media/video/zr36120.c	Fri Nov 17 17:56:52 2000
+++ linux/drivers/media/video/zr36120.c	Fri Feb  9 11:30:23 2001
@@ -25,7 +25,7 @@
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
@@ -1866,14 +1866,16 @@
 			SA_SHIRQ|SA_INTERRUPT,"zoran",(void *)ztv);
 		if (result==-EINVAL)
 		{
+			iounmap(ztv->zoran_mem);
 			printk(KERN_ERR "zoran: Bad irq number or handler\n");
 			return -EINVAL;
 		}
 		if (result==-EBUSY)
 			printk(KERN_ERR "zoran: IRQ %d busy, change your PnP config in BIOS\n",dev->irq);
-		if (result < 0)
+		if (result < 0) {
+			iounmap(ztv->zoran_mem);
 			return result;
-
+		}
 		/* Enable bus-mastering */
 		pci_set_master(dev);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/cfi_cmdset_0001.c linux/drivers/mtd/cfi_cmdset_0001.c
--- v2.4.1/linux/drivers/mtd/cfi_cmdset_0001.c	Wed Nov 15 00:41:03 2000
+++ linux/drivers/mtd/cfi_cmdset_0001.c	Fri Feb  9 11:30:23 2001
@@ -15,7 +15,7 @@
 #include <asm/byteorder.h>
 
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi.h>
@@ -816,13 +816,13 @@
 			 * as the whole point is that nobody can do anything
 			 * with the chip now anyway.
 			 */
-			spin_unlock_bh(chip->mutex);
 			break;
 
 		default:
 			ret = -EAGAIN;
 			break;
 		}
+		spin_unlock_bh(chip->mutex);
 	}
 
 	/* Unlock the chips again */
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/cfi_cmdset_0002.c linux/drivers/mtd/cfi_cmdset_0002.c
--- v2.4.1/linux/drivers/mtd/cfi_cmdset_0002.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/mtd/cfi_cmdset_0002.c	Fri Feb  9 11:30:23 2001
@@ -18,7 +18,7 @@
 #include <asm/byteorder.h>
 
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi.h>
@@ -552,13 +552,13 @@
 			 * as the whole point is that nobody can do anything
 			 * with the chip now anyway.
 			 */
-			spin_unlock_bh(chip->mutex);
 			break;
 
 		default:
 			ret = -EAGAIN;
 			break;
 		}
+		spin_unlock_bh(chip->mutex);
 	}
 
 	/* Unlock the chips again */
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/cfi_probe.c linux/drivers/mtd/cfi_probe.c
--- v2.4.1/linux/drivers/mtd/cfi_probe.c	Sun Dec 31 10:26:17 2000
+++ linux/drivers/mtd/cfi_probe.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/map.h>
 #include <linux/mtd/cfi.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/doc1000.c linux/drivers/mtd/doc1000.c
--- v2.4.1/linux/drivers/mtd/doc1000.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/mtd/doc1000.c	Fri Feb  9 11:30:23 2001
@@ -12,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/doc2000.c linux/drivers/mtd/doc2000.c
--- v2.4.1/linux/drivers/mtd/doc2000.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/doc2000.c	Fri Feb  9 11:30:23 2001
@@ -15,7 +15,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/doc2001.c linux/drivers/mtd/doc2001.c
--- v2.4.1/linux/drivers/mtd/doc2001.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/doc2001.c	Fri Feb  9 11:30:23 2001
@@ -15,7 +15,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/docecc.c linux/drivers/mtd/docecc.c
--- v2.4.1/linux/drivers/mtd/docecc.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/docecc.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/docprobe.c linux/drivers/mtd/docprobe.c
--- v2.4.1/linux/drivers/mtd/docprobe.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/mtd/docprobe.c	Fri Feb  9 11:30:23 2001
@@ -50,7 +50,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/ftl.c linux/drivers/mtd/ftl.c
--- v2.4.1/linux/drivers/mtd/ftl.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/mtd/ftl.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -68,7 +68,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/map_ram.c linux/drivers/mtd/map_ram.c
--- v2.4.1/linux/drivers/mtd/map_ram.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/map_ram.c	Fri Feb  9 11:30:23 2001
@@ -10,7 +10,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/map.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/map_rom.c linux/drivers/mtd/map_rom.c
--- v2.4.1/linux/drivers/mtd/map_rom.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/map_rom.c	Fri Feb  9 11:30:23 2001
@@ -10,7 +10,7 @@
 #include <asm/io.h>
 #include <asm/byteorder.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/mtd/map.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mapped.c linux/drivers/mtd/mapped.c
--- v2.4.1/linux/drivers/mtd/mapped.c	Sun Sep 24 12:12:33 2000
+++ linux/drivers/mtd/mapped.c	Wed Dec 31 16:00:00 1969
@@ -1,673 +0,0 @@
-// -*- mode: cpp; mode: fold -*-
-// Description                                                          /*{{{*/
-// $Id: mapped.c,v 1.8 2000/03/31 14:40:42 dwmw2 Exp $
-/* ######################################################################
-
-   Flash MTD Routines
-
-   These routine support IDing and manipulating flash. Currently the 
-   older JEDEC ID mechanism and a table is used for determining the
-   flash characterisitics, but it is trivial to add support for the
-   CFI specification:
-     http://www.pentium.com/design/flash/ in the technote section.
-   
-   ##################################################################### */
-									/*}}}*/
-#include <linux/mtd/mapped.h>
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <asm/io.h>
-
-struct JEDECTable mtd_JEDEC_table[] = 
-  {{0x01AD,"AMD Am29F016",2*1024*1024,64*1024,MTD_CAP_NORFLASH},
-   {0x01D5,"AMD Am29F080",1*1024*1024,64*1024,MTD_CAP_NORFLASH},
-   {}};
-
-// flash_setup - Setup the mapped_mtd_info structure for normal flash	/*{{{*/
-// ---------------------------------------------------------------------
-/* There is a set of commands that flash manufactures follow for getting the
-   JEDEC id, erasing and writing. So long as your flash device supports 
-   getting the JEDEC ID in this (standard?) way it will be supported as flash,
-   otherwise it is converted to ROM. Upon completion the structure is 
-   registered with the MTD layer */
-int mtd_mapped_setup(struct mapped_mtd_info *map)
-{
-   DEBUG(1, "\n");
-   // Must define a page function to use the defaults!
-   if (map->page == 0)
-      return -1;
-   
-   if (map->jedec_sense == 0)
-      map->jedec_sense = flash_jedec;
-
-   if (map->jedec_sense(map) != 0)
-      return -1;
-
-   if (map->mtd.erase == 0 && map->mtd.type == MTD_NORFLASH)
-      map->mtd.erase = flash_erase;
-   if (map->mtd.write == 0)
-   {
-      if (map->mtd.type == MTD_NORFLASH)
-	 map->mtd.write = flash_write;
-      if (map->mtd.type == MTD_RAM)
-	 map->mtd.write = ram_write;      
-   }   
-   if (map->mtd.read == 0)
-      map->mtd.read = rom_read;   
-   
-   return add_mtd_device(&map->mtd);
-}
-									/*}}}*/
-// flash_remove - Remove the flash device from the MTD layer		/*{{{*/
-// ---------------------------------------------------------------------
-/* Free any memory allocated for the device here */
-int mtd_mapped_remove(struct mapped_mtd_info *map)
-{
-   return del_mtd_device(&map->mtd);
-}
-									/*}}}*/
-
-// checkparity - Checks a number for odd parity				/*{{{*/
-// ---------------------------------------------------------------------
-/* Helper for the JEDEC function, JEDEC numbers all have odd parity */
-static int checkparity(u_char C)
-{
-   u_char parity = 0;
-   while (C != 0)
-   {
-      parity ^= C & 1;
-      C >>= 1;
-   }
-   
-   return parity == 1;
-}
-									/*}}}*/
-// SetJedec - Set the jedec information for a chip			/*{{{*/
-// ---------------------------------------------------------------------
-/* We track the configuration of each chip separately in the chip list, 
-   each chip can have a different type and configuration to allow for 
-   maximum flexability. */
-void set_jedec(struct mapped_mtd_info *map,unsigned chip,unsigned char mfr,
-	      unsigned char id)
-{
-   unsigned long longID = (mfr << 8) + id;
-   unsigned int I;
-   
-   map->mtd.type = MTD_NORFLASH;
-   map->mfr = mfr;
-   map->id = id;
-
-   // Locate the chip in the jedec table
-   for (I = 0; mtd_JEDEC_table[I].jedec != 0; I++)
-   {      
-      if (mtd_JEDEC_table[I].jedec == longID)
-	 break;
-   }
-
-   if (mtd_JEDEC_table[I].jedec != longID || longID == 0)
-   {
-      printk("Unknown JEDEC number %x-%x, treating as ROM\n",map->mfr,
-	     map->id);
-      map->mtd.type = MTD_ROM;
-      return;
-   }
-      
-   // Setup the MTD from the JEDEC information
-//   map->mtd.size = mtd_JEDEC_table[I].size;
-//   map->mtd.erasesize = mtd_JEDEC_table[I].sectorsize;
-//   map->mtd.capabilities = mtd_JEDEC_table[I].capabilities;
-//   strncpy(map->mtd.part,mtd_JEDEC_table[I].name,sizeof(map->mtd.part)-1);
-   
-   map->chips[chip].jedec = longID;
-   map->chips[chip].size = mtd_JEDEC_table[I].size;
-   map->chips[chip].sectorsize = mtd_JEDEC_table[I].sectorsize;
-   map->chips[chip].capabilities = mtd_JEDEC_table[I].capabilities;
-   map->chips[chip].base = 0; 
-}
-									/*}}}*/
-// isjedec - Check if reading from the memory location gives jedec #s	/*{{{*/
-// ---------------------------------------------------------------------
-/* This is ment to be called on the flash window once it is in jedec mode */
-int isjedec(unsigned long base)
-{
-   // Test #1, JEDEC numbers are readable from 0x??00/0x??01
-   if (readb(base + 0) != readb(base + 0x100) || 
-       readb(base + 1) != readb(base + 0x101))
-      return 0;
-   
-   // Test #2 JEDEC numbers exhibit odd parity
-   if (checkparity(readb(base + 0)) == 0 || checkparity(readb(base + 1)) == 0)
-      return 0;
-   return 1;
-}
-									/*}}}*/
-// flash_jedec - JEDEC ID sensor					/*{{{*/
-// ---------------------------------------------------------------------
-/* The mysterious jedec flash probe sequence writes a specific pattern of
-   bytes to the flash. This should be general enough to work with any MTD
-   structure that may contain a flash chip, but note that it will corrupt
-   address 0x5555 on SRAM cards if the machine dies between the two 
-   critical operations. */
-int flash_jedec(struct mapped_mtd_info *map)
-{
-   unsigned I;
-   u_char OldVal;
-   unsigned long base;
-   unsigned long baseaddr = 0;
-   unsigned chip = 0;
-   unsigned count;
-   
-   // Who has a page size this small? :>
-   if (map->pagesize < 0x555)
-      return 1;
-   
-   base = map->page(map,0);
-   
-   // Wait for any write/erase operation to settle
-   OldVal = readb(base);
-   for (I = 0; OldVal != readb(base) && I < 10000; I++)
-      OldVal = readb(base);
-   
-   /* Check for sram by writing to it, the write also happens to be part 
-      of the flash reset sequence.. */
-   OldVal = readb(base + 0x555);
-   writeb(OldVal,base + 0x555);
-   writeb(0xF0,base + 0x555);
-   if (OldVal != readb(base + 0x555))
-   {
-      udelay(100);
-      
-      // Set it back and make sure..
-      writeb(OldVal,base + 0x555);
-      if (OldVal == readb(base + 0x555))
-      {
-	 map->mtd.type = MTD_RAM;
-	 return 0;
-      }
-      
-      writeb(0xF0,base + 0x555);
-   }
-   
-   // Probe for chips
-   while (chip < sizeof(map->chips)/sizeof(map->chips[0]))
-   {
-      // Already in jedec mode, we might be doing some address wrap around
-      if (chip != 0 && isjedec(base) != 0)
-      {
-	 /* Try to reset this page and check if that resets the first page
-	    to confirm */
-	 writeb(0xF0,base + 0x555);
-	 if (isjedec(base) != 0)
-	    break;
-	 base = map->page(map,0);
-	 if (isjedec(base) == 0)
-	    break;
-	 base = map->page(map,baseaddr/map->pagesize);
-      }
-      
-      // Send the sequence
-      writeb(0xAA,base + 0x555);
-      writeb(0x55,base + 0x2AA);
-      writeb(0x90,base + 0x555);
-
-      // Check the jedec number
-      if (isjedec(base) == 0)
-      {
-	 /* If this is the first chip it must be rom, otherwise it is the
-	    end of the flash region */
-	 if (chip == 0)
-	 {
-	    map->mtd.type = MTD_ROM;
-	    return 0;
-	 }
-	 break;
-      }      
-      
-      // Store the jdec info
-      set_jedec(map,chip,readb(base + 0),readb(base + 1));
-      map->chips[chip].base = baseaddr;
-      
-      // Jump to the next chip
-      baseaddr += map->chips[chip].size;
-      if (baseaddr/map->pagesize > map->maxsize)
-	 break;
-      base = map->page(map,baseaddr/map->pagesize);
-      if (base == 0)
-	 return -EIO;
-      
-      chip++;
-   }
-
-   // Reset all of the chips
-   map->mtd.size = 0;
-   baseaddr = 0;
-   map->mtd.flags = 0xFFFF;
-   for (I = 0; map->chips[I].jedec != 0; I++)
-   {
-      // Fill in the various MTD structures
-      map->mtd.size += map->chips[I].size;
-      if (map->mtd.erasesize < map->chips[I].sectorsize)
-	 map->mtd.erasesize = map->chips[I].sectorsize;
-      map->mtd.flags &= map->chips[I].capabilities;
-      
-      base = map->page(map,baseaddr/map->pagesize);
-      baseaddr += map->chips[chip].size;
-      writeb(0xF0,base + 0);  // Reset      
-   }   
-   
-   /* Generate a part name that includes the number of different chips and
-      other configuration information */
-   count = 1;
-   map->part[0] = 0;
-   for (I = 0; map->chips[I].jedec != 0; I++)
-   {
-      unsigned J;
-      if (map->chips[I+1].jedec == map->chips[I].jedec)
-      {
-	 count++;
-	 continue;
-      }
-      
-      // Locate the chip in the jedec table
-      for (J = 0; mtd_JEDEC_table[J].jedec != 0; J++)
-      {      
-	 if (mtd_JEDEC_table[J].jedec == map->chips[I].jedec)
-	    break;
-      }
-      
-      if (map->part[0] != 0)
-	 strcat(map->part,",");
-      
-      if (count != 1)
-	 sprintf(map->part+strlen(map->part),"%u*[%s]",count,
-		 mtd_JEDEC_table[J].name);
-      else
-	 sprintf(map->part+strlen(map->part),"%s",
-		 mtd_JEDEC_table[J].name);
-      count = 1;
-   }   
-   return 0;
-}
-									/*}}}*/
-
-// flash_failed - Print a console message about why the failure		/*{{{*/
-// ---------------------------------------------------------------------
-/* Pass the flags value that the flash return before it re-entered read 
-   mode. */
-static void flash_failed(unsigned char code)
-{
-   /* Bit 5 being high indicates that there was an internal device
-      failure, erasure time limits exceeded or something */
-   if ((code & (1 << 5)) != 0)
-   {
-      printk("mtd: Internal Flash failure\n");
-      return;
-   }
-   printk("mtd: Programming didn't take\n");
-}
-									/*}}}*/
-// flash_erase - Generic erase function					/*{{{*/
-// ---------------------------------------------------------------------
-/* This uses the erasure function described in the AMD Flash Handbook, 
-   it will work for flashes with a fixed sector size only. Flashes with
-   a selection of sector sizes (ie the AMD Am29F800B) will need a different
-   routine. This routine tries to parallize erasing multiple chips/sectors 
-   where possible */
-int flash_erase(struct mtd_info *mtd, struct erase_info *instr)
-{
-   unsigned long Time = 0;
-   unsigned long NoTime = 0;
-   unsigned long start = instr->addr, len = instr->len;
-   unsigned int I;
-   struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd;
-
-   // Verify the arguments..
-   if (start + len > map->mtd.size ||
-       (start % map->mtd.erasesize) != 0 ||
-       (len % map->mtd.erasesize) != 0 ||
-       (len/map->mtd.erasesize) == 0)
-      return -EINVAL;
-   
-   flash_chip_scan(map,start,len);
-
-   // Start the erase sequence on each chip
-   for (I = 0; map->chips[I].jedec != 0; I++)
-   {
-      unsigned long off;
-      struct flash_chip *chip = map->chips + I;
-      unsigned long base;
-      unsigned long flags;
-      
-      if (chip->length == 0)
-	 continue;
-      
-      if (page_jump(map,chip->base + chip->start,0x555,&base,0) != 0)
-	 return -EIO;
-      
-      // Send the erase setup code
-      writeb(0xF0,base + 0x555);
-      writeb(0xAA,base + 0x555);
-      writeb(0x55,base + 0x2AA);
-      writeb(0x80,base + 0x555);
-      writeb(0xAA,base + 0x555);
-      writeb(0x55,base + 0x2AA);
-
-      // Use chip erase if possible
-      if (chip->start == 0 && chip->length == chip->size)
-      {
-	 writeb(0x10,base+0x555);
-	 continue;
-      }
-            
-      /* Once we start selecting the erase sectors the delay between each 
-         command must not exceed 50us or it will immediately start erasing 
-         and ignore the other sectors */
-      save_flags(flags);
-      cli();
-      for (off = 0; off < chip->length; off += chip->sectorsize)
-      {
-	 if (page_jump(map,chip->base + chip->start + off,1,&base,0) != 0)
-	    return -EIO;
-	 
-	 // Check to make sure we didn't timeout
-	 writeb(0x30,base);
-	 if ((readb(base) & (1 << 3)) != 0)
-	 {
-	    printk("mtd: Ack! We timed out the erase timer!\n");
-	    return -EIO;
-	 }       	 
-      }
-      restore_flags(flags);
-   }   
-
-   /* We could split this into a timer routine and return early, performing
-      background erasure.. Maybe later if the need warrents */
-   
-   /* Poll the flash for erasure completion, specs say this can take as long
-      as 480 seconds to do all the sectors (for a 2 meg flash). 
-      Erasure time is dependant on chip age, temp and wear.. */
-   Time = 0;
-   NoTime = 0;
-   for (I = 0; map->chips[I].jedec != 0; I++)
-   {
-      struct flash_chip *chip = map->chips + I;
-      unsigned long base;
-      unsigned long off = 0;
-      if (chip->length == 0)
-	 continue;
-      
-      if (page_jump(map,chip->base + chip->start,1,&base,0) != 0)
-	 return -EIO;
-      
-      while (1)
-      {
-	 unsigned char Last[4];
-	 unsigned long Count = 0;
-	 
-	 /* During erase bit 7 is held low and bit 6 toggles, we watch this,
-	    should it stop toggling or go high then the erase is completed,
-  	    or this is not really flash ;> */
-	 Last[0] = readb(base);
-	 Last[1] = readb(base);
-	 Last[2] = readb(base);
-	 for (Count = 3; (Last[(Count - 1) % 4] & (1 << 7)) == 0 && 
-	      Last[(Count - 1) % 4] != Last[(Count - 2) % 4]; Count++)
-	 {
-	    if (NoTime == 0)
-	       Time += HZ/10 - schedule_timeout(HZ/10);
-	    NoTime = 0;
-	    
-	    Last[Count % 4] = readb(base);
-	 
-	    // Count time, max of 15s per sector (according to AMD)
-	    if (Time > 15*len/mtd->erasesize*HZ)
-	    {
-	       printk("mtd: Flash Erase Timed out\n");
-	       return -EIO;
-	    }	    
-	 }
-	 
-	 if (Last[(Count - 1) % 4] == Last[(Count - 2) % 4])
-	 {
-	    flash_failed(Last[(Count - 3) % 4]);
-	    return -EIO;
-	 }
-	 
-	 // Skip to the next chip if we used chip erase
-	 if (chip->length == chip->size)
-	    off = chip->size;
-	 else
-	    off += chip->sectorsize;
-	 
-	 if (off >= chip->length)
-	    break;
-	 if (page_jump(map,chip->base + chip->start + off,1,&base,0) != 0)
-	    return -EIO;	 
-	 NoTime = 1;
-      }      
-   }
-       	 
-   // Paranoid verify of erasure
-   {
-      unsigned long base;
-      unsigned long buflen;
-      while (len > 0)
-      {
-	 unsigned long step;
-	 
-	 if (page_jump(map,start,len,&base,&buflen) != 0)
-	    return -EIO;
-	 start += buflen;
-	 len -= buflen;
-	 step = buflen/128;
-	 for (;buflen != 0; buflen -= step)
-	 {
-	    if (readb(base+buflen-1) != 0xFF)
-	    {
-	       printk("mtd: Flash Erase didn't take %lu %lu %lu\n",buflen,len,start);
-	       return -EIO;
-	    }
-	 }	 
-      }      
-   }   
-   
-   return 0;
-}
-#if 1
-									/*}}}*/
-// flash_write - Generic writing function				/*{{{*/
-// ---------------------------------------------------------------------
-/* This could do parallel writes on multiple chips but doesnt, memory 
-   constraints make that infeasable. This should work with any sort of 
-   linear flash that is not interleved */
-extern int flash_write(struct mtd_info *mtd, loff_t start, size_t len,
-		       size_t *retlen, const u_char *buf)
-{
-   struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd;
-   unsigned long base;
-   unsigned long off;
-   DEBUG(1,"\n");
-   if (start + len > mtd->size)
-      return -EIO;
-   
-   while (len != 0)
-   {
-      // Compute the page offset and reposition
-      base = map->page(map,(u_long)start/map->pagesize);
-      off = (u_long)start %  map->pagesize;
-
-      // Loop over this page
-      for (; off != map->pagesize && len != 0; start++, len--, off++,buf++)
-      {
-	 unsigned char oldbyte = readb(base+off);
-	 unsigned char Last[4];
-	 unsigned long Count = 0;
-
-	 if (oldbyte == *buf)
-	    continue;
-	 if (((~oldbyte) & *buf) != 0)
-	    printk("mtd: warn: Trying to set a 0 to a 1\n");
-	     
-	 // Write
-	 writeb(0xAA,base + 0x555);
-	 writeb(0x55,base + 0x2AA);
-	 writeb(0xA0,base + 0x555);
-	 writeb(*buf,base + off);
-	 Last[0] = readb(base + off);
-	 Last[1] = readb(base + off);
-	 Last[2] = readb(base + off);
-	 
-	 /* Wait for the flash to finish the operation. We store the last 4
-	    status bytes that have been retrieved so we can determine why
-	    it failed. The toggle bits keep toggling when there is a 
-	    failure */
-	 for (Count = 3; Last[(Count - 1) % 4] != Last[(Count - 2) % 4] &&
-	      Count < 10000; Count++)
-	    Last[Count % 4] = readb(base + off);
-	 if (Last[(Count - 1) % 4] != *buf)
-	 {
-	    flash_failed(Last[(Count - 3) % 4]);
-	    return -EIO;
-	 }	 
-      }
-   }
-   *retlen = len;
-   return 0;
-}
-#endif
-
-// ram_write - Generic writing function	for ram				/*{{{*/
-// ---------------------------------------------------------------------
-/* */
-extern int ram_write(struct mtd_info *mtd, loff_t start, size_t len,
-		       size_t *retlen, const u_char *buf)
-{
-   struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd;
-   unsigned long base;
-   size_t origlen = len;
-   unsigned long buflen;
-   DEBUG(1,"\n");
-   if (start + len > mtd->size)
-      return -EIO;
-   
-   while (len != 0)
-   {
-      // Reposition..
-      if (page_jump(map,start,len,&base,&buflen) != 0)
-	 return -EIO;
-      
-      // Copy
-      memcpy_toio(base,buf,buflen);
-      len -= buflen;
-      start += buflen;
-   }
-   *retlen = origlen;
-   return 0;
-}
-
-// rom_read - Read handler for any sort of device			/*{{{*/
-// ---------------------------------------------------------------------
-/* This is a generic read function that should work with any device in the
-   mapped region. */
-extern int rom_read(struct mtd_info *mtd, loff_t start, size_t len,
-		    size_t *retlen, u_char *buf)
-{
-   struct mapped_mtd_info *map = (struct mapped_mtd_info *)mtd;
-   size_t origlen = len;
-   unsigned long base;
-   unsigned long buflen;
-
-   printk("Rom_Read\n");
-   if (start + len > mtd->size)
-      return -EIO;
-   
-   while (len != 0)
-   {
-      // Reposition..
-      if (page_jump(map,start,len,&base,&buflen) != 0)
-	 return -EIO;
-      
-      // Copy
-      memcpy_fromio(buf,base,buflen);
-      len -= buflen;
-      start += buflen;
-   }
-   *retlen = origlen;
-   return 0;
-}
-
-// page_jump - Move the window and return the buffer			/*{{{*/
-// ---------------------------------------------------------------------
-/* Unlike the page function this returns a buffer and length adjusted for
-   the page dimensions and the reading offset into the page, simplifies
-   many of the other routines */
-int page_jump(struct mapped_mtd_info *map,unsigned long start,
-	      unsigned long len,unsigned long *base,
-	      unsigned long *retlen)
-{
-   DEBUG(1,"Page Jump\n");
-   if (start > map->mtd.size || start + len > map->mtd.size)
-      return -EINVAL;
-      
-   *base = map->page(map,start/map->pagesize);
-   if (*base == 0)
-      return -EIO;
-
-   *base += start % map->pagesize;
-
-   // If retlen is 0 that mean the caller requires len bytes, no quibbling.
-   if (retlen == 0)
-   {
-      if (len > map->pagesize  - (start % map->pagesize))
-	 return -EIO;
-      return 0;
-   }
-   
-   // Compute the buffer paramaters and return
-   if (len > map->pagesize - (start % map->pagesize))
-      *retlen = map->pagesize - (start % map->pagesize);
-   else
-      *retlen = len;
-   return 0;
-}
-									/*}}}*/
-// flash_chip_scan - Intersect a region with the flash chip structure	/*{{{*/
-// ---------------------------------------------------------------------
-/* This is used to enhance the speed of the erase routine,
-   when things are being done to multiple chips it is possible to
-   parallize the operations, particularly full memory erases of multi
-   chip memories benifit */
-
-void flash_chip_scan(struct mapped_mtd_info *map,unsigned long start,
-		     unsigned long len)
-{
-   unsigned int I = 0;
-
-   DEBUG(1,"\n");
-   // Zero the records
-   for (I = 0; map->chips[I].jedec != 0; I++)
-      map->chips[I].start = map->chips[I].length = 0;
-   
-   // Intesect our region with the chip structures
-   for (I = 0; map->chips[I].jedec != 0 && len != 0; I++)
-   {
-      // Havent found the start yet
-      if (start >= map->chips[I].base + map->chips[I].size)
-	 continue;
-
-      // Store the portion of this chip that is being effected
-      map->chips[I].start = start - map->chips[I].base;
-      if (len <= map->chips[I].size - map->chips[I].start)
-	 map->chips[I].length = len;
-      else
-	 map->chips[I].length = map->chips[I].size - map->chips[I].start;
-      len -= map->chips[I].length;
-      start = map->chips[I].base + map->chips[I].size;
-   }
-}
-									/*}}}*/
-
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mixmem.c linux/drivers/mtd/mixmem.c
--- v2.4.1/linux/drivers/mtd/mixmem.c	Tue Jul  4 10:10:05 2000
+++ linux/drivers/mtd/mixmem.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <asm/io.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mtdblock.c linux/drivers/mtd/mtdblock.c
--- v2.4.1/linux/drivers/mtd/mtdblock.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/mtd/mtdblock.c	Fri Feb  9 11:30:23 2001
@@ -10,7 +10,7 @@
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mtd/mtd.h>
 
 #define MAJOR_NR MTD_BLOCK_MAJOR
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mtdchar.c linux/drivers/mtd/mtdchar.c
--- v2.4.1/linux/drivers/mtd/mtdchar.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/mtd/mtdchar.c	Fri Feb  9 11:30:23 2001
@@ -1,6 +1,5 @@
 /*
- * Almost: $Id: mtdchar.c,v 1.21 2000/12/09 21:15:12 dwmw2 Exp $
- * (With some of the compatibility for previous kernels taken out)
+ * $Id: mtdchar.c,v 1.21.2.3 2001/01/09 00:18:31 dwmw2 Exp $
  *
  * Character-device access to raw MTD devices.
  *
@@ -13,7 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mtd/mtd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #ifdef CONFIG_DEVFS_FS
 #include <linux/devfs_fs_kernel.h>
@@ -447,10 +446,6 @@
 mod_init_t init_mtdchar(void)
 {
 #ifdef CONFIG_DEVFS_FS
-	int i;
-	char name[8];
-	struct mtd_info* mtd;
-
 	if (devfs_register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops))
 	{
 		printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mtdcore.c linux/drivers/mtd/mtdcore.c
--- v2.4.1/linux/drivers/mtd/mtdcore.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/mtdcore.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mtdpart.c linux/drivers/mtd/mtdpart.c
--- v2.4.1/linux/drivers/mtd/mtdpart.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/mtdpart.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/list.h>
 
 #include <linux/mtd/mtd.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/mtdram.c linux/drivers/mtd/mtdram.c
--- v2.4.1/linux/drivers/mtd/mtdram.c	Tue Jul 18 15:03:56 2000
+++ linux/drivers/mtd/mtdram.c	Fri Feb  9 11:30:23 2001
@@ -12,7 +12,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/mtd/compatmac.h>
 #include <linux/mtd/mtd.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/nftl.c linux/drivers/mtd/nftl.c
--- v2.4.1/linux/drivers/mtd/nftl.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/nftl.c	Fri Feb  9 11:30:23 2001
@@ -63,7 +63,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/blkpg.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/nftlmount.c linux/drivers/mtd/nftlmount.c
--- v2.4.1/linux/drivers/mtd/nftlmount.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/mtd/nftlmount.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/miscdevice.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/mtd/mtd.h>
@@ -118,7 +118,7 @@
 				break;
 			}
 		}
-	ReplUnitTable:
+	ReplUnitTable:;
 	}
 
 	if (boot_record_count == 0) {
@@ -652,7 +652,7 @@
 				}
 			}
 		}
-	examine_ReplUnitTable:
+	examine_ReplUnitTable:;
 	}
 
 	/* second pass to format unreferenced blocks  and init free block count */
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/octagon-5066.c linux/drivers/mtd/octagon-5066.c
--- v2.4.1/linux/drivers/mtd/octagon-5066.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/octagon-5066.c	Fri Feb 16 16:02:36 2001
@@ -1,4 +1,4 @@
-// $Id: octagon-5066.c,v 1.12 2000/11/27 08:50:22 dwmw2 Exp $
+// $Id: octagon-5066.c,v 1.12.2.1 2001/02/15 10:12:48 dwmw2 Exp $
 /* ######################################################################
 
    Octagon 5066 MTD Driver. 
@@ -25,7 +25,7 @@
    ##################################################################### */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <asm/io.h>
@@ -273,7 +273,7 @@
 		}
 	}
 	
-	if (!oct5066_mtd[1] && !oct5066_mtd[2]) {
+	if (!oct5066_mtd[0] && !oct5066_mtd[1]) {
 		cleanup_oct5066();
 		return -ENXIO;
 	}	  
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/pmc551.c linux/drivers/mtd/pmc551.c
--- v2.4.1/linux/drivers/mtd/pmc551.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/mtd/pmc551.c	Fri Feb 16 16:02:36 2001
@@ -78,7 +78,7 @@
 #include <linux/sched.h>
 #include <linux/init.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
@@ -483,7 +483,7 @@
         pci_write_config_word( dev, PMC551_SDRAM_CMD, 0x00bf );
 
         /*
-         * Wait untill command has gone through
+         * Wait until command has gone through
          * FIXME: register spinning issue
          */
         do {	pci_read_config_word( dev, PMC551_SDRAM_CMD, &cmd );
@@ -709,7 +709,7 @@
                        PCI_Device->irq);
 
                 /*
-                 * The PMC551 device acts VERY wierd if you don't init it
+                 * The PMC551 device acts VERY weird if you don't init it
                  * first.  i.e. it will not correctly report devsel.  If for
                  * some reason the sdram is in a wrote-protected state the
                  * device will DEVSEL when it is written to causing problems
@@ -804,6 +804,7 @@
 
                 if (add_mtd_device(mtd)) {
                         printk(KERN_NOTICE "pmc551: Failed to register new device\n");
+			iounmap(priv->start);
                         kfree(mtd->priv);
                         kfree(mtd);
                         break;
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/rpxlite.c linux/drivers/mtd/rpxlite.c
--- v2.4.1/linux/drivers/mtd/rpxlite.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/rpxlite.c	Sun Feb  4 10:05:30 2001
@@ -94,6 +94,7 @@
 		return 0;
 	}
 
+	iounmap((void *)rpxlite_map.map_priv_1);
 	return -ENXIO;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/slram.c linux/drivers/mtd/slram.c
--- v2.4.1/linux/drivers/mtd/slram.c	Tue Jul  4 10:10:05 2000
+++ linux/drivers/mtd/slram.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/major.h>
@@ -200,6 +200,7 @@
 	if (add_mtd_device(mymtd))
 	{
 		printk("Failed to register new device\n");
+	        iounmap(((struct mypriv *)mymtd->priv)->start);
 		kfree(mymtd->priv);
 		kfree(mymtd);
 		return -EAGAIN;
diff -u --recursive --new-file v2.4.1/linux/drivers/mtd/vmax301.c linux/drivers/mtd/vmax301.c
--- v2.4.1/linux/drivers/mtd/vmax301.c	Mon Dec 11 14:57:58 2000
+++ linux/drivers/mtd/vmax301.c	Fri Feb  9 11:30:23 2001
@@ -17,7 +17,7 @@
    ##################################################################### */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <asm/spinlock.h>
@@ -228,8 +228,10 @@
 		}
 	}
 
-	if (!vmax_mtd[1] && !vmax_mtd[2])
+	if (!vmax_mtd[1] && !vmax_mtd[2]) {
+		iounmap(iomapadr);
 		return -ENXIO;
+	}
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c501.c linux/drivers/net/3c501.c
--- v2.4.1/linux/drivers/net/3c501.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/3c501.c	Tue Feb 13 13:15:05 2001
@@ -4,7 +4,7 @@
 
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU Public License,
+    distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
 
     This is a device driver for the 3Com Etherlink 3c501.
@@ -101,7 +101,7 @@
 #include <linux/fcntl.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/config.h>	/* for CONFIG_IP_MULTICAST */
@@ -796,6 +796,7 @@
 		insb(DATAPORT, skb_put(skb,pkt_len), pkt_len);
 		skb->protocol=eth_type_trans(skb,dev);
 		netif_rx(skb);
+		dev->last_rx = jiffies;
 		lp->stats.rx_packets++;
 		lp->stats.rx_bytes+=pkt_len;
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c503.c linux/drivers/net/3c503.c
--- v2.4.1/linux/drivers/net/3c503.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/3c503.c	Tue Feb 13 13:15:05 2001
@@ -4,7 +4,7 @@
 
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU Public License,
+    distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
 
     The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c505.c linux/drivers/net/3c505.c
--- v2.4.1/linux/drivers/net/3c505.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/3c505.c	Tue Feb 13 13:15:05 2001
@@ -99,7 +99,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <asm/bitops.h>
@@ -689,6 +689,7 @@
 					skb->protocol = eth_type_trans(skb,dev);
 					adapter->stats.rx_bytes += skb->len;
 					netif_rx(skb);
+					dev->last_rx = jiffies;
 				}
 			}
 			adapter->dmaing = 0;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c507.c linux/drivers/net/3c507.c
--- v2.4.1/linux/drivers/net/3c507.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/3c507.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
@@ -59,7 +59,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 
@@ -835,7 +835,9 @@
 
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += pkt_len;
 		}
 
 		/* Clear the status word and set End-of-List on the rx frame. */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c509.c linux/drivers/net/3c509.c
--- v2.4.1/linux/drivers/net/3c509.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/3c509.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	Copyright 1994-1998 by Donald Becker.
 	Copyright 1993 United States Government as represented by the
 	Director, National Security Agency.	 This software may be used and
-	distributed according to the terms of the GNU Public License,
+	distributed according to the terms of the GNU General Public License,
 	incorporated herein by reference.
 
 	This driver is for the 3Com EtherLinkIII series.
@@ -59,7 +59,7 @@
 #include <linux/interrupt.h>
 #include <linux/errno.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -889,6 +889,7 @@
 				outw(RxDiscard, ioaddr + EL3_CMD); /* Pop top Rx packet. */
 				skb->protocol = eth_type_trans(skb,dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
 				continue;
 			}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c515.c linux/drivers/net/3c515.c
--- v2.4.1/linux/drivers/net/3c515.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/3c515.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 	Written 1997-1998 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This driver is for the 3Com ISA EtherLink XL "Corkscrew" 3c515 ethercard.
 
@@ -57,7 +57,7 @@
 #include <linux/errno.h>
 #include <linux/in.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <asm/bitops.h>
@@ -599,6 +599,8 @@
 	/* Caution: quad-word alignment required for rings! */
 	dev->priv =
 	    kmalloc(sizeof(struct corkscrew_private), GFP_KERNEL);
+	if (!dev->priv)
+		return NULL;
 	memset(dev->priv, 0, sizeof(struct corkscrew_private));
 	dev = init_etherdev(dev, sizeof(struct corkscrew_private));
 	dev->base_addr = ioaddr;
@@ -1079,6 +1081,7 @@
 	}
 	/* Put out the doubleword header... */
 	outl(skb->len, ioaddr + TX_FIFO);
+	vp->stats.tx_bytes += skb->len;
 #ifdef VORTEX_BUS_MASTER
 	if (vp->bus_master) {
 		/* Set the bus-master controller to transfer the packet. */
@@ -1137,7 +1140,6 @@
 			outb(0x00, ioaddr + TxStatus);	/* Pop the status stack. */
 		}
 	}
-	vp->stats.tx_bytes += skb->len;
 	return 0;
 }
 
@@ -1340,7 +1342,7 @@
 				netif_rx(skb);
 				dev->last_rx = jiffies;
 				vp->stats.rx_packets++;
-				vp->stats.rx_bytes += skb->len;
+				vp->stats.rx_bytes += pkt_len;
 				/* Wait a limited time to go to next packet. */
 				for (i = 200; i >= 0; i--)
 					if (! (inw(ioaddr + EL3_STATUS) & CmdInProgress)) 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c523.c linux/drivers/net/3c523.c
--- v2.4.1/linux/drivers/net/3c523.c	Sat Dec 30 11:23:13 2000
+++ linux/drivers/net/3c523.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 
 
    This is an extension to the Linux operating system, and is covered by the
-   same Gnu Public License that covers that work.
+   same GNU General Public License that covers that work.
 
    Copyright 1995, 1996 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
 
@@ -91,7 +91,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/mca.h>
@@ -148,9 +148,9 @@
 
 #define RECV_BUFF_SIZE 1524	/* slightly oversized */
 #define XMIT_BUFF_SIZE 1524	/* slightly oversized */
-#define NUM_XMIT_BUFFS 4	/* config for both, 8K and 16K shmem */
-#define NUM_RECV_BUFFS_8  1	/* config for 8K shared mem */
-#define NUM_RECV_BUFFS_16 6	/* config for 16K shared mem */
+#define NUM_XMIT_BUFFS 1	/* config for both, 8K and 16K shmem */
+#define NUM_RECV_BUFFS_8  4	/* config for 8K shared mem */
+#define NUM_RECV_BUFFS_16 9	/* config for 16K shared mem */
 
 #if (NUM_XMIT_BUFFS == 1)
 #define NO_NOPCOMMANDS		/* only possible with NUM_XMIT_BUFFS=1 */
@@ -197,6 +197,7 @@
 	struct net_device_stats stats;
 	unsigned long base;
 	char *memtop;
+	unsigned long mapped_start;		/* Start of ioremap */
 	volatile struct rfd_struct *rfd_last, *rfd_top, *rfd_first;
 	volatile struct scp_struct *scp;	/* volatile is important */
 	volatile struct iscp_struct *iscp;	/* volatile is important */
@@ -303,13 +304,13 @@
 	char *iscp_addrs[2];
 	int i = 0;
 
-	p->base = where + size - 0x01000000;
-	p->memtop = phys_to_virt(where) + size;
-	p->scp = (struct scp_struct *)phys_to_virt(p->base + SCP_DEFAULT_ADDRESS);
+	p->base = (unsigned long) bus_to_virt((unsigned long)where) + size - 0x01000000;
+	p->memtop = bus_to_virt((unsigned long)where) + size;
+	p->scp = (struct scp_struct *)(p->base + SCP_DEFAULT_ADDRESS);
 	memset((char *) p->scp, 0, sizeof(struct scp_struct));
 	p->scp->sysbus = SYSBUSVAL;	/* 1 = 8Bit-Bus, 0 = 16 Bit */
 
-	iscp_addrs[0] = phys_to_virt(where);
+	iscp_addrs[0] = bus_to_virt((unsigned long)where);
 	iscp_addrs[1] = (char *) p->scp - sizeof(struct iscp_struct);
 
 	for (i = 0; i < 2; i++) {
@@ -325,6 +326,7 @@
 
 		/* apparently, you sometimes have to kick the 82586 twice... */
 		elmc_id_attn586();
+		DELAY(1);
 
 		if (p->iscp->busy) {	/* i82586 clears 'busy' after successful init */
 			return 0;
@@ -344,8 +346,8 @@
 	elmc_id_reset586();
 	DELAY(2);
 
-	p->scp = (struct scp_struct *) phys_to_virt(p->base + SCP_DEFAULT_ADDRESS);
-	p->scb = (struct scb_struct *) phys_to_virt(dev->mem_start);
+	p->scp = (struct scp_struct *) (p->base + SCP_DEFAULT_ADDRESS);
+	p->scb = (struct scb_struct *) bus_to_virt(dev->mem_start);
 	p->iscp = (struct iscp_struct *) ((char *) p->scp - sizeof(struct iscp_struct));
 
 	memset((char *) p->iscp, 0, sizeof(struct iscp_struct));
@@ -409,6 +411,8 @@
 	u_char revision = 0;
 	int i = 0;
 	unsigned int size = 0;
+	int retval;
+	struct priv *pr;
 
 	SET_MODULE_OWNER(dev);
 	if (MCA_bus == 0) {
@@ -428,18 +432,24 @@
 		   Also reject it if the card is already in use.
 		 */
 
-		if((irq && irq != dev->irq) || (base_addr && base_addr != dev->base_addr)
-		   || check_region(dev->base_addr,ELMC_IO_EXTENT)) {
+		if ((irq && irq != dev->irq) || 
+		    (base_addr && base_addr != dev->base_addr)) {
 			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
 			continue;
 		}
+		if (!request_region(dev->base_addr, ELMC_IO_EXTENT, dev->name)) {
+			slot = mca_find_adapter(ELMC_MCA_ID, slot + 1);
+			continue;
+		}
+
 		/* found what we're looking for... */
 		break;
 	}
 
 	/* we didn't find any 3c523 in the slots we checked for */
 	if (slot == MCA_NOTFOUND) {
-		return ((base_addr || irq) ? ENXIO : ENODEV);
+		retval = ((base_addr || irq) ? -ENXIO : -ENODEV);
+		goto err_out;
 	}
 	mca_set_adapter_name(slot, "3Com 3c523 Etherlink/MC");
 	mca_set_adapter_procfn(slot, (MCA_ProcFn) elmc_getinfo, dev);
@@ -479,15 +489,14 @@
 		break;
 	}
 
-	request_region(dev->base_addr, ELMC_IO_EXTENT, "3c523");
-
-	dev->priv = (void *) kmalloc(sizeof(struct priv), GFP_KERNEL);
+	pr = dev->priv = kmalloc(sizeof(struct priv), GFP_KERNEL);
 	if (dev->priv == NULL) {
-		return -ENOMEM;
+		retval = -ENOMEM;
+		goto err_out;
 	}
-	memset((char *) dev->priv, 0, sizeof(struct priv));
+	memset(pr, 0, sizeof(struct priv));
 
-	((struct priv *) (dev->priv))->slot = slot;
+	pr->slot = slot;
 
 	printk(KERN_INFO "%s: 3Com 3c523 Rev 0x%x at %#lx\n", dev->name, (int) revision,
 	       dev->base_addr);
@@ -513,18 +522,21 @@
 	if (!check586(dev, dev->mem_start, size)) {
 		printk(KERN_ERR "%s: memprobe, Can't find memory at 0x%lx!\n", dev->name,
 		       dev->mem_start);
-		release_region(dev->base_addr, ELMC_IO_EXTENT);
-		return -ENODEV;
+		kfree(dev->priv);
+		dev->priv = NULL;
+		retval = -ENODEV;
+		goto err_out;
 	}
 	dev->mem_end = dev->mem_start + size;	/* set mem_end showed by 'ifconfig' */
 
-	((struct priv *) (dev->priv))->base = dev->mem_start + size - 0x01000000;
+	pr->memtop = bus_to_virt(dev->mem_start) + size;
+	pr->base = (unsigned long) bus_to_virt(dev->mem_start) + size - 0x01000000;
 	alloc586(dev);
 
 	elmc_id_reset586();	/* make sure it doesn't generate spurious ints */
 
 	/* set number of receive-buffs according to memsize */
-	((struct priv *) dev->priv)->num_recv_buffs = NUM_RECV_BUFFS_16;
+	pr->num_recv_buffs = NUM_RECV_BUFFS_16;
 
 	/* dump all the assorted information */
 	printk(KERN_INFO "%s: IRQ %d, %sternal xcvr, memory %#lx-%#lx.\n", dev->name,
@@ -563,6 +575,9 @@
 #endif
 
 	return 0;
+err_out:
+	release_region(dev->base_addr, ELMC_IO_EXTENT);
+	return retval;
 }
 
 /**********************************************
@@ -944,9 +959,11 @@
 				if (skb != NULL) {
 					skb->dev = dev;
 					skb_reserve(skb, 2);	/* 16 byte alignment */
-					memcpy(skb_put(skb, totlen), (u8 *)phys_to_virt(p->base) + (unsigned long) rbd->buffer, totlen);
+					skb_put(skb,totlen);
+					eth_copy_and_sum(skb, (char *) p->base+(unsigned long) rbd->buffer,totlen,0);
 					skb->protocol = eth_type_trans(skb, dev);
 					netif_rx(skb);
+					dev->last_rx = jiffies;
 					p->stats.rx_packets++;
 					p->stats.rx_bytes += totlen;
 				} else {
@@ -1086,6 +1103,7 @@
 static int elmc_send_packet(struct sk_buff *skb, struct net_device *dev)
 {
 	int len;
+	int i;
 #ifndef NO_NOPCOMMANDS
 	int next_nop;
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c523.h linux/drivers/net/3c523.h
--- v2.4.1/linux/drivers/net/3c523.h	Thu Dec 12 06:51:09 1996
+++ linux/drivers/net/3c523.h	Fri Feb  9 11:40:02 2001
@@ -9,7 +9,7 @@
  * Intel i82586 Ethernet definitions
  *
  * This is an extension to the Linux operating system, and is covered by the
- * same Gnu Public License that covers that work.
+ * same GNU General Public License that covers that work.
  *
  * Copyright 1995 by Chris Beauregard (cpbeaure@undergrad.math.uwaterloo.ca)
  *
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c527.c linux/drivers/net/3c527.c
--- v2.4.1/linux/drivers/net/3c527.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/3c527.c	Tue Feb 13 13:15:05 2001
@@ -11,7 +11,7 @@
  *	documentation.
  *
  *	This software may be used and distributed according to the terms
- *	of the GNU Public License, incorporated herein by reference.
+ *	of the GNU General Public License, incorporated herein by reference.
  *
  */
 
@@ -66,7 +66,7 @@
 #include <linux/mca.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -1069,9 +1069,10 @@
 					bus_to_virt(p->data), length);
 				skb->protocol=eth_type_trans(skb,dev);
 				skb->dev=dev;
-				lp->net_stats.rx_packets++;
-				lp->net_stats.rx_bytes+=skb->len;
 				netif_rx(skb);
+				dev->last_rx = jiffies;
+				lp->net_stats.rx_packets++;
+				lp->net_stats.rx_bytes += length;
 			}
 			else
 				lp->net_stats.rx_dropped++;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.4.1/linux/drivers/net/3c59x.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/3c59x.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 	Written 1996-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This driver is for the 3Com "Vortex" and "Boomerang" series ethercards.
 	Members of the series include Fast EtherLink 3c590/3c592/3c595/3c597
@@ -192,7 +192,7 @@
 #include <linux/errno.h>
 #include <linux/in.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/7990.c linux/drivers/net/7990.c
--- v2.4.1/linux/drivers/net/7990.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/7990.c	Tue Feb 13 13:15:05 2001
@@ -21,7 +21,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -303,8 +303,10 @@
                                          (unsigned char *)&(ib->rx_buf [lp->rx_new][0]),
                                          len, 0);
                         skb->protocol = eth_type_trans (skb, dev);
-                        netif_rx (skb);
-                        lp->stats.rx_packets++;
+			netif_rx (skb);
+			dev->last_rx = jiffies;
+			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += len;
                 }
 
                 /* Return the packet to the pool */
@@ -492,7 +494,7 @@
 	printk("lance_tx_timeout\n");
 	lance_reset(dev);
 	dev->trans_start = jiffies;
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/8139too.c linux/drivers/net/8139too.c
--- v2.4.1/linux/drivers/net/8139too.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/net/8139too.c	Tue Feb 13 13:15:46 2001
@@ -35,7 +35,7 @@
 	-----<snip>-----
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Contributors:
 
@@ -1828,6 +1828,7 @@
 
 			skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
+			dev->last_rx = jiffies;
 			tp->stats.rx_bytes += pkt_size;
 			tp->stats.rx_packets++;
 		} else {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/82596.c linux/drivers/net/82596.c
--- v2.4.1/linux/drivers/net/82596.c	Tue Nov 14 11:24:14 2000
+++ linux/drivers/net/82596.c	Tue Feb 13 13:15:05 2001
@@ -32,7 +32,7 @@
    Written 1993 by Donald Becker.
    Copyright 1993 United States Government as represented by the Director,
    National Security Agency. This software may only be used and distributed
-   according to the terms of the GNU Public License as modified by SRC,
+   according to the terms of the GNU General Public License as modified by SRC,
    incorporated herein by reference.
 
    The author may be reached as becker@super.org or
@@ -51,7 +51,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
@@ -807,6 +807,7 @@
 						pkt_len);
 #endif
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
 				lp->stats.rx_bytes+=pkt_len;
 			}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/8390.c linux/drivers/net/8390.c
--- v2.4.1/linux/drivers/net/8390.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/8390.c	Sun Feb  4 10:05:30 2001
@@ -6,7 +6,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
@@ -742,6 +742,7 @@
 				ei_block_input(dev, pkt_len, skb, current_offset + sizeof(rx_frame));
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				ei_local->stat.rx_packets++;
 				ei_local->stat.rx_bytes += pkt_len;
 				if (pkt_stat & ENRSR_PHY)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/8390.h linux/drivers/net/8390.h
--- v2.4.1/linux/drivers/net/8390.h	Thu Jan  4 14:52:01 2001
+++ linux/drivers/net/8390.h	Wed Feb 21 16:11:10 2001
@@ -45,10 +45,6 @@
 extern unsigned long autoirq_report(int waittime);
 #endif
 
-/* Currently unused - delete in v2.5.x after purging from drivers */
-#define load_8390_module(driver)	0
-#define unload_8390_module()		do { } while (0)
-
 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);
@@ -67,7 +63,8 @@
 	unsigned char mcfilter[8];
 	unsigned open:1;
 	unsigned word16:1;  		/* We have the 16-bit (vs 8-bit) version of the card. */
-	unsigned bigendian:1;		/* 16-bit big endian mode */
+	unsigned bigendian:1;		/* 16-bit big endian mode. Do NOT */
+					/* set this on random 8390 clones! */
 	unsigned txing:1;		/* Transmit Active */
 	unsigned irqlock:1;		/* 8390's intrs disabled when '1'. */
 	unsigned dmaing:1;		/* Remote DMA Active */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.4.1/linux/drivers/net/Config.in	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/Config.in	Tue Feb 13 13:15:05 2001
@@ -52,7 +52,7 @@
    if [ "$CONFIG_SGI_IP27" = "y" ]; then
       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
-   if [ "CONFIG_IA64_SGI_SN1" = "y" ]; then
+   if [ "$CONFIG_IA64_SGI_SN1" = "y" ]; then
       bool '  SGI IOC3 Ethernet' CONFIG_SGI_IOC3_ETH
    fi
    if [ "$CONFIG_SUPERH" = "y" ]; then
@@ -103,9 +103,7 @@
    dep_bool '  Other ISA cards' CONFIG_NET_ISA $CONFIG_ISA
    if [ "$CONFIG_NET_ISA" = "y" ]; then
       tristate '    Cabletron E21xx support' CONFIG_E2100
-      if [ "$CONFIG_OBSOLETE" = "y" ]; then
-         tristate '    EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
-      fi
+      tristate '    EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
       tristate '    EtherExpress 16 support' CONFIG_EEXPRESS
       tristate '    EtherExpressPro support/EtherExpress 10 (i82595) support' CONFIG_EEXPRESS_PRO
       if [ "$CONFIG_OBSOLETE" = "y" ]; then
diff -u --recursive --new-file v2.4.1/linux/drivers/net/LICENSE.SRC linux/drivers/net/LICENSE.SRC
--- v2.4.1/linux/drivers/net/LICENSE.SRC	Wed Dec  1 04:44:15 1993
+++ linux/drivers/net/LICENSE.SRC	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used
-    and distributed according to the terms of the GNU Public License,
+    and distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
 
     In addition to the disclaimers in the GPL, SRC expressly disclaims any
diff -u --recursive --new-file v2.4.1/linux/drivers/net/Space.c linux/drivers/net/Space.c
--- v2.4.1/linux/drivers/net/Space.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/Space.c	Tue Feb 13 13:15:05 2001
@@ -170,7 +170,7 @@
  * drivers that probe for EISA cards (in the ISA group).  These are the
  * EISA only driver probes, and also the legacy PCI probes
  */
-struct devprobe eisa_probes[] __initdata = {
+static struct devprobe eisa_probes[] __initdata = {
 #ifdef CONFIG_DE4X5             /* DEC DE425, DE434, DE435 adapters */
 	{de4x5_probe, 0},
 #endif
@@ -193,7 +193,7 @@
 };
 
 
-struct devprobe mca_probes[] __initdata = {
+static struct devprobe mca_probes[] __initdata = {
 #ifdef CONFIG_ULTRAMCA 
 	{ultramca_probe, 0},
 #endif
@@ -216,7 +216,7 @@
  * ISA probes that touch addresses < 0x400 (including those that also
  * look for EISA/PCI/MCA cards in addition to ISA cards).
  */
-struct devprobe isa_probes[] __initdata = {
+static struct devprobe isa_probes[] __initdata = {
 #ifdef CONFIG_EL3		/* ISA, EISA, MCA 3c5x9 */
 	{el3_probe, 0},
 #endif
@@ -319,7 +319,7 @@
 	{NULL, 0},
 };
 
-struct devprobe parport_probes[] __initdata = {
+static struct devprobe parport_probes[] __initdata = {
 #ifdef CONFIG_DE600		/* D-Link DE-600 adapter */
 	{de600_probe, 0},
 #endif
@@ -329,7 +329,7 @@
 	{NULL, 0},
 };
 
-struct devprobe m68k_probes[] __initdata = {
+static struct devprobe m68k_probes[] __initdata = {
 #ifdef CONFIG_ATARILANCE	/* Lance-based Atari ethernet boards */
 	{atarilance_probe, 0},
 #endif
@@ -367,14 +367,14 @@
 };
 
 
-struct devprobe sgi_probes[] __initdata = {
+static struct devprobe sgi_probes[] __initdata = {
 #ifdef CONFIG_SGISEEQ
 	{sgiseeq_probe, 0},
 #endif
 	{NULL, 0},
 };
 
-struct devprobe mips_probes[] __initdata = {
+static struct devprobe mips_probes[] __initdata = {
 #ifdef CONFIG_MIPS_JAZZ_SONIC
 	{sonic_probe, 0},
 #endif
@@ -640,47 +640,6 @@
 #define	NEXT_DEV	(&sbni0_dev)
 #endif 
 	
-/* S/390 channels */
-#ifdef CONFIG_CTC
-    extern int ctc_probe(struct net_device *dev);
-    static struct net_device ctc7_dev =
-       {"ctc7", 0, 0, 0, 0, 0, 0, 0, 0, 0, NEXT_DEV,  ctc_probe};
-    static struct net_device ctc6_dev =
-       {"ctc6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc7_dev, ctc_probe};
-    static struct net_device ctc5_dev =
-       {"ctc5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc6_dev, ctc_probe};
-    static struct net_device ctc4_dev =
-       {"ctc4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc5_dev, ctc_probe};
-    static struct net_device ctc3_dev =
-       {"ctc3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc4_dev, ctc_probe};
-    static struct net_device ctc2_dev =
-       {"ctc2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc3_dev, ctc_probe};
-    static struct net_device ctc1_dev =
-       {"ctc1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc2_dev, ctc_probe};
-    static struct net_device ctc0_dev =
-       {"ctc0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc1_dev, ctc_probe}; 
-
-    static struct net_device escon7_dev =
-       {"escon7", 0, 0, 0, 0, 0, 0, 0, 0, 0, &ctc0_dev,   ctc_probe};
-    static struct net_device escon6_dev =
-       {"escon6", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon7_dev, ctc_probe};
-    static struct net_device escon5_dev =
-       {"escon5", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon6_dev, ctc_probe};
-    static struct net_device escon4_dev =
-       {"escon4", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon5_dev, ctc_probe};
-    static struct net_device escon3_dev =
-       {"escon3", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon4_dev, ctc_probe};
-    static struct net_device escon2_dev =
-       {"escon2", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon3_dev, ctc_probe};
-    static struct net_device escon1_dev =
-       {"escon1", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon2_dev, ctc_probe};
-    static struct net_device escon0_dev =
-       {"escon0", 0, 0, 0, 0, 0, 0, 0, 0, 0, &escon1_dev, ctc_probe}; 
-
-#undef  NEXT_DEV
-#define NEXT_DEV        (&escon0_dev)                                  
-#endif  
-
 /*
  *	The loopback device is global so it can be directly referenced
  *	by the network code. Also, it must be first on device list.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/a2065.c linux/drivers/net/a2065.c
--- v2.4.1/linux/drivers/net/a2065.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/a2065.c	Tue Feb 13 13:15:05 2001
@@ -43,7 +43,7 @@
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/config.h>
 #include <linux/init.h>
@@ -335,7 +335,9 @@
 					 len, 0);
 			skb->protocol = eth_type_trans (skb, dev);
 			netif_rx (skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += len;
 		}
 
 		/* Return the packet to the pool */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ac3200.c linux/drivers/net/ac3200.c
--- v2.4.1/linux/drivers/net/ac3200.c	Tue Nov 14 13:16:37 2000
+++ linux/drivers/net/ac3200.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 	Written 1993, 1994 by Donald Becker.
 	Copyright 1993 United States Government as represented by the Director,
 	National Security Agency.  This software may only be used and distributed
-	according to the terms of the GNU Public License as modified by SRC,
+	according to the terms of the GNU General Public License as modified by SRC,
 	incorporated herein by reference.
 
 	The author may be reached as becker@cesdis.gsfc.nasa.gov, or
diff -u --recursive --new-file v2.4.1/linux/drivers/net/acenic.c linux/drivers/net/acenic.c
--- v2.4.1/linux/drivers/net/acenic.c	Thu Jan  4 15:25:55 2001
+++ linux/drivers/net/acenic.c	Tue Feb 13 13:15:05 2001
@@ -44,6 +44,8 @@
  *   Val Henson <vhenson@esscom.com>:    Reset Jumbo skb producer and
  *                                       rx producer index when
  *                                       flushing the Jumbo ring.
+ *   Hans Grobler <grobh@sun.ac.za>:     Memory leak fixes in the
+ *                                       driver init path.
  */
 
 #include <linux/config.h>
@@ -77,7 +79,6 @@
 
 
 #undef INDEX_DEBUG
-#define TX_HOST_RING	1
 
 #ifdef CONFIG_ACENIC_OMIT_TIGON_I
 #define ACE_IS_TIGON_I(ap)	0
@@ -151,6 +152,11 @@
 #define __exit
 #endif
 
+#ifndef __devinit
+#define __devinit	__init
+#endif
+
+
 #ifndef SMP_CACHE_BYTES
 #define SMP_CACHE_BYTES	L1_CACHE_BYTES
 #endif
@@ -188,6 +194,8 @@
 	void *virt_ptr;
 
 	virt_ptr = kmalloc(size, GFP_KERNEL);
+	if (!virt_ptr)
+		return NULL;
 	*dma_handle = virt_to_bus(virt_ptr);
 	return virt_ptr;
 }
@@ -481,15 +489,15 @@
 static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1};
 
 static char version[] __initdata = 
-  "acenic.c: v0.49 12/13/2000  Jes Sorensen, linux-acenic@SunSITE.auc.dk\n"
+  "acenic.c: v0.50 02/02/2001  Jes Sorensen, linux-acenic@SunSITE.dk\n"
   "                            http://home.cern.ch/~jes/gige/acenic.html\n";
 
-static struct net_device *root_dev = NULL;
+static struct net_device *root_dev;
 
 static int probed __initdata = 0;
 
 
-int __init acenic_probe (ACE_PROBE_ARG)
+int __devinit acenic_probe (ACE_PROBE_ARG)
 {
 #ifdef NEW_NETINIT
 	struct net_device *dev;
@@ -658,12 +666,19 @@
 			printk(KERN_ERR "%s: Driver compiled without Tigon I"
 			       " support - NIC disabled\n", dev->name);
 			ace_init_cleanup(dev);
+			kfree(dev);
 			continue;
 		}
 #endif
 
-		if (ace_allocate_descriptors(dev))
+		if (ace_allocate_descriptors(dev)) {
+			/*
+			 * ace_allocate_descriptors() calls
+			 * ace_init_cleanup() on error.
+			 */
+			kfree(dev);
 			continue;
+		}
 
 #ifdef MODULE
 		if (boards_found >= ACE_MAX_MOD_PARMS)
@@ -674,8 +689,13 @@
 		ap->board_idx = BOARD_IDX_STATIC;
 #endif
 
-		if (ace_init(dev))
+		if (ace_init(dev)) {
+			/*
+			 * ace_init() calls ace_init_cleanup() on error.
+			 */
+			kfree(dev);
 			continue;
+		}
 
 		boards_found++;
 	}
@@ -705,7 +725,7 @@
 #endif
 
 
-void __exit ace_module_cleanup(void)
+static void __exit ace_module_cleanup(void)
 {
 	struct ace_private *ap;
 	struct ace_regs *regs;
@@ -1006,10 +1026,15 @@
 	 * This will most likely need BYTE_SWAP once we switch
 	 * to using __raw_writel()
 	 */
-	writel((WORD_SWAP | CLR_INT |
-		((WORD_SWAP | CLR_INT) << 24)),
+#ifdef __parisc__
+	writel((WORD_SWAP | BYTE_SWAP | CLR_INT |
+		((WORD_SWAP | BYTE_SWAP | CLR_INT) << 24)),
 	       &regs->HostCtrl);
 #else
+	writel((WORD_SWAP | CLR_INT | ((WORD_SWAP | CLR_INT) << 24)),
+	       &regs->HostCtrl);
+#endif
+#else
 	writel((CLR_INT | WORD_SWAP | ((CLR_INT | WORD_SWAP) << 24)),
 	       &regs->HostCtrl);
 #endif
@@ -1026,7 +1051,7 @@
 	switch(tig_ver){
 #ifndef CONFIG_ACENIC_OMIT_TIGON_I
 	case 4:
-		printk(KERN_INFO"  Tigon I  (Rev. 4), Firmware: %i.%i.%i, ",
+		printk(KERN_INFO "  Tigon I  (Rev. 4), Firmware: %i.%i.%i, ",
 		       tigonFwReleaseMajor, tigonFwReleaseMinor,
 		       tigonFwReleaseFix);
 		writel(0, &regs->LocalCtrl);
@@ -1034,7 +1059,7 @@
 		break;
 #endif
 	case 6:
-		printk(KERN_INFO"  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
+		printk(KERN_INFO "  Tigon II (Rev. %i), Firmware: %i.%i.%i, ",
 		       tig_ver, tigon2FwReleaseMajor, tigon2FwReleaseMinor,
 		       tigon2FwReleaseFix);
 		writel(readl(&regs->CpuBCtrl) | CPU_HALT, &regs->CpuBCtrl);
@@ -1048,8 +1073,8 @@
 		ap->version = 2;
 		break;
 	default:
-		printk(KERN_INFO"  Unsupported Tigon version detected (%i), ",
-		       tig_ver);
+		printk(KERN_WARNING "  Unsupported Tigon version detected "
+		       "(%i), ", tig_ver);
 		ecode = -ENODEV;
 		goto init_error;
 	}
@@ -2040,6 +2065,7 @@
 
 		netif_rx(skb);		/* send it up */
 
+		dev->last_rx = jiffies;
 		ap->stats.rx_packets++;
 		ap->stats.rx_bytes += retdesc->size;
 
@@ -2752,7 +2778,7 @@
 }
 
 
-void __init ace_copy(struct ace_regs *regs, void *src, u32 dest, int size)
+static void __init ace_copy(struct ace_regs *regs, void *src, u32 dest, int size)
 {
 	unsigned long tdest;
 	u32 *wsrc;
@@ -2784,7 +2810,7 @@
 }
 
 
-void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
+static void __init ace_clear(struct ace_regs *regs, u32 dest, int size)
 {
 	unsigned long tdest;
 	short tsize = 0, i;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/aironet4500_card.c linux/drivers/net/aironet4500_card.c
--- v2.4.1/linux/drivers/net/aironet4500_card.c	Tue Nov  7 11:02:24 2000
+++ linux/drivers/net/aironet4500_card.c	Tue Feb 13 13:15:04 2001
@@ -23,7 +23,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/aironet4500_core.c linux/drivers/net/aironet4500_core.c
--- v2.4.1/linux/drivers/net/aironet4500_core.c	Mon Dec 11 12:39:45 2000
+++ linux/drivers/net/aironet4500_core.c	Tue Feb 13 13:15:05 2001
@@ -1526,9 +1526,10 @@
 	rx_buff->skb = NULL;
 	rx_buff->u.rx.payload = NULL;
 	priv->stats.rx_packets++;
-	priv->stats.rx_bytes++;
+	priv->stats.rx_bytes += skb->len;
 	
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	AWC_ENTRY_EXIT_DEBUG("exit\n");
 	return ;
 
@@ -3025,7 +3026,7 @@
 	}
 	restore_flags(flags);
 	dev->trans_start = jiffies;
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/aironet4500_proc.c linux/drivers/net/aironet4500_proc.c
--- v2.4.1/linux/drivers/net/aironet4500_proc.c	Fri Mar 10 09:43:04 2000
+++ linux/drivers/net/aironet4500_proc.c	Tue Feb 13 13:15:04 2001
@@ -18,7 +18,7 @@
 
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/am79c961a.c linux/drivers/net/am79c961a.c
--- v2.4.1/linux/drivers/net/am79c961a.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/am79c961a.c	Tue Feb 13 13:15:04 2001
@@ -21,7 +21,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/appletalk/cops.c linux/drivers/net/appletalk/cops.c
--- v2.4.1/linux/drivers/net/appletalk/cops.c	Sat Dec 30 11:23:13 2000
+++ linux/drivers/net/appletalk/cops.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
  *      Director, National Security Agency.
  *
  *      This software may be used and distributed according to the terms
- *      of the GNU Public License, incorporated herein by reference.
+ *      of the GNU General Public License, incorporated herein by reference.
  *
  *	Changes:
  *	19970608	Alan Cox	Allowed dual card type support
@@ -59,7 +59,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -851,8 +851,7 @@
 
         /* Send packet to a higher place. */
         netif_rx(skb);
-
-        return;
+	dev->last_rx = jiffies;
 }
 
 static void cops_timeout(struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/appletalk/ltpc.c linux/drivers/net/appletalk/ltpc.c
--- v2.4.1/linux/drivers/net/appletalk/ltpc.c	Sun Dec 31 10:26:17 2000
+++ linux/drivers/net/appletalk/ltpc.c	Tue Feb 13 13:15:05 2001
@@ -215,7 +215,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -787,6 +787,7 @@
 
 	/* toss it onwards */
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	return 0;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/Makefile linux/drivers/net/arcnet/Makefile
--- v2.4.1/linux/drivers/net/arcnet/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/arcnet/Makefile	Tue Feb 13 13:15:04 2001
@@ -22,6 +22,6 @@
 obj-$(CONFIG_ARCNET_COM20020_ISA) += com20020-isa.o
 obj-$(CONFIG_ARCNET_COM20020_PCI) += com20020-pci.o
 
-L_TARGET := arcnet.a
+O_TARGET := arcnetdrv.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/arc-rawmode.c linux/drivers/net/arcnet/arc-rawmode.c
--- v2.4.1/linux/drivers/net/arcnet/arc-rawmode.c	Tue Jan  4 09:41:45 2000
+++ linux/drivers/net/arcnet/arc-rawmode.c	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -128,6 +128,7 @@
 
 	skb->protocol = 0;
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/arc-rimi.c linux/drivers/net/arcnet/arc-rimi.c
--- v2.4.1/linux/drivers/net/arcnet/arc-rimi.c	Sat May 13 07:50:25 2000
+++ linux/drivers/net/arcnet/arc-rimi.c	Tue Feb 13 13:15:05 2001
@@ -15,7 +15,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -27,7 +27,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/bootmem.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/arcnet.c linux/drivers/net/arcnet/arcnet.c
--- v2.4.1/linux/drivers/net/arcnet/arcnet.c	Sun Sep 17 09:45:05 2000
+++ linux/drivers/net/arcnet/arcnet.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/com20020-isa.c linux/drivers/net/arcnet/com20020-isa.c
--- v2.4.1/linux/drivers/net/arcnet/com20020-isa.c	Sun Sep 17 09:45:05 2000
+++ linux/drivers/net/arcnet/com20020-isa.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/com20020-pci.c linux/drivers/net/arcnet/com20020-pci.c
--- v2.4.1/linux/drivers/net/arcnet/com20020-pci.c	Sun Sep 17 09:45:05 2000
+++ linux/drivers/net/arcnet/com20020-pci.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/com20020.c linux/drivers/net/arcnet/com20020.c
--- v2.4.1/linux/drivers/net/arcnet/com20020.c	Tue May  2 12:36:09 2000
+++ linux/drivers/net/arcnet/com20020.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/com90io.c linux/drivers/net/arcnet/com90io.c
--- v2.4.1/linux/drivers/net/arcnet/com90io.c	Sat May 13 07:50:25 2000
+++ linux/drivers/net/arcnet/com90io.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -28,7 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
 #include <linux/bootmem.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/com90xx.c linux/drivers/net/arcnet/com90xx.c
--- v2.4.1/linux/drivers/net/arcnet/com90xx.c	Thu Jun 29 11:11:22 2000
+++ linux/drivers/net/arcnet/com90xx.c	Tue Feb 13 13:15:05 2001
@@ -15,7 +15,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/rfc1051.c linux/drivers/net/arcnet/rfc1051.c
--- v2.4.1/linux/drivers/net/arcnet/rfc1051.c	Tue Jan  4 09:41:45 2000
+++ linux/drivers/net/arcnet/rfc1051.c	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -161,6 +161,7 @@
 
 	skb->protocol = type_trans(skb, dev);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arcnet/rfc1201.c linux/drivers/net/arcnet/rfc1201.c
--- v2.4.1/linux/drivers/net/arcnet/rfc1201.c	Tue May  2 12:36:09 2000
+++ linux/drivers/net/arcnet/rfc1201.c	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  *
  * **********************
@@ -230,6 +230,7 @@
 
 		skb->protocol = type_trans(skb, dev);
 		netif_rx(skb);
+		dev->last_rx = jiffies;
 	} else {		/* split packet */
 		/*
 		 * NOTE: MSDOS ARP packet correction should only need to apply to
@@ -365,6 +366,7 @@
 
 			skb->protocol = type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 		}
 	}
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ariadne.c linux/drivers/net/ariadne.c
--- v2.4.1/linux/drivers/net/ariadne.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/net/ariadne.c	Tue Feb 13 13:15:05 2001
@@ -43,7 +43,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/interrupt.h>
@@ -741,7 +741,9 @@
 #endif
 
 	    netif_rx(skb);
+	    dev->last_rx = jiffies;
 	    priv->stats.rx_packets++;
+	    priv->stats.rx_bytes += pkt_len;
 	}
 
 	priv->rx_ring[entry]->RMD1 |= RF_OWN;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arlan-proc.c linux/drivers/net/arlan-proc.c
--- v2.4.1/linux/drivers/net/arlan-proc.c	Sat Dec 18 15:34:29 1999
+++ linux/drivers/net/arlan-proc.c	Tue Feb 13 13:15:05 2001
@@ -58,7 +58,7 @@
 }
 
 
-const char *arlan_diagnostic_info_string(struct net_device *dev)
+static const char *arlan_diagnostic_info_string(struct net_device *dev)
 {
 
 	volatile struct arlan_shmem *arlan = ((struct arlan_private *) dev->priv)->card;
@@ -790,7 +790,7 @@
 	return proc_dostring(ctl, write, filp, buffer, lenp);
 }
 
-int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp,
+static int arlan_sysctl_reset(ctl_table * ctl, int write, struct file *filp,
 		       void *buffer, size_t * lenp)
 {
 	int pos = 0;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arlan.c linux/drivers/net/arlan.c
--- v2.4.1/linux/drivers/net/arlan.c	Sat Dec 30 11:23:13 2000
+++ linux/drivers/net/arlan.c	Tue Feb 13 13:15:05 2001
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1997 Cullen Jennings
  *  Copyright (C) 1998 Elmer Joandiu, elmer@ylenurme.ee
- *  Gnu Public License applies
+ *  GNU General Public License applies
  * This module provides support for the Arlan 655 card made by Aironet
  */
 
@@ -32,7 +32,7 @@
 static int async = 1;
 static int tx_queue_len = 1;
 static int arlan_EEPROM_bad;
-int arlan_entry_and_exit_debug;
+static int arlan_entry_and_exit_debug;
 
 #ifdef ARLAN_DEBUGING
 
@@ -87,7 +87,7 @@
 #endif
 
 struct arlan_conf_stru arlan_conf[MAX_ARLANS];
-int arlans_found;
+static int arlans_found;
 
 static  int 	arlan_probe_here(struct net_device *dev, int ioaddr);
 static  int 	arlan_open(struct net_device *dev);
@@ -1063,7 +1063,7 @@
 
 }
 
-int __init arlan_probe_everywhere(struct net_device *dev)
+static int __init arlan_probe_everywhere(struct net_device *dev)
 {
 	int m;
 	int probed = 0;
@@ -1103,7 +1103,7 @@
 	return -ENODEV;
 }
 
-int __init arlan_find_devices(void)
+static int __init arlan_find_devices(void)
 {
 	int m;
 	int found = 0;
@@ -1229,7 +1229,7 @@
 }
 
 
-int __init arlan_probe_here(struct net_device *dev, int memaddr)
+static int __init arlan_probe_here(struct net_device *dev, int memaddr)
 {
 	volatile struct arlan_shmem *arlan;
 
@@ -1721,7 +1721,9 @@
 					printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol);
 				}
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			priv->stats.rx_packets++;
+			priv->stats.rx_bytes += pkt_len;
 		}
 		break;
 		
diff -u --recursive --new-file v2.4.1/linux/drivers/net/arlan.h linux/drivers/net/arlan.h
--- v2.4.1/linux/drivers/net/arlan.h	Mon Dec 11 13:01:00 2000
+++ linux/drivers/net/arlan.h	Tue Feb 13 13:15:05 2001
@@ -1,7 +1,7 @@
 /*
  *  Copyright (C) 1997 Cullen Jennings
  *  Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500	
- *  Gnu Public License applies
+ *  GNU General Public License applies
  */
 #include <linux/version.h>
 
@@ -15,7 +15,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/at1700.c linux/drivers/net/at1700.c
--- v2.4.1/linux/drivers/net/at1700.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/at1700.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
@@ -34,9 +34,6 @@
 	response to inb()s from other device probes!
 */
 
-static const char *version =
-	"at1700.c:v1.15 4/7/98  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
-
 #include <linux/config.h>
 #include <linux/module.h>
 
@@ -48,7 +45,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <asm/system.h>
@@ -63,6 +60,9 @@
 
 #include <linux/mca.h>
 
+static char version[] __initdata =
+	"at1700.c:v1.15 4/7/98  Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
+
 /* Tunable parameters. */
 
 /* When to switch from the 64-entry multicast filter to Rx-all-multicast. */
@@ -175,7 +175,7 @@
 };
 /* rEnE : maybe there are others I don't know off... */
 
-struct at1720_mca_adapters_struct at1720_mca_adapters[] = {
+static struct at1720_mca_adapters_struct at1720_mca_adapters[] = {
 	{ "Allied Telesys AT1720AT",	0x6410 },
 	{ "Allied Telesys AT1720BT", 	0x6413 },
 	{ "Allied Telesys AT1720T",		0x6416 },
@@ -218,7 +218,7 @@
    that can be done is checking a few bits and then diving right into an
    EEPROM read. */
 
-static int at1700_probe1(struct net_device *dev, int ioaddr)
+static int __init 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};
@@ -737,7 +737,9 @@
 			insw(ioaddr + DATAPORT, skb_put(skb,pkt_len), (pkt_len + 1) >> 1);
 			skb->protocol=eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += pkt_len;
 		}
 		if (--boguscount <= 0)
 			break;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/atari_bionet.c linux/drivers/net/atari_bionet.c
--- v2.4.1/linux/drivers/net/atari_bionet.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/atari_bionet.c	Tue Feb 13 13:15:05 2001
@@ -93,7 +93,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
@@ -374,6 +374,8 @@
 
 	if (dev->priv == NULL)
 		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+	if (!dev->priv)
+		return -ENOMEM;
 	memset(dev->priv, 0, sizeof(struct net_local));
 
 	dev->open		= bionet_open;
@@ -551,6 +553,7 @@
 			memcpy(skb->data, nic_packet->buffer, pkt_len);
 			skb->protocol = eth_type_trans( skb, dev ); 
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes+=pkt_len;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/atari_pamsnet.c linux/drivers/net/atari_pamsnet.c
--- v2.4.1/linux/drivers/net/atari_pamsnet.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/atari_pamsnet.c	Tue Feb 13 13:15:05 2001
@@ -87,7 +87,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/pgtable.h>
@@ -633,6 +633,8 @@
 	/* Initialize the device structure. */
 	if (dev->priv == NULL)
 		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
+	if (!dev->priv)
+		return -ENOMEM;
 	memset(dev->priv, 0, sizeof(struct net_local));
 
 	dev->open		= pamsnet_open;
@@ -794,6 +796,7 @@
 			 */
 			memcpy(skb->data, nic_packet->buffer, pkt_len);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes+=pkt_len;
 		}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/atarilance.c linux/drivers/net/atarilance.c
--- v2.4.1/linux/drivers/net/atarilance.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/atarilance.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 	Written 1995/96 by Roman Hodek (Roman.Hodek@informatik.uni-erlangen.de)
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This drivers was written with the following sources of reference:
 	 - The driver for the Riebl Lance card by the TU Vienna.
@@ -53,7 +53,7 @@
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
@@ -515,8 +515,11 @@
 
   probe_ok:
 	init_etherdev( dev, sizeof(struct lance_private) );
-	if (!dev->priv)
+	if (!dev->priv) {
 		dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL );
+		if (!dev->priv)
+			return 0;
+	}
 	lp = (struct lance_private *)dev->priv;
 	MEM = (struct lance_memory *)memaddr;
 	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
@@ -765,7 +768,7 @@
 	lance_init_ring(dev);
 	REGA( CSR0 ) = CSR0_INEA | CSR0_INIT | CSR0_STRT;
 	dev->trans_start = jiffies;
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 }
 
 /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
@@ -820,9 +823,9 @@
 	head->misc = 0;
 	lp->memcpy_f( PKTBUF_ADDR(head), (void *)skb->data, skb->len );
 	head->flag = TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP;
+	lp->stats.tx_bytes += skb->len;
 	dev_kfree_skb( skb );
 	lp->cur_tx++;
-	lp->stats.tx_bytes += skb->len;
 	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
 		lp->cur_tx -= TX_RING_SIZE;
 		lp->dirty_tx -= TX_RING_SIZE;
@@ -1028,8 +1031,9 @@
 				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
-				lp->stats.rx_bytes += skb->len;
+				lp->stats.rx_bytes += pkt_len;
 			}
 		}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/atp.c linux/drivers/net/atp.c
--- v2.4.1/linux/drivers/net/atp.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/atp.c	Tue Feb 13 13:15:05 2001
@@ -132,7 +132,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -627,7 +627,6 @@
 					write_reg_high(ioaddr, CMR2, lp->addr_mode);
 				} else if ((read_status & (CMR1_BufEnb << 3)) == 0) {
 					net_rx(dev);
-					dev->last_rx = jiffies;
 					num_tx_since_rx = 0;
 				} else
 					break;
@@ -785,6 +784,7 @@
 		read_block(ioaddr, pkt_len, skb_put(skb,pkt_len), dev->if_port);
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
+		dev->last_rx = jiffies;
 		lp->stats.rx_packets++;
 		lp->stats.rx_bytes += pkt_len;
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/bagetlance.c linux/drivers/net/bagetlance.c
--- v2.4.1/linux/drivers/net/bagetlance.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/bagetlance.c	Tue Feb 13 13:15:05 2001
@@ -22,7 +22,7 @@
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 
@@ -584,8 +584,11 @@
 
   probe_ok:
 	init_etherdev( dev, sizeof(struct lance_private) );
-	if (!dev->priv)
+	if (!dev->priv) {
 		dev->priv = kmalloc( sizeof(struct lance_private), GFP_KERNEL );
+		if (!dev->priv)
+			return 0;
+	}
 	lp = (struct lance_private *)dev->priv;
 	MEM = (struct lance_memory *)memaddr;
 	IO = lp->iobase = (struct lance_ioreg *)ioaddr;
@@ -930,9 +933,9 @@
 #else
     SET_FLAG(head,(TMD1_OWN_CHIP | TMD1_ENP | TMD1_STP));
 #endif
+	lp->stats.tx_bytes += skb->len;
 	dev_kfree_skb( skb );
 	lp->cur_tx++;
-	lp->stats.tx_bytes += skb->len;
 	while( lp->cur_tx >= TX_RING_SIZE && lp->dirty_tx >= TX_RING_SIZE ) {
 		lp->cur_tx -= TX_RING_SIZE;
 		lp->dirty_tx -= TX_RING_SIZE;
@@ -1182,8 +1185,9 @@
 				lp->memcpy_f( skb->data, PKTBUF_ADDR(head), pkt_len );
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
-				lp->stats.rx_bytes += skb->len;
+				lp->stats.rx_bytes += pkt_len;
 			}
 		}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/bmac.c linux/drivers/net/bmac.c
--- v2.4.1/linux/drivers/net/bmac.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/bmac.c	Tue Feb 13 13:15:05 2001
@@ -91,7 +91,7 @@
 
 #define N_REG_ENTRIES 31
 
-bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
+static bmac_reg_entry_t reg_entries[N_REG_ENTRIES] = {
 	{"MEMADD", MEMADD},
 	{"MEMDATAHI", MEMDATAHI},
 	{"MEMDATALO", MEMDATALO},
@@ -125,10 +125,10 @@
 	{"RXCV", RXCV}
 };
 
-struct net_device *bmac_devs = NULL;
+static struct net_device *bmac_devs;
 
 #ifdef CONFIG_PMAC_PBOOK
-int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
+static int bmac_sleep_notify(struct pmu_sleep_notifier *self, int when);
 static struct pmu_sleep_notifier bmac_sleep_notifier = {
 	bmac_sleep_notify, SLEEP_LEVEL_NET,
 };
@@ -169,14 +169,14 @@
 #define	DBDMA_SET(x)	( ((x) | (x) << 16) )
 #define	DBDMA_CLEAR(x)	( (x) << 16)
 
-static __inline__ void
+static inline void
 dbdma_st32(volatile unsigned long *a, unsigned long x)
 {
 	__asm__ volatile( "stwbrx %0,0,%1" : : "r" (x), "r" (a) : "memory");
 	return;
 }
 
-static __inline__ unsigned long
+static inline unsigned long
 dbdma_ld32(volatile unsigned long *a)
 {
 	unsigned long swap;
@@ -184,7 +184,7 @@
 	return swap;
 }
 
-void
+static void
 dbdma_stop(volatile struct dbdma_regs *dmap)
 {
 	dbdma_st32((volatile unsigned long *)&dmap->control,
@@ -226,14 +226,14 @@
 	out_le16(&cp->res_count, 0);
 }
 
-static __inline__
+static inline
 void bmwrite(struct net_device *dev, unsigned long reg_offset, unsigned data )
 {
 	out_le16((void *)dev->base_addr + reg_offset, data);
 }
 
 
-static __inline__
+static inline
 volatile unsigned short bmread(struct net_device *dev, unsigned long reg_offset )
 {
 	return in_le16((void *)dev->base_addr + reg_offset);
@@ -476,7 +476,7 @@
 }
 
 #ifdef CONFIG_PMAC_PBOOK
-int
+static int
 bmac_sleep_notify(struct pmu_sleep_notifier *self, int when)
 {
 	struct bmac_data *bp;
@@ -679,7 +679,7 @@
 	return 0;
 }
 
-static int rxintcount = 0;
+static int rxintcount;
 
 static void bmac_rxdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -747,7 +747,7 @@
 	}
 }
 
-static int txintcount = 0;
+static int txintcount;
 
 static void bmac_txdma_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
@@ -1067,7 +1067,7 @@
 }
 #endif /* SUNHME_MULTICAST */
 
-static int miscintcount = 0;
+static int miscintcount;
 
 static void bmac_misc_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/bsd_comp.c linux/drivers/net/bsd_comp.c
--- v2.4.1/linux/drivers/net/bsd_comp.c	Fri May 12 11:29:52 2000
+++ linux/drivers/net/bsd_comp.c	Tue Feb 13 13:15:04 2001
@@ -63,7 +63,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <linux/ppp_defs.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/cs89x0.c linux/drivers/net/cs89x0.c
--- v2.4.1/linux/drivers/net/cs89x0.c	Tue Nov 14 11:34:25 2000
+++ linux/drivers/net/cs89x0.c	Tue Feb 13 13:15:05 2001
@@ -7,7 +7,7 @@
 	written 1993-1994 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
         The author may be reached at nelson@crynwr.com, Crynwr
         Software, 521 Pleasant Valley Rd., Potsdam, NY 13676
@@ -119,7 +119,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -773,8 +773,9 @@
 	}
         skb->protocol=eth_type_trans(skb,dev);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
-	return;
+	lp->stats.rx_bytes += length;
 }
 
 #endif	/* ALLOW_DMA */
@@ -1446,9 +1447,9 @@
 
         skb->protocol=eth_type_trans(skb,dev);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
-	lp->stats.rx_bytes+=skb->len;
-	return;
+	lp->stats.rx_bytes += length;
 }
 
 #if ALLOW_DMA
diff -u --recursive --new-file v2.4.1/linux/drivers/net/daynaport.c linux/drivers/net/daynaport.c
--- v2.4.1/linux/drivers/net/daynaport.c	Sun Dec  3 17:48:19 2000
+++ linux/drivers/net/daynaport.c	Tue Feb 13 13:15:05 2001
@@ -8,7 +8,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	    TODO:
 
@@ -44,7 +44,7 @@
 #include <linux/etherdevice.h>
 #include "8390.h"
 
-int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
+static int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
 				  int prom, struct nubus_dev *ndev);
 
 static int ns8390_open(struct net_device *dev);
@@ -144,7 +144,7 @@
 	NS8390_CABLETRON
 };
 
-int __init ns8390_ident(struct nubus_dev* ndev)
+static int __init ns8390_ident(struct nubus_dev* ndev)
 {
 	/* This really needs to be tested and tested hard.  */
 		
@@ -194,7 +194,7 @@
  *	Memory probe for 8390 cards
  */
  
-int __init apple_8390_mem_probe(volatile unsigned short *p)
+static int __init apple_8390_mem_probe(volatile unsigned short *p)
 {
 	int i, j;
 	/*
@@ -454,8 +454,7 @@
 	return -ENODEV;
 }
 
-int __init mac8390_ethernet_addr(struct nubus_dev* ndev, 
-				 unsigned char addr[6])
+static int __init mac8390_ethernet_addr(struct nubus_dev* ndev, unsigned char addr[6])
 {
 	struct nubus_dir dir;
 	struct nubus_dirent ent;
@@ -470,8 +469,8 @@
 	return 0;
 }
 
-int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
-			 int type, int promoff, struct nubus_dev *ndev)
+static int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
+			 	int type, int promoff, struct nubus_dev *ndev)
 {
 	static u32 fwrd4_offsets[16]={
 		0,      4,      8,      12,
diff -u --recursive --new-file v2.4.1/linux/drivers/net/de4x5.c linux/drivers/net/de4x5.c
--- v2.4.1/linux/drivers/net/de4x5.c	Wed Nov  8 17:09:50 2000
+++ linux/drivers/net/de4x5.c	Fri Feb  9 11:40:02 2001
@@ -445,7 +445,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -1662,6 +1662,7 @@
 	    STOP_DE4X5;
 	    printk("%s: Fatal bus error occurred, sts=%#8x, device stopped.\n",
 		   dev->name, sts);
+	    spin_unlock(&lp->lock);
 	    return;
 	}
     }
@@ -1733,6 +1734,7 @@
 		    netif_rx(skb);
 		    
 		    /* Update stats */
+		    dev->last_rx = jiffies;
 		    lp->stats.rx_packets++;
  		    lp->stats.rx_bytes += pkt_len;
 		    de4x5_local_stats(dev, skb->data, pkt_len);
diff -u --recursive --new-file v2.4.1/linux/drivers/net/de4x5.h linux/drivers/net/de4x5.h
--- v2.4.1/linux/drivers/net/de4x5.h	Mon Dec 11 13:02:04 2000
+++ linux/drivers/net/de4x5.h	Fri Feb  9 11:40:02 2001
@@ -2,7 +2,7 @@
     Copyright 1994 Digital Equipment Corporation.
 
     This software may be used and distributed according to  the terms of the
-    GNU Public License, incorporated herein by reference.
+    GNU General Public License, incorporated herein by reference.
 
     The author may    be  reached as davies@wanton.lkg.dec.com  or   Digital
     Equipment Corporation, 550 King Street, Littleton MA 01460.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/declance.c linux/drivers/net/declance.c
--- v2.4.1/linux/drivers/net/declance.c	Mon Oct 30 12:24:21 2000
+++ linux/drivers/net/declance.c	Tue Feb 13 13:15:05 2001
@@ -73,7 +73,7 @@
 #include <linux/string.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/user.h>
 #include <linux/utsname.h>
 #include <linux/a.out.h>
@@ -613,6 +613,7 @@
 				    len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 		}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/defxx.c linux/drivers/net/defxx.c
--- v2.4.1/linux/drivers/net/defxx.c	Tue Sep  5 12:57:51 2000
+++ linux/drivers/net/defxx.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
  *   Copyright Digital Equipment Corporation 1996.
  *
  *   This software may be used and distributed according to the terms of
- *   the GNU Public License, incorporated herein by reference.
+ *   the GNU General Public License, incorporated herein by reference.
  *
  * Abstract:
  *   A Linux device driver supporting the Digital Equipment Corporation
@@ -207,7 +207,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -2861,7 +2861,7 @@
 					netif_rx(skb);
 
 					/* Update the rcv counters */
-
+					bp->dev->last_rx = jiffies;
 					bp->rcv_total_frames++;
 					if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
 						bp->rcv_multicast_frames++;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/defxx.h linux/drivers/net/defxx.h
--- v2.4.1/linux/drivers/net/defxx.h	Tue Sep  5 12:57:51 2000
+++ linux/drivers/net/defxx.h	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
  *   Copyright Digital Equipment Corporation 1996.
  *
  *   This software may be used and distributed according to the terms of
- *   the GNU Public License, incorporated herein by reference.
+ *   the GNU General Public License, incorporated herein by reference.
  *
  * Abstract:
  *   Contains all definitions specified by port specification and required
diff -u --recursive --new-file v2.4.1/linux/drivers/net/depca.c linux/drivers/net/depca.c
--- v2.4.1/linux/drivers/net/depca.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/depca.c	Tue Feb 13 13:15:05 2001
@@ -12,7 +12,7 @@
 
 
     This software may be used and distributed according to the terms of
-    the GNU Public License, incorporated herein by reference.
+    the GNU General Public License, incorporated herein by reference.
 
     This driver is written for the Digital Equipment Corporation series
     of DEPCA and EtherWORKS ethernet cards:
@@ -241,7 +241,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -990,11 +990,13 @@
 	  */
 	  skb->protocol=eth_type_trans(skb,dev);
 	  netif_rx(skb);
- 
+
 	  /*
 	  ** Update stats
 	  */
+	  dev->last_rx = jiffies;
 	  lp->stats.rx_packets++;
+	  lp->stats.rx_bytes += pkt_len;
 	  for (i=1; i<DEPCA_PKT_STAT_SZ-1; i++) {
 	    if (pkt_len < (i*DEPCA_PKT_BIN_SZ)) {
 	      lp->pktStats.bins[i]++;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/depca.h linux/drivers/net/depca.h
--- v2.4.1/linux/drivers/net/depca.h	Mon Dec 11 13:02:02 2000
+++ linux/drivers/net/depca.h	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
     Written 1994 by David C. Davies.
 
     Copyright 1994 David C. Davies. This software may be used and distributed
-    according to the terms of the GNU Public License, incorporated herein by
+    according to the terms of the GNU General Public License, incorporated herein by
     reference.
 */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/dgrs.c linux/drivers/net/dgrs.c
--- v2.4.1/linux/drivers/net/dgrs.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/dgrs.c	Tue Feb 13 13:15:05 2001
@@ -670,7 +670,9 @@
 	 */
 	skb->protocol = eth_type_trans(skb, devN);
 	netif_rx(skb);
+	devN->last_rx = jiffies;
 	++privN->stats.rx_packets;
+	privN->stats.rx_bytes += len;
 
 out:
 	cbp->xmit.status = I596_CB_STATUS_C | I596_CB_STATUS_OK;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/dmfe.c linux/drivers/net/dmfe.c
--- v2.4.1/linux/drivers/net/dmfe.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/dmfe.c	Tue Feb 13 13:15:04 2001
@@ -79,7 +79,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/e2100.c linux/drivers/net/e2100.c
--- v2.4.1/linux/drivers/net/e2100.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/e2100.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	Copyright 1994 by Donald Becker.
 	Copyright 1993 United States Government as represented by the
 	Director, National Security Agency.  This software may be used and
-	distributed according to the terms of the GNU Public License,
+	distributed according to the terms of the GNU General Public License,
 	incorporated herein by reference.
 
 	This is a driver for the Cabletron E2100 series ethercards.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/eepro.c linux/drivers/net/eepro.c
--- v2.4.1/linux/drivers/net/eepro.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/eepro.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	Copyright (C) 1994, 1995,1996 by Bao C. Ha.
 
 	This software may be used and distributed
-	according to the terms of the GNU Public License,
+	according to the terms of the GNU General Public License,
 	incorporated herein by reference.
 
 	The author may be reached at bao.ha@srs.gov 
@@ -130,7 +130,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/eepro100.c linux/drivers/net/eepro100.c
--- v2.4.1/linux/drivers/net/eepro100.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/eepro100.c	Tue Feb 13 13:15:05 2001
@@ -10,7 +10,7 @@
 	Please use this email address and linux-kernel mailing list for bug reports.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This driver is for the Intel EtherExpress Pro100 (Speedo3) design.
 	It should work with all i82557/558/559 boards.
@@ -91,15 +91,12 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
-#if defined(MODVERSIONS)
-#include <linux/modversions.h>
-#endif
 
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
@@ -475,7 +472,7 @@
 	struct speedo_mc_block *mc_setup_tail;/* Multicast setup frame list tail. */
 	int in_interrupt;					/* Word-aligned dev->interrupt */
 	unsigned char acpi_pwr;
-	char rx_mode;						/* Current PROMISC/ALLMULTI setting. */
+	signed char rx_mode;					/* Current PROMISC/ALLMULTI setting. */
 	unsigned int tx_full:1;				/* The Tx queue is full. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
 	unsigned int flow_ctrl:1;			/* Use 802.3x flow control. */
@@ -490,12 +487,12 @@
 /* The parameters for a CmdConfigure operation.
    There are so many options that it would be difficult to document each bit.
    We mostly use the default or recommended settings. */
-const char i82557_config_cmd[CONFIG_DATA_SIZE] = {
+static const char i82557_config_cmd[CONFIG_DATA_SIZE] = {
 	22, 0x08, 0, 0,  0, 0, 0x32, 0x03,  1, /* 1=Use MII  0=Use AUI */
 	0, 0x2E, 0,  0x60, 0,
 	0xf2, 0x48,   0, 0x40, 0xf2, 0x80, 		/* 0x40=Force full-duplex */
 	0x3f, 0x05, };
-const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
+static const char i82558_config_cmd[CONFIG_DATA_SIZE] = {
 	22, 0x08, 0, 1,  0, 0, 0x22, 0x03,  1, /* 1=Use MII  0=Use AUI */
 	0, 0x2E, 0,  0x60, 0x08, 0x88,
 	0x68, 0, 0x40, 0xf2, 0x84,		/* Disable FC */
@@ -725,7 +722,7 @@
 		/* The self-test results must be paragraph aligned. */
 		volatile s32 *self_test_results;
 		int boguscnt = 16000;	/* Timeout for set-test. */
-		if (eeprom[3] & 0x03)
+		if ((eeprom[3] & 0x03) != 0x03)
 			printk(KERN_INFO "  Receiver lock-up bug exists -- enabling"
 				   " work-around.\n");
 		printk(KERN_INFO "  Board assembly %4.4x%2.2x-%3.3d, Physical"
diff -u --recursive --new-file v2.4.1/linux/drivers/net/eexpress.c linux/drivers/net/eexpress.c
--- v2.4.1/linux/drivers/net/eexpress.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/eexpress.c	Tue Feb 13 13:15:05 2001
@@ -120,7 +120,7 @@
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mca.h>
 
 #include <linux/spinlock.h>
@@ -939,6 +939,7 @@
 			        insw(ioaddr+DATAPORT, skb_put(skb,pkt_len),(pkt_len+1)>>1);
 				skb->protocol = eth_type_trans(skb,dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
 				lp->stats.rx_bytes += pkt_len;
 			}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/epic100.c linux/drivers/net/epic100.c
--- v2.4.1/linux/drivers/net/epic100.c	Sun Sep 10 13:21:13 2000
+++ linux/drivers/net/epic100.c	Tue Feb 13 13:15:05 2001
@@ -91,18 +91,13 @@
 #error You must compile this driver with "-O".
 #endif
 
-#include <linux/version.h>
 #include <linux/module.h>
-#if LINUX_VERSION_CODE < 0x20300  &&  defined(MODVERSIONS)
-#include <linux/modversions.h>
-#endif
-
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -1128,6 +1123,7 @@
 			}
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			ep->stats.rx_packets++;
 			ep->stats.rx_bytes += pkt_len;
 		}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/eql.c linux/drivers/net/eql.c
--- v2.4.1/linux/drivers/net/eql.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/net/eql.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
  *
  *
  *	This software may be used and distributed according to the terms
- *	of the GNU Public License, incorporated herein by reference.
+ *	of the GNU General Public License, incorporated herein by reference.
  * 
  * The author may be reached as simon@ncm.com, or C/O
  *    NCM
diff -u --recursive --new-file v2.4.1/linux/drivers/net/es3210.c linux/drivers/net/es3210.c
--- v2.4.1/linux/drivers/net/es3210.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/es3210.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Copyright (C) 1996, Paul Gortmaker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Information and Code Sources:
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/eth16i.c linux/drivers/net/eth16i.c
--- v2.4.1/linux/drivers/net/eth16i.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/eth16i.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
    Based on skeleton.c and heavily on at1700.c by Donald Becker
 
    This software may be used and distributed according to the terms
-   of the GNU Public Licence, incorporated herein by reference.
+   of the GNU General Public License, incorporated herein by reference.
 
    The author may be reached as miku@iki.fi
 
@@ -155,7 +155,7 @@
 #include <linux/ptrace.h>		  
 #include <linux/ioport.h>		  
 #include <linux/in.h>		  
-#include <linux/malloc.h>		  
+#include <linux/slab.h>		  
 #include <linux/string.h>		  
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -1196,6 +1196,7 @@
 
 			skb->protocol=eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes += pkt_len;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ethertap.c linux/drivers/net/ethertap.c
--- v2.4.1/linux/drivers/net/ethertap.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/ethertap.c	Tue Feb 13 13:15:05 2001
@@ -16,7 +16,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 
@@ -279,6 +279,7 @@
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes+=len;
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	return len;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ewrk3.c linux/drivers/net/ewrk3.c
--- v2.4.1/linux/drivers/net/ewrk3.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/ewrk3.c	Fri Feb 16 16:06:17 2001
@@ -5,7 +5,7 @@
    Copyright 1994 Digital Equipment Corporation.
 
    This software may be used and distributed according to the terms of
-   the GNU Public License, incorporated herein by reference.
+   the GNU General Public License, incorporated herein by reference.
 
    This driver is written for the Digital Equipment Corporation series
    of EtherWORKS ethernet cards:
@@ -136,9 +136,6 @@
    =========================================================================
  */
 
-static const char *version = "ewrk3.c:v0.43 96/8/16 davies@maniac.ultranet.com\n";
-
-#include <linux/config.h>
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -147,7 +144,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -167,6 +164,9 @@
 
 #include "ewrk3.h"
 
+static const char version[] __initdata =
+"ewrk3.c:v0.43a 2001/02/04 davies@maniac.ultranet.com\n";
+
 #ifdef EWRK3_DEBUG
 static int ewrk3_debug = EWRK3_DEBUG;
 #else
@@ -273,9 +273,9 @@
 	u_char mPage;		/* Maximum 2kB Page number */
 	u_char lemac;		/* Chip rev. level */
 	u_char hard_strapped;	/* Don't allow a full open */
-	u_char lock;		/* Lock the page register */
 	u_char txc;		/* Transmit cut through */
 	u_char *mctbl;		/* Pointer to the multicast table */
+	spinlock_t hw_lock;
 };
 
 /*
@@ -530,6 +530,7 @@
 							lp->shmem_length = shmem_length;
 							lp->lemac = lemac;
 							lp->hard_strapped = hard_strapped;
+							spin_lock_init(&lp->hw_lock);
 
 							lp->mPage = 64;
 							if (cmr & CMR_DRAM)
@@ -715,8 +716,6 @@
 		outb(page, EWRK3_FMQ);	/* to the Free Memory Queue */
 	}
 
-	lp->lock = 0;		/* Ensure there are no locks */
-
 	START_EWRK3;		/* Enable the TX and/or RX */
 }
 
@@ -760,111 +759,118 @@
 /*
    ** Writes a socket buffer to the free page queue
  */
-static int ewrk3_queue_pkt(struct sk_buff *skb, struct net_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;
-	int status = 0;
+	u_long buf = 0;
 	u_char icr;
+	u_char page;
 
-	netif_stop_queue(dev);
-#ifdef CONFIG_SMP
-#error "This needs spinlocks"
-#endif
-	DISABLE_IRQs;	/* So that the page # remains correct */
+	spin_lock_irq (&lp->hw_lock);
+	DISABLE_IRQs;
+
+	/* if no resources available, exit, request packet be queued */
+	if (inb (EWRK3_FMQC) == 0) {
+		printk (KERN_WARNING "%s: ewrk3_queue_pkt(): No free resources...\n",
+			dev->name);
+		printk (KERN_WARNING "%s: ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n",
+			dev->name, inb (EWRK3_CSR), inb (EWRK3_ICR),
+			inb (EWRK3_FMQC));
+		goto err_out;
+	}
 
 	/*
-	   ** Get a free page from the FMQ when resources are available
+	 ** Get a free page from the FMQ
 	 */
-	if (inb(EWRK3_FMQC) > 0) 
-	{
-		u_long buf = 0;
-		u_char page;
+	if ((page = inb (EWRK3_FMQ)) >= lp->mPage) {
+		printk ("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
+		     (u_char) page);
+		goto err_out;
+	}
 
-		if ((page = inb(EWRK3_FMQ)) < lp->mPage) {
-			/*
-			   ** Set up shared memory window and pointer into the window
-			 */
-			while (test_and_set_bit(0, (void *) &lp->lock) != 0);	/* Wait for lock to free */
-			if (lp->shmem_length == IO_ONLY) {
-				outb(page, EWRK3_IOPR);
-			} else if (lp->shmem_length == SHMEM_2K) {
-				buf = lp->shmem_base;
-				outb(page, EWRK3_MPR);
-			} else if (lp->shmem_length == SHMEM_32K) {
-				buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
-				outb((page >> 4), EWRK3_MPR);
-			} else if (lp->shmem_length == SHMEM_64K) {
-				buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
-				outb((page >> 5), EWRK3_MPR);
-			} else {
-				status = -1;
-				printk(KERN_ERR "%s: Oops - your private data area is hosed!\n", dev->name);
-			}
 
-			if (!status) {
-				/*
-				   ** Set up the buffer control structures and copy the data from
-				   ** the socket buffer to the shared memory .
-				 */
-					if (lp->shmem_length == IO_ONLY) {
-					int i;
-					u_char *p = skb->data;
-						outb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);
-					outb((char) (skb->len & 0xff), EWRK3_DATA);
-					outb((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);
-					outb((char) 0x04, EWRK3_DATA);
-					for (i = 0; i < skb->len; i++) {
-						outb(*p++, EWRK3_DATA);
-					}
-					outb(page, EWRK3_TQ);	/* Start sending pkt */
-				} else {
-					writeb((char) (TCR_QMODE | TCR_PAD | TCR_IFC), (char *) buf);	/* ctrl byte */
-					buf += 1;
-					writeb((char) (skb->len & 0xff), (char *) buf);		/* length (16 bit xfer) */
-					buf += 1;
-					if (lp->txc) {
-						writeb((char) (((skb->len >> 8) & 0xff) | XCT), (char *) buf);
-						buf += 1;
-						writeb(0x04, (char *) buf);	/* index byte */
-						buf += 1;
-						writeb(0x00, (char *) (buf + skb->len));	/* Write the XCT flag */
-						isa_memcpy_toio(buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */
-						outb(page, EWRK3_TQ);	/* Start sending pkt */
-						isa_memcpy_toio(buf + PRELOAD, skb->data + PRELOAD, skb->len - PRELOAD);
-						writeb(0xff, (char *) (buf + skb->len));	/* Write the XCT flag */
-					} else {
-						writeb((char) ((skb->len >> 8) & 0xff), (char *) buf);
-						buf += 1;
-						writeb(0x04, (char *) buf);	/* index byte */
-						buf += 1;
-						isa_memcpy_toio(buf, skb->data, skb->len);		/* Write data bytes */
-						outb(page, EWRK3_TQ);	/* Start sending pkt */
-					}
-				}
+	/*
+	 ** Set up shared memory window and pointer into the window
+	 */
+	if (lp->shmem_length == IO_ONLY) {
+		outb (page, EWRK3_IOPR);
+	} else if (lp->shmem_length == SHMEM_2K) {
+		buf = lp->shmem_base;
+		outb (page, EWRK3_MPR);
+	} else if (lp->shmem_length == SHMEM_32K) {
+		buf = ((((short) page << 11) & 0x7800) + lp->shmem_base);
+		outb ((page >> 4), EWRK3_MPR);
+	} else if (lp->shmem_length == SHMEM_64K) {
+		buf = ((((short) page << 11) & 0xf800) + lp->shmem_base);
+		outb ((page >> 5), EWRK3_MPR);
+	} else {
+		printk (KERN_ERR "%s: Oops - your private data area is hosed!\n",
+			dev->name);
+		BUG ();
+	}
 
-				lp->stats.tx_bytes += skb->len;
-				dev->trans_start = jiffies;
-				dev_kfree_skb(skb);
-			} else {	/* return unused page to the free memory queue */
-				outb(page, EWRK3_FMQ);
-			}
-			lp->lock = 0;	/* unlock the page register */
-		} else {
-			printk("ewrk3_queue_pkt(): Invalid free memory page (%d).\n",
-			       (u_char) page);
+	/*
+	 ** Set up the buffer control structures and copy the data from
+	 ** the socket buffer to the shared memory .
+	 */
+	if (lp->shmem_length == IO_ONLY) {
+		int i;
+		u_char *p = skb->data;
+		outb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), EWRK3_DATA);
+		outb ((char) (skb->len & 0xff), EWRK3_DATA);
+		outb ((char) ((skb->len >> 8) & 0xff), EWRK3_DATA);
+		outb ((char) 0x04, EWRK3_DATA);
+		for (i = 0; i < skb->len; i++) {
+			outb (*p++, EWRK3_DATA);
 		}
+		outb (page, EWRK3_TQ);	/* Start sending pkt */
 	} else {
-		printk(KERN_WARNING "%s: ewrk3_queue_pkt(): No free resources...\n", dev->name);
-		printk(KERN_WARNING "%s: ewrk3_queue_pkt(): CSR: %02x ICR: %02x FMQC: %02x\n", dev->name, inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));
+		isa_writeb ((char) (TCR_QMODE | TCR_PAD | TCR_IFC), buf);	/* ctrl byte */
+		buf += 1;
+		isa_writeb ((char) (skb->len & 0xff), buf);	/* length (16 bit xfer) */
+		buf += 1;
+		if (lp->txc) {
+			isa_writeb ((char)
+				    (((skb->len >> 8) & 0xff) | XCT), buf);
+			buf += 1;
+			isa_writeb (0x04, buf);	/* index byte */
+			buf += 1;
+			isa_writeb (0x00, (buf + skb->len));	/* Write the XCT flag */
+			isa_memcpy_toio (buf, skb->data, PRELOAD);	/* Write PRELOAD bytes */
+			outb (page, EWRK3_TQ);	/* Start sending pkt */
+			isa_memcpy_toio (buf + PRELOAD,
+					 skb->data + PRELOAD,
+					 skb->len - PRELOAD);
+			isa_writeb (0xff, (buf + skb->len));	/* Write the XCT flag */
+		} else {
+			isa_writeb ((char)
+				    ((skb->len >> 8) & 0xff), buf);
+			buf += 1;
+			isa_writeb (0x04, buf);	/* index byte */
+			buf += 1;
+			isa_memcpy_toio (buf, skb->data, skb->len);	/* Write data bytes */
+			outb (page, EWRK3_TQ);	/* Start sending pkt */
+		}
 	}
 
-	/* Check for free resources: clear 'tbusy' if there are some */
-	if (inb(EWRK3_FMQC) > 0) {
-		netif_wake_queue(dev);
-	}
 	ENABLE_IRQs;
-	return status;
+	spin_unlock_irq (&lp->hw_lock);
+
+	lp->stats.tx_bytes += skb->len;
+	dev->trans_start = jiffies;
+	dev_kfree_skb (skb);
+
+	/* Check for free resources: stop Tx queue if there are none */
+	if (inb (EWRK3_FMQC) == 0)
+		netif_stop_queue (dev);
+
+	return 0;
+
+err_out:
+	ENABLE_IRQs;
+	spin_unlock_irq (&lp->hw_lock);
+	return 1;
 }
 
 /*
@@ -886,6 +892,7 @@
 	/*
 	 ** Mask the EWRK3 board interrupts and turn on the LED
 	 */
+	spin_lock(&lp->hw_lock);
 	DISABLE_IRQs;
 
 	cr = inb(EWRK3_CR);
@@ -917,6 +924,7 @@
 	cr &= ~CR_LED;
 	outb(cr, EWRK3_CR);
 	ENABLE_IRQs;
+	spin_unlock(&lp->hw_lock);
 }
 
 static int ewrk3_rx(struct net_device *dev)
@@ -924,23 +932,12 @@
 	struct ewrk3_private *lp = (struct ewrk3_private *) dev->priv;
 	u_long iobase = dev->base_addr;
 	int i, status = 0;
-	u_char page, tmpPage = 0, tmpLock = 0;
+	u_char page;
 	u_long buf = 0;
 
 	while (inb(EWRK3_RQC) && !status) {	/* Whilst there's incoming data */
 		if ((page = inb(EWRK3_RQ)) < lp->mPage) {	/* Get next entry's buffer page */
 			/*
-			   ** Preempt any process using the current page register. Check for
-			   ** an existing lock to reduce time taken in I/O transactions.
-			 */
-			if ((tmpLock = test_and_set_bit(0, (void *) &lp->lock)) == 1) {		/* Assert lock */
-				if (lp->shmem_length == IO_ONLY) {	/* Get existing page */
-					tmpPage = inb(EWRK3_IOPR);
-				} else {
-					tmpPage = inb(EWRK3_MPR);
-				}
-			}
-			/*
 			   ** Set up shared memory window and pointer into the window
 			 */
 			if (lp->shmem_length == IO_ONLY) {
@@ -968,9 +965,9 @@
 					pkt_len = inb(EWRK3_DATA);
 					pkt_len |= ((u_short) inb(EWRK3_DATA) << 8);
 				} else {
-					rx_status = readb(buf);
+					rx_status = isa_readb(buf);
 					buf += 1;
-					pkt_len = readw(buf);
+					pkt_len = isa_readw(buf);
 					buf += 3;
 				}
 
@@ -1010,6 +1007,7 @@
 						/*
 						   ** Update stats
 						 */
+						dev->last_rx = jiffies;
 						lp->stats.rx_packets++;
 						lp->stats.rx_bytes += pkt_len;
 						for (i = 1; i < EWRK3_PKT_STAT_SZ - 1; i++) {
@@ -1044,15 +1042,6 @@
 			   ** Return the received buffer to the free memory queue
 			 */
 			outb(page, EWRK3_FMQ);
-
-			if (tmpLock) {	/* If a lock was preempted */
-				if (lp->shmem_length == IO_ONLY) {	/* Replace old page */
-					outb(tmpPage, EWRK3_IOPR);
-				} else {
-					outb(tmpPage, EWRK3_MPR);
-				}
-			}
-			lp->lock = 0;	/* Unlock the page register */
 		} else {
 			printk("ewrk3_rx(): Illegal page number, page %d\n", page);
 			printk("ewrk3_rx(): CSR: %02x ICR: %02x FMQC: %02x\n", inb(EWRK3_CSR), inb(EWRK3_ICR), inb(EWRK3_FMQC));
@@ -1190,7 +1179,7 @@
 	u16 hashcode;
 	s32 crc, poly = CRC_POLYNOMIAL_LE;
 
-	while (test_and_set_bit(0, (void *) &lp->lock) != 0);	/* Wait for lock to free */
+	spin_lock_irq(&lp->hw_lock);
 
 	if (lp->shmem_length == IO_ONLY) {
 		outb(0, EWRK3_IOPR);
@@ -1204,7 +1193,7 @@
 			if (lp->shmem_length == IO_ONLY) {
 				outb(0xff, EWRK3_DATA);
 			} else {	/* memset didn't work here */
-				writew(0xffff, p);
+				isa_writew(0xffff, (int) p);
 				p++;
 				i++;
 			}
@@ -1221,8 +1210,8 @@
 				outb(0x00, EWRK3_DATA);
 			}
 		} else {
-			memset_io(lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
-			writeb(0x80, (char *) (lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
+			isa_memset_io((int) lp->mctbl, 0, (HASH_TABLE_LEN >> 3));
+			isa_writeb(0x80, (int) (lp->mctbl + (HASH_TABLE_LEN >> 4) - 1));
 		}
 
 		/* Update table */
@@ -1251,15 +1240,13 @@
 					outw((short) ((long) lp->mctbl) + byte, EWRK3_PIR1);
 					outb(tmp, EWRK3_DATA);
 				} else {
-					writeb(readb(lp->mctbl + byte) | bit, lp->mctbl + byte);
+					isa_writeb(isa_readb((int)(lp->mctbl + byte)) | bit, (int)(lp->mctbl + byte));
 				}
 			}
 		}
 	}
 
-	lp->lock = 0;		/* Unlock the page register */
-
-	return;
+	spin_unlock_irq(&lp->hw_lock);
 }
 
 /*
@@ -1709,24 +1696,22 @@
 
 		break;
 	case EWRK3_GET_MCA:	/* Get the multicast address table */
-			while (test_and_set_bit(0, (void *) &lp->lock) != 0);	/* Wait for lock to free */
-			if (lp->shmem_length == IO_ONLY) {
-				outb(0, EWRK3_IOPR);
-				outw(PAGE0_HTE, EWRK3_PIR1);
-				for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {
-					tmp.addr[i] = inb(EWRK3_DATA);
-				}
-			} else {
-				outb(0, EWRK3_MPR);
-				isa_memcpy_fromio(tmp.addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
-			}
-			ioc->len = (HASH_TABLE_LEN >> 3);
-			if (copy_to_user(ioc->data, tmp.addr, ioc->len)) {
-				status = -EFAULT;
-				break;
+		spin_lock_irq(&lp->hw_lock);
+		if (lp->shmem_length == IO_ONLY) {
+			outb(0, EWRK3_IOPR);
+			outw(PAGE0_HTE, EWRK3_PIR1);
+			for (i = 0; i < (HASH_TABLE_LEN >> 3); i++) {
+				tmp.addr[i] = inb(EWRK3_DATA);
 			}
+		} else {
+			outb(0, EWRK3_MPR);
+			isa_memcpy_fromio(tmp.addr, lp->shmem_base + PAGE0_HTE, (HASH_TABLE_LEN >> 3));
+		}
+		spin_unlock_irq(&lp->hw_lock);
 
-		lp->lock = 0;	/* Unlock the page register */
+		ioc->len = (HASH_TABLE_LEN >> 3);
+		if (copy_to_user(ioc->data, tmp.addr, ioc->len))
+			status = -EFAULT;
 
 		break;
 	case EWRK3_SET_MCA:	/* Set a multicast address */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ewrk3.h linux/drivers/net/ewrk3.h
--- v2.4.1/linux/drivers/net/ewrk3.h	Thu Apr 11 23:49:37 1996
+++ linux/drivers/net/ewrk3.h	Sun Feb  4 10:05:30 2001
@@ -4,7 +4,7 @@
     Copyright 1994 Digital Equipment Corporation.
 
     This software may be used and distributed according to  the terms of the
-    GNU Public License, incorporated herein by reference.
+    GNU General Public License, incorporated herein by reference.
 
     The author may    be  reached as davies@wanton.lkg.dec.com  or   Digital
     Equipment Corporation, 550 King Street, Littleton MA 01460.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/fc/iph5526.c linux/drivers/net/fc/iph5526.c
--- v2.4.1/linux/drivers/net/fc/iph5526.c	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/fc/iph5526.c	Tue Feb 13 13:15:05 2001
@@ -3148,6 +3148,7 @@
 	if (skb->protocol == ntohs(ETH_P_ARP))
 		skb->data[1] = 0x06;
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	fi->fc_stats.rx_packets++;
 	LEAVE("rx_net_packet");
 }
@@ -3168,6 +3169,7 @@
 	skb->protocol = fc_type_trans(skb, dev);
 	DPRINTK("protocol = %x", skb->protocol);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	LEAVE("rx_net_mfs_packet");
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
--- v2.4.1/linux/drivers/net/fmv18x.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/fmv18x.c	Tue Feb 13 13:15:05 2001
@@ -20,7 +20,7 @@
 			for testing this driver.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This is a device driver for the Fujitsu FMV-181/182/183/184, which
 	is a straight-forward Fujitsu MB86965 implementation.
@@ -44,7 +44,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <asm/system.h>
@@ -526,7 +526,9 @@
 
 			skb->protocol=eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += pkt_len;
 		}
 		if (--boguscount <= 0)
 			break;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/gmac.c linux/drivers/net/gmac.c
--- v2.4.1/linux/drivers/net/gmac.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/net/gmac.c	Tue Feb 13 13:15:05 2001
@@ -1209,8 +1209,9 @@
 				skb->ip_summed = CHECKSUM_NONE;
 			skb->ip_summed = CHECKSUM_NONE;
 			skb->protocol = eth_type_trans(skb, dev);
-			netif_rx(skb);
 			gm->stats.rx_bytes += skb->len;
+			netif_rx(skb);
+			dev->last_rx = jiffies;
 			++gm->stats.rx_packets;
 		}
 		
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hamachi.c linux/drivers/net/hamachi.c
--- v2.4.1/linux/drivers/net/hamachi.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/hamachi.c	Tue Feb 13 13:15:05 2001
@@ -4,7 +4,7 @@
 	Updates 2000 by Keith Underwood.
 
 	This software may be used and distributed according to the terms of 
-	the GNU Public License (GPL), incorporated herein by reference.
+	the GNU General Public License (GPL), incorporated herein by reference.
 	Drivers based on or derived from this code fall under the GPL and must
 	retain the authorship, copyright and license notice.  This file is not
 	a complete program and may only be used when the entire operating
@@ -159,7 +159,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hamradio/6pack.c linux/drivers/net/hamradio/6pack.c
--- v2.4.1/linux/drivers/net/hamradio/6pack.c	Thu Jan  4 12:50:12 2001
+++ linux/drivers/net/hamradio/6pack.c	Thu Feb  8 16:32:44 2001
@@ -32,7 +32,6 @@
 #include <linux/skbuff.h>
 #include <linux/rtnetlink.h>
 #include <linux/if_arp.h>
-#include <linux/if_slip.h>
 #include <linux/init.h>
 #include <linux/ip.h>
 #include <linux/tcp.h>
@@ -75,7 +74,7 @@
 #define SIXP_RESYNC_TIMEOUT		500	/* in 10 ms */
 
 /* 6pack configuration. */
-#define SIXP_NRUNIT			256	/* MAX number of 6pack channels */
+#define SIXP_NRUNIT			31      /* MAX number of 6pack channels */
 #define SIXP_MTU			256	/* Default MTU */
 
 enum sixpack_flags {
@@ -128,20 +127,18 @@
 	struct timer_list	resync_t;
 };
 
-/* should later be moved to include/net/ax25.h */
 #define AX25_6PACK_HEADER_LEN 0
 #define SIXPACK_MAGIC 0x5304
 
-static const char banner[] __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n";
-
 typedef struct sixpack_ctrl {
-	struct sixpack	ctrl;		/* 6pack things			*/
+	struct sixpack	ctrl;			/* 6pack things			*/
 	struct net_device	dev;		/* the device			*/
 } sixpack_ctrl_t;
 static sixpack_ctrl_t **sixpack_ctrls;
-int sixpack_maxdev = SIXP_NRUNIT;	/* Can be overridden with insmod! */
 
-static struct tty_ldisc	sp_ldisc;
+int sixpack_maxdev = SIXP_NRUNIT;	/* Can be overridden with insmod! */
+MODULE_PARM(sixpack_maxdev, "i");
+MODULE_PARM_DESC(sixpack_maxdev, "number of 6PACK devices");
 
 static void sp_start_tx_timer(struct sixpack *);
 static void sp_xmit_on_air(unsigned long);
@@ -687,52 +684,67 @@
 	return 0;
 }
 
+/* Fill in our line protocol discipline */
+static struct tty_ldisc sp_ldisc = {
+	magic:		TTY_LDISC_MAGIC,
+	name:		"6pack",
+	open:		sixpack_open,
+	close:		sixpack_close,
+	ioctl:		(int (*)(struct tty_struct *, struct file *,
+			unsigned int, unsigned long)) sixpack_ioctl,
+	receive_buf:	sixpack_receive_buf,
+	receive_room:	sixpack_receive_room,
+	write_wakeup:	sixpack_write_wakeup,
+};
+
 /* Initialize 6pack control device -- register 6pack line discipline */
 
+static const char msg_banner[]  __initdata = KERN_INFO "AX.25: 6pack driver, " SIXPACK_VERSION " (dynamic channels, max=%d)\n";
+static const char msg_invparm[] __initdata = KERN_ERR  "6pack: sixpack_maxdev parameter too large.\n";
+static const char msg_nomem[]   __initdata = KERN_ERR  "6pack: can't allocate sixpack_ctrls[] array! No 6pack available.\n";
+static const char msg_regfail[] __initdata = KERN_ERR  "6pack: can't register line discipline (err = %d)\n";
+
 static int __init sixpack_init_driver(void)
 {
 	int status;
 
+	/* Do sanity checks on maximum device parameter. */
 	if (sixpack_maxdev < 4)
-		sixpack_maxdev = 4; /* Sanity */
+		sixpack_maxdev = 4;
+	if (sixpack_maxdev * sizeof(void*) >= KMALLOC_MAXSIZE) {
+	        printk(msg_invparm);
+		return -ENFILE;
+	}
 
-	printk(banner, sixpack_maxdev);
+	printk(msg_banner, sixpack_maxdev);
 
 	sixpack_ctrls = (sixpack_ctrl_t **) kmalloc(sizeof(void*)*sixpack_maxdev, GFP_KERNEL);
 	if (sixpack_ctrls == NULL) {
-		printk(KERN_WARNING "6pack: Can't allocate sixpack_ctrls[] array!  Uaargh! (-> No 6pack available)\n");
+		printk(msg_nomem);
 		return -ENOMEM;
 	}
 
 	/* Clear the pointer array, we allocate devices when we need them */
 	memset(sixpack_ctrls, 0, sizeof(void*)*sixpack_maxdev); /* Pointers */
 
-	/* Fill in our line protocol discipline, and register it */
-	sp_ldisc.magic  = TTY_LDISC_MAGIC;
-	sp_ldisc.name   = "6pack";
-	sp_ldisc.flags  = 0;
-	sp_ldisc.open   = sixpack_open;
-	sp_ldisc.close  = sixpack_close;
-	sp_ldisc.read   = NULL;
-	sp_ldisc.write  = NULL;
-	sp_ldisc.ioctl  = (int (*)(struct tty_struct *, struct file *,
-				   unsigned int, unsigned long)) sixpack_ioctl;
-	sp_ldisc.poll = NULL;
-	sp_ldisc.receive_buf = sixpack_receive_buf;
-	sp_ldisc.receive_room = sixpack_receive_room;
-	sp_ldisc.write_wakeup = sixpack_write_wakeup;
-	if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0)  {
-		printk(KERN_WARNING "6pack: can't register line discipline (err = %d)\n", status);
+	/* Register the provided line protocol discipline */
+	if ((status = tty_register_ldisc(N_6PACK, &sp_ldisc)) != 0) {
+		printk(msg_regfail, status);
 		kfree(sixpack_ctrls);
 	}
 
 	return status;
 }
 
-static void __exit sixpack_cleanup_driver(void)
+static const char msg_unregfail[] __exitdata = KERN_ERR "6pack: can't unregister line discipline (err = %d)\n";
+
+static void __exit sixpack_exit_driver(void)
 {
 	int i;
 
+	if ((i = tty_register_ldisc(N_6PACK, NULL)))
+		printk(msg_unregfail, i);
+
 	for (i = 0; i < sixpack_maxdev; i++) {
 		if (sixpack_ctrls[i]) {
 			/*
@@ -746,8 +758,6 @@
 		}
 	}
 	kfree(sixpack_ctrls);
-	if ((i = tty_register_ldisc(N_6PACK, NULL)))
-		printk(KERN_WARNING "6pack: can't unregister line discipline (err = %d)\n", i);
 }
 
 
@@ -1059,8 +1069,6 @@
 
 MODULE_AUTHOR("Andreas Könsgen <ajk@ccac.rwth-aachen.de>");
 MODULE_DESCRIPTION("6pack driver for AX.25");
-MODULE_PARM(sixpack_maxdev, "i");
-MODULE_PARM_DESC(sixpack_maxdev, "number of 6PACK devices");
 
 module_init(sixpack_init_driver);
-module_exit(sixpack_cleanup_driver);
+module_exit(sixpack_exit_driver);
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hamradio/hdlcdrv.c linux/drivers/net/hamradio/hdlcdrv.c
--- v2.4.1/linux/drivers/net/hamradio/hdlcdrv.c	Mon Dec 11 13:41:41 2000
+++ linux/drivers/net/hamradio/hdlcdrv.c	Tue Feb 13 13:15:05 2001
@@ -49,7 +49,7 @@
 #include <linux/net.h>
 #include <linux/in.h>
 #include <linux/if.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hamradio/scc.c linux/drivers/net/hamradio/scc.c
--- v2.4.1/linux/drivers/net/hamradio/scc.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/hamradio/scc.c	Tue Feb 13 13:15:05 2001
@@ -160,7 +160,7 @@
 #include <linux/in.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 
 #include <linux/skbuff.h>
@@ -1776,7 +1776,7 @@
 
 			if (hwcfg.vector_latch) {
 				if (!request_region(Vector_Latch, 1, "scc vector latch"))
-					printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%x\n, disabled.", (unsigned int)hwcfg.vector_latch);
+					printk(KERN_WARNING "z8530drv: warning, cannot reserve vector latch port 0x%lx\n, disabled.", hwcfg.vector_latch);
 				else
 					Vector_Latch = hwcfg.vector_latch;
 			}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hamradio/yam.c linux/drivers/net/hamradio/yam.c
--- v2.4.1/linux/drivers/net/hamradio/yam.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/net/hamradio/yam.c	Tue Feb 13 13:15:05 2001
@@ -45,7 +45,7 @@
 #include <linux/net.h>
 #include <linux/in.h>
 #include <linux/if.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <asm/bitops.h>
 #include <asm/io.h>
@@ -878,7 +878,6 @@
 
 	printk(KERN_INFO "%s at iobase 0x%lx irq %u uart %s\n", dev->name, dev->base_addr, dev->irq,
 		   uart_str[u]);
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -905,7 +904,6 @@
 
 	printk(KERN_INFO "%s: close yam at iobase 0x%lx irq %u\n",
 		   yam_drvname, dev->base_addr, dev->irq);
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -938,14 +936,17 @@
 	case SIOCYAMSMCS:
 		if (netif_running(dev))
 			return -EINVAL;		/* Cannot change this parameter when up */
-		ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_KERNEL);
-		if(ym==NULL)
+		if ((ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_KERNEL)) == NULL)
 			return -ENOBUFS;
 		ym->bitrate = 9600;
-		if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs)))
-			 return -EFAULT;
-		if (ym->bitrate > YAM_MAXBITRATE)
+		if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs))) {
+			kfree(ym);
+			return -EFAULT;
+		}
+		if (ym->bitrate > YAM_MAXBITRATE) {
+			kfree(ym);
 			return -EINVAL;
+		}
 		add_mcs(ym->bits, ym->bitrate);
 		kfree(ym);
 		break;
@@ -1129,8 +1130,11 @@
 
 		if (register_netdev(dev)) {
 			printk(KERN_WARNING "yam: cannot register net device %s\n", dev->name);
+			dev->priv = NULL;
 			return -ENXIO;
 		}
+
+		SET_MODULE_OWNER(dev);
 	}
 
 	yam_timer.function = yam_dotimer;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hp-plus.c linux/drivers/net/hp-plus.c
--- v2.4.1/linux/drivers/net/hp-plus.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/hp-plus.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	These cards are sold under several model numbers, usually 2724*.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hp.c linux/drivers/net/hp.c
--- v2.4.1/linux/drivers/net/hp.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/hp.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hp100.c linux/drivers/net/hp100.c
--- v2.4.1/linux/drivers/net/hp100.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/hp100.c	Tue Feb 13 13:15:05 2001
@@ -96,7 +96,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
@@ -1317,7 +1317,7 @@
  * Returns: 0 if unable to allocate skb_buff
  *          1 if successful
  */
-int hp100_build_rx_pdl( hp100_ring_t *ringptr, struct net_device *dev )
+static int hp100_build_rx_pdl( hp100_ring_t *ringptr, struct net_device *dev )
 {
 #ifdef HP100_DEBUG_B
   int ioaddr = dev->base_addr;
@@ -1969,8 +1969,9 @@
 	  skb->protocol = eth_type_trans( skb, dev );
 
 	  netif_rx( skb );
+	  dev->last_rx = jiffies;
 	  lp->stats.rx_packets++;
-	  lp->stats.rx_bytes += skb->len;
+	  lp->stats.rx_bytes += pkt_len;
       
 #ifdef HP100_DEBUG_RX
 	  printk( "hp100: %s: rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
@@ -2076,8 +2077,9 @@
 														
 	      netif_rx( ptr->skb );              /* Up and away... */
 
+	      dev->last_rx = jiffies;
 	      lp->stats.rx_packets++;
-	      lp->stats.rx_bytes += ptr->skb->len;
+	      lp->stats.rx_bytes += pkt_len;
 	    }
 
           switch ( header & 0x00070000 ) {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hplance.c linux/drivers/net/hplance.c
--- v2.4.1/linux/drivers/net/hplance.c	Tue Dec  5 12:31:01 2000
+++ linux/drivers/net/hplance.c	Tue Feb 13 13:15:04 2001
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/hydra.c linux/drivers/net/hydra.c
--- v2.4.1/linux/drivers/net/hydra.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/hydra.c	Tue Feb 13 13:15:04 2001
@@ -19,7 +19,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -82,9 +82,6 @@
     unsigned long board;
     int err = -ENODEV;
 
-    if (load_8390_module("hydra.c"))
-	return -ENOSYS;
-
     while ((z = zorro_find_device(ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET, z))) {
 	board = z->resource.start;
 	if (!request_mem_region(board, 0x10000, "Hydra"))
@@ -96,10 +93,9 @@
 	err = 0;
     }
 
-    if (err == -ENODEV) {
+    if (err == -ENODEV)
 	printk("No Hydra ethernet card found.\n");
-	unload_8390_module();
-    }
+
     return err;
 }
 
@@ -116,9 +112,10 @@
 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
 
-    dev = init_etherdev(0, 0);
+    dev = init_etherdev(NULL, 0);
     if (!dev)
 	return -ENOMEM;
+    SET_MODULE_OWNER(dev);
 
     for(j = 0; j < ETHER_ADDR_LEN; j++)
 	dev->dev_addr[j] = *((u8 *)(board + HYDRA_ADDRPROM + 2*j));
@@ -174,7 +171,6 @@
 static int hydra_open(struct net_device *dev)
 {
     ei_open(dev);
-    MOD_INC_USE_COUNT;
     return 0;
 }
 
@@ -183,7 +179,6 @@
     if (ei_debug > 1)
 	printk("%s: Shutting down ethercard.\n", dev->name);
     ei_close(dev);
-    MOD_DEC_USE_COUNT;
     return 0;
 }
 
@@ -254,7 +249,6 @@
 	kfree(dev);
 	root_hydra_dev = next;
     }
-    unload_8390_module();
 #endif
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/i82586.h linux/drivers/net/i82586.h
--- v2.4.1/linux/drivers/net/i82586.h	Mon Dec  2 23:24:15 1996
+++ linux/drivers/net/i82586.h	Tue Feb 13 13:15:05 2001
@@ -407,7 +407,7 @@
 
 /*
  * This software may only be used and distributed
- * according to the terms of the GNU Public License.
+ * according to the terms of the GNU General Public License.
  *
  * For more details, see wavelan.c.
  */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ibmlana.c linux/drivers/net/ibmlana.c
--- v2.4.1/linux/drivers/net/ibmlana.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/ibmlana.c	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
 net-3-driver for the IBM LAN Adapter/A
 
 This is an extension to the Linux operating system, and is covered by the
-same Gnu Public License that covers that work.
+same GNU General Public License that covers that work.
 
 Copyright 1999 by Alfred Arnold (alfred@ccac.rwth-aachen.de, aarnold@elsa.de)
 
@@ -78,7 +78,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/time.h>
@@ -621,6 +621,7 @@
 
 				/* bookkeeping */
 
+				dev->last_rx = jiffies;
 				priv->stat.rx_packets++;
 #if (LINUX_VERSION_CODE >= 0x20119)	/* byte counters for kernel >= 2.1.25 */
 				priv->stat.rx_bytes += rda.length;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ioc3-eth.c linux/drivers/net/ioc3-eth.c
--- v2.4.1/linux/drivers/net/ioc3-eth.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/ioc3-eth.c	Tue Feb 13 13:15:05 2001
@@ -447,6 +447,7 @@
 			rxb = (struct ioc3_erxbuf *) new_skb->data;
 			skb_reserve(new_skb, RX_OFFSET);
 
+			dev->last_rx = jiffies;
 			ip->stats.rx_packets++;		/* Statistics */
 			ip->stats.rx_bytes += len;
 		} else {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.4.1/linux/drivers/net/irda/irport.c	Sun Nov 12 20:43:07 2000
+++ linux/drivers/net/irda/irport.c	Tue Feb 13 13:15:05 2001
@@ -41,7 +41,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/serial_reg.h>
@@ -616,7 +616,7 @@
 	struct irport_cb *self;
 	unsigned long flags;
 	int iobase;
-	__u32 speed;
+	__s32 speed;
 
 	ASSERT(dev != NULL, return 0;);
 	
@@ -628,12 +628,14 @@
 	netif_stop_queue(dev);
 	
 	/* Check if we need to change the speed */
-	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
 			irda_task_execute(self, __irport_change_speed, 
 					  irport_change_speed_complete, 
 					  NULL, (void *) speed);
+			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.4.1/linux/drivers/net/irda/irtty.c	Mon Nov 27 18:07:31 2000
+++ linux/drivers/net/irda/irtty.c	Thu Feb  8 15:14:08 2001
@@ -279,6 +279,11 @@
 	tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
 	tty->disc_data = 0;
 	
+	/* We are not using any dongle anymore! */
+	if (self->dongle)
+		irda_device_dongle_cleanup(self->dongle);
+	self->dongle = NULL;
+
 	/* Remove netdevice */
 	if (self->netdev) {
 		rtnl_lock();
@@ -286,11 +291,6 @@
 		rtnl_unlock();
 	}
 	
-	/* We are not using any dongle anymore! */
-	if (self->dongle)
-		irda_device_dongle_cleanup(self->dongle);
-	self->dongle = NULL;
-
 	/* Remove speed changing task if any */
 	if (self->task)
 		irda_task_delete(self->task);
@@ -629,7 +629,7 @@
 {
 	struct irtty_cb *self;
 	int actual = 0;
-	__u32 speed;
+	__s32 speed;
 
 	self = (struct irtty_cb *) dev->priv;
 	ASSERT(self != NULL, return 0;);
@@ -638,12 +638,14 @@
 	netif_stop_queue(dev);
 	
 	/* Check if we need to change the speed */
-	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
 			irda_task_execute(self, irtty_change_speed, 
 					  irtty_change_speed_complete, 
 					  NULL, (void *) speed);
+			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c
--- v2.4.1/linux/drivers/net/irda/nsc-ircc.c	Mon Nov 27 18:07:31 2000
+++ linux/drivers/net/irda/nsc-ircc.c	Tue Feb 13 13:15:05 2001
@@ -49,7 +49,7 @@
 #include <linux/netdevice.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
 
@@ -1064,7 +1064,7 @@
 	struct nsc_ircc_cb *self;
 	unsigned long flags;
 	int iobase;
-	__u32 speed;
+	__s32 speed;
 	__u8 bank;
 	
 	self = (struct nsc_ircc_cb *) dev->priv;
@@ -1076,10 +1076,12 @@
 	netif_stop_queue(dev);
 		
 	/* Check if we need to change the speed */
-	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
 			nsc_ircc_change_speed(self, speed); 
+			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
@@ -1116,7 +1118,7 @@
 	struct nsc_ircc_cb *self;
 	unsigned long flags;
 	int iobase;
-	__u32 speed;
+	__s32 speed;
 	__u8 bank;
 	int mtt, diff;
 	
@@ -1126,10 +1128,12 @@
 	netif_stop_queue(dev);
 	
 	/* Check if we need to change the speed */
-	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
 			nsc_ircc_change_speed(self, speed); 
+			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
@@ -1956,16 +1960,20 @@
 	/* Disable interrupts & save flags */
 	save_flags(flags);
 	cli();
-	
+
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			goto out;
+		}
 		nsc_ircc_change_speed(self, irq->ifr_baudrate);
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			goto out;
+		}
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
@@ -1974,9 +1982,8 @@
 	default:
 		ret = -EOPNOTSUPP;
 	}
-	
+out:
 	restore_flags(flags);
-	
 	return ret;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c
--- v2.4.1/linux/drivers/net/irda/smc-ircc.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/irda/smc-ircc.c	Tue Feb 13 13:15:05 2001
@@ -40,7 +40,7 @@
 #include <linux/netdevice.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
 #include <linux/serial_reg.h>
@@ -606,7 +606,7 @@
 	struct irport_cb *irport;
 	struct ircc_cb *self;
 	unsigned long flags;
-	__u32 speed;
+	__s32 speed;
 	int iobase;
 	int mtt;
 
@@ -619,10 +619,12 @@
 	netif_stop_queue(dev);
 
 	/* Check if we need to change the speed after this frame */
-	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
 			ircc_change_speed(self, speed); 
+			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c
--- v2.4.1/linux/drivers/net/irda/toshoboe.c	Thu Jan  4 12:50:12 2001
+++ linux/drivers/net/irda/toshoboe.c	Tue Feb 13 13:15:05 2001
@@ -62,7 +62,7 @@
 #include <linux/netdevice.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/rtnetlink.h>
@@ -263,7 +263,7 @@
 toshoboe_hard_xmit (struct sk_buff *skb, struct net_device *dev)
 {
   struct toshoboe_cb *self;
-  __u32 speed;
+  __s32 speed;
   int mtt, len;
 
   self = (struct toshoboe_cb *) dev->priv;
@@ -272,10 +272,12 @@
     );
 
   /* Check if we need to change the speed */
-  if ((speed = irda_get_speed(skb)) != self->io.speed) {
+  speed = irda_get_next_speed(skb);
+  if ((speed != self->io.speed) && (speed != -1)) {
 	/* Check for empty frame */
 	if (!skb->len) {
 	    toshoboe_setbaud(self, speed); 
+	    dev_kfree_skb(skb);
 	    return 0;
 	} else
 	    self->new_speed = speed;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c
--- v2.4.1/linux/drivers/net/irda/w83977af_ir.c	Sat Nov 11 18:11:23 2000
+++ linux/drivers/net/irda/w83977af_ir.c	Tue Feb 13 13:15:05 2001
@@ -47,7 +47,7 @@
 #include <linux/netdevice.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/rtnetlink.h>
 
@@ -497,7 +497,7 @@
 int w83977af_hard_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct w83977af_ir *self;
-	__u32 speed;
+	__s32 speed;
 	int iobase;
 	__u8 set;
 	int mtt;
@@ -513,10 +513,12 @@
 	netif_stop_queue(dev);
 	
 	/* Check if we need to change the speed */
-	if ((speed = irda_get_speed(skb)) != self->io.speed) {
+	speed = irda_get_next_speed(skb);
+	if ((speed != self->io.speed) && (speed != -1)) {
 		/* Check for empty frame */
 		if (!skb->len) {
 			w83977af_change_speed(self, speed); 
+			dev_kfree_skb(skb);
 			return 0;
 		} else
 			self->new_speed = speed;
@@ -1337,13 +1339,17 @@
 	
 	switch (cmd) {
 	case SIOCSBANDWIDTH: /* Set bandwidth */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			goto out;
+		}
 		w83977af_change_speed(self, irq->ifr_baudrate);
 		break;
 	case SIOCSMEDIABUSY: /* Set media busy */
-		if (!capable(CAP_NET_ADMIN))
-			return -EPERM;
+		if (!capable(CAP_NET_ADMIN)) {
+			ret = -EPERM;
+			goto out;
+		}
 		irda_device_set_media_busy(self->netdev, TRUE);
 		break;
 	case SIOCGRECEIVING: /* Check if we are receiving right now */
@@ -1352,9 +1358,8 @@
 	default:
 		ret = -EOPNOTSUPP;
 	}
-	
+out:
 	restore_flags(flags);
-	
 	return ret;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/isa-skeleton.c linux/drivers/net/isa-skeleton.c
--- v2.4.1/linux/drivers/net/isa-skeleton.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/isa-skeleton.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
  *	Director, National Security Agency.
  *
  *	This software may be used and distributed according to the terms
- *	of the GNU Public License, incorporated herein by reference.
+ *	of the GNU General Public License, incorporated herein by reference.
  *
  *	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
  *	Center of Excellence in Space Data and Information Sciences
@@ -49,7 +49,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -544,7 +544,9 @@
 			insw(ioaddr, skb->data, (pkt_len + 1) >> 1);
 
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
+			lp->stats.rx_bytes += pkt_len;
 		}
 	} while (--boguscount);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/jazzsonic.c linux/drivers/net/jazzsonic.c
--- v2.4.1/linux/drivers/net/jazzsonic.c	Mon Oct 30 12:24:21 2000
+++ linux/drivers/net/jazzsonic.c	Tue Feb 13 13:15:04 2001
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <asm/bootinfo.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/lance.c linux/drivers/net/lance.c
--- v2.4.1/linux/drivers/net/lance.c	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/lance.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	Copyright 1993 United States Government as represented by the
 	Director, National Security Agency.
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This driver is for the Allied Telesis AT1500 and HP J2405A, and should work
 	with most other LANCE-based bus-master (NE2100/NE2500) ethercards.
@@ -44,7 +44,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/init.h>
@@ -837,7 +837,7 @@
 	lance_restart (dev, 0x0043, 1);
 
 	dev->trans_start = jiffies;
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 }
 
 
@@ -874,6 +874,8 @@
 
 	lp->tx_ring[entry].misc = 0x0000;
 
+	lp->stats.tx_bytes += skb->len;
+
 	/* If any part of this buffer is >16M we must copy it to a low-memory
 	   buffer. */
 	if ((u32)virt_to_bus(skb->data) + skb->len > 0x01000000) {
@@ -889,7 +891,6 @@
 		lp->tx_ring[entry].base = ((u32)virt_to_bus(skb->data) & 0xffffff) | 0x83000000;
 	}
 	lp->cur_tx++;
-	lp->stats.tx_bytes += skb->len;
 
 	/* Trigger an immediate send poll. */
 	outw(0x0000, ioaddr+LANCE_ADDR);
@@ -1087,10 +1088,11 @@
 				eth_copy_and_sum(skb,
 					(unsigned char *)bus_to_virt((lp->rx_ring[entry].base & 0x00ffffff)),
 					pkt_len,0);
-				lp->stats.rx_bytes+=skb->len;
 				skb->protocol=eth_type_trans(skb,dev);
-				lp->stats.rx_packets++;
 				netif_rx(skb);
+				dev->last_rx = jiffies;
+				lp->stats.rx_packets++;
+				lp->stats.rx_bytes+=pkt_len;
 			}
 		}
 		/* The docs say that the buffer length isn't touched, but Andrew Boyd
diff -u --recursive --new-file v2.4.1/linux/drivers/net/lasi_82596.c linux/drivers/net/lasi_82596.c
--- v2.4.1/linux/drivers/net/lasi_82596.c	Wed Dec  6 11:46:39 2000
+++ linux/drivers/net/lasi_82596.c	Tue Feb 13 13:15:05 2001
@@ -60,7 +60,7 @@
    Written 1993 by Donald Becker.
    Copyright 1993 United States Government as represented by the Director,
    National Security Agency. This software may only be used and distributed
-   according to the terms of the GNU Public License as modified by SRC,
+   according to the terms of the GNU General Public License as modified by SRC,
    incorporated herein by reference.
 
    The author may be reached as becker@super.org or
@@ -68,8 +68,6 @@
 
  */
 
-static const char *version = "82596.c $Revision: 1.14 $\n";
-
 #include <linux/module.h>
 
 #include <linux/kernel.h>
@@ -78,7 +76,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
@@ -97,6 +95,9 @@
 #include <asm/gsc.h>
 #include <asm/cache.h>
 
+static char version[] __initdata =
+	"82596.c $Revision: 1.14 $\n";
+
 /* DEBUG flags
  */
 
@@ -374,7 +375,7 @@
 	dma_addr_t dma_addr;
 };
 
-char init_setup[] =
+static char init_setup[] =
 {
 	0x8E,			/* length, prefetch on */
 	0xC8,			/* fifo to 8, monitor off */
@@ -790,6 +791,7 @@
 				skb->len = pkt_len;
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
 				lp->stats.rx_bytes+=pkt_len;
 			}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/lne390.c linux/drivers/net/lne390.c
--- v2.4.1/linux/drivers/net/lne390.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/lne390.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Copyright (C) 1996-1998, Paul Gortmaker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Information and Code Sources:
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/loopback.c linux/drivers/net/loopback.c
--- v2.4.1/linux/drivers/net/loopback.c	Mon Mar 27 10:35:56 2000
+++ linux/drivers/net/loopback.c	Tue Feb 13 13:15:05 2001
@@ -85,12 +85,14 @@
 #ifndef LOOPBACK_MUST_CHECKSUM
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 #endif
-	netif_rx(skb);
 
+	dev->last_rx = jiffies;
 	stats->rx_bytes+=skb->len;
 	stats->tx_bytes+=skb->len;
 	stats->rx_packets++;
 	stats->tx_packets++;
+
+	netif_rx(skb);
 
 	return(0);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/mac89x0.c linux/drivers/net/mac89x0.c
--- v2.4.1/linux/drivers/net/mac89x0.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/net/mac89x0.c	Tue Feb 13 13:15:05 2001
@@ -1,10 +1,10 @@
-/* cs89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
+/* mac89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
 /*
 	Written 1996 by Russell Nelson, with reference to skeleton.c
 	written 1993-1994 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached at nelson@crynwr.com, Crynwr
 	Software, 11 Grant St., Potsdam, NY 13676
@@ -86,7 +86,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/nubus.h>
 #include <asm/system.h>
@@ -527,9 +527,9 @@
 
         skb->protocol=eth_type_trans(skb,dev);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
-	lp->stats.rx_bytes+=skb->len;
-	return;
+	lp->stats.rx_bytes += length;
 }
 
 /* The inverse routine to net_open(). */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/mace.c linux/drivers/net/mace.c
--- v2.4.1/linux/drivers/net/mace.c	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/mace.c	Tue Feb 13 13:15:05 2001
@@ -826,9 +826,10 @@
 		skb_put(skb, nb);
 		skb->dev = dev;
 		skb->protocol = eth_type_trans(skb, dev);
+		mp->stats.rx_bytes += skb->len;
 		netif_rx(skb);
+		dev->last_rx = jiffies;
 		mp->rx_bufs[i] = 0;
-		mp->stats.rx_bytes += skb->len;
 		++mp->stats.rx_packets;
 	    }
 	} else {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/macmace.c linux/drivers/net/macmace.c
--- v2.4.1/linux/drivers/net/macmace.c	Mon Jan 31 10:34:12 2000
+++ linux/drivers/net/macmace.c	Tue Feb 13 13:15:05 2001
@@ -733,6 +733,7 @@
 	
 	skb->protocol = eth_type_trans(skb, dev);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	mp->stats.rx_packets++;
 	mp->stats.rx_bytes+=mf->len;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/macsonic.c linux/drivers/net/macsonic.c
--- v2.4.1/linux/drivers/net/macsonic.c	Mon Jan 31 23:43:51 2000
+++ linux/drivers/net/macsonic.c	Tue Feb 13 13:15:04 2001
@@ -32,7 +32,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/nubus.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/mvme147.c linux/drivers/net/mvme147.c
--- v2.4.1/linux/drivers/net/mvme147.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/net/mvme147.c	Tue Feb 13 13:15:04 2001
@@ -12,7 +12,7 @@
 #include <linux/interrupt.h>
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/myri_sbus.c linux/drivers/net/myri_sbus.c
--- v2.4.1/linux/drivers/net/myri_sbus.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/myri_sbus.c	Tue Feb 13 13:15:05 2001
@@ -17,7 +17,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -531,7 +531,9 @@
 		DRX(("prot[%04x] netif_rx ", skb->protocol));
 		netif_rx(skb);
 
+		dev->last_rx = jiffies;
 		mp->enet_stats.rx_packets++;
+		mp->enet_stats.rx_bytes += len;
 	next:
 		DRX(("NEXT\n"));
 		entry = NEXT_RX(entry);
@@ -592,7 +594,7 @@
 
 	mp->enet_stats.tx_errors++;
 	myri_init(mp, 0);
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 }
 
 static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/natsemi.c linux/drivers/net/natsemi.c
--- v2.4.1/linux/drivers/net/natsemi.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/natsemi.c	Tue Feb 13 13:15:04 2001
@@ -26,6 +26,11 @@
 		- Bug fixes and better intr performance (Tjeerd)
 	Version 1.0.2:
 		- Now reads correct MAC address from eeprom
+	Version 1.0.3:
+		- Eliminate redundant priv->tx_full flag
+		- Call netif_start_queue from dev->tx_timeout
+		- wmb() in start_tx() to flush data
+		- Update Tx locking
 
 */
 
@@ -35,7 +40,7 @@
 static const char version2[] =
 "  http://www.scyld.com/network/natsemi.html\n";
 static const char version3[] =
-"  (unofficial 2.4.x kernel port, version 1.0.2, October 6, 2000 Jeff Garzik, Tjeerd Mulder)\n";
+"  (unofficial 2.4.x kernel port, version 1.0.3, January 21, 2001 Jeff Garzik, Tjeerd Mulder)\n";
 /* Updated to recommendations in pci-skeleton v2.03. */
 
 /* Automatically extracted configuration info:
@@ -105,7 +110,7 @@
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -187,13 +192,14 @@
 
 The send packet thread has partial control over the Tx ring and 'dev->tbusy'
 flag.  It sets the tbusy flag whenever it's queuing a Tx packet. If the next
-queue slot is empty, it clears the tbusy flag when finished otherwise it sets
-the 'lp->tx_full' flag.
+queue slot is empty, it clears the tbusy flag when finished.  Under 2.4, the
+"tbusy flag" is now controlled by netif_{start,stop,wake}_queue() and tested
+by netif_queue_stopped().
 
 The interrupt handler has exclusive control over the Rx ring and records stats
 from the Tx ring.  After reaping the stats, it marks the Tx queue entry as
-empty by incrementing the dirty_tx mark. Iff the 'lp->tx_full' flag is set, it
-clears both the tx_full and tbusy flags.
+empty by incrementing the dirty_tx mark. Iff Tx queueing is stopped and Tx
+entries were reaped, the Tx queue is started and scheduled.
 
 IV. Notes
 
@@ -319,7 +325,6 @@
 	unsigned int cur_rx, dirty_rx;		/* Producer/consumer ring indices */
 	unsigned int cur_tx, dirty_tx;
 	unsigned int rx_buf_sz;				/* Based on MTU+slack. */
-	unsigned int tx_full:1;				/* The Tx queue is full. */
 	/* These values are keep track of the transceiver/media in use. */
 	unsigned int full_duplex:1;			/* Full-duplex operation requested. */
 	unsigned int duplex_lock:1;
@@ -697,7 +702,7 @@
 
 	dev->trans_start = jiffies;
 	np->stats.tx_errors++;
-	return;
+	netif_start_queue(dev);
 }
 
 
@@ -707,7 +712,6 @@
 	struct netdev_private *np = (struct netdev_private *)dev->priv;
 	int i;
 
-	np->tx_full = 0;
 	np->cur_rx = np->cur_tx = 0;
 	np->dirty_rx = np->dirty_tx = 0;
 
@@ -763,11 +767,13 @@
 	np->cur_tx++;
 
 	/* StrongARM: Explicitly cache flush np->tx_ring and skb->data,skb->len. */
+	wmb();
 
-	if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1) {
-		np->tx_full = 1;
+	spin_lock_irq(&np->lock);
+	if (np->cur_tx - np->dirty_tx >= TX_QUEUE_LEN - 1)
 		netif_stop_queue(dev);
-	}
+	spin_unlock_irq(&np->lock);
+
 	/* Wake the potentially-idle transmit channel. */
 	writel(TxOn, dev->base_addr + ChipCmd);
 
@@ -798,9 +804,7 @@
 #endif
 
 	ioaddr = dev->base_addr;
-	np = (struct netdev_private *)dev->priv;
-
-	spin_lock(&np->lock);
+	np = dev->priv;
 
 	do {
 		u32 intr_status = readl(ioaddr + IntrStatus);
@@ -818,6 +822,8 @@
 		if (intr_status & (IntrRxDone | IntrRxErr | IntrRxIdle | IntrRxOverrun))
 			netdev_rx(dev);
 
+		spin_lock(&np->lock);
+
 		for (; np->cur_tx - np->dirty_tx > 0; np->dirty_tx++) {
 			int entry = np->dirty_tx % TX_RING_SIZE;
 			if (np->tx_ring[entry].cmd_status & cpu_to_le32(DescOwn))
@@ -839,13 +845,14 @@
 			dev_kfree_skb_irq(np->tx_skbuff[entry]);
 			np->tx_skbuff[entry] = 0;
 		}
-		if (np->tx_full
+		if (netif_queue_stopped(dev)
 			&& np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
 			/* The ring is no longer full, wake queue. */
-			np->tx_full = 0;
 			netif_wake_queue(dev);
 		}
 
+		spin_unlock(&np->lock);
+
 		/* Abnormal error summary/uncommon events handlers. */
 		if (intr_status & IntrAbnormalSummary)
 			netdev_error(dev, intr_status);
@@ -873,8 +880,6 @@
 		}
 	}
 #endif
-
-	spin_unlock(&np->lock);
 }
 
 /* This routine is logically part of the interrupt handler, but separated
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ne.c linux/drivers/net/ne.c
--- v2.4.1/linux/drivers/net/ne.c	Thu Jan  4 14:44:07 2001
+++ linux/drivers/net/ne.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
     Director, National Security Agency.
 
     This software may be used and distributed according to the terms
-    of the GNU Public License, incorporated herein by reference.
+    of the GNU General Public License, incorporated herein by reference.
 
     The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
     Center of Excellence in Space Data and Information Sciences
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ne2.c linux/drivers/net/ne2.c
--- v2.4.1/linux/drivers/net/ne2.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/ne2.c	Fri Feb  9 11:40:02 2001
@@ -4,7 +4,7 @@
    modified by Wim Dumon (Apr 1996)
 
    This software may be used and distributed according to the terms
-   of the GNU Public License, incorporated herein by reference.
+   of the GNU General Public License, incorporated herein by reference.
 
    The author may be reached as wimpie@linux.cc.kuleuven.ac.be
 
@@ -45,6 +45,9 @@
 
    Mon Nov 16 15:28:23 CET 1998 (Wim Dumon)
    - pass 'dev' as last parameter of request_irq in stead of 'NULL'   
+
+   Wed Feb  7 21:24:00 CET 2001 (Alfred Arnold)
+   - added support for the D-Link DE-320CT
    
    *    WARNING
 	-------
@@ -67,7 +70,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <asm/system.h>
 #include <asm/bitops.h>
@@ -114,6 +117,11 @@
 		{0x1000, 0x2020, 0x8020, 0xa0a0, 0xb0b0, 0xc0c0, 0xc3d0};
 static int irqs[4] __initdata = {3, 4, 5, 9};
 
+/* From the D-Link ADF file: */
+static unsigned int dlink_addresses[4]=
+                {0x300, 0x320, 0x340, 0x360};
+static int dlink_irqs[8] = {3, 4, 5, 9, 10, 11, 14, 15};
+
 struct ne2_adapters_t {
 	unsigned int	id;
 	char		*name;
@@ -123,6 +131,7 @@
 	{ 0x6354, "Arco Ethernet Adapter AE/2" },
 	{ 0x70DE, "Compex ENET-16 MC/P" },
 	{ 0x7154, "Novell Ethernet Adapter NE/2" },
+        { 0x56ea, "D-Link DE-320CT" },
 	{ 0x0000, NULL }
 };
 
@@ -143,6 +152,98 @@
 
 
 /*
+ * special code to read the DE-320's MAC address EEPROM.  In contrast to a 
+ * standard NE design, this is a serial EEPROM (93C46) that has to be read
+ * bit by bit.  The EEPROM cotrol port at base + 0x1e has the following 
+ * layout:
+ *
+ * Bit 0 = Data out (read from EEPROM)
+ * Bit 1 = Data in  (write to EEPROM)
+ * Bit 2 = Clock
+ * Bit 3 = Chip Select
+ * Bit 7 = ~50 kHz clock for defined delays
+ *
+ */
+
+static void dlink_put_eeprom(unsigned char value, unsigned int addr)
+{
+	int z;
+	unsigned char v1, v2;
+
+	/* write the value to the NIC EEPROM register */
+
+	outb(value, addr + 0x1e);
+
+	/* now wait the clock line to toggle twice.  Effectively, we are
+	   waiting (at least) for one clock cycle */
+
+	for (z = 0; z < 2; z++) {
+		do {
+			v1 = inb(addr + 0x1e);
+			v2 = inb(addr + 0x1e);
+		}
+		while (!((v1 ^ v2) & 0x80));
+	}
+}
+
+static void dlink_send_eeprom_bit(unsigned int bit, unsigned int addr)
+{
+	/* shift data bit into correct position */
+
+	bit = bit << 1;
+
+	/* write value, keep clock line high for two cycles */
+
+	dlink_put_eeprom(0x09 | bit, addr);
+	dlink_put_eeprom(0x0d | bit, addr);
+	dlink_put_eeprom(0x0d | bit, addr);
+	dlink_put_eeprom(0x09 | bit, addr);
+}
+
+static void dlink_send_eeprom_word(unsigned int value, unsigned int len, unsigned int addr)
+{
+	int z;
+
+	/* adjust bits so that they are left-aligned in a 16-bit-word */
+
+	value = value << (16 - len);
+
+	/* shift bits out to the EEPROM */
+
+	for (z = 0; z < len; z++) {
+		dlink_send_eeprom_bit((value & 0x8000) >> 15, addr);
+		value = value << 1;
+	}
+}
+
+static unsigned int dlink_get_eeprom(unsigned int eeaddr, unsigned int addr)
+{
+	int z;
+	unsigned int value = 0;
+ 
+	/* pull the CS line low for a moment.  This resets the EEPROM-
+	   internal logic, and makes it ready for a new command. */
+
+	dlink_put_eeprom(0x01, addr);
+	dlink_put_eeprom(0x09, addr);
+
+	/* send one start bit, read command (1 - 0), plus the address to
+           the EEPROM */
+
+	dlink_send_eeprom_word(0x0180 | (eeaddr & 0x3f), 9, addr);
+
+	/* get the data word.  We clock by sending 0s to the EEPROM, which
+	   get ignored during the read process */
+
+	for (z = 0; z < 16; z++) {
+		dlink_send_eeprom_bit(0, addr);
+		value = (value << 1) | (inb(addr + 0x1e) & 0x01);
+	}
+
+	return value;
+}
+
+/*
  * Note that at boot, this probe only picks up one card at a time.
  */
 
@@ -221,12 +322,20 @@
 		return -ENODEV;
 	}
 
-	i = (POS & 0xE)>>1;
-	/* printk("Halleluja sdog, als er na de pijl een 1 staat is 1 - 1 == 0"
-	   " en zou het moeten werken -> %d\n", i);
-	   The above line was for remote testing, thanx to sdog ... */
-	base_addr = addresses[i - 1];
-	irq = irqs[(POS & 0x60)>>5];
+	/* handle different POS register structure for D-Link card */
+
+	if (mca_read_stored_pos(slot, 0) == 0xea) {
+		base_addr = dlink_addresses[(POS >> 5) & 0x03];
+		irq = dlink_irqs[(POS >> 2) & 0x07];
+	}
+        else {
+		i = (POS & 0xE)>>1;
+		/* printk("Halleluja sdog, als er na de pijl een 1 staat is 1 - 1 == 0"
+	   	" en zou het moeten werken -> %d\n", i);
+	   	The above line was for remote testing, thanx to sdog ... */
+		base_addr = addresses[i - 1];
+		irq = irqs[(POS & 0x60)>>5];
+	}
 
 	if (!request_region(base_addr, NE_IO_EXTENT, dev->name))
 		return -EBUSY;
@@ -307,6 +416,20 @@
 	}
 	for(i = 0; i < 6 /*sizeof(SA_prom)*/; i+=1) {
 		SA_prom[i] = inb(base_addr + NE_DATAPORT);
+	}
+
+	/* I don't know whether the previous sequence includes the general
+           board reset procedure, so better don't omit it and just overwrite
+           the garbage read from a DE-320 with correct stuff. */
+
+	if (mca_read_stored_pos(slot, 0) == 0xea) {
+		unsigned int v;
+
+		for (i = 0; i < 3; i++) {
+ 			v = dlink_get_eeprom(i, base_addr);
+			SA_prom[(i << 1)    ] = v & 0xff;
+			SA_prom[(i << 1) + 1] = (v >> 8) & 0xff;
+		}
 	}
 
 	start_page = NESM_START_PG;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ne2k-pci.c linux/drivers/net/ne2k-pci.c
--- v2.4.1/linux/drivers/net/ne2k-pci.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/ne2k-pci.c	Sat Feb  3 11:44:58 2001
@@ -202,6 +202,10 @@
 	if (fnd_cnt++ == 0)
 		printk(KERN_INFO "%s" KERN_INFO "%s", version1, version2);
 
+	i = pci_enable_device (pdev);
+	if (i)
+		return i;
+
 	ioaddr = pci_resource_start (pdev, 0);
 	irq = pdev->irq;
 
@@ -209,10 +213,6 @@
 		printk (KERN_ERR "ne2k-pci: no I/O resource at PCI BAR #0\n");
 		return -ENODEV;
 	}
-
-	i = pci_enable_device (pdev);
-	if (i)
-		return i;
 
 	if (request_region (ioaddr, NE_IO_EXTENT, "ne2k-pci") == NULL) {
 		printk (KERN_ERR "ne2k-pci: I/O resource 0x%x @ 0x%lx busy\n",
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ne3210.c linux/drivers/net/ne3210.c
--- v2.4.1/linux/drivers/net/ne3210.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/ne3210.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Copyright (C) 1998, Paul Gortmaker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Information and Code Sources:
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/net_init.c linux/drivers/net/net_init.c
--- v2.4.1/linux/drivers/net/net_init.c	Tue Sep 19 08:31:43 2000
+++ linux/drivers/net/net_init.c	Tue Feb 13 13:15:04 2001
@@ -36,7 +36,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/if_ether.h>
 #include <linux/string.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ni5010.c linux/drivers/net/ni5010.c
--- v2.4.1/linux/drivers/net/ni5010.c	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/ni5010.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
  *	Copyright 1996,1997 Jan-Pascal van Best and Andreas Mohr.
  *
  *	This software may be used and distributed according to the terms
- *	of the GNU Public License, incorporated herein by reference.
+ *	of the GNU General Public License, incorporated herein by reference.
  *
  * 	The authors may be reached as:
  *		jvbest@wi.leidenuniv.nl		a.mohr@mailto.de
@@ -55,7 +55,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -117,7 +117,7 @@
 static void	hardware_send_packet(struct net_device *dev, char *buf, int length);
 static void 	chipset_init(struct net_device *dev, int startp);
 static void	dump_packet(void *buf, int len);
-static void 	show_registers(struct net_device *dev);
+static void 	ni5010_show_registers(struct net_device *dev);
 
 
 int __init ni5010_probe(struct net_device *dev)
@@ -397,7 +397,7 @@
 	
 	netif_start_queue(dev);
 		
-	if (NI5010_DEBUG) show_registers(dev); 
+	if (NI5010_DEBUG) ni5010_show_registers(dev); 
 
 	PRINTK((KERN_DEBUG "%s: open successful\n", dev->name));
      	return 0;
@@ -551,6 +551,7 @@
 		
 	skb->protocol = eth_type_trans(skb,dev);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
 	lp->stats.rx_bytes += lp->i_pkt_size;
 
@@ -625,7 +626,7 @@
 
 	PRINTK2((KERN_DEBUG "%s: entering ni5010_get_stats\n", dev->name));
 	
-	if (NI5010_DEBUG) show_registers(dev);
+	if (NI5010_DEBUG) ni5010_show_registers(dev);
 	
 	/* cli(); */
 	/* Update the statistics from the device registers. */
@@ -676,7 +677,7 @@
                 return;
         }
 
-	if (NI5010_DEBUG) show_registers(dev);
+	if (NI5010_DEBUG) ni5010_show_registers(dev);
 
 	if (inb(IE_ISTAT) & IS_EN_XMT) {
 		PRINTK((KERN_WARNING "%s: sending packet while already transmitting, not possible\n", 
@@ -709,7 +710,7 @@
 
 	netif_wake_queue(dev);
 	
-	if (NI5010_DEBUG) show_registers(dev);	
+	if (NI5010_DEBUG) ni5010_show_registers(dev);	
 }
 
 static void chipset_init(struct net_device *dev, int startp)
@@ -718,7 +719,7 @@
 	PRINTK3((KERN_DEBUG "%s: doing NOTHING in chipset_init\n", dev->name));
 }
 
-static void show_registers(struct net_device *dev)
+static void ni5010_show_registers(struct net_device *dev)
 {
 	int ioaddr = dev->base_addr;
 	
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ni5010.h linux/drivers/net/ni5010.h
--- v2.4.1/linux/drivers/net/ni5010.h	Sat Nov 29 10:33:19 1997
+++ linux/drivers/net/ni5010.h	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
  * Racal-Interlan ni5010 Ethernet definitions
  *
  * This is an extension to the Linux operating system, and is covered by the
- * same Gnu Public License that covers that work.
+ * same GNU General Public License that covers that work.
  *
  * copyrights (c) 1996 by Jan-Pascal van Best (jvbest@wi.leidenuniv.nl)
  *
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ni52.c linux/drivers/net/ni52.c
--- v2.4.1/linux/drivers/net/ni52.c	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/ni52.c	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
  * net-3-driver for the NI5210 card (i82586 Ethernet chip)
  *
  * This is an extension to the Linux operating system, and is covered by the
- * same Gnu Public License that covers that work.
+ * same GNU General Public License that covers that work.
  *
  * Alphacode 0.82 (96/09/29) for Linux 2.0.0 (or later)
  * Copyrights (c) 1994,1995,1996 by M.Hipp (hippm@informatik.uni-tuebingen.de)
@@ -111,7 +111,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -918,7 +918,9 @@
 						eth_copy_and_sum(skb,(char *) p->base+(unsigned long) rbd->buffer,totlen,0);
 						skb->protocol=eth_type_trans(skb,dev);
 						netif_rx(skb);
+						dev->last_rx = jiffies;
 						p->stats.rx_packets++;
+						p->stats.rx_bytes += totlen;
 					}
 					else
 						p->stats.rx_dropped++;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ni52.h linux/drivers/net/ni52.h
--- v2.4.1/linux/drivers/net/ni52.h	Tue Jun  8 10:27:18 1999
+++ linux/drivers/net/ni52.h	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
  * Intel i82586 Ethernet definitions
  *
  * This is an extension to the Linux operating system, and is covered by the
- * same Gnu Public License that covers that work.
+ * same GNU General Public License that covers that work.
  *
  * copyrights (c) 1994 by Michael Hipp (hippm@informatik.uni-tuebingen.de)
  *
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ni65.c linux/drivers/net/ni65.c
--- v2.4.1/linux/drivers/net/ni65.c	Tue May  2 12:40:59 2000
+++ linux/drivers/net/ni65.c	Tue Feb 13 13:15:05 2001
@@ -12,7 +12,7 @@
  * driver probes: io: 0x360,0x300,0x320,0x340 / dma: 3,5,6,7
  *
  * This is an extension to the Linux operating system, and is covered by the
- * same Gnu Public License that covers the Linux-kernel.
+ * same GNU General Public License that covers the Linux-kernel.
  *
  * comments/bugs/suggestions can be sent to:
  *   Michael Hipp
@@ -67,7 +67,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -1045,6 +1045,7 @@
 				p->stats.rx_bytes += len;
 				skb->protocol=eth_type_trans(skb,dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 			}
 			else
 			{
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ni65.h linux/drivers/net/ni65.h
--- v2.4.1/linux/drivers/net/ni65.h	Tue Oct  8 23:57:20 1996
+++ linux/drivers/net/ni65.h	Tue Feb 13 13:15:05 2001
@@ -1,7 +1,7 @@
 /* am7990 (lance) definitions
  * 
  * This is an extension to the Linux operating system, and is covered by
- * same Gnu Public License that covers that work.
+ * same GNU General Public License that covers that work.
  * 
  * Michael Hipp
  * email: mhipp@student.uni-tuebingen.de
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pci-skeleton.c linux/drivers/net/pci-skeleton.c
--- v2.4.1/linux/drivers/net/pci-skeleton.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/pci-skeleton.c	Tue Feb 13 13:15:05 2001
@@ -0,0 +1,2176 @@
+/*
+
+	drivers/net/pci-skeleton.c
+
+	Maintained by Jeff Garzik <jgarzik@mandrakesoft.com>
+
+	Original code came from 8139too.c, which in turns was based
+	originally on Donald Becker's rtl8139.c driver, versions 1.11
+	and older.  This driver was originally based on rtl8139.c
+	version 1.07.  Header of rtl8139.c version 1.11:
+
+	-----<snip>-----
+
+        	Written 1997-2000 by Donald Becker.
+		This software may be used and distributed according to the
+		terms of the GNU General Public License (GPL), incorporated
+		herein by reference.  Drivers based on or derived from this
+		code fall under the GPL and must retain the authorship,
+		copyright and license notice.  This file is not a complete
+		program and may only be used when the entire operating
+		system is licensed under the GPL.
+
+		This driver is for boards based on the RTL8129 and RTL8139
+		PCI ethernet chips.
+
+		The author may be reached as becker@scyld.com, or C/O Scyld
+		Computing Corporation 410 Severn Ave., Suite 210 Annapolis
+		MD 21403
+
+		Support and updates available at
+		http://www.scyld.com/network/rtl8139.html
+
+		Twister-tuning table provided by Kinston
+		<shangh@realtek.com.tw>.
+
+	-----<snip>-----
+
+	This software may be used and distributed according to the terms
+	of the GNU Public License, incorporated herein by reference.
+
+
+-----------------------------------------------------------------------------
+
+				Theory of Operation
+
+I. Board Compatibility
+
+This device driver is designed for the RealTek RTL8139 series, the RealTek
+Fast Ethernet controllers for PCI and CardBus.  This chip is used on many
+low-end boards, sometimes with its markings changed.
+
+
+II. Board-specific settings
+
+PCI bus devices are configured by the system at boot time, so no jumpers
+need to be set on the board.  The system BIOS will assign the
+PCI INTA signal to a (preferably otherwise unused) system IRQ line.
+
+III. Driver operation
+
+IIIa. Rx Ring buffers
+
+The receive unit uses a single linear ring buffer rather than the more
+common (and more efficient) descriptor-based architecture.  Incoming frames
+are sequentially stored into the Rx region, and the host copies them into
+skbuffs.
+
+Comment: While it is theoretically possible to process many frames in place,
+any delay in Rx processing would cause us to drop frames.  More importantly,
+the Linux protocol stack is not designed to operate in this manner.
+
+IIIb. Tx operation
+
+The RTL8139 uses a fixed set of four Tx descriptors in register space.
+In a stunningly bad design choice, Tx frames must be 32 bit aligned.  Linux
+aligns the IP header on word boundaries, and 14 byte ethernet header means
+that almost all frames will need to be copied to an alignment buffer.
+
+IVb. References
+
+http://www.realtek.com.tw/cn/cn.html
+http://www.scyld.com/expert/NWay.html
+
+IVc. Errata
+
+1) The RTL-8139 has a serious problem with motherboards which do
+posted MMIO writes to PCI space.  This driver works around the
+problem by having an MMIO  register write be immediately followed by
+an MMIO register read.
+
+2) The RTL-8129 is only supported in Donald Becker's rtl8139 driver.
+
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+#include <asm/io.h>
+
+
+#define NETDRV_VERSION		"1.0.0"
+#define MODNAME			"netdrv"
+#define NETDRV_DRIVER_LOAD_MSG	"MyVendor Fast Ethernet driver " NETDRV_VERSION " loaded"
+#define PFX			MODNAME ": "
+
+
+/* define to 1 to enable PIO instead of MMIO */
+#undef USE_IO_OPS
+
+/* define to 1 to enable copious debugging info */
+#undef NETDRV_DEBUG
+
+/* define to 1 to disable lightweight runtime debugging checks */
+#undef NETDRV_NDEBUG
+
+
+#ifdef NETDRV_DEBUG
+/* note: prints function name for you */
+#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#else
+#  define DPRINTK(fmt, args...)
+#endif
+
+#ifdef NETDRV_NDEBUG
+#  define assert(expr) do {} while (0)
+#else
+#  define assert(expr) \
+        if(!(expr)) {					\
+        printk( "Assertion failed! %s,%s,%s,line=%d\n",	\
+        #expr,__FILE__,__FUNCTION__,__LINE__);		\
+        }
+#endif
+
+
+/* A few user-configurable values. */
+/* media options */
+static int media[] = {-1, -1, -1, -1, -1, -1, -1, -1};
+
+/* Maximum events (Rx packets, etc.) to handle at each interrupt. */
+static int max_interrupt_work = 20;
+
+/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
+   The RTL chips use a 64 element hash table based on the Ethernet CRC.  */
+static int multicast_filter_limit = 32;
+
+/* Size of the in-memory receive ring. */
+#define RX_BUF_LEN_IDX	2	/* 0==8K, 1==16K, 2==32K, 3==64K */
+#define RX_BUF_LEN (8192 << RX_BUF_LEN_IDX)
+#define RX_BUF_PAD 16
+#define RX_BUF_WRAP_PAD 2048 /* spare padding to handle lack of packet wrap */
+#define RX_BUF_TOT_LEN (RX_BUF_LEN + RX_BUF_PAD + RX_BUF_WRAP_PAD)
+
+/* Number of Tx descriptor registers. */
+#define NUM_TX_DESC	4
+
+/* max supported ethernet frame size -- must be at least (dev->mtu+14+4).*/
+#define MAX_ETH_FRAME_SIZE	1536
+
+/* Size of the Tx bounce buffers -- must be at least (dev->mtu+14+4). */
+#define TX_BUF_SIZE	MAX_ETH_FRAME_SIZE
+#define TX_BUF_TOT_LEN	(TX_BUF_SIZE * NUM_TX_DESC)
+
+/* PCI Tuning Parameters
+   Threshold is bytes transferred to chip before transmission starts. */
+#define TX_FIFO_THRESH 256	/* In bytes, rounded down to 32 byte units. */
+
+/* The following settings are log_2(bytes)-4:  0 == 16 bytes .. 6==1024, 7==end of packet. */
+#define RX_FIFO_THRESH	6	/* Rx buffer level before first PCI xfer.  */
+#define RX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
+#define TX_DMA_BURST	6	/* Maximum PCI burst, '6' is 1024 */
+
+
+/* Operational parameters that usually are not changed. */
+/* Time in jiffies before concluding the transmitter is hung. */
+#define TX_TIMEOUT  (6*HZ)
+
+
+enum {
+	HAS_CHIP_XCVR = 0x020000,
+	HAS_LNK_CHNG = 0x040000,
+};
+
+#define NETDRV_MIN_IO_SIZE 0x80
+#define RTL8139B_IO_SIZE 256
+
+#define NETDRV_CAPS	HAS_CHIP_XCVR|HAS_LNK_CHNG
+
+typedef enum {
+	RTL8139 = 0,
+	NETDRV_CB,
+	SMC1211TX,
+	/*MPX5030,*/
+	DELTA8139,
+	ADDTRON8139,
+} board_t;
+
+
+/* indexed by board_t, above */
+static struct {
+	const char *name;
+} board_info[] __devinitdata = {
+	{ "RealTek RTL8139 Fast Ethernet" },
+	{ "RealTek RTL8139B PCI/CardBus" },
+	{ "SMC1211TX EZCard 10/100 (RealTek RTL8139)" },
+/*	{ MPX5030, "Accton MPX5030 (RealTek RTL8139)" },*/
+	{ "Delta Electronics 8139 10/100BaseTX" },
+	{ "Addtron Technolgy 8139 10/100BaseTX" },
+};
+
+
+static struct pci_device_id netdrv_pci_tbl[] __devinitdata = {
+	{0x10ec, 0x8139, PCI_ANY_ID, PCI_ANY_ID, 0, 0, RTL8139 },
+	{0x10ec, 0x8138, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NETDRV_CB },
+	{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SMC1211TX },
+/*	{0x1113, 0x1211, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MPX5030 },*/
+	{0x1500, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DELTA8139 },
+	{0x4033, 0x1360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ADDTRON8139 },
+	{0,}
+};
+MODULE_DEVICE_TABLE (pci, netdrv_pci_tbl);
+
+
+/* The rest of these values should never change. */
+
+/* Symbolic offsets to registers. */
+enum NETDRV_registers {
+	MAC0 = 0,		/* Ethernet hardware address. */
+	MAR0 = 8,		/* Multicast filter. */
+	TxStatus0 = 0x10,	/* Transmit status (Four 32bit registers). */
+	TxAddr0 = 0x20,		/* Tx descriptors (also four 32bit). */
+	RxBuf = 0x30,
+	RxEarlyCnt = 0x34,
+	RxEarlyStatus = 0x36,
+	ChipCmd = 0x37,
+	RxBufPtr = 0x38,
+	RxBufAddr = 0x3A,
+	IntrMask = 0x3C,
+	IntrStatus = 0x3E,
+	TxConfig = 0x40,
+	ChipVersion = 0x43,
+	RxConfig = 0x44,
+	Timer = 0x48,		/* A general-purpose counter. */
+	RxMissed = 0x4C,	/* 24 bits valid, write clears. */
+	Cfg9346 = 0x50,
+	Config0 = 0x51,
+	Config1 = 0x52,
+	FlashReg = 0x54,
+	MediaStatus = 0x58,
+	Config3 = 0x59,
+	Config4 = 0x5A,		/* absent on RTL-8139A */
+	HltClk = 0x5B,
+	MultiIntr = 0x5C,
+	TxSummary = 0x60,
+	BasicModeCtrl = 0x62,
+	BasicModeStatus = 0x64,
+	NWayAdvert = 0x66,
+	NWayLPAR = 0x68,
+	NWayExpansion = 0x6A,
+	/* Undocumented registers, but required for proper operation. */
+	FIFOTMS = 0x70,		/* FIFO Control and test. */
+	CSCR = 0x74,		/* Chip Status and Configuration Register. */
+	PARA78 = 0x78,
+	PARA7c = 0x7c,		/* Magic transceiver parameter register. */
+	Config5 = 0xD8,		/* absent on RTL-8139A */
+};
+
+enum ClearBitMasks {
+	MultiIntrClear = 0xF000,
+	ChipCmdClear = 0xE2,
+	Config1Clear = (1<<7)|(1<<6)|(1<<3)|(1<<2)|(1<<1),
+};
+
+enum ChipCmdBits {
+	CmdReset = 0x10,
+	CmdRxEnb = 0x08,
+	CmdTxEnb = 0x04,
+	RxBufEmpty = 0x01,
+};
+
+/* Interrupt register bits, using my own meaningful names. */
+enum IntrStatusBits {
+	PCIErr = 0x8000,
+	PCSTimeout = 0x4000,
+	RxFIFOOver = 0x40,
+	RxUnderrun = 0x20,
+	RxOverflow = 0x10,
+	TxErr = 0x08,
+	TxOK = 0x04,
+	RxErr = 0x02,
+	RxOK = 0x01,
+};
+enum TxStatusBits {
+	TxHostOwns = 0x2000,
+	TxUnderrun = 0x4000,
+	TxStatOK = 0x8000,
+	TxOutOfWindow = 0x20000000,
+	TxAborted = 0x40000000,
+	TxCarrierLost = 0x80000000,
+};
+enum RxStatusBits {
+	RxMulticast = 0x8000,
+	RxPhysical = 0x4000,
+	RxBroadcast = 0x2000,
+	RxBadSymbol = 0x0020,
+	RxRunt = 0x0010,
+	RxTooLong = 0x0008,
+	RxCRCErr = 0x0004,
+	RxBadAlign = 0x0002,
+	RxStatusOK = 0x0001,
+};
+
+/* Bits in RxConfig. */
+enum rx_mode_bits {
+	AcceptErr = 0x20,
+	AcceptRunt = 0x10,
+	AcceptBroadcast = 0x08,
+	AcceptMulticast = 0x04,
+	AcceptMyPhys = 0x02,
+	AcceptAllPhys = 0x01,
+};
+
+/* Bits in TxConfig. */
+enum tx_config_bits {
+	TxIFG1 = (1 << 25),	/* Interframe Gap Time */
+	TxIFG0 = (1 << 24),	/* Enabling these bits violates IEEE 802.3 */
+	TxLoopBack = (1 << 18) | (1 << 17), /* enable loopback test mode */
+	TxCRC = (1 << 16),	/* DISABLE appending CRC to end of Tx packets */
+	TxClearAbt = (1 << 0),	/* Clear abort (WO) */
+	TxDMAShift = 8,		/* DMA burst value (0-7) is shift this many bits */
+
+	TxVersionMask = 0x7C800000, /* mask out version bits 30-26, 23 */
+};
+
+/* Bits in Config1 */
+enum Config1Bits {
+	Cfg1_PM_Enable = 0x01,
+	Cfg1_VPD_Enable = 0x02,
+	Cfg1_PIO = 0x04,
+	Cfg1_MMIO = 0x08,
+	Cfg1_LWAKE = 0x10,
+	Cfg1_Driver_Load = 0x20,
+	Cfg1_LED0 = 0x40,
+	Cfg1_LED1 = 0x80,
+};
+
+enum RxConfigBits {
+	/* Early Rx threshold, none or X/16 */
+	RxCfgEarlyRxNone = 0,
+	RxCfgEarlyRxShift = 24,
+
+	/* rx fifo threshold */
+	RxCfgFIFOShift = 13,
+	RxCfgFIFONone = (7 << RxCfgFIFOShift),
+
+	/* Max DMA burst */
+	RxCfgDMAShift = 8,
+	RxCfgDMAUnlimited = (7 << RxCfgDMAShift),
+
+	/* rx ring buffer length */
+	RxCfgRcv8K = 0,
+	RxCfgRcv16K = (1 << 11),
+	RxCfgRcv32K = (1 << 12),
+	RxCfgRcv64K = (1 << 11) | (1 << 12),
+
+	/* Disable packet wrap at end of Rx buffer */
+	RxNoWrap = (1 << 7),
+};
+
+
+/* Twister tuning parameters from RealTek.
+   Completely undocumented, but required to tune bad links. */
+enum CSCRBits {
+	CSCR_LinkOKBit = 0x0400,
+	CSCR_LinkChangeBit = 0x0800,
+	CSCR_LinkStatusBits = 0x0f000,
+	CSCR_LinkDownOffCmd = 0x003c0,
+	CSCR_LinkDownCmd = 0x0f3c0,
+};
+
+
+enum Cfg9346Bits {
+	Cfg9346_Lock = 0x00,
+	Cfg9346_Unlock = 0xC0,
+};
+
+
+#define PARA78_default	0x78fa8388
+#define PARA7c_default	0xcb38de43	/* param[0][3] */
+#define PARA7c_xxx		0xcb38de43
+static const unsigned long param[4][4] = {
+	{0xcb39de43, 0xcb39ce43, 0xfb38de03, 0xcb38de43},
+	{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+	{0xcb39de43, 0xcb39ce43, 0xcb39ce83, 0xcb39ce83},
+	{0xbb39de43, 0xbb39ce43, 0xbb39ce83, 0xbb39ce83}
+};
+
+struct ring_info {
+	struct sk_buff *skb;
+	dma_addr_t mapping;
+};
+
+
+typedef enum {
+	CH_8139 = 0,
+	CH_8139_K,
+	CH_8139A,
+	CH_8139B,
+	CH_8130,
+	CH_8139C,
+} chip_t;
+
+
+/* directly indexed by chip_t, above */
+const static struct {
+	const char *name;
+	u8 version; /* from RTL8139C docs */
+	u32 RxConfigMask; /* should clear the bits supported by this chip */
+} rtl_chip_info[] = {
+	{ "RTL-8139",
+	  0x40,
+	  0xf0fe0040, /* XXX copied from RTL8139A, verify */
+	},
+
+	{ "RTL-8139 rev K",
+	  0x60,
+	  0xf0fe0040,
+	},
+
+	{ "RTL-8139A",
+	  0x70,
+	  0xf0fe0040,
+	},
+
+	{ "RTL-8139B",
+	  0x78,
+	  0xf0fc0040
+	},
+
+	{ "RTL-8130",
+	  0x7C,
+	  0xf0fe0040, /* XXX copied from RTL8139A, verify */
+	},
+
+	{ "RTL-8139C",
+	  0x74,
+	  0xf0fc0040, /* XXX copied from RTL8139B, verify */
+	},
+
+};
+
+
+struct netdrv_private {
+	board_t board;
+	void *mmio_addr;
+	int drv_flags;
+	struct pci_dev *pci_dev;
+	struct net_device_stats stats;
+	struct timer_list timer;	/* Media selection timer. */
+	unsigned char *rx_ring;
+	unsigned int cur_rx;	/* Index into the Rx buffer of next Rx pkt. */
+	unsigned int tx_flag;
+	atomic_t cur_tx;
+	atomic_t dirty_tx;
+	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
+	struct ring_info tx_info[NUM_TX_DESC];
+	unsigned char *tx_buf[NUM_TX_DESC];	/* Tx bounce buffers */
+	unsigned char *tx_bufs;	/* Tx bounce buffer region. */
+	dma_addr_t rx_ring_dma;
+	dma_addr_t tx_bufs_dma;
+	char phys[4];		/* MII device addresses. */
+	char twistie, twist_row, twist_col;	/* Twister tune state. */
+	unsigned int full_duplex:1;	/* Full-duplex operation requested. */
+	unsigned int duplex_lock:1;
+	unsigned int default_port:4;	/* Last dev->if_port value. */
+	unsigned int media2:4;	/* Secondary monitored media port. */
+	unsigned int medialock:1;	/* Don't sense media type. */
+	unsigned int mediasense:1;	/* Media sensing in progress. */
+	spinlock_t lock;
+	chip_t chipset;
+};
+
+MODULE_AUTHOR ("Jeff Garzik <jgarzik@mandrakesoft.com>");
+MODULE_DESCRIPTION ("RealTek RTL-8139 Fast Ethernet driver");
+MODULE_PARM (multicast_filter_limit, "i");
+MODULE_PARM (max_interrupt_work, "i");
+MODULE_PARM (debug, "i");
+MODULE_PARM (media, "1-" __MODULE_STRING(8) "i");
+
+static int read_eeprom (void *ioaddr, int location, int addr_len);
+static int netdrv_open (struct net_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 val);
+static void netdrv_timer (unsigned long data);
+static void netdrv_tx_timeout (struct net_device *dev);
+static void netdrv_init_ring (struct net_device *dev);
+static int netdrv_start_xmit (struct sk_buff *skb,
+			       struct net_device *dev);
+static void netdrv_interrupt (int irq, void *dev_instance,
+			       struct pt_regs *regs);
+static int netdrv_close (struct net_device *dev);
+static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd);
+static struct net_device_stats *netdrv_get_stats (struct net_device *dev);
+static inline u32 ether_crc (int length, unsigned char *data);
+static void netdrv_set_rx_mode (struct net_device *dev);
+static void netdrv_hw_start (struct net_device *dev);
+
+
+#ifdef USE_IO_OPS
+
+#define NETDRV_R8(reg)		inb (((unsigned long)ioaddr) + (reg))
+#define NETDRV_R16(reg)		inw (((unsigned long)ioaddr) + (reg))
+#define NETDRV_R32(reg)		((unsigned long) inl (((unsigned long)ioaddr) + (reg)))
+#define NETDRV_W8(reg, val8)	outb ((val8), ((unsigned long)ioaddr) + (reg))
+#define NETDRV_W16(reg, val16)	outw ((val16), ((unsigned long)ioaddr) + (reg))
+#define NETDRV_W32(reg, val32)	outl ((val32), ((unsigned long)ioaddr) + (reg))
+#define NETDRV_W8_F		NETDRV_W8
+#define NETDRV_W16_F		NETDRV_W16
+#define NETDRV_W32_F		NETDRV_W32
+#undef readb
+#undef readw
+#undef readl
+#undef writeb
+#undef writew
+#undef writel
+#define readb(addr) inb((unsigned long)(addr))
+#define readw(addr) inw((unsigned long)(addr))
+#define readl(addr) inl((unsigned long)(addr))
+#define writeb(val,addr) outb((val),(unsigned long)(addr))
+#define writew(val,addr) outw((val),(unsigned long)(addr))
+#define writel(val,addr) outl((val),(unsigned long)(addr))
+
+#else
+
+/* write MMIO register, with flush */
+/* Flush avoids rtl8139 bug w/ posted MMIO writes */
+#define NETDRV_W8_F(reg, val8)	do { writeb ((val8), ioaddr + (reg)); readb (ioaddr + (reg)); } while (0)
+#define NETDRV_W16_F(reg, val16)	do { writew ((val16), ioaddr + (reg)); readw (ioaddr + (reg)); } while (0)
+#define NETDRV_W32_F(reg, val32)	do { writel ((val32), ioaddr + (reg)); readl (ioaddr + (reg)); } while (0)
+
+
+#if MMIO_FLUSH_AUDIT_COMPLETE
+
+/* write MMIO register */
+#define NETDRV_W8(reg, val8)	writeb ((val8), ioaddr + (reg))
+#define NETDRV_W16(reg, val16)	writew ((val16), ioaddr + (reg))
+#define NETDRV_W32(reg, val32)	writel ((val32), ioaddr + (reg))
+
+#else
+
+/* write MMIO register, then flush */
+#define NETDRV_W8		NETDRV_W8_F
+#define NETDRV_W16		NETDRV_W16_F
+#define NETDRV_W32		NETDRV_W32_F
+
+#endif /* MMIO_FLUSH_AUDIT_COMPLETE */
+
+/* read MMIO register */
+#define NETDRV_R8(reg)		readb (ioaddr + (reg))
+#define NETDRV_R16(reg)		readw (ioaddr + (reg))
+#define NETDRV_R32(reg)		((unsigned long) readl (ioaddr + (reg)))
+
+#endif /* USE_IO_OPS */
+
+
+static const u16 netdrv_intr_mask =
+	PCIErr | PCSTimeout | RxUnderrun | RxOverflow | RxFIFOOver |
+	TxErr | TxOK | RxErr | RxOK;
+
+static const unsigned int netdrv_rx_config =
+	  RxCfgEarlyRxNone | RxCfgRcv32K | RxNoWrap |
+	  (RX_FIFO_THRESH << RxCfgFIFOShift) |
+	  (RX_DMA_BURST << RxCfgDMAShift);
+
+
+static int __devinit netdrv_init_board (struct pci_dev *pdev,
+					 struct net_device **dev_out,
+					 void **ioaddr_out)
+{
+	void *ioaddr = NULL;
+	struct net_device *dev;
+	struct netdrv_private *tp;
+	u8 tmp8;
+	int rc, i;
+	u32 pio_start, pio_end, pio_flags, pio_len;
+	unsigned long mmio_start, mmio_end, mmio_flags, mmio_len;
+	u32 tmp;
+
+	DPRINTK ("ENTER\n");
+
+	assert (pdev != NULL);
+	assert (ioaddr_out != NULL);
+
+	*ioaddr_out = NULL;
+	*dev_out = NULL;
+
+	/* dev zeroed in init_etherdev */
+	dev = init_etherdev (NULL, sizeof (*tp));
+	if (dev == NULL) {
+		printk (KERN_ERR PFX "unable to alloc new ethernet\n");
+		DPRINTK ("EXIT, returning -ENOMEM\n");
+		return -ENOMEM;
+	}
+	SET_MODULE_OWNER(dev);
+	tp = dev->priv;
+
+	pio_start = pci_resource_start (pdev, 0);
+	pio_end = pci_resource_end (pdev, 0);
+	pio_flags = pci_resource_flags (pdev, 0);
+	pio_len = pci_resource_len (pdev, 0);
+
+	mmio_start = pci_resource_start (pdev, 1);
+	mmio_end = pci_resource_end (pdev, 1);
+	mmio_flags = pci_resource_flags (pdev, 1);
+	mmio_len = pci_resource_len (pdev, 1);
+
+	/* set this immediately, we need to know before
+	 * we talk to the chip directly */
+	DPRINTK("PIO region size == 0x%02X\n", pio_len);
+	DPRINTK("MMIO region size == 0x%02lX\n", mmio_len);
+	if (pio_len == RTL8139B_IO_SIZE)
+		tp->chipset = CH_8139B;
+
+	/* make sure PCI base addr 0 is PIO */
+	if (!(pio_flags & IORESOURCE_IO)) {
+		printk (KERN_ERR PFX "region #0 not a PIO resource, aborting\n");
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	/* make sure PCI base addr 1 is MMIO */
+	if (!(mmio_flags & IORESOURCE_MEM)) {
+		printk (KERN_ERR PFX "region #1 not an MMIO resource, aborting\n");
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	/* check for weird/broken PCI region reporting */
+	if ((pio_len < NETDRV_MIN_IO_SIZE) ||
+	    (mmio_len < NETDRV_MIN_IO_SIZE)) {
+		printk (KERN_ERR PFX "Invalid PCI region size(s), aborting\n");
+		rc = -ENODEV;
+		goto err_out;
+	}
+
+	/* make sure our PIO region in PCI space is available */
+	if (!request_region (pio_start, pio_len, dev->name)) {
+		printk (KERN_ERR PFX "no I/O resource available, aborting\n");
+		rc = -EBUSY;
+		goto err_out;
+	}
+
+	/* make sure our MMIO region in PCI space is available */
+	if (!request_mem_region (mmio_start, mmio_len, dev->name)) {
+		printk (KERN_ERR PFX "no mem resource available, aborting\n");
+		rc = -EBUSY;
+		goto err_out_free_pio;
+	}
+
+	/* enable device (incl. PCI PM wakeup), and bus-mastering */
+	rc = pci_enable_device (pdev);
+	if (rc)
+		goto err_out_free_mmio;
+
+	pci_set_master (pdev);
+
+#ifdef USE_IO_OPS
+	ioaddr = (void *) pio_start;
+#else
+	/* ioremap MMIO region */
+	ioaddr = ioremap (mmio_start, mmio_len);
+	if (ioaddr == NULL) {
+		printk (KERN_ERR PFX "cannot remap MMIO, aborting\n");
+		rc = -EIO;
+		goto err_out_free_mmio;
+	}
+#endif /* USE_IO_OPS */
+
+	/* Soft reset the chip. */
+	NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) | CmdReset);
+
+	/* Check that the chip has finished the reset. */
+	for (i = 1000; i > 0; i--)
+		if ((NETDRV_R8 (ChipCmd) & CmdReset) == 0)
+			break;
+		else
+			udelay (10);
+
+	/* Bring the chip out of low-power mode. */
+	if (tp->chipset == CH_8139B) {
+		NETDRV_W8 (Config1, NETDRV_R8 (Config1) & ~(1<<4));
+		NETDRV_W8 (Config4, NETDRV_R8 (Config4) & ~(1<<2));
+	} else {
+		/* handle RTL8139A and RTL8139 cases */
+		/* XXX from becker driver. is this right?? */
+		NETDRV_W8 (Config1, 0);
+	}
+
+#ifndef USE_IO_OPS
+	/* sanity checks -- ensure PIO and MMIO registers agree */
+	assert (inb (pio_start+Config0) == readb (ioaddr+Config0));
+	assert (inb (pio_start+Config1) == readb (ioaddr+Config1));
+	assert (inb (pio_start+TxConfig) == readb (ioaddr+TxConfig));
+	assert (inb (pio_start+RxConfig) == readb (ioaddr+RxConfig));
+#endif /* !USE_IO_OPS */
+
+	/* make sure chip thinks PIO and MMIO are enabled */
+	tmp8 = NETDRV_R8 (Config1);
+	if ((tmp8 & Cfg1_PIO) == 0) {
+		printk (KERN_ERR PFX "PIO not enabled, Cfg1=%02X, aborting\n", tmp8);
+		rc = -EIO;
+		goto err_out_iounmap;
+	}
+	if ((tmp8 & Cfg1_MMIO) == 0) {
+		printk (KERN_ERR PFX "MMIO not enabled, Cfg1=%02X, aborting\n", tmp8);
+		rc = -EIO;
+		goto err_out_iounmap;
+	}
+
+	/* identify chip attached to board */
+	tmp = NETDRV_R8 (ChipVersion);
+	for (i = ARRAY_SIZE (rtl_chip_info) - 1; i >= 0; i--)
+		if (tmp == rtl_chip_info[i].version) {
+			tp->chipset = i;
+			goto match;
+		}
+
+	/* if unknown chip, assume array element #0, original RTL-8139 in this case */
+	printk (KERN_DEBUG PFX "PCI device %s: unknown chip version, assuming RTL-8139\n",
+		pdev->slot_name);
+	printk (KERN_DEBUG PFX "PCI device %s: TxConfig = 0x%lx\n", pdev->slot_name, NETDRV_R32 (TxConfig));
+	tp->chipset = 0;
+
+match:
+	DPRINTK ("chipset id (%d) == index %d, '%s'\n",
+		tmp,
+		tp->chipset,
+		rtl_chip_info[tp->chipset].name);
+
+	DPRINTK ("EXIT, returning 0\n");
+	*ioaddr_out = ioaddr;
+	*dev_out = dev;
+	return 0;
+
+err_out_iounmap:
+	assert (ioaddr > 0);
+#ifndef USE_IO_OPS
+	iounmap (ioaddr);
+#endif /* !USE_IO_OPS */
+err_out_free_mmio:
+	release_mem_region (mmio_start, mmio_len);
+err_out_free_pio:
+	release_region (pio_start, pio_len);
+err_out:
+	unregister_netdev (dev);
+	kfree (dev);
+	DPRINTK ("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+
+static int __devinit netdrv_init_one (struct pci_dev *pdev,
+				       const struct pci_device_id *ent)
+{
+	struct net_device *dev = NULL;
+	struct netdrv_private *tp;
+	int i, addr_len, option;
+	void *ioaddr = NULL;
+	static int board_idx = -1;
+	static int printed_version = 0;
+	u8 tmp;
+
+	DPRINTK ("ENTER\n");
+
+	assert (pdev != NULL);
+	assert (ent != NULL);
+
+	board_idx++;
+
+	if (!printed_version) {
+		printk (KERN_INFO NETDRV_DRIVER_LOAD_MSG "\n");
+		printed_version = 1;
+	}
+
+	i = netdrv_init_board (pdev, &dev, &ioaddr);
+	if (i < 0) {
+		DPRINTK ("EXIT, returning %d\n", i);
+		return i;
+	}
+
+	tp = dev->priv;
+
+	assert (ioaddr != NULL);
+	assert (dev != NULL);
+	assert (tp != NULL);
+
+	addr_len = read_eeprom (ioaddr, 0, 8) == 0x8129 ? 8 : 6;
+	for (i = 0; i < 3; i++)
+		((u16 *) (dev->dev_addr))[i] =
+		    le16_to_cpu (read_eeprom (ioaddr, i + 7, addr_len));
+
+	/* The Rtl8139-specific entries in the device structure. */
+	dev->open = netdrv_open;
+	dev->hard_start_xmit = netdrv_start_xmit;
+	dev->stop = netdrv_close;
+	dev->get_stats = netdrv_get_stats;
+	dev->set_multicast_list = netdrv_set_rx_mode;
+	dev->do_ioctl = mii_ioctl;
+	dev->tx_timeout = netdrv_tx_timeout;
+	dev->watchdog_timeo = TX_TIMEOUT;
+
+	dev->irq = pdev->irq;
+	dev->base_addr = (unsigned long) ioaddr;
+
+	/* dev->priv/tp zeroed and aligned in init_etherdev */
+	tp = dev->priv;
+
+	/* note: tp->chipset set in netdrv_init_board */
+	tp->drv_flags = PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+			PCI_COMMAND_MASTER | NETDRV_CAPS;
+	tp->pci_dev = pdev;
+	tp->board = ent->driver_data;
+	tp->mmio_addr = ioaddr;
+	tp->lock = SPIN_LOCK_UNLOCKED;
+
+	pdev->driver_data = dev;
+
+	tp->phys[0] = 32;
+
+	printk (KERN_INFO "%s: %s at 0x%lx, "
+		"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, "
+		"IRQ %d\n",
+		dev->name,
+		board_info[ent->driver_data].name,
+		dev->base_addr,
+		dev->dev_addr[0], dev->dev_addr[1],
+		dev->dev_addr[2], dev->dev_addr[3],
+		dev->dev_addr[4], dev->dev_addr[5],
+		dev->irq);
+
+	printk (KERN_DEBUG "%s:  Identified 8139 chip type '%s'\n",
+		dev->name, rtl_chip_info[tp->chipset].name);
+
+	/* Put the chip into low-power mode. */
+	NETDRV_W8_F (Cfg9346, Cfg9346_Unlock);
+
+	tmp = NETDRV_R8 (Config1) & Config1Clear;
+	tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
+	NETDRV_W8_F (Config1, tmp);
+
+	NETDRV_W8_F (HltClk, 'H');	/* 'R' would leave the clock running. */
+
+	/* The lower four bits are the media type. */
+	option = (board_idx > 7) ? 0 : media[board_idx];
+	if (option > 0) {
+		tp->full_duplex = (option & 0x200) ? 1 : 0;
+		tp->default_port = option & 15;
+		if (tp->default_port)
+			tp->medialock = 1;
+	}
+
+	if (tp->full_duplex) {
+		printk (KERN_INFO
+			"%s: Media type forced to Full Duplex.\n",
+			dev->name);
+		mdio_write (dev, tp->phys[0], 4, 0x141);
+		tp->duplex_lock = 1;
+	}
+
+	DPRINTK ("EXIT - returning 0\n");
+	return 0;
+}
+
+
+static void __devexit netdrv_remove_one (struct pci_dev *pdev)
+{
+	struct net_device *dev = pdev->driver_data;
+	struct netdrv_private *np;
+
+	DPRINTK ("ENTER\n");
+
+	assert (dev != NULL);
+
+	np = (struct netdrv_private *) (dev->priv);
+	assert (np != NULL);
+
+	unregister_netdev (dev);
+
+#ifndef USE_IO_OPS
+	iounmap (np->mmio_addr);
+#endif /* !USE_IO_OPS */
+
+	release_region (pci_resource_start (pdev, 0),
+			pci_resource_len (pdev, 0));
+	release_mem_region (pci_resource_start (pdev, 1),
+			    pci_resource_len (pdev, 1));
+
+#ifndef NETDRV_NDEBUG
+	/* poison memory before freeing */
+	memset (dev, 0xBC,
+		sizeof (struct net_device) +
+		sizeof (struct netdrv_private));
+#endif /* NETDRV_NDEBUG */
+
+	kfree (dev);
+
+	pdev->driver_data = NULL;
+
+	pci_power_off (pdev, -1);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+/* Serial EEPROM section. */
+
+/*  EEPROM_Ctrl bits. */
+#define EE_SHIFT_CLK	0x04	/* EEPROM shift clock. */
+#define EE_CS			0x08	/* EEPROM chip select. */
+#define EE_DATA_WRITE	0x02	/* EEPROM chip data in. */
+#define EE_WRITE_0		0x00
+#define EE_WRITE_1		0x02
+#define EE_DATA_READ	0x01	/* EEPROM chip data out. */
+#define EE_ENB			(0x80 | EE_CS)
+
+/* Delay between EEPROM clock transitions.
+   No extra delay is needed with 33Mhz PCI, but 66Mhz may change this.
+ */
+
+#define eeprom_delay()	readl(ee_addr)
+
+/* The EEPROM commands include the alway-set leading bit. */
+#define EE_WRITE_CMD	(5)
+#define EE_READ_CMD		(6)
+#define EE_ERASE_CMD	(7)
+
+static int __devinit read_eeprom (void *ioaddr, int location, int addr_len)
+{
+	int i;
+	unsigned retval = 0;
+	void *ee_addr = ioaddr + Cfg9346;
+	int read_cmd = location | (EE_READ_CMD << addr_len);
+
+	DPRINTK ("ENTER\n");
+
+	writeb (EE_ENB & ~EE_CS, ee_addr);
+	writeb (EE_ENB, ee_addr);
+	eeprom_delay ();
+
+	/* Shift the read command bits out. */
+	for (i = 4 + addr_len; i >= 0; i--) {
+		int dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0;
+		writeb (EE_ENB | dataval, ee_addr);
+		eeprom_delay ();
+		writeb (EE_ENB | dataval | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay ();
+	}
+	writeb (EE_ENB, ee_addr);
+	eeprom_delay ();
+
+	for (i = 16; i > 0; i--) {
+		writeb (EE_ENB | EE_SHIFT_CLK, ee_addr);
+		eeprom_delay ();
+		retval =
+		    (retval << 1) | ((readb (ee_addr) & EE_DATA_READ) ? 1 :
+				     0);
+		writeb (EE_ENB, ee_addr);
+		eeprom_delay ();
+	}
+
+	/* Terminate the EEPROM access. */
+	writeb (~EE_CS, ee_addr);
+	eeprom_delay ();
+
+	DPRINTK ("EXIT - returning %d\n", retval);
+	return retval;
+}
+
+/* MII serial management: mostly bogus for now. */
+/* Read and write the MII management registers using software-generated
+   serial MDIO protocol.
+   The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
+   met by back-to-back PCI I/O cycles, but we insert a delay to avoid
+   "overclocking" issues. */
+#define MDIO_DIR		0x80
+#define MDIO_DATA_OUT	0x04
+#define MDIO_DATA_IN	0x02
+#define MDIO_CLK		0x01
+#define MDIO_WRITE0 (MDIO_DIR)
+#define MDIO_WRITE1 (MDIO_DIR | MDIO_DATA_OUT)
+
+#define mdio_delay()	readb(mdio_addr)
+
+
+static char mii_2_8139_map[8] = {
+	BasicModeCtrl,
+	BasicModeStatus,
+	0,
+	0,
+	NWayAdvert,
+	NWayLPAR,
+	NWayExpansion,
+	0
+};
+
+
+/* Syncronize the MII management interface by shifting 32 one bits out. */
+static void mdio_sync (void *mdio_addr)
+{
+	int i;
+
+	DPRINTK ("ENTER\n");
+
+	for (i = 32; i >= 0; i--) {
+		writeb (MDIO_WRITE1, mdio_addr);
+		mdio_delay ();
+		writeb (MDIO_WRITE1 | MDIO_CLK, mdio_addr);
+		mdio_delay ();
+	}
+
+	DPRINTK ("EXIT\n");
+}
+
+
+static int mdio_read (struct net_device *dev, int phy_id, int location)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *mdio_addr = tp->mmio_addr + Config4;
+	int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
+	int retval = 0;
+	int i;
+
+	DPRINTK ("ENTER\n");
+
+	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
+		DPRINTK ("EXIT after directly using 8139 internal regs\n");
+		return location < 8 && mii_2_8139_map[location] ?
+		    readw (tp->mmio_addr + mii_2_8139_map[location]) : 0;
+	}
+	mdio_sync (mdio_addr);
+	/* Shift the read command bits out. */
+	for (i = 15; i >= 0; i--) {
+		int dataval = (mii_cmd & (1 << i)) ? MDIO_DATA_OUT : 0;
+
+		writeb (MDIO_DIR | dataval, mdio_addr);
+		mdio_delay ();
+		writeb (MDIO_DIR | dataval | MDIO_CLK, mdio_addr);
+		mdio_delay ();
+	}
+
+	/* Read the two transition, 16 data, and wire-idle bits. */
+	for (i = 19; i > 0; i--) {
+		writeb (0, mdio_addr);
+		mdio_delay ();
+		retval =
+		    (retval << 1) | ((readb (mdio_addr) & MDIO_DATA_IN) ? 1
+				     : 0);
+		writeb (MDIO_CLK, mdio_addr);
+		mdio_delay ();
+	}
+
+	DPRINTK ("EXIT, returning %d\n", (retval >> 1) & 0xffff);
+	return (retval >> 1) & 0xffff;
+}
+
+
+static void mdio_write (struct net_device *dev, int phy_id, int location,
+			int value)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *mdio_addr = tp->mmio_addr + Config4;
+	int mii_cmd =
+	    (0x5002 << 16) | (phy_id << 23) | (location << 18) | value;
+	int i;
+
+	DPRINTK ("ENTER\n");
+
+	if (phy_id > 31) {	/* Really a 8139.  Use internal registers. */
+		if (location < 8 && mii_2_8139_map[location]) {
+			writew (value,
+				tp->mmio_addr + mii_2_8139_map[location]);
+			readw (tp->mmio_addr + mii_2_8139_map[location]);
+		}
+		DPRINTK ("EXIT after directly using 8139 internal regs\n");
+		return;
+	}
+	mdio_sync (mdio_addr);
+
+	/* Shift the command bits out. */
+	for (i = 31; i >= 0; i--) {
+		int dataval =
+		    (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
+		writeb (dataval, mdio_addr);
+		mdio_delay ();
+		writeb (dataval | MDIO_CLK, mdio_addr);
+		mdio_delay ();
+	}
+
+	/* Clear out extra bits. */
+	for (i = 2; i > 0; i--) {
+		writeb (0, mdio_addr);
+		mdio_delay ();
+		writeb (MDIO_CLK, mdio_addr);
+		mdio_delay ();
+	}
+
+	DPRINTK ("EXIT\n");
+}
+
+
+static int netdrv_open (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	int retval;
+#ifdef NETDRV_DEBUG
+	void *ioaddr = tp->mmio_addr;
+#endif
+
+	DPRINTK ("ENTER\n");
+
+	retval = request_irq (dev->irq, netdrv_interrupt, SA_SHIRQ, dev->name, dev);
+	if (retval) {
+		DPRINTK ("EXIT, returning %d\n", retval);
+		return retval;
+	}
+
+	tp->tx_bufs = pci_alloc_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
+					   &tp->tx_bufs_dma);
+	tp->rx_ring = pci_alloc_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
+					   &tp->rx_ring_dma);
+	if (tp->tx_bufs == NULL || tp->rx_ring == NULL) {
+		free_irq(dev->irq, dev);
+
+		if (tp->tx_bufs)
+			pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
+					    tp->tx_bufs, tp->tx_bufs_dma);
+		if (tp->rx_ring)
+			pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
+					    tp->rx_ring, tp->rx_ring_dma);
+
+		DPRINTK ("EXIT, returning -ENOMEM\n");
+		return -ENOMEM;
+
+	}
+
+	tp->full_duplex = tp->duplex_lock;
+	tp->tx_flag = (TX_FIFO_THRESH << 11) & 0x003f0000;
+
+	netdrv_init_ring (dev);
+	netdrv_hw_start (dev);
+
+	DPRINTK ("%s: netdrv_open() ioaddr %#lx IRQ %d"
+			" GP Pins %2.2x %s-duplex.\n",
+			dev->name, pci_resource_start (tp->pci_dev, 1),
+			dev->irq, NETDRV_R8 (MediaStatus),
+			tp->full_duplex ? "full" : "half");
+
+	/* Set the timer to switch to check for link beat and perhaps switch
+	   to an alternate media type. */
+	init_timer (&tp->timer);
+	tp->timer.expires = jiffies + 3 * HZ;
+	tp->timer.data = (unsigned long) dev;
+	tp->timer.function = &netdrv_timer;
+	add_timer (&tp->timer);
+
+	DPRINTK ("EXIT, returning 0\n");
+	return 0;
+}
+
+
+/* Start the hardware at open or resume. */
+static void netdrv_hw_start (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	u32 i;
+	u8 tmp;
+
+	DPRINTK ("ENTER\n");
+
+	/* Soft reset the chip. */
+	NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) | CmdReset);
+	udelay (100);
+
+	/* Check that the chip has finished the reset. */
+	for (i = 1000; i > 0; i--)
+		if ((NETDRV_R8 (ChipCmd) & CmdReset) == 0)
+			break;
+
+	/* Restore our idea of the MAC address. */
+	NETDRV_W32_F (MAC0 + 0, cpu_to_le32 (*(u32 *) (dev->dev_addr + 0)));
+	NETDRV_W32_F (MAC0 + 4, cpu_to_le32 (*(u32 *) (dev->dev_addr + 4)));
+
+	/* Must enable Tx/Rx before setting transfer thresholds! */
+	NETDRV_W8_F (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) |
+			   CmdRxEnb | CmdTxEnb);
+
+	i = netdrv_rx_config |
+	    (NETDRV_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
+	NETDRV_W32_F (RxConfig, i);
+
+	/* Check this value: the documentation for IFG contradicts ifself. */
+	NETDRV_W32 (TxConfig, (TX_DMA_BURST << TxDMAShift));
+
+	/* unlock Config[01234] and BMCR register writes */
+	NETDRV_W8_F (Cfg9346, Cfg9346_Unlock);
+	udelay (10);
+
+	tp->cur_rx = 0;
+
+	if (tp->chipset >= CH_8139A) {
+		tmp = NETDRV_R8 (Config1) & Config1Clear;
+		tmp |= Cfg1_Driver_Load;
+		tmp |= (tp->chipset == CH_8139B) ? 3 : 1; /* Enable PM/VPD */
+		NETDRV_W8_F (Config1, tmp);
+	} else {
+		u8 foo = NETDRV_R8 (Config1) & Config1Clear;
+		NETDRV_W8 (Config1, tp->full_duplex ? (foo|0x60) : (foo|0x20));
+	}
+
+	if (tp->chipset >= CH_8139B) {
+		tmp = NETDRV_R8 (Config4) & ~(1<<2);
+		/* chip will clear Rx FIFO overflow automatically */
+		tmp |= (1<<7);
+		NETDRV_W8 (Config4, tmp);
+
+		/* disable magic packet scanning, which is enabled
+		 * when PM is enabled above (Config1) */
+		NETDRV_W8 (Config3, NETDRV_R8 (Config3) & ~(1<<5));
+	}
+
+	/* Lock Config[01234] and BMCR register writes */
+	NETDRV_W8_F (Cfg9346, Cfg9346_Lock);
+	udelay (10);
+
+	/* init Rx ring buffer DMA address */
+	NETDRV_W32_F (RxBuf, tp->rx_ring_dma);
+
+	/* init Tx buffer DMA addresses */
+	for (i = 0; i < NUM_TX_DESC; i++)
+		NETDRV_W32_F (TxAddr0 + (i * 4), tp->tx_bufs_dma + (tp->tx_buf[i] - tp->tx_bufs));
+
+	NETDRV_W32_F (RxMissed, 0);
+
+	netdrv_set_rx_mode (dev);
+
+	/* no early-rx interrupts */
+	NETDRV_W16 (MultiIntr, NETDRV_R16 (MultiIntr) & MultiIntrClear);
+
+	/* make sure RxTx has started */
+	NETDRV_W8_F (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear) |
+			   CmdRxEnb | CmdTxEnb);
+
+	/* Enable all known interrupts by setting the interrupt mask. */
+	NETDRV_W16_F (IntrMask, netdrv_intr_mask);
+
+	netif_start_queue (dev);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+/* Initialize the Rx and Tx rings, along with various 'dev' bits. */
+static void netdrv_init_ring (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	int i;
+
+	DPRINTK ("ENTER\n");
+
+	tp->cur_rx = 0;
+	atomic_set (&tp->cur_tx, 0);
+	atomic_set (&tp->dirty_tx, 0);
+
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		tp->tx_info[i].skb = NULL;
+		tp->tx_info[i].mapping = 0;
+		tp->tx_buf[i] = &tp->tx_bufs[i * TX_BUF_SIZE];
+	}
+
+	DPRINTK ("EXIT\n");
+}
+
+
+#ifndef NETDRV_TUNE_TWISTER
+static inline void netdrv_tune_twister (struct net_device *dev,
+				  struct netdrv_private *tp) {}
+#else
+static void netdrv_tune_twister (struct net_device *dev,
+				  struct netdrv_private *tp)
+{
+	int linkcase;
+
+	DPRINTK ("ENTER\n");
+
+	/* This is a complicated state machine to configure the "twister" for
+	   impedance/echos based on the cable length.
+	   All of this is magic and undocumented.
+	 */
+	switch (tp->twistie) {
+	case 1:
+		if (NETDRV_R16 (CSCR) & CSCR_LinkOKBit) {
+			/* We have link beat, let us tune the twister. */
+			NETDRV_W16 (CSCR, CSCR_LinkDownOffCmd);
+			tp->twistie = 2;	/* Change to state 2. */
+			next_tick = HZ / 10;
+		} else {
+			/* Just put in some reasonable defaults for when beat returns. */
+			NETDRV_W16 (CSCR, CSCR_LinkDownCmd);
+			NETDRV_W32 (FIFOTMS, 0x20);	/* Turn on cable test mode. */
+			NETDRV_W32 (PARA78, PARA78_default);
+			NETDRV_W32 (PARA7c, PARA7c_default);
+			tp->twistie = 0;	/* Bail from future actions. */
+		}
+		break;
+	case 2:
+		/* Read how long it took to hear the echo. */
+		linkcase = NETDRV_R16 (CSCR) & CSCR_LinkStatusBits;
+		if (linkcase == 0x7000)
+			tp->twist_row = 3;
+		else if (linkcase == 0x3000)
+			tp->twist_row = 2;
+		else if (linkcase == 0x1000)
+			tp->twist_row = 1;
+		else
+			tp->twist_row = 0;
+		tp->twist_col = 0;
+		tp->twistie = 3;	/* Change to state 2. */
+		next_tick = HZ / 10;
+		break;
+	case 3:
+		/* Put out four tuning parameters, one per 100msec. */
+		if (tp->twist_col == 0)
+			NETDRV_W16 (FIFOTMS, 0);
+		NETDRV_W32 (PARA7c, param[(int) tp->twist_row]
+			 [(int) tp->twist_col]);
+		next_tick = HZ / 10;
+		if (++tp->twist_col >= 4) {
+			/* For short cables we are done.
+			   For long cables (row == 3) check for mistune. */
+			tp->twistie =
+			    (tp->twist_row == 3) ? 4 : 0;
+		}
+		break;
+	case 4:
+		/* Special case for long cables: check for mistune. */
+		if ((NETDRV_R16 (CSCR) &
+		     CSCR_LinkStatusBits) == 0x7000) {
+			tp->twistie = 0;
+			break;
+		} else {
+			NETDRV_W32 (PARA7c, 0xfb38de03);
+			tp->twistie = 5;
+			next_tick = HZ / 10;
+		}
+		break;
+	case 5:
+		/* Retune for shorter cable (column 2). */
+		NETDRV_W32 (FIFOTMS, 0x20);
+		NETDRV_W32 (PARA78, PARA78_default);
+		NETDRV_W32 (PARA7c, PARA7c_default);
+		NETDRV_W32 (FIFOTMS, 0x00);
+		tp->twist_row = 2;
+		tp->twist_col = 0;
+		tp->twistie = 3;
+		next_tick = HZ / 10;
+		break;
+
+	default:
+		/* do nothing */
+		break;
+	}
+
+	DPRINTK ("EXIT\n");
+}
+#endif /* NETDRV_TUNE_TWISTER */
+
+
+static void netdrv_timer (unsigned long data)
+{
+	struct net_device *dev = (struct net_device *) data;
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	int next_tick = 60 * HZ;
+	int mii_reg5;
+
+	mii_reg5 = mdio_read (dev, tp->phys[0], 5);
+
+	if (!tp->duplex_lock && mii_reg5 != 0xffff) {
+		int duplex = (mii_reg5 & 0x0100)
+		    || (mii_reg5 & 0x01C0) == 0x0040;
+		if (tp->full_duplex != duplex) {
+			tp->full_duplex = duplex;
+			printk (KERN_INFO
+				"%s: Setting %s-duplex based on MII #%d link"
+				" partner ability of %4.4x.\n", dev->name,
+				tp->full_duplex ? "full" : "half",
+				tp->phys[0], mii_reg5);
+			NETDRV_W8 (Cfg9346, Cfg9346_Unlock);
+			NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			NETDRV_W8 (Cfg9346, Cfg9346_Lock);
+		}
+	}
+
+	netdrv_tune_twister (dev, tp);
+
+	DPRINTK ("%s: Media selection tick, Link partner %4.4x.\n",
+		 dev->name, NETDRV_R16 (NWayLPAR));
+	DPRINTK ("%s:  Other registers are IntMask %4.4x IntStatus %4.4x"
+		 " RxStatus %4.4x.\n", dev->name,
+		 NETDRV_R16 (IntrMask),
+		 NETDRV_R16 (IntrStatus),
+		 NETDRV_R32 (RxEarlyStatus));
+	DPRINTK ("%s:  Chip config %2.2x %2.2x.\n",
+		 dev->name, NETDRV_R8 (Config0),
+		 NETDRV_R8 (Config1));
+
+	tp->timer.expires = jiffies + next_tick;
+	add_timer (&tp->timer);
+}
+
+
+static void netdrv_tx_clear (struct netdrv_private *tp)
+{
+	int i;
+
+	atomic_set (&tp->cur_tx, 0);
+	atomic_set (&tp->dirty_tx, 0);
+
+	/* Dump the unsent Tx packets. */
+	for (i = 0; i < NUM_TX_DESC; i++) {
+		struct ring_info *rp = &tp->tx_info[i];
+		if (rp->mapping != 0) {
+			pci_unmap_single (tp->pci_dev, rp->mapping,
+					  rp->skb->len, PCI_DMA_TODEVICE);
+			rp->mapping = 0;
+		}
+		if (rp->skb) {
+			dev_kfree_skb (rp->skb);
+			rp->skb = NULL;
+			tp->stats.tx_dropped++;
+		}
+	}
+}
+
+
+static void netdrv_tx_timeout (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	int i;
+	u8 tmp8;
+	unsigned long flags;
+
+	DPRINTK ("%s: Transmit timeout, status %2.2x %4.4x "
+		 "media %2.2x.\n", dev->name,
+		 NETDRV_R8 (ChipCmd),
+		 NETDRV_R16 (IntrStatus),
+		 NETDRV_R8 (MediaStatus));
+
+	/* disable Tx ASAP, if not already */
+	tmp8 = NETDRV_R8 (ChipCmd);
+	if (tmp8 & CmdTxEnb)
+		NETDRV_W8 (ChipCmd, tmp8 & ~CmdTxEnb);
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	NETDRV_W16 (IntrMask, 0x0000);
+
+	/* Emit info to figure out what went wrong. */
+	printk (KERN_DEBUG "%s: Tx queue start entry %d  dirty entry %d.\n",
+		dev->name, atomic_read (&tp->cur_tx),
+		atomic_read (&tp->dirty_tx));
+	for (i = 0; i < NUM_TX_DESC; i++)
+		printk (KERN_DEBUG "%s:  Tx descriptor %d is %8.8lx.%s\n",
+			dev->name, i, NETDRV_R32 (TxStatus0 + (i * 4)),
+			i == atomic_read (&tp->dirty_tx) % NUM_TX_DESC ?
+				" (queue head)" : "");
+
+	/* Stop a shared interrupt from scavenging while we are. */
+	spin_lock_irqsave (&tp->lock, flags);
+	
+	netdrv_tx_clear (tp);
+
+	spin_unlock_irqrestore (&tp->lock, flags);
+
+	/* ...and finally, reset everything */
+	netdrv_hw_start (dev);
+
+	netif_wake_queue (dev);
+}
+
+
+
+static int netdrv_start_xmit (struct sk_buff *skb, struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	int entry;
+
+	/* Calculate the next Tx descriptor entry. */
+	entry = atomic_read (&tp->cur_tx) % NUM_TX_DESC;
+
+	assert (tp->tx_info[entry].skb == NULL);
+	assert (tp->tx_info[entry].mapping == 0);
+
+	tp->tx_info[entry].skb = skb;
+	/* tp->tx_info[entry].mapping = 0; */
+	memcpy (tp->tx_buf[entry], skb->data, skb->len);
+
+	/* Note: the chip doesn't have auto-pad! */
+	NETDRV_W32 (TxStatus0 + (entry * sizeof(u32)),
+		 tp->tx_flag | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN));
+
+	dev->trans_start = jiffies;
+	atomic_inc (&tp->cur_tx);
+	if ((atomic_read (&tp->cur_tx) - atomic_read (&tp->dirty_tx)) >= NUM_TX_DESC)
+		netif_stop_queue (dev);
+
+	DPRINTK ("%s: Queued Tx packet at %p size %u to slot %d.\n",
+		 dev->name, skb->data, skb->len, entry);
+
+	return 0;
+}
+
+
+static void netdrv_tx_interrupt (struct net_device *dev,
+				  struct netdrv_private *tp,
+				  void *ioaddr)
+{
+	int cur_tx, dirty_tx, tx_left;
+
+	assert (dev != NULL);
+	assert (tp != NULL);
+	assert (ioaddr != NULL);
+
+	dirty_tx = atomic_read (&tp->dirty_tx);
+
+	cur_tx = atomic_read (&tp->cur_tx);
+	tx_left = cur_tx - dirty_tx;
+	while (tx_left > 0) {
+		int entry = dirty_tx % NUM_TX_DESC;
+		int txstatus;
+
+		txstatus = NETDRV_R32 (TxStatus0 + (entry * sizeof (u32)));
+
+		if (!(txstatus & (TxStatOK | TxUnderrun | TxAborted)))
+			break;	/* It still hasn't been Txed */
+
+		/* Note: TxCarrierLost is always asserted at 100mbps. */
+		if (txstatus & (TxOutOfWindow | TxAborted)) {
+			/* There was an major error, log it. */
+			DPRINTK ("%s: Transmit error, Tx status %8.8x.\n",
+				 dev->name, txstatus);
+			tp->stats.tx_errors++;
+			if (txstatus & TxAborted) {
+				tp->stats.tx_aborted_errors++;
+				NETDRV_W32 (TxConfig, TxClearAbt | (TX_DMA_BURST << TxDMAShift));
+			}
+			if (txstatus & TxCarrierLost)
+				tp->stats.tx_carrier_errors++;
+			if (txstatus & TxOutOfWindow)
+				tp->stats.tx_window_errors++;
+#ifdef ETHER_STATS
+			if ((txstatus & 0x0f000000) == 0x0f000000)
+				tp->stats.collisions16++;
+#endif
+		} else {
+			if (txstatus & TxUnderrun) {
+				/* Add 64 to the Tx FIFO threshold. */
+				if (tp->tx_flag < 0x00300000)
+					tp->tx_flag += 0x00020000;
+				tp->stats.tx_fifo_errors++;
+			}
+			tp->stats.collisions += (txstatus >> 24) & 15;
+			tp->stats.tx_bytes += txstatus & 0x7ff;
+			tp->stats.tx_packets++;
+		}
+
+		/* Free the original skb. */
+		if (tp->tx_info[entry].mapping != 0) {
+			pci_unmap_single(tp->pci_dev,
+					 tp->tx_info[entry].mapping,
+					 tp->tx_info[entry].skb->len,
+					 PCI_DMA_TODEVICE);
+			tp->tx_info[entry].mapping = 0;
+		}
+		dev_kfree_skb_irq (tp->tx_info[entry].skb);
+		tp->tx_info[entry].skb = NULL;
+		dirty_tx++;
+		if (dirty_tx < 0) { /* handle signed int overflow */
+			atomic_sub (cur_tx, &tp->cur_tx); /* XXX racy? */
+			dirty_tx = cur_tx - tx_left + 1;
+		}
+		if (netif_queue_stopped (dev))
+			netif_wake_queue (dev);
+
+		cur_tx = atomic_read (&tp->cur_tx);
+		tx_left = cur_tx - dirty_tx;
+
+	}
+
+#ifndef NETDRV_NDEBUG
+	if (atomic_read (&tp->cur_tx) - dirty_tx > NUM_TX_DESC) {
+		printk (KERN_ERR
+		  "%s: Out-of-sync dirty pointer, %d vs. %d.\n",
+		     dev->name, dirty_tx, atomic_read (&tp->cur_tx));
+		dirty_tx += NUM_TX_DESC;
+	}
+#endif /* NETDRV_NDEBUG */
+
+	atomic_set (&tp->dirty_tx, dirty_tx);
+}
+
+
+/* TODO: clean this up!  Rx reset need not be this intensive */
+static void netdrv_rx_err (u32 rx_status, struct net_device *dev,
+			    struct netdrv_private *tp, void *ioaddr)
+{
+	u8 tmp8;
+	int tmp_work = 1000;
+
+	DPRINTK ("%s: Ethernet frame had errors, status %8.8x.\n",
+	         dev->name, rx_status);
+	if (rx_status & RxTooLong) {
+		DPRINTK ("%s: Oversized Ethernet frame, status %4.4x!\n",
+			 dev->name, rx_status);
+		/* A.C.: The chip hangs here. */
+	}
+	tp->stats.rx_errors++;
+	if (rx_status & (RxBadSymbol | RxBadAlign))
+		tp->stats.rx_frame_errors++;
+	if (rx_status & (RxRunt | RxTooLong))
+		tp->stats.rx_length_errors++;
+	if (rx_status & RxCRCErr)
+		tp->stats.rx_crc_errors++;
+	/* Reset the receiver, based on RealTek recommendation. (Bug?) */
+	tp->cur_rx = 0;
+
+	/* disable receive */
+	tmp8 = NETDRV_R8 (ChipCmd) & ChipCmdClear;
+	NETDRV_W8_F (ChipCmd, tmp8 | CmdTxEnb);
+
+	/* A.C.: Reset the multicast list. */
+	netdrv_set_rx_mode (dev);
+
+	/* XXX potentially temporary hack to
+	 * restart hung receiver */
+	while (--tmp_work > 0) {
+		tmp8 = NETDRV_R8 (ChipCmd);
+		if ((tmp8 & CmdRxEnb) && (tmp8 & CmdTxEnb))
+			break;
+		NETDRV_W8_F (ChipCmd,
+			  (tmp8 & ChipCmdClear) | CmdRxEnb | CmdTxEnb);
+	}
+
+	/* G.S.: Re-enable receiver */
+	/* XXX temporary hack to work around receiver hang */
+	netdrv_set_rx_mode (dev);
+
+	if (tmp_work <= 0)
+		printk (KERN_WARNING PFX "tx/rx enable wait too long\n");
+}
+
+
+/* The data sheet doesn't describe the Rx ring at all, so I'm guessing at the
+   field alignments and semantics. */
+static void netdrv_rx_interrupt (struct net_device *dev,
+				  struct netdrv_private *tp, void *ioaddr)
+{
+	unsigned char *rx_ring;
+	u16 cur_rx;
+
+	assert (dev != NULL);
+	assert (tp != NULL);
+	assert (ioaddr != NULL);
+
+	rx_ring = tp->rx_ring;
+	cur_rx = tp->cur_rx;
+
+	DPRINTK ("%s: In netdrv_rx(), current %4.4x BufAddr %4.4x,"
+		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+		 NETDRV_R16 (RxBufAddr),
+		 NETDRV_R16 (RxBufPtr), NETDRV_R8 (ChipCmd));
+
+	while ((NETDRV_R8 (ChipCmd) & RxBufEmpty) == 0) {
+		int ring_offset = cur_rx % RX_BUF_LEN;
+		u32 rx_status;
+		unsigned int rx_size;
+		unsigned int pkt_size;
+		struct sk_buff *skb;
+
+		/* read size+status of next frame from DMA ring buffer */
+		rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset));
+		rx_size = rx_status >> 16;
+		pkt_size = rx_size - 4;
+
+		DPRINTK ("%s:  netdrv_rx() status %4.4x, size %4.4x,"
+			 " cur %4.4x.\n", dev->name, rx_status,
+			 rx_size, cur_rx);
+#if NETDRV_DEBUG > 2
+		{
+			int i;
+			DPRINTK ("%s: Frame contents ", dev->name);
+			for (i = 0; i < 70; i++)
+				printk (" %2.2x",
+					rx_ring[ring_offset + i]);
+			printk (".\n");
+		}
+#endif
+
+		/* E. Gill */
+		/* Note from BSD driver:
+		 * Here's a totally undocumented fact for you. When the
+		 * RealTek chip is in the process of copying a packet into
+		 * RAM for you, the length will be 0xfff0. If you spot a
+		 * packet header with this value, you need to stop. The
+		 * datasheet makes absolutely no mention of this and
+		 * RealTek should be shot for this.
+		 */
+		if (rx_size == 0xfff0)
+			break;
+
+		/* If Rx err or invalid rx_size/rx_status received
+		 * (which happens if we get lost in the ring),
+		 * Rx process gets reset, so we abort any further
+		 * Rx processing.
+		 */
+		if ((rx_size > (MAX_ETH_FRAME_SIZE+4)) ||
+		    (!(rx_status & RxStatusOK))) {
+			netdrv_rx_err (rx_status, dev, tp, ioaddr);
+			return;
+		}
+
+		/* Malloc up new buffer, compatible with net-2e. */
+		/* Omit the four octet CRC from the length. */
+
+		/* TODO: consider allocating skb's outside of
+		 * interrupt context, both to speed interrupt processing,
+		 * and also to reduce the chances of having to
+		 * drop packets here under memory pressure.
+		 */
+
+		skb = dev_alloc_skb (pkt_size + 2);
+		if (skb) {
+			skb->dev = dev;
+			skb_reserve (skb, 2);	/* 16 byte align the IP fields. */
+
+			eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0);
+			skb_put (skb, pkt_size);
+
+			skb->protocol = eth_type_trans (skb, dev);
+			netif_rx (skb);
+			dev->last_rx = jiffies;
+			tp->stats.rx_bytes += pkt_size;
+			tp->stats.rx_packets++;
+		} else {
+			printk (KERN_WARNING
+				"%s: Memory squeeze, dropping packet.\n",
+				dev->name);
+			tp->stats.rx_dropped++;
+		}
+
+		cur_rx = (cur_rx + rx_size + 4 + 3) & ~3;
+		NETDRV_W16_F (RxBufPtr, cur_rx - 16);
+	}
+
+	DPRINTK ("%s: Done netdrv_rx(), current %4.4x BufAddr %4.4x,"
+		 " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx,
+		 NETDRV_R16 (RxBufAddr),
+		 NETDRV_R16 (RxBufPtr), NETDRV_R8 (ChipCmd));
+
+	tp->cur_rx = cur_rx;
+}
+
+
+static void netdrv_weird_interrupt (struct net_device *dev,
+				     struct netdrv_private *tp,
+				     void *ioaddr,
+				     int status, int link_changed)
+{
+	printk (KERN_DEBUG "%s: Abnormal interrupt, status %8.8x.\n",
+		dev->name, status);
+
+	assert (dev != NULL);
+	assert (tp != NULL);
+	assert (ioaddr != NULL);
+
+	/* Update the error count. */
+	tp->stats.rx_missed_errors += NETDRV_R32 (RxMissed);
+	NETDRV_W32 (RxMissed, 0);
+
+	if ((status & RxUnderrun) && link_changed &&
+	    (tp->drv_flags & HAS_LNK_CHNG)) {
+		/* Really link-change on new chips. */
+		int lpar = NETDRV_R16 (NWayLPAR);
+		int duplex = (lpar & 0x0100) || (lpar & 0x01C0) == 0x0040
+				|| tp->duplex_lock;
+		if (tp->full_duplex != duplex) {
+			tp->full_duplex = duplex;
+			NETDRV_W8 (Cfg9346, Cfg9346_Unlock);
+			NETDRV_W8 (Config1, tp->full_duplex ? 0x60 : 0x20);
+			NETDRV_W8 (Cfg9346, Cfg9346_Lock);
+		}
+		status &= ~RxUnderrun;
+	}
+
+	/* XXX along with netdrv_rx_err, are we double-counting errors? */
+	if (status &
+	    (RxUnderrun | RxOverflow | RxErr | RxFIFOOver))
+		tp->stats.rx_errors++;
+
+	if (status & (PCSTimeout))
+		tp->stats.rx_length_errors++;
+	if (status & (RxUnderrun | RxFIFOOver))
+		tp->stats.rx_fifo_errors++;
+	if (status & RxOverflow) {
+		tp->stats.rx_over_errors++;
+		tp->cur_rx = NETDRV_R16 (RxBufAddr) % RX_BUF_LEN;
+		NETDRV_W16_F (RxBufPtr, tp->cur_rx - 16);
+	}
+	if (status & PCIErr) {
+		u16 pci_cmd_status;
+		pci_read_config_word (tp->pci_dev, PCI_STATUS, &pci_cmd_status);
+
+		printk (KERN_ERR "%s: PCI Bus error %4.4x.\n",
+			dev->name, pci_cmd_status);
+	}
+}
+
+
+/* The interrupt handler does all of the Rx thread work and cleans up
+   after the Tx thread. */
+static void netdrv_interrupt (int irq, void *dev_instance,
+			       struct pt_regs *regs)
+{
+	struct net_device *dev = (struct net_device *) dev_instance;
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	int boguscnt = max_interrupt_work;
+	void *ioaddr = tp->mmio_addr;
+	int status = 0, link_changed = 0; /* avoid bogus "uninit" warning */
+
+	spin_lock (&tp->lock);
+
+	do {
+		status = NETDRV_R16 (IntrStatus);
+
+		/* h/w no longer present (hotplug?) or major error, bail */
+		if (status == 0xFFFF)
+			break;
+
+		/* Acknowledge all of the current interrupt sources ASAP, but
+		   an first get an additional status bit from CSCR. */
+		if (status & RxUnderrun)
+			link_changed = NETDRV_R16 (CSCR) & CSCR_LinkChangeBit;
+
+		/* E. Gill */
+		/* In case of an RxFIFOOver we must also clear the RxOverflow
+		   bit to avoid dropping frames for ever. Believe me, I got a
+		   lot of troubles copying huge data (approximately 2 RxFIFOOver
+		   errors per 1GB data transfer).
+		   The following is written in the 'p-guide.pdf' file (RTL8139(A/B)
+		   Programming guide V0.1, from 1999/1/15) on page 9 from REALTEC.
+		   -----------------------------------------------------------
+		   2. RxFIFOOvw handling:
+		     When RxFIFOOvw occurs, all incoming packets are discarded.
+		     Clear ISR(RxFIFOOvw) doesn't dismiss RxFIFOOvw event. To
+		     dismiss RxFIFOOvw event, the ISR(RxBufOvw) must be written
+		     with a '1'.
+		   -----------------------------------------------------------
+		   Unfortunately I was not able to find any reason for the
+		   RxFIFOOver error (I got the feeling this depends on the
+		   CPU speed, lower CPU speed --> more errors).
+		   After clearing the RxOverflow bit the transfer of the
+		   packet was repeated and all data are error free transfered */
+		NETDRV_W16_F (IntrStatus, (status & RxFIFOOver) ? (status | RxOverflow) : status);
+
+		DPRINTK ("%s: interrupt  status=%#4.4x new intstat=%#4.4x.\n",
+				dev->name, status,
+				NETDRV_R16 (IntrStatus));
+
+		if ((status &
+		     (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+		      RxFIFOOver | TxErr | TxOK | RxErr | RxOK)) == 0)
+			break;
+
+		/* Check uncommon events with one test. */
+		if (status & (PCIErr | PCSTimeout | RxUnderrun | RxOverflow |
+		  	      RxFIFOOver | TxErr | RxErr))
+			netdrv_weird_interrupt (dev, tp, ioaddr,
+						 status, link_changed);
+
+		if (status & (RxOK | RxUnderrun | RxOverflow | RxFIFOOver))	/* Rx interrupt */
+			netdrv_rx_interrupt (dev, tp, ioaddr);
+
+		if (status & (TxOK | TxErr))
+			netdrv_tx_interrupt (dev, tp, ioaddr);
+
+		boguscnt--;
+	} while (boguscnt > 0);
+
+	if (boguscnt <= 0) {
+		printk (KERN_WARNING
+			"%s: Too much work at interrupt, "
+			"IntrStatus=0x%4.4x.\n", dev->name,
+			status);
+
+		/* Clear all interrupt sources. */
+		NETDRV_W16 (IntrStatus, 0xffff);
+	}
+
+	spin_unlock (&tp->lock);
+
+	DPRINTK ("%s: exiting interrupt, intr_status=%#4.4x.\n",
+		 dev->name, NETDRV_R16 (IntrStatus));
+}
+
+
+static int netdrv_close (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	DPRINTK ("ENTER\n");
+
+	netif_stop_queue (dev);
+
+	DPRINTK ("%s: Shutting down ethercard, status was 0x%4.4x.\n",
+			dev->name, NETDRV_R16 (IntrStatus));
+
+	del_timer_sync (&tp->timer);
+
+	spin_lock_irqsave (&tp->lock, flags);
+
+	/* Stop the chip's Tx and Rx DMA processes. */
+	NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear));
+
+	/* Disable interrupts by clearing the interrupt mask. */
+	NETDRV_W16 (IntrMask, 0x0000);
+
+	/* Update the error counts. */
+	tp->stats.rx_missed_errors += NETDRV_R32 (RxMissed);
+	NETDRV_W32 (RxMissed, 0);
+
+	spin_unlock_irqrestore (&tp->lock, flags);
+
+	synchronize_irq ();
+	free_irq (dev->irq, dev);
+
+	netdrv_tx_clear (tp);
+
+	pci_free_consistent(tp->pci_dev, RX_BUF_TOT_LEN,
+			    tp->rx_ring, tp->rx_ring_dma);
+	pci_free_consistent(tp->pci_dev, TX_BUF_TOT_LEN,
+			    tp->tx_bufs, tp->tx_bufs_dma);
+	tp->rx_ring = NULL;
+	tp->tx_bufs = NULL;
+
+	/* Green! Put the chip in low-power mode. */
+	NETDRV_W8 (Cfg9346, Cfg9346_Unlock);
+	NETDRV_W8 (Config1, 0x03);
+	NETDRV_W8 (HltClk, 'H');	/* 'R' would leave the clock running. */
+
+	DPRINTK ("EXIT\n");
+	return 0;
+}
+
+
+static int mii_ioctl (struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	u16 *data = (u16 *) & rq->ifr_data;
+	unsigned long flags;
+	int rc = 0;
+
+	DPRINTK ("ENTER\n");
+
+	switch (cmd) {
+	case SIOCDEVPRIVATE:	/* Get the address of the PHY in use. */
+		data[0] = tp->phys[0] & 0x3f;
+		/* Fall Through */
+
+	case SIOCDEVPRIVATE + 1:	/* Read the specified MII register. */
+		spin_lock_irqsave (&tp->lock, flags);
+		data[3] = mdio_read (dev, data[0], data[1] & 0x1f);
+		spin_unlock_irqrestore (&tp->lock, flags);
+		break;
+
+	case SIOCDEVPRIVATE + 2:	/* Write the specified MII register */
+		if (!capable (CAP_NET_ADMIN)) {
+			rc = -EPERM;
+			break;
+		}
+
+		spin_lock_irqsave (&tp->lock, flags);
+		mdio_write (dev, data[0], data[1] & 0x1f, data[2]);
+		spin_unlock_irqrestore (&tp->lock, flags);
+		break;
+
+	default:
+		rc = -EOPNOTSUPP;
+		break;
+	}
+
+	DPRINTK ("EXIT, returning %d\n", rc);
+	return rc;
+}
+
+
+static struct net_device_stats *netdrv_get_stats (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+
+	DPRINTK ("ENTER\n");
+
+	assert (tp != NULL);
+
+	if (netif_running(dev)) {
+		unsigned long flags;
+
+		spin_lock_irqsave (&tp->lock, flags);
+
+		tp->stats.rx_missed_errors += NETDRV_R32 (RxMissed);
+		NETDRV_W32 (RxMissed, 0);
+
+		spin_unlock_irqrestore (&tp->lock, flags);
+	}
+
+	DPRINTK ("EXIT\n");
+	return &tp->stats;
+}
+
+/* Set or clear the multicast filter for this adaptor.
+   This routine is not state sensitive and need not be SMP locked. */
+
+static unsigned const ethernet_polynomial = 0x04c11db7U;
+static inline u32 ether_crc (int length, unsigned char *data)
+{
+	int crc = -1;
+
+	DPRINTK ("ENTER\n");
+
+	while (--length >= 0) {
+		unsigned char current_octet = *data++;
+		int bit;
+		for (bit = 0; bit < 8; bit++, current_octet >>= 1)
+			crc = (crc << 1) ^
+			    ((crc < 0) ^ (current_octet & 1) ?
+			     ethernet_polynomial : 0);
+	}
+
+	DPRINTK ("EXIT\n");
+	return crc;
+}
+
+
+static void netdrv_set_rx_mode (struct net_device *dev)
+{
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	u32 mc_filter[2];	/* Multicast hash filter */
+	int i, rx_mode;
+	u32 tmp;
+
+	DPRINTK ("ENTER\n");
+
+	DPRINTK ("%s:   netdrv_set_rx_mode(%4.4x) done -- Rx config %8.8x.\n",
+			dev->name, dev->flags, NETDRV_R32 (RxConfig));
+
+	/* Note: do not reorder, GCC is clever about common statements. */
+	if (dev->flags & IFF_PROMISC) {
+		/* Unconditionally log net taps. */
+		printk (KERN_NOTICE "%s: Promiscuous mode enabled.\n",
+			dev->name);
+		rx_mode =
+		    AcceptBroadcast | AcceptMulticast | AcceptMyPhys |
+		    AcceptAllPhys;
+		mc_filter[1] = mc_filter[0] = 0xffffffff;
+	} else if ((dev->mc_count > multicast_filter_limit)
+		   || (dev->flags & IFF_ALLMULTI)) {
+		/* Too many to filter perfectly -- accept all multicasts. */
+		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+		mc_filter[1] = mc_filter[0] = 0xffffffff;
+	} else {
+		struct dev_mc_list *mclist;
+		rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys;
+		mc_filter[1] = mc_filter[0] = 0;
+		for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
+		     i++, mclist = mclist->next)
+			set_bit (ether_crc (ETH_ALEN, mclist->dmi_addr) >> 26,
+				 mc_filter);
+	}
+
+	/* if called from irq handler, lock already acquired */
+	if (!in_irq ())
+		spin_lock_irq (&tp->lock);
+
+	/* We can safely update without stopping the chip. */
+	tmp = netdrv_rx_config | rx_mode |
+		(NETDRV_R32 (RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask);
+	NETDRV_W32_F (RxConfig, tmp);
+	NETDRV_W32_F (MAR0 + 0, mc_filter[0]);
+	NETDRV_W32_F (MAR0 + 4, mc_filter[1]);
+
+	if (!in_irq ())
+		spin_unlock_irq (&tp->lock);
+
+	DPRINTK ("EXIT\n");
+}
+
+
+static void netdrv_suspend (struct pci_dev *pdev)
+{
+	struct net_device *dev = pdev->driver_data;
+	struct netdrv_private *tp = (struct netdrv_private *) dev->priv;
+	void *ioaddr = tp->mmio_addr;
+	unsigned long flags;
+
+	netif_device_detach (dev);
+
+	spin_lock_irqsave (&tp->lock, flags);
+
+	/* Disable interrupts, stop Tx and Rx. */
+	NETDRV_W16 (IntrMask, 0x0000);
+	NETDRV_W8 (ChipCmd, (NETDRV_R8 (ChipCmd) & ChipCmdClear));
+
+	/* Update the error counts. */
+	tp->stats.rx_missed_errors += NETDRV_R32 (RxMissed);
+	NETDRV_W32 (RxMissed, 0);
+
+	spin_unlock_irqrestore (&tp->lock, flags);
+
+	pci_power_off (pdev, -1);
+}
+
+
+static void netdrv_resume (struct pci_dev *pdev)
+{
+	struct net_device *dev = pdev->driver_data;
+
+	pci_power_on (pdev);
+	netif_device_attach (dev);
+	netdrv_hw_start (dev);
+}
+
+
+static struct pci_driver netdrv_pci_driver = {
+	name:		MODNAME,
+	id_table:	netdrv_pci_tbl,
+	probe:		netdrv_init_one,
+	remove:		netdrv_remove_one,
+	suspend:	netdrv_suspend,
+	resume:		netdrv_resume,
+};
+
+
+static int __init netdrv_init_module (void)
+{
+	return pci_module_init (&netdrv_pci_driver);
+}
+
+
+static void __exit netdrv_cleanup_module (void)
+{
+	pci_unregister_driver (&netdrv_pci_driver);
+}
+
+
+module_init(netdrv_init_module);
+module_exit(netdrv_cleanup_module);
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/3c574_cs.c linux/drivers/net/pcmcia/3c574_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/3c574_cs.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/net/pcmcia/3c574_cs.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	David Hinds, dahinds@users.sourceforge.net (from his PC card code).
 
 	This software may be used and distributed according to the terms of
-	the GNU Public License, incorporated herein by reference.
+	the GNU General Public License, incorporated herein by reference.
 
 	This driver derives from Donald Becker's 3c509 core, which has the
 	following copyright:
@@ -75,7 +75,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
@@ -325,8 +325,10 @@
 	ether_setup(dev);
 	dev->open = &el3_open;
 	dev->stop = &el3_close;
+#ifdef HAVE_TX_TIMEOUT
 	dev->tx_timeout = el3_tx_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
+#endif
 
 	/* Register with Card Services */
 	link->next = dev_list;
@@ -859,7 +861,7 @@
 	/* Issue TX_RESET and TX_START commands. */
 	wait_for_completion(dev, TxReset);
 	outw(TxEnable, ioaddr + EL3_CMD);
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 }
 
 static void pop_tx_status(struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/3c589_cs.c linux/drivers/net/pcmcia/3c589_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/3c589_cs.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/net/pcmcia/3c589_cs.c	Tue Feb 13 13:15:05 2001
@@ -11,7 +11,7 @@
     Written 1994 by Donald Becker.
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU Public License,
+    distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
     Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
 
@@ -22,7 +22,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
@@ -243,8 +243,10 @@
     ether_setup(dev);
     dev->open = &el3_open;
     dev->stop = &el3_close;
+#ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = el3_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
+#endif
     
     /* Register with Card Services */
     link->next = dev_list;
@@ -686,7 +688,7 @@
     /* Issue TX_RESET and TX_START commands. */
     wait_for_completion(dev, TxReset);
     outw(TxEnable, ioaddr + EL3_CMD);
-    netif_start_queue(dev);
+    netif_wake_queue(dev);
 }
 
 static void pop_tx_status(struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/aironet4500_cs.c linux/drivers/net/pcmcia/aironet4500_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/aironet4500_cs.c	Tue Jul 18 16:52:34 2000
+++ linux/drivers/net/pcmcia/aironet4500_cs.c	Tue Feb 13 13:15:05 2001
@@ -19,7 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/com20020_cs.c linux/drivers/net/pcmcia/com20020_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/com20020_cs.c	Wed Aug  9 13:51:40 2000
+++ linux/drivers/net/pcmcia/com20020_cs.c	Tue Feb 13 13:15:05 2001
@@ -17,7 +17,7 @@
  * skeleton.c Written 1993 by Donald Becker.
  * Copyright 1993 United States Government as represented by the
  * Director, National Security Agency.  This software may only be used
- * and distributed according to the terms of the GNU Public License as
+ * and distributed according to the terms of the GNU General Public License as
  * modified by SRC, incorporated herein by reference.
  * 
  * **********************
@@ -35,7 +35,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/fmvj18x_cs.c linux/drivers/net/pcmcia/fmvj18x_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/fmvj18x_cs.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/net/pcmcia/fmvj18x_cs.c	Tue Feb 13 13:15:05 2001
@@ -32,7 +32,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/ibmtr_cs.c linux/drivers/net/pcmcia/ibmtr_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/ibmtr_cs.c	Wed May 10 16:56:42 2000
+++ linux/drivers/net/pcmcia/ibmtr_cs.c	Tue Feb 13 13:15:05 2001
@@ -55,7 +55,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/netwave_cs.c linux/drivers/net/pcmcia/netwave_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/netwave_cs.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/net/pcmcia/netwave_cs.c	Tue Feb 13 13:15:05 2001
@@ -48,7 +48,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <asm/system.h>
@@ -1218,7 +1218,7 @@
  *    This function is the interrupt handler for the Netwave card. This
  *    routine will be called whenever: 
  *	  1. A packet is received.
- *	  2. A packet has successfully been transfered and the unit is
+ *	  2. A packet has successfully been transferred and the unit is
  *	     ready to transmit another packet.
  *	  3. A command has completed execution.
  */
@@ -1350,7 +1350,7 @@
     DEBUG(1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name);
     netwave_reset(dev);
     dev->trans_start = jiffies;
-    netif_start_queue(dev);
+    netif_wake_queue(dev);
 } /* netwave_watchdog */
 
 static struct net_device_stats *netwave_get_stats(struct net_device *dev) {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/nmclan_cs.c linux/drivers/net/pcmcia/nmclan_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/nmclan_cs.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/net/pcmcia/nmclan_cs.c	Tue Feb 13 13:15:05 2001
@@ -4,13 +4,13 @@
 
   The Ethernet LAN uses the Advanced Micro Devices (AMD) Am79C940 Media
   Access Controller for Ethernet (MACE).  It is essentially the Am2150
-  PCMCIA Ethernet card contained in the the Am2150 Demo Kit.
+  PCMCIA Ethernet card contained in the Am2150 Demo Kit.
 
 Written by Roger C. Pao <rpao@paonet.org>
   Copyright 1995 Roger C. Pao
 
   This software may be used and distributed according to the terms of
-  the GNU Public License.
+  the GNU General Public License.
 
 Ported to Linux 1.3.* network driver environment by
   Matti Aarnio <mea@utu.fi>
@@ -124,7 +124,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
@@ -515,8 +515,10 @@
     ether_setup(dev);
     dev->open = &mace_open;
     dev->stop = &mace_close;
+#ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = mace_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
+#endif
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -1023,7 +1025,7 @@
   printk("NOT resetting card\n");
 #endif /* #if RESET_ON_TIMEOUT */
   dev->trans_start = jiffies;
-  netif_start_queue(dev);
+  netif_wake_queue(dev);
 }
 
 static int mace_start_xmit(struct sk_buff *skb, struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/ositech.h linux/drivers/net/pcmcia/ositech.h
--- v2.4.1/linux/drivers/net/pcmcia/ositech.h	Wed Oct 20 21:33:12 1999
+++ linux/drivers/net/pcmcia/ositech.h	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
     (Special thanks to Kevin MacPherson of OSITECH)
 
     This software may be used and distributed according to the terms of
-    the GNU Public License, incorporated herein by reference.
+    the GNU General Public License, incorporated herein by reference.
 */
 
     static const u_char __Xilinx7OD[] = {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/pcnet_cs.c linux/drivers/net/pcmcia/pcnet_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/pcnet_cs.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/net/pcmcia/pcnet_cs.c	Tue Feb 13 13:15:05 2001
@@ -18,7 +18,7 @@
     Written 1992,1993 by Donald Becker.
     Copyright 1993 United States Government as represented by the
     Director, National Security Agency.  This software may be used and
-    distributed according to the terms of the GNU Public License,
+    distributed according to the terms of the GNU General Public License,
     incorporated herein by reference.
     Donald Becker may be reached at becker@cesdis1.gsfc.nasa.gov
 
@@ -33,7 +33,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/ray_cs.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/net/pcmcia/ray_cs.c	Tue Feb 13 13:15:05 2001
@@ -34,7 +34,7 @@
 #include <linux/sched.h>
 #include <linux/proc_fs.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/smc91c92_cs.c linux/drivers/net/pcmcia/smc91c92_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/smc91c92_cs.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/net/pcmcia/smc91c92_cs.c	Tue Feb 13 13:15:05 2001
@@ -21,7 +21,7 @@
     Mariner, with help from Allen Brost. 
 
     This software may be used and distributed according to the terms of
-    the GNU Public License, incorporated herein by reference.
+    the GNU General Public License, incorporated herein by reference.
 
 ======================================================================*/
 
@@ -29,7 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
@@ -363,8 +363,10 @@
     ether_setup(dev);
     dev->open = &smc91c92_open;
     dev->stop = &smc91c92_close;
+#ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = smc_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
+#endif
     dev->priv = link->priv = link->irq.Instance = smc;
     
     /* Register with Card Services */
@@ -1316,7 +1318,7 @@
     smc_reset(dev);
     dev->trans_start = jiffies;
     smc->saved_skb = NULL;
-    netif_start_queue(dev);
+    netif_wake_queue(dev);
 }
 
 static int smc_start_xmit(struct sk_buff *skb, struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/wavelan_cs.h linux/drivers/net/pcmcia/wavelan_cs.h
--- v2.4.1/linux/drivers/net/pcmcia/wavelan_cs.h	Mon Dec 11 12:59:28 2000
+++ linux/drivers/net/pcmcia/wavelan_cs.h	Tue Feb 13 13:15:05 2001
@@ -364,7 +364,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/xirc2ps_cs.c linux/drivers/net/pcmcia/xirc2ps_cs.c
--- v2.4.1/linux/drivers/net/pcmcia/xirc2ps_cs.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/net/pcmcia/xirc2ps_cs.c	Tue Feb 13 13:15:05 2001
@@ -63,7 +63,7 @@
 #include <linux/init.h>
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/interrupt.h>
@@ -644,8 +644,10 @@
     ether_setup(dev);
     dev->open = &do_open;
     dev->stop = &do_stop;
+#ifdef HAVE_TX_TIMEOUT
     dev->tx_timeout = do_tx_timeout;
     dev->watchdog_timeo = TX_TIMEOUT;
+#endif
 
     /* Register with Card Services */
     link->next = dev_list;
@@ -1519,7 +1521,7 @@
     /* reset the card */
     do_reset(dev,1);
     dev->trans_start = jiffies;
-    netif_start_queue(dev);
+    netif_wake_queue(dev);
 }
 
 static int
@@ -2058,3 +2060,28 @@
 module_init(init_xirc2ps_cs);
 module_exit(exit_xirc2ps_cs);
 
+#ifndef MODULE
+static int __init setup_xirc2ps_cs(char *str)
+{
+	/* irq, irq_mask, if_port, full_duplex, do_sound, lockup_hack
+	 * [,irq2 [,irq3 [,irq4]]]
+	 */
+	int ints[10] = { -1 };
+
+	str = get_options(str, 9, ints);
+
+#define MAYBE_SET(X,Y) if (ints[0] >= Y && ints[Y] != -1) { X = ints[Y]; }
+	MAYBE_SET(irq_list[0], 1);
+	MAYBE_SET(irq_mask, 2);
+	MAYBE_SET(if_port, 3);
+	MAYBE_SET(full_duplex, 4);
+	MAYBE_SET(do_sound, 5);
+	MAYBE_SET(lockup_hack, 6);
+	MAYBE_SET(irq_list[1], 7);
+	MAYBE_SET(irq_list[2], 8);
+	MAYBE_SET(irq_list[3], 9);
+#undef  MAYBE_SET(X,Y)
+}
+
+__setup("xirc2ps_cs=", setup_xirc2ps_cs);
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcmcia/xircom_tulip_cb.c linux/drivers/net/pcmcia/xircom_tulip_cb.c
--- v2.4.1/linux/drivers/net/pcmcia/xircom_tulip_cb.c	Tue Nov  7 11:09:19 2000
+++ linux/drivers/net/pcmcia/xircom_tulip_cb.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	This driver is for the Digital "Tulip" Ethernet adapter interface.
 	It should work with most DEC 21*4*-based chips/ethercards, as well as
@@ -104,7 +104,7 @@
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pcnet32.c linux/drivers/net/pcnet32.c
--- v2.4.1/linux/drivers/net/pcnet32.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/pcnet32.c	Tue Feb 13 13:15:05 2001
@@ -8,7 +8,7 @@
  *	Director, National Security Agency.
  * 
  *	This software may be used and distributed according to the terms
- *	of the GNU Public License, incorporated herein by reference.
+ *	of the GNU General Public License, incorporated herein by reference.
  *
  *	This driver is for PCnet32 and PCnetPCI based ethercards
  */
@@ -23,7 +23,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -811,7 +811,7 @@
 	val |= 0x10;
     lp->a.write_csr (ioaddr, 124, val);
     
-    if (lp->mii & !(lp->options & PORT_ASEL)) {
+    if (lp->mii && !(lp->options & PORT_ASEL)) {
 	val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */
 	if (lp->options & PORT_FD)
 	    val |= 0x10;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/plip.c linux/drivers/net/plip.c
--- v2.4.1/linux/drivers/net/plip.c	Mon Dec 11 12:39:45 2000
+++ linux/drivers/net/plip.c	Tue Feb 13 13:15:05 2001
@@ -728,6 +728,7 @@
 		/* Inform the upper layer for the arrival of a packet. */
 		rcv->skb->protocol=plip_type_trans(rcv->skb, dev);
 		netif_rx(rcv->skb);
+		dev->last_rx = jiffies;
 		nl->enet_stats.rx_bytes += rcv->length.h;
 		nl->enet_stats.rx_packets++;
 		rcv->skb = NULL;
@@ -994,7 +995,6 @@
 		netif_wake_queue (dev);
 	case PLIP_CN_NONE:
 	case PLIP_CN_SEND:
-		dev->last_rx = jiffies;
 		rcv->state = PLIP_PK_TRIGGER;
 		nl->connection = PLIP_CN_RECEIVE;
 		nl->timeout_count = 0;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ppp_async.c linux/drivers/net/ppp_async.c
--- v2.4.1/linux/drivers/net/ppp_async.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/ppp_async.c	Tue Feb 13 13:15:05 2001
@@ -942,7 +942,7 @@
 	}
 }
 
-void __exit ppp_async_cleanup(void)
+static void __exit ppp_async_cleanup(void)
 {
 	if (tty_register_ldisc(N_PPP, NULL) != 0)
 		printk(KERN_ERR "failed to unregister PPP line discipline\n");
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ppp_deflate.c linux/drivers/net/ppp_deflate.c
--- v2.4.1/linux/drivers/net/ppp_deflate.c	Sun Mar 12 21:12:37 2000
+++ linux/drivers/net/ppp_deflate.c	Tue Feb 13 13:15:05 2001
@@ -32,7 +32,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
--- v2.4.1/linux/drivers/net/ppp_generic.c	Tue Nov 28 21:53:45 2000
+++ linux/drivers/net/ppp_generic.c	Sun Feb  4 10:05:30 2001
@@ -1412,6 +1412,7 @@
 			skb->protocol = htons(npindex_to_ethertype[npi]);
 			skb->mac.raw = skb->data;
 			netif_rx(skb);
+			ppp->dev->last_rx = jiffies;
 		}
 	}
 	return;
@@ -2342,7 +2343,7 @@
 	write_lock_bh(&pch->upl);
 	ret = -EINVAL;
 	if (pch->ppp != 0)
-		goto outw;
+		goto outwl;
 	ppp_lock(ppp);
 	spin_lock_bh(&pch->downl);
 	if (pch->chan == 0)		/* need to check this?? */
@@ -2361,7 +2362,7 @@
  outr:
 	spin_unlock_bh(&pch->downl);
 	ppp_unlock(ppp);
- outw:
+ outwl:
 	write_unlock_bh(&pch->upl);
  out:
 	spin_unlock(&all_ppp_lock);
@@ -2408,7 +2409,7 @@
 	kfree(pch);
 }
 
-void __exit ppp_cleanup(void)
+static void __exit ppp_cleanup(void)
 {
 	/* should never happen */
 	if (!list_empty(&all_ppp_units) || !list_empty(&all_channels))
diff -u --recursive --new-file v2.4.1/linux/drivers/net/ppp_synctty.c linux/drivers/net/ppp_synctty.c
--- v2.4.1/linux/drivers/net/ppp_synctty.c	Sat May 20 11:34:54 2000
+++ linux/drivers/net/ppp_synctty.c	Tue Feb 13 13:15:05 2001
@@ -738,7 +738,7 @@
 	}
 }
 
-void __exit
+static void __exit
 ppp_sync_cleanup(void)
 {
 	if (tty_register_ldisc(N_SYNC_PPP, NULL) != 0)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pppoe.c linux/drivers/net/pppoe.c
--- v2.4.1/linux/drivers/net/pppoe.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/pppoe.c	Tue Feb 13 13:15:05 2001
@@ -39,7 +39,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/pppox.c linux/drivers/net/pppox.c
--- v2.4.1/linux/drivers/net/pppox.c	Mon Oct 16 12:26:08 2000
+++ linux/drivers/net/pppox.c	Tue Feb 13 13:15:05 2001
@@ -26,7 +26,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 
 #include <linux/netdevice.h>
@@ -38,7 +38,7 @@
 #include <linux/if_ppp.h>
 #include <linux/ppp_channel.h>
 
-static struct pppox_proto *proto[PX_MAX_PROTO+1] = { NULL, };
+static struct pppox_proto *proto[PX_MAX_PROTO+1];
 
 int register_pppox_proto(int proto_num, struct pppox_proto *pp)
 {
@@ -77,8 +77,8 @@
 EXPORT_SYMBOL(unregister_pppox_proto);
 EXPORT_SYMBOL(pppox_unbind_sock);
 
-int pppox_ioctl(struct socket* sock, unsigned int cmd,
-		unsigned long arg)
+static int pppox_ioctl(struct socket* sock, unsigned int cmd,
+		       unsigned long arg)
 {
 	struct sock *sk = sock->sk;
 	struct pppox_opt *po;
@@ -116,7 +116,7 @@
 }
 
 
-int pppox_create(struct socket *sock, int protocol)
+static int pppox_create(struct socket *sock, int protocol)
 {
 	int err = 0;
 
@@ -137,12 +137,12 @@
 	return err;
 }
 
-struct net_proto_family pppox_proto_family = {
+static struct net_proto_family pppox_proto_family = {
 	PF_PPPOX,
 	pppox_create
 };
 
-int __init pppox_init(void)
+static int __init pppox_init(void)
 {
 	int err = 0;
 
@@ -155,7 +155,7 @@
 	return err;
 }
 
-void __exit pppox_exit(void)
+static void __exit pppox_exit(void)
 {
 	sock_unregister(PF_PPPOX);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/rclanmtl.c linux/drivers/net/rclanmtl.c
--- v2.4.1/linux/drivers/net/rclanmtl.c	Mon Dec 11 13:04:09 2000
+++ linux/drivers/net/rclanmtl.c	Sun Feb  4 10:05:30 2001
@@ -36,15 +36,11 @@
 ** *************************************************************************
 */
 
-#undef DEBUG
+#define DEBUG 1
 
 #define RC_LINUX_MODULE
 #include "rclanmtl.h"
 
-#define dprintf kprintf
-
-extern int printk(const char * fmt, ...);
-
  /* RedCreek LAN device Target ID */
 #define RC_LAN_TARGET_ID  0x10 
  /* RedCreek's OSM default LAN receive Initiator */
@@ -216,8 +212,8 @@
 /* #define RC_PRIVATE_GET_IP_AND_MASK  0x0007 */ /* OBSOLETE */
 #define RC_PRIVATE_GET_LINK_SPEED   0x0008
 #define RC_PRIVATE_GET_FIRMWARE_REV 0x0009
-/* #define RC_PRIVATE_GET_MAC_ADDR     0x000A *//**/
-#define RC_PRIVATE_GET_IP_AND_MASK  0x000B /**/
+/* #define RC_PRIVATE_GET_MAC_ADDR     0x000A */
+#define RC_PRIVATE_GET_IP_AND_MASK  0x000B 
 #define RC_PRIVATE_DEBUG_MSG        0x000C
 #define RC_PRIVATE_REPORT_DRIVER_CAPABILITY  0x000D
 #define RC_PRIVATE_SET_PROMISCUOUS_MODE  0x000e
@@ -247,72 +243,11 @@
 #define MSG_FRAME_SIZE  512
 #define NMBR_MSG_FRAMES 30
 
-/*
-**  Message Unit CSR definitions for RedCreek PCI45 board
-*/
-typedef struct tag_rcatu 
-{
-    volatile unsigned long APICRegSel;  /* APIC Register Select */
-    volatile unsigned long reserved0;
-    volatile unsigned long APICWinReg;  /* APIC Window Register */
-    volatile unsigned long reserved1;
-    volatile unsigned long InMsgReg0;   /* inbound message register 0 */
-    volatile unsigned long InMsgReg1;   /* inbound message register 1 */
-    volatile unsigned long OutMsgReg0;  /* outbound message register 0 */
-    volatile unsigned long OutMsgReg1;  /* outbound message register 1 */
-    volatile unsigned long InDoorReg;   /* inbound doorbell register */
-    volatile unsigned long InIntStat;   /* inbound interrupt status register */
-    volatile unsigned long InIntMask;   /* inbound interrupt mask register */
-    volatile unsigned long OutDoorReg;  /* outbound doorbell register */
-    volatile unsigned long OutIntStat;  /* outbound interrupt status register */
-    volatile unsigned long OutIntMask;  /* outbound interrupt mask register */
-    volatile unsigned long reserved2;
-    volatile unsigned long reserved3;
-    volatile unsigned long InQueue;     /* inbound queue port */
-    volatile unsigned long OutQueue;    /* outbound queue port */
-    volatile unsigned long reserved4;
-    volatile unsigned long reserver5;
-    /* RedCreek extension */
-    volatile unsigned long EtherMacLow;
-    volatile unsigned long EtherMacHi;
-    volatile unsigned long IPaddr;
-    volatile unsigned long IPmask;
-}
-ATU, *PATU;
-
- /* 
- ** typedef PAB
- **
- ** PCI Adapter Block - holds instance specific information and is located
- ** in a reserved space at the start of the message buffer allocated by user.
- */
-typedef struct
-{
-    PATU             p_atu;                /* ptr to  ATU register block */
-    PU8              pPci45LinBaseAddr;
-    PU8              pLinOutMsgBlock;
-    U32              outMsgBlockPhyAddr; 
-    PFNTXCALLBACK    pTransCallbackFunc;
-    PFNRXCALLBACK    pRecvCallbackFunc;
-    PFNCALLBACK      pRebootCallbackFunc;
-    PFNCALLBACK      pCallbackFunc;
-    U16              IOPState;
-    U16              InboundMFrameSize;
-}
-PAB, *PPAB;
-
  /* 
  ** in reserved space right after PAB in host memory is area for returning
  ** values from card 
  */
 
- /* 
- ** Array of pointers to PCI Adapter Blocks.
- ** Indexed by a zero based (0-31) interface number.
- */ 
-#define MAX_ADAPTERS 32
-static PPAB  PCIAdapterBlock[MAX_ADAPTERS];
-
 /*
 ** typedef NICSTAT
 **
@@ -357,19 +292,13 @@
 static int SendEnableSysMsg(PPAB pPab);
 
 
-/* 1st 100h bytes of message block is reserved for messenger instance */
-#define ADAPTER_BLOCK_RESERVED_SPACE 0x100
-
 /*
 ** =========================================================================
 ** RCInitI2OMsgLayer()
 **
 ** Initialize the RedCreek I2O Module and adapter.
 **
-** Inputs:  AdapterID - interface number from 0 to 15
-**          pciBaseAddr - virual base address of PCI (set by BIOS)
-**          p_msgbuf - virual address to private message block (min. 16K)
-**          p_phymsgbuf - physical address of private message block
+** Inputs:  dev - the devices net_device struct
 **          TransmitCallbackFunction - address of transmit callback function
 **          ReceiveCallbackFunction  - address of receive  callback function
 **
@@ -379,42 +308,49 @@
 ** =========================================================================
 */
 RC_RETURN
-RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr, 
-                  PU8 p_msgbuf,  PU8 p_phymsgbuf,
+RCInitI2OMsgLayer(struct net_device *dev,
                   PFNTXCALLBACK  TransmitCallbackFunction,
                   PFNRXCALLBACK  ReceiveCallbackFunction,
                   PFNCALLBACK    RebootCallbackFunction)
 {
     int result;
     PPAB pPab; 
-    
-#ifdef DEBUG
-    kprintf("InitI2O: Adapter:0x%04.4ux ATU:0x%08.8ulx msgbuf:0x%08.8ulx phymsgbuf:0x%08.8ulx\n"
-            "TransmitCallbackFunction:0x%08.8ulx  ReceiveCallbackFunction:0x%08.8ulx\n",
-            AdapterID, pciBaseAddr, p_msgbuf, p_phymsgbuf, TransmitCallbackFunction, ReceiveCallbackFunction);
-#endif /* DEBUG */
+    U32 pciBaseAddr = dev->base_addr;
+    PDPA pDpa = dev->priv;
+    PU8 p_msgbuf = pDpa->PLanApiPA;
+    PU8 p_phymsgbuf = (PU8)virt_to_bus((void *) p_msgbuf);    
+    
+    dprintk("InitI2O: Adapter:0x%04ux ATU:0x%08ulx msgbuf:0x%08ulx phymsgbuf:0x%08ulx\n"
+            "TransmitCallbackFunction:0x%08ulx  ReceiveCallbackFunction:0x%08ulx\n",
+            pDpa->id, pciBaseAddr, (u32)p_msgbuf, (u32)p_phymsgbuf, 
+	    (u32)TransmitCallbackFunction, (u32)ReceiveCallbackFunction);
 
     
     /* Check if this interface already initialized - if so, shut it down */
-    if (PCIAdapterBlock[AdapterID] != NULL)
-    {
-        printk("PCIAdapterBlock[%d]!=NULL\n", AdapterID);
-//        RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
-        PCIAdapterBlock[AdapterID] = NULL;
+    if (pDpa->pPab != NULL) {
+	    printk(KERN_WARNING "(rcpci45 driver:) pDpa->pPab [%d] != NULL\n", pDpa->id);
+/*          RCResetLANCard(pDpa->id, 0, (PU32)NULL, (PFNCALLBACK)NULL); */
+	    pDpa->pPab = NULL;
     }
 
-    /* 
-    ** store adapter instance values in adapter block.
-    ** Adapter block is at beginning of message buffer
-    */  
-    pPab = (PPAB)p_msgbuf;
+    /* store adapter instance values in adapter block.
+     * Adapter block is at beginning of message buffer */  
     
+    pPab = kmalloc(sizeof(*pPab), GFP_KERNEL);
+    if (!pPab) {
+	    printk(KERN_ERR "(rcpci45 driver:) RCInitI2OMsgLayer: Could not allocate memory for PAB struct!\n");
+	    result = RC_RTN_MALLOC_ERROR;
+	    goto err_out;
+    }
+
+    memset(pPab, 0, sizeof(*pPab));
+    pDpa->pPab = pPab;
     pPab->p_atu = (PATU)pciBaseAddr;
     pPab->pPci45LinBaseAddr =  (PU8)pciBaseAddr;
     
-    /* Set outbound message frame addr - skip over Adapter Block */
-    pPab->outMsgBlockPhyAddr = (U32)(p_phymsgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
-    pPab->pLinOutMsgBlock    = (PU8)(p_msgbuf + ADAPTER_BLOCK_RESERVED_SPACE);
+    /* Set outbound message frame addr */
+    pPab->outMsgBlockPhyAddr = (U32)p_phymsgbuf;
+    pPab->pLinOutMsgBlock    = (PU8)p_msgbuf;
 
     /* store callback function addresses */
     pPab->pTransCallbackFunc = TransmitCallbackFunction;
@@ -428,26 +364,29 @@
     result = GetI2OStatus(pPab);
     
     if (result != RC_RTN_NO_ERROR)
-        return result;
+	    goto err_out_dealloc;
 
-    if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL)
-    {
-        printk("pPab->IOPState == op: resetting adapter\n");
-        RCResetLANCard(AdapterID, 0, (PU32)NULL, (PFNCALLBACK)NULL);
+    if (pPab->IOPState == I2O_IOP_STATE_OPERATIONAL) {
+        printk(KERN_INFO "(rcpci45 driver:) pPab->IOPState == op: resetting adapter\n");
+        RCResetLANCard(dev, 0, (PU32)NULL, (PFNCALLBACK)NULL);
     }
         
     result = SendI2OOutboundQInitMsg(pPab);
     
     if (result != RC_RTN_NO_ERROR)
-        return result;
+	    goto err_out_dealloc;
 
     result = SendEnableSysMsg(pPab);
    
     if (result != RC_RTN_NO_ERROR)
-        return result;
+	    goto err_out_dealloc;
    
-    PCIAdapterBlock[AdapterID] = pPab;
     return RC_RTN_NO_ERROR;
+
+ err_out_dealloc:
+    kfree(pPab);
+ err_out:
+    return result;
 }
 
 /*
@@ -462,13 +401,11 @@
 */
 #define i960_OUT_POST_Q_INT_BIT        0x0008 /* bit set masks interrupts */
 
-RC_RETURN RCDisableI2OInterrupts(U16 AdapterID)
+RC_RETURN RCDisableI2OInterrupts(struct net_device *dev)
 {
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
 
-    pPab = PCIAdapterBlock[AdapterID];
-    
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
         
@@ -477,12 +414,11 @@
     return RC_RTN_NO_ERROR;
 }
 
-RC_RETURN RCEnableI2OInterrupts(U16 AdapterID)
+RC_RETURN RCEnableI2OInterrupts(struct net_device *dev)
 {
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
+
 
-    pPab = PCIAdapterBlock[AdapterID];
-    
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -499,18 +435,16 @@
 ** =========================================================================
 */
 RC_RETURN
-RCI2OSendPacket(U16 AdapterID, U32 InitiatorContext, PRCTCB pTransCtrlBlock)
+RCI2OSendPacket(struct net_device *dev, U32 InitiatorContext, 
+		PRCTCB pTransCtrlBlock)
 {
     U32 msgOffset;
     PU32 pMsg;
     int size;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
-#ifdef DEBUG
-    kprintf("RCI2OSendPacket()...\n");
-#endif /* DEBUG */
-    
-    pPab = PCIAdapterBlock[AdapterID];
+
+    dprintk("RCI2OSendPacket()...\n");
 
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
@@ -522,9 +456,7 @@
 
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        kprintf("RCI2OSendPacket(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
+        dprintk("RCI2OSendPacket(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
         
@@ -535,9 +467,7 @@
 
     if (size == -1) /* error processing TCB - send NOP msg */
     {
-#ifdef DEBUG
-        kprintf("RCI2OSendPacket(): Error Rrocess TCB!\n");
-#endif /* DEBUG */
+        dprintk("RCI2OSendPacket(): Error Rrocess TCB!\n");
         pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
         pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
         return RC_RTN_TCB_ERROR;
@@ -565,35 +495,28 @@
 ** =========================================================================
 */
 RC_RETURN
-RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransCtrlBlock)
+RCPostRecvBuffers(struct net_device *dev, PRCTCB pTransCtrlBlock)
 {
     U32 msgOffset;
     PU32 pMsg;
     int size;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
-#ifdef DEBUG
-    kprintf("RCPostRecvBuffers()...\n");
-#endif /* DEBUG */
+    dprintk("RCPostRecvBuffers()...\n");
     
     /* search for DeviceHandle */
-    pPab = PCIAdapterBlock[AdapterID];
 
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
-
     /* get Inbound free Q entry - reading from In Q gets free Q entry */
     /* offset to Msg Frame in PCI msg block */
     msgOffset = pPab->p_atu->InQueue; 
 
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        kprintf("RCPostRecvBuffers(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
+        dprintk("RCPostRecvBuffers(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
-   
     }
     /* calc virual address of msg - virual already mapped to physical */    
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
@@ -602,9 +525,7 @@
 
     if (size == -1) /* error prcessing TCB - send 3 DWORD private msg == NOP */
     {
-#ifdef DEBUG
-        kprintf("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
-#endif /* DEBUG */
+        dprintk("RCPostRecvBuffers(): Error Processing TCB! size = %d\n", size);
         pMsg[0] = THREE_WORD_MSG_SIZE | SGL_OFFSET_0;
         pMsg[1] = I2O_UTIL_NOP << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
         /* post to Post Q */   
@@ -632,17 +553,16 @@
 ** =========================================================================
 */
 void 
-RCProcI2OMsgQ(U16 AdapterID)
+RCProcI2OMsgQ(struct net_device *dev)
 {
     U32 phyAddrMsg;
     PU8 p8Msg;
     PU32 p32;
     U16 count;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
     unsigned char debug_msg[20];
     
-    pPab = PCIAdapterBlock[AdapterID];
-    
+
     if (pPab == NULL)
         return;
     
@@ -653,89 +573,66 @@
         p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
         p32 = (PU32)p8Msg;
         
-        //printk(" msg: 0x%x  0x%x \n", p8Msg[7], p32[5]);
+        dprintk("msg: 0x%x  0x%x \n", p8Msg[7], p32[5]);
 
-        /* 
-        ** Send Packet Reply Msg
-        */
-        if (I2O_LAN_PACKET_SEND == p8Msg[7])  /* function code byte */
-        {
+        /* Send Packet Reply Msg */
+        if (I2O_LAN_PACKET_SEND == p8Msg[7]) {  /* function code byte */
             count = *(PU16)(p8Msg+2);
             count -= p8Msg[0] >> 4;
             /* status, count, context[], adapter */
-            (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, AdapterID);
-        }             
-        /* 
-        ** Receive Packet Reply Msg */
-        else if (I2O_LAN_RECEIVE_POST == p8Msg[7])
-        {
-#ifdef DEBUG    
-            kprintf("I2O_RECV_REPLY pPab:0x%08.8ulx p8Msg:0x%08.8ulx p32:0x%08.8ulx\n", pPab, p8Msg, p32);
-            kprintf("msg: 0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
-                    p32[0], p32[1], p32[2], p32[3]);
-            kprintf("     0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
-                    p32[4], p32[5], p32[6], p32[7]);
-            kprintf("     0x%08.8ulx:0X%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
-                    p32[8], p32[9], p32[10], p32[11]);
-#endif
-            /*  status, count, buckets remaining, packetParmBlock, adapter */
-            (*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, AdapterID);
-      
-      
-        }
-        else if (I2O_LAN_RESET == p8Msg[7] || I2O_LAN_SHUTDOWN == p8Msg[7])
-        {
-            if (pPab->pCallbackFunc)
-            {
-                (*pPab->pCallbackFunc)(p8Msg[19],0,0,AdapterID);
-            }
-            else
-            {
-                pPab->pCallbackFunc = (PFNCALLBACK) 1;
-            }
-            //PCIAdapterBlock[AdapterID] = 0;
-        }
-        else if (I2O_PRIVATE == p8Msg[7])
-        {
-            //printk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
+            (*pPab->pTransCallbackFunc)(p8Msg[19], count, p32+5, dev);
+        } else if (I2O_LAN_RECEIVE_POST == p8Msg[7]) { /* Receive Packet Reply Msg */
+		dprintk("I2O_RECV_REPLY pPab:0x%08ulx p8Msg:0x%08ulx p32:0x%08ulx\n", (u32)pPab, (u32)p8Msg, (u32)p32);
+		dprintk("msg: 0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+			p32[0], p32[1], p32[2], p32[3]);
+		dprintk("     0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
+			p32[4], p32[5], p32[6], p32[7]);
+		dprintk("     0x%08ulx:0X%08ulx:0x%08ulx:0x%08ulx\n",
+			p32[8], p32[9], p32[10], p32[11]);
+		/*  status, count, buckets remaining, packetParmBlock, adapter */
+		(*pPab->pRecvCallbackFunc)(p8Msg[19], p8Msg[12], p32[5], p32+6, dev);      
+        } else if (I2O_LAN_RESET == p8Msg[7] || I2O_LAN_SHUTDOWN == p8Msg[7])
+		if (pPab->pCallbackFunc)
+			(*pPab->pCallbackFunc)(p8Msg[19],0,0,dev);
+		else		
+			pPab->pCallbackFunc = (PFNCALLBACK) 1;
+        else if (I2O_PRIVATE == p8Msg[7]) {
+	    dprintk("i2o private 0x%x, 0x%x \n", p8Msg[7], p32[5]);
             switch (p32[5])
             {
             case RC_PRIVATE_DEBUG_MSG:
                 msgFlag = 1;
-                /*printk("Received I2O_PRIVATE msg\n");*/
-                debug_msg[15]  = (p32[6]&0xff000000) >> 24;
-                debug_msg[14]  = (p32[6]&0x00ff0000) >> 16;
-                debug_msg[13]  = (p32[6]&0x0000ff00) >> 8;
-                debug_msg[12]  = (p32[6]&0x000000ff);
-
-                debug_msg[11]  = (p32[7]&0xff000000) >> 24;
-                debug_msg[10]  = (p32[7]&0x00ff0000) >> 16;
-                debug_msg[ 9]  = (p32[7]&0x0000ff00) >> 8;
-                debug_msg[ 8]  = (p32[7]&0x000000ff);
-
-                debug_msg[ 7]  = (p32[8]&0xff000000) >> 24;
-                debug_msg[ 6]  = (p32[8]&0x00ff0000) >> 16;
+                dprintk("Received I2O_PRIVATE msg\n");
+                debug_msg[15] = (p32[6]&0xff000000) >> 24;
+                debug_msg[14] = (p32[6]&0x00ff0000) >> 16;
+                debug_msg[13] = (p32[6]&0x0000ff00) >> 8;
+                debug_msg[12] = (p32[6]&0x000000ff);
+			      
+                debug_msg[11] = (p32[7]&0xff000000) >> 24;
+                debug_msg[10] = (p32[7]&0x00ff0000) >> 16;
+                debug_msg[ 9] = (p32[7]&0x0000ff00) >> 8;
+                debug_msg[ 8] = (p32[7]&0x000000ff);
+			      
+                debug_msg[ 7] = (p32[8]&0xff000000) >> 24;
+                debug_msg[ 6] = (p32[8]&0x00ff0000) >> 16;
                 debug_msg[ 5] = (p32[8]&0x0000ff00) >> 8;
                 debug_msg[ 4] = (p32[8]&0x000000ff);
-
+			      
                 debug_msg[ 3] = (p32[9]&0xff000000) >> 24;
                 debug_msg[ 2] = (p32[9]&0x00ff0000) >> 16;
                 debug_msg[ 1] = (p32[9]&0x0000ff00) >> 8;
                 debug_msg[ 0] = (p32[9]&0x000000ff);
 
                 debug_msg[16] = '\0';
-                printk (debug_msg);
+                dprintk("%s", debug_msg);
                 break;
             case RC_PRIVATE_REBOOT:
-                printk("Adapter reboot initiated...\n");
+                dprintk("Adapter reboot initiated...\n");
                 if (pPab->pRebootCallbackFunc)
-                {
-                    (*pPab->pRebootCallbackFunc)(0,0,0,AdapterID);
-                }
+                    (*pPab->pRebootCallbackFunc)(0,0,0,dev);
                 break;
             default:
-                printk("Unknown private I2O msg received: 0x%lx\n",
-                       p32[5]);
+                printk(KERN_WARNING "(rcpci45 driver:) Unknown private I2O msg received: 0x%x\n", p32[5]);
                 break;
             }
         }
@@ -744,9 +641,7 @@
         ** Process other Msg's
         */
         else
-        {
             ProcessOutboundI2OMsg(pPab, phyAddrMsg);
-        }
         
         /* return MFA to outbound free Q*/
         pPab->p_atu->OutQueue = phyAddrMsg;
@@ -766,7 +661,7 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkStatistics(U16 AdapterID, 
+RCGetLinkStatistics(struct net_device *dev, 
                     P_RCLINKSTATS StatsReturnAddr,
                     PFNWAITCALLBACK WaitCallback)
 {
@@ -776,11 +671,10 @@
     volatile PU32 p32, pReturnAddr;
     P_NICSTAT pStats;
     int i;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
-/*kprintf("Get82558Stats() StatsReturnAddr:0x%08.8ulx\n", StatsReturnAddr);*/
 
-    pPab = PCIAdapterBlock[AdapterID];
+/*dprintk("Get82558Stats() StatsReturnAddr:0x%08ulx\n", StatsReturnAddr); */
 
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
@@ -789,28 +683,25 @@
 
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        kprintf("Get8255XStats(): Inbound Free Q empty!\n");
-#endif
+        dprintk("Get8255XStats(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
     /* calc virual address of msg - virual already mapped to physical */
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
-/*dprintf("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
-/*dprintf("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+/*dprintk("Get82558Stats - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintk("Get82558Stats - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
     pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
     pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
     pMsg[3] = 0x112; /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_NIC_STATS;
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
-
-    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
-
-    pStats = (P_NICSTAT)p32;
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
+    
+    p32 = (PU32) pPab->outMsgBlockPhyAddr;
+    pStats = (P_NICSTAT)pPab->pLinOutMsgBlock;
     pStats->dump_status = 0xFFFFFFFF;
 
     /* post to Inbound Post Q */
@@ -822,17 +713,14 @@
         if (WaitCallback)
             (*WaitCallback)();
         
-        for (i = 0; i < 1000; i++)
-            ;
+	udelay(10);
 
         if (pStats->dump_status != 0xFFFFFFFF)
             break;
 
         if (!timeout--)
         {
-#ifdef DEBUG
-            kprintf("RCGet82558Stats() Timeout waiting for NIC statistics\n");
-#endif
+            dprintk("RCGet82558Stats() Timeout waiting for NIC statistics\n");
             return RC_RTN_MSG_REPLY_TIMEOUT;
         }
     }
@@ -853,17 +741,17 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkStatus(U16 AdapterID, PU32 ReturnAddr, PFNWAITCALLBACK WaitCallback)
+RCGetLinkStatus(struct net_device *dev, PU32 ReturnAddr, 
+		PFNWAITCALLBACK WaitCallback)
 {
     U32 msgOffset;
     volatile U32 timeout;
     volatile PU32 pMsg;
     volatile PU32 p32;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
-/*kprintf("Get82558LinkStatus() ReturnPhysAddr:0x%08.8ulx\n", ReturnAddr);*/
 
-    pPab = PCIAdapterBlock[AdapterID];
+    dprintk("Get82558LinkStatus() ReturnPhysAddr:0x%08ulx\n", (u32)ReturnAddr);
 
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
@@ -872,49 +760,40 @@
 
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        dprintf("Get82558LinkStatus(): Inbound Free Q empty!\n");
-#endif
+        dprintk("Get82558LinkStatus(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
     /* calc virual address of msg - virual already mapped to physical */
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
-/*dprintf("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
-/*dprintf("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
+/*dprintk("Get82558LinkStatus - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", pMsg, msgOffset);*/
+/*dprintk("Get82558LinkStatus - pMsg = 0x%08X, InQ msgOffset = 0x%08X\n", pMsg, msgOffset);*/
 
     pMsg[0] = SIX_WORD_MSG_SIZE | SGL_OFFSET_0;
     pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
     pMsg[2] = DEFAULT_RECV_INIT_CONTEXT;
     pMsg[3] = 0x112; /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_STATUS;
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
 
-    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (PU32)pPab->pLinOutMsgBlock;
     *p32 = 0xFFFFFFFF;
     
     /* post to Inbound Post Q */
     pPab->p_atu->InQueue = msgOffset;
 
     timeout = 100000;
-    while (1)
-    {
-        U32 i;
-
+    while (1) {
         if (WaitCallback)
             (*WaitCallback)();
         
-        for (i = 0; i < 1000; i++)
-            ;
+	udelay(10);
 
         if (*p32 != 0xFFFFFFFF)
             break;
 
-        if (!timeout--)
-        {
-#ifdef DEBUG
-            kprintf("Timeout waiting for link status\n");
-#endif    
+        if (!timeout--) {
+            dprintk("Timeout waiting for link status\n");
             return RC_RTN_MSG_REPLY_TIMEOUT;
         }
     }
@@ -934,17 +813,16 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback)
+RCGetMAC(struct net_device *dev, PFNWAITCALLBACK WaitCallback)
 {
-    unsigned i, timeout;
+    unsigned timeout;
     U32      off;
+    PU8      mac = dev->dev_addr;
     PU32     p;
     U32      temp[2];
-    PPAB     pPab;
+    PPAB     pPab = ((PDPA)dev->priv)->pPab;
     PATU     p_atu;
     
-    pPab = PCIAdapterBlock[AdapterID];
-    
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -960,10 +838,8 @@
 
     p = (PU32)(pPab->pPci45LinBaseAddr + off);
 
-#ifdef RCDEBUG
-    printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
+    dprintk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
            (uint)p_atu, (uint)off, (uint)p);
-#endif /* RCDEBUG */
     /* setup private message */
     p[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
     p[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
@@ -973,10 +849,8 @@
 
 
     p_atu->InQueue = off;   /* send it to the I2O device */
-#ifdef RCDEBUG
-    printk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
+    dprintk("RCGetMAC: p_atu 0x%08x, off 0x%08x, p 0x%08x\n", 
            (uint)p_atu, (uint)off, (uint)p);
-#endif /* RCDEBUG */
 
     /* wait for the rcpci45 board to update the info */
     timeout = 1000000;
@@ -985,8 +859,7 @@
         if (WaitCallback)
             (*WaitCallback)();
     
-        for (i = 0; i < 1000; i++)
-            ;
+	udelay(10);
 
         if (!timeout--)
         {
@@ -1001,9 +874,7 @@
     memcpy((char *)mac, (char *)temp, 6);
 
 
-#ifdef RCDEBUG
-//    printk("rc_getmac: 0x%X\n", ptr);
-#endif /* RCDEBUG */
+    dprintk("rc_getmac: 0x%x\n", (u32)mac);
 
     return RC_RTN_NO_ERROR;
 }
@@ -1018,15 +889,13 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetMAC(U16 AdapterID, PU8 mac)
+RCSetMAC(struct net_device *dev, PU8 mac)
 {
     U32  off;
     PU32 pMsg;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
 
-    pPab = PCIAdapterBlock[AdapterID];
-    
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -1067,15 +936,13 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode)
+RCSetLinkSpeed(struct net_device *dev, U16 LinkSpeedCode)
 {
     U32  off;
     PU32 pMsg;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
     
-    pPab =PCIAdapterBlock[AdapterID];
-     
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -1109,14 +976,12 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+RCSetPromiscuousMode(struct net_device *dev, U16 Mode)
 {
     U32  off;
     PU32 pMsg;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
     
-    pPab =PCIAdapterBlock[AdapterID];
-     
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -1152,22 +1017,20 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, 
+		     PFNWAITCALLBACK WaitCallback)
 {
     U32 msgOffset, timeout;
     PU32 pMsg;
     volatile PU32 p32;
-    PPAB pPab;
-
-    pPab =PCIAdapterBlock[AdapterID];
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
 
     msgOffset = pPab->p_atu->InQueue;
 
-
     if (msgOffset == 0xFFFFFFFF)
     {
-        kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+	printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
@@ -1175,7 +1038,7 @@
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1185,7 +1048,7 @@
     pMsg[3] = 0x219;             /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_PROMISCUOUS_MODE;
     /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
    
     /* post to Inbound Post Q */   
 
@@ -1193,23 +1056,19 @@
 
     /* wait for response */
     timeout = 1000000;
-    while(1)
-    {
-        int i;
-        
+    while(1) {
         if (WaitCallback)
             (*WaitCallback)();
 
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
-            
+	udelay(10);  /* please don't hog the bus!!! */
+
         if (p32[0] != 0xff)
             break;
             
         if (!timeout--)
         {
-            kprintf("Timeout waiting for promiscuous mode from adapter\n");
-            kprintf("0x%8.8lx\n", p32[0]);
+	    dprintk("Timeout waiting for promiscuous mode from adapter\n");
+            dprintk("0x%8x\n", p32[0]);
             return RC_RTN_NO_LINK_SPEED;
         }
     }
@@ -1230,14 +1089,13 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+RCSetBroadcastMode(struct net_device *dev, U16 Mode)
 {
     U32  off;
     PU32 pMsg;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
     
-    pPab =PCIAdapterBlock[AdapterID];
-     
+
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -1273,22 +1131,20 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+RCGetBroadcastMode(struct net_device *dev, PU32 pMode, 
+		   PFNWAITCALLBACK WaitCallback)
 {
     U32 msgOffset, timeout;
     PU32 pMsg;
     volatile PU32 p32;
-    PPAB pPab;
-
-    pPab =PCIAdapterBlock[AdapterID];
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
 
     msgOffset = pPab->p_atu->InQueue;
 
-
     if (msgOffset == 0xFFFFFFFF)
     {
-        kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+        printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
@@ -1296,7 +1152,7 @@
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1306,7 +1162,7 @@
     pMsg[3] = 0x219;             /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_BROADCAST_MODE;
     /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
    
     /* post to Inbound Post Q */   
 
@@ -1314,23 +1170,19 @@
 
     /* wait for response */
     timeout = 1000000;
-    while(1)
-    {
-        int i;
-        
+    while(1) {
         if (WaitCallback)
             (*WaitCallback)();
 
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+        udelay(10);      /* please don't hog the bus!!! */
             
         if (p32[0] != 0xff)
             break;
             
         if (!timeout--)
         {
-            kprintf("Timeout waiting for promiscuous mode from adapter\n");
-            kprintf("0x%8.8lx\n", p32[0]);
+            printk(KERN_WARNING "(rcpci45 driver:) Timeout waiting for promiscuous mode from adapter\n");
+            printk(KERN_WARNING "(rcpci45 driver:) 0x%8x\n", p32[0]);
             return RC_RTN_NO_LINK_SPEED;
         }
     }
@@ -1356,23 +1208,21 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback)
+RCGetLinkSpeed(struct net_device *dev, PU32 pLinkSpeedCode, 
+	       PFNWAITCALLBACK WaitCallback)
 {
     U32 msgOffset, timeout;
     PU32 pMsg;
     volatile PU32 p32;
     U8 IOPLinkSpeed;
-    PPAB pPab;
-
-    pPab =PCIAdapterBlock[AdapterID];
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
 
     msgOffset = pPab->p_atu->InQueue;
 
-
     if (msgOffset == 0xFFFFFFFF)
     {
-        kprintf("RCGetLinkSpeed(): Inbound Free Q empty!\n");
+        printk(KERN_WARNING "(rcpci45 driver:) RCGetLinkSpeed(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
@@ -1380,7 +1230,7 @@
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1390,7 +1240,7 @@
     pMsg[3] = 0x219;             /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_LINK_SPEED;
     /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
    
     /* post to Inbound Post Q */   
 
@@ -1398,23 +1248,19 @@
 
     /* wait for response */
     timeout = 1000000;
-    while(1)
-    {
-        int i;
-        
+    while(1) {
         if (WaitCallback)
             (*WaitCallback)();
 
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+        udelay(10);      /* please don't hog the bus!!! */
             
         if (p32[0] != 0xff)
             break;
             
         if (!timeout--)
         {
-            kprintf("Timeout waiting for link speed from IOP\n");
-            kprintf("0x%8.8lx\n", p32[0]);
+            dprintk("Timeout waiting for link speed from IOP\n");
+            dprintk("0x%8x\n", p32[0]);
             return RC_RTN_NO_LINK_SPEED;
         }
     }
@@ -1429,7 +1275,7 @@
 
 /*
 ** =========================================================================
-** RCReportDriverCapability(U16 AdapterID, U32 capability)
+** RCReportDriverCapability(struct net_device *dev, U32 capability)
 **
 ** Currently defined bits:
 ** WARM_REBOOT_CAPABLE   0x01
@@ -1437,14 +1283,12 @@
 ** =========================================================================
 */
 RC_RETURN
-RCReportDriverCapability(U16 AdapterID, U32 capability)
+RCReportDriverCapability(struct net_device *dev, U32 capability)
 {
     U32  off;
     PU32 pMsg;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
-    pPab =PCIAdapterBlock[AdapterID];
-     
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -1477,21 +1321,19 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback)
+RCGetFirmwareVer(struct net_device *dev, PU8 pFirmString, 
+		 PFNWAITCALLBACK WaitCallback)
 {
     U32 msgOffset, timeout;
     PU32 pMsg;
     volatile PU32 p32;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
-    pPab =PCIAdapterBlock[AdapterID];
 
     msgOffset = pPab->p_atu->InQueue;
-
-
     if (msgOffset == 0xFFFFFFFF)
     {
-        kprintf("RCGetFirmwareVer(): Inbound Free Q empty!\n");
+        dprintk("RCGetFirmwareVer(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
@@ -1499,7 +1341,7 @@
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
     /* virtual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0xff;
 
     /* setup private message */
@@ -1509,7 +1351,7 @@
     pMsg[3] = 0x219;             /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_FIRMWARE_REV;
     /* phys address to return status - area right after PAB */
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
 
 
    
@@ -1520,22 +1362,18 @@
     
     /* wait for response */
     timeout = 1000000;
-    while(1)
-    {
-        int i;
-        
-        if (WaitCallback)
+    while(1) {
+	if (WaitCallback)
             (*WaitCallback)();
             
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+        udelay(10);     /* please don't hog the bus!!! */
 
         if (p32[0] != 0xff)
             break;
             
         if (!timeout--)
         {
-            kprintf("Timeout waiting for link speed from IOP\n");
+            dprintk("Timeout waiting for link speed from IOP\n");
             return RC_RTN_NO_FIRM_VER;
         }
     }
@@ -1558,17 +1396,15 @@
 ** =========================================================================
 */
 RC_RETURN 
-RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+RCResetLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, 
+	       PFNCALLBACK CallbackFunction)
 {
     unsigned long off;
     PU32 pMsg;
-    PPAB pPab;
-    int i;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
     long timeout = 0;
 
     
-    pPab =PCIAdapterBlock[AdapterID];
-     
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
 
@@ -1595,9 +1431,8 @@
            or until timer goes off */
         while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
         {
-            RCProcI2OMsgQ(AdapterID);
-            for (i = 0; i < 100000; i++)     /* please don't hog the bus!!! */
-                ;
+            RCProcI2OMsgQ(dev);
+            udelay(1000);    /* please don't hog the bus!!! */
             timeout++;
             if (timeout > 10000)
             {
@@ -1619,14 +1454,13 @@
 ** =========================================================================
 */
 RC_RETURN 
-RCResetIOP(U16 AdapterID)
+RCResetIOP(struct net_device *dev)
 {
     U32 msgOffset, timeout;
     PU32 pMsg;
-    PPAB pPab;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
     volatile PU32 p32;
     
-    pPab = PCIAdapterBlock[AdapterID];
     msgOffset = pPab->p_atu->InQueue;
 
     if (msgOffset == 0xFFFFFFFF)
@@ -1644,12 +1478,12 @@
     pMsg[4] = 0; /* universal context */
     pMsg[5] = 0; /* universal context */
     /* phys address to return status - area right after PAB */
-    pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[6] = pPab->outMsgBlockPhyAddr;
     pMsg[7] = 0;
     pMsg[8] = 1;  /*  return 1 byte */
 
     /* virual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0;
     p32[1] = 0;
 
@@ -1659,19 +1493,15 @@
 
     /* wait for response */
     timeout = 1000000;
-    while(1)
-    {
-        int i;
-        
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+    while(1) {        
+        udelay(10);     /* please don't hog the bus!!! */
             
         if (p32[0] || p32[1])
             break;
             
         if (!timeout--)
         {
-            printk("RCResetIOP timeout\n");
+            dprintk("RCResetIOP timeout\n");
             return RC_RTN_MSG_REPLY_TIMEOUT;
         }
     }
@@ -1692,16 +1522,14 @@
 ** =========================================================================
 */
 RC_RETURN 
-RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
+RCShutdownLANCard(struct net_device *dev, U16 ResourceFlags, 
+		  PU32 ReturnAddr, PFNCALLBACK CallbackFunction)
 {
     volatile PU32 pMsg;
     U32 off;
-    PPAB pPab;
-    int i;
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
     long timeout = 0;
 
-    pPab = PCIAdapterBlock[AdapterID];
-
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
 
@@ -1728,13 +1556,12 @@
            or until timer goes off */
         while (pPab->pCallbackFunc == (PFNCALLBACK)NULL)
         {
-            RCProcI2OMsgQ(AdapterID);
-            for (i = 0; i < 100000; i++)     /* please don't hog the bus!!! */
-                ;
+            RCProcI2OMsgQ(dev);
+            udelay(1000);     /* please don't hog the bus!!! */
             timeout++;
             if (timeout > 10000)
             {
-				printk("RCShutdownLANCard(): timeout\n");
+		printk(KERN_WARNING "(rcpci45 driver:) RCShutdownLANCard(): timeout\n");
                 break;
             }
         }
@@ -1758,13 +1585,11 @@
 ** =========================================================================
 */
 RC_RETURN
-RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask)
+RCSetRavlinIPandMask(struct net_device *dev, U32 ipAddr, U32 netMask)
 {
     volatile PU32 pMsg;
     U32 off;
-    PPAB pPab;
-
-    pPab = PCIAdapterBlock[AdapterID];
+    PPAB pPab = ((PDPA)dev->priv)->pPab;
 
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
@@ -1800,21 +1625,17 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask, 
+RCGetRavlinIPandMask(struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, 
                      PFNWAITCALLBACK WaitCallback)
 {
-    unsigned i, timeout;
+    unsigned timeout;
     U32      off;
     PU32     pMsg, p32;
-    PPAB     pPab;
+    PPAB     pPab = ((PDPA)dev->priv)->pPab;
     PATU     p_atu;
     
-#ifdef DEBUG
-    kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
-#endif /* DEBUG */
+    dprintk("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", (u32)pIpAddr, *pIpAddr);
 
-    pPab = PCIAdapterBlock[AdapterID];
-    
     if (pPab == NULL)
         return RC_RTN_ADPTR_NOT_REGISTERED;
     
@@ -1824,26 +1645,22 @@
     if (0xFFFFFFFF == off)
         return RC_RTN_FREE_Q_EMPTY;
 
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     *p32 = 0xFFFFFFFF;
 
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + off);
 
-#ifdef DEBUG
-    kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
-#endif /* DEBUG */
+    dprintk("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", (u32)p_atu, off, (u32)p32);
     /* setup private message */
     pMsg[0] = FIVE_WORD_MSG_SIZE | SGL_OFFSET_0;
     pMsg[1] = I2O_PRIVATE << 24 | I2O_HOST_TID << 12 | RC_LAN_TARGET_ID;
     pMsg[2] = 0;               /* initiator context */
     pMsg[3] = 0x218;           /* transaction context */
     pMsg[4] = RC_PCI45_VENDOR_ID << 16 | RC_PRIVATE_GET_IP_AND_MASK;
-    pMsg[5] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[5] = pPab->outMsgBlockPhyAddr;
 
     p_atu->InQueue = off;   /* send it to the I2O device */
-#ifdef DEBUG
-    kprintf("RCGetRavlinIPandMask: p_atu 0x%08.8ulx, off 0x%08.8ulx, p32 0x%08.8ulx\n", p_atu, off, p32);
-#endif /* DEBUG */
+    dprintk("RCGetRavlinIPandMask: p_atu 0x%08ulx, off 0x%08ulx, p32 0x%08ulx\n", (u32)p_atu, off, (u32)p32);
 
     /* wait for the rcpci45 board to update the info */
     timeout = 100000;
@@ -1851,32 +1668,24 @@
     {
         if (WaitCallback)
             (*WaitCallback)();
-    
-        for (i = 0; i < 1000; i++)
-            ;
+
+	udelay(10);
 
         if (!timeout--)
         {
-#ifdef DEBUG
-            kprintf("RCGetRavlinIPandMask: Timeout\n");
-#endif /* DEBUG */
+            dprintk("RCGetRavlinIPandMask: Timeout\n");
             return RC_RTN_MSG_REPLY_TIMEOUT;
         }
     }
 
-#ifdef DEBUG
-    kprintf("RCGetRavlinIPandMask: after time out\n", \
-            "p32[0] (IpAddr) 0x%08.8ulx, p32[1] (IPmask) 0x%08.8ulx\n", p32[0], p32[1]);
-#endif /* DEBUG */
+    dprintk("RCGetRavlinIPandMask: after time out\np32[0] (IpAddr) 0x%08ulx, p32[1] (IPmask) 0x%08ulx\n", p32[0], p32[1]);
     
     /* send IP and mask to user's space  */
     *pIpAddr  = p32[0];
     *pNetMask = p32[1];
 
 
-#ifdef DEBUG
-    kprintf("RCGetRavlinIPandMask: pIpAddr is 0x%08.8ulx, *IpAddr is 0x%08.8ulx\n", pIpAddr, *pIpAddr);
-#endif /* DEBUG */
+    dprintk("RCGetRavlinIPandMask: pIpAddr is 0x%08ulx, *IpAddr is 0x%08ulx\n", (u32)pIpAddr, *pIpAddr);
 
     return RC_RTN_NO_ERROR;
 }
@@ -1911,9 +1720,7 @@
     
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        kprintf("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
+        dprintk("SendI2OOutboundQInitMsg(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
     
@@ -1921,9 +1728,7 @@
     /* calc virual address of msg - virual already mapped to physical */    
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
-#ifdef DEBUG
-    kprintf("SendI2OOutboundQInitMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
-#endif /* DEBUG */
+    dprintk("SendI2OOutboundQInitMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", (u32)pMsg, msgOffset);
 
     pMsg[0] = EIGHT_WORD_MSG_SIZE | TRL_OFFSET_6;
     pMsg[1] = I2O_EXEC_OUTBOUND_INIT << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
@@ -1933,10 +1738,10 @@
     pMsg[5] = MSG_FRAME_SIZE  << 16 | 0x80; /* outbound msg frame size and Initcode */
     pMsg[6] = 0xD0000004;       /* simple sgl element LE, EOB */
     /* phys address to return status - area right after PAB */
-    pMsg[7] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[7] = pPab->outMsgBlockPhyAddr;
 
     /* virual pointer to return buffer - clear first two dwords */
-    p32 = (PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0;
     
     /* post to Inbound Post Q */   
@@ -1946,17 +1751,14 @@
     timeout = 100000;
     while(1)
     {
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+        udelay(10);      /* please don't hog the bus!!! */
             
         if (p32[0])
             break;
             
         if (!timeout--)
         {
-#ifdef DEBUG
-            kprintf("Timeout wait for InitOutQ InPrgress status from IOP\n");
-#endif /* DEBUG */
+            dprintk("Timeout wait for InitOutQ InPrgress status from IOP\n");
             return RC_RTN_NO_I2O_STATUS;
         }
     }
@@ -1964,17 +1766,14 @@
     timeout = 100000;
     while(1)
     {
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+	udelay(10);    /* please don't hog the bus!!! */
             
         if (p32[0] == I2O_EXEC_OUTBOUND_INIT_COMPLETE)
             break;
 
         if (!timeout--)
         {
-#ifdef DEBUG
-            kprintf("Timeout wait for InitOutQ Complete status from IOP\n");
-#endif /* DEBUG */
+            dprintk("Timeout wait for InitOutQ Complete status from IOP\n");
             return RC_RTN_NO_I2O_STATUS;
         }
     }
@@ -2008,14 +1807,10 @@
     
     
     msgOffset = pPab->p_atu->InQueue; 
-#ifdef DEBUG
-    printk("GetI2OStatus: msg offset = 0x%x\n", msgOffset);
-#endif /* DEBUG */
+    dprintk("GetI2OStatus: msg offset = 0x%x\n", msgOffset);
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        kprintf("GetI2OStatus(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
+        dprintk("GetI2OStatus(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
@@ -2029,64 +1824,50 @@
     pMsg[4] = 0; /* universal context */
     pMsg[5] = 0; /* universal context */
     /* phys address to return status - area right after PAB */
-    pMsg[6] = pPab->outMsgBlockPhyAddr - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB); 
+    pMsg[6] = pPab->outMsgBlockPhyAddr;
     pMsg[7] = 0;
     pMsg[8] = 88;  /*  return 88 bytes */
 
     /* virual pointer to return buffer - clear first two dwords */
-    p32 = (volatile PU32)(pPab->pLinOutMsgBlock - ADAPTER_BLOCK_RESERVED_SPACE + sizeof(PAB));
+    p32 = (volatile PU32)pPab->pLinOutMsgBlock;
     p32[0] = 0;
     p32[1] = 0;
 
-#ifdef DEBUG
-    kprintf("GetI2OStatus - pMsg:0x%08.8ulx, msgOffset:0x%08.8ulx, [1]:0x%08.8ulx, [6]:0x%08.8ulx\n",
-            pMsg, msgOffset, pMsg[1], pMsg[6]);
-#endif /* DEBUG */
+    dprintk("GetI2OStatus - pMsg:0x%08ulx, msgOffset:0x%08ulx, [1]:0x%08ulx, [6]:0x%08ulx\n",
+            (u32)pMsg, msgOffset, pMsg[1], pMsg[6]);
    
     /* post to Inbound Post Q */   
     pPab->p_atu->InQueue = msgOffset;
     
-#ifdef DEBUG
-    kprintf("Return status to p32 = 0x%08.8ulx\n", p32);
-#endif /* DEBUG */
+    dprintk("Return status to p32 = 0x%08ulx\n", (u32)p32);
     
     /* wait for response */
     timeout = 1000000;
-    while(1)
-    {
-        int i;
-        
-        for (i = 0; i < 1000; i++)      /* please don't hog the bus!!! */
-            ;
+    while(1) {
+        udelay(10);      /* please don't hog the bus!!! */
             
         if (p32[0] && p32[1])
             break;
             
         if (!timeout--)
         {
-#ifdef DEBUG
-            kprintf("Timeout waiting for status from IOP\n");
-            kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
-            kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
-            kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
-#endif /* DEBUG */
+            dprintk("Timeout waiting for status from IOP\n");
+            dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]);
+            dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]);
+            dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], p32[10], p32[11]);
             return RC_RTN_NO_I2O_STATUS;
         }
     }
             
-#ifdef DEBUG
-    kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
-    kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
-    kprintf("0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[8], p32[9], p32[10], p32[11]);
-#endif /* DEBUG */
+    dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]);
+    dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]);
+    dprintk("0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[8], p32[9], p32[10], p32[11]);
     /* get IOP state */
     pPab->IOPState = ((volatile PU8)p32)[10];
     pPab->InboundMFrameSize  = ((volatile PU16)p32)[6];
     
-#ifdef DEBUG
-    kprintf("IOP state 0x%02.2x InFrameSize = 0x%04.4x\n", 
+    dprintk("IOP state 0x%02x InFrameSize = 0x%04x\n", 
             pPab->IOPState, pPab->InboundMFrameSize);
-#endif /* DEBUG */
     return RC_RTN_NO_ERROR;
 }
 
@@ -2101,25 +1882,21 @@
 static int 
 SendEnableSysMsg(PPAB pPab)
 {
-    U32 msgOffset; // timeout;
+    U32 msgOffset; 
     volatile PU32 pMsg;
 
     msgOffset = pPab->p_atu->InQueue;
 
     if (msgOffset == 0xFFFFFFFF)
     {
-#ifdef DEBUG
-        kprintf("SendEnableSysMsg(): Inbound Free Q empty!\n");
-#endif /* DEBUG */
+        dprintk("SendEnableSysMsg(): Inbound Free Q empty!\n");
         return RC_RTN_FREE_Q_EMPTY;
     }
 
     /* calc virual address of msg - virual already mapped to physical */
     pMsg = (PU32)(pPab->pPci45LinBaseAddr + msgOffset);
 
-#ifdef DEBUG
-    kprintf("SendEnableSysMsg - pMsg = 0x%08.8ulx, InQ msgOffset = 0x%08.8ulx\n", pMsg, msgOffset);
-#endif /* DEBUG */
+    dprintk("SendEnableSysMsg - pMsg = 0x%08ulx, InQ msgOffset = 0x%08ulx\n", (u32)pMsg, msgOffset);
 
     pMsg[0] = FOUR_WORD_MSG_SIZE | SGL_OFFSET_0;
     pMsg[1] = I2O_EXEC_SYS_ENABLE << 24 | I2O_HOST_TID << 12 | I2O_IOP_TID;
@@ -2160,12 +1937,10 @@
     pMsg = pMsgFrame;
     nmbrDwords = 0;
 
-#ifdef DEBUG
-    kprintf("FillI2OMsgSGLFromTCBX\n");
-    kprintf("TCB  0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n",
+    dprintk("FillI2OMsgSGLFromTCBX\n");
+    dprintk("TCB  0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n",
             pTCB[0], pTCB[1], pTCB[2], pTCB[3], pTCB[4]);
-    kprintf("pTCB 0x%08.8ulx, pMsg 0x%08.8ulx\n", pTCB, pMsg);
-#endif /* DEBUG */
+    dprintk("pTCB 0x%08ulx, pMsg 0x%08ulx\n", (u32)pTCB, (u32)pMsg);
     
     nmbrBuffers = *pTCB++;
     
@@ -2245,23 +2020,19 @@
 {
     PU8 p8Msg;
     PU32 p32;
-    //  U16 count;
+/*      U16 count; */
     
     
     p8Msg = pPab->pLinOutMsgBlock + (phyAddrMsg - pPab->outMsgBlockPhyAddr);
     p32 = (PU32)p8Msg;
     
-#ifdef DEBUG
-    kprintf("VXD: ProcessOutboundI2OMsg - pPab 0x%08.8ulx, phyAdr 0x%08.8ulx, linAdr 0x%08.8ulx\n", pPab, phyAddrMsg, p8Msg);
-    kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[0], p32[1], p32[2], p32[3]);
-    kprintf("msg :0x%08.8ulx:0x%08.8ulx:0x%08.8ulx:0x%08.8ulx\n", p32[4], p32[5], p32[6], p32[7]);
-#endif /* DEBUG */
+    dprintk("VXD: ProcessOutboundI2OMsg - pPab 0x%08ulx, phyAdr 0x%08ulx, linAdr 0x%08ulx\n", (u32)pPab, phyAddrMsg, (u32)p8Msg);
+    dprintk("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[0], p32[1], p32[2], p32[3]);
+    dprintk("msg :0x%08ulx:0x%08ulx:0x%08ulx:0x%08ulx\n", p32[4], p32[5], p32[6], p32[7]);
 
     if (p32[4] >> 24 != I2O_REPLY_STATUS_SUCCESS)
     {
-#ifdef DEBUG
-        kprintf("Message reply status not success\n");
-#endif /* DEBUG */
+        dprintk("Message reply status not success\n");
         return;
     }
     
@@ -2269,36 +2040,26 @@
     {
     case I2O_EXEC_SYS_TAB_SET:
         msgFlag = 1;
-#ifdef DEBUG
-        kprintf("Received I2O_EXEC_SYS_TAB_SET reply\n");
-#endif /* DEBUG */
+        dprintk("Received I2O_EXEC_SYS_TAB_SET reply\n");
         break;
 
     case I2O_EXEC_HRT_GET:
         msgFlag = 1;
-#ifdef DEBUG
-        kprintf("Received I2O_EXEC_HRT_GET reply\n");
-#endif /* DEBUG */
+        dprintk("Received I2O_EXEC_HRT_GET reply\n");
         break;
         
     case I2O_EXEC_LCT_NOTIFY:
         msgFlag = 1;
-#ifdef DEBUG
-        kprintf("Received I2O_EXEC_LCT_NOTIFY reply\n");
-#endif /* DEBUG */
+        dprintk("Received I2O_EXEC_LCT_NOTIFY reply\n");
         break;
         
     case I2O_EXEC_SYS_ENABLE:
         msgFlag = 1;
-#ifdef DEBUG
-        kprintf("Received I2O_EXEC_SYS_ENABLE reply\n");
-#endif /* DEBUG */
+        dprintk("Received I2O_EXEC_SYS_ENABLE reply\n");
         break;
 
     default:    
-#ifdef DEBUG
-        kprintf("Received UNKNOWN reply\n");
-#endif /* DEBUG */
+        dprintk("Received UNKNOWN reply\n");
         break;
     }
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/rclanmtl.h linux/drivers/net/rclanmtl.h
--- v2.4.1/linux/drivers/net/rclanmtl.h	Mon Dec 11 13:01:09 2000
+++ linux/drivers/net/rclanmtl.h	Sun Feb  4 10:05:30 2001
@@ -39,34 +39,31 @@
 
 /* Linux specific includes */
 #include <asm/types.h>
-#define kprintf printk
 #ifdef RC_LINUX_MODULE     /* linux modules need non-library version of string functions */
 #include <linux/string.h>
 #else
 #include <string.h>
 #endif
+#include <linux/delay.h> /* for udelay() */
 
-/* PCI/45 Configuration space values */
-#define RC_PCI45_VENDOR_ID  0x4916
-#define RC_PCI45_DEVICE_ID  0x1960
+#include <linux/netdevice.h>
+#include <linux/if_ether.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
 
+#include <asm/io.h>
 
- /* RedCreek API function return values */
-#define RC_RTN_NO_ERROR             0
-#define RC_RTN_I2O_NOT_INIT         1
-#define RC_RTN_FREE_Q_EMPTY         2
-#define RC_RTN_TCB_ERROR            3
-#define RC_RTN_TRANSACTION_ERROR    4
-#define RC_RTN_ADAPTER_ALREADY_INIT 5
-#define RC_RTN_MALLOC_ERROR         6
-#define RC_RTN_ADPTR_NOT_REGISTERED 7
-#define RC_RTN_MSG_REPLY_TIMEOUT    8
-#define RC_RTN_NO_I2O_STATUS        9
-#define RC_RTN_NO_FIRM_VER         10
-#define RC_RTN_NO_LINK_SPEED       11
+/* Debug stuff. Define for debug output */
+#define RCDEBUG
 
-/* Driver capability flags */
-#define WARM_REBOOT_CAPABLE      0x01
+#ifdef RCDEBUG
+#define dprintk(args...) printk(KERN_DEBUG "(rcpci45 driver:) " args)
+#else
+#define dprintk(args...) { }
+#endif
+
+
+/* Typedefs */
 
  /* scalar data types */
 typedef __u8		U8;
@@ -78,7 +75,6 @@
 typedef unsigned long   BF;
 typedef int             RC_RETURN;
 
-
  /* 
  ** type PFNWAITCALLBACK
  **
@@ -116,7 +112,7 @@
                               U8   PktCount,
                               U32  BucketsRemain,
                               PU32 PacketDescBlock,
-                              U16  AdapterID);
+                              struct net_device *);
 
  /* 
  ** type PFNCALLBACK 
@@ -129,7 +125,105 @@
 typedef void (*PFNCALLBACK)(U32  Status,
                               U32  Param1,
                               U32  Param2,
-                              U16  AdapterID);
+                              struct net_device *dev);
+
+/*
+**  Message Unit CSR definitions for RedCreek PCI45 board
+*/
+typedef struct tag_rcatu 
+{
+    volatile unsigned long APICRegSel;  /* APIC Register Select */
+    volatile unsigned long reserved0;
+    volatile unsigned long APICWinReg;  /* APIC Window Register */
+    volatile unsigned long reserved1;
+    volatile unsigned long InMsgReg0;   /* inbound message register 0 */
+    volatile unsigned long InMsgReg1;   /* inbound message register 1 */
+    volatile unsigned long OutMsgReg0;  /* outbound message register 0 */
+    volatile unsigned long OutMsgReg1;  /* outbound message register 1 */
+    volatile unsigned long InDoorReg;   /* inbound doorbell register */
+    volatile unsigned long InIntStat;   /* inbound interrupt status register */
+    volatile unsigned long InIntMask;   /* inbound interrupt mask register */
+    volatile unsigned long OutDoorReg;  /* outbound doorbell register */
+    volatile unsigned long OutIntStat;  /* outbound interrupt status register */
+    volatile unsigned long OutIntMask;  /* outbound interrupt mask register */
+    volatile unsigned long reserved2;
+    volatile unsigned long reserved3;
+    volatile unsigned long InQueue;     /* inbound queue port */
+    volatile unsigned long OutQueue;    /* outbound queue port */
+    volatile unsigned long reserved4;
+    volatile unsigned long reserver5;
+    /* RedCreek extension */
+    volatile unsigned long EtherMacLow;
+    volatile unsigned long EtherMacHi;
+    volatile unsigned long IPaddr;
+    volatile unsigned long IPmask;
+} *PATU;
+
+ /* 
+ ** typedef PAB
+ **
+ ** PCI Adapter Block - holds instance specific information.
+ */
+typedef struct
+{
+    PATU             p_atu;                /* ptr to  ATU register block */
+    PU8              pPci45LinBaseAddr;
+    PU8              pLinOutMsgBlock;
+    U32              outMsgBlockPhyAddr; 
+    PFNTXCALLBACK    pTransCallbackFunc;
+    PFNRXCALLBACK    pRecvCallbackFunc;
+    PFNCALLBACK      pRebootCallbackFunc;
+    PFNCALLBACK      pCallbackFunc;
+    U16              IOPState;
+    U16              InboundMFrameSize;
+} *PPAB;
+
+/*
+ * Driver Private Area, DPA.
+ */
+typedef struct
+{
+    U8     id;                        /* the AdapterID */
+
+    /* These two field are basically for the RCioctl function.
+     * I could not determine if they could be avoided. (RAA)*/
+    U32    pci_addr;               /* the pci address of the adapter */
+    U32    pci_addr_len;
+
+    struct timer_list timer;        /*  timer */
+    struct net_device_stats  stats; /* the statistics structure */
+    unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
+    unsigned char shutdown;
+    unsigned char reboot;
+    unsigned char nexus;
+    PU8    msgbuf;            /* Pointer to Lan Api Private Area */
+    PU8    PLanApiPA;         /* Pointer to Lan Api Private Area (aligned) */
+    PPAB   pPab;              /* Pointer to the PCI Adapter Block */
+} *PDPA;
+
+
+
+/* PCI/45 Configuration space values */
+#define RC_PCI45_VENDOR_ID  0x4916
+#define RC_PCI45_DEVICE_ID  0x1960
+
+
+ /* RedCreek API function return values */
+#define RC_RTN_NO_ERROR             0
+#define RC_RTN_I2O_NOT_INIT         1
+#define RC_RTN_FREE_Q_EMPTY         2
+#define RC_RTN_TCB_ERROR            3
+#define RC_RTN_TRANSACTION_ERROR    4
+#define RC_RTN_ADAPTER_ALREADY_INIT 5
+#define RC_RTN_MALLOC_ERROR         6
+#define RC_RTN_ADPTR_NOT_REGISTERED 7
+#define RC_RTN_MSG_REPLY_TIMEOUT    8
+#define RC_RTN_NO_I2O_STATUS        9
+#define RC_RTN_NO_FIRM_VER         10
+#define RC_RTN_NO_LINK_SPEED       11
+
+/* Driver capability flags */
+#define WARM_REBOOT_CAPABLE      0x01
 
 /*
 ** Status - Transmit and Receive callback status word 
@@ -298,21 +392,15 @@
  ** transport layer.  This buffer must be a contigous memory block of a 
  ** minimum of 16K bytes and long word aligned.  The user also must provide
  ** the base address of the RedCreek PCI adapter assigned by BIOS or operating
- ** system.  The user provided value AdapterID is a zero based index of the
- ** Ravlin 45/PCI adapter.  This interface number is used in all subsequent API
- ** calls to identify which adpapter for which the function is intended.  
- ** Up to sixteen interfaces are supported with this API.
- **
- ** Inputs:  AdapterID - interface number from 0 to 15
- **          pciBaseAddr - virual base address of PCI (set by BIOS)
- **          p_msgbuf - virual address to private message block (min. 16K)
- **          p_phymsgbuf - physical address of private message block
+ ** system.  
+ **
+ ** Inputs:  dev - the net_device struct for the device.
  **          TransmitCallbackFunction - address of user's TX callback function
  **          ReceiveCallbackFunction  - address of user's RX callback function
+ **          RebootCallbackFunction  - address of user's reboot callback function
  **
  */
-RC_RETURN RCInitI2OMsgLayer(U16 AdapterID, U32 pciBaseAddr, 
-                            PU8 p_msgbuf,  PU8 p_phymsgbuf,
+RC_RETURN RCInitI2OMsgLayer(struct net_device *dev,
                             PFNTXCALLBACK TransmitCallbackFunction,
                             PFNRXCALLBACK ReceiveCallbackFunction,
                             PFNCALLBACK   RebootCallbackFunction);
@@ -327,7 +415,7 @@
  ** 0x04030201 and 0x00FFFFFF on a little endian machine.
  **
  */
-RC_RETURN RCSetRavlinIPandMask(U16 AdapterID, U32 ipAddr, U32 netMask);
+RC_RETURN RCSetRavlinIPandMask(struct net_device *dev, U32 ipAddr, U32 netMask);
 
 
 /*
@@ -339,7 +427,7 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetRavlinIPandMask(U16 AdapterID, PU32 pIpAddr, PU32 pNetMask, 
+RCGetRavlinIPandMask(struct net_device *dev, PU32 pIpAddr, PU32 pNetMask, 
                         PFNWAITCALLBACK WaitCallback);
 
  /* 
@@ -351,7 +439,7 @@
  ** callback functions, TransmitCallbackFunction or ReceiveCallbackFunction,
  ** if a TX or RX transaction has completed.
  */
-void RCProcI2OMsgQ(U16 AdapterID);
+void RCProcI2OMsgQ(struct net_device *dev);
 
 
  /*
@@ -362,8 +450,8 @@
  ** will prevent hardware interrupt to host even though the outbound I2O msg
  ** queue is not emtpy.
  */
-RC_RETURN RCEnableI2OInterrupts(U16 adapterID);
-RC_RETURN RCDisableI2OInterrupts(U16 AdapterID);
+RC_RETURN RCEnableI2OInterrupts(struct net_device *dev);
+RC_RETURN RCDisableI2OInterrupts(struct net_device *dev);
 
 
  /* 
@@ -378,7 +466,7 @@
  ** to the RedCreek adapter are considered owned by the adapter until the
  ** context is return to user through the ReceiveCallbackFunction.
  */
-RC_RETURN RCPostRecvBuffers(U16 AdapterID, PRCTCB pTransactionCtrlBlock);
+RC_RETURN RCPostRecvBuffers(struct net_device *dev, PRCTCB pTransactionCtrlBlock);
 #define MAX_NMBR_POST_BUFFERS_PER_MSG 32
 
  /*
@@ -391,7 +479,7 @@
  ** Transmit buffer are considered owned by the adapter until context's
  ** returned to user through the TransmitCallbackFunction.
  */
-RC_RETURN RCI2OSendPacket(U16 AdapterID, 
+RC_RETURN RCI2OSendPacket(struct net_device *dev, 
                           U32 context, 
                           PRCTCB pTransactionCtrlBlock);
 
@@ -425,7 +513,7 @@
  ** If given, not NULL, the function WaitCallback is called during the wait
  ** loop while waiting for the adapter to respond.
  */
-RC_RETURN RCGetLinkStatistics(U16 AdapterID,
+RC_RETURN RCGetLinkStatistics(struct net_device *dev,
                               P_RCLINKSTATS StatsReturnAddr,
                               PFNWAITCALLBACK WaitCallback);
 
@@ -436,7 +524,7 @@
  ** If given, not NULL, the function WaitCallback is called during the wait
  ** loop while waiting for the adapter to respond.
  */
-RC_RETURN RCGetLinkStatus(U16 AdapterID, 
+RC_RETURN RCGetLinkStatus(struct net_device *dev, 
                           PU32 pReturnStatus,
                           PFNWAITCALLBACK WaitCallback);
                                
@@ -453,7 +541,7 @@
  ** adapter runs in promiscous mode because of the dual address requirement.
  ** The MAC address is returned to the unsigned char array pointer to by mac.
  */
-RC_RETURN RCGetMAC(U16 AdapterID, PU8 mac, PFNWAITCALLBACK WaitCallback);
+RC_RETURN RCGetMAC(struct net_device *dev, PFNWAITCALLBACK WaitCallback);
 
  /*
  ** RCSetMAC()
@@ -461,14 +549,14 @@
  ** Set a new user port MAC address.  This address will be returned on
  ** subsequent RCGetMAC() calls.
  */
-RC_RETURN RCSetMAC(U16 AdapterID, PU8 mac);
+RC_RETURN RCSetMAC(struct net_device *dev, PU8 mac);
 
  /*
  ** RCSetLinkSpeed()
  **
  ** set adapter's link speed based on given input code.
  */
-RC_RETURN RCSetLinkSpeed(U16 AdapterID, U16 LinkSpeedCode);
+RC_RETURN RCSetLinkSpeed(struct net_device *dev, U16 LinkSpeedCode);
  /* Set link speed codes */
 #define LNK_SPD_AUTO_NEG_NWAY   0
 #define LNK_SPD_100MB_FULL      1
@@ -492,10 +580,10 @@
 #define LNK_SPD_10MB_HALF       4
 
 RC_RETURN
-RCGetLinkSpeed(U16 AdapterID, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
+RCGetLinkSpeed(struct net_device *dev, PU32 pLinkSpeedCode, PFNWAITCALLBACK WaitCallback);
 /*
 ** =========================================================================
-** RCSetPromiscuousMode(U16 AdapterID, U16 Mode)
+** RCSetPromiscuousMode(struct net_device *dev, U16 Mode)
 **
 ** Defined values for Mode:
 **  0 - turn off promiscuous mode
@@ -506,10 +594,10 @@
 #define PROMISCUOUS_MODE_OFF 0
 #define PROMISCUOUS_MODE_ON  1
 RC_RETURN
-RCSetPromiscuousMode(U16 AdapterID, U16 Mode);
+RCSetPromiscuousMode(struct net_device *dev, U16 Mode);
 /*
 ** =========================================================================
-** RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+** RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback)
 **
 ** get promiscuous mode setting
 **
@@ -520,11 +608,11 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetPromiscuousMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+RCGetPromiscuousMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback);
 
 /*
 ** =========================================================================
-** RCSetBroadcastMode(U16 AdapterID, U16 Mode)
+** RCSetBroadcastMode(struct net_device *dev, U16 Mode)
 **
 ** Defined values for Mode:
 **  0 - turn off promiscuous mode
@@ -535,10 +623,10 @@
 #define BROADCAST_MODE_OFF 0
 #define BROADCAST_MODE_ON  1
 RC_RETURN
-RCSetBroadcastMode(U16 AdapterID, U16 Mode);
+RCSetBroadcastMode(struct net_device *dev, U16 Mode);
 /*
 ** =========================================================================
-** RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback)
+** RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback)
 **
 ** get broadcast mode setting
 **
@@ -549,10 +637,10 @@
 ** =========================================================================
 */
 RC_RETURN
-RCGetBroadcastMode(U16 AdapterID, PU32 pMode, PFNWAITCALLBACK WaitCallback);
+RCGetBroadcastMode(struct net_device *dev, PU32 pMode, PFNWAITCALLBACK WaitCallback);
 /*
 ** =========================================================================
-** RCReportDriverCapability(U16 AdapterID, U32 capability)
+** RCReportDriverCapability(struct net_device *dev, U32 capability)
 **
 ** Currently defined bits:
 ** WARM_REBOOT_CAPABLE   0x01
@@ -560,7 +648,7 @@
 ** =========================================================================
 */
 RC_RETURN
-RCReportDriverCapability(U16 AdapterID, U32 capability);
+RCReportDriverCapability(struct net_device *dev, U32 capability);
 
 /*
 ** RCGetFirmwareVer()
@@ -570,7 +658,7 @@
 ** WARNING: user's space pointed to by pFirmString should be at least 60 bytes.
 */
 RC_RETURN
-RCGetFirmwareVer(U16 AdapterID, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
+RCGetFirmwareVer(struct net_device *dev, PU8 pFirmString, PFNWAITCALLBACK WaitCallback);
 
 /*
 ** ----------------------------------------------
@@ -601,7 +689,7 @@
  ** operation if the receive buffers were returned during LANReset.
  ** Note: The IOP status is not affected by a LAN reset.
  */
-RC_RETURN RCResetLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+RC_RETURN RCResetLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
 
 
  /*
@@ -623,7 +711,7 @@
  ** Note: The IOP status is not affected by a LAN shutdown.
  */                                      
 RC_RETURN 
-RCShutdownLANCard(U16 AdapterID, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
+RCShutdownLANCard(struct net_device *dev, U16 ResourceFlags, PU32 ReturnAddr, PFNCALLBACK CallbackFunction);
 
  /*
  ** RCResetIOP();
@@ -633,6 +721,6 @@
  **     Clears outbound message Q. 
  */
 RC_RETURN 
-RCResetIOP(U16 AdapterID);
+RCResetIOP(struct net_device *dev);
 
 #endif /* RCLANMTL_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/rcpci45.c linux/drivers/net/rcpci45.c
--- v2.4.1/linux/drivers/net/rcpci45.c	Mon Jan  1 10:17:49 2001
+++ linux/drivers/net/rcpci45.c	Tue Feb 13 13:15:05 2001
@@ -15,12 +15,6 @@
 ** 
 ** None known at this time.
 **
-**  TODO:
-**      -Get rid of the wait loops in the API and replace them
-**       with system independent delays ...something like
-**       "delayms(2)".  However, under normal circumstances, the 
-**       delays are very short so they're not a problem.
-**
 **  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
@@ -36,7 +30,8 @@
 **  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 **
 **   
-**  Rasmus Andersen, December 2000: Converted to new PCI API.
+**  Rasmus Andersen, December 2000: Converted to new PCI API and general
+**  cleanup.
 **
 **  Pete Popov, January 11,99: Fixed a couple of 2.1.x problems 
 **  (virt_to_bus() not called), tested it under 2.2pre5 (as a module), and 
@@ -58,19 +53,14 @@
 #include <linux/in.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/timer.h>
 #include <asm/irq.h>            /* For NR_IRQS only. */
 #include <asm/bitops.h>
-#include <asm/io.h>
 #include <asm/uaccess.h>
 
-#include <linux/if_ether.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
 
 
 static char version[] __initdata =
@@ -83,7 +73,6 @@
 #define RUN_AT(x) (jiffies + (x))
 
 #define NEW_MULTICAST
-#include <linux/delay.h>
 
 /* PCI/45 Configuration space values */
 #define RC_PCI45_VENDOR_ID  0x4916
@@ -106,38 +95,7 @@
 
 static void rc_timer(unsigned long);
 
-/*
- * Driver Private Area, DPA.
- */
-typedef struct
-{
-
-    /* 
-     *    pointer to the device structure which is part
-     * of the interface to the Linux kernel.
-     */
-    struct net_device *dev;            
-     
-    U8     id;                        /* the AdapterID */
-    U32    pci_addr;               /* the pci address of the adapter */
-    U32    bus;
-    U32    function;
-    struct timer_list timer;        /*  timer */
-    struct net_device_stats  stats; /* the statistics structure */
-    unsigned long numOutRcvBuffers;/* number of outstanding receive buffers*/
-    unsigned char shutdown;
-    unsigned char reboot;
-    unsigned char nexus;
-    PU8    PLanApiPA;             /* Pointer to Lan Api Private Area */
-
-}
-DPA, *PDPA;
-
-#define MAX_ADAPTERS 32
-
-static PDPA  PCIAdapters[MAX_ADAPTERS];
-
-static int RCinit(struct net_device *dev);
+static int RCinit(struct net_device *);
 
 static int RCopen(struct net_device *);
 static int RC_xmit_packet(struct sk_buff *, struct net_device *);
@@ -146,35 +104,39 @@
 static struct net_device_stats *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 void RCxmit_callback(U32, U16, PU32, struct net_device *);
+static void RCrecv_callback(U32, U8, U32, PU32, struct net_device *);
+static void RCreset_callback(U32, U32, U32, struct net_device *);
+static void RCreboot_callback(U32, U32, U32, struct net_device *);
 static int RC_allocate_and_post_buffers(struct net_device *, int);
 
 
 static struct pci_device_id rcpci45_pci_table[] __devinitdata = {
-	{ RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-	{0, }
+	{ RC_PCI45_VENDOR_ID, RC_PCI45_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, },
+	{ }
 };
 MODULE_DEVICE_TABLE(pci, rcpci45_pci_table);
 
-static void rcpci45_remove_one(struct pci_dev *pdev)
+static void __exit rcpci45_remove_one(struct pci_dev *pdev)
 {
 	struct net_device *dev = pdev->driver_data;
 	PDPA pDpa = dev->priv;
 
         if (!dev) {
-                printk (KERN_ERR "remove non-existent device\n");
+                printk (KERN_ERR "(rcpci45 driver:) remove non-existent device\n");
                 return;
         }
 
-	printk("IOP reset: 0x%x\n", RCResetIOP(pDpa->id));
+	dprintk("remove_one: IOP reset: 0x%x\n", RCResetIOP(dev));
 
-	unregister_netdev(dev);
+	/* RAA Inspired by starfire.c and yellowfin.c we keep these
+	 * here. */
+  	unregister_netdev(dev);
+	free_irq(dev->irq, dev); 
 	iounmap((void *)dev->base_addr);
-        free_irq(dev->irq, dev);
-
+	kfree(pDpa->PLanApiPA);
+	kfree(pDpa->pPab);
+	kfree(pDpa);
 	kfree(dev);
 }
 
@@ -192,18 +154,16 @@
 static int rcpci45_init_one(struct pci_dev *pdev, 
 			    const struct pci_device_id *ent)
 {
-    int dev_size = 32768;        
-    unsigned long *vaddr=0;
+    unsigned long *vaddr;
     PDPA pDpa;
-    int init_status;
-
-    long memaddr = pci_resource_start(pdev, 0);
-    int card_idx;    
+    int error = -ENOMEM;
+    static int card_idx = -1;
     struct net_device *dev;
+    unsigned long pci_start = pci_resource_start(pdev,0);
+    unsigned long pci_len = pci_resource_len(pdev,0);
+    
 
-    static int card_counter = 0;
-
-    card_idx = card_counter++; /* Yeah, icky hack. */
+    card_idx++;
 
     /* 
      * Allocate and fill new device structure. 
@@ -214,111 +174,80 @@
      * the LAN API layer.
      */
 
-    dev = (struct net_device *) kmalloc(dev_size, GFP_DMA | GFP_KERNEL |GFP_ATOMIC);
-    if (!dev)
-    {
-        printk("rcpci45 driver: unable to kmalloc dev struct\n");
-        return 1;   
+    dev = init_etherdev(NULL, sizeof(*pDpa));
+    if (!dev) {
+	printk(KERN_ERR "(rcpci45 driver:) unable to allocate in init_etherdev\n");
+	goto err_out;
     }
-    memset(dev, 0, dev_size);
 
     pdev->driver_data = dev;
-
-    /*
-     * dev->priv will point to the start of DPA.
-     */
-    dev->priv = (void *)(((long)dev + sizeof(struct net_device) + 15) & ~15);
-
-#ifdef RCDEBUG
-    printk("rc: dev = 0x%x, dev->priv = 0x%x\n", (uint)dev, (uint)dev->priv);
-#endif
     
     pDpa = dev->priv;
+    pDpa->id = card_idx;
+    pDpa->pci_addr = pci_start;
 
-    pDpa->dev = dev;            /* this is just for easy reference */
-    pDpa->function = pdev->devfn;
-    pDpa->bus = (unsigned char)pdev->bus->number;
-    pDpa->id = card_idx;        /* the device number */
-    pDpa->pci_addr = memaddr;
-    PCIAdapters[card_idx] = pDpa;
-
-#ifdef RCDEBUG
-    printk("rc: pDpa = 0x%x, id = %d \n", (uint)pDpa, (uint)pDpa->id);
-#endif
+    if (!pci_start || !(pci_resource_flags(pdev, 0) & IORESOURCE_MEM)) {
+	printk(KERN_ERR "(rcpci45 driver:) No PCI memory resources! Aborting.\n");
+	goto err_out_free_dev;
+    }    
 
     /*
      * Save the starting address of the LAN API private area.  We'll
      * pass that to RCInitI2OMsgLayer().
      */
-    pDpa->PLanApiPA = (void *)(((long)pDpa + sizeof(DPA) + 0xff) & ~0xff);
-#ifdef RCDEBUG
-    printk("rc: pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
-#endif
+    /* RAA FIXME: This size should be a #define somewhere after I
+     * clear up some questions: What flags are neeeded in the alloc below
+     * and what needs to be done before the memarea is long word aligned?
+     * (Look in old code for an approach.) (Also note that the 16K below
+     * is substantially less than the 32K allocated before (even though
+     * some of the spacce was used for data structures.) */
+    pDpa->msgbuf = kmalloc(16384, GFP_KERNEL);
+    if (!pDpa->msgbuf) {
+        printk(KERN_ERR "(rcpci45 driver:) Could not allocate %d byte memory for the private msgbuf!\n", 16384); /* RAA FIXME not hardcoded! */
+	goto err_out_free_dev;
+    }
+    pDpa->PLanApiPA = (void *)(((long)pDpa->msgbuf + 0xff) & ~0xff);
+
+    dprintk("pDpa->PLanApiPA = 0x%x\n", (uint)pDpa->PLanApiPA);
     
-    /* The adapter is accessable through memory-access read/write, not
+    /* The adapter is accessible through memory-access read/write, not
      * I/O read/write.  Thus, we need to map it to some virtual address
-     * area in order to access the registers are normal memory.
-     */
-    vaddr = (ulong *) ioremap (memaddr, 2*32768);
-#ifdef RCDEBUG
-    printk("rc: RCfound_device: 0x%x, priv = 0x%x, vaddr = 0x%x\n", 
-           (uint)dev, (uint)dev->priv, (uint)vaddr);
-#endif
-    dev->base_addr = (unsigned long)vaddr;
-    dev->irq = pdev->irq;
-
-    /*
-     * Request a shared interrupt line.
+     * area in order to access the registers as normal memory.
      */
-    if ( request_irq(dev->irq, (void *)RCinterrupt,
-                     SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev) )
-    {
-        printk( "RC PCI 45: %s: unable to get IRQ %d\n", (PU8)dev->name, (uint)dev->irq );
-        iounmap(vaddr);
-        kfree(dev);
-        return 1;
+    if (request_mem_region(pci_start, pci_len, dev->name) == NULL) {
+        printk(KERN_ERR "(rcpci45 driver:) %d: resource 0x%lx @ 0x%lx busy, aborting\n",card_idx, pci_start, pci_len);
+	goto err_out_free_msgbuf;
     }
 
-    init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr, 
-                  pDpa->PLanApiPA, (PU8)virt_to_bus((void *)pDpa->PLanApiPA),
-                  (PFNTXCALLBACK)RCxmit_callback,
-                  (PFNRXCALLBACK)RCrecv_callback,
-                  (PFNCALLBACK)RCreboot_callback);
-    if (init_status)
-    {
-        printk("rc: Unable to initialize msg layer\n");
-        free_irq(dev->irq, dev);
-        iounmap(vaddr);
-        kfree(dev);
-        return 1;
+    if (pci_enable_device(pdev)) {
+        printk(KERN_ERR "(rcpci45 driver:) %d: unable to enable pci device, aborting\n",card_idx);
+	goto err_out_free_msgbuf;
     }
-    if (RCGetMAC(pDpa->id, dev->dev_addr, NULL))
-    {
-        printk("rc: Unable to get adapter MAC\n");
-        free_irq(dev->irq, dev);
-        iounmap(vaddr);
-        kfree(dev);
-        return 1;
+
+    vaddr = (ulong *) ioremap (pci_start, pci_len); 
+    if (!vaddr) {
+        printk(KERN_ERR "(rcpci45 driver:) Unable to remap address range from %lu to %lu\n", pci_start, pci_start+pci_len);
+	goto err_out_free_msgbuf;
     }
 
-    DriverControlWord |= WARM_REBOOT_CAPABLE;
-    RCReportDriverCapability(pDpa->id, DriverControlWord);
+    dprintk("rcpci45_init_one: 0x%x, priv = 0x%x, vaddr = 0x%x\n", 
+           (uint)dev, (uint)dev->priv, (uint)vaddr);
+    dev->base_addr = (unsigned long)vaddr;
+    dev->irq = pdev->irq;
 
     dev->init = &RCinit;
-    ether_setup(dev);            /* linux kernel interface */
-
-    if (register_netdev(dev) != 0) /* linux kernel interface */
-    {
-        printk("rc: unable to register device \n");
-        free_irq(dev->irq, dev);
-        iounmap(vaddr);
-        kfree(dev);
-        return 1;
-    }
-    printk("%s: RedCreek Communications IPSEC VPN adapter\n",
-        dev->name);
 
     return 0; /* success */
+
+
+ err_out_free_msgbuf:
+    kfree(pDpa->msgbuf);
+ err_out_free_dev:
+    kfree(dev);
+ err_out:
+    unregister_netdev(dev);
+    card_idx--;
+    return error;
 }
 
 static struct pci_driver rcpci45_driver = {
@@ -328,12 +257,12 @@
 	remove: rcpci45_remove_one,
 };
 
-static int __init rcpci_init_module (void)
+static int __init rcpci_init_module(void)
 {
 	int rc = pci_module_init(&rcpci45_driver);
 
 	if (!rc)
-		printk(version);
+		printk(KERN_INFO "%s",version);
 	return rc;
 }
 
@@ -344,14 +273,42 @@
     PDPA pDpa = (PDPA) dev->priv;
     int count = 0;
     int requested = 0;
+    int error;
 
-#ifdef RCDEBUG
-    printk("rc: RCopen\n");
-#endif
-    RCEnableI2OInterrupts(pDpa->id);
+    dprintk("(rcpci45 driver:) RCopen\n");
 
-    if (pDpa->nexus)
-    {
+    /* Request a shared interrupt line. */
+    if ( (error=request_irq(dev->irq, (void *)RCinterrupt,
+                     SA_INTERRUPT|SA_SHIRQ, "RedCreek VPN Adapter", dev)) ) {
+        printk(KERN_ERR "(rcpci45 driver:) %s: unable to get IRQ %d\n", dev->name, dev->irq );
+	goto err_out;
+    }
+
+    error = RCInitI2OMsgLayer(dev, (PFNTXCALLBACK)RCxmit_callback,
+			      (PFNRXCALLBACK)RCrecv_callback,
+			      (PFNCALLBACK)RCreboot_callback);
+    if (error) {
+        printk(KERN_ERR "(rcpci45 driver:) Unable to initialize msg layer\n");
+	goto err_out_free_irq;
+    }
+    if ( (error=RCGetMAC(dev, NULL)) ) {
+        printk(KERN_ERR "(rcpci45 driver:) Unable to get adapter MAC\n");
+	goto err_out_free_irq;
+    }
+
+    DriverControlWord |= WARM_REBOOT_CAPABLE;
+    RCReportDriverCapability(dev, DriverControlWord);
+
+    printk(KERN_INFO "%s: RedCreek Communications IPSEC VPN adapter\n",
+        dev->name);
+
+
+    /* RAA: Old RCopen starts here */
+    RCEnableI2OInterrupts(dev);
+
+    /* RAA Hmm, how does the comment below jibe with the newly imported
+     * code above? A FIXME!!*/
+    if (pDpa->nexus) {
         /* This is not the first time RCopen is called.  Thus,
          * the interface was previously opened and later closed
          * by RCclose().  RCclose() does a Shutdown; to wake up
@@ -361,16 +318,12 @@
          * were turned off -- we need will need to reinitialize
          * the adapter, rather than simply waking it up.  
          */
-        printk("rc: Waking up adapter...\n");
-        RCResetLANCard(pDpa->id,0,0,0);
-    }
-    else
-    {
+	dprintk(KERN_INFO "Waking up adapter...\n");
+        RCResetLANCard(dev,0,0,0);
+    } else
         pDpa->nexus = 1;
-    }
 
-    while(post_buffers)
-    {
+    while(post_buffers) {
         if (post_buffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
             requested = MAX_NMBR_POST_BUFFERS_PER_MSG;
         else
@@ -382,25 +335,26 @@
             /*
              * Check to see if we were able to post any buffers at all.
              */
-            if (post_buffers == MAX_NMBR_RCV_BUFFERS)
-            {
-                printk("rc: Error RCopen: not able to allocate any buffers\r\n");
+            if (post_buffers == MAX_NMBR_RCV_BUFFERS) {
+                printk(KERN_ERR "(rcpci45 driver:) Error RCopen: not able to allocate any buffers\r\n");
                 return(-ENOMEM);                    
             }
-            printk("rc: Warning RCopen: not able to allocate all requested buffers\r\n");
+            printk(KERN_WARNING "(rcpci45 driver:) Warning RCopen: not able to allocate all requested buffers\r\n");
             break;            /* we'll try to post more buffers later */
-        }
-        else
+        } else
             post_buffers -= count;
     }
     pDpa->numOutRcvBuffers = MAX_NMBR_RCV_BUFFERS - post_buffers;
     pDpa->shutdown = 0;        /* just in case */
-#ifdef RCDEBUG
-    printk("rc: RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
-#endif
+    dprintk("RCopen: posted %d buffers\n", (uint)pDpa->numOutRcvBuffers);
     MOD_INC_USE_COUNT;
     netif_start_queue(dev);
     return 0;
+
+ err_out_free_irq:
+    free_irq(dev->irq, dev);
+ err_out:
+    return error;
 }
 
 static int
@@ -414,11 +368,8 @@
    
     netif_stop_queue(dev);
      
-    if (pDpa->shutdown || pDpa->reboot)
-    {
-#ifdef RCDEBUG
-            printk("rc: RC_xmit_packet: tbusy!\n");
-#endif
+    if (pDpa->shutdown || pDpa->reboot) {
+            dprintk("RC_xmit_packet: tbusy!\n");
             return 1;
     }
       
@@ -440,20 +391,13 @@
     ptcb->b.size = skb->len;
     ptcb->b.addr = virt_to_bus((void *)skb->data);
 
-#ifdef RCDEBUG
-    printk("rc: RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", 
+    dprintk("RC xmit: skb = 0x%x, pDpa = 0x%x, id = %d, ptcb = 0x%x\n", 
            (uint)skb, (uint)pDpa, (uint)pDpa->id, (uint)ptcb);
-#endif
-    if ( (status = RCI2OSendPacket(pDpa->id, (U32)NULL, (PRCTCB)ptcb))
-         != RC_RTN_NO_ERROR)
-    {
-#ifdef RCDEBUG
-        printk("rc: RC send error 0x%x\n", (uint)status);
-#endif
+    if ( (status = RCI2OSendPacket(dev, (U32)NULL, (PRCTCB)ptcb))
+         != RC_RTN_NO_ERROR) {
+        dprintk("RC send error 0x%x\n", (uint)status);
         return 1;
-    }
-    else
-    {
+    } else {
         dev->trans_start = jiffies;
         netif_wake_queue(dev);
     }
@@ -477,103 +421,77 @@
 RCxmit_callback(U32 Status, 
                 U16 PcktCount, 
                 PU32 BufferContext, 
-                U16 AdapterID)
+                struct net_device *dev)
 {
     struct sk_buff *skb;
-    PDPA pDpa;
-    struct net_device *dev;
+    PDPA pDpa = dev->priv;
 
-        pDpa = PCIAdapters[AdapterID];
-        if (!pDpa)
-        {
-            printk("rc: Fatal error: xmit callback, !pDpa\n");
+    if (!pDpa) {
+            printk(KERN_ERR "(rcpci45 driver:) Fatal error: xmit callback, !pDpa\n");
             return;
-        }
-        dev = pDpa->dev;
+    }
 
-        // printk("xmit_callback: Status = 0x%x\n", (uint)Status);
-        if (Status != I2O_REPLY_STATUS_SUCCESS)
-        {
-            printk("rc: xmit_callback: Status = 0x%x\n", (uint)Status);
-        }
-#ifdef RCDEBUG
-        if (pDpa->shutdown || pDpa->reboot)
-            printk("rc: xmit callback: shutdown||reboot\n");
-#endif
-
-#ifdef RCDEBUG     
-        printk("rc: xmit_callback: PcktCount = %d, BC = 0x%x\n", 
-               (uint)PcktCount, (uint)BufferContext);
-#endif
-        while (PcktCount--)
-        {
+/*      dprintk("xmit_callback: Status = 0x%x\n", (uint)Status); */
+    if (Status != I2O_REPLY_STATUS_SUCCESS)
+            dprintk("xmit_callback: Status = 0x%x\n", (uint)Status);
+    if (pDpa->shutdown || pDpa->reboot)
+            dprintk("xmit callback: shutdown||reboot\n");
+
+    dprintk("xmit_callback: PcktCount = %d, BC = 0x%x\n", 
+	   (uint)PcktCount, (uint)BufferContext);
+
+    while (PcktCount--) {
             skb = (struct sk_buff *)(BufferContext[0]);
-#ifdef RCDEBUG
-            printk("rc: skb = 0x%x\n", (uint)skb);
-#endif
+            dprintk("skb = 0x%x\n", (uint)skb);
             BufferContext++;
             dev_kfree_skb_irq(skb);
-        }
-	netif_wake_queue(dev);
+    }
+    netif_wake_queue(dev);
 }
 
 static void
-RCreset_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+RCreset_callback(U32 Status, U32 p1, U32 p2, struct net_device *dev)
 {
-    PDPA pDpa;
-    struct net_device *dev;
+    PDPA pDpa = dev->priv;
      
-    pDpa = PCIAdapters[AdapterID];
-    dev = pDpa->dev;
-#ifdef RCDEBUG
-    printk("rc: RCreset_callback Status 0x%x\n", (uint)Status);
-#endif
+    dprintk("RCreset_callback Status 0x%x\n", (uint)Status);
     /*
      * Check to see why we were called.
      */
-    if (pDpa->shutdown)
-    {
-        printk("rc: Shutting down interface\n");
+    if (pDpa->shutdown) {
+        printk(KERN_INFO "(rcpci45 driver:) Shutting down interface\n");
         pDpa->shutdown = 0;
         pDpa->reboot = 0;
         MOD_DEC_USE_COUNT; 
-    }
-    else if (pDpa->reboot)
-    {
-        printk("rc: reboot, shutdown adapter\n");
+    } else if (pDpa->reboot) {
+        printk(KERN_INFO "(rcpci45 driver:) reboot, shutdown adapter\n");
         /*
          * We don't set any of the flags in RCShutdownLANCard()
          * and we don't pass a callback routine to it.
          * The adapter will have already initiated the reboot by
          * the time the function returns.
          */
-        RCDisableI2OInterrupts(pDpa->id);
-        RCShutdownLANCard(pDpa->id,0,0,0);
-        printk("rc: scheduling timer...\n");
+        RCDisableI2OInterrupts(dev);
+        RCShutdownLANCard(dev,0,0,0);
+        printk(KERN_INFO "(rcpci45 driver:) scheduling timer...\n");
         init_timer(&pDpa->timer);
         pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 4 sec. */
         pDpa->timer.data = (unsigned long)dev;
         pDpa->timer.function = &rc_timer;    /* timer handler */
         add_timer(&pDpa->timer);
     }
-
-
-
 }
 
 static void
-RCreboot_callback(U32 Status, U32 p1, U32 p2, U16 AdapterID)
+RCreboot_callback(U32 Status, U32 p1, U32 p2, struct net_device *dev)
 {
-    PDPA pDpa;
+    PDPA pDpa = dev->priv;
     
-    pDpa = PCIAdapters[AdapterID];
-#ifdef RCDEBUG
-    printk("rc: RCreboot: rcv buffers outstanding = %d\n", 
+    dprintk("RCreboot: rcv buffers outstanding = %d\n", 
            (uint)pDpa->numOutRcvBuffers);
-#endif
-    if (pDpa->shutdown)
-    {
-        printk("rc: skipping reboot sequence -- shutdown already initiated\n");
+
+    if (pDpa->shutdown) {
+        printk(KERN_INFO "(rcpci45 driver:) skipping reboot sequence -- shutdown already initiated\n");
         return;
     }
     pDpa->reboot = 1;
@@ -587,8 +505,7 @@
      * schedule a timer callback routine to execute 3 seconds 
      * later; this routine will reinitialize the adapter at that time.
      */
-    RCResetLANCard(pDpa->id, 
-                   RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
+    RCResetLANCard(dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
                    RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
                    (PFNCALLBACK)RCreset_callback);
 }
@@ -615,66 +532,51 @@
                 U8   PktCount, 
                 U32  BucketsRemain, 
                 PU32 PacketDescBlock, 
-                U16  AdapterID)
+                struct net_device *dev)
 {
 
     U32 len, count;
-    PDPA pDpa;
+    PDPA pDpa = dev->priv;
     struct sk_buff *skb;
-    struct net_device *dev;
     singleTCB tcb;
     psingleTCB ptcb = &tcb;
 
 
-        pDpa = PCIAdapters[AdapterID];
-        dev = pDpa->dev;
-
-        ptcb->bcount = 1;
-
-#ifdef RCDEBUG
-        printk("rc: RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
-               (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);
-#endif
-        
-#ifdef RCDEBUG
-        if ((pDpa->shutdown || pDpa->reboot) && !Status)
-            printk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
-#endif
+    ptcb->bcount = 1;
+    
+    dprintk("RCrecv_callback: 0x%x, 0x%x, 0x%x\n",
+	   (uint)PktCount, (uint)BucketsRemain, (uint)PacketDescBlock);
 
-        if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
-        {
+    if ((pDpa->shutdown || pDpa->reboot) && !Status)
+            dprintk("shutdown||reboot && !Status: PktCount = %d\n",PktCount);
+    
+    if ( (Status != I2O_REPLY_STATUS_SUCCESS) || pDpa->shutdown)
+    {
             /*
              * Free whatever buffers the adapter returned, but don't
              * pass them to the kernel.
              */
-        
-                if (!pDpa->shutdown && !pDpa->reboot)
-                    printk("rc: RCrecv error: status = 0x%x\n", (uint)Status);
-#ifdef RCDEBUG
+	    
+	    if (!pDpa->shutdown && !pDpa->reboot)
+                    printk(KERN_INFO "(rcpci45 driver:) RCrecv error: status = 0x%x\n", (uint)Status);
                 else
-                    printk("rc: Returning %d buffers, status = 0x%x\n", 
+			dprintk("Returning %d buffers, status = 0x%x\n", 
                            PktCount, (uint)Status);
-#endif
             /*
              * TO DO: check the nature of the failure and put the adapter in
              * failed mode if it's a hard failure.  Send a reset to the adapter
              * and free all outstanding memory.
              */
             if (Status == I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER)
-            {
-#ifdef RCDEBUG
-                printk("RCrecv status ABORT NO DATA TRANSFER\n");
-#endif
-            }
+                dprintk("RCrecv status ABORT NO DATA TRANSFER\n");
+
             /* check for reset status: I2O_REPLY_STATUS_ABORT_NO_DATA_TRANSFER */ 
             if (PacketDescBlock)
             {
                 while(PktCount--)
                 {
                     skb = (struct sk_buff *)PacketDescBlock[0];
-#ifdef RCDEBUG
-                    printk("free skb 0x%p\n", skb);
-#endif
+                    dprintk("free skb 0x%p\n", skb);
                     dev_kfree_skb (skb);
                     pDpa->numOutRcvBuffers--;
                     PacketDescBlock += BD_SIZE; /* point to next context field */
@@ -687,14 +589,12 @@
             while(PktCount--)
             {
                 skb = (struct sk_buff *)PacketDescBlock[0];
-#ifdef RCDEBUG
                 if (pDpa->shutdown)
-                    printk("shutdown: skb=0x%x\n", (uint)skb);
+			dprintk("shutdown: skb=0x%x\n", (uint)skb);
 
-                printk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
+                dprintk("skb = 0x%x: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", (uint)skb,
                        (uint)skb->data[0], (uint)skb->data[1], (uint)skb->data[2],
                        (uint)skb->data[3], (uint)skb->data[4], (uint)skb->data[5]);
-#endif
 
 #ifdef PROMISCUOUS_BY_DEFAULT   /* early 2.x firmware */
                 if ( (memcmp(dev->dev_addr, skb->data, 6)) &&
@@ -711,15 +611,13 @@
                     ptcb->b.size = MAX_ETHER_SIZE;
                     ptcb->b.addr = virt_to_bus((void *)skb->data);
 
-                    if ( RCPostRecvBuffers(pDpa->id, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
+                    if ( RCPostRecvBuffers(dev, (PRCTCB)ptcb ) != RC_RTN_NO_ERROR)
                     {
-                        printk("rc: RCrecv_callback: post buffer failed!\n");
+                        printk(KERN_WARNING "(rcpci45 driver:) RCrecv_callback: post buffer failed!\n");
                         dev_kfree_skb (skb);
                     }
                     else
-                    {
                         pDpa->numOutRcvBuffers++;
-                    }
                 }
                 else
 #endif /* PROMISCUOUS_BY_DEFAULT */
@@ -768,16 +666,14 @@
 
     pDpa = (PDPA) (dev->priv);
      
-#ifdef RCDEBUG
     if (pDpa->shutdown)
-        printk("rc: shutdown: service irq\n");
+        dprintk("shutdown: service irq\n");
 
-    printk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", 
+    dprintk("RC irq: pDpa = 0x%x, dev = 0x%x, id = %d\n", 
            (uint)pDpa, (uint)dev, (uint)pDpa->id);
-    printk("dev = 0x%x\n", (uint)dev);
-#endif
+    dprintk("dev = 0x%x\n", (uint)dev);
 
-    RCProcI2OMsgQ(pDpa->id);
+    RCProcI2OMsgQ(dev);
 }
 
 
@@ -794,12 +690,9 @@
 
     if (pDpa->reboot)
     {
-        init_status = RCInitI2OMsgLayer(pDpa->id, dev->base_addr, 
-                                    pDpa->PLanApiPA, 
-                                    (PU8)virt_to_bus((void *)pDpa->PLanApiPA),
-                                    (PFNTXCALLBACK)RCxmit_callback,
-                                    (PFNRXCALLBACK)RCrecv_callback,
-                                    (PFNCALLBACK)RCreboot_callback);
+        init_status = RCInitI2OMsgLayer(dev, (PFNTXCALLBACK)RCxmit_callback,
+					(PFNRXCALLBACK)RCrecv_callback,
+					(PFNCALLBACK)RCreboot_callback);
 
         switch(init_status)
         {
@@ -807,8 +700,8 @@
  
             pDpa->reboot = 0;
             pDpa->shutdown = 0;        /* just in case */
-            RCReportDriverCapability(pDpa->id, DriverControlWord);
-            RCEnableI2OInterrupts(pDpa->id);
+            RCReportDriverCapability(dev, DriverControlWord);
+            RCEnableI2OInterrupts(dev);
 
             if (dev->flags & IFF_UP)
             {
@@ -825,34 +718,34 @@
                 }
                 pDpa->numOutRcvBuffers = 
                     MAX_NMBR_RCV_BUFFERS - post_buffers;
-                printk("rc: posted %d buffers \r\n", 
+                dprintk("rc: posted %d buffers \r\n", 
                        (uint)pDpa->numOutRcvBuffers);
             }
-            printk("rc: Initialization done.\n");
+            dprintk("Initialization done.\n");
             netif_wake_queue(dev);
             retry=0;
             return;
         case RC_RTN_FREE_Q_EMPTY:
             retry++;
-            printk("rc: inbound free q empty\n");
+            printk(KERN_WARNING "(rcpci45 driver:) inbound free q empty\n");
             break;
         default:
             retry++;
-            printk("rc: bad status after reboot: %d\n", init_status);    
+            printk(KERN_WARNING "(rcpci45 driver:) bad status after reboot: %d\n", init_status);    
             break;
         }
 
         if (retry > REBOOT_REINIT_RETRY_LIMIT)
         {
-            printk("rc: unable to reinitialize adapter after reboot\n");
-            printk("rc: decrementing driver and closing interface\n");
-            RCDisableI2OInterrupts(pDpa->id);
+            printk(KERN_WARNING "(rcpci45 driver:) unable to reinitialize adapter after reboot\n");
+            printk(KERN_WARNING "(rcpci45 driver:) decrementing driver and closing interface\n");
+            RCDisableI2OInterrupts(dev);
             dev->flags &= ~IFF_UP;
             MOD_DEC_USE_COUNT; 
         }
         else
         {
-            printk("rc: rescheduling timer...\n");
+            printk(KERN_INFO "(rcpci45 driver:) rescheduling timer...\n");
             init_timer(&pDpa->timer);
             pDpa->timer.expires = RUN_AT((40*HZ)/10); /* 3 sec. */
             pDpa->timer.data = (unsigned long)dev;
@@ -861,33 +754,26 @@
         }
     }
     else
-    {
-        printk("rc: timer??\n");
-    }
+        printk(KERN_WARNING "(rcpci45 driver:) timer??\n");
 }
 
 static int
 RCclose(struct net_device *dev)
 {
-
     PDPA pDpa = (PDPA) dev->priv;
 
     netif_stop_queue(dev);
     
-#ifdef RCDEBUG
-    printk("rc: RCclose\r\n");
-#endif
+    dprintk("RCclose\r\n");
+
     if (pDpa->reboot)
     {
-        printk("rc: skipping reset -- adapter already in reboot mode\n");
+        printk(KERN_INFO "(rcpci45 driver:) skipping reset -- adapter already in reboot mode\n");
         dev->flags &= ~IFF_UP;
         pDpa->shutdown = 1;
         return 0;
     }
-#ifdef RCDEBUG
-    printk("rc: receive buffers outstanding: %d\n", 
-           (uint)pDpa->numOutRcvBuffers);
-#endif
+    dprintk("receive buffers outstanding: %d\n", (uint)pDpa->numOutRcvBuffers);
 
     pDpa->shutdown = 1;
 
@@ -898,12 +784,11 @@
      * even if there are none.
      */
 
-    RCShutdownLANCard(pDpa->id, 
-                      RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
+    RCShutdownLANCard(dev, RC_RESOURCE_RETURN_POSTED_RX_BUCKETS | 
                       RC_RESOURCE_RETURN_PEND_TX_BUFFERS,0,
                       (PFNCALLBACK)RCreset_callback);
 
-        dev->flags &= ~IFF_UP;
+    dev->flags &= ~IFF_UP;
     return 0;
 }
 
@@ -916,39 +801,35 @@
 
     if (!pDpa)
     {
-        printk("rc: RCget_stats: !pDpa\n");
+	dprintk("RCget_stats: !pDpa\n");
         return 0;
     }
     else if (!(dev->flags & IFF_UP))    
     {
-#ifdef RCDEBUG
-        printk("rc: RCget_stats: device down\n");
-#endif
+	dprintk("RCget_stats: device down\n");
         return 0;
     }
 
     memset(&RCstats, 0, sizeof(RCLINKSTATS));
-    if ( (RCGetLinkStatistics(pDpa->id, &RCstats, (void *)0)) == RC_RTN_NO_ERROR )
+    if ( (RCGetLinkStatistics(dev, &RCstats, (void *)0)) == RC_RTN_NO_ERROR )
     {
-#ifdef RCDEBUG
-        printk("rc: TX_good 0x%x\n", (uint)RCstats.TX_good);
-        printk("rc: TX_maxcol 0x%x\n", (uint)RCstats.TX_maxcol);
-        printk("rc: TX_latecol 0x%x\n", (uint)RCstats.TX_latecol);
-        printk("rc: TX_urun 0x%x\n", (uint)RCstats.TX_urun);
-        printk("rc: TX_crs 0x%x\n", (uint)RCstats.TX_crs);
-        printk("rc: TX_def 0x%x\n", (uint)RCstats.TX_def);
-        printk("rc: TX_singlecol 0x%x\n", (uint)RCstats.TX_singlecol);
-        printk("rc: TX_multcol 0x%x\n", (uint)RCstats.TX_multcol);
-        printk("rc: TX_totcol 0x%x\n", (uint)RCstats.TX_totcol);
-
-        printk("rc: Rcv_good 0x%x\n", (uint)RCstats.Rcv_good);
-        printk("rc: Rcv_CRCerr 0x%x\n", (uint)RCstats.Rcv_CRCerr);
-        printk("rc: Rcv_alignerr 0x%x\n", (uint)RCstats.Rcv_alignerr);
-        printk("rc: Rcv_reserr 0x%x\n", (uint)RCstats.Rcv_reserr);
-        printk("rc: Rcv_orun 0x%x\n", (uint)RCstats.Rcv_orun);
-        printk("rc: Rcv_cdt 0x%x\n", (uint)RCstats.Rcv_cdt);
-        printk("rc: Rcv_runt 0x%x\n", (uint)RCstats.Rcv_runt);
-#endif
+	dprintk("TX_good 0x%x\n", (uint)RCstats.TX_good);
+        dprintk("TX_maxcol 0x%x\n", (uint)RCstats.TX_maxcol);
+        dprintk("TX_latecol 0x%x\n", (uint)RCstats.TX_latecol);
+        dprintk("TX_urun 0x%x\n", (uint)RCstats.TX_urun);
+        dprintk("TX_crs 0x%x\n", (uint)RCstats.TX_crs);
+        dprintk("TX_def 0x%x\n", (uint)RCstats.TX_def);
+        dprintk("TX_singlecol 0x%x\n", (uint)RCstats.TX_singlecol);
+        dprintk("TX_multcol 0x%x\n", (uint)RCstats.TX_multcol);
+        dprintk("TX_totcol 0x%x\n", (uint)RCstats.TX_totcol);
+		 
+        dprintk("Rcv_good 0x%x\n", (uint)RCstats.Rcv_good);
+        dprintk("Rcv_CRCerr 0x%x\n", (uint)RCstats.Rcv_CRCerr);
+        dprintk("Rcv_alignerr 0x%x\n", (uint)RCstats.Rcv_alignerr);
+        dprintk("Rcv_reserr 0x%x\n", (uint)RCstats.Rcv_reserr);
+        dprintk("Rcv_orun 0x%x\n", (uint)RCstats.Rcv_orun);
+        dprintk("Rcv_cdt 0x%x\n", (uint)RCstats.Rcv_cdt);
+        dprintk("Rcv_runt 0x%x\n", (uint)RCstats.Rcv_runt);
 
         pDpa->stats.rx_packets = RCstats.Rcv_good; /* total packets received    */
         pDpa->stats.tx_packets = RCstats.TX_good; /* total packets transmitted    */
@@ -1000,9 +881,7 @@
     RCuser_struct RCuser;
     PDPA pDpa = dev->priv;
 
-#if RCDEBUG
-    printk("RCioctl: cmd = 0x%x\n", cmd);
-#endif
+    dprintk("RCioctl: cmd = 0x%x\n", cmd);
  
     if(!capable(CAP_NET_ADMIN))
     	return -EPERM;
@@ -1023,109 +902,107 @@
         if(copy_from_user(&RCuser, rq->ifr_data, sizeof(RCuser)))
              return -EFAULT;
         
-#ifdef RCDEBUG
-        printk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
-#endif
+        dprintk("RCioctl: RCuser_cmd = 0x%x\n", RCuser.cmd);
   
         switch(RCuser.cmd)
         {
         case RCUC_GETFWVER:
-            printk("RC GETFWVER\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETFWVER\n");
             RCUD_GETFWVER = &RCuser.RCUS_GETFWVER;
-            RCGetFirmwareVer(pDpa->id, (PU8) &RCUD_GETFWVER->FirmString, NULL);
+            RCGetFirmwareVer(dev, (PU8) &RCUD_GETFWVER->FirmString, NULL);
             break;
         case RCUC_GETINFO:
-            printk("RC GETINFO\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETINFO\n");
             RCUD_GETINFO = &RCuser.RCUS_GETINFO;
             RCUD_GETINFO -> mem_start = dev->base_addr;
-            RCUD_GETINFO -> mem_end = dev->base_addr + 2*32768;
-            RCUD_GETINFO -> base_addr = pDpa->pci_addr;
+	    RCUD_GETINFO -> mem_end = dev->base_addr + pDpa->pci_addr_len;
+	    RCUD_GETINFO -> base_addr = pDpa->pci_addr;  
             RCUD_GETINFO -> irq = dev->irq;
             break;
         case RCUC_GETIPANDMASK:
-            printk("RC GETIPANDMASK\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETIPANDMASK\n");
             RCUD_GETIPANDMASK = &RCuser.RCUS_GETIPANDMASK;
-            RCGetRavlinIPandMask(pDpa->id, (PU32) &RCUD_GETIPANDMASK->IpAddr,
+            RCGetRavlinIPandMask(dev, (PU32) &RCUD_GETIPANDMASK->IpAddr,
                                  (PU32) &RCUD_GETIPANDMASK->NetMask, NULL);
             break;
         case RCUC_GETLINKSTATISTICS:
-            printk("RC GETLINKSTATISTICS\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETLINKSTATISTICS\n");
             RCUD_GETLINKSTATISTICS = &RCuser.RCUS_GETLINKSTATISTICS;
-            RCGetLinkStatistics(pDpa->id, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
+            RCGetLinkStatistics(dev, (P_RCLINKSTATS) &RCUD_GETLINKSTATISTICS->StatsReturn, NULL);
             break;
         case RCUC_GETLINKSTATUS:
-            printk("RC GETLINKSTATUS\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETLINKSTATUS\n");
             RCUD_GETLINKSTATUS = &RCuser.RCUS_GETLINKSTATUS;
-            RCGetLinkStatus(pDpa->id, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
+            RCGetLinkStatus(dev, (PU32) &RCUD_GETLINKSTATUS->ReturnStatus, NULL);
             break;
         case RCUC_GETMAC:
-            printk("RC GETMAC\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETMAC\n");
             RCUD_GETMAC = &RCuser.RCUS_GETMAC;
-            RCGetMAC(pDpa->id, (PU8) &RCUD_GETMAC->mac, NULL);
+            RCGetMAC(dev, NULL);
             break;
         case RCUC_GETPROM:
-            printk("RC GETPROM\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETPROM\n");
             RCUD_GETPROM = &RCuser.RCUS_GETPROM;
-            RCGetPromiscuousMode(pDpa->id, (PU32) &RCUD_GETPROM->PromMode, NULL);
+            RCGetPromiscuousMode(dev, (PU32) &RCUD_GETPROM->PromMode, NULL);
             break;
         case RCUC_GETBROADCAST:
-            printk("RC GETBROADCAST\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETBROADCAST\n");
             RCUD_GETBROADCAST = &RCuser.RCUS_GETBROADCAST;
-            RCGetBroadcastMode(pDpa->id, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL);
+            RCGetBroadcastMode(dev, (PU32) &RCUD_GETBROADCAST->BroadcastMode, NULL);
             break;
         case RCUC_GETSPEED:
-            printk("RC GETSPEED\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC GETSPEED\n");
             if (!(dev->flags & IFF_UP))    
             {
-                printk("RCioctl, GETSPEED error: interface down\n");
+                printk(KERN_ERR "(rcpci45 driver:) RCioctl, GETSPEED error: interface down\n");
                 return -ENODATA;
             }
             RCUD_GETSPEED = &RCuser.RCUS_GETSPEED;
-            RCGetLinkSpeed(pDpa->id, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
-            printk("RC speed = 0x%u\n", RCUD_GETSPEED->LinkSpeedCode);
+            RCGetLinkSpeed(dev, (PU32) &RCUD_GETSPEED->LinkSpeedCode, NULL);
+            printk(KERN_INFO "(rcpci45 driver:) RC speed = 0x%u\n", RCUD_GETSPEED->LinkSpeedCode);
             break;
         case RCUC_SETIPANDMASK:
-            printk("RC SETIPANDMASK\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC SETIPANDMASK\n");
             RCUD_SETIPANDMASK = &RCuser.RCUS_SETIPANDMASK;
-            printk ("RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
+            printk (KERN_INFO "(rcpci45 driver:) RC New IP Addr = %d.%d.%d.%d, ", (U8) ((RCUD_SETIPANDMASK->IpAddr) & 0xff),
                     (U8) ((RCUD_SETIPANDMASK->IpAddr >>  8) & 0xff),
                     (U8) ((RCUD_SETIPANDMASK->IpAddr >> 16) & 0xff),
                     (U8) ((RCUD_SETIPANDMASK->IpAddr >> 24) & 0xff));
-            printk ("RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
+            printk (KERN_INFO "(rcpci45 driver:) RC New Mask = %d.%d.%d.%d\n", (U8) ((RCUD_SETIPANDMASK->NetMask) & 0xff),
                     (U8) ((RCUD_SETIPANDMASK->NetMask >>  8) & 0xff),
                     (U8) ((RCUD_SETIPANDMASK->NetMask >> 16) & 0xff),
                     (U8) ((RCUD_SETIPANDMASK->NetMask >> 24) & 0xff));
-            RCSetRavlinIPandMask(pDpa->id, (U32) RCUD_SETIPANDMASK->IpAddr,
+            RCSetRavlinIPandMask(dev, (U32) RCUD_SETIPANDMASK->IpAddr,
                                  (U32) RCUD_SETIPANDMASK->NetMask);
             break;
         case RCUC_SETMAC:
-            printk("RC SETMAC\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC SETMAC\n");
             RCUD_SETMAC = &RCuser.RCUS_SETMAC;
-            printk ("RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
+            printk (KERN_INFO "(rcpci45 driver:) RC New MAC addr = %02X:%02X:%02X:%02X:%02X:%02X\n",
                     (U8) (RCUD_SETMAC->mac[0]), (U8) (RCUD_SETMAC->mac[1]), (U8) (RCUD_SETMAC->mac[2]),
                     (U8) (RCUD_SETMAC->mac[3]), (U8) (RCUD_SETMAC->mac[4]), (U8) (RCUD_SETMAC->mac[5]));
-            RCSetMAC(pDpa->id, (PU8) &RCUD_SETMAC->mac);
+            RCSetMAC(dev, (PU8) &RCUD_SETMAC->mac);
             break;
         case RCUC_SETSPEED:
-            printk("RC SETSPEED\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC SETSPEED\n");
             RCUD_SETSPEED = &RCuser.RCUS_SETSPEED;
-            RCSetLinkSpeed(pDpa->id, (U16) RCUD_SETSPEED->LinkSpeedCode);
-            printk("RC New speed = 0x%x\n", RCUD_SETSPEED->LinkSpeedCode);
+            RCSetLinkSpeed(dev, (U16) RCUD_SETSPEED->LinkSpeedCode);
+            printk(KERN_INFO "(rcpci45 driver:) RC New speed = 0x%x\n", RCUD_SETSPEED->LinkSpeedCode);
             break;
         case RCUC_SETPROM:
-            printk("RC SETPROM\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC SETPROM\n");
             RCUD_SETPROM = &RCuser.RCUS_SETPROM;
-            RCSetPromiscuousMode(pDpa->id,(U16)RCUD_SETPROM->PromMode);
-            printk("RC New prom mode = 0x%x\n", RCUD_SETPROM->PromMode);
+            RCSetPromiscuousMode(dev,(U16)RCUD_SETPROM->PromMode);
+            printk(KERN_INFO "(rcpci45 driver:) RC New prom mode = 0x%x\n", RCUD_SETPROM->PromMode);
             break;
         case RCUC_SETBROADCAST:
-            printk("RC SETBROADCAST\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC SETBROADCAST\n");
             RCUD_SETBROADCAST = &RCuser.RCUS_SETBROADCAST;
-            RCSetBroadcastMode(pDpa->id,(U16)RCUD_SETBROADCAST->BroadcastMode);
-            printk("RC New broadcast mode = 0x%x\n", RCUD_SETBROADCAST->BroadcastMode);
+            RCSetBroadcastMode(dev,(U16)RCUD_SETBROADCAST->BroadcastMode);
+            printk(KERN_INFO "(rcpci45 driver:) RC New broadcast mode = 0x%x\n", RCUD_SETBROADCAST->BroadcastMode);
             break;
         default:
-            printk("RC command default\n");
+            printk(KERN_INFO "(rcpci45 driver:) RC command default\n");
             RCUD_DEFAULT = &RCuser.RCUS_DEFAULT;
             RCUD_DEFAULT -> rc = 0x11223344;
             break;
@@ -1147,14 +1024,14 @@
     /*
      * To be completed ...
       */
-    printk("rc: RCconfig\n");
+    dprintk("RCconfig\n");
     return 0;
     if (dev->flags & IFF_UP)    /* can't act on a running interface */
         return -EBUSY;
 
      /* Don't allow changing the I/O address */
     if (map->base_addr != dev->base_addr) {
-        printk(KERN_WARNING "RC pci45: Change I/O address not implemented\n");
+        printk(KERN_WARNING "(rcpci45 driver:)  Change I/O address not implemented\n");
         return -EOPNOTSUPP;
     }
     return 0;
@@ -1175,54 +1052,46 @@
 {
 
     int i;
-    PDPA pDpa = (PDPA)dev->priv;
     PU32 p;
     psingleB pB;
     struct sk_buff *skb;
     RC_RETURN status;
+    U32 res;
 
     if (!numBuffers)
         return 0;
     else if (numBuffers > MAX_NMBR_POST_BUFFERS_PER_MSG)
     {
-#ifdef RCDEBUG
-        printk("rc: Too many buffers requested!\n");
-        printk("rc: attempting to allocate only 32 buffers\n");
-#endif
+        dprintk("Too many buffers requested!\n");
+        dprintk("attempting to allocate only 32 buffers\n");
         numBuffers = 32;
     }
     
-    p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_ATOMIC);
+    p = (PU32) kmalloc(sizeof(U32) + numBuffers*sizeof(singleB), GFP_KERNEL);
 
-#ifdef RCDEBUG
-    printk("rc: TCB = 0x%x\n", (uint)p);
-#endif
+    dprintk("TCB = 0x%x\n", (uint)p);
 
     if (!p)
     {
-        printk("rc: RCopen: unable to allocate TCB\n");
+        printk(KERN_WARNING "(rcpci45 driver:) RCopen: unable to allocate TCB\n");
         return 0;
     }
 
     p[0] = 0;                              /* Buffer Count */
     pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
 
-#ifdef RCDEBUG
-    printk("rc: p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
-    printk("rc: pB = 0x%x\n", (uint)pB);
-#endif
+    dprintk("p[0] = 0x%x, p = 0x%x, pB = 0x%x\n", (uint)p[0], (uint)p, (uint)pB);
+    dprintk("pB = 0x%x\n", (uint)pB);
 
     for (i=0; i<numBuffers; i++)
     {
         skb = dev_alloc_skb(MAX_ETHER_SIZE+2);
         if (!skb)
         {
-            printk("rc: Doh! RCopen: unable to allocate enough skbs!\n");
+            dprintk("Doh! RCopen: unable to allocate enough skbs!\n");
             if (*p != 0)        /* did we allocate any buffers at all? */
             {
-#ifdef RCDEBUG
-                printk("rc: will post only %d buffers \n", (uint)(*p));
-#endif
+                dprintk("will post only %d buffers \n", (uint)(*p));
                 break;
             }
             else 
@@ -1231,9 +1100,7 @@
                 return 0;
             }
         }
-#ifdef RCDEBUG
-        printk("post 0x%x\n", (uint)skb);
-#endif
+        dprintk("post 0x%x\n", (uint)skb);
         skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
         pB->context = (U32)skb;
         pB->scount = 1;        /* segment count */
@@ -1243,24 +1110,21 @@
         pB++;
     }
 
-    if ( (status = RCPostRecvBuffers(pDpa->id, (PRCTCB)p )) != RC_RTN_NO_ERROR)
+    if ( (status = RCPostRecvBuffers(dev, (PRCTCB)p )) != RC_RTN_NO_ERROR)
     {
-        printk("rc: Post buffer failed with error code 0x%x!\n", status);
+        printk(KERN_WARNING "(rcpci45 driver:) Post buffer failed with error code 0x%x!\n", status);
         pB = (psingleB)((U32)p + sizeof(U32)); /* point to the first buffer */
         while(p[0])
         {
             skb = (struct sk_buff *)pB->context;
-#ifdef RCDEBUG
-            printk("rc: freeing 0x%x\n", (uint)skb);
-#endif
+            dprintk("freeing 0x%x\n", (uint)skb);
             dev_kfree_skb (skb);
             p[0]--;
             pB++;
         }
-#ifdef RCDEBUG
-        printk("rc: freed all buffers, p[0] = %ld\n", p[0]);
-#endif
+        dprintk("freed all buffers, p[0] = %d\n", (uint)p[0]);
     }
+    res = p[0];
     kfree(p);
-    return(p[0]);                /* return the number of posted buffers */
+    return(res);                /* return the number of posted buffers */
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/rrunner.c linux/drivers/net/rrunner.c
--- v2.4.1/linux/drivers/net/rrunner.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/net/rrunner.c	Tue Feb 13 13:15:05 2001
@@ -997,8 +997,9 @@
 
 			netif_rx(skb);		/* send it up */
 
+			dev->last_rx = jiffies;
 			rrpriv->stats.rx_packets++;
-			rrpriv->stats.rx_bytes += skb->len;
+			rrpriv->stats.rx_bytes += pkt_len;
 		}
 	defer:
 		rrpriv->rx_ring[index].mode = 0;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sb1000.c linux/drivers/net/sb1000.c
--- v2.4.1/linux/drivers/net/sb1000.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/sb1000.c	Tue Feb 13 13:15:05 2001
@@ -44,7 +44,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
@@ -76,7 +76,6 @@
 struct sb1000_private {
 	struct sk_buff *rx_skb[NPIDS];
 	short rx_dlen[NPIDS];
-	unsigned int rx_bytes;
 	unsigned int rx_frames;
 	short rx_error_count;
 	short rx_error_dpc_count;
@@ -887,9 +886,9 @@
 	/* datagram completed: send to upper level */
 	skb_trim(skb, dlen);
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 	stats->rx_bytes+=dlen;
 	stats->rx_packets++;
-	lp->rx_bytes += dlen;
 	lp->rx_skb[ns] = 0;
 	lp->rx_session_id[ns] |= 0x40;
 	return 0;
@@ -974,7 +973,6 @@
 	lp->rx_dlen[1] = 0;
 	lp->rx_dlen[2] = 0;
 	lp->rx_dlen[3] = 0;
-	lp->rx_bytes = 0;
 	lp->rx_frames = 0;
 	lp->rx_error_count = 0;
 	lp->rx_error_dpc_count = 0;
@@ -1029,7 +1027,7 @@
 
 	switch (cmd) {
 	case SIOCGCMSTATS:		/* get statistics */
-		stats[0] = lp->rx_bytes;
+		stats[0] = lp->stats.rx_bytes;
 		stats[1] = lp->rx_frames;
 		stats[2] = lp->stats.rx_packets;
 		stats[3] = lp->stats.rx_errors;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/seeq8005.c linux/drivers/net/seeq8005.c
--- v2.4.1/linux/drivers/net/seeq8005.c	Sat Nov 11 18:56:58 2000
+++ linux/drivers/net/seeq8005.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	See the skeleton.c file for further copyright information.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as hamish@zot.apana.org.au
 
@@ -39,7 +39,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <linux/delay.h>
@@ -522,6 +522,7 @@
 
 			skb->protocol=eth_type_trans(skb,dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 			lp->stats.rx_bytes += pkt_len;
 		}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/setup.c linux/drivers/net/setup.c
--- v2.4.1/linux/drivers/net/setup.c	Thu Jan  4 12:50:17 2001
+++ linux/drivers/net/setup.c	Tue Feb 13 13:15:05 2001
@@ -50,7 +50,7 @@
 	int status;	/* non-zero if autoprobe has failed */
 };
  
-struct net_probe pci_probes[] __initdata = {
+static struct net_probe pci_probes[] __initdata = {
 	/*
 	 *	Early setup devices
 	 */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sgiseeq.c linux/drivers/net/sgiseeq.c
--- v2.4.1/linux/drivers/net/sgiseeq.c	Mon Oct 30 12:24:22 2000
+++ linux/drivers/net/sgiseeq.c	Tue Feb 13 13:15:05 2001
@@ -11,7 +11,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 
@@ -325,6 +325,7 @@
 				eth_copy_and_sum(skb, pkt_pointer + 2, len, 0);
 				skb->protocol = eth_type_trans(skb, dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				sp->stats.rx_packets++;
 				sp->stats.rx_bytes += len;
 			} else {
diff -u --recursive --new-file v2.4.1/linux/drivers/net/shaper.c linux/drivers/net/shaper.c
--- v2.4.1/linux/drivers/net/shaper.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/net/shaper.c	Tue Feb 13 13:15:05 2001
@@ -76,7 +76,7 @@
 #include <linux/ptrace.h>
 #include <linux/fcntl.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sis900.c linux/drivers/net/sis900.c
--- v2.4.1/linux/drivers/net/sis900.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/sis900.c	Tue Feb 13 13:15:05 2001
@@ -1,11 +1,11 @@
 /* sis900.c: A SiS 900/7016 PCI Fast Ethernet driver for Linux.
    Copyright 1999 Silicon Integrated System Corporation 
-   Revision:	1.07.07	Nov. 29 2000
+   Revision:	1.07.08	Jan. 8 2001
    
    Modified from the driver which is originally written by Donald Becker.
    
    This software may be used and distributed according to the terms
-   of the GNU Public License (GPL), incorporated herein by reference.
+   of the GNU General Public License (GPL), incorporated herein by reference.
    Drivers based on this skeleton fall under the GPL and must retain
    the authorship (implicit copyright) notice.
    
@@ -18,6 +18,7 @@
    preliminary Rev. 1.0 Jan. 18, 1998
    http://www.sis.com.tw/support/databook.htm
 
+   Rev 1.07.08 Jan.  8 2001 Lei-Chun Chang added RTL8201 PHY support
    Rev 1.07.07 Nov. 29 2000 Lei-Chun Chang added kernel-doc extractable documentation and 630 workaround fix
    Rev 1.07.06 Nov.  7 2000 Jeff Garzik <jgarzik@mandrakesoft.com> some bug fix and cleaning
    Rev 1.07.05 Nov.  6 2000 metapirat<metapirat@gmx.de> contribute media type select by ifconfig
@@ -43,7 +44,7 @@
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
@@ -59,7 +60,7 @@
 #include "sis900.h"
 
 static const char *version =
-"sis900.c: v1.07.07  11/29/2000\n";
+"sis900.c: v1.07.08  1/8/2001\n";
 
 static int max_interrupt_work = 20;
 static int multicast_filter_limit = 128;
@@ -92,6 +93,7 @@
 static void sis900_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
 static void amd79c901_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
 static void ics1893_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
+static void rtl8201_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex);
 
 static struct mii_chip_info {
 	const char * name;
@@ -104,6 +106,7 @@
 	{"AMD 79C901 10BASE-T PHY",  0x0000, 0x35b9, amd79c901_read_mode},
 	{"AMD 79C901 HomePNA PHY",   0x0000, 0x35c8, amd79c901_read_mode},
 	{"ICS 1893 Integrated PHYceiver"   , 0x0015, 0xf441,ics1893_read_mode},
+	{"RTL 8201 10/100Mbps Phyceiver"   , 0x0000, 0x8201,rtl8201_read_mode},
 	{0,},
 };
 
@@ -270,6 +273,7 @@
 	net_dev = init_etherdev(NULL, sizeof(struct sis900_private));
 	if (!net_dev)
 		return -ENOMEM;
+	SET_MODULE_OWNER(net_dev);
 
 	if (!request_region(ioaddr, SIS900_TOTAL_SIZE, net_dev->name)) {
 		printk(KERN_ERR "sis900.c: can't allocate I/O space at 0x%lX\n", ioaddr);
@@ -368,7 +372,8 @@
 
 		/* search our mii table for the current mii */ 
 		for (i = 0; mii_chip_table[i].phy_id1; i++)
-			if (phy_id0 == mii_chip_table[i].phy_id0) {
+			if (phy_id0 == mii_chip_table[i].phy_id0 &&
+			    phy_id1 == mii_chip_table[i].phy_id1) {
 				struct mii_phy * mii_phy;
 
 				printk(KERN_INFO
@@ -606,8 +611,7 @@
 	struct sis900_private *sis_priv = (struct sis900_private *)net_dev->priv;
 	long ioaddr = net_dev->base_addr;
 	u8  revision;
-
-	MOD_INC_USE_COUNT;
+	int ret;
 
 	/* Soft reset the chip. */
 	sis900_reset(net_dev);
@@ -618,10 +622,9 @@
 	    revision == SIS630A_900_REV)
 		sis630_set_eq(net_dev,revision);
 
-	if (request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev)) {
-		MOD_DEC_USE_COUNT;
-		return -EAGAIN;
-	}
+	ret = request_irq(net_dev->irq, &sis900_interrupt, SA_SHIRQ, net_dev->name, net_dev);
+	if (ret)
+		return ret;
 
 	sis900_init_rxfilter(net_dev);
 
@@ -1112,6 +1115,51 @@
 }
 
 /**
+ *	rtl8201_read_mode: - read media mode for rtl8201 phy
+ *	@net_dev: the net device to read mode for
+ *	@phy_addr: mii phy address
+ *	@speed: the transmit speed to be determined
+ *	@duplex: the duplex mode to be determined
+ *
+ *	read MII_STATUS register from rtl8201 phy
+ *	to determine the speed and duplex mode for sis900
+ */
+
+static void rtl8201_read_mode(struct net_device *net_dev, int phy_addr, int *speed, int *duplex)
+{
+	u32 status;
+
+	status = mdio_read(net_dev, phy_addr, MII_STATUS);
+
+	if (status & MII_STAT_CAN_TX_FDX) {
+		*speed = HW_SPEED_100_MBPS;
+		*duplex = FDX_CAPABLE_FULL_SELECTED;
+	}
+	else if (status & MII_STAT_CAN_TX) {
+		*speed = HW_SPEED_100_MBPS;
+		*duplex = FDX_CAPABLE_HALF_SELECTED;
+	}
+	else if (status & MII_STAT_CAN_T_FDX) {
+		*speed = HW_SPEED_10_MBPS;
+		*duplex = FDX_CAPABLE_FULL_SELECTED;
+	}
+	else if (status & MII_STAT_CAN_T) {
+		*speed = HW_SPEED_10_MBPS;
+		*duplex = FDX_CAPABLE_HALF_SELECTED;
+	}
+
+	if (status & MII_STAT_LINK)
+		printk(KERN_INFO "%s: Media Link On %s %s-duplex \n",
+		       net_dev->name,
+		       *speed == HW_SPEED_100_MBPS ?
+		       "100mbps" : "10mbps",
+		       *duplex == FDX_CAPABLE_FULL_SELECTED ?
+		       "full" : "half");
+	else
+		printk(KERN_INFO "%s: Media Link Off\n", net_dev->name);
+}
+
+/**
  *	sis900_tx_timeout: - sis900 transmit timeout routine
  *	@net_dev: the net device to transmit
  *
@@ -1505,8 +1553,6 @@
 	}
 
 	/* Green! Put the chip in low-power mode. */
-
-	MOD_DEC_USE_COUNT;
 
 	return 0;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sk98lin/h/skdrv1st.h linux/drivers/net/sk98lin/h/skdrv1st.h
--- v2.4.1/linux/drivers/net/sk98lin/h/skdrv1st.h	Fri Sep 15 14:34:19 2000
+++ linux/drivers/net/sk98lin/h/skdrv1st.h	Tue Feb 13 13:15:05 2001
@@ -105,7 +105,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/byteorder.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sk_g16.c linux/drivers/net/sk_g16.c
--- v2.4.1/linux/drivers/net/sk_g16.c	Fri Jul 14 12:20:22 2000
+++ linux/drivers/net/sk_g16.c	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
  * Copyright (C) 1994 by PJD Weichmann & SWS Bern, Switzerland
  *
  * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
+ * of the GNU General Public License, incorporated herein by reference.
  *
  * Module         : sk_g16.c
  *
@@ -65,7 +65,7 @@
 #include <linux/fcntl.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h> 
 #include <linux/delay.h>
 #include <asm/system.h>
@@ -1248,7 +1248,7 @@
 {
 	printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name);
 	SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */
-	netif_start_queue(dev);		 /* Clear Transmitter flag */
+	netif_wake_queue(dev);		 /* Clear Transmitter flag */
 	dev->trans_start = jiffies;      /* Mark Start of transmission */
 }
 
@@ -1634,6 +1634,7 @@
 	     */
 
 	    writeb(RX_OWN, rmdp->u.s.status);
+	    dev->last_rx = jiffies;
 	    p->stats.rx_packets++;
 	    p->stats.rx_bytes += len;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sk_g16.h linux/drivers/net/sk_g16.h
--- v2.4.1/linux/drivers/net/sk_g16.h	Wed Aug 10 09:26:18 1994
+++ linux/drivers/net/sk_g16.h	Tue Feb 13 13:15:05 2001
@@ -1,7 +1,7 @@
 /*-
  *
  * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
+ * of the GNU General Public License, incorporated herein by reference.
  *
  * Module         : sk_g16.h
  * Version        : $Revision$  
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sk_mca.c linux/drivers/net/sk_mca.c
--- v2.4.1/linux/drivers/net/sk_mca.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/sk_mca.c	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
 net-3-driver for the SKNET MCA-based cards
 
 This is an extension to the Linux operating system, and is covered by the
-same Gnu Public License that covers that work.
+same GNU General Public License that covers that work.
 
 Copyright 1999 by Alfred Arnold (alfred@ccac.rwth-aachen.de, aarnold@elsa.de)
 
@@ -86,7 +86,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/time.h>
@@ -654,6 +654,7 @@
 				priv->stat.rx_bytes += descr.Len;
 #endif
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 			}
 		}
 
@@ -1157,6 +1158,8 @@
 	/* allocate structure */
 	priv = dev->priv =
 	    (skmca_priv *) kmalloc(sizeof(skmca_priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
 	priv->slot = slot;
 	priv->macbase = base + 0x3fc0;
 	priv->ioregaddr = base + 0x3ff0;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/skfp/skfddi.c linux/drivers/net/skfp/skfddi.c
--- v2.4.1/linux/drivers/net/skfp/skfddi.c	Thu Oct 12 14:19:32 2000
+++ linux/drivers/net/skfp/skfddi.c	Tue Feb 13 13:15:05 2001
@@ -84,7 +84,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
@@ -1958,6 +1958,7 @@
 	skb->dev = bp->dev;	/* pass up device pointer */
 
 	netif_rx(skb);
+	bp->dev->last_rx = jiffies;
 
 	HWM_RX_CHECK(smc, RX_LOW_WATERMARK);
 	return;
@@ -2215,6 +2216,7 @@
 
 	// deliver frame to system
 	skb->protocol = fddi_type_trans(skb, ((skfddi_priv *) & smc->os)->dev);
+	skb->dev->last_rx = jiffies;
 	netif_rx(skb);
 
 	return (0);
diff -u --recursive --new-file v2.4.1/linux/drivers/net/slip.c linux/drivers/net/slip.c
--- v2.4.1/linux/drivers/net/slip.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/net/slip.c	Tue Feb 13 13:15:05 2001
@@ -387,6 +387,7 @@
 	skb->mac.raw=skb->data;
 	skb->protocol=htons(ETH_P_IP);
 	netif_rx(skb);
+	sl->dev->last_rx = jiffies;
 	sl->rx_packets++;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/smc-ultra.c linux/drivers/net/smc-ultra.c
--- v2.4.1/linux/drivers/net/smc-ultra.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/smc-ultra.c	Tue Feb 13 13:15:05 2001
@@ -8,7 +8,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
diff -u --recursive --new-file v2.4.1/linux/drivers/net/smc-ultra32.c linux/drivers/net/smc-ultra32.c
--- v2.4.1/linux/drivers/net/smc-ultra32.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/smc-ultra32.c	Tue Feb 13 13:15:05 2001
@@ -7,7 +7,7 @@
 	version of the card by Paul Gortmaker and Leonard N. Zubkoff.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 Theory of Operation:
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/smc9194.c linux/drivers/net/smc9194.c
--- v2.4.1/linux/drivers/net/smc9194.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/smc9194.c	Tue Feb 13 13:15:05 2001
@@ -4,7 +4,7 @@
  .
  . Copyright (C) 1996 by Erik Stahlman
  . This software may be used and distributed according to the terms
- . of the GNU Public License, incorporated herein by reference.
+ . of the GNU General Public License, incorporated herein by reference.
  .
  . "Features" of the SMC chip:
  .   4608 byte packet memory. ( for the 91C92.  Others have more )
@@ -66,7 +66,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <asm/bitops.h>
@@ -1384,7 +1384,9 @@
 
 		skb->protocol = eth_type_trans(skb, dev );
 		netif_rx(skb);
+		dev->last_rx = jiffies;
 		lp->stats.rx_packets++;
+		lp->stats.rx_bytes += packet_length;
 	} else {
 		/* error ... */
 		lp->stats.rx_errors++;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/smc9194.h linux/drivers/net/smc9194.h
--- v2.4.1/linux/drivers/net/smc9194.h	Thu Apr 11 23:49:39 1996
+++ linux/drivers/net/smc9194.h	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
  . Copyright (C) 1996 by Erik Stahlman 
  .
  . This software may be used and distributed according to the terms
- . of the GNU Public License, incorporated herein by reference.
+ . of the GNU General Public License, incorporated herein by reference.
  .
  . This file contains register information and access macros for 
  . the SMC91xxx chipset.   
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sonic.c linux/drivers/net/sonic.c
--- v2.4.1/linux/drivers/net/sonic.c	Tue Jul 11 11:12:24 2000
+++ linux/drivers/net/sonic.c	Tue Feb 13 13:15:05 2001
@@ -339,6 +339,7 @@
 	    eth_copy_and_sum(skb, pkt_ptr, pkt_len, 0);
 	    skb->protocol=eth_type_trans(skb,dev);
 	    netif_rx(skb);			/* pass the packet to upper layers */
+	    dev->last_rx = jiffies;
 	    lp->stats.rx_packets++;
 	    lp->stats.rx_bytes += pkt_len;
 	    
diff -u --recursive --new-file v2.4.1/linux/drivers/net/strip.c linux/drivers/net/strip.c
--- v2.4.1/linux/drivers/net/strip.c	Tue Jul 11 11:12:24 2000
+++ linux/drivers/net/strip.c	Sun Feb  4 10:05:30 2001
@@ -82,12 +82,9 @@
 /* Header files								*/
 
 #include <linux/config.h>
-
-#ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
-#endif
-
+#include <linux/init.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
 #include <asm/segment.h>
@@ -459,7 +456,7 @@
 /************************************************************************/
 /* Global variables							*/
 
-static struct strip *struct_strip_list = NULL;
+static struct strip *struct_strip_list;
 
 
 /************************************************************************/
@@ -492,7 +489,7 @@
 
 typedef unsigned long InterruptStatus;
 
-extern __inline__ InterruptStatus DisableInterrupts(void)
+static inline InterruptStatus DisableInterrupts(void)
 {
     InterruptStatus x;
     save_flags(x);
@@ -500,7 +497,7 @@
     return(x);
 }
 
-extern __inline__ void RestoreInterrupts(InterruptStatus x)
+static inline void RestoreInterrupts(InterruptStatus x)
 {
     restore_flags(x);
 }
@@ -2589,11 +2586,7 @@
     dev->hard_start_xmit    = strip_xmit;
     dev->hard_header        = strip_header;
     dev->rebuild_header     = strip_rebuild_header;
-    /*  dev->type_trans            unused */
-    /*  dev->set_multicast_list   unused */
     dev->set_mac_address    = dev_set_mac_address;
-    /*  dev->do_ioctl             unused */
-    /*  dev->set_config           unused */
     dev->get_stats          = strip_get_stats;
     return 0;
 }
@@ -2730,9 +2723,7 @@
     tty->termios->c_cflag |= CLOCAL;    /* Ignore modem control signals. */
     tty->termios->c_cflag &= ~HUPCL;    /* Don't close on hup */
 
-#ifdef MODULE
     MOD_INC_USE_COUNT;
-#endif
 
     printk(KERN_INFO "STRIP: device \"%s\" activated\n", strip_info->dev.name);
 
@@ -2760,7 +2751,6 @@
     if (!strip_info || strip_info->magic != STRIP_MAGIC)
         return;
 
-    dev_close(&strip_info->dev);
     unregister_netdev(&strip_info->dev);
 
     tty->disc_data = 0;
@@ -2768,9 +2758,7 @@
     printk(KERN_INFO "STRIP: device \"%s\" closed down\n", strip_info->dev.name);
     strip_free(strip_info);
     tty->disc_data = NULL;
-#ifdef MODULE
     MOD_DEC_USE_COUNT;
-#endif
 }
 
 
@@ -2823,80 +2811,65 @@
 /************************************************************************/
 /* Initialization							*/
 
+static struct tty_ldisc strip_ldisc = {
+	magic:		TTY_LDISC_MAGIC,
+	name:		"strip",
+	open:		strip_open,
+	close:		strip_close,
+	ioctl:		strip_ioctl,
+	receive_buf:	strip_receive_buf,
+	receive_room:	strip_receive_room,
+	write_wakeup:	strip_write_some_more,
+};
+
 /*
  * Initialize the STRIP driver.
  * This routine is called at boot time, to bootstrap the multi-channel
  * STRIP driver
  */
 
-int strip_init_ctrl_dev(struct net_device *dummy)
+static const char signon[] __initdata = KERN_INFO "STRIP: Version %s (unlimited channels)\n";
+
+static int __init strip_init_driver(void)
 {
-    static struct tty_ldisc strip_ldisc;
     int status;
 
-    printk(KERN_INFO "STRIP: Version %s (unlimited channels)\n", StripVersion);
+    printk(signon, StripVersion);
 
     /*
      * Fill in our line protocol discipline, and register it
      */
-
-    memset(&strip_ldisc, 0, sizeof(strip_ldisc));
-    strip_ldisc.magic        = TTY_LDISC_MAGIC;
-    strip_ldisc.flags        = 0;
-    strip_ldisc.open         = strip_open;
-    strip_ldisc.close        = strip_close;
-    strip_ldisc.read         = NULL;
-    strip_ldisc.write        = NULL;
-    strip_ldisc.ioctl        = strip_ioctl;
-    strip_ldisc.poll         = NULL;
-    strip_ldisc.receive_buf  = strip_receive_buf;
-    strip_ldisc.receive_room = strip_receive_room;
-    strip_ldisc.write_wakeup = strip_write_some_more;
-    status = tty_register_ldisc(N_STRIP, &strip_ldisc);
-    if (status != 0)
-    {
+    if ((status = tty_register_ldisc(N_STRIP, &strip_ldisc)))
         printk(KERN_ERR "STRIP: can't register line discipline (err = %d)\n", status);
-    }
 
     /*
      * Register the status file with /proc
      */
-    proc_net_create ("strip", S_IFREG | S_IRUGO, get_status_info);
+    proc_net_create("strip", S_IFREG | S_IRUGO, get_status_info);
 
-#ifdef MODULE
-     return status;
-#else
-
-    /* Return "not found", so that dev_init() will unlink
-     * the placeholder device entry for us.
-     */
-    return -ENODEV;
-#endif
+    return status;
 }
+module_init(strip_init_driver);
 
+static const char signoff[] __exitdata = KERN_INFO "STRIP: Module Unloaded\n";
 
-/************************************************************************/
-/* From here down is only used when compiled as an external module	*/
-
-#ifdef MODULE
-
-int init_module(void)
-{
-    return strip_init_ctrl_dev(0);
-}
-
-void cleanup_module(void)
+static void __exit strip_exit_driver(void)
 {
     int i;
     while (struct_strip_list)
         strip_free(struct_strip_list);
 
     /* Unregister with the /proc/net file here. */
-    proc_net_remove ("strip");
+    proc_net_remove("strip");
 
     if ((i = tty_register_ldisc(N_STRIP, NULL)))
         printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i);
 
-    printk(KERN_INFO "STRIP: Module Unloaded\n");
+    printk(signoff);
 }
-#endif /* MODULE */
+module_exit(strip_exit_driver);
+
+MODULE_AUTHOR("Stuart Cheshire <cheshire@cs.stanford.edu>");
+MODULE_DESCRIPTION("Starmode Radio IP (STRIP) Device Driver");
+MODULE_SUPPORTED_DEVICE("Starmode Radio IP (STRIP) modem");
+
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sun3lance.c linux/drivers/net/sun3lance.c
--- v2.4.1/linux/drivers/net/sun3lance.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/sun3lance.c	Tue Feb 13 13:15:05 2001
@@ -3,7 +3,7 @@
 
   Sun3 Lance ethernet driver, by Sam Creasey (sammy@users.qual.net).  
   This driver is a part of the linux kernel, and is thus distributed
-  under the GNU Public License.
+  under the GNU General Public License.
   
   The values used in LANCE_OBIO and LANCE_IRQ seem to be empirically
   true for the correct IRQ and address of the lance registers.  They
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 #include <linux/ptrace.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
@@ -780,8 +780,9 @@
 
 				skb->protocol = eth_type_trans( skb, dev );
 				netif_rx( skb );
+				dev->last_rx = jiffies;
 				lp->stats.rx_packets++;
-				lp->stats.rx_bytes += skb->len;
+				lp->stats.rx_bytes += pkt_len;
 			}
 		}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sunbmac.c linux/drivers/net/sunbmac.c
--- v2.4.1/linux/drivers/net/sunbmac.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/sunbmac.c	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -864,6 +864,7 @@
 		/* No checksums done by the BigMAC ;-( */
 		skb->protocol = eth_type_trans(skb, bp->dev);
 		netif_rx(skb);
+		bp->dev->last_rx = jiffies;
 		bp->enet_stats.rx_packets++;
 		bp->enet_stats.rx_bytes += len;
 	next:
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sundance.c linux/drivers/net/sundance.c
--- v2.4.1/linux/drivers/net/sundance.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/sundance.c	Tue Feb 13 13:15:05 2001
@@ -84,7 +84,7 @@
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sunhme.c linux/drivers/net/sunhme.c
--- v2.4.1/linux/drivers/net/sunhme.c	Mon Dec 11 12:37:03 2000
+++ linux/drivers/net/sunhme.c	Tue Feb 13 13:15:05 2001
@@ -27,7 +27,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -2088,6 +2088,7 @@
 		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
 
+		dev->last_rx = jiffies;
 		hp->net_stats.rx_packets++;
 		hp->net_stats.rx_bytes += len;
 	next:
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sunlance.c linux/drivers/net/sunlance.c
--- v2.4.1/linux/drivers/net/sunlance.c	Mon Oct 23 21:59:03 2000
+++ linux/drivers/net/sunlance.c	Tue Feb 13 13:15:05 2001
@@ -82,7 +82,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -552,6 +552,7 @@
 					 len, 0);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 		}
 
@@ -723,6 +724,7 @@
 			lance_piocopy_to_skb(skb, &(ib->rx_buf[entry][0]), len);
 			skb->protocol = eth_type_trans(skb, dev);
 			netif_rx(skb);
+			dev->last_rx = jiffies;
 			lp->stats.rx_packets++;
 		}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/sunqe.c linux/drivers/net/sunqe.c
--- v2.4.1/linux/drivers/net/sunqe.c	Mon Oct 23 21:59:03 2000
+++ linux/drivers/net/sunqe.c	Tue Feb 13 13:15:05 2001
@@ -20,7 +20,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/delay.h>
 #include <linux/init.h>
@@ -438,6 +438,7 @@
 						 len, 0);
 				skb->protocol = eth_type_trans(skb, qep->dev);
 				netif_rx(skb);
+				dev->last_rx = jiffies;
 				qep->net_stats.rx_packets++;
 				qep->net_stats.rx_bytes += len;
 			}
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/Config.in linux/drivers/net/tokenring/Config.in
--- v2.4.1/linux/drivers/net/tokenring/Config.in	Thu Mar 30 16:54:53 2000
+++ linux/drivers/net/tokenring/Config.in	Fri Feb 16 16:02:36 2001
@@ -13,6 +13,7 @@
    dep_tristate '  Generic TMS380 Token Ring ISA/PCI adapter support' CONFIG_TMS380TR $CONFIG_TR
    if [ "$CONFIG_TMS380TR" != "n" ]; then
       dep_tristate '    Generic TMS380 PCI support' CONFIG_TMSPCI $CONFIG_TMS380TR
+      dep_tristate '    Generic TMS380 ISA support' CONFIG_TMSISA $CONFIG_TMS380TR
       dep_tristate '    Madge Smart 16/4 PCI Mk2 support' CONFIG_ABYSS $CONFIG_TMS380TR
       if [ "$CONFIG_MCA" = "y" ]; then 
          dep_tristate '    Madge Smart 16/4 Ringnode MicroChannel' CONFIG_MADGEMC $CONFIG_TMS380TR
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/Makefile linux/drivers/net/tokenring/Makefile
--- v2.4.1/linux/drivers/net/tokenring/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/net/tokenring/Makefile	Fri Feb 16 16:02:36 2001
@@ -19,8 +19,9 @@
 obj-$(CONFIG_ABYSS) 	+= abyss.o
 obj-$(CONFIG_MADGEMC) 	+= madgemc.o
 obj-$(CONFIG_TMSPCI) 	+= tmspci.o
+obj-$(CONFIG_TMSISA) 	+= tmsisa.o
 obj-$(CONFIG_SMCTR) 	+= smctr.o
 
-L_TARGET := tr.a
+O_TARGET := tr.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/abyss.c linux/drivers/net/tokenring/abyss.c
--- v2.4.1/linux/drivers/net/tokenring/abyss.c	Tue Dec  5 12:29:38 2000
+++ linux/drivers/net/tokenring/abyss.c	Fri Feb 16 16:02:36 2001
@@ -4,7 +4,7 @@
  *  Written 1999-2000 by Adam Fritzler
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  *
  *  This driver module supports the following cards:
  *      - Madge Smart 16/4 PCI Mk2
@@ -137,7 +137,8 @@
 	 */
 	dev->base_addr += 0x10;
 		
-	ret = tmsdev_init(dev);
+	ret = tmsdev_init(dev,0,pdev);
+	/* XXX: should be the max PCI32 DMA max */
 	if (ret) {
 		printk("%s: unable to get memory for dev->priv.\n", 
 		       dev->name);
@@ -153,7 +154,6 @@
 	printk("\n");
 
 	tp = dev->priv;
-	tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
 	tp->setnselout = abyss_setnselout_pins;
 	tp->sifreadb = abyss_sifreadb;
 	tp->sifreadw = abyss_sifreadw;
@@ -173,7 +173,7 @@
 	return 0;
 
 err_out_tmsdev:
-	kfree(dev->priv);
+	tmsdev_term(dev);
 err_out_irq:
 	free_irq(pdev->irq, dev);
 err_out_region:
@@ -441,7 +441,7 @@
 	unregister_netdev(dev);
 	release_region(dev->base_addr-0x10, ABYSS_IO_EXTENT);
 	free_irq(dev->irq, dev);
-	kfree(dev->priv);
+	tmsdev_term(dev);
 	kfree(dev);
 	pci_set_drvdata(pdev, NULL);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/ibmtr.c linux/drivers/net/tokenring/ibmtr.c
--- v2.4.1/linux/drivers/net/tokenring/ibmtr.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/net/tokenring/ibmtr.c	Tue Feb 13 13:15:05 2001
@@ -2,7 +2,7 @@
  *
  *	Written 1993 by Mark Swanson and Peter De Schrijver.
  *	This software may be used and distributed according to the terms
- *	of the GNU Public License, incorporated herein by reference.
+ *	of the GNU General Public License, incorporated herein by reference.
  *
  *	This device driver should work with Any IBM Token Ring Card that does
  *	not use DMA.
@@ -1786,6 +1786,7 @@
 		skb->ip_summed = 1;
 	}
 	netif_rx(skb);
+	dev->last_rx = jiffies;
 }
 
 static int tok_send_packet(struct sk_buff *skb, struct net_device *dev)
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/lanstreamer.c linux/drivers/net/tokenring/lanstreamer.c
--- v2.4.1/linux/drivers/net/tokenring/lanstreamer.c	Tue Jul 18 16:52:35 2000
+++ linux/drivers/net/tokenring/lanstreamer.c	Fri Feb 16 16:02:36 2001
@@ -237,6 +237,7 @@
 				printk(KERN_ERR "lanstreamer: out of memory.\n");
 				break;
 			}
+			SET_MODULE_OWNER(dev);
 #endif
 			dev->priv = (void *) streamer_priv;
 #if STREAMER_DEBUG
@@ -736,7 +737,6 @@
 #endif
 
 	netif_start_queue(dev);
-	MOD_INC_USE_COUNT;
 	return 0;
 }
 
@@ -852,6 +852,7 @@
 					/* send up to the protocol */
 					netif_rx(skb);
 				}
+				dev->last_rx = jiffies;
 				streamer_priv->streamer_stats.rx_packets++;
 				streamer_priv->streamer_stats.rx_bytes += length;
 			}	/* if skb == null */
@@ -906,7 +907,7 @@
 				streamer_priv->streamer_stats.tx_bytes += streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]->len;
 				streamer_priv->streamer_stats.tx_packets++;
 				dev_kfree_skb_irq(streamer_priv->tx_ring_skb[streamer_priv->tx_ring_last_status]);
-				streamer_priv-> streamer_tx_ring[streamer_priv->tx_ring_last_status].buffer = 0xdeadbeef;
+				streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buffer = 0xdeadbeef;
 				streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].status = 0;
 				streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].bufcnt_framelen = 0;
 				streamer_priv->streamer_tx_ring[streamer_priv->tx_ring_last_status].buflen = 0;
@@ -1070,8 +1071,6 @@
 	printk("\n");
 #endif
 	free_irq(dev->irq, dev);
-
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
@@ -1383,8 +1382,11 @@
 			       status, len);
 		}
 #endif
-		mac_frame = dev_alloc_skb(frame_len);
-
+		if (!(mac_frame = dev_alloc_skb(frame_len))) {
+			printk(KERN_WARNING "%s: Memory squeeze, dropping frame.\n",
+			       dev->name);
+			goto drop_frame;
+		}
 		/* Walk the buffer chain, creating the frame */
 
 		do {
@@ -1431,7 +1433,7 @@
 		netif_rx(mac_frame);
 
 		/* Now tell the card we have dealt with the received frame */
-
+drop_frame:
 		/* Set LISR Bit 1 */
 		writel(LISR_ARB_FREE, streamer_priv->streamer_mmio + LISR_SUM);
 
@@ -1758,6 +1760,7 @@
 	{
 		dev_streamer[i] = NULL;
 		dev_streamer[i] = init_trdev(dev_streamer[i], 0);
+		SET_MODULE_OWNER(dev_streamer[i]);
 		if (dev_streamer[i] == NULL)
 			return -ENOMEM;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/madgemc.c linux/drivers/net/tokenring/madgemc.c
--- v2.4.1/linux/drivers/net/tokenring/madgemc.c	Wed Jan 26 13:16:05 2000
+++ linux/drivers/net/tokenring/madgemc.c	Fri Feb 16 16:02:36 2001
@@ -4,7 +4,7 @@
  *  Written 2000 by Adam Fritzler
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  *
  *  This driver module supports the following cards:
  *      - Madge Smart 16/4 Ringnode MC16
@@ -349,7 +349,7 @@
 			printk(":%2.2x", dev->dev_addr[i]);
 		printk("\n");
 
-		if (tmsdev_init(dev)) {
+		if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL)) {
 			printk("%s: unable to get memory for dev->priv.\n", 
 			       dev->name);
 			return -1;
@@ -362,7 +362,6 @@
 		 * they know what they're talking about.  Cut off DMA
 		 * at 16mb.
 		 */
-		tp->dmalimit = ISA_MAX_ADDRESS; /* XXX: ?? */
 		tp->setnselout = madgemc_setnselout_pins;
 		tp->sifwriteb = madgemc_sifwriteb;
 		tp->sifreadb = madgemc_sifreadb;
@@ -383,7 +382,7 @@
 			printk("madgemc: register_trdev() returned non-zero.\n");
 			
 			kfree(card);
-			kfree(dev->priv);
+			tmsdev_term(dev);
 			kfree(dev);
 			return -1;
 		}
@@ -783,7 +782,7 @@
 		unregister_trdev(dev);
 		release_region(dev->base_addr-MADGEMC_SIF_OFFSET, MADGEMC_IO_EXTENT);
 		free_irq(dev->irq, dev);
-		kfree(dev->priv);
+		tmsdev_term(dev);
 		kfree(dev);
 		this_card = madgemc_card_list;
 		madgemc_card_list = this_card->next;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/olympic.c linux/drivers/net/tokenring/olympic.c
--- v2.4.1/linux/drivers/net/tokenring/olympic.c	Tue Dec  5 12:29:39 2000
+++ linux/drivers/net/tokenring/olympic.c	Tue Feb 13 13:15:05 2001
@@ -15,7 +15,7 @@
  *  assistance and perserverance with the testing of this driver.
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  * 
  *  4/27/99 - Alpha Release 0.1.0
  *            First release to the public
@@ -210,6 +210,8 @@
 			}
 
 			olympic_priv=kmalloc(sizeof (struct olympic_private), GFP_KERNEL);
+			if (!olympic_priv)
+				return 0;
 			memset(olympic_priv, 0, sizeof(struct olympic_private));
 			init_waitqueue_head(&olympic_priv->srb_wait);
 			init_waitqueue_head(&olympic_priv->trb_wait);
@@ -766,6 +768,7 @@
 						skb->protocol = tr_type_trans(skb,dev);
 						netif_rx(skb) ; 
 					} 
+					dev->last_rx = jiffies ;
 					olympic_priv->olympic_stats.rx_packets++ ; 
 					olympic_priv->olympic_stats.rx_bytes += length ; 
 				} /* if skb == null */
@@ -1276,6 +1279,7 @@
 		mac_frame->dev = dev ; 
 		mac_frame->protocol = tr_type_trans(mac_frame,dev);
 		netif_rx(mac_frame) ; 	
+		dev->last_rx = jiffies ;
 
 		/* Now tell the card we have dealt with the received frame */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/olympic.h linux/drivers/net/tokenring/olympic.h
--- v2.4.1/linux/drivers/net/tokenring/olympic.h	Mon Jun 19 13:42:39 2000
+++ linux/drivers/net/tokenring/olympic.h	Tue Feb 13 13:15:05 2001
@@ -11,7 +11,7 @@
  *      Director, National Security Agency.
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  */
 
 #define CID 0x4e
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/smctr.c linux/drivers/net/tokenring/smctr.c
--- v2.4.1/linux/drivers/net/tokenring/smctr.c	Mon Oct 16 12:58:51 2000
+++ linux/drivers/net/tokenring/smctr.c	Fri Feb 16 16:02:36 2001
@@ -4,11 +4,11 @@
  *  Written by Jay Schulist <jschlst@turbolinux.com>
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  *
  *  This device driver works with the following SMC adapters:
- *      - SMC TokenCard Elite   (8115T)
- *      - SMC TokenCard Elite/A MCA (8115T/A)
+ *      - SMC TokenCard Elite   (8115T, chips 825/584)
+ *      - SMC TokenCard Elite/A MCA (8115T/A, chips 825/594)
  *
  *  Source(s):
  *  	- SMC TokenCard SDK.
@@ -16,13 +16,16 @@
  *  Maintainer(s):
  *    JS        Jay Schulist <jschlst@turbolinux.com>
  *
+ * Changes:
+ *    07102000          JS      Fixed a timing problem in smctr_wait_cmd();
+ *                              Also added a bit more discriptive error msgs.
+ *    07122000          JS      Fixed problem with detecting a card with
+ *				module io/irq/mem specified.
+ *
  *  To do:
  *    1. Multicast support.
  */
 
-static const char *version = "smctr.c: v1.1 1/1/00 by jschlst@turbolinux.com\n";
-static const char *cardname = "smctr";
-
 #ifdef MODULE
 #include <linux/module.h>
 #include <linux/version.h>
@@ -37,7 +40,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/time.h>
 #include <asm/system.h>
@@ -59,6 +62,10 @@
 #include "smctr.h"               /* Our Stuff */
 #include "smctr_firmware.h"      /* SMC adapter firmware */
 
+static char version[] __initdata = KERN_INFO "smctr.c: v1.4 7/12/00 by jschlst@turbolinux.com\n";
+static const char *cardname = "smctr";
+
+
 #define SMCTR_IO_EXTENT   20
 
 /* A zero-terminated list of I/O addresses to be probed. */
@@ -72,7 +79,7 @@
 static unsigned int smctr_posid = 0x6ec6;
 #endif
 
-static int ringspeed = 0;
+static int ringspeed;
 
 /* SMC Name of the Adapter. */
 static char *smctr_name = "SMC TokenCard";
@@ -107,7 +114,6 @@
 static int smctr_decode_firmware(struct net_device *dev);
 static int smctr_disable_16bit(struct net_device *dev);
 static int smctr_disable_adapter_ctrl_store(struct net_device *dev);
-static int smctr_disable_adapter_ram(struct net_device *dev);
 static int smctr_disable_bic_int(struct net_device *dev);
 
 /* E */
@@ -219,9 +225,7 @@
         struct net_device *dev, __u16 rx_status);
 
 /* R */
-static int smctr_ram_conflict_test(struct net_device *dev);
 static int smctr_ram_memory_test(struct net_device *dev);
-static unsigned int __init smctr_read_584_chksum(int ioaddr);
 static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
         __u16 *correlator);
 static int smctr_rcv_init(struct net_device *dev, MAC_HEADER *rmf,
@@ -234,7 +238,6 @@
 static int smctr_reset_adapter(struct net_device *dev);
 static int smctr_restart_tx_chain(struct net_device *dev, short queue);
 static int smctr_ring_status_chg(struct net_device *dev);
-static int smctr_rom_conflict_test(struct net_device *dev);
 static int smctr_rx_frame(struct net_device *dev);
 
 /* S */
@@ -626,7 +629,10 @@
                         break;
 
                 case WD8115T:
-                        smctr_model = "8115T";
+			if(tp->extra_info & CHIP_REV_MASK)
+                                smctr_model = "8115T rev XE";
+                        else
+                                smctr_model = "8115T rev XD";
                         break;
 
                 default:
@@ -827,16 +833,6 @@
 
 static int smctr_disable_16bit(struct net_device *dev)
 {
-        struct net_local *tp = (struct net_local *)dev->priv;
-        __u8 r;
-
-        if(tp->adapter_bus == BUS_ISA16_TYPE
-                && ((tp->adapter_flags & FORCED_16BIT_MODE) == 0))
-        {
-                r = inb(dev->base_addr + LAAR);
-                outb((r & ~LAAR_MEM16ENB), dev->base_addr + LAAR);
-        }
-
         return (0);
 }
 
@@ -860,22 +856,6 @@
         return (0);
 }
 
-static int smctr_disable_adapter_ram(struct net_device *dev)
-{
-        int ioaddr = dev->base_addr;
-        __u8 r;
-
-        /* First disable memory enable bit. */
-        r = inb(ioaddr + MSR);
-        outb(~MSR_MEMB & r, ioaddr + MSR);
-
-        /* Now disable 16 bit memory enable bit. */
-        r = inb(ioaddr + LAAR);
-        outb(~LAAR_MEM16ENB & r, ioaddr + LAAR);
-
-        return (0);
-}
-
 static int smctr_disable_bic_int(struct net_device *dev)
 {
         struct net_local *tp = (struct net_local *)dev->priv;
@@ -993,6 +973,11 @@
         request_region(ioaddr, SMCTR_IO_EXTENT, smctr_name);
 
         b = inb(ioaddr + BDID);
+	if(b != BRD_ID_8115T)
+        {
+                printk("%s: The adapter found is not supported\n", dev->name);
+                return (-1);
+        }
 
         /* Check for 8115T Board ID */
         r2 = 0;
@@ -1015,7 +1000,10 @@
                         break;
 
                 case WD8115T:
-                        smctr_model = "8115T";
+			if(tp->extra_info & CHIP_REV_MASK)
+                                smctr_model = "8115T rev XE";
+                        else
+                                smctr_model = "8115T rev XD";
                         break;
 
                 default:
@@ -1164,12 +1152,13 @@
                 if(!(r1 & 0x2) )           /* GP2_ETRD */
                         tp->mode_bits |= EARLY_TOKEN_REL;
 
-                /* see if the chip is corrupted */
+                /* see if the chip is corrupted
                 if(smctr_read_584_chksum(ioaddr))
                 {
                         printk("%s: EEPROM Checksum Failure\n", dev->name);
                         return(-1);
                 }
+		*/
         }
 
         return (0);
@@ -1359,7 +1348,7 @@
          * Make sure the mem_used offset at this point is the
          * same as in allocate_shared memory or the following
          * boundry adjustment will be incorrect (i.e. not allocating
-         * the non-mac recieve buffers above cannot change the 256
+         * the non-mac receive buffers above cannot change the 256
          * byte offset).
          *
          * Since this cannot be guaranteed, adding the full 256 bytes
@@ -1607,53 +1596,48 @@
         smctr_disable_bic_int(dev);
         smctr_set_trc_reset(dev->base_addr);
 
-        /* By default the adapter will operate in 16-bit mode only. If
-         * there are two or more adapters in a box, switching between
-         * 16-bit and 8-bit mode may cause problems. In short the adapters
-         * will interfere with each other. XXX - smc.
-         */
-        smctr_disable_adapter_ram(dev);
-        if((err = smctr_rom_conflict_test(dev)))
-                return (err);
-
-        if((err = smctr_ram_conflict_test(dev)))
-                return (err);
-
-        smctr_enable_adapter_ram(dev);
         smctr_enable_16bit(dev);
         smctr_set_page(dev, (__u8 *)tp->ram_access);
 
         if(smctr_checksum_firmware(dev))
-                return (UCODE_NOT_PRESENT);
-
-        if((err = smctr_ram_memory_test(dev)))
-                return (err);
-
-        smctr_enable_16bit(dev);
-        if(smctr_checksum_firmware(dev))
-                return (-1);
+	{
+                printk("%s: Previously loaded firmware is missing\n",dev->name);                return (-ENOENT);
+        }
 
         if((err = smctr_ram_memory_test(dev)))
-                return (-1);
+	{
+                printk("%s: RAM memory test failed.\n", dev->name);
+                return (-EIO);
+        }
 
-        smctr_set_rx_look_ahead(dev);
+	smctr_set_rx_look_ahead(dev);
         smctr_load_node_addr(dev);
 
         /* Initialize adapter for Internal Self Test. */
         smctr_reset_adapter(dev);
-
         if((err = smctr_init_card_real(dev)))
-                return (err);
+	{
+                printk("%s: Initialization of card failed (%d)\n",
+                        dev->name, err);
+                return (-EINVAL);
+        }
 
         /* This routine clobbers the TRC's internal registers. */
         if((err = smctr_internal_self_test(dev)))
-                return (err);
+	{
+                printk("%s: Card failed internal self test (%d)\n",
+                        dev->name, err);
+                return (-EINVAL);
+        }
 
         /* Re-Initialize adapter's internal registers */
         smctr_reset_adapter(dev);
-
         if((err = smctr_init_card_real(dev)))
-                return (err);
+	{
+                printk("%s: Initialization of card failed (%d)\n",
+                        dev->name, err);
+                return (-EINVAL);
+        }
 
         smctr_enable_bic_int(dev);
 
@@ -1742,7 +1726,10 @@
                 return (err);
 
         if((err = smctr_issue_init_txrx_cmd(dev)))
+	{
+                printk("%s: Hardware failure\n", dev->name);
                 return (err);
+        }
 
         return (0);
 }
@@ -2737,7 +2724,10 @@
                 return (err);
 
         if((err = smctr_wait_cmd(dev)))
+	{
+                printk("%s: Hardware failure\n", dev->name);
                 return (err);
+        }
 
         /* Initialize Transmit Queue Pointers that are used, to point to
          * a single FCB.
@@ -3551,18 +3541,11 @@
  */
 static int smctr_open(struct net_device *dev)
 {
-        struct net_local *tp = (struct net_local *)dev->priv;
         int err;
 
         if(smctr_debug > 10)
                 printk("%s: smctr_open\n", dev->name);
 
-        tp->status = NOT_INITIALIZED;
-
-        err = smctr_load_firmware(dev);
-        if(err < 0)
-                return (err);
-
         err = smctr_init_adapter(dev);
         if(err < 0)
                 return (err);
@@ -3596,16 +3579,16 @@
         smctr_set_page(dev, (__u8 *)tp->ram_access);
 
         if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)MAC_QUEUE)))
-                return (err);
+                goto out;
 
         if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)MAC_QUEUE)))
-                return (err);
+                goto out;
 
         if((err = smctr_issue_resume_rx_fcb_cmd(dev, (short)NON_MAC_QUEUE)))
-                return (err);
+                goto out;
 
         if((err = smctr_issue_resume_rx_bdb_cmd(dev, (short)NON_MAC_QUEUE)))
-                return (err);
+                goto out;
 
         tp->status = CLOSED;
 
@@ -3652,10 +3635,16 @@
                         {
                                 if(!(err = smctr_lobe_media_test(dev)))
                                         err = smctr_issue_insert_cmd(dev);
+				else
+                                {
+                                        if(err == LOBE_MEDIA_TEST_FAILED)
+                                                printk("%s: Lobe Media Test Failure - Check cable?\n", dev->name);
+                                }
                         }
                 }
         }
 
+out:
         restore_flags(flags);
 
         return (err);
@@ -3689,13 +3678,13 @@
 
 static int __init smctr_probe1(struct net_device *dev, int ioaddr)
 {
-        static unsigned version_printed = 0;
+        static unsigned version_printed;
         struct net_local *tp;
         int err;
         __u32 *ram;
 
         if(smctr_debug && version_printed++ == 0)
-                printk("%s", version);
+                printk(version);
 
 #ifndef MODULE
         dev = init_trdev(dev, 0);
@@ -3706,8 +3695,10 @@
         /* Setup this devices private information structure */
         tp = (struct net_local *)kmalloc(sizeof(struct net_local),
                 GFP_KERNEL);
-        if(tp == NULL)
-                return (-ENOMEM);
+        if(tp == NULL) {
+		err = -ENOMEM;
+		goto out;
+	}
         memset(tp, 0, sizeof(struct net_local));
         dev->priv = tp;
         dev->base_addr = ioaddr;
@@ -3716,11 +3707,9 @@
         err = smctr_chk_isa(dev);
         if(err < 0)
         {
-		err = smctr_chk_mca(dev);
-		if(err < 0)
-		{
-                	kfree(tp);
-                	return (-ENODEV);
+		if ((err = smctr_chk_mca(dev)) < 0) {
+			err = -ENODEV;
+			goto out_tp;
 		}
         }
 
@@ -3729,6 +3718,15 @@
         dev->rmem_end = dev->mem_end = dev->mem_start + 0x10000;
         ram = (__u32 *)phys_to_virt(dev->mem_start);
         tp->ram_access = *(__u32 *)&ram;
+	tp->status = NOT_INITIALIZED;
+
+        err = smctr_load_firmware(dev);
+        if(err != UCODE_PRESENT && err != SUCCESS)
+        {
+                printk("%s: Firmware load failed (%d)\n", dev->name, err);
+		err = -EIO;
+		goto out_tp;
+        }
 
 	/* Allow user to specify ring speed on module insert. */
 	if(ringspeed == 4)
@@ -3741,6 +3739,7 @@
                 (unsigned int)dev->base_addr,
                 dev->irq, tp->rom_base, tp->ram_base);
 
+	/* AKPM: there's no point in this */
         dev->init               = smctr_init_card;
         dev->open               = smctr_open;
         dev->stop               = smctr_close;
@@ -3749,8 +3748,12 @@
         dev->watchdog_timeo	= HZ;
         dev->get_stats          = smctr_get_stats;
         dev->set_multicast_list = &smctr_set_multicast_list;
-
         return (0);
+
+out_tp:
+	kfree(tp);
+out:
+	return err;
 }
 
 static int smctr_process_rx_packet(MAC_HEADER *rmf, __u16 size,
@@ -3952,7 +3955,8 @@
         {
                 rmf->vl = SWAP_BYTES(rmf->vl);
 
-                skb = dev_alloc_skb(size);
+                if (!(skb = dev_alloc_skb(size)))
+			return -ENOMEM;
                 skb->len = size;
 
                 /* Slide data into a sleek skb. */
@@ -3967,33 +3971,13 @@
                 skb->dev = dev;
                 skb->protocol = tr_type_trans(skb, dev);
                 netif_rx(skb);
+		dev->last_rx = jiffies;
                 err = 0;
         }
 
         return (err);
 }
 
-/* Test for RAM in adapter RAM space. */
-static int smctr_ram_conflict_test(struct net_device *dev)
-{
-        struct net_local *tp = (struct net_local *)dev->priv;
-        unsigned int i;
-        __u16 sword;
-
-        for(i = 0; i < (unsigned int)(tp->ram_usable * 1024); i += 1024)
-        {
-                sword = *(__u16 *)(tp->ram_access + i);
-                *(__u16 *)(tp->ram_access + i) = 0x1234;
-                if(*(__u16 *)(tp->ram_access + i) == 0x1234)
-                {
-                        *(__u16 *)(tp->ram_access + i) = sword;
-                        return (-1);
-                }
-        }
-
-        return (0);
-}
-
 /* Adapter RAM test. Incremental word ODD boundry data test. */
 static int smctr_ram_memory_test(struct net_device *dev)
 {
@@ -4034,7 +4018,7 @@
                                 err_offset      = j;
                                 err_word        = word_read;
                                 err_pattern     = word_pattern;
-                                return (-1);
+                                return (RAM_TEST_FAILED);
                         }
                 }
         }
@@ -4059,7 +4043,7 @@
                                 err_offset      = j;
                                 err_word        = word_read;
                                 err_pattern     = word_pattern;
-                                return (-1);
+                                return (RAM_TEST_FAILED);
                         }
                 }
         }
@@ -4069,57 +4053,6 @@
         return (0);
 }
 
-static unsigned int __init smctr_read_584_chksum(int ioaddr)
-{
-        __u8 pg_no, r1, r2;
-        __u16 byte_no, csum_val = 0;
-
-        for(pg_no = 0; pg_no < 16; pg_no++)
-        {
-                r1 = inb(ioaddr + 0x01);
-                r1 &= 0x04;
-                r1 |= 0x02;
-
-                outb(r1, ioaddr + 0x01);
-
-                r1 = inb(ioaddr + 0x03);
-                r1 &= 0x0f;
-                r1 |= (pg_no << 4);
-
-                outb(r1, ioaddr + 0x03);
-
-                r1 = inb(ioaddr + 0x01);
-                r1 &= 0x04;
-                r1 |= 0x12;
-
-                outb(r1, ioaddr + 0x01);
-
-                do {
-                        r1 = inb(ioaddr + 0x01);
-                } while(r1 & 0x10);
-
-                r2 = 0;
-                for(byte_no = 0x08; byte_no < 0x10; byte_no++)
-                {
-                        r1 = inb(ioaddr + byte_no);
-                        r2 += r1;
-                }
-
-                csum_val += r2;
-        }
-
-        r1 = inb(ioaddr + 0x01);
-        r1 &= 0x04;
-        r1 |= 0x10;
-        outb(r1, ioaddr + 0x01);
-
-        csum_val &= 0xff;
-        if(csum_val == 0xff)
-                return (0);
-        else
-                return (-1);
-}
-
 static int smctr_rcv_chg_param(struct net_device *dev, MAC_HEADER *rmf,
         __u16 *correlator)
 {
@@ -4445,10 +4378,10 @@
         int ioaddr = dev->base_addr;
 
         /* Reseting the NIC will put it in a halted and un-initialized state. */        smctr_set_trc_reset(ioaddr);
-        udelay(200000); /* ~2 ms */
+        mdelay(200); /* ~2 ms */
 
         smctr_clear_trc_reset(ioaddr);
-        udelay(200000); /* ~2 ms */
+        mdelay(200); /* ~2 ms */
 
         /* Remove any latched interrupts that occured prior to reseting the
          * adapter or possibily caused by line glitches due to the reset.
@@ -4578,21 +4511,6 @@
         return (0);
 }
 
-/* Test for ROM signature within adapter RAM space. */
-static int smctr_rom_conflict_test(struct net_device *dev)
-{
-        struct net_local *tp = (struct net_local *)dev->priv;
-        unsigned int i;
-
-        for(i = 0; i < (unsigned int)tp->ram_usable * 1024; i += 4096)
-        {
-                if(*(__u16 *)(tp->ram_access + i) == 0xaa55)
-                        return (-1);
-        }
-
-        return (0);
-}
-
 static int smctr_rx_frame(struct net_device *dev)
 {
         struct net_local *tp = (struct net_local *)dev->priv;
@@ -4641,6 +4559,7 @@
                                 skb->dev = dev;
                                 skb->protocol = tr_type_trans(skb, dev);
                                 netif_rx(skb);
+				dev->last_rx = jiffies;
                         }
                         else
                                 smctr_process_rx_packet((MAC_HEADER *)pbuff,
@@ -4700,7 +4619,7 @@
         {
                 if(fcb->frame_status & FCB_COMMAND_DONE)
                         break;
-                udelay(1000);
+                mdelay(1);
         }
 
         /* Check if GOOD frame Tx'ed. */
@@ -4814,7 +4733,7 @@
         {
                 if(fcb->frame_status & FCB_COMMAND_DONE)
                         break;
-                udelay(1000);
+                mdelay(1);
         }
 
         /* Check if GOOD frame Tx'ed */
@@ -5118,7 +5037,7 @@
 		{
           		if(fcb->frame_status & FCB_COMMAND_DONE)
               			break;
-          		udelay(1000);
+          		mdelay(1);
       		}
 
                 /* Check if GOOD frame Tx'ed */
@@ -5181,7 +5100,7 @@
 	{
        		if(fcb->frame_status & FCB_COMMAND_DONE)
            		break;
-        	udelay(1000);
+        	mdelay(1);
    	}
 
         /* Check if GOOD frame Tx'ed */
@@ -5194,7 +5113,7 @@
 		{
           		if(fcb->frame_status & FCB_COMMAND_DONE)
               			break;
-        		udelay(1000);
+        		mdelay(1);
       		}
 
                 if(!(fcb->frame_status & FCB_COMMAND_DONE))
@@ -5451,7 +5370,7 @@
 {
         struct net_local *tp = (struct net_local *)dev->priv;
 
-        tp->acb_head->cmd_done_status   = 0;
+        tp->acb_head->cmd_done_status   = ACB_COMMAND_NOT_DONE;
         tp->acb_head->cmd               = command;
         tp->acb_head->subcmd            = subcommand;
         tp->acb_head->data_offset_lo
@@ -5752,14 +5671,15 @@
         {
                 if(tp->acb_head->cmd_done_status & ACB_COMMAND_DONE)
                         break;
+		udelay(1);
                 loop_count--;
         }
 
         if(loop_count == 0)
-                return(-1);
+                return(HARDWARE_FAILED);
 
         if(tp->acb_head->cmd_done_status & 0xff)
-                return(-1);
+                return(HARDWARE_FAILED);
 
         return (0);
 }
@@ -5795,7 +5715,7 @@
         if(timeout)
                 return (0);
         else
-                return (-1);
+                return (HARDWARE_FAILED);
 }
 
 #ifdef MODULE
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/tms380tr.c linux/drivers/net/tokenring/tms380tr.c
--- v2.4.1/linux/drivers/net/tokenring/tms380tr.c	Fri Sep 22 14:21:17 2000
+++ linux/drivers/net/tokenring/tms380tr.c	Fri Feb 16 16:02:36 2001
@@ -8,18 +8,12 @@
  *  http://www.linux-sna.org
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  *
  *  The following modules are currently available for card support:
  *	- tmspci (Generic PCI card support)
  *	- abyss (Madge PCI support)
- *  
- *  The following cards are currently lacking support, even
- *  though they were supported in previous versions, because
- *  their code did not get migrated into a seperate module:
- *	- SysKonnect TR4/16(+) ISA	(SK-4190)
- *  They are no longer supported by this driver, at least until
- *  a module gets written for them.
+ *      - tmsisa (SysKonnect TR4/16 ISA)
  *
  *  Sources:
  *  	- The hardware related parts of this driver are take from
@@ -38,6 +32,7 @@
  *    CG	Christoph Goos		cgoos@syskonnect.de
  *    AF	Adam Fritzler		mid@auk.cx
  *    MLP       Mike Phillips           phillim@amtrak.com
+ *    JF	Jochen Friedrich	jochen@scram.de
  *     
  *  Modification History:
  *	29-Aug-97	CG	Created
@@ -57,10 +52,15 @@
  *	30-Dec-99	AF	Turned tms380tr into a library ala 8390.
  *				Madge support is provided in the abyss module
  *				Generic PCI support is in the tmspci module.
- *
+ *	30-Nov-00	JF	Updated PCI code to support IO MMU via
+ *				pci_map_static(). Alpha uses this MMU for ISA
+ *				as well.
+ *      14-Jan-01	JF	Fix DMA on ifdown/ifup sequences. Some 
+ *      			cleanup.
+ *      			
  *  To do:
  *    1. Multi/Broadcast packet handling (this may have fixed itself)
- *    2. Write a sktrisa module that includes the old ISA support
+ *    2. Write a sktrisa module that includes the old ISA support (done)
  *    3. Allow modules to load their own microcode
  *    4. Speed up the BUD process -- freezing the kernel for 3+sec is
  *         quite unacceptable.
@@ -68,7 +68,7 @@
  */
 
 #ifdef MODULE
-static const char *version = "tms380tr.c: v1.07 21/01/2000 by Christoph Goos, Adam Fritzler\n";
+static const char *version = "tms380tr.c: v1.08 14/01/2001 by Christoph Goos, Adam Fritzler\n";
 #endif
 
 #ifdef MODULE
@@ -84,7 +84,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/time.h>
 #include <asm/system.h>
@@ -125,9 +125,6 @@
 static void	tms380tr_cancel_tx_queue(struct net_local* tp);
 static int 	tms380tr_chipset_init(struct net_device *dev);
 static void 	tms380tr_chk_irq(struct net_device *dev);
-#if 0
-static unsigned char tms380tr_chk_frame(struct net_device *dev, unsigned char *Addr);
-#endif
 static void 	tms380tr_chk_outstanding_cmds(struct net_device *dev);
 static void 	tms380tr_chk_src_addr(unsigned char *frame, unsigned char *hw_addr);
 static unsigned char tms380tr_chk_ssb(struct net_local *tp, unsigned short IrqType);
@@ -191,7 +188,7 @@
 
 
 
-#if TMS380TR_DEBUG > 0
+#if 0 /* TMS380TR_DEBUG > 0 */
 static int madgemc_sifprobe(struct net_device *dev)
 {
         unsigned char old, chk1, chk2;
@@ -259,6 +256,16 @@
 	int err;
 	
 	/* Reset the hardware here. Don't forget to set the station address. */
+
+	if(dev->dma > 0) 
+	{
+		unsigned long flags=claim_dma_lock();
+		disable_dma(dev->dma);
+		set_dma_mode(dev->dma, DMA_MODE_CASCADE);
+		enable_dma(dev->dma);
+		release_dma_lock(flags);
+	}
+	
 	err = tms380tr_chipset_init(dev);
   	if(err)
 	{
@@ -275,6 +282,7 @@
 
 	printk(KERN_INFO "%s: Adapter RAM size: %dK\n", 
 	       dev->name, tms380tr_read_ptr(dev));
+
 	tms380tr_enable_interrupts(dev);
 	tms380tr_open_adapter(dev);
 
@@ -334,18 +342,26 @@
 	tms380tr_init_opb(dev);
 	tms380tr_init_net_local(dev);
 
+	if(tms380tr_debug > 3)
+		printk(KERN_INFO "%s: Resetting adapter...\n", dev->name);
 	err = tms380tr_reset_adapter(dev);
 	if(err < 0)
 		return (-1);
 
+	if(tms380tr_debug > 3)
+		printk(KERN_INFO "%s: Bringup diags...\n", dev->name);
 	err = tms380tr_bringup_diags(dev);
 	if(err < 0)
 		return (-1);
 
+	if(tms380tr_debug > 3)
+		printk(KERN_INFO "%s: Init adapter...\n", dev->name);
 	err = tms380tr_init_adapter(dev);
 	if(err < 0)
 		return (-1);
 
+	if(tms380tr_debug > 3)
+		printk(KERN_INFO "%s: Done!\n", dev->name);
 	return (0);
 }
 
@@ -356,6 +372,7 @@
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
 	int i;
+	dma_addr_t dmabuf;
 
 	tp->scb.CMD	= 0;
 	tp->scb.Parm[0] = 0;
@@ -381,11 +398,11 @@
 
 	skb_queue_head_init(&tp->SendSkbQueue);
 	tp->QueueSkb = MAX_TX_QUEUE;
-	
+
 	/* Create circular chain of transmit lists */
 	for (i = 0; i < TPL_NUM; i++)
 	{
-		tp->Tpl[i].NextTPLAddr = htonl((unsigned long) virt_to_bus(&tp->Tpl[(i+1) % TPL_NUM]));
+		tp->Tpl[i].NextTPLAddr = htonl(((char *)(&tp->Tpl[(i+1) % TPL_NUM]) - (char *)tp) + tp->dmabuffer); /* DMA buffer may be MMU driven */
 		tp->Tpl[i].Status	= 0;
 		tp->Tpl[i].FrameSize	= 0;
 		tp->Tpl[i].FragList[0].DataCount	= 0;
@@ -393,6 +410,7 @@
 		tp->Tpl[i].NextTPLPtr	= &tp->Tpl[(i+1) % TPL_NUM];
 		tp->Tpl[i].MData	= NULL;
 		tp->Tpl[i].TPLIndex	= i;
+		tp->Tpl[i].DMABuff	= 0;
 		tp->Tpl[i].BusyFlag	= 0;
 	}
 
@@ -401,19 +419,20 @@
 	/* Create circular chain of receive lists */
 	for (i = 0; i < RPL_NUM; i++)
 	{
-		tp->Rpl[i].NextRPLAddr = htonl((unsigned long) virt_to_bus(&tp->Rpl[(i+1) % RPL_NUM]));
+		tp->Rpl[i].NextRPLAddr = htonl(((char *)(&tp->Rpl[(i+1) % RPL_NUM]) - (char *)tp) + tp->dmabuffer); /* DMA buffer may be MMU driven */
 		tp->Rpl[i].Status = (RX_VALID | RX_START_FRAME | RX_END_FRAME | RX_FRAME_IRQ);
 		tp->Rpl[i].FrameSize = 0;
 		tp->Rpl[i].FragList[0].DataCount = cpu_to_be16((unsigned short)tp->MaxPacketSize);
 
 		/* Alloc skb and point adapter to data area */
 		tp->Rpl[i].Skb = dev_alloc_skb(tp->MaxPacketSize);
+			tp->Rpl[i].DMABuff = 0;
 
 		/* skb == NULL ? then use local buffer */
 		if(tp->Rpl[i].Skb == NULL)
 		{
 			tp->Rpl[i].SkbStat = SKB_UNAVAILABLE;
-			tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[i]));
+			tp->Rpl[i].FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[i] - (char *)tp) + tp->dmabuffer);
 			tp->Rpl[i].MData = tp->LocalRxBuffers[i];
 		}
 		else	/* SKB != NULL */
@@ -422,17 +441,19 @@
 			skb_put(tp->Rpl[i].Skb, tp->MaxPacketSize);
 
 			/* data unreachable for DMA ? then use local buffer */
-			if(tp->dmalimit && virt_to_bus(tp->Rpl[i].Skb->data) + tp->MaxPacketSize > tp->dmalimit)
+			dmabuf = pci_map_single(tp->pdev, tp->Rpl[i].Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+			if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
 			{
 				tp->Rpl[i].SkbStat = SKB_DATA_COPY;
-				tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[i]));
+				tp->Rpl[i].FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[i] - (char *)tp) + tp->dmabuffer);
 				tp->Rpl[i].MData = tp->LocalRxBuffers[i];
 			}
 			else	/* DMA directly in skb->data */
 			{
 				tp->Rpl[i].SkbStat = SKB_DMA_DIRECT;
-				tp->Rpl[i].FragList[0].DataAddr = htonl(virt_to_bus(tp->Rpl[i].Skb->data));
+				tp->Rpl[i].FragList[0].DataAddr = htonl(dmabuf);
 				tp->Rpl[i].MData = tp->Rpl[i].Skb->data;
+				tp->Rpl[i].DMABuff = dmabuf;
 			}
 		}
 
@@ -506,7 +527,7 @@
 	tp->ocpl.TXBufMin	 = TX_BUF_MIN;
 	tp->ocpl.TXBufMax	 = TX_BUF_MAX;
 
-	Addr = htonl(virt_to_bus(tp->ProductID));
+	Addr = htonl(((char *)tp->ProductID - (char *)tp) + tp->dmabuffer);
 
 	tp->ocpl.ProdIDAddr[0]	 = LOWORD(Addr);
 	tp->ocpl.ProdIDAddr[1]	 = HIWORD(Addr);
@@ -610,10 +631,11 @@
 {
 	TPL *tpl;
 	short length;
-	unsigned char *buf, *newbuf;
+	unsigned char *buf;
 	struct sk_buff *skb;
 	int i;
-    
+	dma_addr_t dmabuf, newbuf;
+   
 	for(;;)
 	{
 		/* Try to get a free TPL from the chain.
@@ -634,26 +656,30 @@
 			return;
 
 		tp->QueueSkb++;
+		dmabuf = 0;
+
 		/* Is buffer reachable for Busmaster-DMA? */
-		if(tp->dmalimit && virt_to_bus((void*)(((long) skb->data) + skb->len)) > tp->dmalimit)
+
+		length	= skb->len;
+		dmabuf = pci_map_single(tp->pdev, skb->data, length, PCI_DMA_TODEVICE);
+		if(tp->dmalimit && (dmabuf + length > tp->dmalimit))
 		{
 			/* Copy frame to local buffer */
+			pci_unmap_single(tp->pdev, dmabuf, length, PCI_DMA_TODEVICE);
+			dmabuf  = 0;
 			i 	= tp->TplFree->TPLIndex;
-			length 	= skb->len;
 			buf 	= tp->LocalTxBuffers[i];
 			memcpy(buf, skb->data, length);
-			newbuf 	= buf;
+			newbuf 	= ((char *)buf - (char *)tp) + tp->dmabuffer;
 		}
 		else
 		{
 			/* Send direct from skb->data */
-			length = skb->len;
-			newbuf = skb->data;
+			newbuf	= dmabuf;
+			buf	= skb->data;
 		}
-
 		/* Source address in packet? */
-		tms380tr_chk_src_addr(newbuf, dev->dev_addr);
-
+		tms380tr_chk_src_addr(buf, dev->dev_addr);
 		tp->LastSendTime	= jiffies;
 		tpl 			= tp->TplFree;	/* Get the "free" TPL */
 		tpl->BusyFlag 		= 1;		/* Mark TPL as busy */
@@ -661,12 +687,13 @@
     
 		/* Save the skb for delayed return of skb to system */
 		tpl->Skb = skb;
+		tpl->DMABuff = dmabuf;
 		tpl->FragList[0].DataCount = cpu_to_be16((unsigned short)length);
-		tpl->FragList[0].DataAddr  = htonl(virt_to_bus(newbuf));
+		tpl->FragList[0].DataAddr  = htonl(newbuf);
 
 		/* Write the data length in the transmit list. */
 		tpl->FrameSize 	= cpu_to_be16((unsigned short)length);
-		tpl->MData 	= newbuf;
+		tpl->MData 	= buf;
 
 		/* Transmit the frame and set the status values. */
 		tms380tr_write_tpl_status(tpl, TX_VALID | TX_START_FRAME
@@ -1155,9 +1182,10 @@
 	}
 	
 	SIFWRITEW(0xFF00, SIFCMD);
+#if 0
 	if(dev->dma > 0) /* what the? */
 		SIFWRITEB(0xff, POSREG);
-
+#endif
 	tms380tr_cancel_tx_queue(tp);
 
 	return (0);
@@ -1331,6 +1359,7 @@
 		}
 	} while(count == 0);
 
+	printk(KERN_INFO "%s: Adapter Download Failed\n", dev->name);
 	return (-1);
 }
 
@@ -1381,6 +1410,7 @@
 
 	Status = SIFREADW(SIFSTS);
 	
+	printk(KERN_INFO "%s: Hardware error\n", dev->name);
 	/* Hardware error occurred! */
 	Status &= 0x001f;
 	if (Status & 0x0010)
@@ -1412,9 +1442,16 @@
 	int i, loop_cnt, retry_cnt;
 
 	/* Normalize: byte order low/high, word order high/low! (only IPB!) */
-	tp->ipb.SCB_Addr = SWAPW(virt_to_bus(&tp->scb));
-	tp->ipb.SSB_Addr = SWAPW(virt_to_bus(&tp->ssb));
+	tp->ipb.SCB_Addr = SWAPW(((char *)&tp->scb - (char *)tp) + tp->dmabuffer);
+	tp->ipb.SSB_Addr = SWAPW(((char *)&tp->ssb - (char *)tp) + tp->dmabuffer);
 
+	if(tms380tr_debug > 3)
+	{
+		printk(KERN_INFO "%s: buffer (real): %lx\n", dev->name, (long) &tp->scb);
+		printk(KERN_INFO "%s: buffer (virt): %lx\n", dev->name, (long) ((char *)&tp->scb - (char *)tp) + tp->dmabuffer);
+		printk(KERN_INFO "%s: buffer (DMA) : %lx\n", dev->name, (long) tp->dmabuffer);
+		printk(KERN_INFO "%s: buffer (tp)  : %lx\n", dev->name, (long) tp);
+	}
 	/* Maximum: three initialization retries */
 	retry_cnt = INIT_MAX_RETRIES;
 
@@ -1454,8 +1491,11 @@
 			i = 0;
 			do {	/* Test if contents of SCB is valid */
 				if(SCB_Test[i] != *(cb_ptr + i))
+				{
+					printk(KERN_INFO "%s: DMA failed\n", dev->name);
 					/* DMA data error: wrong data in SCB */
 					return (-1);
+				}
 				i++;
 			} while(i < 6);
 
@@ -1477,6 +1517,7 @@
 				Status = SIFREADW(SIFSTS);
 				Status &= STS_ERROR_MASK;
 				/* ShowInitialisationErrorCode(Status); */
+				printk(KERN_INFO "%s: Status error: %d\n", dev->name, Status);
 				return (-1); /* Unrecoverable error */
 			}
 			else
@@ -1491,6 +1532,7 @@
 		}
 	} while(retry_cnt > 0);
 
+	printk(KERN_INFO "%s: Retry exceeded\n", dev->name);
 	return (-1);
 }
 
@@ -1520,7 +1562,7 @@
 			/* Execute OPEN command	*/
 			tp->CMDqueue ^= OC_OPEN;
 
-			Addr = htonl(virt_to_bus(&tp->ocpl));
+			Addr = htonl(((char *)&tp->ocpl - (char *)tp) + tp->dmabuffer);
 			tp->scb.Parm[0] = LOWORD(Addr);
 			tp->scb.Parm[1] = HIWORD(Addr);
 			tp->scb.CMD = OPEN;
@@ -1554,7 +1596,7 @@
 			if(tp->CMDqueue & OC_RECEIVE)
 			{
 				tp->CMDqueue ^= OC_RECEIVE;
-				Addr = htonl(virt_to_bus(tp->RplHead));
+				Addr = htonl(((char *)tp->RplHead - (char *)tp) + tp->dmabuffer);
 				tp->scb.Parm[0] = LOWORD(Addr);
 				tp->scb.Parm[1] = HIWORD(Addr);
 				tp->scb.CMD = RECEIVE;
@@ -1595,7 +1637,7 @@
 
 						tp->CMDqueue ^= OC_TRANSMIT;
 						tms380tr_cancel_tx_queue(tp);
-						Addr = htonl(virt_to_bus(tp->TplBusy));
+						Addr = htonl(((char *)tp->TplBusy - (char *)tp) + tp->dmabuffer);
 						tp->scb.Parm[0] = LOWORD(Addr);
 						tp->scb.Parm[1] = HIWORD(Addr);
 						tp->scb.CMD = TRANSMIT;
@@ -1634,7 +1676,7 @@
 									if(tp->CMDqueue & OC_READ_ERROR_LOG)
 									{
 										tp->CMDqueue ^= OC_READ_ERROR_LOG;
-										Addr = htonl(virt_to_bus(&tp->errorlogtable));
+										Addr = htonl(((char *)&tp->errorlogtable - (char *)tp) + tp->dmabuffer);
 										tp->scb.Parm[0] = LOWORD(Addr);
 										tp->scb.Parm[1] = HIWORD(Addr);
 										tp->scb.CMD = READ_ERROR_LOG;
@@ -1976,8 +2018,9 @@
 		tpl->BusyFlag = 0;		/* "free" TPL */
 
 		printk(KERN_INFO "Cancel tx (%08lXh).\n", (unsigned long)tpl);
-
-		dev_kfree_skb(tpl->Skb);
+		if (tpl->DMABuff)
+			pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_any(tpl->Skb);
 	}
 
 	for(;;)
@@ -1986,7 +2029,7 @@
 		if(skb == NULL)
 			break;
 		tp->QueueSkb++;
-		dev_kfree_skb(skb);
+		dev_kfree_skb_any(skb);
 	}
 
 	return;
@@ -2053,7 +2096,9 @@
 		}
 
 		tp->MacStat.tx_packets++;
-		dev_kfree_skb(tpl->Skb);
+		if (tpl->DMABuff)
+			pci_unmap_single(tp->pdev, tpl->DMABuff, tpl->Skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_irq(tpl->Skb);
 		tpl->BusyFlag = 0;	/* "free" TPL */
 	}
 
@@ -2075,6 +2120,7 @@
 	unsigned int Length, Length2;
 	RPL *rpl;
 	RPL *SaveHead;
+	dma_addr_t dmabuf;
 
 	/* NOTE: At this point the SSB from RECEIVE STATUS is no longer
 	 * available, because the CLEAR SSB command has already been issued.
@@ -2118,81 +2164,68 @@
 				tp->RplHead = SaveHead;
 				break;	/* Return to tms380tr_interrupt */
 			}
-#if 0  		/* This might happen for multicast or broadcast packets.
-		   The upper layers are expected to handle this, not here */
-
-			/* Drop frames sent by myself */
-			if(tms380tr_chk_frame(dev, rpl->MData))
-			{
-				printk(KERN_INFO "%s: Received my own frame\n",
-					dev->name);
-				if(rpl->Skb != NULL)
-					dev_kfree_skb(rpl->Skb);
-			}
-			else
-#endif
-			{
-			  tms380tr_update_rcv_stats(tp,ReceiveDataPtr,Length);
+			tms380tr_update_rcv_stats(tp,ReceiveDataPtr,Length);
 			  
-			  if(tms380tr_debug > 3)
-			    printk("%s: Packet Length %04X (%d)\n",
-				   dev->name, Length, Length);
+			if(tms380tr_debug > 3)
+				printk("%s: Packet Length %04X (%d)\n",
+					dev->name, Length, Length);
 			  
-				/* Indicate the received frame to system the
-				 * adapter does the Source-Routing padding for 
-				 * us. See: OpenOptions in tms380tr_init_opb()
-				 */
-				skb = rpl->Skb;
-				if(rpl->SkbStat == SKB_UNAVAILABLE)
+			/* Indicate the received frame to system the
+			 * adapter does the Source-Routing padding for 
+			 * us. See: OpenOptions in tms380tr_init_opb()
+			 */
+			skb = rpl->Skb;
+			if(rpl->SkbStat == SKB_UNAVAILABLE)
+			{
+				/* Try again to allocate skb */
+				skb = dev_alloc_skb(tp->MaxPacketSize);
+				if(skb == NULL)
 				{
-					/* Try again to allocate skb */
-					skb = dev_alloc_skb(tp->MaxPacketSize);
-					if(skb == NULL)
-					{
-						/* Update Stats ?? */
-					}
-					else
-					{
-						skb->dev	= dev;
-						skb_put(skb, tp->MaxPacketSize);
-						rpl->SkbStat 	= SKB_DATA_COPY;
-						ReceiveDataPtr 	= rpl->MData;
-					}
+					/* Update Stats ?? */
 				}
-
-				if(rpl->SkbStat == SKB_DATA_COPY
-					|| rpl->SkbStat == SKB_DMA_DIRECT)
+				else
 				{
-					if(rpl->SkbStat == SKB_DATA_COPY)
-						memmove(skb->data, ReceiveDataPtr, Length);
-
-					/* Deliver frame to system */
-					rpl->Skb = NULL;
-					skb_trim(skb,Length);
-					skb->protocol = tr_type_trans(skb,dev);
-					netif_rx(skb);
+					skb->dev	= dev;
+					skb_put(skb, tp->MaxPacketSize);
+					rpl->SkbStat 	= SKB_DATA_COPY;
+					ReceiveDataPtr 	= rpl->MData;
 				}
 			}
+
+			if(rpl->SkbStat == SKB_DATA_COPY
+				|| rpl->SkbStat == SKB_DMA_DIRECT)
+			{
+				if(rpl->SkbStat == SKB_DATA_COPY)
+					memmove(skb->data, ReceiveDataPtr, Length);
+
+				/* Deliver frame to system */
+				rpl->Skb = NULL;
+				skb_trim(skb,Length);
+				skb->protocol = tr_type_trans(skb,dev);
+				netif_rx(skb);
+			}
 		}
 		else	/* Invalid frame */
 		{
 			if(rpl->Skb != NULL)
-				dev_kfree_skb(rpl->Skb);
+				dev_kfree_skb_irq(rpl->Skb);
 
 			/* Skip list. */
 			if(rpl->Status & RX_START_FRAME)
 				/* Frame start bit is set -> overflow. */
 				tp->MacStat.rx_errors++;
 		}
+		if (rpl->DMABuff)
+			pci_unmap_single(tp->pdev, rpl->DMABuff, tp->MaxPacketSize, PCI_DMA_TODEVICE);
+		rpl->DMABuff = 0;
 
 		/* Allocate new skb for rpl */
 		rpl->Skb = dev_alloc_skb(tp->MaxPacketSize);
-
 		/* skb == NULL ? then use local buffer */
 		if(rpl->Skb == NULL)
 		{
 			rpl->SkbStat = SKB_UNAVAILABLE;
-			rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex]));
+			rpl->FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[rpl->RPLIndex] - (char *)tp) + tp->dmabuffer);
 			rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
 		}
 		else	/* skb != NULL */
@@ -2201,18 +2234,20 @@
 			skb_put(rpl->Skb, tp->MaxPacketSize);
 
 			/* Data unreachable for DMA ? then use local buffer */
-			if(tp->dmalimit && virt_to_bus(rpl->Skb->data) + tp->MaxPacketSize > tp->dmalimit)
+			dmabuf = pci_map_single(tp->pdev, rpl->Skb->data, tp->MaxPacketSize, PCI_DMA_FROMDEVICE);
+			if(tp->dmalimit && (dmabuf + tp->MaxPacketSize > tp->dmalimit))
 			{
 				rpl->SkbStat = SKB_DATA_COPY;
-				rpl->FragList[0].DataAddr = htonl(virt_to_bus(tp->LocalRxBuffers[rpl->RPLIndex]));
+				rpl->FragList[0].DataAddr = htonl(((char *)tp->LocalRxBuffers[rpl->RPLIndex] - (char *)tp) + tp->dmabuffer);
 				rpl->MData = tp->LocalRxBuffers[rpl->RPLIndex];
 			}
 			else
 			{
 				/* DMA directly in skb->data */
 				rpl->SkbStat = SKB_DMA_DIRECT;
-				rpl->FragList[0].DataAddr = htonl(virt_to_bus(rpl->Skb->data));
+				rpl->FragList[0].DataAddr = htonl(dmabuf);
 				rpl->MData = rpl->Skb->data;
+				rpl->DMABuff = dmabuf;
 			}
 		}
 
@@ -2267,29 +2302,6 @@
 	return;
 }
 
-#if 0
-/*
- * 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 tms380tr_chk_frame(struct net_device *dev, unsigned char *Addr)
-{
-	int i;
-
-	for(i = 5; i > 0; i--)
-	{
-		if(Addr[8 + i] != dev->dev_addr[i])
-			return (0);
-	}
-
-	/* Mask out RIF bit. */
-	if((Addr[8] & ~TR_RII) != (unsigned char)(dev->dev_addr[0]))
-		return (0);
-
-	return (1);  /* It is my frame. */
-}
-#endif
-
 static int tms380tr_set_mac_address(struct net_device *dev, void *addr)
 {
 	struct net_local *tp = (struct net_local *)dev->priv;
@@ -2322,18 +2334,46 @@
 }
 #endif
 
-int tmsdev_init(struct net_device *dev)
+void tmsdev_term(struct net_device *dev)
+{
+	struct net_local *tp;
+
+	tp = (struct net_local *) dev->priv;
+	pci_unmap_single(tp->pdev, tp->dmabuffer, sizeof(struct net_local),
+		PCI_DMA_BIDIRECTIONAL);
+	kfree(dev->priv);
+}
+
+int tmsdev_init(struct net_device *dev, unsigned long dmalimit, 
+		struct pci_dev *pdev)
 {
 	if (dev->priv == NULL)
 	{
 		struct net_local *tms_local;
+		dma_addr_t buffer;
 		
 		dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL | GFP_DMA);
 		if (dev->priv == NULL)
+		{
+                        printk("%s: Out of memory for DMA\n",
+                                dev->name);
 			return -ENOMEM;
+		}
 		memset(dev->priv, 0, sizeof(struct net_local));
 		tms_local = (struct net_local *)dev->priv;
 		init_waitqueue_head(&tms_local->wait_for_tok_int);
+		tms_local->dmalimit = dmalimit;
+		tms_local->pdev = pdev;
+                buffer = pci_map_single(pdev, (void *)tms_local,
+                        sizeof(struct net_local), PCI_DMA_BIDIRECTIONAL);
+                if (buffer + sizeof(struct net_local) > dmalimit)
+                {
+			printk("%s: Memory not accessible for DMA\n",
+				dev->name);
+			tmsdev_term(dev);
+			return -ENOMEM;
+		}
+		tms_local->dmabuffer = buffer;
 	}
 	
 	/* These can be overridden by the card driver if needed */
@@ -2357,6 +2397,7 @@
 EXPORT_SYMBOL(tms380tr_close);
 EXPORT_SYMBOL(tms380tr_interrupt);
 EXPORT_SYMBOL(tmsdev_init);
+EXPORT_SYMBOL(tmsdev_term);
 EXPORT_SYMBOL(tms380tr_wait);
 
 struct module *TMS380_module = NULL;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/tms380tr.h linux/drivers/net/tokenring/tms380tr.h
--- v2.4.1/linux/drivers/net/tokenring/tms380tr.h	Wed Jan 26 13:16:05 2000
+++ linux/drivers/net/tokenring/tms380tr.h	Fri Feb 16 16:02:36 2001
@@ -15,7 +15,9 @@
 int tms380tr_open(struct net_device *dev);
 int tms380tr_close(struct net_device *dev);
 void tms380tr_interrupt(int irq, void *dev_id, struct pt_regs *regs);
-int tmsdev_init(struct net_device *dev);
+int tmsdev_init(struct net_device *dev, unsigned long dmalimit,
+		struct pci_dev *pdev);
+void tmsdev_term(struct net_device *dev);
 void tms380tr_wait(unsigned long time);
 
 #define TMS380TR_MAX_ADAPTERS 7
@@ -360,19 +362,19 @@
 					 */
 
 	/* Interrupt vectors the adapter places on attached system bus. */
-	unsigned char CMD_Status_IV;	/* Interrupt vector: command status. */
-	unsigned char TX_IV;		/* Interrupt vector: transmit. */
-	unsigned char RX_IV;		/* Interrupt vector: receive. */
-	unsigned char Ring_Status_IV;	/* Interrupt vector: ring status. */
-	unsigned char SCB_Clear_IV;	/* Interrupt vector: SCB clear. */
-	unsigned char Adapter_CHK_IV;	/* Interrupt vector: adapter check. */
-
-	unsigned short RX_Burst_Size;	/* Max. number of transfer cycles. */
-	unsigned short TX_Burst_Size;	/* During DMA burst; even value! */
-	unsigned short DMA_Abort_Thrhld;/* Number of DMA retries. */
+	u_int8_t  CMD_Status_IV;    /* Interrupt vector: command status. */
+	u_int8_t  TX_IV;	    /* Interrupt vector: transmit. */
+	u_int8_t  RX_IV;	    /* Interrupt vector: receive. */
+	u_int8_t  Ring_Status_IV;   /* Interrupt vector: ring status. */
+	u_int8_t  SCB_Clear_IV;	    /* Interrupt vector: SCB clear. */
+	u_int8_t  Adapter_CHK_IV;   /* Interrupt vector: adapter check. */
+
+	u_int16_t RX_Burst_Size;    /* Max. number of transfer cycles. */
+	u_int16_t TX_Burst_Size;    /* During DMA burst; even value! */
+	u_int16_t DMA_Abort_Thrhld; /* Number of DMA retries. */
 
-	unsigned long SCB_Addr;	/* SCB address: even, word aligned, high-low */
-	unsigned long SSB_Addr;	/* SSB address: even, word aligned, high-low */
+	u_int32_t SCB_Addr;   /* SCB address: even, word aligned, high-low */
+	u_int32_t SSB_Addr;   /* SSB address: even, word aligned, high-low */
 } IPB, *IPB_Ptr;
 #pragma pack()
 
@@ -463,35 +465,35 @@
 
 #pragma pack(1)
 typedef struct {
-	unsigned short OPENOptions;
-	unsigned char NodeAddr[6];	/* Adapter node address; use ROM 
-					 * address
-					 */
-	unsigned long GroupAddr;	/* Multicast: high order
-					 * bytes = 0xC000
-					 */
-	unsigned long FunctAddr;	/* High order bytes = 0xC000 */
-	unsigned short RxListSize;	/* RPL size: 0 (=26), 14, 20 or
-					 * 26 bytes read by the adapter.
-					 * (Depending on the number of 
-					 * fragments/list)
-					 */
-	unsigned short TxListSize;	/* TPL size */
-	unsigned short BufSize;		/* Is automatically rounded up to the
-					 * nearest nK boundary.
-					 */
-	unsigned short FullDuplex;
-	unsigned short Reserved;
-	unsigned char TXBufMin;		/* Number of adapter buffers reserved
-					 * for transmission a minimum of 2
-					 * buffers must be allocated.
-					 */
-	unsigned char TXBufMax;		/* Maximum number of adapter buffers
-					 * for transmit; a minimum of 2 buffers
-					 * must be available for receive.
-					 * Default: 6
-					 */
-	unsigned short ProdIDAddr[2];	/* Pointer to product ID. */
+	u_int16_t OPENOptions;
+	u_int8_t  NodeAddr[6];	/* Adapter node address; use ROM 
+				 * address
+				 */
+	u_int32_t GroupAddr;	/* Multicast: high order
+				 * bytes = 0xC000
+				 */
+	u_int32_t FunctAddr;	/* High order bytes = 0xC000 */
+	u_int16_t RxListSize;	/* RPL size: 0 (=26), 14, 20 or
+				 * 26 bytes read by the adapter.
+				 * (Depending on the number of 
+				 * fragments/list)
+				 */
+	u_int16_t TxListSize;	/* TPL size */
+	u_int16_t BufSize;	/* Is automatically rounded up to the
+				 * nearest nK boundary.
+				 */
+	u_int16_t FullDuplex;
+	u_int16_t Reserved;
+	u_int8_t  TXBufMin;	/* Number of adapter buffers reserved
+				 * for transmission a minimum of 2
+				 * buffers must be allocated.
+				 */
+	u_int8_t  TXBufMax;	/* Maximum number of adapter buffers
+				 * for transmit; a minimum of 2 buffers
+				 * must be available for receive.
+				 * Default: 6
+				 */
+	u_int16_t ProdIDAddr[2];/* Pointer to product ID. */
 } OPB, *OPB_Ptr;
 #pragma pack()
 
@@ -502,8 +504,8 @@
  */
 #pragma pack(1)
 typedef struct {
-	unsigned short CMD;	/* Command code */
-	unsigned short Parm[2];	/* Pointer to Command Parameter Block */
+	u_int16_t CMD;		/* Command code */
+	u_int16_t Parm[2];	/* Pointer to Command Parameter Block */
 } SCB;	/* System Command Block (32 bit physical address; big endian)*/
 #pragma pack()
 
@@ -515,8 +517,8 @@
  */
 #pragma pack(1)
 typedef struct {
-	unsigned short STS;	/* Status code */
-	unsigned short Parm[3];	/* Parameter or pointer to Status Parameter
+	u_int16_t STS;		/* Status code */
+	u_int16_t Parm[3];	/* Parameter or pointer to Status Parameter
 				 * Block.
 				 */
 } SSB;	/* System Status Block (big endian - physical address)  */
@@ -539,33 +541,33 @@
 
 #pragma pack(1)
 typedef struct {
-	unsigned char Line_Error;	/* Line error: code violation in
+	u_int8_t  Line_Error;		/* Line error: code violation in
 					 * frame or in a token, or FCS error.
 					 */
-	unsigned char Internal_Error;	/* IBM specific. (Reserved_1) */
-	unsigned char Burst_Error;
-	unsigned char ARI_FCI_Error;	/* ARI/FCI bit zero in AMP or
+	u_int8_t  Internal_Error;	/* IBM specific. (Reserved_1) */
+	u_int8_t  Burst_Error;
+	u_int8_t  ARI_FCI_Error;	/* ARI/FCI bit zero in AMP or
 					 * SMP MAC frame.
 					 */
-	unsigned char AbortDelimeters;	/* IBM specific. (Reserved_2) */
-	unsigned char Reserved_3;
-	unsigned char Lost_Frame_Error;	/* Receive of end of transmitted
+	u_int8_t  AbortDelimeters;	/* IBM specific. (Reserved_2) */
+	u_int8_t  Reserved_3;
+	u_int8_t  Lost_Frame_Error;	/* Receive of end of transmitted
 					 * frame failed.
 					 */
-	unsigned char Rx_Congest_Error;	/* Adapter in repeat mode has not
+	u_int8_t  Rx_Congest_Error;	/* Adapter in repeat mode has not
 					 * enough buffer space to copy incoming
 					 * frame.
 					 */
-	unsigned char Frame_Copied_Error;/* ARI bit not zero in frame
+	u_int8_t  Frame_Copied_Error;	/* ARI bit not zero in frame
 					 * addressed to adapter.
 					 */
-	unsigned char Frequency_Error;	/* IBM specific. (Reserved_4) */
-	unsigned char Token_Error;	/* (active only in monitor station) */
-	unsigned char Reserved_5;
-	unsigned char DMA_Bus_Error;	/* DMA bus errors not exceeding the
+	u_int8_t  Frequency_Error;	/* IBM specific. (Reserved_4) */
+	u_int8_t  Token_Error;		/* (active only in monitor station) */
+	u_int8_t  Reserved_5;
+	u_int8_t  DMA_Bus_Error;	/* DMA bus errors not exceeding the
 					 * abort thresholds.
 					 */
-	unsigned char DMA_Parity_Error;	/* DMA parity errors not exceeding
+	u_int8_t  DMA_Parity_Error;	/* DMA parity errors not exceeding
 					 * the abort thresholds.
 					 */
 } ERRORTAB;	/* Adapter error counters */
@@ -575,16 +577,16 @@
 /*--------------------- Send and Receive definitions -------------------*/
 #pragma pack(1)
 typedef struct {
-	unsigned short DataCount;	/* Value 0, even and odd values are
-					 * permitted; value is unaltered most
-					 * significant bit set: following
-					 * fragments last fragment: most
-					 * significant bit is not evaluated.
-					 * (???)
-					 */
-	unsigned long DataAddr;		/* Pointer to frame data fragment;
-					 * even or odd.
-					 */
+	u_int16_t DataCount;	/* Value 0, even and odd values are
+				 * permitted; value is unaltered most
+				 * significant bit set: following
+				 * fragments last fragment: most
+				 * significant bit is not evaluated.
+				 * (???)
+				 */
+	u_int32_t DataAddr;	/* Pointer to frame data fragment;
+				 * even or odd.
+				 */
 } Fragment;
 #pragma pack()
 
@@ -675,17 +677,17 @@
 typedef struct s_TPL TPL;
 
 struct s_TPL {	/* Transmit Parameter List (align on even word boundaries) */
-	unsigned long NextTPLAddr;	/* Pointer to next TPL in chain; if
+	u_int32_t NextTPLAddr;		/* Pointer to next TPL in chain; if
 					 * pointer is odd: this is the last
 					 * TPL. Pointing to itself can cause
 					 * problems!
 					 */
-	volatile unsigned short Status;	/* Initialized by the adapter:
+	volatile u_int16_t Status;	/* Initialized by the adapter:
 					 * CSTAT_REQUEST important: update least
 					 * significant bit first! Set by the
 					 * adapter: CSTAT_COMPLETE status.
 					 */
-	unsigned short FrameSize;	/* Number of bytes to be transmitted
+	u_int16_t FrameSize;		/* Number of bytes to be transmitted
 					 * as a frame including AC/FC,
 					 * Destination, Source, Routing field
 					 * not including CRC, FS, End Delimiter
@@ -714,6 +716,7 @@
 	struct sk_buff *Skb;
 	unsigned char TPLIndex;
 	volatile unsigned char BusyFlag;/* Flag: TPL busy? */
+	dma_addr_t DMABuff;		/* DMA IO bus address from pci_map */
 };
 
 /* ---------------------Receive Functions-------------------------------*
@@ -1015,18 +1018,18 @@
 #pragma pack(1)
 typedef struct s_RPL RPL;
 struct s_RPL {	/* Receive Parameter List */
-	unsigned long NextRPLAddr;	/* Pointer to next RPL in chain
+	u_int32_t NextRPLAddr;		/* Pointer to next RPL in chain
 					 * (normalized = physical 32 bit
 					 * address) if pointer is odd: this
 					 * is last RPL. Pointing to itself can
 					 * cause problems!
 					 */
-	volatile unsigned short Status;	/* Set by creation of Receive Parameter
+	volatile u_int16_t Status;	/* Set by creation of Receive Parameter
 					 * List RECEIVE_CSTAT_COMPLETE set by
 					 * adapter in lists that start or end
 					 * a frame.
 					 */
-	volatile unsigned short FrameSize; /* Number of bytes received as a
+	volatile u_int16_t FrameSize;	 /* Number of bytes received as a
 					 * frame including AC/FC, Destination,
 					 * Source, Routing field not including 
 					 * CRC, FS (Frame Status), End Delimiter
@@ -1054,6 +1057,7 @@
 	struct sk_buff *Skb;
 	SKB_STAT SkbStat;
 	int RPLIndex;
+	dma_addr_t DMABuff;		/* DMA IO bus address from pci_map */
 };
 
 /* Information that need to be kept for each board. */
@@ -1084,6 +1088,7 @@
 	RPL *RplTail;
 	unsigned char LocalRxBuffers[RPL_NUM][DEFAULT_PACKET_SIZE];
 
+	struct pci_dev *pdev;
 	int DataRate;
 	unsigned char ScbInUse;
 	unsigned short CMDqueue;
@@ -1111,6 +1116,9 @@
 	struct tr_statistics MacStat;	/* MAC statistics structure */
 
 	unsigned long dmalimit; /* the max DMA address (ie, ISA) */
+	dma_addr_t    dmabuffer; /* the DMA bus address corresponding to
+				    priv. Might be different from virt_to_bus()
+				    for architectures with IO MMU (Alpha) */
 
 	struct timer_list timer;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/tmsisa.c linux/drivers/net/tokenring/tmsisa.c
--- v2.4.1/linux/drivers/net/tokenring/tmsisa.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/tokenring/tmsisa.c	Fri Feb 16 16:02:36 2001
@@ -0,0 +1,464 @@
+/*
+ *  tmsisa.c: A generic network driver for TMS380-based ISA token ring cards.
+ *
+ *  Based on tmspci written 1999 by Adam Fritzler
+ *  
+ *  Written 2000 by Jochen Friedrich
+ *  Dedicated to my girlfriend Steffi Bopp
+ *
+ *  This software may be used and distributed according to the terms
+ *  of the GNU Public License, incorporated herein by reference.
+ *
+ *  This driver module supports the following cards:
+ *	- SysKonnect TR4/16(+) ISA	(SK-4190)
+ *
+ *  Maintainer(s):
+ *    AF        Adam Fritzler           mid@auk.cx
+ *    JF	Jochen Friedrich	jochen@scram.de
+ *
+ *  TODO:
+ *	1. Add support for Proteon TR ISA adapters (1392, 1392+)
+ */
+static const char *version = "tmsisa.c: v1.00 14/01/2001 by Jochen Friedrich\n";
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/pci.h>
+#include <asm/dma.h>
+
+#include <linux/netdevice.h>
+#include <linux/trdevice.h>
+#include "tms380tr.h"
+
+#define TMS_ISA_IO_EXTENT 32
+
+/* A zero-terminated list of I/O addresses to be probed. */
+static unsigned int portlist[] __initdata = {
+	0x0A20, 0x1A20, 0x0B20, 0x1B20, 0x0980, 0x1980, 0x0900, 0x1900,// SK
+	0
+};
+
+/* A zero-terminated list of IRQs to be probed. 
+ * Used again after initial probe for sktr_chipset_init, called from sktr_open.
+ */
+static unsigned short irqlist[] = {
+	3, 5, 9, 10, 11, 12, 15,
+	0
+};
+
+/* A zero-terminated list of DMAs to be probed. */
+static int dmalist[] __initdata = {
+	5, 6, 7,
+	0
+};
+
+static char *isa_cardname = "SK NET TR 4/16 ISA\0";
+
+int tms_isa_probe(struct net_device *dev);
+static int tms_isa_open(struct net_device *dev);
+static int tms_isa_close(struct net_device *dev);
+static void tms_isa_read_eeprom(struct net_device *dev);
+static unsigned short tms_isa_setnselout_pins(struct net_device *dev);
+
+static unsigned short tms_isa_sifreadb(struct net_device *dev, unsigned short reg)
+{
+	return inb(dev->base_addr + reg);
+}
+
+static unsigned short tms_isa_sifreadw(struct net_device *dev, unsigned short reg)
+{
+	return inw(dev->base_addr + reg);
+}
+
+static void tms_isa_sifwriteb(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	outb(val, dev->base_addr + reg);
+}
+
+static void tms_isa_sifwritew(struct net_device *dev, unsigned short val, unsigned short reg)
+{
+	outw(val, dev->base_addr + reg);
+}
+
+struct tms_isa_card {
+	struct net_device *dev;
+	struct tms_isa_card *next;
+};
+
+static struct tms_isa_card *tms_isa_card_list = NULL;
+
+static int __init tms_isa_probe1(int ioaddr)
+{
+	unsigned char old, chk1, chk2;
+
+	old = inb(ioaddr + SIFADR);	/* Get the old SIFADR value */
+
+	chk1 = 0;	/* Begin with check value 0 */
+	do {
+		/* Write new SIFADR value */
+		outb(chk1, ioaddr + SIFADR);
+
+		/* Read, invert and write */
+		chk2 = inb(ioaddr + SIFADD);
+		chk2 ^= 0x0FE;
+		outb(chk2, ioaddr + SIFADR);
+
+		/* Read, invert and compare */
+		chk2 = inb(ioaddr + SIFADD);
+		chk2 ^= 0x0FE;
+
+		if(chk1 != chk2)
+			return (-1);	/* No adapter */
+
+		chk1 -= 2;
+	} while(chk1 != 0);	/* Repeat 128 times (all byte values) */
+
+    	/* Restore the SIFADR value */
+	outb(old, ioaddr + SIFADR);
+
+	return (0);
+}
+
+int __init tms_isa_probe(struct net_device *dev)
+{
+        static int versionprinted = 0;
+	struct net_local *tp;
+	int j;
+	struct tms_isa_card *card;
+
+	if(check_region(dev->base_addr, TMS_ISA_IO_EXTENT))
+		return -1;
+
+	if(tms_isa_probe1(dev->base_addr))
+		return -1;
+   
+	if (versionprinted++ == 0)
+		printk("%s", version);
+ 
+	/* At this point we have found a valid card. */
+    
+	if (!request_region(dev->base_addr, TMS_ISA_IO_EXTENT, isa_cardname))
+		return -1;
+
+	if (tmsdev_init(dev, ISA_MAX_ADDRESS, NULL))
+       	{
+		release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+		return -1;
+	}
+
+	dev->base_addr &= ~3; 
+		
+	tms_isa_read_eeprom(dev);
+
+	printk("%s:    Ring Station Address: ", dev->name);
+	printk("%2.2x", dev->dev_addr[0]);
+	for (j = 1; j < 6; j++)
+		printk(":%2.2x", dev->dev_addr[j]);
+	printk("\n");
+		
+	tp = (struct net_local *)dev->priv;
+	tp->setnselout = tms_isa_setnselout_pins;
+		
+	tp->sifreadb = tms_isa_sifreadb;
+	tp->sifreadw = tms_isa_sifreadw;
+	tp->sifwriteb = tms_isa_sifwriteb;
+	tp->sifwritew = tms_isa_sifwritew;
+	
+	memcpy(tp->ProductID, isa_cardname, PROD_ID_SIZE + 1);
+
+	tp->tmspriv = NULL;
+
+	dev->open = tms_isa_open;
+	dev->stop = tms_isa_close;
+
+	if (dev->irq == 0)
+	{
+		for(j = 0; irqlist[j] != 0; j++)
+		{
+			dev->irq = irqlist[j];
+			if (!request_irq(dev->irq, tms380tr_interrupt, 0, 
+				isa_cardname, dev))
+				break;
+                }
+		
+                if(irqlist[j] == 0)
+                {
+                        printk("%s: AutoSelect no IRQ available\n", dev->name);
+			release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+			tmsdev_term(dev);
+			return -1;
+		}
+	}
+	else
+	{
+		for(j = 0; irqlist[j] != 0; j++)
+			if (irqlist[j] == dev->irq)
+				break;
+		if (irqlist[j] == 0)
+		{
+			printk("%s: Illegal IRQ %d specified\n",
+				dev->name, dev->irq);
+			release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+			tmsdev_term(dev);
+			return -1;
+		}
+		if (request_irq(dev->irq, tms380tr_interrupt, 0, 
+			isa_cardname, dev))
+		{
+                        printk("%s: Selected IRQ %d not available\n", 
+				dev->name, dev->irq);
+			release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+			tmsdev_term(dev);
+			return -1;
+		}
+	}
+
+	if (dev->dma == 0)
+	{
+		for(j = 0; dmalist[j] != 0; j++)
+		{
+			dev->dma = dmalist[j];
+                        if (!request_dma(dev->dma, isa_cardname))
+				break;
+		}
+
+		if(dmalist[j] == 0)
+		{
+			printk("%s: AutoSelect no DMA available\n", dev->name);
+			release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+			free_irq(dev->irq, dev);
+			tmsdev_term(dev);
+			return -1;
+		}
+	}
+	else
+	{
+		for(j = 0; dmalist[j] != 0; j++)
+			if (dmalist[j] == dev->dma)
+				break;
+		if (dmalist[j] == 0)
+		{
+                        printk("%s: Illegal DMA %d specified\n", 
+				dev->name, dev->dma);
+			release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+			free_irq(dev->irq, dev);
+			tmsdev_term(dev);
+			return -1;
+		}
+		if (request_dma(dev->dma, isa_cardname))
+		{
+                        printk("%s: Selected DMA %d not available\n", 
+				dev->name, dev->dma);
+			release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+			free_irq(dev->irq, dev);
+			tmsdev_term(dev);
+			return -1;
+		}
+	}
+
+	printk("%s:    IO: %#4lx  IRQ: %d  DMA: %d\n",
+	       dev->name, dev->base_addr, dev->irq, dev->dma);
+		
+	if (register_trdev(dev) == 0) 
+	{
+		/* Enlist in the card list */
+		card = kmalloc(sizeof(struct tms_isa_card), GFP_KERNEL);
+		card->next = tms_isa_card_list;
+		tms_isa_card_list = card;
+		card->dev = dev;
+	} 
+	else 
+	{
+		printk("%s: register_trdev() returned non-zero.\n", dev->name);
+		release_region(dev->base_addr, TMS_ISA_IO_EXTENT); 
+		free_irq(dev->irq, dev);
+		free_dma(dev->dma);
+		tmsdev_term(dev);
+		return -1;
+	}
+	
+	return 0;
+}
+
+/*
+ * Reads MAC address from adapter RAM, which should've read it from
+ * the onboard ROM.  
+ *
+ * Calling this on a board that does not support it can be a very
+ * dangerous thing.  The Madge board, for instance, will lock your
+ * machine hard when this is called.  Luckily, its supported in a
+ * seperate driver.  --ASF
+ */
+static void tms_isa_read_eeprom(struct net_device *dev)
+{
+	int i;
+	
+	/* Address: 0000:0000 */
+	tms_isa_sifwritew(dev, 0, SIFADX);
+	tms_isa_sifwritew(dev, 0, SIFADR);	
+	
+	/* Read six byte MAC address data */
+	dev->addr_len = 6;
+	for(i = 0; i < 6; i++)
+		dev->dev_addr[i] = tms_isa_sifreadw(dev, SIFINC) >> 8;
+}
+
+unsigned short tms_isa_setnselout_pins(struct net_device *dev)
+{
+	return 0;
+}
+
+static int tms_isa_open(struct net_device *dev)
+{  
+	struct net_local *tp = (struct net_local *)dev->priv;
+	unsigned short val = 0;
+	unsigned short oldval;
+	int i;
+
+	val = 0;
+	for(i = 0; irqlist[i] != 0; i++)
+	{
+		if(irqlist[i] == dev->irq)
+			break;
+	}
+
+	val |= CYCLE_TIME << 2;
+	val |= i << 4;
+	i = dev->dma - 5;
+	val |= i;
+	if(tp->DataRate == SPEED_4)
+		val |= LINE_SPEED_BIT;
+	else
+		val &= ~LINE_SPEED_BIT;
+	oldval = tms_isa_sifreadb(dev, POSREG);
+	/* Leave cycle bits alone */
+	oldval |= 0xf3;
+	val &= oldval;
+	tms_isa_sifwriteb(dev, val, POSREG);
+
+	tms380tr_open(dev);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int tms_isa_close(struct net_device *dev)
+{
+	tms380tr_close(dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+#ifdef MODULE
+
+#define ISATR_MAX_ADAPTERS 3
+
+static int io[ISATR_MAX_ADAPTERS];
+static int irq[ISATR_MAX_ADAPTERS];
+static int dma[ISATR_MAX_ADAPTERS];
+
+MODULE_PARM(io, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
+MODULE_PARM(irq, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
+MODULE_PARM(dma, "1-" __MODULE_STRING(ISATR_MAX_ADAPTERS) "i");
+
+int init_module(void)
+{
+	int i, num;
+	struct net_device *dev;
+
+	num = 0;
+	if (io[0]) 
+	{ /* Only probe addresses from command line */
+		for (i = 0; i < ISATR_MAX_ADAPTERS; i++)
+	       	{
+			if (io[i] == 0)
+				continue;
+
+			dev = init_trdev(NULL, 0);
+			if (!dev)
+				return (-ENOMEM);
+		
+			dev->base_addr = io[i];
+			dev->irq       = irq[i];
+			dev->dma       = dma[i];
+
+			if (tms_isa_probe(dev))
+			{
+				unregister_netdev(dev);
+				kfree(dev);
+			}
+			else
+				num++;
+		}
+	}
+       	else
+       	{
+		for(i = 0; portlist[i]; i++)
+		{
+			if (num >= ISATR_MAX_ADAPTERS)
+				continue;
+
+			dev = init_trdev(NULL, 0);
+			if (!dev)
+				return (-ENOMEM);
+		
+			dev->base_addr = portlist[i];
+			dev->irq       = irq[num];
+			dev->dma       = dma[num];
+
+			if (tms_isa_probe(dev))
+			{
+				unregister_netdev(dev);
+				kfree(dev);
+			}
+			else
+				num++;
+		}
+	}
+	printk(KERN_NOTICE "tmsisa.c: %d cards found.\n", num);
+	/* Probe for cards. */
+	if (num == 0) {
+		printk(KERN_NOTICE "tmsisa.c: No cards found.\n");
+	}
+	return (0);
+}
+
+void cleanup_module(void)
+{
+	struct net_device *dev;
+	struct tms_isa_card *this_card;
+
+	while (tms_isa_card_list) {
+		dev = tms_isa_card_list->dev;
+		
+		unregister_netdev(dev);
+		release_region(dev->base_addr, TMS_ISA_IO_EXTENT);
+		free_irq(dev->irq, dev);
+		free_dma(dev->dma);
+		tmsdev_term(dev);
+		kfree(dev);
+		this_card = tms_isa_card_list;
+		tms_isa_card_list = this_card->next;
+		kfree(this_card);
+	}
+}
+#endif /* MODULE */
+
+
+/*
+ * Local variables:
+ *  compile-command: "gcc -DMODVERSIONS  -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmsisa.c"
+ *  alt-compile-command: "gcc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer -I/usr/src/linux/drivers/net/tokenring/ -c tmsisa.c"
+ *  c-set-style "K&R"
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ *  tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tokenring/tmspci.c linux/drivers/net/tokenring/tmspci.c
--- v2.4.1/linux/drivers/net/tokenring/tmspci.c	Tue Dec  5 12:29:39 2000
+++ linux/drivers/net/tokenring/tmspci.c	Fri Feb 16 16:02:36 2001
@@ -4,7 +4,7 @@
  *  Written 1999 by Adam Fritzler
  *
  *  This software may be used and distributed according to the terms
- *  of the GNU Public License, incorporated herein by reference.
+ *  of the GNU General Public License, incorporated herein by reference.
  *
  *  This driver module supports the following cards:
  *	- SysKonnect TR4/16(+) PCI	(SK-4590)
@@ -142,14 +142,14 @@
 		printk(":%2.2x", dev->dev_addr[i]);
 	printk("\n");
 		
-	ret = tmsdev_init(dev);
+	ret = tmsdev_init(dev,0, pdev);
+	/* XXX: should be the max PCI32 DMA max */
 	if (ret) {
 		printk("%s: unable to get memory for dev->priv.\n", dev->name);
 		goto err_out_irq;
 	}
 
 	tp = dev->priv;
-	tp->dmalimit = 0; /* XXX: should be the max PCI32 DMA max */
 	tp->setnselout = tms_pci_setnselout_pins;
 		
 	tp->sifreadb = tms_pci_sifreadb;
@@ -172,7 +172,7 @@
 	return 0;
 
 err_out_tmsdev:
-	kfree(dev->priv);
+	tmsdev_term(dev);
 err_out_irq:
 	free_irq(pdev->irq, dev);
 err_out_region:
@@ -228,7 +228,7 @@
 	unregister_netdev(dev);
 	release_region(dev->base_addr, TMS_PCI_IO_EXTENT);
 	free_irq(dev->irq, dev);
-	kfree(dev->priv);
+	tmsdev_term(dev);
 	kfree(dev);
 	pci_set_drvdata(pdev, NULL);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/21142.c linux/drivers/net/tulip/21142.c
--- v2.4.1/linux/drivers/net/tulip/21142.c	Tue Nov  7 11:08:09 2000
+++ linux/drivers/net/tulip/21142.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please refer to Documentation/networking/tulip.txt for more
 	information on this driver.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/eeprom.c linux/drivers/net/tulip/eeprom.c
--- v2.4.1/linux/drivers/net/tulip/eeprom.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/tulip/eeprom.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please refer to Documentation/networking/tulip.txt for more
 	information on this driver.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/interrupt.c linux/drivers/net/tulip/interrupt.c
--- v2.4.1/linux/drivers/net/tulip/interrupt.c	Tue Nov  7 11:08:09 2000
+++ linux/drivers/net/tulip/interrupt.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please refer to Documentation/networking/tulip.txt for more
 	information on this driver.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/media.c linux/drivers/net/tulip/media.c
--- v2.4.1/linux/drivers/net/tulip/media.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/tulip/media.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please refer to Documentation/networking/tulip.txt for more
 	information on this driver.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/pnic.c linux/drivers/net/tulip/pnic.c
--- v2.4.1/linux/drivers/net/tulip/pnic.c	Mon Jun 19 13:42:39 2000
+++ linux/drivers/net/tulip/pnic.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please refer to Documentation/networking/tulip.txt for more
 	information on this driver.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/timer.c linux/drivers/net/tulip/timer.c
--- v2.4.1/linux/drivers/net/tulip/timer.c	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/tulip/timer.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please refer to Documentation/networking/tulip.txt for more
 	information on this driver.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/tulip.h linux/drivers/net/tulip/tulip.h
--- v2.4.1/linux/drivers/net/tulip/tulip.h	Sat Dec 30 11:23:14 2000
+++ linux/drivers/net/tulip/tulip.h	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tulip/tulip_core.c linux/drivers/net/tulip/tulip_core.c
--- v2.4.1/linux/drivers/net/tulip/tulip_core.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/tulip/tulip_core.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Written/copyright 1994-1999 by Donald Becker.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	Please read Documentation/networking/tulip.txt for more
 	information.
diff -u --recursive --new-file v2.4.1/linux/drivers/net/tun.c linux/drivers/net/tun.c
--- v2.4.1/linux/drivers/net/tun.c	Sun Dec  3 17:45:22 2000
+++ linux/drivers/net/tun.c	Tue Feb 13 13:15:05 2001
@@ -28,7 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
@@ -224,6 +224,7 @@
 	if (tun->flags & TUN_NOCHECKSUM)
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
  
+	skb->dev->last_rx = jiffies;
 	netif_rx(skb);
    
 	tun->stats.rx_packets++;
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/cosa.c linux/drivers/net/wan/cosa.c
--- v2.4.1/linux/drivers/net/wan/cosa.c	Sat Dec 30 18:16:13 2000
+++ linux/drivers/net/wan/cosa.c	Tue Feb 13 13:15:05 2001
@@ -82,7 +82,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
 #include <linux/fs.h>
 #include <linux/devfs_fs_kernel.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/cycx_main.c linux/drivers/net/wan/cycx_main.c
--- v2.4.1/linux/drivers/net/wan/cycx_main.c	Sun Aug 13 10:21:20 2000
+++ linux/drivers/net/wan/cycx_main.c	Tue Feb 13 13:15:05 2001
@@ -38,7 +38,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
 #include <linux/module.h>	/* support for loadable modules */
 #include <linux/ioport.h>	/* request_region(), release_region() */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/cycx_x25.c linux/drivers/net/wan/cycx_x25.c
--- v2.4.1/linux/drivers/net/wan/cycx_x25.c	Thu May  4 11:31:21 2000
+++ linux/drivers/net/wan/cycx_x25.c	Tue Feb 13 13:15:05 2001
@@ -82,7 +82,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <asm/byteorder.h>	/* htons(), etc. */
 #include <linux/if_arp.h>       /* ARPHRD_HWX25 */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/dlci.c linux/drivers/net/wan/dlci.c
--- v2.4.1/linux/drivers/net/wan/dlci.c	Tue May  2 12:41:00 2000
+++ linux/drivers/net/wan/dlci.c	Tue Feb 13 13:15:05 2001
@@ -39,7 +39,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/init.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/lmc/lmc_ioctl.h linux/drivers/net/wan/lmc/lmc_ioctl.h
--- v2.4.1/linux/drivers/net/wan/lmc/lmc_ioctl.h	Fri Apr 21 16:08:45 2000
+++ linux/drivers/net/wan/lmc/lmc_ioctl.h	Tue Feb 13 13:15:05 2001
@@ -13,7 +13,7 @@
   * Matt Thomas (matt@3am-software.com).
   *
   * This software may be used and distributed according to the terms
-  * of the GNU Public License version 2, incorporated herein by reference.
+  * of the GNU General Public License version 2, incorporated herein by reference.
   */
 
 #define LMCIOCGINFO             SIOCDEVPRIVATE+3 /* get current state */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/lmc/lmc_main.c linux/drivers/net/wan/lmc/lmc_main.c
--- v2.4.1/linux/drivers/net/wan/lmc/lmc_main.c	Tue Jul 11 11:12:24 2000
+++ linux/drivers/net/wan/lmc/lmc_main.c	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
   * Allan Cox
   *
   * This software may be used and distributed according to the terms
-  * of the GNU Public License version 2, incorporated herein by reference.
+  * of the GNU General Public License version 2, incorporated herein by reference.
   *
   * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.
   *
@@ -46,7 +46,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/lmc/lmc_media.c linux/drivers/net/wan/lmc/lmc_media.c
--- v2.4.1/linux/drivers/net/wan/lmc/lmc_media.c	Fri Apr 21 16:08:45 2000
+++ linux/drivers/net/wan/lmc/lmc_media.c	Tue Feb 13 13:15:05 2001
@@ -9,7 +9,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/segment.h>
@@ -56,7 +56,7 @@
   * Matt Thomas (matt@3am-software.com).
   *
   * This software may be used and distributed according to the terms
-  * of the GNU Public License version 2, incorporated herein by reference.
+  * of the GNU General Public License version 2, incorporated herein by reference.
   */
 
 /*
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/lmc/lmc_proto.c linux/drivers/net/wan/lmc/lmc_proto.c
--- v2.4.1/linux/drivers/net/wan/lmc/lmc_proto.c	Fri Apr 21 16:38:26 2000
+++ linux/drivers/net/wan/lmc/lmc_proto.c	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
   * Allan Cox
   *
   * This software may be used and distributed according to the terms
-  * of the GNU Public License version 2, incorporated herein by reference.
+  * of the GNU General Public License version 2, incorporated herein by reference.
   *
   * Driver for the LanMedia LMC5200, LMC5245, LMC1000, LMC1200 cards.
   */
@@ -27,7 +27,7 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <asm/segment.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/lmc/lmc_var.h linux/drivers/net/wan/lmc/lmc_var.h
--- v2.4.1/linux/drivers/net/wan/lmc/lmc_var.h	Mon Dec 11 12:59:54 2000
+++ linux/drivers/net/wan/lmc/lmc_var.h	Tue Feb 13 13:15:05 2001
@@ -14,7 +14,7 @@
   * Matt Thomas (matt@3am-software.com).
   *
   * This software may be used and distributed according to the terms
-  * of the GNU Public License version 2, incorporated herein by reference.
+  * of the GNU General Public License version 2, incorporated herein by reference.
   */
 
 #include <linux/timer.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/lmc/lmc_ver.h linux/drivers/net/wan/lmc/lmc_ver.h
--- v2.4.1/linux/drivers/net/wan/lmc/lmc_ver.h	Fri Apr 21 16:08:45 2000
+++ linux/drivers/net/wan/lmc/lmc_ver.h	Tue Feb 13 13:15:05 2001
@@ -12,7 +12,7 @@
   * Matt Thomas (matt@3am-software.com).
   *
   * This software may be used and distributed according to the terms
-  * of the GNU Public License version 2, incorporated herein by reference.
+  * of the GNU General Public License version 2, incorporated herein by reference.
   */
 
  /*
@@ -25,7 +25,7 @@
   * made the souce code not only hard to read but version problems hard
   * to track down.  If I'm overiding a function/etc with something in
   * this file it will be prefixed by "LMC_" which will mean look
-  * here for the the version dependant change that's been done.
+  * here for the version dependant change that's been done.
   *
   */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sbni.c linux/drivers/net/wan/sbni.c
--- v2.4.1/linux/drivers/net/wan/sbni.c	Sat Aug 12 20:45:48 2000
+++ linux/drivers/net/wan/sbni.c	Tue Feb 13 13:15:05 2001
@@ -5,7 +5,7 @@
  * Written 1999 by Yaroslav Polyakov (xenon@granch.ru).
  *
  * This software may be used and distributed according to the terms
- * of the GNU Public License, incorporated herein by reference.
+ * of the GNU General Public License, incorporated herein by reference.
  * 
  *   // Whole developers team:
  *   //   Yaroslav Polyakov (xenon@granch.ru)
@@ -66,7 +66,7 @@
 #include <linux/fcntl.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sdla.c linux/drivers/net/wan/sdla.c
--- v2.4.1/linux/drivers/net/wan/sdla.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/net/wan/sdla.c	Tue Feb 13 13:15:05 2001
@@ -43,7 +43,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sdla_chdlc.c linux/drivers/net/wan/sdla_chdlc.c
--- v2.4.1/linux/drivers/net/wan/sdla_chdlc.c	Tue Jul 11 11:12:24 2000
+++ linux/drivers/net/wan/sdla_chdlc.c	Tue Feb 13 13:15:05 2001
@@ -28,7 +28,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
@@ -867,7 +867,7 @@
 		card->devname);
 
 	/* unbusy the interface */
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sdla_fr.c linux/drivers/net/wan/sdla_fr.c
--- v2.4.1/linux/drivers/net/wan/sdla_fr.c	Tue Jul 11 11:12:24 2000
+++ linux/drivers/net/wan/sdla_fr.c	Tue Feb 13 13:15:05 2001
@@ -114,7 +114,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
@@ -1133,7 +1133,7 @@
 
 	printk (KERN_INFO "%s: Transmit timed out\n", chan->name);
 	chan->drvstats_if_send.if_send_tbusy_timeout++;
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sdla_ppp.c linux/drivers/net/wan/sdla_ppp.c
--- v2.4.1/linux/drivers/net/wan/sdla_ppp.c	Thu May  4 11:31:21 2000
+++ linux/drivers/net/wan/sdla_ppp.c	Tue Feb 13 13:15:05 2001
@@ -80,7 +80,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <linux/if_arp.h>	/* ARPHRD_* defines */
@@ -819,7 +819,7 @@
 	++card->wandev.stats.collisions;
 
 	/* unbusy the card (because only one interface per card) */
-	netif_start_queue(dev);
+	netif_wake_queue(dev);
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sdla_x25.c linux/drivers/net/wan/sdla_x25.c
--- v2.4.1/linux/drivers/net/wan/sdla_x25.c	Thu May  4 11:31:21 2000
+++ linux/drivers/net/wan/sdla_x25.c	Tue Feb 13 13:15:05 2001
@@ -43,7 +43,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/wanrouter.h>	/* WAN router definitions */
 #include <linux/wanpipe.h>	/* WANPIPE common user API definitions */
 #include <asm/byteorder.h>	/* htons(), etc. */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/sdlamain.c linux/drivers/net/wan/sdlamain.c
--- v2.4.1/linux/drivers/net/wan/sdlamain.c	Mon Dec 11 13:01:55 2000
+++ linux/drivers/net/wan/sdlamain.c	Tue Feb 13 13:15:05 2001
@@ -39,7 +39,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/string.h>	/* inline memset(), etc. */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/kernel.h>	/* printk(), and other useful stuff */
 #include <linux/module.h>	/* support for loadable modules */
 #include <linux/ioport.h>	/* request_region(), release_region() */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wan/z85230.h linux/drivers/net/wan/z85230.h
--- v2.4.1/linux/drivers/net/wan/z85230.h	Sat Feb 12 15:45:05 2000
+++ linux/drivers/net/wan/z85230.h	Tue Feb 13 13:15:05 2001
@@ -8,6 +8,8 @@
 #ifndef _Z8530_H
 #define _Z8530_H
 
+#include <linux/tty.h>
+
 /* Conversion routines to/from brg time constants from/to bits
  * per second.
  */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wavelan.c linux/drivers/net/wavelan.c
--- v2.4.1/linux/drivers/net/wavelan.c	Thu Oct 12 14:19:32 2000
+++ linux/drivers/net/wavelan.c	Tue Feb 13 13:15:05 2001
@@ -2469,8 +2469,9 @@
 	netif_rx(skb);
 
 	/* Keep statistics up to date */
+	dev->last_rx = jiffies;
 	lp->stats.rx_packets++;
-	lp->stats.rx_bytes += skb->len;
+	lp->stats.rx_bytes += sksize;
 
 #ifdef DEBUG_RX_TRACE
 	printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name);
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wavelan.h linux/drivers/net/wavelan.h
--- v2.4.1/linux/drivers/net/wavelan.h	Sun Mar 12 19:11:17 2000
+++ linux/drivers/net/wavelan.h	Tue Feb 13 13:15:05 2001
@@ -364,7 +364,7 @@
 
 /*
  * This software may only be used and distributed
- * according to the terms of the GNU Public License.
+ * according to the terms of the GNU General Public License.
  *
  * For more details, see wavelan.c.
  */
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wavelan.p.h linux/drivers/net/wavelan.p.h
--- v2.4.1/linux/drivers/net/wavelan.p.h	Mon Dec 11 13:01:59 2000
+++ linux/drivers/net/wavelan.p.h	Tue Feb 13 13:15:05 2001
@@ -374,7 +374,7 @@
 #include	<linux/netdevice.h>
 #include	<linux/etherdevice.h>
 #include	<linux/skbuff.h>
-#include	<linux/malloc.h>
+#include	<linux/slab.h>
 #include	<linux/timer.h>
 #include	<linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/net/wd.c linux/drivers/net/wd.c
--- v2.4.1/linux/drivers/net/wd.c	Mon Dec 11 13:38:29 2000
+++ linux/drivers/net/wd.c	Tue Feb 13 13:15:05 2001
@@ -6,7 +6,7 @@
 	Director, National Security Agency.
 
 	This software may be used and distributed according to the terms
-	of the GNU Public License, incorporated herein by reference.
+	of the GNU General Public License, incorporated herein by reference.
 
 	The author may be reached as becker@CESDIS.gsfc.nasa.gov, or C/O
 	Center of Excellence in Space Data and Information Sciences
diff -u --recursive --new-file v2.4.1/linux/drivers/net/winbond-840.c linux/drivers/net/winbond-840.c
--- v2.4.1/linux/drivers/net/winbond-840.c	Sat Dec 30 11:16:04 2000
+++ linux/drivers/net/winbond-840.c	Tue Feb 13 13:15:05 2001
@@ -120,17 +120,17 @@
 #include <linux/timer.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 #include <asm/processor.h>		/* Processor type for cache alignment. */
 #include <asm/bitops.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Winbond W89c840 Ethernet driver");
diff -u --recursive --new-file v2.4.1/linux/drivers/net/znet.c linux/drivers/net/znet.c
--- v2.4.1/linux/drivers/net/znet.c	Mon Jun 19 13:42:38 2000
+++ linux/drivers/net/znet.c	Tue Feb 13 13:15:05 2001
@@ -340,7 +340,7 @@
 			dev->name);
 	outb (CMD0_RESET, ioaddr);
 	hardware_init (dev);
-	netif_start_queue (dev);
+	netif_wake_queue (dev);
 }
 
 static int znet_send_packet(struct sk_buff *skb, struct net_device *dev)
@@ -585,7 +585,9 @@
 		  }
 		  skb->protocol=eth_type_trans(skb,dev);
 		  netif_rx(skb);
+		  dev->last_rx = jiffies;
 		  lp->stats.rx_packets++;
+		  lp->stats.rx_bytes += pkt_len;
 		}
 		zn.rx_cur = this_rfp_ptr;
 		if (zn.rx_cur >= zn.rx_end)
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/Config.in linux/drivers/parport/Config.in
--- v2.4.1/linux/drivers/parport/Config.in	Mon Jun 19 13:42:38 2000
+++ linux/drivers/parport/Config.in	Sat Feb  3 12:43:52 2001
@@ -12,8 +12,8 @@
 if [ "$CONFIG_PARPORT" != "n" ]; then
    dep_tristate '  PC-style hardware' CONFIG_PARPORT_PC $CONFIG_PARPORT
    if [ "$CONFIG_PARPORT_PC" != "n" ]; then
-      bool '    Use FIFO/DMA if available' CONFIG_PARPORT_PC_FIFO
       if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+         bool '    Use FIFO/DMA if available (EXPERIMENTAL)' CONFIG_PARPORT_PC_FIFO
          bool '    SuperIO chipset support (EXPERIMENTAL)' CONFIG_PARPORT_PC_SUPERIO
       fi
    fi
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/init.c linux/drivers/parport/init.c
--- v2.4.1/linux/drivers/parport/init.c	Wed Jul 12 16:24:33 2000
+++ linux/drivers/parport/init.c	Fri Feb  9 11:30:23 2001
@@ -15,7 +15,7 @@
 #include <linux/parport.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #ifndef MODULE
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/parport_arc.c linux/drivers/parport/parport_arc.c
--- v2.4.1/linux/drivers/parport/parport_arc.c	Thu Aug  5 14:23:14 1999
+++ linux/drivers/parport/parport_arc.c	Fri Feb  9 11:30:23 2001
@@ -20,7 +20,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/parport.h>
 
 #include <asm/ptrace.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/parport_gsc.c linux/drivers/parport/parport_gsc.c
--- v2.4.1/linux/drivers/parport/parport_gsc.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/parport/parport_gsc.c	Fri Feb  9 11:30:23 2001
@@ -27,7 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/sysctl.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/parport_pc.c linux/drivers/parport/parport_pc.c
--- v2.4.1/linux/drivers/parport/parport_pc.c	Thu Jan  4 13:12:48 2001
+++ linux/drivers/parport/parport_pc.c	Fri Feb  9 11:30:23 2001
@@ -48,7 +48,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/sysctl.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/parport_sunbpp.c linux/drivers/parport/parport_sunbpp.c
--- v2.4.1/linux/drivers/parport/parport_sunbpp.c	Thu Mar 30 16:54:53 2000
+++ linux/drivers/parport/parport_sunbpp.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: parport_sunbpp.c,v 1.10 2000/03/27 01:47:56 anton Exp $
+/* $Id: parport_sunbpp.c,v 1.11 2001/02/13 01:16:58 davem Exp $
  * Parallel-port routines for Sun architecture
  * 
  * Author: Derrick J. Brashear <shadow@dementia.org>
@@ -22,7 +22,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <linux/parport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/probe.c linux/drivers/parport/probe.c
--- v2.4.1/linux/drivers/parport/probe.c	Thu Jan  4 13:12:53 2001
+++ linux/drivers/parport/probe.c	Sat Feb  3 12:43:37 2001
@@ -75,8 +75,9 @@
 			char *u;
 			*(sep++) = 0;
 			/* Get rid of trailing blanks */
-			u = strchr (sep, ' ');
-			if (u) *u = '\0';
+			u = sep + strlen (sep) - 1;
+			while (u >= p && *u == ' ')
+				*u-- = '\0';
 			u = p;
 			while (*u) {
 				*u = toupper(*u);
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/procfs.c linux/drivers/parport/procfs.c
--- v2.4.1/linux/drivers/parport/procfs.c	Wed Jul  5 11:55:45 2000
+++ linux/drivers/parport/procfs.c	Fri Feb  9 11:30:23 2001
@@ -16,7 +16,7 @@
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/parport.h>
 #include <linux/ctype.h>
 #include <linux/sysctl.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/parport/share.c linux/drivers/parport/share.c
--- v2.4.1/linux/drivers/parport/share.c	Mon Jul 24 18:59:27 2000
+++ linux/drivers/parport/share.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/kmod.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.4.1/linux/drivers/pci/pci.c	Mon Dec 11 13:46:26 2000
+++ linux/drivers/pci/pci.c	Fri Feb 16 16:06:17 2001
@@ -16,11 +16,10 @@
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <linux/pm.h>
-#include <linux/slab.h>
 #include <linux/kmod.h>		/* for hotplug_path */
 
 #include <asm/page.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/Config.in linux/drivers/pcmcia/Config.in
--- v2.4.1/linux/drivers/pcmcia/Config.in	Thu Nov 16 16:38:16 2000
+++ linux/drivers/pcmcia/Config.in	Fri Feb 16 16:02:36 2001
@@ -19,6 +19,9 @@
    fi
    bool '  i82365 compatible bridge support' CONFIG_I82365
    bool '  Databook TCIC host bridge support' CONFIG_TCIC
+   if [ "$CONFIG_HD64465" = "y" ]; then
+      dep_tristate '  HD64465 host bridge support' CONFIG_HD64465_PCMCIA $CONFIG_PCMCIA
+   fi
 fi
 
 endmenu
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/Makefile linux/drivers/pcmcia/Makefile
--- v2.4.1/linux/drivers/pcmcia/Makefile	Fri Dec 29 14:07:22 2000
+++ linux/drivers/pcmcia/Makefile	Fri Feb 16 16:02:36 2001
@@ -32,6 +32,9 @@
   ifeq ($(CONFIG_TCIC),y)
     obj-y += tcic.o
   endif
+  ifeq ($(CONFIG_HD64465_PCMCIA),y)
+    obj-y += hd64465_ss.o
+  endif
 else
   ifeq ($(CONFIG_PCMCIA),m)
     obj-m   := pcmcia_core.o ds.o
@@ -40,6 +43,9 @@
     endif
     ifeq ($(CONFIG_TCIC),y)
       obj-m += tcic.o
+    endif
+    ifeq ($(CONFIG_HD64465_PCMCIA),m)
+      obj-m += hd64465_ss.o
     endif
      ifeq ($(CONFIG_CARDBUS),y)
 	obj-m += yenta_socket.o cb_enabler.o
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/bulkmem.c linux/drivers/pcmcia/bulkmem.c
--- v2.4.1/linux/drivers/pcmcia/bulkmem.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/pcmcia/bulkmem.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -37,7 +37,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/cardbus.c linux/drivers/pcmcia/cardbus.c
--- v2.4.1/linux/drivers/pcmcia/cardbus.c	Wed Nov  8 17:03:09 2000
+++ linux/drivers/pcmcia/cardbus.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -51,7 +51,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/cb_enabler.c linux/drivers/pcmcia/cb_enabler.c
--- v2.4.1/linux/drivers/pcmcia/cb_enabler.c	Sat Sep  2 00:13:49 2000
+++ linux/drivers/pcmcia/cb_enabler.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -43,7 +43,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/cirrus.h linux/drivers/pcmcia/cirrus.h
--- v2.4.1/linux/drivers/pcmcia/cirrus.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/cirrus.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/cistpl.c linux/drivers/pcmcia/cistpl.c
--- v2.4.1/linux/drivers/pcmcia/cistpl.c	Thu Oct 26 16:52:16 2000
+++ linux/drivers/pcmcia/cistpl.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -40,7 +40,7 @@
 #include <linux/major.h>
 #include <linux/errno.h>
 #include <linux/timer.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/pci.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/cs.c linux/drivers/pcmcia/cs.c
--- v2.4.1/linux/drivers/pcmcia/cs.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/pcmcia/cs.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -38,7 +38,7 @@
 #include <linux/string.h>
 #include <linux/major.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
 #include <linux/timer.h>
@@ -1458,6 +1458,8 @@
 	    s->functions = 1;
 	s->config = kmalloc(sizeof(config_t) * s->functions,
 			    GFP_KERNEL);
+	if (!s->config)
+		return CS_OUT_OF_RESOURCE;
 	memset(s->config, 0, sizeof(config_t) * s->functions);
     }
     
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- v2.4.1/linux/drivers/pcmcia/ds.c	Sat Sep  2 00:13:49 2000
+++ linux/drivers/pcmcia/ds.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -38,7 +38,7 @@
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/fcntl.h>
 #include <linux/sched.h>
@@ -414,6 +414,8 @@
     /* Add binding to list for this socket */
     driver->use_count++;
     b = kmalloc(sizeof(socket_bind_t), GFP_KERNEL);
+    if (!b) 
+      return -ENOMEM;
     b->driver = driver;
     b->function = bind_info->function;
     b->instance = NULL;
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/hd64465_ss.c linux/drivers/pcmcia/hd64465_ss.c
--- v2.4.1/linux/drivers/pcmcia/hd64465_ss.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/pcmcia/hd64465_ss.c	Fri Feb 16 16:02:36 2001
@@ -0,0 +1,1088 @@
+/*
+ * $Id$
+ *
+ * Device driver for the PCMCIA controller module of the
+ * Hitachi HD64465 handheld companion chip.
+ *
+ * Note that the HD64465 provides a very thin PCMCIA host bridge
+ * layer, requiring a lot of the work of supporting cards to be
+ * performed by the processor.  For example: mapping of card
+ * interrupts to processor IRQs is done by IRQ demuxing software;
+ * IO and memory mappings are fixed; setting voltages according
+ * to card Voltage Select pins etc is done in software.
+ *
+ * Note also that this driver uses only the simple, fixed,
+ * 16MB, 16-bit wide mappings to PCMCIA spaces defined by the
+ * HD64465.  Larger mappings, smaller mappings, or mappings of
+ * different width to the same socket, are all possible only by
+ * involving the SH7750's MMU, which is considered unnecessary here.
+ * The downside is that it may be possible for some drivers to
+ * break because they need or expect 8-bit mappings.
+ *
+ * This driver currently supports only the following configuration:
+ * SH7750 CPU, HD64465, TPS2206 voltage control chip.
+ *
+ * by Greg Banks <gbanks@pocketpenguins.com>
+ * (c) 2000 PocketPenguins Inc
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <asm/errno.h>
+#include <linux/irq.h>
+
+#include <asm/io.h>
+#include <asm/hd64465.h>
+
+#include <pcmcia/version.h>
+#include <pcmcia/cs_types.h>
+#include <pcmcia/cs.h>
+#include <pcmcia/ss.h>
+#include <pcmcia/bulkmem.h>
+#include <pcmcia/cistpl.h>
+#include "cs_internal.h"
+
+#define MODNAME "hd64465_ss"
+
+/* #define HD64465_DEBUG 1 */
+
+#ifndef HD64465_DEBUG
+#define HD64465_DEBUG 0
+#endif
+
+#if HD64465_DEBUG
+#define DPRINTK(args...)	printk(MODNAME ": " args)
+#else
+#define DPRINTK(args...)
+#endif
+
+extern int hd64465_io_debug;
+
+
+/*============================================================*/
+
+#define HS_IO_MAP_SIZE 	(64*1024)
+
+typedef struct hs_socket_t
+{
+    u_int   	    	irq;
+    u_long  	    	mem_base;
+    u_long  	    	mem_length;
+    void	    	(*handler)(void *info, u_int events);
+    void    	    	*handler_info;
+    u_int   	    	pending_events;
+    u_int   	    	ctrl_base;
+    socket_state_t  	state;
+    pccard_io_map     	io_maps[MAX_IO_WIN];
+    pccard_mem_map  	mem_maps[MAX_WIN];
+    struct vm_struct	*io_vma;    /* allocated kernel vm for mapping IO space */
+} hs_socket_t;
+
+#define HS_MAX_SOCKETS 2
+static hs_socket_t hs_sockets[HS_MAX_SOCKETS];
+static spinlock_t hs_pending_event_lock = SPIN_LOCK_UNLOCKED;
+
+/* Calculate socket number from ptr into hs_sockets[] */
+#define hs_sockno(sp) 	(sp - hs_sockets)
+
+static socket_cap_t hs_socket_cap =
+{
+    SS_CAP_PCCARD   	    /* support 16 bit cards */
+    |SS_CAP_STATIC_MAP      /* mappings are fixed in host memory */
+    ,
+    0xffde/*0xffff*/, 	    /* IRQs mapped in s/w so can do any, really */
+    HD64465_PCC_WINDOW,     /* 16MB fixed window size */
+    0,	    	    	    /* no PCI support */
+    0,	    	    	    /* no CardBus support */
+    0	    	    	    /* no bus operations needed */
+};
+
+#define hs_in(sp, r)	    inb((sp)->ctrl_base + (r))
+#define hs_out(sp, v, r)    outb(v, (sp)->ctrl_base + (r))
+
+
+/* translate a boolean value to a bit in a register */
+#define bool_to_regbit(sp, r, bi, bo)	    	\
+    do {    	    	    	    	    	\
+    	unsigned short v = hs_in(sp, r);    	\
+	if (bo)     	    	    	    	\
+	    v |= (bi);	    	    	    	\
+	else	    	    	    	    	\
+	    v &= ~(bi);     	    	    	\
+	hs_out(sp, v, r);   	    	    	\
+    } while(0)
+    
+/* register offsets from HD64465_REG_PCC[01]ISR */
+#define ISR 	0x0
+#define GCR 	0x2
+#define CSCR 	0x4
+#define CSCIER 	0x6
+#define SCR 	0x8
+
+
+/* Mask and values for CSCIER register */
+#define IER_MASK    0x80
+#define IER_ON	    0x3f    	/* interrupts on */
+#define IER_OFF     0x00    	/* interrupts off */
+
+/*============================================================*/
+
+#if HD64465_DEBUG > 10
+
+static void cis_hex_dump(const unsigned char *x, int len)
+{
+    	int i;
+	
+    	for (i=0 ; i<len ; i++)
+	{
+	    if (!(i & 0xf))
+	    	printk("\n%08x", (unsigned)(x + i));
+	    printk(" %02x", *(volatile unsigned short*)x);
+	    x += 2;
+	}
+	printk("\n");
+}
+
+#endif
+/*============================================================*/
+
+/*
+ * This code helps create the illusion that the IREQ line from
+ * the PC card is mapped to one of the CPU's IRQ lines by the
+ * host bridge hardware (which is how every host bridge *except*
+ * the HD64465 works).  In particular, it supports enabling
+ * and disabling the IREQ line by code which knows nothing
+ * about the host bridge (e.g. device drivers, IDE code) using
+ * the request_irq(), free_irq(), probe_irq_on() and probe_irq_off()
+ * functions.  Also, it supports sharing the mapped IRQ with
+ * real hardware IRQs from the -IRL0-3 lines.
+ */
+
+#define HS_NUM_MAPPED_IRQS  16	/* Limitation of the PCMCIA code */
+static struct
+{
+    /* index is mapped irq number */
+    hs_socket_t *sock;
+    hw_irq_controller *old_handler;
+} hs_mapped_irq[HS_NUM_MAPPED_IRQS];
+
+static void hs_socket_enable_ireq(hs_socket_t *sp)
+{
+    	unsigned short cscier;
+	
+    	DPRINTK("hs_socket_enable_ireq(sock=%d)\n", hs_sockno(sp));
+
+    	cscier = hs_in(sp, CSCIER);
+	cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK;
+    	cscier |= HD64465_PCCCSCIER_PIREQE_LEVEL;
+	hs_out(sp, cscier, CSCIER);
+}
+
+static void hs_socket_disable_ireq(hs_socket_t *sp)
+{
+    	unsigned short cscier;
+	
+    	DPRINTK("hs_socket_disable_ireq(sock=%d)\n", hs_sockno(sp));
+	
+    	cscier = hs_in(sp, CSCIER);
+	cscier &= ~HD64465_PCCCSCIER_PIREQE_MASK;
+	hs_out(sp, cscier, CSCIER);
+}
+
+static unsigned int hs_startup_irq(unsigned int irq)
+{
+	hs_socket_enable_ireq(hs_mapped_irq[irq].sock);
+	hs_mapped_irq[irq].old_handler->startup(irq);
+	return 0;
+}
+
+static void hs_shutdown_irq(unsigned int irq)
+{
+	hs_socket_disable_ireq(hs_mapped_irq[irq].sock);
+	hs_mapped_irq[irq].old_handler->shutdown(irq);
+}
+
+static void hs_enable_irq(unsigned int irq)
+{
+	hs_socket_enable_ireq(hs_mapped_irq[irq].sock);
+	hs_mapped_irq[irq].old_handler->enable(irq);
+}
+
+static void hs_disable_irq(unsigned int irq)
+{
+	hs_socket_disable_ireq(hs_mapped_irq[irq].sock);
+	hs_mapped_irq[irq].old_handler->disable(irq);
+}
+
+extern struct hw_interrupt_type no_irq_type;
+
+static void hs_mask_and_ack_irq(unsigned int irq)
+{
+	hs_socket_disable_ireq(hs_mapped_irq[irq].sock);
+	/* ack_none() spuriously complains about an unexpected IRQ */
+	if (hs_mapped_irq[irq].old_handler != &no_irq_type)
+	    hs_mapped_irq[irq].old_handler->ack(irq);
+}
+
+static void hs_end_irq(unsigned int irq)
+{
+	hs_socket_enable_ireq(hs_mapped_irq[irq].sock);
+	hs_mapped_irq[irq].old_handler->end(irq);
+}
+
+
+static struct hw_interrupt_type hd64465_ss_irq_type = {
+	typename:	"PCMCIA-IRQ",
+	startup:	hs_startup_irq,
+	shutdown:	hs_shutdown_irq,
+	enable:		hs_enable_irq,
+	disable:	hs_disable_irq,
+	ack:		hs_mask_and_ack_irq,
+	end:		hs_end_irq
+};
+
+/* 
+ * This function should only ever be called with interrupts disabled.
+ */
+static void hs_map_irq(hs_socket_t *sp, unsigned int irq)
+{
+    	DPRINTK("hs_map_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq);
+	
+	if (irq >= HS_NUM_MAPPED_IRQS)
+	    return;
+
+    	hs_mapped_irq[irq].sock = sp;
+	/* insert ourselves as the irq controller */
+	hs_mapped_irq[irq].old_handler = irq_desc[irq].handler;
+	irq_desc[irq].handler = &hd64465_ss_irq_type;
+}
+
+
+/* 
+ * This function should only ever be called with interrupts disabled.
+ */
+static void hs_unmap_irq(hs_socket_t *sp, unsigned int irq)
+{
+    	DPRINTK("hs_unmap_irq(sock=%d irq=%d)\n", hs_sockno(sp), irq);
+	
+	if (irq >= HS_NUM_MAPPED_IRQS)
+	    return;
+		
+	/* restore the original irq controller */
+	irq_desc[irq].handler = hs_mapped_irq[irq].old_handler;
+}
+
+/*============================================================*/
+
+
+/*
+ * Set Vpp and Vcc (in tenths of a Volt).  Does not
+ * support the hi-Z state.
+ *
+ * Note, this assumes the board uses a TPS2206 chip to control
+ * the Vcc and Vpp voltages to the hs_sockets.  If your board
+ * uses the MIC2563 (also supported by the HD64465) then you
+ * will have to modify this function.
+ */
+    	    	    	    	         /* 0V   3.3V  5.5V */
+static const u_char hs_tps2206_avcc[3] = { 0x00, 0x04, 0x08 };
+static const u_char hs_tps2206_bvcc[3] = { 0x00, 0x80, 0x40 };
+
+static int hs_set_voltages(hs_socket_t *sp, int Vcc, int Vpp)
+{
+    	u_int psr;
+	u_int vcci = 0;
+	u_int sock = hs_sockno(sp);
+	
+    	DPRINTK("hs_set_voltage(%d, %d, %d)\n", sock, Vcc, Vpp);
+
+    	switch (Vcc)
+	{
+	case 0:  vcci = 0; break;
+	case 33: vcci = 1; break;
+	case 50: vcci = 2; break;
+	default: return 0;
+	}
+
+    	/* Note: Vpp = 120 not supported -- Greg Banks */
+	if (Vpp != 0 && Vpp != Vcc)
+	    return 0;
+	
+	/* The PSR register holds 8 of the 9 bits which control
+	 * the TPS2206 via its serial interface.
+	 */
+	psr = inw(HD64465_REG_PCCPSR);
+	switch (sock)
+	{
+	case 0:
+	    psr &= 0x0f;
+	    psr |= hs_tps2206_avcc[vcci];
+	    psr |= (Vpp == 0 ? 0x00 : 0x02);
+	    break;
+	case 1:
+	    psr &= 0xf0;
+	    psr |= hs_tps2206_bvcc[vcci];
+	    psr |= (Vpp == 0 ? 0x00 : 0x20);
+	    break;
+	};
+	outw(psr, HD64465_REG_PCCPSR);
+	
+	return 1;
+}
+
+
+/*============================================================*/
+
+/*
+ * Drive the RESET line to the card.
+ */
+static void hs_reset_socket(hs_socket_t *sp, int on)
+{
+    	unsigned short v;
+	
+	v = hs_in(sp, GCR);
+	if (on)
+	    v |= HD64465_PCCGCR_PCCR;
+	else
+	    v &= ~HD64465_PCCGCR_PCCR;
+	hs_out(sp, v, GCR);
+}
+
+/*============================================================*/
+
+static int hs_init(unsigned int sock)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+	
+    	DPRINTK("hs_init(%d)\n", sock);
+	
+	sp->pending_events = 0;
+	sp->state.Vcc = 0;
+	sp->state.Vpp = 0;
+	hs_set_voltages(sp, 0, 0);
+	
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_suspend(unsigned int sock)
+{
+    	DPRINTK("hs_suspend(%d)\n", sock);
+
+    	/* TODO */
+	
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_register_callback(unsigned int sock,
+    	    void (*handler)(void *, unsigned int), void * info)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+	
+    	DPRINTK("hs_register_callback(%d)\n", sock);
+	sp->handler = handler;
+	sp->handler_info = info;
+	if (handler == 0) {
+	    MOD_DEC_USE_COUNT;
+	} else {
+	    MOD_INC_USE_COUNT;
+	}
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_inquire_socket(unsigned int sock, socket_cap_t *cap)
+{
+    	DPRINTK("hs_inquire_socket(%d)\n", sock);
+
+	*cap = hs_socket_cap;
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_get_status(unsigned int sock, u_int *value)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+    	unsigned int isr;
+	u_int status = 0;
+	
+	
+	isr = hs_in(sp, ISR);
+
+    	/* Card is seated and powered when *both* CD pins are low */
+	if ((isr & HD64465_PCCISR_PCD_MASK) == 0)
+    	{
+	    status |= SS_DETECT;    /* card present */
+
+	    switch (isr & HD64465_PCCISR_PBVD_MASK)
+	    {
+	    case HD64465_PCCISR_PBVD_BATGOOD:   
+		break;
+	    case HD64465_PCCISR_PBVD_BATWARN:
+		status |= SS_BATWARN;
+		break;
+	    default:
+		status |= SS_BATDEAD;
+		break;
+	    }
+
+	    if (isr & HD64465_PCCISR_PREADY)
+		status |= SS_READY;
+
+	    if (isr & HD64465_PCCISR_PMWP)
+		status |= SS_WRPROT;
+		
+	    /* Voltage Select pins interpreted as per Table 4-5 of the std.
+	     * Assuming we have the TPS2206, the socket is a "Low Voltage
+	     * key, 3.3V and 5V available, no X.XV available".
+	     */
+	    switch (isr & (HD64465_PCCISR_PVS2|HD64465_PCCISR_PVS1))
+	    {
+	    case HD64465_PCCISR_PVS1:
+	    	printk(KERN_NOTICE MODNAME ": cannot handle X.XV card, ignored\n");
+		status = 0;
+	    	break;
+	    case 0:
+	    case HD64465_PCCISR_PVS2:
+    	    	/* 3.3V */
+    	    	status |= SS_3VCARD;
+	    	break;
+	    case HD64465_PCCISR_PVS2|HD64465_PCCISR_PVS1:
+	    	/* 5V */
+	    	break;
+	    }
+		
+	    /* TODO: SS_POWERON */
+	    /* TODO: SS_STSCHG */
+    	}	
+	
+    	DPRINTK("hs_get_status(%d) = %x\n", sock, status);
+	
+	*value = status;
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_get_socket(unsigned int sock, socket_state_t *state)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+
+    	DPRINTK("hs_get_socket(%d)\n", sock);
+	
+	*state = sp->state;
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_set_socket(unsigned int sock, socket_state_t *state)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+    	u_long flags;
+	u_int changed;
+	unsigned short cscier;
+
+    	DPRINTK("hs_set_socket(sock=%d, flags=%x, csc_mask=%x, Vcc=%d, Vpp=%d, io_irq=%d)\n",
+	    sock, state->flags, state->csc_mask, state->Vcc, state->Vpp, state->io_irq);
+	
+	save_and_cli(flags);	/* Don't want interrupts happening here */
+
+	if (state->Vpp != sp->state.Vpp ||
+	    state->Vcc != sp->state.Vcc) {
+	    if (!hs_set_voltages(sp, state->Vcc, state->Vpp)) {
+	    	restore_flags(flags);
+	    	return -EINVAL;
+	    }
+	}
+
+/*    	hd64465_io_debug = 1; */
+    	/*
+	 * Handle changes in the Card Status Change mask,
+	 * by propagating to the CSCR register
+	 */	
+	changed = sp->state.csc_mask ^ state->csc_mask;
+	cscier = hs_in(sp, CSCIER);
+	    
+	if (changed & SS_DETECT) {
+	    if (state->csc_mask & SS_DETECT)
+		cscier |= HD64465_PCCCSCIER_PCDE;
+	    else
+		cscier &= ~HD64465_PCCCSCIER_PCDE;
+	}
+
+	if (changed & SS_READY) {
+	    if (state->csc_mask & SS_READY)
+		cscier |= HD64465_PCCCSCIER_PRE;
+	    else
+		cscier &= ~HD64465_PCCCSCIER_PRE;
+	}
+
+	if (changed & SS_BATDEAD) {
+	    if (state->csc_mask & SS_BATDEAD)
+		cscier |= HD64465_PCCCSCIER_PBDE;
+	    else
+		cscier &= ~HD64465_PCCCSCIER_PBDE;
+	}
+
+	if (changed & SS_BATWARN) {
+	    if (state->csc_mask & SS_BATWARN)
+		cscier |= HD64465_PCCCSCIER_PBWE;
+	    else
+		cscier &= ~HD64465_PCCCSCIER_PBWE;
+	}
+
+	if (changed & SS_STSCHG) {
+	    if (state->csc_mask & SS_STSCHG)
+		cscier |= HD64465_PCCCSCIER_PSCE;
+	    else
+		cscier &= ~HD64465_PCCCSCIER_PSCE;
+	}
+
+    	hs_out(sp, cscier, CSCIER);
+
+	if (sp->state.io_irq && !state->io_irq)
+	    hs_unmap_irq(sp, sp->state.io_irq);
+	else if (!sp->state.io_irq && state->io_irq)
+	    hs_map_irq(sp, state->io_irq);
+
+
+    	/*
+	 * Handle changes in the flags field,
+	 * by propagating to config registers.
+	 */	
+	changed = sp->state.flags ^ state->flags;
+
+	if (changed & SS_IOCARD) {
+	    DPRINTK("card type: %s\n",
+		    (state->flags & SS_IOCARD ? "i/o" : "memory" ));
+	    bool_to_regbit(sp, GCR, HD64465_PCCGCR_PCCT,
+		state->flags & SS_IOCARD);
+	}
+
+	if (changed & SS_RESET) {
+	    DPRINTK("%s reset card\n",
+		(state->flags & SS_RESET ? "start" : "stop"));
+	    bool_to_regbit(sp, GCR, HD64465_PCCGCR_PCCR,
+		state->flags & SS_RESET);
+	}
+
+	if (changed & SS_OUTPUT_ENA) {
+	    DPRINTK("%sabling card output\n",
+		(state->flags & SS_OUTPUT_ENA ? "en" : "dis"));
+	    bool_to_regbit(sp, GCR, HD64465_PCCGCR_PDRV,
+		state->flags & SS_OUTPUT_ENA);
+	}
+
+    	/* TODO: SS_SPKR_ENA */
+	    
+/*    	hd64465_io_debug = 0; */
+	sp->state = *state;
+	    
+	restore_flags(flags);
+
+#if HD64465_DEBUG > 10
+	if (state->flags & SS_OUTPUT_ENA)   
+	    cis_hex_dump((const unsigned char*)sp->mem_base, 0x100);
+#endif
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_get_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+	int map = io->map;
+
+    	DPRINTK("hs_get_io_map(%d, %d)\n", sock, map);
+	if (map >= MAX_IO_WIN)
+	    return -EINVAL;
+	
+	*io = sp->io_maps[map];
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_set_io_map(unsigned int sock, struct pccard_io_map *io)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+	int map = io->map;
+	struct pccard_io_map *sio;
+	pgprot_t prot;
+
+    	DPRINTK("hs_set_io_map(sock=%d, map=%d, flags=0x%x, speed=%dns, start=0x%04x, stop=0x%04x)\n",
+	    sock, map, io->flags, io->speed, io->start, io->stop);
+	if (map >= MAX_IO_WIN)
+	    return -EINVAL;
+	sio = &sp->io_maps[map];
+
+    	/* check for null changes */	
+    	if (io->flags == sio->flags &&
+	    io->start == sio->start &&
+	    io->stop == sio->stop)
+	    return 0;
+	
+	if (io->flags & MAP_AUTOSZ)
+	    prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IODYN);
+	else if (io->flags & MAP_16BIT)
+	    prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IO16);
+	else
+	    prot = PAGE_KERNEL_PCC(sock, _PAGE_PCC_IO8);
+
+	/* TODO: handle MAP_USE_WAIT */
+	if (io->flags & MAP_USE_WAIT)
+	    printk(KERN_INFO MODNAME ": MAP_USE_WAIT unimplemented\n");
+	/* TODO: handle MAP_PREFETCH */
+	if (io->flags & MAP_PREFETCH)
+	    printk(KERN_INFO MODNAME ": MAP_PREFETCH unimplemented\n");
+	/* TODO: handle MAP_WRPROT */
+	if (io->flags & MAP_WRPROT)
+	    printk(KERN_INFO MODNAME ": MAP_WRPROT unimplemented\n");
+	/* TODO: handle MAP_0WS */
+	if (io->flags & MAP_0WS)
+	    printk(KERN_INFO MODNAME ": MAP_0WS unimplemented\n");
+
+	if (io->flags & MAP_ACTIVE) {
+	    unsigned long pstart, psize, paddrbase, vaddrbase;
+	    
+	    paddrbase = virt_to_phys((void*)(sp->mem_base + 2 * HD64465_PCC_WINDOW));
+	    vaddrbase = (unsigned long)sp->io_vma->addr;
+	    pstart = io->start & PAGE_MASK;
+	    psize = ((io->stop + PAGE_SIZE) & PAGE_MASK) - pstart;
+
+    	    /*
+	     * Change PTEs in only that portion of the mapping requested
+	     * by the caller.  This means that most of the time, most of
+	     * the PTEs in the io_vma will be unmapped and only the bottom
+	     * page will be mapped.  But the code allows for weird cards
+	     * that might want IO ports > 4K.
+	     */
+	    DPRINTK("remap_page_range(vaddr=0x%08lx, paddr=0x%08lx, size=0x%08lxx)\n",
+	    	vaddrbase + pstart, paddrbase + pstart, psize);
+	    remap_page_range(vaddrbase + pstart, paddrbase + pstart, psize, prot);
+	    
+	    /*
+	     * Change the mapping used by inb() outb() etc
+	     */
+	    hd64465_port_map(
+	    	io->start,
+		io->stop - io->start + 1,
+	    	vaddrbase + io->start);
+	} else {
+	    hd64465_port_unmap(
+	    	sio->start,
+		sio->stop - sio->start + 1);
+	    /* TODO: remap_page_range() to mark pages not present ? */
+	}
+	
+	*sio = *io;
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_get_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+	int map = mem->map;
+
+    	DPRINTK("hs_get_mem_map(%d, %d)\n", sock, map);
+	if (map >= MAX_WIN)
+	    return -EINVAL;
+	
+	*mem = sp->mem_maps[map];
+	return 0;
+}
+
+/*============================================================*/
+
+static int hs_set_mem_map(unsigned int sock, struct pccard_mem_map *mem)
+{
+    	hs_socket_t *sp = &hs_sockets[sock];
+	struct pccard_mem_map *smem;
+	int map = mem->map;
+	unsigned long paddr, size;
+
+#if 0
+    	DPRINTK("hs_set_mem_map(sock=%d, map=%d, flags=0x%x, sys_start=0x%08lx, sys_end=0x%08lx, card_start=0x%08x)\n",
+	    sock, map, mem->flags, mem->sys_start, mem->sys_stop, mem->card_start);
+#endif
+
+	if (map >= MAX_WIN)
+	    return -EINVAL;
+	smem = &sp->mem_maps[map];
+	
+	size = mem->sys_stop - mem->sys_start + 1;
+	
+	paddr = sp->mem_base;	    	    /* base of Attribute mapping */
+	if (!(mem->flags & MAP_ATTRIB))
+	    paddr += HD64465_PCC_WINDOW;    /* base of Common mapping */
+	paddr += mem->card_start;
+
+    	/* Because we specified SS_CAP_STATIC_MAP, we are obliged
+	 * at this time to report the system address corresponding
+	 * to the card address requested.  This is how Socket Services
+	 * queries our fixed mapping.  I wish this fact had been
+	 * documented - Greg Banks.
+	 */
+    	mem->sys_start = paddr;
+	mem->sys_stop = paddr + size - 1;
+	
+	*smem = *mem;
+	
+    	return 0;
+}
+
+/* TODO: do we need to use the MMU to access Common memory ??? */
+
+/*============================================================*/
+
+static void hs_proc_setup(unsigned int sock, struct proc_dir_entry *base)
+{
+    	DPRINTK("hs_proc_setup(%d)\n", sock);
+}
+
+/*============================================================*/
+
+/*
+ * This function is registered with the HD64465 glue code to do a
+ * secondary demux step on the PCMCIA interrupts.  It handles 
+ * mapping the IREQ request from the card to a standard Linux
+ * IRQ, as requested by SocketServices.
+ */
+static int hs_irq_demux(int irq, void *dev)
+{
+    	hs_socket_t *sp = (hs_socket_t *)dev;
+	u_int cscr;
+    	
+    	DPRINTK("hs_irq_demux(irq=%d)\n", irq);
+
+    	if (sp->state.io_irq &&
+	    (cscr = hs_in(sp, CSCR)) & HD64465_PCCCSCR_PIREQ) {
+	    cscr &= ~HD64465_PCCCSCR_PIREQ;
+	    hs_out(sp, cscr, CSCR);
+	    return sp->state.io_irq;
+	}
+	    
+	return irq;
+}
+
+/*============================================================*/
+
+/*
+ * Interrupt handling routine.
+ *
+ * This uses the schedule_task() technique to cause reportable events
+ * such as card insertion and removal to be handled in keventd's
+ * process context.
+ */
+ 
+
+static void hs_events_bh(void *dummy)
+{
+	hs_socket_t *sp;
+	u_int events;
+	int i;
+
+	for (i=0; i<HS_MAX_SOCKETS; i++) {
+	    sp = &hs_sockets[i];
+
+	    spin_lock_irq(&hs_pending_event_lock);
+	    events = sp->pending_events;
+	    sp->pending_events = 0;
+	    spin_unlock_irq(&hs_pending_event_lock);
+	    
+	    if (sp->handler)
+		sp->handler(sp->handler_info, events);
+	}
+}
+
+static struct tq_struct hs_events_task = {
+	routine:	hs_events_bh
+};
+
+static void hs_interrupt(int irq, void *dev, struct pt_regs *regs)
+{
+    	hs_socket_t *sp = (hs_socket_t *)dev;
+	u_int events = 0;
+	u_int cscr;
+	
+	
+	cscr = hs_in(sp, CSCR);
+	
+	DPRINTK("hs_interrupt, cscr=%04x\n", cscr);
+
+	/* check for bus-related changes to be reported to Socket Services */
+	if (cscr & HD64465_PCCCSCR_PCDC) {
+	    /* double-check for a 16-bit card, as we don't support CardBus */
+	    if ((hs_in(sp, ISR) & HD64465_PCCISR_PCD_MASK) != 0) {
+	    	printk(KERN_NOTICE MODNAME
+		    ": socket %d, card not a supported card type or not inserted correctly\n",
+		    hs_sockno(sp));
+		/* Don't do the rest unless a card is present */
+		cscr &= ~(HD64465_PCCCSCR_PCDC|
+		    	  HD64465_PCCCSCR_PRC|
+			  HD64465_PCCCSCR_PBW|
+		    	  HD64465_PCCCSCR_PBD|
+			  HD64465_PCCCSCR_PSC);
+	    } else {
+	    	cscr &= ~HD64465_PCCCSCR_PCDC;
+		events |= SS_DETECT;    	/* card insertion or removal */
+    	    }
+	}
+	if (cscr & HD64465_PCCCSCR_PRC) {
+	    cscr &= ~HD64465_PCCCSCR_PRC;
+	    events |= SS_READY;     	/* ready signal changed */
+	}
+	if (cscr & HD64465_PCCCSCR_PBW) {
+	    cscr &= ~HD64465_PCCCSCR_PSC;
+	    events |= SS_BATWARN;     	/* battery warning */
+	}
+	if (cscr & HD64465_PCCCSCR_PBD) {
+	    cscr &= ~HD64465_PCCCSCR_PSC;
+	    events |= SS_BATDEAD;     	/* battery dead */
+	}
+	if (cscr & HD64465_PCCCSCR_PSC) {
+	    cscr &= ~HD64465_PCCCSCR_PSC;
+	    events |= SS_STSCHG;     	/* STSCHG (status changed) signal */
+	}
+	
+	if (cscr & HD64465_PCCCSCR_PIREQ) {
+	    cscr &= ~HD64465_PCCCSCR_PIREQ;
+
+    	    /* This should have been dealt with during irq demux */	    
+	    printk(KERN_NOTICE MODNAME ": unexpected IREQ from card\n");
+	}
+
+	hs_out(sp, cscr, CSCR);
+
+	if (events) {
+	    /*
+    	     * Arrange for events to be reported to the registered
+	     * event handler function (from CardServices) in a process
+	     * context (keventd) "soon".
+	     */
+	    spin_lock(&hs_pending_event_lock);
+	    sp->pending_events |= events;
+	    spin_unlock(&hs_pending_event_lock);
+	    
+	    schedule_task(&hs_events_task);
+	}
+}
+
+/*============================================================*/
+
+static struct pccard_operations hs_operations = {
+	hs_init,
+	hs_suspend,
+	hs_register_callback,
+	hs_inquire_socket,
+	hs_get_status,
+	hs_get_socket,
+	hs_set_socket,
+	hs_get_io_map,
+	hs_set_io_map,
+	hs_get_mem_map,
+	hs_set_mem_map,
+	hs_proc_setup
+};
+
+static int hs_init_socket(hs_socket_t *sp, int irq, unsigned long mem_base,
+    	    unsigned int ctrl_base)
+{
+    	unsigned short v;
+    	int i, err;
+
+    	memset(sp, 0, sizeof(*sp));
+	sp->irq = irq;
+	sp->mem_base = mem_base;
+	sp->mem_length = 4*HD64465_PCC_WINDOW;	/* 16MB */
+	sp->ctrl_base = ctrl_base;
+	
+	for (i=0 ; i<MAX_IO_WIN ; i++)
+	    sp->io_maps[i].map = i;
+	for (i=0 ; i<MAX_WIN ; i++)
+	    sp->mem_maps[i].map = i;
+	
+	if ((sp->io_vma = get_vm_area(HS_IO_MAP_SIZE, VM_IOREMAP)) == 0)
+	    return -ENOMEM;
+
+	hd64465_register_irq_demux(sp->irq, hs_irq_demux, sp);
+	
+    	if ((err = request_irq(sp->irq, hs_interrupt, SA_INTERRUPT, MODNAME, sp)) < 0)
+	    return err;
+    	if (request_mem_region(sp->mem_base, sp->mem_length, MODNAME) == 0) {
+    	    sp->mem_base = 0;
+	    return -ENOMEM;
+	}
+
+
+	/* According to section 3.2 of the PCMCIA standard, low-voltage
+	 * capable cards must implement cold insertion, i.e. Vpp and
+	 * Vcc set to 0 before card is inserted.
+	 */
+	/*hs_set_voltages(sp, 0, 0);*/
+	
+	/* hi-Z the outputs to the card and set 16MB map mode */
+	v = hs_in(sp, GCR);
+	v &= ~HD64465_PCCGCR_PCCT;  	/* memory-only card */
+	hs_out(sp, v, GCR);
+
+	v = hs_in(sp, GCR);
+	v |= HD64465_PCCGCR_PDRV;   	/* enable outputs to card */
+	hs_out(sp, v, GCR);
+
+	v = hs_in(sp, GCR);
+	v |= HD64465_PCCGCR_PMMOD; 	/* 16MB mapping mode */
+	hs_out(sp, v, GCR);
+
+	v = hs_in(sp, GCR);
+	/* lowest 16MB of Common */
+	v &= ~(HD64465_PCCGCR_PPA25|HD64465_PCCGCR_PPA24); 
+	hs_out(sp, v, GCR);
+	
+	hs_reset_socket(sp, 1);
+
+    	return 0;
+}
+
+static void hs_exit_socket(hs_socket_t *sp)
+{
+    	unsigned short cscier, gcr;
+	
+	/* turn off interrupts in hardware */
+    	cscier = hs_in(sp, CSCIER);
+	cscier = (cscier & IER_MASK) | IER_OFF;
+    	hs_out(sp, cscier, CSCIER);
+	
+	/* hi-Z the outputs to the card */
+    	gcr = hs_in(sp, GCR);
+	gcr &= HD64465_PCCGCR_PDRV;
+	hs_out(sp, gcr, GCR);
+
+    	/* power the card down */
+	hs_set_voltages(sp, 0, 0);
+
+    	if (sp->mem_base != 0)
+	    release_mem_region(sp->mem_base, sp->mem_length);
+	if (sp->irq != 0) {
+	    free_irq(sp->irq, hs_interrupt);
+    	    hd64465_unregister_irq_demux(sp->irq);
+	}
+	if (sp->io_vma != 0)
+	    vfree(sp->io_vma->addr);
+}
+
+
+static int __init init_hs(void)
+{
+	servinfo_t serv;
+	int i;
+	unsigned short v;
+
+    	/*
+	 * Check API version
+	 */
+	pcmcia_get_card_services_info(&serv);
+	if (serv.Revision != CS_RELEASE_CODE) {
+	    printk(KERN_NOTICE MODNAME ": Card Services release does not match!\n");
+	    return -ENODEV;
+	}
+
+/*	hd64465_io_debug = 1; */
+	
+	/* Wake both sockets out of STANDBY mode */
+	/* TODO: wait 15ms */
+	v = inw(HD64465_REG_SMSCR);
+	v &= ~(HD64465_SMSCR_PC0ST|HD64465_SMSCR_PC1ST);
+	outw(v, HD64465_REG_SMSCR);
+
+	/* keep power controller out of shutdown mode */
+	v = inb(HD64465_REG_PCC0SCR);
+	v |= HD64465_PCCSCR_SHDN;
+	outb(v, HD64465_REG_PCC0SCR);
+
+    	/* use serial (TPS2206) power controller */
+	v = inb(HD64465_REG_PCC0CSCR);
+	v |= HD64465_PCCCSCR_PSWSEL;
+	outb(v, HD64465_REG_PCC0CSCR);
+
+    	hs_set_voltages(&hs_sockets[0], 0, 0);
+    	hs_set_voltages(&hs_sockets[1], 0, 0);
+	
+	/*
+	 * Setup hs_sockets[] structures and request system resources.
+	 * TODO: on memory allocation failure, power down the socket
+	 *       before quitting.
+	 */
+	i = hs_init_socket(&hs_sockets[0],
+	    HD64465_IRQ_PCMCIA0,
+	    HD64465_PCC0_BASE,
+	    HD64465_REG_PCC0ISR);
+	if (i < 0)
+	    return i;
+	i = hs_init_socket(&hs_sockets[1],
+	    HD64465_IRQ_PCMCIA1,
+	    HD64465_PCC1_BASE,
+	    HD64465_REG_PCC1ISR);
+	if (i < 0)
+	    return i;
+
+/*	hd64465_io_debug = 0; */
+	    
+
+	if (register_ss_entry(HS_MAX_SOCKETS, &hs_operations) != 0) {
+	    for (i=0 ; i<HS_MAX_SOCKETS ; i++)
+		hs_exit_socket(&hs_sockets[i]);
+    	    return -ENODEV;
+	}
+
+	printk(KERN_INFO "HD64465 PCMCIA bridge:\n");
+	for (i=0 ; i<HS_MAX_SOCKETS ; i++) {
+	    hs_socket_t *sp = &hs_sockets[i];
+	    
+	    printk(KERN_INFO "  socket %d at 0x%08lx irq %d io window %ldK@0x%08lx\n",
+	    	i, sp->mem_base, sp->irq,
+		sp->io_vma->size>>10, (unsigned long)sp->io_vma->addr);
+	}
+
+    	return 0;
+}
+
+static void __exit exit_hs(void)
+{
+    	u_long flags;
+	int i;
+	
+	save_and_cli(flags);
+
+    	/*
+	 * Release kernel resources
+	 */
+	for (i=0 ; i<HS_MAX_SOCKETS ; i++)
+	    hs_exit_socket(&hs_sockets[i]);
+	unregister_ss_entry(&hs_operations);
+	
+	restore_flags(flags);
+}
+
+module_init(init_hs);
+module_exit(exit_hs);
+
+/*============================================================*/
+/*END*/
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/i82365.c linux/drivers/pcmcia/i82365.c
--- v2.4.1/linux/drivers/pcmcia/i82365.c	Thu Nov 16 16:38:16 2000
+++ linux/drivers/pcmcia/i82365.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -41,7 +41,7 @@
 #include <linux/errno.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/i82365.h linux/drivers/pcmcia/i82365.h
--- v2.4.1/linux/drivers/pcmcia/i82365.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/i82365.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/o2micro.h linux/drivers/pcmcia/o2micro.h
--- v2.4.1/linux/drivers/pcmcia/o2micro.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/o2micro.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/old-yenta.h linux/drivers/pcmcia/old-yenta.h
--- v2.4.1/linux/drivers/pcmcia/old-yenta.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/old-yenta.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/ricoh.h linux/drivers/pcmcia/ricoh.h
--- v2.4.1/linux/drivers/pcmcia/ricoh.h	Tue Jan 25 11:41:20 2000
+++ linux/drivers/pcmcia/ricoh.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- v2.4.1/linux/drivers/pcmcia/rsrc_mgr.c	Sat Sep  2 00:13:49 2000
+++ linux/drivers/pcmcia/rsrc_mgr.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -40,7 +40,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/timer.h>
 #include <asm/irq.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/rsrc_mgr.h linux/drivers/pcmcia/rsrc_mgr.h
--- v2.4.1/linux/drivers/pcmcia/rsrc_mgr.h	Sat Sep  2 00:13:49 2000
+++ linux/drivers/pcmcia/rsrc_mgr.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/smc34c90.h linux/drivers/pcmcia/smc34c90.h
--- v2.4.1/linux/drivers/pcmcia/smc34c90.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/smc34c90.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/tcic.c linux/drivers/pcmcia/tcic.c
--- v2.4.1/linux/drivers/pcmcia/tcic.c	Thu Nov 16 16:38:16 2000
+++ linux/drivers/pcmcia/tcic.c	Fri Feb 16 16:02:36 2001
@@ -19,7 +19,7 @@
     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
 
     Alternatively, the contents of this file may be used under the
-    terms of the GNU Public License version 2 (the "GPL"), in which
+    terms of the GNU General Public License version 2 (the "GPL"), in which
     case the provisions of the GPL are applicable instead of the
     above.  If you wish to allow the use of your version of this file
     only under the terms of the GPL and not to allow others to use
@@ -45,7 +45,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/tcic.h linux/drivers/pcmcia/tcic.h
--- v2.4.1/linux/drivers/pcmcia/tcic.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/tcic.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/ti113x.h linux/drivers/pcmcia/ti113x.h
--- v2.4.1/linux/drivers/pcmcia/ti113x.h	Thu Jan  4 14:51:40 2001
+++ linux/drivers/pcmcia/ti113x.h	Wed Feb 21 16:10:56 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/topic.h linux/drivers/pcmcia/topic.h
--- v2.4.1/linux/drivers/pcmcia/topic.h	Fri Sep  3 12:27:58 1999
+++ linux/drivers/pcmcia/topic.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pcmcia/vg468.h linux/drivers/pcmcia/vg468.h
--- v2.4.1/linux/drivers/pcmcia/vg468.h	Thu Nov 11 16:03:37 1999
+++ linux/drivers/pcmcia/vg468.h	Fri Feb 16 16:02:36 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/drivers/pnp/isapnp.c linux/drivers/pnp/isapnp.c
--- v2.4.1/linux/drivers/pnp/isapnp.c	Mon Dec 11 12:38:58 2000
+++ linux/drivers/pnp/isapnp.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/dma.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/Config.in linux/drivers/s390/Config.in
--- v2.4.1/linux/drivers/s390/Config.in	Sun Oct  8 09:30:41 2000
+++ linux/drivers/s390/Config.in	Tue Feb 13 14:13:44 2001
@@ -1,64 +1,74 @@
 mainmenu_option next_comment
-comment 'S/390 block device drivers'
+comment 'Block device drivers'
 
 tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
-if [ "$CONFIG_NET" = "y" ]; then
-  tristate 'Network block device support' CONFIG_BLK_DEV_NBD
-fi
-source drivers/md/Config.in
+dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
-if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
-  bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
+if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
+  int '   Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 24576
 fi
+dep_bool '   Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD
+tristate 'XPRAM disk support' CONFIG_BLK_DEV_XPRAM
 
-bool 'Support for VM minidisk (VM only)' CONFIG_MDISK
-if [ "$CONFIG_MDISK" = "y" ]; then
-  bool '   Support for synchronous read-write' CONFIG_MDISK_SYNC
-fi
+comment 'S/390 block device drivers'
 
 tristate 'Support for DASD devices' CONFIG_DASD
 if [ "$CONFIG_DASD" != "n"  ]; then
-  comment 'DASD disciplines'
   bool '   Support for ECKD Disks' CONFIG_DASD_ECKD
+  bool '   Support for FBA  Disks' CONFIG_DASD_FBA
 #  bool '   Support for CKD  Disks' CONFIG_DASD_CKD
-  bool '   Support for DIAG access to CMS reserved Disks' CONFIG_DASD_MDSK
+  if [ "$CONFIG_ARCH_S390" = "y" ]; then
+    bool '   Support for DIAG access to CMS reserved Disks' CONFIG_DASD_MDSK
+  fi;
 fi
 
 endmenu
 
-#menu_option next_comment
-#endmenu
+source drivers/md/Config.in
 
-if [ "$CONFIG_NET" = "y" ]; then
-  mainmenu_option next_comment
-  comment 'S/390 Network device support'
-  bool 'Channel Device Configuration (Temporary Option)' CONFIG_CHANDEV
-  bool 'Network device support' CONFIG_NETDEVICES
-  if [ "$CONFIG_NETDEVICES" = "y" ]; then
-    mainmenu_option next_comment
-    comment 'S390 Network devices'
-    bool 'CTC device support' CONFIG_CTC
-    bool 'IUCV device support (VM only)' CONFIG_IUCV
-    tristate 'Dummy net driver support' CONFIG_DUMMY
-    bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
-    bool 'Token Ring driver support' CONFIG_TR
-    bool 'FDDI driver support' CONFIG_FDDI
-    endmenu
-  fi
-  endmenu
+mainmenu_option next_comment
+comment 'Character device drivers'
+bool 'Unix98 PTY support' CONFIG_UNIX98_PTYS
+if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
+  int 'Maximum number of Unix98 PTYs in use (0-2048)' CONFIG_UNIX98_PTY_COUNT 256
 fi
 
-mainmenu_option next_comment
-comment 'S/390 Terminal and Console options'
+comment 'S/390 character device drivers'
 
 bool 'Support for 3215 line mode terminal' CONFIG_3215
 if [ "$CONFIG_3215" = "y" ]; then
   bool 'Support for console on 3215 line mode terminal' CONFIG_3215_CONSOLE
 fi
-
 bool 'Support for HWC line mode terminal' CONFIG_HWC
 if [ "$CONFIG_HWC" = "y" ]; then
   bool 'console on HWC line mode terminal' CONFIG_HWC_CONSOLE
 fi
+tristate 'S/390 tape device support' CONFIG_S390_TAPE
+if [ "$CONFIG_S390_TAPE" != "n" ]; then
+  comment 'S/390 tape interface support'
+  bool '   Support for tape character devices' CONFIG_S390_TAPE_CHAR
+  bool '   Support for tape block devices' CONFIG_S390_TAPE_BLOCK
+  comment 'S/390 tape hardware support'
+  bool '   Support for 3490 tape hardware' CONFIG_S390_TAPE_3490
+  bool '   Support for 3480 tape hardware' CONFIG_S390_TAPE_3480
+fi
 endmenu
+
+if [ "$CONFIG_NET" = "y" ]; then
+  mainmenu_option next_comment
+  comment 'Network device drivers'
+  bool 'Network device support' CONFIG_NETDEVICES
+
+  if [ "$CONFIG_NETDEVICES" = "y" ]; then
+    tristate 'Dummy net driver support' CONFIG_DUMMY
+    bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET
+    bool 'Token Ring driver support' CONFIG_TR
+    bool 'FDDI driver support' CONFIG_FDDI
+    comment 'S/390 network device drivers'
+    bool 'Channel Device Configuration (Temporary Option)' CONFIG_CHANDEV
+    tristate 'CTC device support' CONFIG_CTC
+    tristate 'IUCV device support (VM only)' CONFIG_IUCV
+  fi
+  endmenu
+fi
 
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/Makefile linux/drivers/s390/Makefile
--- v2.4.1/linux/drivers/s390/Makefile	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/Makefile	Tue Feb 13 14:13:44 2001
@@ -11,19 +11,18 @@
 
 CFLAGS += 
 O_TARGET := io.o
-O_OBJS    :=         
-M_OBJS   :=
 
-SUBDIRS := $(SUBDIRS) arch/s390/drivers/block arch/s390/drivers/char \
-	arch/s390/drivers/misc  arch/s390/drivers/net
-MOD_SUB_DIRS += ./net
+obj-y	:= s390io.o s390mach.o s390dyn.o idals.o ccwcache.o
 
-O_OBJS := block/s390-block.o \
+subdir-y := block char misc net
+subdir-m := $(subdir-y)
+
+obj-y += block/s390-block.o \
   char/s390-char.o \
   misc/s390-misc.o \
   net/s390-net.o 
 
-io.o: $(O_OBJS)
+io.o: $(obj-y)
 
 block/s390-block.o: dummy
 	$(MAKE)  -C block
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/Makefile linux/drivers/s390/block/Makefile
--- v2.4.1/linux/drivers/s390/block/Makefile	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/Makefile	Tue Feb 13 14:13:44 2001
@@ -2,30 +2,33 @@
 
 CFLAGS += 
 O_TARGET := s390-block.o
-O_OBJS   :=         
-M_OBJS   :=
 
-ifeq ($(CONFIG_DASD),y)
-  O_OBJS += dasd.o dasd_ccwstuff.o dasd_erp.o
-  ifeq ($(CONFIG_PROC_FS),y)
-   O_OBJS += dasd_proc.o dasd_profile.o
-  endif 
+DASD_OBJS := dasd.o
   ifeq ($(CONFIG_DASD_ECKD),y)
-   O_OBJS += dasd_eckd.o
-  endif 
+    DASD_OBJS += dasd_eckd.o dasd_3990_erp.o dasd_9343_erp.o
+  endif
+  ifeq ($(CONFIG_DASD_FBA),y)
+    DASD_OBJS += dasd_fba.o dasd_3370_erp.o dasd_9336_erp.o
+  endif
   ifeq ($(CONFIG_DASD_MDSK),y)
-   O_OBJS += dasd_mdsk.o
-  endif 
+    DASD_OBJS += dasd_mdsk.o
+  endif
 #  ifeq ($(CONFIG_DASD_CKD),y)
-#   O_OBJS += dasd_ckd.o
-#  endif 
-endif
+#    DASD_OBJS += dasd_ckd.o
+#  endif
 
-ifeq ($(CONFIG_MDISK),y)
-  O_OBJS += mdisk.o
+ifeq ($(CONFIG_DASD),y)
+  obj-y += $(DASD_OBJS)
+else
+  ifeq ($(CONFIG_DASD),m)
+    obj-m += dasd_mod.o
+    D_OBJS += $(DASD_OBJS)
+  endif
 endif
 
+obj-$(CONFIG_BLK_DEV_XPRAM) += xpram.o
+
 dasd_mod.o: $(D_OBJS)
-	$(LD) $(LD_RFLAG) -r -o $@ $+
+	$(LD) $(LD_RFLAG) -r -o $@ $(D_OBJS)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd.c linux/drivers/s390/block/dasd.c
--- v2.4.1/linux/drivers/s390/block/dasd.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/s390/block/dasd.c	Fri Feb 16 16:02:36 2001
@@ -1,1542 +1,2989 @@
 /* 
  * File...........: linux/drivers/s390/block/dasd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- *                : Utz Bacher <utz.bacher@de.ibm.com>
+ *                  Horst Hummel <Horst.Hummel@de.ibm.com>  
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ * 11/09/00 complete redesign after code review
  */
 
 #include <linux/config.h>
+#include <linux/version.h>
 #include <linux/init.h>
+#include <linux/blkdev.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
-
-#ifdef MODULE
-#include <linux/module.h>
-#endif				/* MODULE */
-
 #include <linux/tqueue.h>
 #include <linux/timer.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/genhd.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/hdreg.h>
 #include <linux/interrupt.h>
 #include <linux/ctype.h>
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#endif				/* CONFIG_PROC_FS */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#include <linux/spinlock.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/blkpg.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include <asm/ccwcache.h>
+#include <asm/dasd.h>
+#include <asm/debug.h>
+
+#include <asm/atomic.h>
+#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/semaphore.h>
 #include <asm/ebcdic.h>
 #include <asm/uaccess.h>
-
 #include <asm/irq.h>
+#include <asm/s390_ext.h>
+#include <asm/s390dyn.h>
+#include <asm/idals.h>
 
-#include <linux/dasd.h>
-#include <linux/blk.h>
+#ifdef CONFIG_DASD_ECKD
+#include "dasd_eckd.h"
+#endif				/*  CONFIG_DASD_ECKD */
+#ifdef CONFIG_DASD_FBA
+#include "dasd_fba.h"
+#endif				/*  CONFIG_DASD_FBA */
+#ifdef CONFIG_DASD_MDSK
+#include "dasd_diag.h"
+#endif				/*  CONFIG_DASD_MDSK */
 
-#include "dasd_erp.h"
-#include "dasd_types.h"
-#include "dasd_ccwstuff.h"
+static struct block_device_operations dasd_device_operations;
 
-#define PRINTK_HEADER DASD_NAME":"
+#ifdef MODULE
+#define EXPORT_SYMTAB
+#include <linux/module.h>
 
-#define CCW_READ_DEVICE_CHARACTERISTICS  0x64
+EXPORT_NO_SYMBOLS;
+MODULE_AUTHOR ("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
+MODULE_DESCRIPTION ("Linux on S/390 DASD device driver,"
+		    " Copyright 2000 IBM Corporation");
+MODULE_SUPPORTED_DEVICE ("dasd");
+MODULE_PARM (dasd, "1-" __MODULE_STRING (256) "s");
+EXPORT_SYMBOL (dasd_discipline_enq);
+EXPORT_SYMBOL (dasd_discipline_deq);
+EXPORT_SYMBOL (dasd_start_IO);
+EXPORT_SYMBOL (dasd_int_handler);
+EXPORT_SYMBOL (dasd_alloc_request);
+EXPORT_SYMBOL (dasd_free_request);
 
-#define DASD_SSCH_RETRIES 2
+#endif				/* MODULE */
 
-/* This macro is a little tricky, but makes the code more easy to read... */
-#define MATCH(info,ct,cm,dt,dm) ( \
-(( info -> sid_data.cu_type  ct ) && ( info -> sid_data.cu_model cm )) && \
-(( info -> sid_data.dev_type dt ) && ( info -> sid_data.dev_model dm )) )
+/* SECTION: Constant definitions to be used within this file */
+#undef ERP_DEBUG
 
-/* Prototypes for the functions called from external */
-static int dasd_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
-static int dasd_open (struct inode *, struct file *);
-static int dasd_release (struct inode *, struct file *);
+#define PRINTK_HEADER DASD_NAME": "
 
-void dasd_debug (unsigned long tag);
-void dasd_profile_add (cqr_t *cqr);
-void dasd_proc_init (void);
+#define DASD_EMERGENCY_REQUESTS 16
+#define DASD_MIN_SIZE_FOR_QUEUE 32
+#undef CONFIG_DYNAMIC_QUEUE_MIN_SIZE
+#define DASD_CHANQ_MAX_SIZE 6
 
-static int dasd_format( int, format_data_t * );
 
-static struct block_device_operations dasd_device_operations;
+/* SECTION: prototypes for static functions of dasd.c */
 
-spinlock_t dasd_lock;		/* general purpose lock for the dasd driver */
+static request_fn_proc do_dasd_request;
+void dasd_schedule_bh (dasd_device_t *);
+static int dasd_set_device_level (unsigned int, int, dasd_discipline_t *, int);
+static request_queue_t *dasd_get_queue (kdev_t kdev);
 
-/* All asynchronous I/O should waint on this wait_queue */
-wait_queue_head_t dasd_waitq;
+static struct block_device_operations dasd_device_operations;
 
-static int dasd_autodetect = 1;
-static int dasd_devno[DASD_MAX_DEVICES] =
-{0,};
-static int dasd_count = 0;
+#ifdef CONFIG_DASD_DYNAMIC
+/* SECTION: managing dynamic configuration of dasd_driver */
 
-extern dasd_chanq_t *cq_head;
+static dasd_devreg_t *dasd_devreg_head = NULL;
 
-static int
-dasd_get_hexdigit (char c)
+/* 
+ * function: dasd_create_devreg
+ * creates a dasd_devreg_t related to a devno
+ */
+static inline dasd_devreg_t *
+dasd_create_devreg (int devno)
 {
-	if ((c >= '0') && (c <= '9'))
-		return c - '0';
-	if ((c >= 'a') && (c <= 'f'))
-		return c + 10 - 'a';
-	if ((c >= 'A') && (c <= 'F'))
-		return c + 10 - 'A';
-	return -1;
+	dasd_devreg_t *r = kmalloc (sizeof (dasd_devreg_t), GFP_KERNEL);
+	if (r != NULL) {
+		memset (r, 0, sizeof (dasd_devreg_t));
+		r->devreg.ci.devno = devno;
+		r->devreg.flag = DEVREG_TYPE_DEVNO;
+		r->devreg.oper_func = dasd_oper_handler;
+	}
+	return r;
 }
 
-/* sets the string pointer after the next comma */
-static void
-dasd_scan_for_next_comma (char **strptr)
+/* 
+ * function: dasd_destroy_devreg
+ * destroys the dasd_devreg_t given as argument
+ */
+static inline void
+dasd_destroy_devreg (dasd_devreg_t * devreg)
 {
-	while (((**strptr) != ',') && ((**strptr)++))
-		(*strptr)++;
-
-	/* set the position AFTER the comma */
-	if (**strptr == ',')
-		(*strptr)++;
+	kfree (devreg);
 }
 
-/*sets the string pointer after the next comma, if a parse error occured */
-static int
-dasd_get_next_int (char **strptr)
+#endif				/* CONFIG_DASD_DYNAMIC */
+
+/* SECTION: managing setup of dasd_driver */
+
+/* default setting is probeonly, autodetect */
+static int dasd_probeonly = 1;	/* is true, when probeonly mode is active */
+static int dasd_autodetect = 1;	/* is true, when autodetection is active */
+
+/* dasd_range_t are used for ordering the DASD devices */
+typedef struct dasd_range_t {
+	unsigned int from;	/* first DASD in range */
+	unsigned int to;	/* last DASD in range */
+	char discipline[4];	/* placeholder to force discipline */
+	struct dasd_range_t *next;	/* next one in linked list */
+} dasd_range_t;
+
+static dasd_range_t *dasd_range_head = NULL;	/* anchor for list of ranges */
+static spinlock_t range_lock = SPIN_LOCK_UNLOCKED;
+
+/* 
+ * function: dasd_create_range
+ * creates a dasd_range_t according to the arguments 
+ * FIXME: no check is performed for reoccurrence of a devno
+ */
+static inline dasd_range_t *
+dasd_create_range (int from, int to)
 {
-	int j, i = -1;		/* for cosmetic reasons first -1, then 0 */
-	if (isxdigit (**strptr)) {
-		for (i = 0; isxdigit (**strptr);) {
-			i <<= 4;
-			j = dasd_get_hexdigit (**strptr);
-			if (j == -1) {
-				PRINT_ERR ("no integer: skipping range.\n");
-				dasd_scan_for_next_comma (strptr);
-				i = -1;
-				break;
-			}
-			i += j;
-			(*strptr)++;
-			if (i > 0xffff) {
-				PRINT_ERR (" value too big, skipping range.\n");
-				dasd_scan_for_next_comma (strptr);
-				i = -1;
-				break;
-			}
-		}
+	dasd_range_t *range = NULL;
+	range = (dasd_range_t *) kmalloc (sizeof (dasd_range_t), GFP_KERNEL);
+	if (range == NULL)
+		return NULL;
+	memset (range, 0, sizeof (dasd_range_t));
+	range->from = from;
+	if (to == 0) {		/* single devno ? */
+		range->to = from;
+	} else {
+		range->to = to;
 	}
-	return i;
+	return range;
 }
 
-static inline int
-devindex_from_devno (int devno)
+/* 
+ * function dasd_destroy_range
+ * destroy a range allocated wit dasd_crate_range
+ * CAUTION: must not be callen in arunning sysztem, because it destroys 
+ * the mapping of DASDs
+ */
+static inline void
+dasd_destroy_range (dasd_range_t * range)
 {
-	int i;
-	for (i = 0; i < dasd_count; i++) {
-		if (dasd_devno[i] == devno)
-			return i;
-	}
-	if (dasd_autodetect) {
-		if (dasd_count < DASD_MAX_DEVICES) {
-			dasd_devno[dasd_count] = devno;
-			return dasd_count++;
-		}
-		return -EOVERFLOW;
-	}
-	return -ENODEV;
+	kfree (range);
 }
 
-/* returns 1, if dasd_no is in the specified ranges, otherwise 0 */
-static inline int
-dasd_is_accessible (int devno)
+/* 
+ * function: dasd_append_range
+ * appends the range given as argument to the list anchored at dasd_range_head. 
+ */
+static inline void
+dasd_append_range (dasd_range_t * range)
 {
-	return (devindex_from_devno (devno) >= 0);
+	dasd_range_t *temp;
+	long flags;
+
+	spin_lock_irqsave (&range_lock, flags);
+	if (dasd_range_head == NULL) {
+		dasd_range_head = range;
+	} else {
+		for (temp = dasd_range_head;
+		     temp && temp->next;
+		     temp = temp->next) ;
+		temp->next = range;
+	}
+	spin_unlock_irqrestore (&range_lock, flags);
 }
 
-/* dasd_insert_range skips ranges, if the start or the end is -1 */
-static void
-dasd_insert_range (int start, int end)
+/*
+ * function dasd_dechain_range
+ * removes a range from the chain of ranges
+ * CAUTION: must not be called in a running system because it destroys 
+ * the mapping of devices
+ */
+static inline void
+dasd_dechain_range (dasd_range_t * range)
 {
-	int curr;
-	FUNCTION_ENTRY ("dasd_insert_range");
-	if (dasd_count >= DASD_MAX_DEVICES) {
-		PRINT_ERR (" too many devices specified, ignoring some.\n");
-		FUNCTION_EXIT ("dasd_insert_range");
-		return;
+	dasd_range_t *temp, *prev = NULL;
+	unsigned long flags;
+
+	spin_lock_irqsave (&range_lock, flags);
+	for (temp = dasd_range_head; temp != NULL; temp = temp->next) {
+		if (temp == range)
+			break;
+		prev = temp;
 	}
-	if ((start == -1) || (end == -1)) {
-		PRINT_ERR
- ("invalid format of parameter, skipping range\n");
-		FUNCTION_EXIT ("dasd_insert_range");
-		return;
+	if (!temp)
+		BUG ();
+	if (prev) {
+		prev->next = temp->next;
+	} else {
+		dasd_range_head = temp->next;
 	}
-	if (end < start) {
-		PRINT_ERR (" ignoring range from %x to %x - start value " \
-			   "must be less than end value.\n", start, end);
-		FUNCTION_EXIT ("dasd_insert_range");
+	spin_unlock_irqrestore (&range_lock, flags);
+}
+
+/* 
+ * function: dasd_add_range
+ * creates a dasd_range_t according to the arguments and
+ * appends it to the list of ranges
+ * additionally a devreg_t is created and added to the list of devregs 
+ */
+static inline void
+dasd_add_range (int from, int to)
+{
+	dasd_range_t *range;
+	range = dasd_create_range (from, to);
+	if (range)
+		dasd_append_range (range);
+	else
 		return;
-	}
-/* concurrent execution would be critical, but will not occur here */
-	for (curr = start; curr <= end; curr++) {
-		if (dasd_is_accessible (curr)) {
-			PRINT_WARN (" %x is already in list as device %d\n",
-				    curr, devindex_from_devno (curr));
-		}
-		dasd_devno[dasd_count] = curr;
-		dasd_count++;
-		if (dasd_count >= DASD_MAX_DEVICES) {
-			PRINT_ERR (" too many devices specified, ignoring some.\n");
-			break;
+#ifdef CONFIG_DASD_DYNAMIC
+	/* allocate and chain devreg infos for the devnos... */
+	{
+		int i;
+		for (i = range->from; i <= range->to; i++) {
+			dasd_devreg_t *reg = dasd_create_devreg (i);
+			s390_device_register (&reg->devreg);
+			reg->next = dasd_devreg_head;
+			dasd_devreg_head = reg;
 		}
 	}
-	PRINT_INFO (" added dasd range from %x to %x.\n",
-		    start, dasd_devno[dasd_count - 1]);
-
-	FUNCTION_EXIT ("dasd_insert_range");
+#endif				/* CONFIG_DASD_DYNAMIC */
 }
 
-static int __init
-dasd_setup (char *str)
+/* 
+ * function: dasd_remove_range
+ * removes a range and the corresponding devregs from all of the chains
+ * CAUTION: must not be called in a running system because it destroys
+ * the mapping of devices!
+ */
+static inline void
+dasd_remove_range (dasd_range_t * range)
 {
-	int devno, devno2;
-
-	FUNCTION_ENTRY ("dasd_setup");
-	dasd_autodetect = 0;
-	while (*str && *str != 1) {
-		if (!isxdigit (*str)) {
-			str++;	/* to avoid looping on two commas */
-			PRINT_ERR (" kernel parameter in invalid format.\n");
-			continue;
-		}
-		devno = dasd_get_next_int (&str);
-
-		/* range was skipped? -> scan for comma has been done */
-		if (devno == -1)
-			continue;
-
-		if (*str == ',') {
-			str++;
-			dasd_insert_range (devno, devno);
-			continue;
-		}
-		if (*str == '-') {
-			str++;
-			devno2 = dasd_get_next_int (&str);
-			if (devno2 == -1) {
-				PRINT_ERR (" invalid character in " \
-					   "kernel parameters.");
+#ifdef CONFIG_DASD_DYNAMIC
+	/* deallocate and dechain devreg infos for the devnos... */
+	{
+		int i;
+		for (i = range->from; i <= range->to; i++) {
+			dasd_devreg_t *reg, *prev = NULL;
+			for (reg = dasd_devreg_head; reg; reg = reg->next) {
+				if (reg->devreg.flag == DEVREG_TYPE_DEVNO &&
+				    reg->devreg.devno == i &&
+				    reg->devreg.oper_func == dasd_oper_handler)
+					break;
+				prev = reg;
+			}
+			if (!reg)
+				BUG ();
+			if (prev) {
+				prev->next = reg->next;
 			} else {
-				dasd_insert_range (devno, devno2);
+				dasd_devreg_head = reg->next;
 			}
-			dasd_scan_for_next_comma (&str);
-			continue;
-		}
-		if (*str == 0) {
-			dasd_insert_range (devno, devno);
-			break;
+			s390_device_unregister (&reg->devreg);
+			dasd_destroy_devreg (reg);
 		}
-		PRINT_ERR (" unexpected character in kernel parameter, " \
-			   "skipping range.\n");
 	}
-	FUNCTION_EXIT ("dasd_setup");
-        return 1;
+	dasd_dechain_range (range);
+	dasd_destroy_range (range);
+#endif				/* CONFIG_DASD_DYNAMIC */
 }
 
-__setup("dasd=", dasd_setup);
-
-dasd_information_t *dasd_info[DASD_MAX_DEVICES] = {NULL,};
-static struct hd_struct dd_hdstruct[DASD_MAX_DEVICES << PARTN_BITS];
-static int dasd_blks[256] = {0,};
-static int dasd_secsize[256] = {0,};
-static int dasd_blksize[256] = {0,};
-static int dasd_maxsecs[256] = {0,};
-
-struct gendisk dd_gendisk =
+/* 
+ * function: dasd_devindex_from_devno
+ * finds the logical number of the devno supplied as argument in the list
+ * of dasd ranges and returns it or ENODEV when not found
+ */
+static int
+dasd_devindex_from_devno (int devno)
 {
-	MAJOR_NR,		/* Major number */
-	"dasd",			/* Major name */
-	PARTN_BITS,		/* Bits to shift to get real from partn */
-	1 << PARTN_BITS,	/* Number of partitions per real */
-	dd_hdstruct,		/* hd struct */
-	dasd_blks,		/* sizes in blocks */
-	DASD_MAX_DEVICES,	/* number */
-	NULL,			/* internal */
-	NULL			/* next */
+	dasd_range_t *temp;
+	int devindex = 0;
+	unsigned long flags;
 
-};
+	spin_lock_irqsave (&range_lock, flags);
+	for (temp = dasd_range_head; temp; temp = temp->next) {
+		if (devno >= temp->from && devno <= temp->to) {
+			spin_unlock_irqrestore (&range_lock, flags);
+			return devindex + devno - temp->from;
+		}
+		devindex += temp->to - temp->from + 1;
+	}
+	spin_unlock_irqrestore (&range_lock, flags);
+	return -ENODEV;
+}
 
-static atomic_t bh_scheduled = ATOMIC_INIT (0);
+/* SECTION: parsing the dasd= parameter of the parmline/insmod cmdline */
 
-static inline void
-schedule_bh (void (*func) (void))
+/* 
+ * char *dasd[] is intended to hold the ranges supplied by the dasd= statement
+ * it is named 'dasd' to directly be filled by insmod with the comma separated
+ * strings when running as a module.
+ * a maximum of 256 ranges can be supplied, as the parmline is limited to
+ * <1024 Byte anyway.
+ */
+char *dasd[256] = {NULL,};
+
+#ifndef MODULE
+/* 
+ * function: dasd_split_parm_string
+ * splits the parmline given to the kernel into comma separated strings
+ * which are filled into the 'dasd[]' array, to be parsed later on
+ */
+static void
+dasd_split_parm_string (char *str)
 {
-	static struct tq_struct dasd_tq =
-	{0,};
-	/* Protect against rescheduling, when already running */
-	if (atomic_compare_and_swap (0, 1, &bh_scheduled))
-		return;
-	dasd_tq.routine = (void *) (void *) func;
-	queue_task (&dasd_tq, &tq_immediate);
-	mark_bh (IMMEDIATE_BH);
-	return;
+	char *tmp = str;
+	int count = 0;
+	do {
+		char *end;
+		int len;
+		end = strchr (tmp, ',');
+		if (end == NULL) {
+			len = strlen (tmp) + 1;
+		} else {
+			len = (long) end - (long) tmp + 1;
+			*end = '\0';
+			end++;
+		}
+		dasd[count] = kmalloc (len * sizeof (char), GFP_ATOMIC);
+		if (dasd == NULL) {
+			printk (KERN_WARNING PRINTK_HEADER
+			    "can't store dasd= parameter no %d\n", count + 1);
+			break;
+		}
+		memset (dasd[count], 0, len * sizeof (char));
+		memcpy (dasd[count], tmp, len * sizeof (char));
+		count++;
+		tmp = end;
+	} while (tmp != NULL && *tmp != '\0');
 }
 
-void
-sleep_done (struct semaphore *sem)
+/* 
+ * dasd_parm_string holds a concatenated version of all 'dasd=' parameters
+ * supplied in the parmline, which is later to be split by 
+ * dasd_split_parm_string
+ * FIXME: why first concatenate then split ?
+ */
+static char dasd_parm_string[1024] __initdata = {0,};
+
+/* 
+ * function: dasd_setup
+ * is invoked for any single 'dasd=' parameter supplied in the parmline
+ * it merges all the arguments into dasd_parm_string
+ */
+void __init
+dasd_setup (char *str, int *ints)
 {
-	if (sem != NULL) {
-		up (sem);
+	int len = strlen (dasd_parm_string);
+	if (len != 0) {
+		strcat (dasd_parm_string, ",");
 	}
+	strcat (dasd_parm_string, str);
 }
-
-void
-sleep (int timeout)
+/* 
+ * function: dasd_call_setup 
+ * is the 2.4 version of dasd_setup and
+ * is invoked for any single 'dasd=' parameter supplied in the parmline
+ */
+int __init
+dasd_call_setup (char *str)
 {
-	struct semaphore sem;
-	struct timer_list timer;
-
-        init_MUTEX_LOCKED (&sem);
-	init_timer (&timer);
-	timer.data = (unsigned long) &sem;
-	timer.expires = jiffies + timeout;
-	timer.function = (void (*)(unsigned long)) sleep_done;
-	printk (KERN_DEBUG PRINTK_HEADER
-		"Sleeping for timer tics %d\n", timeout);
-	add_timer (&timer);
-	down (&sem);
-	del_timer (&timer);
+        int dummy;
+        dasd_setup(str,&dummy);
+	return 1;
 }
 
-#ifdef CONFIG_DASD_ECKD
-extern dasd_operations_t dasd_eckd_operations;
-#endif				/* CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK
-extern dasd_operations_t dasd_mdsk_operations;
-#endif				/* CONFIG_DASD_MDSK */
-
-dasd_operations_t *dasd_disciplines[] =
-{
-#ifdef CONFIG_DASD_ECKD
-	&dasd_eckd_operations,
-#endif				/* CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK
-	&dasd_mdsk_operations,
-#endif				/* CONFIG_DASD_MDSK */
-#ifdef CONFIG_DASD_CKD
-	&dasd_ckd_operations,
-#endif				/* CONFIG_DASD_CKD */
-        NULL
-};
-
-char *dasd_name[] =
-{
-#ifdef CONFIG_DASD_ECKD
-	"ECKD",
-#endif				/* CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK
-	"MDSK",
-#endif				/* CONFIG_DASD_MDSK */
-#ifdef CONFIG_DASD_CKD
-        "CKD",
-#endif                          /* CONFIG_DASD_CKD */
-	"END"
-};
+__setup ("dasd=", dasd_call_setup);
 
+#endif /* MODULE */
 
+/* 
+ * function: dasd_strtoul
+ * provides a wrapper to simple_strtoul to strip leading '0x' and
+ * interpret any argument to dasd=[range,...] as hexadecimal
+ */
 static inline int
-do_dasd_ioctl (struct inode *inp, unsigned int no, unsigned long data)
+dasd_strtoul (char *str, char **stra)
 {
-	int rc;
-	int di;
-	dasd_information_t *dev;
-
-	di = DEVICE_NR (inp->i_rdev);
-	if (!dasd_info[di]) {
-		PRINT_WARN ("No device registered as %d\n", inp->i_rdev);
-		return -EINVAL;
-	}
-	if ((_IOC_DIR (no) != _IOC_NONE) && (data == 0)) {
-		PRINT_DEBUG ("empty data ptr");
-		return -EINVAL;
-	}
-	dev = dasd_info[di];
-	if (!dev) {
-		PRINT_WARN ("No device registered as %d\n", inp->i_rdev);
-		return -EINVAL;
-	}
-	PRINT_INFO ("ioctl 0x%08x %s'0x%x'%d(%d) on dev %d/%d (%d) with data %8lx\n", no,
-		    _IOC_DIR (no) == _IOC_NONE ? "0" :
-		    _IOC_DIR (no) == _IOC_READ ? "r" :
-		    _IOC_DIR (no) == _IOC_WRITE ? "w" :
-		    _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u",
-		    _IOC_TYPE (no), _IOC_NR (no), _IOC_SIZE (no),
-		    MAJOR (inp->i_rdev), MINOR (inp->i_rdev), di, data);
+	char *temp = str;
+	int val;
+	if (*temp == '0') {
+		temp++;		/* strip leading zero */
+		if (*temp == 'x')
+			temp++;	/* strip leading x */
+	}
+	val = simple_strtoul (temp, &temp, 16);		/* interpret anything as hex */
+	*stra = temp;
+	return val;
+}
 
-	switch (no) {
-	case BLKGETSIZE:{	/* Return device size */
-			unsigned long blocks;
-			if (inp->i_rdev & 0x01) {
-				blocks = (dev->sizes.blocks - 3) <<
-				    dev->sizes.s2b_shift;
-			} else {
-				blocks = dev->sizes.kbytes << dev->sizes.s2b_shift;
-			}
-			rc = copy_to_user ((long *) data, &blocks, sizeof (long));
-			break;
-		}
-	case BLKFLSBUF:{
-			rc = fsync_dev (inp->i_rdev);
-			break;
-		}
-	case BLKRAGET:{
-			rc = copy_to_user ((long *) data,
-					read_ahead + MAJOR_NR, sizeof (long));
-			break;
-		}
-	case BLKRASET:{
-			rc = copy_from_user (read_ahead + MAJOR_NR,
-					     (long *) data, sizeof (long));
-			break;
-		}
-	case BLKRRPART:{
-			INTERNAL_CHECK ("BLKRPART not implemented%s", "");
-			rc = -EINVAL;
-			break;
-		}
-	case HDIO_GETGEO:{
-			INTERNAL_CHECK ("HDIO_GETGEO not implemented%s", "");
-			rc = -EINVAL;
-			break;
-		}
+/* 
+ * function: dasd_parse
+ * examines the strings given in the string array str and
+ * creates and adds the ranges to the apropriate lists
+ */
+static inline void
+dasd_parse (char **str)
+{
+	char *temp;
+	int from, to;
 
-	case BIODASDRSID:{
-			rc = copy_to_user ((void *) data,
-					   &(dev->info.sid_data),
-					   sizeof (senseid_t));
+	if (*str) {
+		/* turn off probeonly mode, if any dasd parameter is present */
+		dasd_probeonly = 0;
+		dasd_autodetect = 0;
+	}
+	while (*str) {
+		temp = *str;
+		from = 0;
+		to = 0;
+		if (strcmp ("autodetect", *str) == 0) {
+			dasd_autodetect = 1;
+			printk (KERN_INFO "turning to autodetection mode\n");
 			break;
-		}
-	case BIODASDRWTB:{
-			int offset = 0;
-			int xlt;
-			rc = copy_from_user (&xlt, (void *) data,
-					     sizeof (int));
-                        PRINT_INFO("Xlating %d to",xlt);
-			if (rc)
-				break;
-			if (MINOR (inp->i_rdev) & 1)
-				offset = 3;
-			xlt += offset;
-                        printk(" %d \n",xlt);
-			rc = copy_to_user ((void *) data, &xlt,
-					   sizeof (int));
+		} else if (strcmp ("probeonly", *str) == 0) {
+			dasd_probeonly = 1;
+			printk (KERN_INFO "turning to probeonly mode\n");
 			break;
-		}
-	case BIODASDFORMAT:{
-			/* fdata == NULL is a valid arg to dasd_format ! */
-			format_data_t *fdata = NULL;
-			if (data) {
-				fdata = kmalloc (sizeof (format_data_t),
-						 GFP_ATOMIC);
-				if (!fdata) {
-					rc = -ENOMEM;
-					break;
-				}
-				rc = copy_from_user (fdata, (void *) data,
-						     sizeof (format_data_t));
-				if (rc)
-					break;
-			}
-			rc = dasd_format (inp->i_rdev, fdata);
-			if (fdata) {
-				kfree (fdata);
+		} else {
+			/* turn off autodetect mode, if any range is present */
+			dasd_autodetect = 0;
+			from = dasd_strtoul (temp, &temp);
+			if (*temp == '-') {
+				temp++;
+				to = dasd_strtoul (temp, &temp);
 			}
-			break;
+			dasd_add_range (from, to);
 		}
-	default:
-		rc = -EINVAL;
-		break;
+		str++;
 	}
-	return rc;
 }
 
-static void
-dasd_end_request (struct request *req, int uptodate)
+/* SECTION: Dealing with devices registered to multiple major numbers */
+
+static spinlock_t dasd_major_lock = SPIN_LOCK_UNLOCKED;
+static major_info_t dasd_major_info[] =
 {
-	struct buffer_head *bh;
-	FUNCTION_ENTRY ("dasd_end_request");
-#if DASD_PARANOIA > 2
-	if (!req) {
-		INTERNAL_CHECK ("end_request called with zero arg%s\n", "");
-	}
-#endif				/* DASD_PARANOIA */
-	while ((bh = req->bh) != NULL) {
-		req->bh = bh->b_reqnext;
-		bh->b_reqnext = NULL;
-		bh->b_end_io (bh, uptodate);
-	}
-	if (!end_that_request_first (req, uptodate, DEVICE_NAME)) {
-#ifndef DEVICE_NO_RANDOM
-		add_blkdev_randomness (MAJOR (req->rq_dev));
-#endif
-		DEVICE_OFF (req->rq_dev);
-		end_that_request_last (req);
+	{
+		next:NULL,
+		gendisk: {
+                        INIT_GENDISK(94,DASD_NAME,DASD_PARTN_BITS,DASD_PER_MAJOR)
+		}
 	}
-	FUNCTION_EXIT ("dasd_end_request");
-	return;
-}
+};
 
-void
-dasd_wakeup (void)
+static major_info_t *
+get_new_major_info (void)
 {
-	wake_up (&dasd_waitq);
+	major_info_t *major_info = NULL;
+	unsigned long flags;
+
+	major_info = kmalloc (sizeof (major_info_t), GFP_KERNEL);
+	if (major_info) {
+		major_info_t *temp = dasd_major_info;
+                static major_info_t temp_major_info[] =
+                {
+                        {
+                                next:NULL,
+                                gendisk: {
+                                        INIT_GENDISK(0,DASD_NAME,DASD_PARTN_BITS,DASD_PER_MAJOR)
+                                }
+                        }
+                };
+		spin_lock_irqsave (&dasd_major_lock, flags);
+		while (temp->next)
+			temp = temp->next;
+		temp->next = major_info;
+		spin_unlock_irqrestore (&dasd_major_lock, flags);
+		memcpy (major_info, temp_major_info, sizeof (major_info_t));
+	}
+	return major_info;
 }
 
-int
-dasd_unregister_dasd (int irq, dasd_type_t dt, dev_info_t * info)
+static int
+dasd_register_major (major_info_t * major_info)
 {
 	int rc = 0;
-	FUNCTION_ENTRY ("dasd_unregister_dasd");
-	INTERNAL_CHECK ("dasd_unregister_dasd not implemented%s\n", "");
-	FUNCTION_EXIT ("dasd_unregister_dasd");
-	return rc;
+	int major;
+
+	if (major_info == NULL) {
+		major_info = get_new_major_info ();
+		if (!major_info) {
+			printk (KERN_WARNING PRINTK_HEADER
+				"Cannot get memory to allocate another major number\n");
+			return -ENOMEM;
+		} else {
+			printk (KERN_INFO PRINTK_HEADER
+				"Created another major number\n");
+		}
+	}
+	major = major_info->gendisk.major;
+	rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations);
+	if (rc < 0) {
+		printk (KERN_WARNING PRINTK_HEADER
+		      "Cannot register to major no %d, rc = %d\n", major, rc);
+		return rc;
+	}
+	if (major == 0) {
+		major = rc;
+		rc = 0;
+	}
+	major_info->dasd_device = (dasd_device_t **) kmalloc (DASD_PER_MAJOR * sizeof (dasd_device_t *),
+							      GFP_ATOMIC);
+	if (!major_info->dasd_device)
+		goto out_devfs;
+	memset (major_info->dasd_device, 0, DASD_PER_MAJOR * sizeof (dasd_device_t *));
+	blk_size[major] =
+	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
+	if (!blk_size[major])
+		goto out_dasd_device;
+	memset (blk_size[major], 0, (1 << MINORBITS) * sizeof (int));
+	blksize_size[major] =
+	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
+	if (!blksize_size[major])
+		goto out_blk_size;
+	memset (blksize_size[major], 0, (1 << MINORBITS) * sizeof (int));
+	hardsect_size[major] =
+	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
+	if (!hardsect_size[major])
+		goto out_blksize_size;
+	memset (hardsect_size[major], 0, (1 << MINORBITS) * sizeof (int));
+	max_sectors[major] =
+	    (int *) kmalloc ((1 << MINORBITS) * sizeof (int), GFP_ATOMIC);
+	if (!max_sectors[major])
+		goto out_hardsect_size;
+	memset (max_sectors[major], 0, (1 << MINORBITS) * sizeof (int));
+
+	/* finally do the gendisk stuff */
+	major_info->gendisk.part = kmalloc ((1 << MINORBITS) *
+					    sizeof (struct hd_struct),
+					    GFP_ATOMIC);
+	if (!major_info->gendisk.part)
+		goto out_max_sectors;
+	memset (major_info->gendisk.part, 0, (1 << MINORBITS) *
+		sizeof (struct hd_struct));
+
+	INIT_BLK_DEV(major,do_dasd_request,dasd_get_queue,NULL);
+
+	major_info->gendisk.major = major;
+	major_info->gendisk.next = gendisk_head;
+	major_info->gendisk.sizes = blk_size[major];
+	gendisk_head = &major_info->gendisk;
+	return major;
+out_max_sectors:
+	kfree(max_sectors[major]);
+out_hardsect_size:
+	kfree(hardsect_size[major]);
+out_blksize_size:
+	kfree(blksize_size[major]);
+out_blk_size:
+	kfree(blk_size[major]);
+out_dasd_device:
+	kfree(major_info->dasd_device);
+out_devfs:
+	devfs_unregister_blkdev(major, DASD_NAME);
+	return -ENOMEM;
 }
 
-/* Below you find the functions already cleaned up */
-static dasd_type_t
-check_type (dev_info_t * info)
+static int
+dasd_unregister_major (major_info_t * major_info)
 {
-	dasd_type_t type = dasd_none;
+	int rc = 0;
+	int major;
+	struct gendisk *dd, *prev = NULL;
 
-	FUNCTION_ENTRY ("check_type");
-#ifdef CONFIG_DASD_ECKD
-	if (MATCH (info, == 0x3990, ||1, == 0x3390, ||1) ||
-	    MATCH (info, == 0x9343, ||1, == 0x9345, ||1) ||
-	    MATCH (info, == 0x3990, ||1, == 0x3380, ||1)) {
-		type = dasd_eckd;
-	} else
-#endif				/* CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK
-        if ( MACHINE_IS_VM ) {
-          type = dasd_mdsk;
-        } else 
-#endif 		/* CONFIG_DASD_MDSK */
-        {
-          type = dasd_none;
-        }
-        
-	FUNCTION_EXIT ("check_type");
-	return type;
+	if (major_info == NULL) {
+		return -EINVAL;
+	}
+	major = major_info->gendisk.major;
+        INIT_BLK_DEV(major,NULL,NULL,NULL);
+	blk_size[major] = NULL;
+	blksize_size[major] = NULL;
+	hardsect_size[major] = NULL;
+	max_sectors[major] = NULL;
+
+	/* do the gendisk stuff */
+	for (dd = gendisk_head; dd; dd = dd->next) {
+		if (dd == &major_info->gendisk) {
+			if (prev)
+				prev->next = dd->next;
+			else
+				gendisk_head = dd->next;
+			break;
+		}
+		prev = dd;
+	}
+	if (dd == NULL) {
+		return -ENOENT;
+	}
+	kfree (major_info->dasd_device);
+	kfree (blk_size[major]);
+	kfree (blksize_size[major]);
+	kfree (hardsect_size[major]);
+	kfree (max_sectors[major]);
+	kfree (major_info->gendisk.part);
+
+	rc = devfs_unregister_blkdev (major, DASD_NAME);
+	if (rc < 0) {
+		printk (KERN_WARNING PRINTK_HEADER
+		  "Cannot unregister from major no %d, rc = %d\n", major, rc);
+		return rc;
+	}
+	if (major_info->gendisk.major > 128)
+		kfree (major_info);
+	return rc;
 }
 
-static int
-dasd_read_characteristics (dasd_information_t * info)
+/* 
+ * function: dasd_device_from_kdev
+ * finds the device structure corresponding to the kdev supplied as argument
+ * in the major_info structures and returns it or NULL when not found
+ */
+static inline dasd_device_t *
+dasd_device_from_kdev (kdev_t kdev)
 {
-	int rc;
-	int ct = 0;
-	dev_info_t *di;
-	dasd_type_t dt;
+	major_info_t *major_info = dasd_major_info;
+	unsigned long flags;
 
-	FUNCTION_ENTRY ("read_characteristics");
-	if (info == NULL) {
-		return -ENODEV;
-	}
-	di = &(info->info);
-	if (di == NULL) {
-		return -ENODEV;
+	spin_lock_irqsave (&dasd_major_lock, flags);
+	while (major_info &&
+	       major_info->gendisk.major != MAJOR (kdev)) {
+		major_info = major_info->next;
+	}
+	spin_unlock_irqrestore (&dasd_major_lock, flags);
+	if (major_info)
+		return major_info->dasd_device[MINOR (kdev) >> DASD_PARTN_BITS];
+	return NULL;
+}
+
+/* 
+ * function: dasd_device_from_devno
+ * finds the address of the device structure corresponding to the devno 
+ * supplied as argument in the major_info structures and returns 
+ * it or NULL when not found
+ */
+static inline dasd_device_t **
+dasd_device_from_devno (int devno)
+{
+	major_info_t *major_info = dasd_major_info;
+	int devindex = dasd_devindex_from_devno (devno);
+	unsigned long flags;
+
+	spin_lock_irqsave (&dasd_major_lock, flags);
+	for (major_info = dasd_major_info; major_info;
+	     major_info = major_info->next) {
+		if (devindex < DASD_PER_MAJOR) {
+			spin_unlock_irqrestore (&dasd_major_lock, flags);
+			return &major_info->dasd_device[devindex];
+		}
+		devindex -= DASD_PER_MAJOR;
 	}
-	dt = check_type (di);
-	/* Some cross-checks, if the cu supports RDC */
-	if (MATCH (di, == 0x2835, ||1, ||1, ||1) ||
-	    MATCH (di, == 0x3830, ||1, ||1, ||1) ||
-	    MATCH (di, == 0x3830, ||1, ||1, ||1) ||
-	    MATCH (di, == 0x3990, <=0x03, == 0x3380, <=0x0d)) {
-		PRINT_WARN ("Device %d (%x/%x at %x/%x) supports no RDC\n",
-			    info->info.irq,
-			    di->sid_data.dev_type,
-			    di->sid_data.dev_model,
-			    di->sid_data.cu_type,
-			    di->sid_data.cu_model);
-		return -EINVAL;
+	spin_unlock_irqrestore (&dasd_major_lock, flags);
+	return NULL;
+}
+
+/* SECTION: managing dasd disciplines */
+
+/* anchor and spinlock for list of disciplines */
+static dasd_discipline_t *dasd_disciplines;
+static spinlock_t discipline_lock = SPIN_LOCK_UNLOCKED;
+
+/* 
+ * function dasd_discipline_enq 
+ * chains the discpline given as argument to the head of disiplines
+ * head chaining policy is required to allow module disciplines to
+ * be preferred against those, who are statically linked
+ */
+void
+dasd_discipline_enq (dasd_discipline_t * d)
+{
+	spin_lock (&discipline_lock);
+	d->next = dasd_disciplines;
+	dasd_disciplines = d;
+	spin_unlock (&discipline_lock);
+}
+
+/* 
+ * function dasd_discipline_deq 
+ * removes the discipline given as argument from the list of disciplines
+ */
+int
+dasd_discipline_deq (dasd_discipline_t * d)
+{
+	int rc = 0;
+	spin_lock (&discipline_lock);
+	if (dasd_disciplines == d) {
+		dasd_disciplines = dasd_disciplines->next;
+	} else {
+		dasd_discipline_t *b;
+		b = dasd_disciplines;
+		while (b && b->next != d)
+			b = b->next;
+		if (b != NULL) {
+			b->next = b->next->next;
+		} else {
+			rc = -ENOENT;
+		}
 	}
-	switch (dt) {
-#ifdef CONFIG_DASD_ECKD
-	case dasd_eckd:
-          ct = 64;
-          rc = read_dev_chars (info->info.irq,
-                               (void *) &(info->rdc_data), ct);
-		break;
-#endif				/*  CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK
-	case dasd_mdsk:
-		ct = 0;
+	spin_unlock (&discipline_lock);
+	return rc;
+}
+
+static inline dasd_discipline_t *
+dasd_find_discipline (dasd_device_t * device)
+{
+	dasd_discipline_t *temp;
+	for (temp = dasd_disciplines; temp != NULL; temp = temp->next) {
+		if (temp->id_check)
+			if (temp->id_check (&device->devinfo)) {
+				continue;
+                        }
+		if (temp->check_characteristics) {
+			if (temp->check_characteristics (device)) {
+				continue;
+                        }
+		}
 		break;
-#endif				/*  CONFIG_DASD_MDSK */
-	default:
-		INTERNAL_ERROR ("don't know dasd type %d\n", dt);
 	}
-	if (rc) {
-		PRINT_WARN ("RDC resulted in rc=%d\n", rc);
+	return temp;
+}
+
+/* SECTION: profiling stuff */
+
+static dasd_profile_info_t dasd_global_profile;
+
+/*
+ * macro: dasd_profile_add_counter
+ * increments counter in global and local profiling structures
+ * according to the value
+ */
+#define dasd_profile_add_counter( value, counter, device ) \
+{ \
+        int ind; \
+        long help; \
+	for (ind = 0, help = value >> 3; \
+             ind < 31 && help; \
+             help = help >> 1, ind++) {} \
+	dasd_global_profile.counter[ind]++; \
+        device->profile.counter[ind]++; \
+}
+
+/*
+ * function dasd_profile_add 
+ * adds the profiling information from the cqr given as argument to the
+ * global and device specific profiling information 
+ */
+void
+dasd_profile_add (ccw_req_t * cqr)
+{
+	long strtime, irqtime, endtime, tottime;
+	long tottimeps, sectors;
+	dasd_device_t *device = cqr->device;
+
+	if (!cqr->req)		/* safeguard against abnormal cqrs */
+		return;
+	sectors = ((struct request *) (cqr->req))->nr_sectors;
+	strtime = ((cqr->startclk - cqr->buildclk) >> 12);
+	irqtime = ((cqr->stopclk - cqr->startclk) >> 12);
+	endtime = ((cqr->endclk - cqr->stopclk) >> 12);
+	tottime = ((cqr->endclk - cqr->buildclk) >> 12);
+	tottimeps = tottime / sectors;
+
+	if (!dasd_global_profile.dasd_io_reqs) {
+		memset (&dasd_global_profile, 0, sizeof (dasd_profile_info_t));
+	};
+	if (!device->profile.dasd_io_reqs) {
+		memset (&device->profile, 0, sizeof (dasd_profile_info_t));
+	};
+
+        dasd_global_profile.dasd_io_reqs++;
+        device->profile.dasd_io_reqs++;
+	dasd_profile_add_counter (sectors, dasd_io_secs, device);
+	dasd_profile_add_counter (tottime, dasd_io_times, device);
+	dasd_profile_add_counter (tottimeps, dasd_io_timps, device);
+	dasd_profile_add_counter (strtime, dasd_io_time1, device);
+	dasd_profile_add_counter (irqtime, dasd_io_time2, device);
+	dasd_profile_add_counter (irqtime / sectors, dasd_io_time2ps, device);
+	dasd_profile_add_counter (endtime, dasd_io_time3, device);
+}
+
+/* SECTION: (de)queueing of requests to channel program queues */
+
+/* 
+ * function dasd_chanq_enq 
+ * appends the cqr given as argument to the queue
+ * has to be called with the queue lock (namely the s390_irq_lock) acquired
+ */
+static inline void
+dasd_chanq_enq (dasd_chanq_t * q, ccw_req_t * cqr)
+{
+	if (q->head != NULL) {
+		q->tail->next = cqr;
+	} else
+		q->head = cqr;
+	cqr->next = NULL;
+	q->tail = cqr;
+	check_then_set (&cqr->status, CQR_STATUS_FILLED, CQR_STATUS_QUEUED);
+}
+
+/* 
+ * function dasd_chanq_enq_head
+ * chains the cqr given as argument to the queue head
+ * has to be called with the queue lock (namely the s390_irq_lock) acquired
+ */
+static inline void
+dasd_chanq_enq_head (dasd_chanq_t * q, ccw_req_t * cqr)
+{
+	cqr->next = q->head;
+	q->head = cqr;
+	if (q->tail == NULL)
+		q->tail = cqr;
+	check_then_set (&cqr->status,
+		       CQR_STATUS_FILLED,
+		       CQR_STATUS_QUEUED);
+}
+
+/* 
+ * function dasd_chanq_deq
+ * dechains the cqr given as argument from the queue
+ * has to be called with the queue lock (namely the s390_irq_lock) acquired
+ */
+int
+dasd_chanq_deq (dasd_chanq_t * q, ccw_req_t * cqr)
+{
+	ccw_req_t *prev;
+
+	if (cqr == NULL)
+		BUG ();
+
+	if (cqr == q->head) {
+		q->head = cqr->next;
+		if (q->head == NULL)
+			q->tail = NULL;
+
+	} else {
+		prev = q->head;
+		while (prev && prev->next != cqr)
+			prev = prev->next;
+		if (prev == NULL)
+			return -ENOENT;
+		prev->next = cqr->next;
+		if (prev->next == NULL)
+			q->tail = prev;
 	}
-	FUNCTION_EXIT ("read_characteristics");
-	return rc;
+	cqr->next = NULL;
+	return 0;
 }
 
-/* How many sectors must be in a request to dequeue it ? */
-#define QUEUE_BLOCKS 25
-#define QUEUE_SECTORS (QUEUE_BLOCKS << dasd_info[di]->sizes.s2b_shift)
+/* SECTION: All the gendisk stuff */
+
+/* 
+ * function dasd_partn_detect
+ * calls the function in genhd, which is appropriate to setup a partitioned disk
+ */
+static void
+dasd_partn_detect (dasd_device_t * dev)
+{
+	major_info_t *major_info = dev->major_info;
+	struct gendisk *dd = &major_info->gendisk;
+	int minor = MINOR (dev->kdev);
+
+	register_disk (dd,
+		       MKDEV (dd->major, minor),
+		       1 << DASD_PARTN_BITS,
+		       &dasd_device_operations,
+		       (dev->sizes.blocks << dev->sizes.s2b_shift));
+}
 
-/* How often to retry an I/O before raising an error */
-#define DASD_MAX_RETRIES 5
+/* SECTION: Managing wrappers for ccwcache */
 
+/* array and spinlock of emergency requests */
+static ccw_req_t *dasd_emergency_req[DASD_EMERGENCY_REQUESTS];
+static spinlock_t dasd_emergency_req_lock = SPIN_LOCK_UNLOCKED;
 
-static inline
- cqr_t *
-dasd_cqr_from_req (struct request *req)
+/* 
+ * function dasd_init_emergeny_req
+ * allocates emergeny requests
+ */
+static inline void __init
+dasd_init_emergency_req (void)
 {
-	cqr_t *cqr = NULL;
-	int di;
-	dasd_information_t *info;
+	int i;
+	for (i = 0; i < DASD_EMERGENCY_REQUESTS; i++) {
+		dasd_emergency_req[i] = (ccw_req_t *) get_free_page (GFP_KERNEL);
+		memset (dasd_emergency_req[i], 0, PAGE_SIZE);
+	}
+}
 
-	if (!req) {
-		PRINT_ERR ("No request passed!");
-		return NULL;
+/* 
+ * function dasd_cleanup_emergeny_req
+ * tries to free emergeny requests skipping those, which are currently in use
+ */
+static inline void
+dasd_cleanup_emergency_req (void)
+{
+	int i;
+	for (i = 0; i < DASD_EMERGENCY_REQUESTS; i++) {
+		if (dasd_emergency_req[i])
+			free_page ((long) (dasd_emergency_req[i]));
+		else
+			printk (KERN_WARNING PRINTK_HEADER
+				"losing page for emergency request in use\n");
 	}
-	di = DEVICE_NR (req->rq_dev);
-	info = dasd_info[di];
-	if (!info)
-		return NULL;
-	/* if applicable relocate block */
-        if (MINOR (req->rq_dev) & ((1 << PARTN_BITS) - 1) ) {
-          req->sector += 
-            dd_gendisk.part[MINOR(req->rq_dev)].start_sect;
-        }
-	/* Now check for consistency */
-	if (!req->nr_sectors) {
-		PRINT_WARN ("req: %p dev: %08x sector: %ld nr_sectors: %ld bh: %p\n",
-		     req, req->rq_dev, req->sector, req->nr_sectors, req->bh);
-		return NULL;
+}
+
+/* 
+ * function dasd_alloc_request
+ * tries to return space for a channel program of length cplength with
+ * additional data of size datasize. 
+ * If the ccwcache cannot fulfill the request it tries the emergeny requests
+ * before giving up finally
+ * FIXME: initialization of ccw_req_t should be done by function of ccwcache
+ */
+ccw_req_t *
+dasd_alloc_request (char *magic, int cplength, int datasize)
+{
+	ccw_req_t *rv = NULL;
+	int i;
+	unsigned long flags;
+
+	if ((rv = ccw_alloc_request (magic, cplength, datasize)) != NULL) {
+		return rv;
 	}
-	if (((req->sector + req->nr_sectors) >> 1) > info->sizes.kbytes) {
-		printk (KERN_ERR PRINTK_HEADER
-			"Requesting I/O past end of device %d\n",
-			di);
-		return NULL;
+	if ((((sizeof (ccw_req_t) + 7) & -8) + 
+             cplength*sizeof(ccw1_t) + datasize) > PAGE_SIZE) {
+            BUG();
+        }
+	spin_lock_irqsave (&dasd_emergency_req_lock, flags);
+	for (i = 0; i < DASD_EMERGENCY_REQUESTS; i++) {
+		if (dasd_emergency_req[i] != NULL) {
+			rv = dasd_emergency_req[i];
+			dasd_emergency_req[i] = NULL;
+			break;
+		}
 	}
-	cqr = dasd_disciplines[info->type]->get_req_ccw (di, req);
-	if (!cqr) {
-		PRINT_WARN ("empty CQR generated\n");
+	spin_unlock_irqrestore (&dasd_emergency_req_lock, flags);
+	if (rv) {
+		memset (rv, 0, PAGE_SIZE);
+		rv->cache = (kmem_cache_t *) (dasd_emergency_req + i);
+		strncpy ((char *) (&rv->magic), magic, 4);
+		ASCEBC ((char *) (&rv->magic), 4);
+		rv->cplength = cplength;
+		rv->datasize = datasize;
+		rv->data = (void *) ((long) rv + PAGE_SIZE - datasize);
+		rv->cpaddr = (ccw1_t *) ((long) rv + sizeof (ccw_req_t));
 	} else {
-		cqr->req = req;
-		cqr->int4cqr = cqr;
-		cqr->devindex = di;
-#ifdef DASD_PROFILE
-		asm volatile ("STCK %0":"=m" (cqr->buildclk));
-#endif				/* DASD_PROFILE */
-		if (atomic_compare_and_swap (CQR_STATUS_EMPTY,
-					     CQR_STATUS_FILLED,
-					     &cqr->status)) {
-			PRINT_WARN ("cqr from req stat changed %d\n",
-				    atomic_read (&cqr->status));
-		}
+		panic ("No way to fulfill request for I/O request\n");
 	}
-	return cqr;
+	return rv;
 }
 
+/* 
+ * function dasd_free_request
+ * returns a ccw_req_t to the appropriate cache or emergeny request line
+ */
+void
+dasd_free_request (ccw_req_t * request)
+{
+	if ((request->cache >= (kmem_cache_t *) dasd_emergency_req) &&
+	    (request->cache < (kmem_cache_t *) (dasd_emergency_req +
+						DASD_EMERGENCY_REQUESTS))) {
+		*((ccw_req_t **) (request->cache)) = request;
+	} else {
+		ccw_free_request (request);
+	}
+}			
+
+/* SECTION: Managing the device queues etc. */
+
+
+/* 
+ * function dasd_start_IO
+ * attempts to start the IO and returns an appropriate return code
+ */
 int
-dasd_start_IO (cqr_t * cqr)
+dasd_start_IO (ccw_req_t * cqr)
 {
 	int rc = 0;
-	int retries = DASD_SSCH_RETRIES;
-	int di, irq;
-
-	dasd_debug ((unsigned long) cqr);	/* cqr */
+	dasd_device_t *device = cqr->device;
+	int irq;
+        unsigned long long now;
 
 	if (!cqr) {
-		PRINT_WARN ("(start_IO) no cqr passed\n");
-		return -EINVAL;
+		BUG ();
 	}
-	if (cqr->magic != DASD_MAGIC) {
-		PRINT_WARN ("(start_IO) magic number mismatch\n");
+	irq = device->devinfo.irq;
+	if (strncmp ((char *) &cqr->magic, device->discipline->ebcname, 4)) {
+		DASD_MESSAGE (KERN_WARNING, device,
+			      " ccw_req_t 0x%08X magic doesn't match"
+			      " discipline 0x%08X\n",
+			      cqr->magic,
+			      *(unsigned int *) device->discipline->name);
 		return -EINVAL;
 	}
-	if (atomic_compare_and_swap (CQR_STATUS_QUEUED,
-				     CQR_STATUS_IN_IO,
-				     &cqr->status)) {
-		PRINT_WARN ("start_IO: status changed %d\n",
-			    atomic_read (&cqr->status));
-		atomic_set (&cqr->status, CQR_STATUS_ERROR);
-		return -EINVAL;
-	}
-        di = cqr->devindex;
-	irq = dasd_info[di]->info.irq;
-	do {
-		asm volatile ("STCK %0":"=m" (cqr->startclk));
-		rc = do_IO (irq, cqr->cpaddr, (long) cqr, 0x00, cqr->options);
-		switch (rc) {
-		case 0:
-			if (!(cqr->options & DOIO_WAIT_FOR_INTERRUPT))
-                        	atomic_set_mask (DASD_CHANQ_BUSY,
-                                	         &dasd_info[di]->queue.flags);
-			break;
-		case -ENODEV:
-			PRINT_WARN ("cqr %p: 0x%04x error, %d retries left\n",
-				    cqr, dasd_info[di]->info.devno, retries);
-			break;
-		case -EIO:
-			PRINT_WARN ("cqr %p: 0x%04x I/O, %d retries left\n",
-				    cqr, dasd_info[di]->info.devno, retries);
-			break;
-		case -EBUSY:	/* set up timer, try later */
-			
-			PRINT_WARN ("cqr %p: 0x%04x busy, %d retries left\n",
-				    cqr, dasd_info[di]->info.devno, retries);
-			break;
-		default:
-			
-			PRINT_WARN ("cqr %p: 0x%04x %d, %d retries left\n",
-				    cqr, rc, dasd_info[di]->info.devno,
-                                    retries);
-			break;
-		}
-	} while (rc && --retries);
-	if (rc) {
-		if (atomic_compare_and_swap (CQR_STATUS_IN_IO,
-					     CQR_STATUS_ERROR,
-					     &cqr->status)) {
-			PRINT_WARN ("start_IO:(done) status changed %d\n",
-				    atomic_read (&cqr->status));
-		        atomic_set (&cqr->status, CQR_STATUS_ERROR);
-		}
+
+        asm volatile ("STCK %0":"=m" (now));
+        rc = do_IO (irq, cqr->cpaddr, (long) cqr, cqr->lpm, cqr->options);
+        switch (rc) {
+        case 0:
+            break;
+        case -ENODEV:
+                check_then_set (&cqr->status, 
+                               CQR_STATUS_QUEUED, CQR_STATUS_FAILED);
+            break;
+        case -EIO:
+                check_then_set (&cqr->status, 
+                               CQR_STATUS_QUEUED, CQR_STATUS_FAILED);
+            break;
+        case -EBUSY:
+                DASD_MESSAGE (KERN_WARNING, device,"%s",
+                              "device busy, retry later\n");
+                break;
+        default:
+                DASD_MESSAGE (KERN_ERR, device,
+                              "line %d unknown RC=%d, please report"
+                              " to linux390@de.ibm.com\n",
+                              __LINE__, rc);
+                BUG();
+            break;
         }
+	if (rc == 0) {
+                check_then_set (&cqr->status, 
+                               CQR_STATUS_QUEUED, CQR_STATUS_IN_IO);
+                cqr->startclk = now;
+	}
 	return rc;
 }
 
-static inline
-void
-dasd_end_cqr (cqr_t * cqr, int uptodate)
+/* 
+ * function sleep_on_req
+ * attempts to start the IO and waits for completion
+ * FIXME: replace handmade sleeping by wait_event
+ */
+static int
+sleep_on_req (ccw_req_t * req)
 {
-	struct request *req = cqr->req;
-	asm volatile ("STCK %0":"=m" (cqr->endclk));
-#ifdef DASD_PROFILE
-	dasd_profile_add (cqr);
-#endif				/* DASD_PROFILE */
-	dasd_chanq_deq (&dasd_info[cqr->devindex]->queue, cqr);
-        if (req) {
-                dasd_end_request (req, uptodate);
-        }
-}
+	unsigned long flags;
+	int cs;
+	int rc = 0;
+	dasd_device_t *device = (dasd_device_t *) req->device;
 
-void
-dasd_dump_sense (devstat_t * stat)
+	s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
+	dasd_chanq_enq (&device->queue, req);
+        /* let the bh start the request to keep them in order */
+	dasd_schedule_bh (device); 
+        
+	do {
+		s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);
+                wait_event (device->wait_q,
+                            (((cs=req->status)==CQR_STATUS_DONE)||
+                            (cs==CQR_STATUS_FAILED)));
+		s390irq_spin_lock_irqsave (device->devinfo.irq, flags);
+		cs = req->status;
+	} while (cs != CQR_STATUS_DONE && cs != CQR_STATUS_FAILED);
+
+	s390irq_spin_unlock_irqrestore (device->devinfo.irq, flags);
+	if (cs == CQR_STATUS_FAILED) {
+		rc = -EIO;
+	}
+	return rc;
+
+}				/* end sleep_on_req */
+
+/* 
+ * function dasd_end_request
+ * posts the buffer_cache about a finalized request
+ * FIXME: for requests splitted to serveral cqrs
+ */
+static inline void
+dasd_end_request (struct request *req, int uptodate)
 {
-	int sl, sct;
-	if ( ! stat->flag | DEVSTAT_FLAG_SENSE_AVAIL) {
-		PRINT_INFO("I/O status w/o sense data");
-        } else {
-		printk (KERN_INFO PRINTK_HEADER
-			"-------------------I/O result:-----------\n");
-		for (sl = 0; sl < 4; sl++) {
-			printk (KERN_INFO PRINTK_HEADER "Sense:");
-			for (sct = 0; sct < 8; sct++) {
-				printk (" %2d:0x%02X", 8 * sl + sct,
-					stat->ii.sense.data[8 * sl + sct]);
-			}
-			printk ("\n");
-		}	
+	struct buffer_head *bh;
+	while ((bh = req->bh) != NULL) {
+                int nsect = bh->b_size >> 9;
+                blk_finished_io (nsect);
+		req->bh = bh->b_reqnext;
+		bh->b_reqnext = NULL;
+		bh->b_end_io (bh, uptodate);
 	}
+	if (!end_that_request_first (req, uptodate, DASD_NAME)) {
+#ifndef DEVICE_NO_RANDOM
+		add_blkdev_randomness (MAJOR (req->rq_dev));
+#endif
+		end_that_request_last (req);
+	}
+	return;
+}
+
+/* 
+ * function dasd_get_queue
+ * returns the queue corresponding to a device behind a kdev
+ */
+static request_queue_t *
+dasd_get_queue (kdev_t kdev)
+{
+	dasd_device_t *device = dasd_device_from_kdev (kdev);
+	return &device->request_queue;
 }
 
-static int 
-register_dasd_last (int di)
+/* 
+ * function dasd_check_expire_time
+ * check the request given as argument for expiration
+ * and returns 0 if not yet expired, nonzero else
+ */
+static inline int
+dasd_check_expire_time (ccw_req_t * cqr)
 {
+	unsigned long long now;
 	int rc = 0;
-	int minor;
-        struct buffer_head *bh;
-	rc = dasd_disciplines[dasd_info[di]->type]->fill_sizes_last (di);
-	switch (rc) {
-	case -EMEDIUMTYPE:
-		dasd_info[di]->flags |= DASD_INFO_FLAGS_NOT_FORMATTED;
-		break;
-	}
-	PRINT_INFO ("%ld kB <- 'soft'-block: %d, hardsect %d Bytes\n",
-		    dasd_info[di]->sizes.kbytes,
-		    dasd_info[di]->sizes.bp_block,
-		    dasd_info[di]->sizes.bp_sector);
-	switch (dasd_info[di]->type) {
-#ifdef CONFIG_DASD_ECKD
-	case dasd_eckd:
-		dasd_info[di]->sizes.label_block = 2;
-		break;
-#endif				/* CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK
-	case dasd_mdsk:
-		dasd_info[di]->sizes.label_block = -1;
-		break;
-#endif				/* CONFIG_DASD_ECKD */
 
-	default:
-		INTERNAL_CHECK ("Unknown dasd type %d\n", dasd_info[di]->type);
+	asm volatile ("STCK %0":"=m" (now));
+	if ( cqr->expires + cqr->startclk <  now) {
+		DASD_MESSAGE (KERN_ERR, ((dasd_device_t*)cqr->device),
+			      "IO timeout 0x%08lx%08lx usecs with req %p\n",
+			      (long) (cqr->expires >> 44), 
+                              (long) (cqr->expires >> 12), cqr);
+		cqr->expires <<=1;
 	}
-	minor = di << PARTN_BITS;
-	dasd_blks[minor] = dasd_info[di]->sizes.kbytes;
-	dasd_secsize[minor] = dasd_info[di]->sizes.bp_sector;
-	dasd_blksize[minor] = dasd_info[di]->sizes.bp_block;
-	dasd_maxsecs[minor] = 252<<dasd_info[di]->sizes.s2b_shift;
-	dasd_secsize[minor+1] = dasd_info[di]->sizes.bp_sector;
-	dasd_blksize[minor+1] = dasd_info[di]->sizes.bp_block;
-	dasd_maxsecs[minor+1] = 252<<dasd_info[di]->sizes.s2b_shift;
-
-        {
-#define DASD_NAME_PREFIX "dasd_"
-                char * name =  (char *) kmalloc ( 1+strlen (DASD_NAME_PREFIX) +
-                                                  2 /* 0x */ + 4 /* devno */,
-                                                  GFP_KERNEL);
-                sprintf ( name , DASD_NAME_PREFIX "%04x%c",
-                          dasd_info[di]->info.devno,'\0' );
-                dasd_info[di] -> devfs_entry =
-                        devfs_register ( NULL /* dir */,
-                                         name,
-                                         DEVFS_FL_DEFAULT /* flags */,
-                                         DASD_MAJOR, minor,
-                                         0755 /* mode */, 
-                                         &dasd_device_operations, 
-                                         (void *)dasd_info[di]);
-        }
-        /* end of that stuff */ 
 	return rc;
 }
 
-void 
-dasd_partn_detect ( int di ) 
+/* 
+ * function dasd_finalize_request
+ * implemets the actions to perform, when a request is finally finished
+ * namely in status CQR_STATUS_DONE || CQR_STATUS_FAILED
+ */
+static inline void
+dasd_finalize_request (ccw_req_t * cqr)
 {
-  int  minor = di << PARTN_BITS;
-  LOOP_CONTROL ("Setting partitions of DASD %d\n", di);
-  register_disk (&dd_gendisk,
-                 MKDEV(DASD_MAJOR,minor),
-                 1 << PARTN_BITS,
-                 &dasd_device_operations,
-                 dasd_info[di]->sizes.kbytes << 1);
+        dasd_device_t *device = cqr->device;
+	dasd_discipline_t *discipline = device->discipline;
+        
+	asm volatile ("STCK %0":"=m" (cqr->endclk));
+	if (cqr->req) {
+                dasd_end_request (cqr->req, (cqr->status == CQR_STATUS_DONE));
+                dasd_profile_add (cqr);
+		/* free request if nobody is waiting on it */
+		dasd_free_request (cqr);
+	} else {
+		/* during format we don't have the request structure */
+		/* notify sleeping task about finished postprocessing */
+		wake_up (&device->wait_q);
+	}
+	return;
 }
 
-void
-dasd_do_chanq (void)
+/* 
+ * function dasd_process_queues
+ * transfers the requests on the queue given as argument to the chanq
+ * if possible, the request ist started on a fastpath
+ */
+static void
+dasd_process_queues (dasd_device_t *device)
 {
-	dasd_chanq_t *qp = NULL;
-	cqr_t *cqr;
-        long flags;
-        int irq;
-        int tasks;
-	atomic_set (&bh_scheduled, 0);
-	dasd_debug (0xc4c40000);	/* DD */
-	while ((tasks = atomic_read(&chanq_tasks)) != 0) {
-/* initialization and wraparound */
-		if (qp == NULL) {
-			dasd_debug (0xc4c46df0);        /* DD_0 */
-			qp = cq_head;
-			if (!qp) {
-                          dasd_debug (0xc4c46ff1);        /* DD?1 */
-                          dasd_debug (tasks);      
-                          PRINT_ERR("Mismatch of NULL queue pointer and "
-                                    "still %d chanq_tasks to do!!\n"
-                                    "Please send output of /proc/dasd/debug "
-                                    "to Linux390@de.ibm.com\n", tasks);
-                          atomic_set(&chanq_tasks,0);
-                          break;
-			}
-		}
-/* Get first request */
-		dasd_debug ((unsigned long) qp);
-		cqr = (cqr_t *) (qp->head);
-/* empty queue -> dequeue and proceed */
-		if (!cqr) {
-			dasd_chanq_t *nqp = qp->next_q;
-			cql_deq (qp);
-			qp = nqp;
-			continue;
-		}
-/* process all requests on that queue */
-		do {
-			cqr_t *next;
-			dasd_debug ((unsigned long) cqr);	/* cqr */
-			if (cqr->magic != DASD_MAGIC) {
-				dasd_debug (0xc4c46ff2);	/* DD?2 */
-				panic ( PRINTK_HEADER "do_cq:"
-					"magic mismatch %p -> %x\n", 
-					cqr, cqr -> magic);
-                                break;
-			}
-                        irq = dasd_info[cqr->devindex]->info.irq;
-                        s390irq_spin_lock_irqsave (irq, flags);
-			switch (atomic_read (&cqr->status)) {
-			case CQR_STATUS_IN_IO:
-                                dasd_debug (0xc4c4c9d6);	/* DDIO */
-                                cqr = NULL;
-                                break;
-			case CQR_STATUS_QUEUED:
-                                dasd_debug (0xc4c4e2e3);	/* DDST */
-                                if (dasd_start_IO (cqr) == 0) {
-                                        atomic_dec (&chanq_tasks);
-                                        cqr = NULL;
-                                }
-                                break;
-			case CQR_STATUS_ERROR:
-                                dasd_debug (0xc4c4c5d9);	/* DDER */
-                                dasd_dump_sense (cqr->dstat);
-                                if ( ++ cqr->retries  < 2 ) {
-                                        atomic_set (&cqr->status,
-                                                    CQR_STATUS_QUEUED);
-	                                dasd_debug (0xc4c4e2e3); /* DDST */
-                                        if (dasd_start_IO (cqr) == 0) {
-                                                atomic_dec ( &qp -> 
-                                                             dirty_requests);
-                                                atomic_dec (&chanq_tasks);
-                                                cqr = NULL;
-                                        }
-                                } else {
-                                        atomic_set (&cqr->status,
-                                                    CQR_STATUS_FAILED);
-                                }
-                                break;
-			case CQR_STATUS_DONE:
-                                next = cqr->next;
-                                dasd_debug (0xc4c49692);	/* DDok */
-                                dasd_end_cqr (cqr, 1);
-                                atomic_dec (&chanq_tasks);
-                                cqr = next;
-                                break;
-			case CQR_STATUS_FAILED:
-                                next = cqr->next;
-                                dasd_debug (0xc4c47a7a);	/* DD:: */
-				if ( ! ( dasd_info[cqr->devindex]-> flags &
-                                         DASD_INFO_FLAGS_INITIALIZED ) ) {
-					dasd_info[cqr->devindex]-> flags |=
-                                                DASD_INFO_FLAGS_INITIALIZED |
-                                                DASD_INFO_FLAGS_NOT_FORMATTED;
-				}
-                                dasd_end_cqr (cqr, 0);
-                                atomic_dec ( &qp -> dirty_requests );
-                                atomic_dec (&chanq_tasks);
-                                cqr = next;
-                                break;
-			default:
-                                PRINT_WARN ("unknown cqrstatus\n");
-                                cqr = NULL;
+        unsigned long flags;
+        struct request *req;
+        request_queue_t * queue = &device->request_queue;
+	dasd_chanq_t *qp = &device->queue;
+        int irq = device -> devinfo.irq;
+        ccw_req_t *final_requests= NULL;
+        static int chanq_min_size = DASD_MIN_SIZE_FOR_QUEUE;
+        int chanq_max_size = DASD_CHANQ_MAX_SIZE;
+        ccw_req_t * cqr=NULL,*temp;
+        dasd_erp_postaction_fn_t erp_postaction;
+
+        s390irq_spin_lock_irqsave (irq, flags);
+        /* First we dechain the requests, processed with completed status */
+        while ( qp -> head && 
+                ((qp -> head -> status == CQR_STATUS_DONE) || 
+                 (qp -> head -> status == CQR_STATUS_FAILED) ||
+		 (qp -> head -> status == CQR_STATUS_ERROR) ) ) {
+		dasd_erp_action_fn_t erp_action;
+		ccw_req_t *erp_cqr = NULL;
+		/*  preprocess requests with CQR_STATUS_ERROR */
+		if (qp -> head -> status == CQR_STATUS_ERROR) {
+			if ((qp -> head -> dstat -> flag & DEVSTAT_HALT_FUNCTION) ||
+			    (qp->head->retries-- == 0 ) ||
+			    (device->discipline->erp_action==NULL) ||
+			    ((erp_action=device->discipline->erp_action(qp->head))==NULL)||
+			    ((erp_cqr = erp_action(qp->head))== NULL)) {
+				check_then_set (&qp->head->status,
+                                                CQR_STATUS_ERROR,
+                                                CQR_STATUS_FAILED);
+                                continue;
+			} else {
+				dasd_chanq_enq_head (qp, erp_cqr);
+				/* chain of completed requests is now broken */
+				break; 
 			}
-                        s390irq_spin_unlock_irqrestore (irq, flags);
-		} while (cqr);
-		qp = qp->next_q;
-	}
-	spin_lock (&io_request_lock);
-	do_dasd_request (&blk_dev[DASD_MAJOR].request_queue);
-	spin_unlock (&io_request_lock);
-	dasd_debug (0xc4c46d6d);	/* DD__ */
+		} else if ( qp -> head -> refers ) { /* we deal with an ERP */
+                        char *uptodatestr;
+                        if ( qp -> head -> status == CQR_STATUS_DONE) {
+                                uptodatestr = "ERP successful";
+                        } else {
+                                uptodatestr = "ERP unsuccessful";
+                        }
+                        
+                        if (device->discipline->erp_postaction == NULL ||
+                            ((erp_postaction = device->discipline->erp_postaction (qp->head)) == NULL)) {
+                                /* 
+                                                         * maybe we shoud set it to FAILED, 
+                                                         * because we are very paranoid ;) 
+                                                         */
+                                erp_postaction = default_erp_postaction;
+                        }
+                        DASD_MESSAGE (KERN_INFO, device,
+                                      "%s: postaction [<%p>]\n",
+                                      uptodatestr, erp_postaction);
+                        erp_postaction (qp->head);
+                        continue;
+                }
+                
+		/* dechain request now */
+                if ( final_requests == NULL )
+                        final_requests = qp -> head;
+                cqr = qp -> head;
+                qp -> head = qp -> head -> next;
+		if (qp->head == NULL)
+			qp->tail = NULL;
+        }
+        if ( cqr )
+            cqr -> next = NULL;
+        /* Now we try to fetch requests from the request queue */
+        for (temp = cqr; temp != NULL ;temp=temp-> next )
+                if ( temp ->status == CQR_STATUS_QUEUED)
+                        chanq_max_size --;
+	while ( (! list_empty(&queue->queue_head)) && 
+                (req=dasd_next_request(queue)) != NULL) {
+                /* queue empty or certain critera fulfilled -> transfer */
+                if ( qp -> head == NULL ||
+                     chanq_max_size > 0 ||
+                     (req->nr_sectors >= chanq_min_size)) {
+                        ccw_req_t *cqr;
+                        /* relocate request according to partition table */
+                        req->sector += device->major_info->gendisk.part[MINOR (req->rq_dev)].start_sect;
+                        cqr = device->discipline->build_cp_from_req (device, req);
+                        if (cqr == NULL) {
+                                DASD_MESSAGE (KERN_WARNING, device,
+                                              "CCW creation failed on request %p\n", req);
+				/* revert relocation of request */
+                                req->sector -= device->major_info->gendisk.part[MINOR (req->rq_dev)].start_sect;
+                                break; /* terminate request queue loop */
+                                
+                        } 
+#ifdef CONFIG_DYNAMIC_QUEUE_MIN_SIZE
+                        chanq_min_size = (chanq_min_size + req->nr_sectors)>>1; 
+#endif /* CONFIG_DYNAMIC_QUEUE_MIN_SIZE */
+                        dasd_dequeue_request(queue,req);
+			dasd_chanq_enq (qp, cqr);
+                } else { /* queue not empty OR criteria not met */
+                        break; /* terminate request queue loop */
+                }
+        }
+        /* we process the requests with non-final status */
+        if ( qp -> head ) {
+                switch ( qp->head->status ) {
+                case CQR_STATUS_QUEUED:
+                        /* try to start the first I/O that can be started */
+                        if ( device->discipline->start_IO (qp->head) != 0) 
+                                BUG();
+                        break;
+                case CQR_STATUS_IN_IO:
+                        /* Check, if to invoke the missing interrupt handler */
+                        if ( dasd_check_expire_time (qp->head) ) {
+                                /* to be filled with MIH */
+                        }
+                        break;
+                default: 
+                        BUG();
+                }
+        }
+        /* Now clean the requests with final status */
+        while ( final_requests ) {
+                cqr = final_requests;
+                final_requests = cqr-> next;
+                dasd_finalize_request( cqr );
+        }
+        s390irq_spin_unlock_irqrestore (irq, flags);
 }
 
 /* 
-   The request_fn is called from ll_rw_blk for any new request.
-   We use it to feed the chanqs.
-   This implementation assumes we are serialized by the io_request_lock.
+ * function dasd_run_bh
+ * acquires the locks needed and then runs the bh
  */
+static void
+dasd_run_bh (dasd_device_t *device)
+{
+	long flags;
+	spin_lock_irqsave (&io_request_lock, flags);
+	atomic_set(&device->bh_scheduled,0);
+	dasd_process_queues (device);
+	spin_unlock_irqrestore (&io_request_lock, flags);
+}
 
-#define QUEUE_THRESHOLD 5
-
+/* 
+ * function dasd_schedule_bh
+ * schedules the request_fn to run with next run_bh cycle
+ */
 void
-do_dasd_request (request_queue_t *queue)
+dasd_schedule_bh (dasd_device_t *device)
 {
-	struct request *req;
-	cqr_t *cqr;
-	dasd_chanq_t *q;
-	long flags;
-        int di, irq, go;
-        int broken, busy;
-        
-	dasd_debug (0xc4d90000);	/* DR */
-	dasd_debug ((unsigned long) __builtin_return_address(0));
-        go = 1;
-        while (go && !list_empty(&queue->queue_head)) {
-                req = blkdev_entry_next_request(&queue->queue_head);
-		di = DEVICE_NR (req->rq_dev);
-		dasd_debug ((unsigned long) req);	/* req */
-		dasd_debug (0xc4d90000 +	/* DR## */
-                            ((((di/16)<9?(di/16)+0xf0:(di/16)+0xc1))<<8) +
-                            (((di%16)<9?(di%16)+0xf0:(di%16)+0xc1)));
-                irq = dasd_info[di]->info.irq;
-                s390irq_spin_lock_irqsave (irq, flags);
-                q = &dasd_info[di]->queue;
-                busy = atomic_read(&q->flags) & DASD_CHANQ_BUSY;
-                broken = atomic_read(&q->flags)&DASD_REQUEST_Q_BROKEN;
-                if ( ! busy ||
-                     ( ! broken && 
-                       (req->nr_sectors >= QUEUE_SECTORS))) {
-                        blkdev_dequeue_request(req);
-                        /*
-                          printk ( KERN_INFO "0x%04x %c %d %d\n",
-                          req->rq_dev,req->cmd ?'w':'r',
-                          req->sector,req->nr_sectors);
-                        */
-                        cqr = dasd_cqr_from_req (req);
-                        if (!cqr) {
-                                dasd_debug (0xc4d96ff1); /* DR?1 */
-                                dasd_end_request (req, 0);
-                                goto cont;
-                        }
-                        dasd_debug ((unsigned long) cqr);     /* cqr */
-                        dasd_chanq_enq (q, cqr);
-                        if (!(atomic_read (&q->flags) &
-                              DASD_CHANQ_ACTIVE)) {
-                                cql_enq_head (q);
-                        }
-                        if ( ! busy ) {
-                                atomic_clear_mask (DASD_REQUEST_Q_BROKEN, 
-                                                   &q->flags );
-                                if (atomic_read( &q->dirty_requests) == 0 ) {
-                                        if ( dasd_start_IO (cqr) == 0 ) {
-                                        } else {
-                                                atomic_inc (&chanq_tasks);
-                                                schedule_bh (dasd_do_chanq);
-                                        }
-                                }
-                        } 
-                } else {
-                        dasd_debug (0xc4d9c2d9);	/* DRBR */
-                        atomic_set_mask (DASD_REQUEST_Q_BROKEN, &q->flags );
-                        go = 0;
+	/* Protect against rescheduling, when already running */
+        if (atomic_compare_and_swap(0,1,&device->bh_scheduled)) {
+                return;
+        }
+
+	INIT_LIST_HEAD(&device->bh_tq.list);
+	device->bh_tq.sync = 0;
+	device->bh_tq.routine = (void *) (void *) dasd_run_bh;
+	device->bh_tq.data = device;
+
+	queue_task (&device->bh_tq, &tq_immediate);
+	mark_bh (IMMEDIATE_BH);
+	return;
+}
+
+/* 
+ * function do_dasd_request
+ * is called from ll_rw_blk.c and provides the caller of 
+ * dasd_process_queues
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+static void
+do_dasd_request (request_queue_t * queue)
+{
+        dasd_device_t *device = (dasd_device_t *)
+                ((long)queue-(long)offsetof (dasd_device_t, request_queue));
+	dasd_process_queues (device);
+}
+#else
+static void
+do_dasd_request (void)
+{
+	major_info_t *major_info;
+	dasd_device_t *device;
+	int i;
+
+	for (major_info = dasd_major_info;
+	     major_info != NULL;
+	     major_info = major_info->next) {
+		for (i = 0; i < DASD_PER_MAJOR; i++) {
+			device = major_info->dasd_device[i];
+			if (!device)
+				continue;	/* remove indentation level */
+			dasd_process_queues (device);
 		}
-        cont:
-                s390irq_spin_unlock_irqrestore (irq, flags);
 	}
-	dasd_debug (0xc4d96d6d);	/* DR__ */
 }
+#endif				/* LINUX_IS_24 */
 
+
+
+
+/* 
+ * function dasd_int_handler
+ * is the DASD driver's default interrupt handler for SSCH-IO
+ */
 void
-dasd_handler (int irq, void *ds, struct pt_regs *regs)
+dasd_int_handler (int irq, void *ds, struct pt_regs *regs)
 {
-	devstat_t *stat = (devstat_t *) ds;
 	int ip;
-	cqr_t *cqr;
-	int done_fast_io = 0;
-        
-	dasd_debug (0xc4c80000);	/* DH */
-	if (!stat)
-		PRINT_ERR ("handler called without devstat");
+        int devno;
+	ccw_req_t *cqr;
+	dasd_device_t *device;
+        unsigned long long now;
+#ifdef ERP_DEBUG
+	static int counter;
+#endif
+	dasd_era_t era = dasd_era_none; /* default is everything is okay */
+	devstat_t *stat = (devstat_t *)ds;
+
+        asm volatile ("STCK %0":"=m" (now));
+        if (stat == NULL) {
+                BUG();
+	}
 	ip = stat->intparm;
-	dasd_debug (ip);	/* intparm */
-	switch (ip) {		/* filter special intparms... */
-	case 0x00000000:	/* no intparm: unsolicited interrupt */
-		dasd_debug (0xc4c8a489);	/* DHui */
-		PRINT_INFO ("Unsolicited interrupt on device %04X\n",
-			    stat->devno);
-		dasd_dump_sense (stat);
+	if (!ip) {		/* no intparm: unsolicited interrupt */
+		printk (KERN_INFO PRINTK_HEADER
+                        "unsolicited interrupt: irq0x%x devno%04X\n",
+                        irq,stat->devno);
 		return;
-	default:
-		if (ip & 0x80000001) {
-			dasd_debug (0xc4c8a489);	/* DHui */
-			PRINT_INFO ("Spurious interrupt %08x on device %04X\n",
-				    ip, stat->devno);
-			return;
-		}
-		cqr = (cqr_t *) ip;
-		if (cqr->magic != DASD_MAGIC) {
-			dasd_debug (0xc4c86ff1);	/* DH?1 */
-			PRINT_ERR ("handler:magic mismatch on %p %08x\n",
-                                   cqr, cqr->magic);
-			return;
-		}
-		asm volatile ("STCK %0":"=m" (cqr->stopclk));
-		if ( ( stat->cstat == 0x00 && 
-                       stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END) ) || 
-                     dasd_erp_examine ( cqr ) == dasd_era_none ) {
-                  dasd_debug (0xc4c89692);	/* DHok */
-                  if (atomic_compare_and_swap (CQR_STATUS_IN_IO,
-						     CQR_STATUS_DONE,
-						     &cqr->status)) {
-				PRINT_WARN ("handler: cqrstat changed%d\n",
-					    atomic_read (&cqr->status));
-				atomic_set(&cqr->status, CQR_STATUS_DONE);
-			}
-			if ( ! ( dasd_info[cqr->devindex]-> flags &
-				DASD_INFO_FLAGS_INITIALIZED ) ) {
-				int rc = register_dasd_last ( cqr->devindex );
-				dasd_info[cqr->devindex]-> flags |=
-				DASD_INFO_FLAGS_INITIALIZED;
-				if ( rc ) {
-					dasd_info[cqr->devindex]->flags &= 
-					~DASD_INFO_FLAGS_NOT_FORMATTED;
-				} else {
-					dasd_info[cqr->devindex]->flags |= 
-					DASD_INFO_FLAGS_NOT_FORMATTED;
-				}
+	}
+	if (ip & 0x80000001) {
+		printk (KERN_INFO PRINTK_HEADER
+                        "spurious interrupt: irq0x%x devno%04X, parm %08x\n",
+                        irq,stat->devno,ip);
+		return;
+	}
+	cqr = (ccw_req_t *)(long)ip;
+	device = (dasd_device_t *) cqr->device;
+	if (device == NULL || device != ds-offsetof(dasd_device_t,dev_status)) {
+                BUG();
+	}
+	devno = device->devinfo.devno;
+	if (device->devinfo.irq != irq) {
+                BUG();
+	}
+	if (strncmp (device->discipline->ebcname, (char *) &cqr->magic, 4)) {
+                BUG();
+	}
+#ifdef ERP_DEBUG
+	counter++;
+        if  ( counter % 137 == 0 ) {
+                stat->flag |= DEVSTAT_FLAG_SENSE_AVAIL;
+                stat->cstat = 0x00;
+                stat->dstat = 0x02;
+                memset(stat->ii.sense.data,0,32);
+                stat->ii.sense.data[2] = 0x06;
+                stat->ii.sense.data[4] = 0x04;
+                stat->ii.sense.data[5] = 0x60;
+                stat->ii.sense.data[6] = 0x41;
+                stat->ii.sense.data[8] = 0xff;
+                stat->ii.sense.data[9] = 0xff;
+                stat->ii.sense.data[15] = 0x05;
+                stat->ii.sense.data[16] = 0x21;
+                stat->ii.sense.data[18] = 0x60;
+                stat->ii.sense.data[19] = 0x3b;
+                stat->ii.sense.data[20] = 0x24;
+                stat->ii.sense.data[21] = 0x61;
+                stat->ii.sense.data[22] = 0x65;
+                stat->ii.sense.data[23] = 0x03;
+                stat->ii.sense.data[24] = 0x04;
+                stat->ii.sense.data[25] = 0x10;
+                stat->ii.sense.data[26] = 0x4e;
+        }
+#endif
+        /* first of all lets try to find out the appropriate era_action */
+        if ( stat->flag & DEVSTAT_FLAG_SENSE_AVAIL ||
+             stat->dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END) ) {
+                /* anything abnormal ? */
+                if ( device->discipline->examine_error == NULL ||
+                     stat->flag & DEVSTAT_HALT_FUNCTION ) {
+                        era = dasd_era_fatal;
+                } else {
+                        era = device->discipline->examine_error (cqr, stat);
+                }
+        }
+        if ( era == dasd_era_none ) {
+		if (device->level == DASD_DEVICE_LEVEL_ANALYSIS_PENDING)
+			device->level = DASD_DEVICE_LEVEL_ANALYSIS_PREPARED;
+                check_then_set(&cqr->status, 
+                               CQR_STATUS_IN_IO, CQR_STATUS_DONE);
+                cqr->stopclk=now;
+                cqr=cqr->next;
+		/* start the next queued request if possible -> fast_io */
+                if (cqr->status == CQR_STATUS_QUEUED) {
+                        if (device->discipline->start_IO (cqr) != 0) {
+                                printk (KERN_WARNING PRINTK_HEADER
+                                        "Interrupt fastpath failed!\n");
+                        } 
+                }
+        } else { /* error */
+                if (cqr->dstat == NULL)
+                        cqr->dstat = kmalloc (sizeof (devstat_t), GFP_ATOMIC);
+                if (cqr->dstat) {
+                        memcpy (cqr->dstat, stat, sizeof (devstat_t));
+                } else {
+                        PRINT_ERR ("no memory for dstat...ignoring\n");
+                }
+                /* dump sense data */
+                if (device->discipline &&
+                    device->discipline->dump_sense) {
+                        char *errmsg = device->discipline->dump_sense (device, cqr);
+                        if (errmsg != NULL) {
+                                printk ("Sense data:\n%s", errmsg);
+                                free_page ((unsigned long) errmsg);
+                        } else {
+                                printk (KERN_WARNING PRINTK_HEADER
+                                        "No memory to dump error message\n");
+                        }
+                }
+                switch(era) {
+                case dasd_era_fatal:
+                        check_then_set (&cqr->status,CQR_STATUS_IN_IO,
+                                        CQR_STATUS_FAILED);
+                        break;
+                case dasd_era_recover:
+                        check_then_set (&cqr->status,CQR_STATUS_IN_IO,
+                                        CQR_STATUS_ERROR);
+                        break;
+                default:
+                        BUG();
+                }
+        }                
+	dasd_schedule_bh (device);
+}
+
+/* SECTION: Some stuff related to error recovery */
+
+/*
+ * DEFAULT_ERP_ACTION
+ *
+ * DESCRIPTION
+ *   sets up the default-ERP ccw_req_t, namely one, which performs a TIC
+ *   to the original channel program with a retry counter of 16
+ *
+ * PARAMETER
+ *   cqr                failed CQR
+ *
+ * RETURN VALUES
+ *   erp                CQR performing the ERP
+ */
+ccw_req_t *
+default_erp_action (ccw_req_t * cqr)
+{
+	ccw_req_t *erp = ccw_alloc_request ((char *) &cqr->magic, 1, 0);
+
+	printk (KERN_WARNING PRINTK_HEADER
+		"Default ERP called... \n");
+
+	if (!erp)
+		return NULL;
+
+	erp->cpaddr->cmd_code = CCW_CMD_TIC;
+	erp->cpaddr->cda = (__u32)(void *)cqr->cpaddr;
+	erp->function = default_erp_action;
+	erp->refers = cqr;
+	erp->device = cqr->device;
+	erp->magic = cqr->magic;
+	erp->retries = 16;
+
+	erp->status = CQR_STATUS_FILLED;
+	return erp;
+}
+
+/*
+ * DEFAULT_ERP_POSTACTION
+ *
+ * DESCRIPTION
+ *   Frees all ERPs of the current ERP Chain and set the status
+ *   of the original CQR either to CQR_STATUS_DONE if ERP was successful
+ *   or to CQR_STATUS_FAILED if ERP was NOT successful.
+ *
+ * PARAMETER
+ *   erp                current erp_head
+ *
+ * RETURN VALUES
+ *   cqr                pointer to the original CQR
+ */
+ccw_req_t *
+default_erp_postaction (ccw_req_t * erp)
+{
+	dasd_device_t *device = NULL;
+        ccw_req_t *free_erp;
+        int success;
+        
+	device = (dasd_device_t *) (erp->device);
+
+	if (erp->status == CQR_STATUS_DONE)
+		success = 1;
+	else
+		success = 0;
+
+	if (erp->refers == NULL || erp->function == NULL) {
+                BUG();
+	}
+	if (erp->function != default_erp_action) {
+                printk (KERN_WARNING PRINTK_HEADER
+                        "default ERP postaction called ERP action [<%p>]\n",
+                        erp->function);
+	}
+	/* free all ERPs - but NOT the original cqr */
+        
+	while (erp->refers != NULL) {
+                free_erp = erp;
+		erp = erp->refers;
+		dasd_chanq_deq (&device->queue,	free_erp);
+		dasd_free_request (free_erp);
+	}
+        
+	/* save ptr to original cqr */
+
+        /*
+         * printk (KERN_INFO PRINTK_HEADER
+         * "default_erp_postaction - left original request = %p \n",erp);
+         */
+	/* set corresponding status to original cqr */
+	if (success) {
+		check_then_set (&erp->status, CQR_STATUS_ERROR, 
+                                CQR_STATUS_DONE);
+	} else {
+		check_then_set (&erp->status, CQR_STATUS_ERROR,
+                                CQR_STATUS_FAILED);
+	}
+        
+	/* print current erp_chain */
+#if 0
+	printk (KERN_WARNING PRINTK_HEADER
+		"default ERP postaction finished with remaining chain:\n");
+	{
+		ccw_req_t *temp_erp = NULL;
+		for (temp_erp = erp; temp_erp != NULL; temp_erp = temp_erp->refers) {
+			printk (KERN_WARNING PRINTK_HEADER
+				" erp %p refers to %p \n",
+				temp_erp, temp_erp->refers);
+		}
+	}
+#endif
+	return erp;
+}				/* end default_erp_postaction */
+
+/* SECTION: The helpers of the struct file_operations */
+
+/* 
+ * function dasd_format 
+ * performs formatting of _device_ according to _fdata_
+ * Note: The discipline's format_function is assumed to deliver formatting
+ * commands to format a single unit of the device. In terms of the ECKD
+ * devices this means CCWs are generated to format a single track.
+ */
+
+static int
+dasd_format (dasd_device_t * device, format_data_t * fdata)
+{
+	int rc = 0;
+	ccw_req_t *req = NULL;
+	format_data_t temp =
+	{
+		fdata->start_unit,
+		fdata->stop_unit,
+		fdata->blksize,
+		fdata->intensity
+	};
+
+	if (device->open_count != 1) {
+		DASD_MESSAGE (KERN_INFO, device,
+			      "device is already open %d times",
+			      device->open_count);
+		return -EINVAL;
+	}
+	if (!device->discipline->format_device) {
+		return -EINVAL;
+	}
+	/* downgrade state of the device */
+	dasd_set_device_level (device->devinfo.irq,
+			       DASD_DEVICE_LEVEL_RECOGNIZED,
+			       device->discipline,
+			       0);
+	DASD_MESSAGE (KERN_INFO, device, "Starting format from %d to %d (%d B blocks flags %d",fdata->start_unit,fdata->stop_unit,fdata->blksize,fdata->intensity);
+	/* Invalidate first track */
+	if (fdata->start_unit == DASD_FORMAT_DEFAULT_START_UNIT &&
+	    fdata->stop_unit == DASD_FORMAT_DEFAULT_STOP_UNIT &&
+	    fdata->intensity == DASD_FORMAT_DEFAULT_INTENSITY ) {
+		format_data_t temp2 =
+		{0, 0, DASD_FORMAT_DEFAULT_BLOCKSIZE, 0x04};
+		DASD_MESSAGE (KERN_INFO, device, "%s", "Invalidating first track...");
+		req = device->discipline->format_device (device, &temp2);
+		if (req) {
+			rc = sleep_on_req (req);
+			dasd_free_request (req);	/* request is no longer used */
+		} else {
+			rc = -EINVAL;
+		}
+		if (rc) {
+			printk (KERN_WARNING PRINTK_HEADER "Can't invalidate Track 0\n");
+		}
+		temp.start_unit++;
+		DASD_MESSAGE (KERN_INFO, device, "%s", "...Invalidation complete");
+	}
+	/* format remainnig tracks of device */
+	while (!rc &&
+	       ((req = device->discipline->format_device (device, &temp)) !=
+		NULL)) {
+		if ((rc = sleep_on_req (req)) != 0) {
+			DASD_MESSAGE (KERN_WARNING, device,
+				      " Formatting failed with rc = %d\n",
+				      rc);
+			break;
+		}
+		dasd_free_request (req);	/* request is no longer used */
+		temp.start_unit++;
+	}
+	if (!rc &&
+	    req == NULL) {
+		if (fdata->start_unit == DASD_FORMAT_DEFAULT_START_UNIT &&
+		    fdata->stop_unit == DASD_FORMAT_DEFAULT_STOP_UNIT &&
+	    	    fdata->intensity == DASD_FORMAT_DEFAULT_INTENSITY ) {
+			format_data_t temp2 =
+			{0, 0, fdata->blksize, fdata->intensity};
+			DASD_MESSAGE (KERN_INFO, device, "%s", "Revalidating first track...");
+			req = device->discipline->format_device (device, &temp2);
+			if (req) {
+				rc = sleep_on_req (req);
+				dasd_free_request (req);	/* request is no longer used */
+			} else {
+				rc = -EINVAL;
 			}
-			if (cqr->next) {
-                                dasd_debug (0xc4c8e2e3);	/* DHST */
-				if (dasd_start_IO (cqr->next) == 0) {
-					done_fast_io = 1; 
-                                } else {
-                                        atomic_inc (&chanq_tasks);
-				}
+			if (rc) {
+				printk (KERN_WARNING PRINTK_HEADER
+					"Can't revalidate Track 0\n");
 			}
- 			break;
+			DASD_MESSAGE (KERN_INFO, device, "%s", "...Revalidation complete");
 		}
-                 /* only visited in case of error ! */
-		dasd_debug (0xc4c8c5d9);	/* DHER */
-		if (!cqr->dstat)
-			cqr->dstat = kmalloc (sizeof (devstat_t),
-					      GFP_ATOMIC);
-		if (cqr->dstat) {
-			memcpy (cqr->dstat, stat, sizeof (devstat_t));
-		} else {
-			PRINT_ERR ("no memory for dstat\n");
+	}			/* end if no more requests */
+	if (rc)
+		DASD_MESSAGE (KERN_WARNING, device,
+			      "%s", " Formatting finished unsuccessfully");
+	else
+		DASD_MESSAGE (KERN_INFO, device,
+			      "%s", " Formatting finished successfully");
+
+	/* re-activate device even if formatting was unsuccessful */
+	/* Horst Hummel - 17/10/00 - ITPM PL020062RSC             */
+	dasd_set_device_level (device->devinfo.irq,
+			       DASD_DEVICE_LEVEL_ANALYSIS_PREPARED,
+			       device->discipline,
+			       0);
+	udelay (1500000);
+
+	dasd_set_device_level (device->devinfo.irq,
+			       DASD_DEVICE_LEVEL_ANALYSED,
+			       device->discipline,
+			       0);
+
+	return rc;
+}				/* end dasd_format */
+
+static int
+do_dasd_ioctl (struct inode *inp, /* unsigned */ int no, unsigned long data)
+{
+	int rc = 0;
+	dasd_device_t *device = dasd_device_from_kdev (inp->i_rdev);
+	major_info_t *major_info;
+
+	if (!device) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No device registered as device (%d:%d)\n",
+			MAJOR (inp->i_rdev), MINOR (inp->i_rdev));
+		return -EINVAL;
+	}
+	if ((_IOC_DIR (no) != _IOC_NONE) && (data == 0)) {
+		PRINT_DEBUG ("empty data ptr");
+		return -EINVAL;
+	}
+	major_info = device->major_info;
+#if 0
+	printk (KERN_DEBUG PRINTK_HEADER
+		"ioctl 0x%08x %s'0x%x'%d(%d) on /dev/%s (%d:%d,"
+		" devno 0x%04X on irq %d) with data %8lx\n",
+		no,
+		_IOC_DIR (no) == _IOC_NONE ? "0" :
+		_IOC_DIR (no) == _IOC_READ ? "r" :
+		_IOC_DIR (no) == _IOC_WRITE ? "w" :
+		_IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u",
+		_IOC_TYPE (no), _IOC_NR (no), _IOC_SIZE (no),
+		device->name, MAJOR (inp->i_rdev), MINOR (inp->i_rdev),
+		device->devinfo.devno, device->devinfo.irq,
+		data);
+#endif
+	switch (no) {
+	case BLKGETSIZE:{	/* Return device size */
+			long blocks = blk_size[MAJOR (inp->i_rdev)][MINOR (inp->i_rdev)] << 1;
+			rc = copy_to_user ((long *) data, &blocks, sizeof (long));
+			if (rc)
+				rc = -EFAULT;
+			break;
+		}
+	case BLKRRPART:{
+                        if (!capable(CAP_SYS_ADMIN)) {
+                            rc = -EACCES;
+                            break;
+                        }
+			fsync_dev(inp->i_rdev);
+			dasd_partn_detect (device);
+			invalidate_buffers(inp->i_rdev);
+			rc = 0;
+			break;
+		}
+	case HDIO_GETGEO:{
+			struct hd_geometry geo =
+			{0,};
+			if (device->discipline->fill_geometry)
+				device->discipline->fill_geometry (device, &geo);
+			rc = copy_to_user ((struct hd_geometry *) data, &geo,
+					   sizeof (struct hd_geometry));
+			if (rc)
+				rc = -EFAULT;
+			break;
 		}
-		/* errorprocessing */
-		atomic_set (&cqr->status, CQR_STATUS_ERROR);
-                atomic_inc (&dasd_info[cqr->devindex]->queue.dirty_requests);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+        case BLKSSZGET:
+        case BLKROSET:
+        case BLKROGET:
+        case BLKRASET:
+        case BLKRAGET:
+        case BLKFLSBUF:
+        case BLKPG: 
+        case BLKELVGET:
+        case BLKELVSET:
+                return blk_ioctl(inp->i_rdev, no, data);
+                break;
+#else
+        case BLKRASET:
+                if(!capable(CAP_SYS_ADMIN))
+                        return -EACCES;
+                if(!dev || arg > 0xff)
+                        return -EINVAL;
+                read_ahead[MAJOR(dev)] = arg;
+                rc = 0;
+                break;
+        case BLKRAGET:
+                if (!arg)
+                        return -EINVAL;
+                rc = put_user(read_ahead[MAJOR(dev)], (long *) arg);
+                break;
+        case BLKSSZGET: {
+            /* Block size of media */
+            rc = copy_to_user((int *)data,
+                              &blksize_size[MAJOR(device->kdev)]
+                              [MINOR(device->kdev)],
+                              sizeof(int)) ? -EFAULT : 0;
         }
-        if (done_fast_io == 0)
-		atomic_clear_mask (DASD_CHANQ_BUSY,
-				   &dasd_info[cqr->devindex]->queue.flags);
-        
-	if (cqr->flags & DASD_DO_IO_SLEEP) {
-		dasd_debug (0xc4c8a6a4);	/* DHwu */
-		dasd_wakeup ();
-	} else if (! (cqr->options & DOIO_WAIT_FOR_INTERRUPT) ){
-                dasd_debug (0xc4c8a293);	/* DHsl */
-                atomic_inc (&chanq_tasks);
-                schedule_bh (dasd_do_chanq);
-	} else {
-                dasd_debug (0x64686f6f);	/* DH_g */
-                dasd_debug (cqr->flags);	/* DH_g */
+        RO_IOCTLS (inp->i_rdev, data);
+	case BLKFLSBUF:{
+                if (!capable(CAP_SYS_ADMIN)) 
+                        return -EACCES;
+                fsync_dev(inp->i_rdev);
+                invalidate_buffers(inp->i_rdev);
+                rc = 0;
+                break;
+        }
+#endif				/* LINUX_IS_24 */
+	case BIODASDRSID:{
+			rc = copy_to_user ((void *) data,
+					   &(device->devinfo.sid_data),
+					   sizeof (senseid_t)) ? -EFAULT : 0;
+			break;
+		}
+	case BIODASDRWTB:{
+			int offset = 0;
+			int xlt;
+			rc = copy_from_user (&xlt, (void *) data,
+					     sizeof (int)) ? -EFAULT : 0;
+			if (rc)
+				break;
+			offset = major_info->gendisk.part[MINOR (inp->i_rdev)].start_sect >>
+			    device->sizes.s2b_shift;
+			xlt += offset;
+			rc = copy_to_user ((void *) data, &xlt,
+					   sizeof (int)) ? -EFAULT : 0;
+			break;
+		}
+	case BIODASDFORMAT:{
+			/* fdata == NULL is a valid arg to dasd_format ! */
+			int partn;
+			format_data_t fdata =
+			{
+				DASD_FORMAT_DEFAULT_START_UNIT,
+				DASD_FORMAT_DEFAULT_STOP_UNIT,
+				DASD_FORMAT_DEFAULT_BLOCKSIZE,
+				DASD_FORMAT_DEFAULT_INTENSITY};
+
+                        if (!capable(CAP_SYS_ADMIN)) {
+                            rc = -EACCES;
+                            break;
+                        }
+			if (data) {
+				rc = copy_from_user (&fdata, (void *) data,
+						     sizeof (format_data_t));
+				if (rc) {
+					rc = -EFAULT;
+					break;
+				}
+			}
+			partn = MINOR (inp->i_rdev) & ((1 << major_info->gendisk.minor_shift) - 1);
+			if (partn != 0) {
+				printk (KERN_WARNING PRINTK_HEADER
+					" devno 0x%04X on subchannel %d = /dev/%s (%d:%d)"
+				     " Cannot low-level format a partition\n",
+					device->devinfo.devno, device->devinfo.irq, device->name,
+				    MAJOR (inp->i_rdev), MINOR (inp->i_rdev));
+				return -EINVAL;
+			}
+			rc = dasd_format (device, &fdata);
+			break;
+		}
+	case BIODASDRSRV:{
+            ccw_req_t *req;
+            if (!capable(CAP_SYS_ADMIN)) {
+                rc = -EACCES;
+                break;
+            }
+            req = device->discipline->reserve (device);
+            rc = sleep_on_req (req);
+            dasd_free_request (req);
+            break;
+        }
+	case BIODASDRLSE:{
+            ccw_req_t *req;
+            if (!capable(CAP_SYS_ADMIN)) {
+                rc = -EACCES;
+                break;
+            }
+            req = device->discipline->release (device);
+            rc = sleep_on_req (req);
+            dasd_free_request (req);
+            break;
         }
-	dasd_debug (0xc4c86d6d);	/* DHwu */
+	case BIODASDSLCK:{
+			printk (KERN_WARNING PRINTK_HEADER
+				"Unsupported ioctl BIODASDSLCK\n");
+			break;
+		}
+	default:{
+			DASD_MESSAGE (KERN_INFO, device,
+				    "ioctl 0x%08x=%s'0x%x'%d(%d) data %8lx\n",
+				      no,
+				      _IOC_DIR (no) == _IOC_NONE ? "0" :
+				      _IOC_DIR (no) == _IOC_READ ? "r" :
+				      _IOC_DIR (no) == _IOC_WRITE ? "w" :
+				   _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ?
+				      "rw" : "u",
+				 _IOC_TYPE (no), _IOC_NR (no), _IOC_SIZE (no),
+				      data);
+			rc = -EINVAL;
+			break;
+		}
+	}
+	return rc;
+}
+
+/* SECTION: The members of the struct file_operations */
+
+static int
+dasd_ioctl (struct inode *inp, struct file *filp,
+	    unsigned int no, unsigned long data)
+{
+	int rc = 0;
+	if ((!inp) || !(inp->i_rdev)) {
+		return -EINVAL;
+	}
+	rc = do_dasd_ioctl (inp, no, data);
+	return rc;
+}
+
+static int
+dasd_open (struct inode *inp, struct file *filp)
+{
+	int rc = 0;
+	dasd_device_t *device;
+
+	if ((!inp) || !(inp->i_rdev)) {
+		return -EINVAL;
+	}
+	if (dasd_probeonly) {
+		printk ("\n" KERN_INFO PRINTK_HEADER "No access to device (%d:%d) due to probeonly mode\n", MAJOR (inp->i_rdev), MINOR (inp->i_rdev));
+		return -EPERM;
+	}
+	device = dasd_device_from_kdev (inp->i_rdev);
+	if (device == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No device registered as (%d:%d)\n", MAJOR (inp->i_rdev), MINOR (inp->i_rdev));
+		return -ENODEV;
+	}
+	if (device->level < DASD_DEVICE_LEVEL_RECOGNIZED ||
+	    device->discipline == NULL) {
+		DASD_MESSAGE (KERN_WARNING, device,
+			      " %s", " Cannot open unrecognized device\n");
+		return -EINVAL;
+	}
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif				/* MODULE */
+	device->open_count++;
+	return rc;
+}
+
+static int
+dasd_release (struct inode *inp, struct file *filp)
+{
+	int rc = 0;
+	dasd_device_t *device;
+
+	if ((!inp) || !(inp->i_rdev)) {
+		return -EINVAL;
+	}
+	device = dasd_device_from_kdev (inp->i_rdev);
+	if (device == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No device registered as %d:%d\n",
+			MAJOR (inp->i_rdev), MINOR (inp->i_rdev));
+		return -EINVAL;
+	}
+	if (device->open_count--) {
+#ifdef MODULE
+		MOD_DEC_USE_COUNT;
+#endif				/* MODULE */
+	} 
+	fsync_dev(inp->i_rdev); /* sync the device */
+	if (device->open_count == 0) /* finally invalidate buffers */
+		invalidate_buffers(inp->i_rdev);
+	return rc;
+}
+
+static struct
+block_device_operations dasd_device_operations =
+{
+	open:dasd_open,
+	release:dasd_release,
+	ioctl:dasd_ioctl,
+#if ! (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	read:block_read,
+	write:block_write,
+	fsync:block_fsync,
+#endif				/* LINUX_IS_24 */
+};
+
+/* SECTION: Management of device list */
+
+/* This one is needed for naming 18000+ possible dasd devices */
+int
+dasd_device_name (char *str, int index, int partition, struct gendisk *hd)
+{
+	int len = 0;
+	char first, second, third;
+
+	if (hd) {
+		major_info_t *major_info;
+		for (major_info = dasd_major_info; major_info; major_info = major_info->next) {
+			if (&major_info->gendisk == hd) {
+				break;
+			}
+			index += DASD_PER_MAJOR;
+		}
+		if (major_info == NULL) {
+			return -EINVAL;
+		}
+	}
+	third = index % 26;
+	second = (index / 26) % 27;
+	first = ((index / 26) / 27) % 27;
+
+	len = sprintf (str, "dasd");
+	if (first) {
+		len += sprintf (str + len, "%c", first + 'a' - 1);
+	}
+	if (second) {
+		len += sprintf (str + len, "%c", second + 'a' - 1);
+	}
+	len += sprintf (str + len, "%c", third + 'a');
+	if (partition) {
+		if (partition > 9) {
+			return -EINVAL;
+		} else {
+			len += sprintf (str + len, "%d", partition);
+		}
+	}
+	str[len] = '\0';
+	return 0;
+}
+
+#ifdef CONFIG_DASD_DYNAMIC
+static void
+dasd_not_oper_handler (int irq, int status)
+{
+	dasd_device_t *device = NULL;
+	major_info_t *major_info;
+	int i, devno = -ENODEV;
+
+	for (major_info = dasd_major_info; major_info != NULL; major_info = major_info->next) {
+		for (i = 0; i < DASD_PER_MAJOR; i++) {
+			device = major_info->dasd_device[i];
+			if (device &&
+			    device->devinfo.irq == irq) {
+				devno = device->devinfo.devno;
+				break;
+			}
+		}
+		if (devno != -ENODEV)
+			break;
+	}
+	if (devno < 0) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"not_oper_handler called on irq %d no devno!\n", irq);
+		return;
+	}
+	printk (KERN_INFO PRINTK_HEADER
+		"not_oper_handler called on irq %d devno %04X\n", irq, devno);
+	if (device->open_count != 0) {
+		printk (KERN_ALERT PRINTK_HEADER
+			"Device %04X detached has still been open. expect errors\n", devno);
+	}
+	dasd_set_device_level (irq, DASD_DEVICE_LEVEL_UNKNOWN, NULL, 0);
+}
+
+static int
+dasd_enable_single_volume (int irq)
+{
+	int rc = 0;
+	dasd_set_device_level (irq, DASD_DEVICE_LEVEL_ANALYSIS_PREPARED,
+			       NULL, 0);
+	printk (KERN_INFO PRINTK_HEADER "waiting for response...\n");
+	{
+		static wait_queue_head_t wait_queue;
+		init_waitqueue_head (&wait_queue);
+		interruptible_sleep_on_timeout (&wait_queue, (5 * HZ) >> 1);
+	}
+	dasd_set_device_level (irq, DASD_DEVICE_LEVEL_ANALYSED,
+			       NULL, 0);
+	return rc;
 }
 
-static int
-dasd_format (int dev, format_data_t * fdata)
+int
+dasd_oper_handler (int irq, devreg_t * devreg)
 {
+	int devno;
 	int rc;
-	int devindex = DEVICE_NR (dev);
-	dasd_chanq_t *q;
-	cqr_t *cqr;
-	int irq;
-	long flags;
-	PRINT_INFO ("Format called with devno %x\n", dev);
-	if (MINOR (dev) & (0xff >> (8 - PARTN_BITS))) {
-		PRINT_WARN ("Can't format partition! minor %x %x\n",
-			    MINOR (dev), 0xff >> (8 - PARTN_BITS));
-		return -EINVAL;
-	}
-	down (&dasd_info[devindex]->sem);
-	if (dasd_info[devindex]->open_count == 1) {
-		rc = dasd_disciplines[dasd_info[devindex]->type]->
-		    dasd_format (devindex, fdata);
-		if (rc) {
-			PRINT_WARN ("Formatting failed rc=%d\n", rc);
-		}
+	devno = get_devno_by_irq (irq);
+	if (devno == -ENODEV)
+		return -ENODEV;
+	if (dasd_autodetect) {
+		dasd_add_range (devno, 0);
 	} else {
-		PRINT_WARN ("device is open! %d\n", dasd_info[devindex]->open_count);
-		rc = -EINVAL;
-	}
-	if (!rc) {
-#if DASD_PARANOIA > 1
-		if (!dasd_disciplines[dasd_info[devindex]->type]->fill_sizes_first) {
-			INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dasd_info[devindex]->type);
-	} else
-#endif				/* DASD_PARANOIA */
-	{
-		dasd_info[devindex]->flags &= ~DASD_INFO_FLAGS_INITIALIZED;
-	        irq = dasd_info[devindex]->info.irq;
-		PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n",
-		get_devno_by_irq(irq), irq, devindex);
-        	s390irq_spin_lock_irqsave (irq, flags);
-	        q = &dasd_info[devindex]->queue;
-		cqr = dasd_disciplines[dasd_info[devindex]->type]->
-			fill_sizes_first (devindex);
-	        dasd_chanq_enq (q, cqr);
-		schedule_bh(dasd_do_chanq);
-        	s390irq_spin_unlock_irqrestore (irq, flags);
-	}
+		return -ENODEV;
 	}
-	up (&dasd_info[devindex]->sem);
+	rc = dasd_enable_single_volume (irq);
 	return rc;
 }
+#endif	/* CONFIG_DASD_DYNAMIC */
 
-
+/* 
+ * function dasd_set_device_level 
+ */
 static int
-register_dasd (int irq, dasd_type_t dt, dev_info_t * info)
+dasd_set_device_level (unsigned int irq, int desired_level,
+		       dasd_discipline_t * discipline, int flags)
 {
 	int rc = 0;
-	int di;
-	unsigned long flags;
-	dasd_chanq_t *q;
-	cqr_t * cqr;
-	static spinlock_t register_lock = SPIN_LOCK_UNLOCKED;
-	spin_lock (&register_lock);
-	FUNCTION_ENTRY ("register_dasd");
-	di = devindex_from_devno (info->devno);
-	if (di < 0) {
-		INTERNAL_CHECK ("Can't get index for devno %d\n", info->devno);
+	int devno;
+	dasd_device_t **device_addr, *device;
+	int current_level;
+	major_info_t *major_info = NULL;
+	int i, minor, major;
+	ccw_req_t *cqr = NULL;
+	struct gendisk *dd;
+
+	devno = get_devno_by_irq (irq);
+	if (devno < 0) {
+		printk (KERN_WARNING PRINTK_HEADER " no device appears to be connected to SCH %d\n", irq);
 		return -ENODEV;
 	}
-	if (dasd_info[di]) {	/* devindex is not free */
-		INTERNAL_CHECK ("reusing allocated deviceindex %d\n", di);
+	if (dasd_devindex_from_devno (devno) < 0) {
 		return -ENODEV;
 	}
-	dasd_info[di] = (dasd_information_t *)
-	    kmalloc (sizeof (dasd_information_t), GFP_ATOMIC);
-	if (dasd_info[di] == NULL) {
-		PRINT_WARN ("No memory for dasd_info_t on irq %d\n", irq);
-		return -ENOMEM;
+	while ((device_addr = dasd_device_from_devno (devno)) == NULL) {
+		if ((rc = dasd_register_major (NULL)) > 0) {
+			printk (KERN_INFO PRINTK_HEADER
+				"Registered to major number: %u\n", rc);
+		} else {
+			printk (KERN_WARNING PRINTK_HEADER
+				"Couldn't register to another major no\n");
+			return -ERANGE;
+		}
+	}
+	device = *device_addr;
+	if (!device) {		/* allocate device descriptor */
+		device = kmalloc (sizeof (dasd_device_t), GFP_ATOMIC);
+		if (!device) {
+			printk (KERN_WARNING PRINTK_HEADER " No memory for device descriptor\n");
+			goto nomem;
+		}
+		memset (device, 0, sizeof (dasd_device_t));
+		*device_addr = device;
+	}
+	for (major_info = dasd_major_info; major_info; major_info = major_info->next) {
+		int i;
+		for (i = 0; i < DASD_PER_MAJOR; i++) {
+			if (major_info->dasd_device[i] == device) {
+				device->kdev = MKDEV (major_info->gendisk.major, i << DASD_PARTN_BITS);
+				break;
+			}
+		}
+		if (i < DASD_PER_MAJOR)
+			break;
 	}
-	memset (dasd_info[di], 0, sizeof (dasd_information_t));
-	memcpy (&(dasd_info[di]->info), info, sizeof (dev_info_t));
-	spin_lock_init (&dasd_info[di]->queue.f_lock);
-	spin_lock_init (&dasd_info[di]->queue.q_lock);
-	dasd_info[di]->type = dt;
-	dasd_info[di]->irq = irq;
-        init_MUTEX (&dasd_info[di]->sem);
-	rc = dasd_read_characteristics (dasd_info[di]);
-	if (rc) {
-		PRINT_WARN ("RDC returned error %d\n", rc);
-		rc = -ENODEV;
-		goto unalloc;
-	}
-#if DASD_PARANOIA > 1
-	if (dasd_disciplines[dt]->ck_characteristics)
-#endif				/* DASD_PARANOIA */
-		rc = dasd_disciplines[dt]->
-		    ck_characteristics (dasd_info[di]->rdc_data);
-
-	if (rc) {
-		INTERNAL_CHECK ("Discipline returned non-zero when"
-				"checking device characteristics%s\n", "");
-		rc = -ENODEV;
-		goto unalloc;
+	if (major_info == NULL) {
+		return -ENODEV;
 	}
-	rc = request_irq (irq, dasd_handler, 0, "dasd",
-			  &(dasd_info[di]->dev_status));
-	if (rc) {
-#if DASD_PARANOIA > 0
-		printk (KERN_WARNING PRINTK_HEADER
-			"Cannot register irq %d, rc=%d\n",
-			irq, rc);
-#endif				/* DASD_PARANOIA */
-		rc = -ENODEV;
-		goto unalloc;
-	}
-#if DASD_PARANOIA > 1
-	if (!dasd_disciplines[dt]->fill_sizes_first) {
-		INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dt);
-		goto unregister;
-	}
-#endif				/* DASD_PARANOIA */
-        irq = dasd_info[di]->info.irq;
-	PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n",
-	get_devno_by_irq(irq), irq, di);
-        s390irq_spin_lock_irqsave (irq, flags);
-        q = &dasd_info[di]->queue;
-	cqr = dasd_disciplines[dt]->fill_sizes_first (di);
-        dasd_chanq_enq (q, cqr);
-        cql_enq_head(q);
-	if (dasd_start_IO(cqr) != 0) {
-          atomic_inc(&chanq_tasks);
-        }
-        s390irq_spin_unlock_irqrestore (irq, flags);
+	device->major_info = major_info;
+	dasd_device_name (device->name,
+			  ((long) device_addr -
+			   (long) device->major_info->dasd_device) /
+			  sizeof (dasd_device_t *),
+			  0, &major_info->gendisk);
+	minor = MINOR (device->kdev);
+	major = MAJOR (device->kdev);
+	current_level = device->level;
+	if (desired_level > current_level) {
+		switch (current_level) {
+		case DASD_DEVICE_LEVEL_UNKNOWN:	/* Find a discipline */
+			rc = get_dev_info_by_irq (irq, &device->devinfo);
+			if (rc < 0) {
+				break;
+			}
+			discipline = dasd_find_discipline (device);
+			if (discipline && !rc) {
+                                DASD_MESSAGE (KERN_INFO, device,
+                                              "%s", " ");
+			} else {
+                                break;
+			}
+			device->discipline = discipline;
+			if (device->discipline->int_handler) {
+#ifdef CONFIG_DASD_DYNAMIC
+				s390_request_irq_special (irq,
+                                                          device->discipline->int_handler,
+                                                          dasd_not_oper_handler,
+							  0,
+							  DASD_NAME,
+							  &device->dev_status);
+#else				/* !defined(CONFIG_DASD_DYNAMIC) */
+				request_irq (irq,
+					     device->discipline->int_handler,
+					     0,
+					     DASD_NAME,
+					     &device->dev_status);
+#endif				/* CONFIG_DASD_DYNAMIC */
+			}
+			device->proc_dir = (struct proc_dir_entry *)
+			    kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL);
+			if (device->proc_dir) {
+				memset (device->proc_dir, 0, sizeof (struct proc_dir_entry));
+				device->proc_info = (struct proc_dir_entry *)
+				    kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL);
+				if (device->proc_info) {
+					memset (device->proc_info, 0,
+					      sizeof (struct proc_dir_entry));
+				}
+				device->proc_stats = (struct proc_dir_entry *)
+				    kmalloc (sizeof (struct proc_dir_entry), GFP_KERNEL);
+				if (device->proc_stats) {
+					memset (device->proc_stats, 0,
+					      sizeof (struct proc_dir_entry));
+				}
+			}
+			init_waitqueue_head (&device->wait_q);
+			blk_init_queue (&device->request_queue, do_dasd_request);
+			blk_queue_headactive (&device->request_queue, 0);
+			check_then_set (&device->level,
+				       DASD_DEVICE_LEVEL_UNKNOWN,
+				       DASD_DEVICE_LEVEL_RECOGNIZED);
+			if (desired_level == DASD_DEVICE_LEVEL_RECOGNIZED)
+				break;
+		case DASD_DEVICE_LEVEL_RECOGNIZED:	/* Fallthrough ?? */
+			if (device->discipline->init_analysis) {
+				cqr = device->discipline->init_analysis (device);
+				if (cqr != NULL) {
+					dasd_chanq_enq (&device->queue, cqr);
+					if (device->discipline->start_IO) {
+						long flags;
+						s390irq_spin_lock_irqsave (irq, flags);
+						device->discipline->start_IO (cqr);
+						check_then_set (&device->level,
+                                                                DASD_DEVICE_LEVEL_RECOGNIZED,
+                                                                DASD_DEVICE_LEVEL_ANALYSIS_PENDING);
+						s390irq_spin_unlock_irqrestore (irq, flags);
+					}
+				}
+			} else {
+				check_then_set (&device->level, DASD_DEVICE_LEVEL_RECOGNIZED,
+                                                DASD_DEVICE_LEVEL_ANALYSIS_PREPARED);
+			}
+			if (desired_level >= DASD_DEVICE_LEVEL_ANALYSIS_PENDING)
+				break;
+		case DASD_DEVICE_LEVEL_ANALYSIS_PENDING:	/* Fallthrough ?? */
+			return -EAGAIN;
+		case DASD_DEVICE_LEVEL_ANALYSIS_PREPARED:	/* Re-entering here ! */
+			if (device->discipline->do_analysis)
+                                if (device->discipline->do_analysis (device))
+                                        return -ENODEV;
+			switch (device->sizes.bp_block) {
+			case 512:
+			case 1024:
+			case 2048:
+			case 4096:
+				break;
+			default:
+				{
+					printk (KERN_INFO PRINTK_HEADER
+						"/dev/%s (devno 0x%04X): Detected invalid blocksize of %d bytes"
+						" Did you format the drive?\n",
+						device->name, devno, device->sizes.bp_block);
+					return -EMEDIUMTYPE;
+				}
+			}
+			for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
+				if (i == 0)
+					blk_size[major][minor] = (device->sizes.blocks << device->sizes.s2b_shift) >> 1;
+				else
+					blk_size[major][minor + i] = 0;
+				hardsect_size[major][minor + i] = device->sizes.bp_block;
+				blksize_size[major][minor + i] = device->sizes.bp_block;
+				if (blksize_size[major][minor + i] < 1024)
+					blksize_size[major][minor + i] = 1024;
 
-	goto exit;
+				max_sectors[major][minor + i] =
+                                        255 << device->sizes.s2b_shift;
+			}
+			check_then_set (&device->level,
+				       DASD_DEVICE_LEVEL_ANALYSIS_PREPARED,
+				       DASD_DEVICE_LEVEL_ANALYSED);
+			dd = &major_info->gendisk;
+			dd->sizes[minor] = (device->sizes.blocks <<
+					    device->sizes.s2b_shift) >> 1;
+#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#ifndef MODULE
+			if (flags & 0x80)
+#endif
+#endif				/* KERNEL_VERSION */
+				dasd_partn_detect (device);
+			if (desired_level == DASD_DEVICE_LEVEL_ANALYSED)
+				break;
+		case DASD_DEVICE_LEVEL_ANALYSED:	/* Fallthrough ?? */
 
-      unregister:
-	free_irq (irq, &(dasd_info[di]->dev_status));
-      unalloc:
-	kfree (dasd_info[di]);
+			break;
+		default:
+			printk (KERN_WARNING PRINTK_HEADER
+				"Internal error in " __FILE__ " on line %d."
+				" validate_dasd called from %p with "
+				" desired_level = %d, current_level =%d"
+				" Pls send this message and your System.map to"
+				" linux390@de.ibm.com\n",
+				__LINE__, __builtin_return_address (0),
+				desired_level, current_level);
+			break;
+		}
+	} else if (desired_level < current_level) {	/* donwgrade device status */
+		switch (current_level) {
+		case DASD_DEVICE_LEVEL_ANALYSED:	/* Fallthrough ?? */
+			check_then_set (&device->level,
+				       DASD_DEVICE_LEVEL_ANALYSED,
+				       DASD_DEVICE_LEVEL_ANALYSIS_PREPARED);
+			if (desired_level == DASD_DEVICE_LEVEL_ANALYSIS_PREPARED)
+				break;
+		case DASD_DEVICE_LEVEL_ANALYSIS_PREPARED:
+			for (i = 0; i < (1 << DASD_PARTN_BITS); i++) {
+				blk_size[major][minor] = 0;
+				hardsect_size[major][minor + i] = 0;
+				blksize_size[major][minor + i] = 0;
+				max_sectors[major][minor + i] = 0;
+			}
+			memset (&device->sizes, 0, sizeof (dasd_sizes_t));
+			check_then_set (&device->level,
+				       DASD_DEVICE_LEVEL_ANALYSIS_PREPARED,
+				       DASD_DEVICE_LEVEL_ANALYSIS_PENDING);
+			if (desired_level == DASD_DEVICE_LEVEL_ANALYSIS_PENDING)
+				break;
+		case DASD_DEVICE_LEVEL_ANALYSIS_PENDING:	/* Fallthrough ?? */
+			check_then_set (&device->level,
+				       DASD_DEVICE_LEVEL_ANALYSIS_PENDING,
+				       DASD_DEVICE_LEVEL_RECOGNIZED);
+			if (desired_level == DASD_DEVICE_LEVEL_RECOGNIZED)
+				break;
+		case DASD_DEVICE_LEVEL_RECOGNIZED:	/* Fallthrough ?? */
+			if (device->discipline->int_handler) {
+				free_irq (irq, &device->dev_status);
+			}
+			device->discipline = NULL;
+			blk_cleanup_queue (&device->request_queue);
+			check_then_set (&device->level,
+				       DASD_DEVICE_LEVEL_RECOGNIZED,
+				       DASD_DEVICE_LEVEL_UNKNOWN);
+			if (desired_level == DASD_DEVICE_LEVEL_UNKNOWN)
+				break;
+		case DASD_DEVICE_LEVEL_UNKNOWN:
+			break;
+		default:
+			printk (KERN_WARNING PRINTK_HEADER
+				"Internal error in " __FILE__ " on line %d."
+				" validate_dasd called from %p with "
+				" desired_level = %d, current_level =%d"
+				" Pls send this message and your System.map to"
+				" linux390@de.ibm.com\n",
+				__LINE__, __builtin_return_address (0),
+				desired_level, current_level);
+			break;
+		}
+	}
+	if (rc) {
+		goto exit;
+	}
+      nomem:
+	rc = -ENOMEM;
       exit:
-	spin_unlock (&register_lock);
-	FUNCTION_EXIT ("register_dasd");
-	return rc;
+	return 0;
 }
 
+/* SECTION: Procfs stuff */
+typedef struct {
+	char *data;
+	int len;
+} tempinfo_t;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+static struct proc_dir_entry *dasd_proc_root_entry = NULL;
+#else
+static struct proc_dir_entry dasd_proc_root_entry =
+{
+	low_ino:0,
+	namelen:4,
+	name:"dasd",
+	mode:S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP,
+	nlink:1,
+	uid:0,
+	gid:0,
+	size:0
+};
+#endif				/* KERNEL_VERSION */
+static struct proc_dir_entry *dasd_devices_entry;
+static struct proc_dir_entry *dasd_statistics_entry;
+
 static int
-probe_for_dasd (int irq)
+dasd_devices_open (struct inode *inode, struct file *file)
 {
-	int rc;
-	dev_info_t info;
-	dasd_type_t dt;
-
-	FUNCTION_ENTRY ("probe_for_dasd");
+	int rc = 0;
+	int size = 1;
+	int len = 0;
+	major_info_t *temp = dasd_major_info;
+	tempinfo_t *info;
 
-	rc = get_dev_info_by_irq (irq, &info);
-	if (rc == -ENODEV) {	/* end of device list */
-		return rc;
+	info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t));
+	if (info == NULL) {
+		printk (KERN_WARNING "No memory available for data\n");
+		return -ENOMEM;
+	} else {
+		file->private_data = (void *) info;
 	}
-#if DASD_PARANOIA > 2
-	if (rc) {
-		INTERNAL_CHECK ("unknown rc %d of get_dev_info", rc);
-		return rc;
+	while (temp) {
+		int i;
+		for (i = 0; i < 1 << (MINORBITS - DASD_PARTN_BITS); i++) {
+			dasd_device_t *device = temp->dasd_device[i];
+			if (device) {
+				size += 128;
+			}
+		}
+		temp = temp->next;
 	}
-#endif				/* DASD_PARANOIA */
-	if ((info.status & DEVSTAT_NOT_OPER)) {
-		return -ENODEV;
+	temp = dasd_major_info;
+	info->data = (char *) vmalloc (size);	/* FIXME! determine space needed in a better way */
+	if (size && info->data == NULL) {
+		printk (KERN_WARNING "No memory available for data\n");
+		vfree (info);
+		return -ENOMEM;
 	}
-	dt = check_type (&info);
-	switch (dt) {
-#ifdef CONFIG_DASD_ECKD
-	case dasd_eckd:
-#endif				/* CONFIG_DASD_ECKD */
-		FUNCTION_CONTROL ("Probing devno %d...\n", info.devno);
-		if (!dasd_is_accessible (info.devno)) {
-			FUNCTION_CONTROL ("out of range...skip%s\n", "");
-			return -ENODEV;
-		}
-		if (dasd_disciplines[dt]->ck_devinfo) {
-			rc = dasd_disciplines[dt]->ck_devinfo (&info);
-		}
-#if DASD_PARANOIA > 1
-		else {
-			INTERNAL_ERROR ("no ck_devinfo function%s\n", "");
-			return -ENODEV;
-		}
-#endif				/* DASD_PARANOIA */
-		if (rc == -ENODEV) {
-			return rc;
-		}
-#if DASD_PARANOIA > 2
-		if (rc) {
-			INTERNAL_CHECK ("unknown error rc=%d\n", rc);
-			return -ENODEV;
-		}
-#endif				/* DASD_PARANOIA */
-		rc = register_dasd (irq, dt, &info);
-		if (rc) {
-			PRINT_INFO ("devno %x not enabled as minor %d  due to errors\n",
-				    info.devno,
-				    devindex_from_devno (info.devno) <<
-				    PARTN_BITS);
-		} else {
-			PRINT_INFO ("devno %x added as minor %d (%s)\n",
-				    info.devno,
-			       devindex_from_devno (info.devno) << PARTN_BITS,
-				    dasd_name[dt]);
+	while (temp) {
+		int i;
+		for (i = 0; i < 1 << (MINORBITS - DASD_PARTN_BITS); i++) {
+			dasd_device_t *device = temp->dasd_device[i];
+			if (device) {
+				len += sprintf (info->data + len,
+						"%04X(%s) at (%d:%d) is %7s:",
+						device->devinfo.devno,
+						device->discipline ? device->discipline->name : "none",
+				    temp->gendisk.major, i << DASD_PARTN_BITS,
+						device->name);
+				switch (device->level) {
+				case DASD_DEVICE_LEVEL_UNKNOWN:
+					len += sprintf (info->data + len, "unknown\n");
+					break;
+				case DASD_DEVICE_LEVEL_RECOGNIZED:
+					len += sprintf (info->data + len, "passive");
+					len += sprintf (info->data + len, " at blocksize: %d, %ld blocks, %ld MB\n",
+							device->sizes.bp_block,
+							device->sizes.blocks,
+							((device->sizes.bp_block >> 9) * device->sizes.blocks) >> 11);
+					break;
+				case DASD_DEVICE_LEVEL_ANALYSIS_PENDING:
+					len += sprintf (info->data + len, "busy   \n");
+					break;
+				case DASD_DEVICE_LEVEL_ANALYSIS_PREPARED:
+					len += sprintf (info->data + len, "n/f    \n");
+					break;
+				case DASD_DEVICE_LEVEL_ANALYSED:
+					len += sprintf (info->data + len, "active ");
+					len += sprintf (info->data + len, " at blocksize: %d, %ld blocks, %ld MB\n",
+							device->sizes.bp_block,
+							device->sizes.blocks,
+							((device->sizes.bp_block >> 9) * device->sizes.blocks) >> 11);
+					break;
+				default:
+					len += sprintf (info->data + len, "no stat\n");
+					break;
+				}
+			}
 		}
-	case dasd_none:
-		break;
-	default:
-		PRINT_DEBUG ("unknown device type\n");
-		break;
+		temp = temp->next;
 	}
-	FUNCTION_EXIT ("probe_for_dasd");
+	info->len = len;
 	return rc;
 }
 
-static int
-register_major (int major)
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+static ssize_t
+dasd_devices_read (struct file *file, char *user_buf, size_t user_len, loff_t * offset)
 {
-        request_queue_t *q;
-	int rc = 0;
+	loff_t len;
+	tempinfo_t *p_info = (tempinfo_t *) file->private_data;
 
-	FUNCTION_ENTRY ("register_major");
-	rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations);
-#if DASD_PARANOIA > 1
-	if (rc) {
-		PRINT_WARN ("registering major -> rc=%d aborting... \n", rc);
-		return rc;
+	if (*offset >= p_info->len) {
+		return 0;	/* EOF */
+	} else {
+		len = MIN (user_len, (p_info->len - *offset));
+		if (copy_to_user (user_buf, &(p_info->data[*offset]), len))
+			return -EFAULT;
+		(*offset) += len;
+		return len;	/* number of bytes "read" */
 	}
-#endif				/* DASD_PARANOIA */
-        q = BLK_DEFAULT_QUEUE(major);
-        blk_init_queue(q, do_dasd_request);
-        blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
-	FUNCTION_CONTROL ("successfully registered major: %d\n", major);
-	FUNCTION_EXIT ("register_major");
-	return rc;
 }
 
-/* 
-   Below you find functions which are called from outside. Some of them may be
-   static, because they are called by their function pointers only. Thus static
-   modifier is to make sure, that they are only called via the kernel's methods
- */
+static ssize_t
+dasd_devices_write (struct file *file, const char *user_buf, size_t user_len, loff_t * offset)
+{
+	char *buffer = vmalloc (user_len);
+
+	if (buffer == NULL)
+		return -ENOMEM;
+	if (copy_from_user (buffer, user_buf, user_len)) {
+		vfree(buffer);
+		return -EFAULT;
+	}
+	buffer[user_len] = 0;
+	printk (KERN_INFO PRINTK_HEADER "Now executing %s\n", buffer);
+	if (!strncmp (buffer, "add range", strlen ("add_range"))) {
+
+	} else if (!strncmp (buffer, "enable device", strlen ("enable device"))) {
+
+	} else if (!strncmp (buffer, "disable device", strlen ("disable device"))) {
+
+	} else {
+		printk (KERN_WARNING PRINTK_HEADER "unknown command %s",
+			buffer);
+	}
+	vfree (buffer);
+	return user_len;
+}
 
 static int
-dasd_ioctl (struct inode *inp, struct file *filp,
-	    unsigned int no, unsigned long data)
+dasd_devices_close (struct inode *inode, struct file *file)
 {
 	int rc = 0;
-	FUNCTION_ENTRY ("dasd_ioctl");
-	if ((!inp) || !(inp->i_rdev)) {
-		return -EINVAL;
+	tempinfo_t *p_info = (tempinfo_t *) file->private_data;
+	if (p_info) {
+		if (p_info->data)
+			vfree (p_info->data);
+		vfree (p_info);
 	}
-	rc = do_dasd_ioctl (inp, no, data);
-	FUNCTION_EXIT ("dasd_ioctl");
 	return rc;
 }
 
+static struct file_operations dasd_devices_file_ops =
+{
+	read:dasd_devices_read,	/* read */
+	write:dasd_devices_write,	/* write */
+	open:dasd_devices_open,	/* open */
+	release:dasd_devices_close,	/* close */
+};
+
+static struct inode_operations dasd_devices_inode_ops =
+{
+#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	default_file_ops:&dasd_devices_file_ops		/* file ops */
+#endif				/* LINUX_IS_24 */
+};
+
 static int
-dasd_open (struct inode *inp, struct file *filp)
+dasd_statistics_open (struct inode *inode, struct file *file)
 {
 	int rc = 0;
-	dasd_information_t *dev;
-	FUNCTION_ENTRY ("dasd_open");
-	if ((!inp) || !(inp->i_rdev)) {
-		return -EINVAL;
+	int len = 0;
+	tempinfo_t *info;
+	int shift, i, help = 0;
+
+	info = (tempinfo_t *) vmalloc (sizeof (tempinfo_t));
+	if (info == NULL) {
+		printk (KERN_WARNING "No memory available for data\n");
+		return -ENOMEM;
+	} else {
+		file->private_data = (void *) info;
 	}
-	dev = dasd_info[DEVICE_NR (inp->i_rdev)];
-	if (!dev) {
-		PRINT_DEBUG ("No device registered as %d (%d)\n",
-			    inp->i_rdev, DEVICE_NR (inp->i_rdev));
-		return -EINVAL;
+	info->data = (char *) vmalloc (PAGE_SIZE);	/* FIXME! determine space needed in a better way */
+	if (info->data == NULL) {
+		printk (KERN_WARNING "No memory available for data\n");
+		vfree (info);
+		file->private_data = NULL;
+		return -ENOMEM;
 	}
-	down (&dev->sem);
-	up (&dev->sem);
-#ifdef MODULE
-	MOD_INC_USE_COUNT;
-#endif				/* MODULE */
-#if DASD_PARANOIA > 2
-	if (dev->open_count < 0) {
-		INTERNAL_ERROR ("open count cannot be less than 0: %d",
-				dev->open_count);
-		return -EINVAL;
+	for (shift = 0, help = dasd_global_profile.dasd_io_reqs;
+	     help > 8192;
+	     help = help >> 1, shift++) ;
+	len = sprintf (info->data, "%ld dasd I/O requests\n", dasd_global_profile.dasd_io_reqs);
+	len += sprintf (info->data + len, "__<4 ___8 __16 __32 __64 _128 _256 _512 __1k __2k __4k __8k _16k _32k _64k 128k\n");
+	len += sprintf (info->data + len, "_256 _512 __1M __2M __4M __8M _16M _32M _64M 128M 256M 512M __1G __2G __4G _>4G\n");
+	len += sprintf (info->data + len, "Histogram of sizes (512B secs)\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_secs[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	len += sprintf (info->data + len, "Histogram of I/O times\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_times[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	for (; i < 32; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_times[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	len += sprintf (info->data + len, "Histogram of I/O times per sector\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_timps[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	for (; i < 32; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_timps[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	len += sprintf (info->data + len, "Histogram of I/O time till ssch\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time1[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	for (; i < 32; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time1[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	len += sprintf (info->data + len, "Histogram of I/O time between ssch and irq\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time2[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	for (; i < 32; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time2[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	len += sprintf (info->data + len, "Histogram of I/O time between ssch and irq per sector\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time2ps[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	for (; i < 32; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time2ps[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	len += sprintf (info->data + len, "Histogram of I/O time between irq and end\n");
+	for (i = 0; i < 16; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time3[i] >> shift);
+	}
+	len += sprintf (info->data + len, "\n");
+	for (; i < 32; i++) {
+		len += sprintf (info->data + len, "%4ld ", dasd_global_profile.dasd_io_time3[i] >> shift);
 	}
-#endif				/* DASD_PARANOIA */
-	dev->open_count++;
-	FUNCTION_EXIT ("dasd_open");
+	len += sprintf (info->data + len, "\n");
+	info->len = len;
 	return rc;
 }
 
-static int
-dasd_release (struct inode *inp, struct file *filp)
+static struct file_operations dasd_statistics_file_ops =
+{
+	read:dasd_devices_read,	/* read */
+	open:dasd_statistics_open,	/* open */
+	release:dasd_devices_close,	/* close */
+};
+
+static struct inode_operations dasd_statistics_inode_ops =
+{
+#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	default_file_ops:&dasd_statistics_file_ops	/* file ops */
+#endif				/* LINUX_IS_24 */
+};
+
+int
+dasd_proc_init (void)
 {
 	int rc = 0;
-	dasd_information_t *dev;
-	FUNCTION_ENTRY ("dasd_release");
-	if ((!inp) || !(inp->i_rdev)) {
-		return -EINVAL;
-	}
-	dev = dasd_info[DEVICE_NR (inp->i_rdev)];
-	if (!dev) {
-		PRINT_WARN ("No device registered as %d\n", inp->i_rdev);
-		return -EINVAL;
-	}
-#ifdef MODULE
-	MOD_DEC_USE_COUNT;
-#endif				/* MODULE */
-#if DASD_PARANOIA > 2
-	if (!dev->open_count) {
-		PRINT_WARN ("device %d has not been opened before:\n",
-			    inp->i_rdev);
-	}
-#endif				/* DASD_PARANOIA */
-	dev->open_count--;
-#if DASD_PARANOIA > 2
-	if (dev->open_count < 0) {
-		INTERNAL_ERROR ("open count cannot be less than 0: %d",
-				dev->open_count);
-		return -EINVAL;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	dasd_proc_root_entry = proc_mkdir ("dasd", &proc_root);
+	dasd_devices_entry = create_proc_entry ("devices",
+						S_IFREG | S_IRUGO | S_IWUSR,
+						dasd_proc_root_entry);
+	dasd_devices_entry->proc_fops = &dasd_devices_file_ops;
+	dasd_devices_entry->proc_iops = &dasd_devices_inode_ops;
+	dasd_statistics_entry = create_proc_entry ("statistics",
+						   S_IFREG | S_IRUGO | S_IWUSR,
+						   dasd_proc_root_entry);
+	dasd_statistics_entry->proc_fops = &dasd_statistics_file_ops;
+	dasd_statistics_entry->proc_iops = &dasd_statistics_inode_ops;
+#else
+	proc_register (&proc_root, &dasd_proc_root_entry);
+	dasd_devices_entry = (struct proc_dir_entry *) kmalloc (sizeof (struct proc_dir_entry), GFP_ATOMIC);
+	if (dasd_devices_entry) {
+		memset (dasd_devices_entry, 0, sizeof (struct proc_dir_entry));
+		dasd_devices_entry->name = "devices";
+		dasd_devices_entry->namelen = strlen ("devices");
+		dasd_devices_entry->low_ino = 0;
+		dasd_devices_entry->mode = (S_IFREG | S_IRUGO | S_IWUSR);
+		dasd_devices_entry->nlink = 1;
+		dasd_devices_entry->uid = 0;
+		dasd_devices_entry->gid = 0;
+		dasd_devices_entry->size = 0;
+		dasd_devices_entry->get_info = NULL;
+		dasd_devices_entry->ops = &dasd_devices_inode_ops;
+		proc_register (&dasd_proc_root_entry, dasd_devices_entry);
+	}
+	dasd_statistics_entry = (struct proc_dir_entry *) kmalloc (sizeof (struct proc_dir_entry), GFP_ATOMIC);
+	if (dasd_statistics_entry) {
+		memset (dasd_statistics_entry, 0, sizeof (struct proc_dir_entry));
+		dasd_statistics_entry->name = "statistics";
+		dasd_statistics_entry->namelen = strlen ("statistics");
+		dasd_statistics_entry->low_ino = 0;
+		dasd_statistics_entry->mode = (S_IFREG | S_IRUGO | S_IWUSR);
+		dasd_statistics_entry->nlink = 1;
+		dasd_statistics_entry->uid = 0;
+		dasd_statistics_entry->gid = 0;
+		dasd_statistics_entry->size = 0;
+		dasd_statistics_entry->get_info = NULL;
+		dasd_statistics_entry->ops = &dasd_statistics_inode_ops;
+		proc_register (&dasd_proc_root_entry, dasd_statistics_entry);
 	}
-#endif				/* DASD_PARANOIA */
-	FUNCTION_EXIT ("dasd_release");
+#endif				/* LINUX_IS_24 */
 	return rc;
 }
 
-static struct
-block_device_operations dasd_device_operations =
+void
+dasd_proc_cleanup (void)
 {
-	ioctl:   dasd_ioctl,
-	open:    dasd_open,
-	release: dasd_release,
-};
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	remove_proc_entry ("devices", dasd_proc_root_entry);
+	remove_proc_entry ("statistics", dasd_proc_root_entry);
+	remove_proc_entry ("dasd", &proc_root);
+#else
+	proc_unregister (&dasd_proc_root_entry, dasd_statistics_entry->low_ino);
+	kfree (dasd_statistics_entry);
+	proc_unregister (&dasd_proc_root_entry, dasd_devices_entry->low_ino);
+	kfree (dasd_devices_entry);
+	proc_unregister (&proc_root, dasd_proc_root_entry.low_ino);
+#endif				/* LINUX_IS_24 */
+}
 
-int
+/* SECTION: Initializing the driver */
+
+int __init
 dasd_init (void)
 {
 	int rc = 0;
-	int i;
+	int irq;
+	int j;
+	major_info_t *major_info;
+	dasd_range_t *range;
+
+	printk (KERN_INFO PRINTK_HEADER "initializing...\n");
+	for (major_info = dasd_major_info; major_info; major_info = major_info->next) {
+                if ((rc = dasd_register_major (major_info)) > 0) {
+                        printk (KERN_INFO PRINTK_HEADER
+                                "Registered successfully to major no %u\n", major_info->gendisk.major);
+		} else {
+			printk (KERN_WARNING PRINTK_HEADER
+				"Couldn't register successfully to major no %d\n", major_info->gendisk.major);
+			/* revert registration of major infos */
+			goto major_failed;
+		}
+	}
+#ifndef MODULE
+	dasd_split_parm_string (dasd_parm_string);
+#endif				/* ! MODULE */
+	dasd_parse (dasd);
+	dasd_init_emergency_req ();
 
-	FUNCTION_ENTRY ("dasd_init");
-	PRINT_INFO ("initializing...\n");
-	atomic_set (&chanq_tasks, 0);
-	atomic_set (&bh_scheduled, 0);
-	spin_lock_init (&dasd_lock);
-        init_waitqueue_head(&dasd_waitq);
-	/* First register to the major number */
-	rc = register_major (MAJOR_NR);
-#if DASD_PARANOIA > 1
+	rc = dasd_proc_init ();
 	if (rc) {
-		PRINT_WARN ("registering major_nr returned rc=%d\n", rc);
-		return rc;
+		goto proc_failed;
 	}
-#endif	/* DASD_PARANOIA */ 
-        read_ahead[MAJOR_NR] = 8;
-        blk_size[MAJOR_NR] = dasd_blks;
-	hardsect_size[MAJOR_NR] = dasd_secsize;
-	blksize_size[MAJOR_NR] = dasd_blksize;
-	max_sectors[MAJOR_NR] = dasd_maxsecs;
-#ifdef CONFIG_PROC_FS
-	dasd_proc_init ();
-#endif				/* CONFIG_PROC_FS */
-	/* Now scan the device list for DASDs */
-	FUNCTION_CONTROL ("entering detection loop%s\n", "");
-	for (i = 0; i < NR_IRQS; i++) {
-		int irc;	/* Internal return code */
-		LOOP_CONTROL ("Probing irq %d...\n", i);
-		irc = probe_for_dasd (i);
-		switch (irc) {
-		case 0:
-			LOOP_CONTROL ("Added DASD%s\n", "");
-			break;
-		case -ENODEV:
-			LOOP_CONTROL ("No DASD%s\n", "");
-			break;
-		case -EMEDIUMTYPE:
-			PRINT_WARN ("DASD not formatted%s\n", "");
-			break;
-		default:
-			INTERNAL_CHECK ("probe_for_dasd: unknown rc=%d", irc);
-			break;
+	genhd_dasd_name = dasd_device_name;
+
+#ifdef CONFIG_DASD_ECKD
+	rc = dasd_eckd_init ();
+	if (rc == 0) {
+		printk (KERN_INFO PRINTK_HEADER
+			"Registered ECKD discipline successfully\n");
+	} else {
+		goto eckd_failed;
+	}
+#endif				/* CONFIG_DASD_ECKD */
+#ifdef CONFIG_DASD_FBA
+	rc = dasd_fba_init ();
+	if (rc == 0) {
+		printk (KERN_INFO PRINTK_HEADER
+			"Registered FBA discipline successfully\n");
+	} else {
+		goto fba_failed;
+	}
+#endif				/* CONFIG_DASD_FBA */
+#ifdef CONFIG_DASD_MDSK
+	if (MACHINE_IS_VM) {
+		rc = dasd_diag_init ();
+		if (rc == 0) {
+			printk (KERN_INFO PRINTK_HEADER
+				"Registered MDSK discipline successfully\n");
+		} else {
+			goto mdsk_failed;
 		}
 	}
-	FUNCTION_CONTROL ("detection loop completed %s partn check...\n", "");
-/* Finally do the genhd stuff */
-	dd_gendisk.next = gendisk_head;
-	gendisk_head = &dd_gendisk;
-        for ( i = 0; i < DASD_MAX_DEVICES; i ++ )
-          if ( dasd_info[i] )
-                dasd_partn_detect ( i );
-
-	FUNCTION_EXIT ("dasd_init");
+#endif				/* CONFIG_DASD_MDSK */
+	rc = 0;
+	for (range = dasd_range_head; range; range = range->next) {
+		for (j = range->from; j <= range->to; j++) {
+			irq = get_irq_by_devno (j);
+			if (irq >= 0)
+				dasd_set_device_level (irq, DASD_DEVICE_LEVEL_ANALYSIS_PREPARED,
+						       NULL, 0);
+		}
+	}
+	if (dasd_autodetect) {
+		for (irq = get_irq_first (); irq != -ENODEV; irq = get_irq_next (irq)) {
+			int devno = get_devno_by_irq (irq);
+			int index = dasd_devindex_from_devno (devno);
+			if (index == -ENODEV) {		/* not included in ranges */
+				dasd_add_range (devno, 0);
+				dasd_set_device_level (irq, DASD_DEVICE_LEVEL_ANALYSIS_PREPARED,
+						       NULL, 0);
+			}
+		}
+	}
+	printk (KERN_INFO PRINTK_HEADER "waiting for responses...\n");
+	{
+		static wait_queue_head_t wait_queue;
+		init_waitqueue_head (&wait_queue);
+		interruptible_sleep_on_timeout (&wait_queue,
+						(5 * HZ) );
+	}
+	for (range = dasd_range_head; range; range = range->next) {
+		for (j = range->from; j <= range->to; j++) {
+			irq = get_irq_by_devno (j);
+			if (irq >= 0) {
+				dasd_set_device_level (irq, DASD_DEVICE_LEVEL_ANALYSED,
+						       NULL, 0);
+			}
+		}
+	}
+	goto out;
+#ifdef CONFIG_DASD_MDSK
+      mdsk_failed:
+	dasd_diag_cleanup ();
+#endif				/* CONFIG_DASD_MDSK */
+#ifdef CONFIG_DASD_FBA
+      fba_failed:
+	dasd_fba_cleanup ();
+#endif				/* CONFIG_DASD_FBA */
+#ifdef CONFIG_DASD_ECKD
+      eckd_failed:
+	dasd_eckd_cleanup ();
+#endif				/* CONFIG_DASD_ECKD */
+      proc_failed:
+	dasd_proc_cleanup ();
+      major_failed:{
+                major_info_t * temp;
+		for (temp = dasd_major_info;
+		     temp && (temp != major_info);
+		     temp = temp->next) {
+			dasd_unregister_major (temp);
+		}
+	}
+	dasd_cleanup_emergency_req ();
+	printk (KERN_INFO PRINTK_HEADER "initialization not performed due to errors\n");
+      out:
+	printk (KERN_INFO PRINTK_HEADER "initialization finished\n");
 	return rc;
 }
 
+void
+cleanup_dasd (void)
+{
+	int j, rc = 0;
+	int irq;
+	major_info_t *major_info;
+	dasd_range_t *range, *next;
+
+	printk (KERN_INFO PRINTK_HEADER "shutting down\n");
+
+	dasd_proc_cleanup ();
+
+	for (range = dasd_range_head; range; range = range->next) {
+		for (j = range->from; j <= range->to; j++) {
+			irq = get_irq_by_devno (j);
+			if (irq >= 0) {
+				dasd_set_device_level (irq, DASD_DEVICE_LEVEL_UNKNOWN,
+						       NULL, 0);
+			}
+		}
+	}
+	for (major_info = dasd_major_info; major_info; major_info = major_info->next) {
+		int i;
+		for (i = 0; i < DASD_PER_MAJOR; i++) {
+			kfree (major_info->dasd_device[i]);
+		}
+		if ((rc = dasd_unregister_major (major_info)) == 0) {
+			printk (KERN_INFO PRINTK_HEADER
+				"Unregistered successfully from major no %u\n", major_info->gendisk.major);
+		} else {
+			printk (KERN_WARNING PRINTK_HEADER
+				"Couldn't unregister successfully from major no %d rc = %d\n", major_info->gendisk.major, rc);
+		}
+	}
+	dasd_cleanup_emergency_req ();
+
+	range = dasd_range_head;
+	while (range) {
+		next = range->next;
+		kfree (range);
+		if (next == NULL)
+			break;
+		else
+			range = next;
+	}
+	dasd_range_head = NULL;
+
+#ifdef CONFIG_DASD_DYNAMIC
+	{
+		dasd_devreg_t *reg;
+		while (dasd_devreg_head) {
+			reg = dasd_devreg_head->next;
+			kfree (dasd_devreg_head);
+			dasd_devreg_head = reg;
+		}
+	}
+#endif	/* CONFIG_DASD_DYNAMIC */
+	printk (KERN_INFO PRINTK_HEADER "shutdown completed\n");
+}
+
 #ifdef MODULE
 int
 init_module (void)
 {
 	int rc = 0;
-
-	FUNCTION_ENTRY ("init_module");
-	PRINT_INFO ("trying to load module\n");
-	rc = dasd_init ();
-	if (rc == 0) {
-		PRINT_INFO ("module loaded successfully\n");
-	} else {
-		PRINT_WARN ("warning: Module load returned rc=%d\n", rc);
-	}
-	FUNCTION_EXIT ("init_module");
+	return dasd_init ();
 	return rc;
 }
 
 void
 cleanup_module (void)
 {
-	int rc = 0;
-
-	FUNCTION_ENTRY ("cleanup_module");
-	PRINT_INFO ("trying to unload module \n");
-
-	/* FIXME: replace by proper unload functionality */
-	INTERNAL_ERROR ("Modules not yet implemented %s", "");
-
-	if (rc == 0) {
-		PRINT_INFO ("module unloaded successfully\n");
-	} else {
-		PRINT_WARN ("module unloaded with errors\n");
-	}
-	FUNCTION_EXIT ("cleanup_module");
+	cleanup_dasd ();
+	return;
 }
-#endif				/* MODULE */
+#endif
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_3370_erp.c linux/drivers/s390/block/dasd_3370_erp.c
--- v2.4.1/linux/drivers/s390/block/dasd_3370_erp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_3370_erp.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,105 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_3370_erp.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+
+#include <asm/ccwcache.h>
+#include <asm/dasd.h>
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#define PRINTK_HEADER "dasd_erp(3370)"
+#endif				/* PRINTK_HEADER */
+
+/*
+ * DASD_3370_ERP_EXAMINE 
+ *
+ * DESCRIPTION
+ *   Checks only for fatal/no/recover error. 
+ *   A detailed examination of the sense data is done later outside
+ *   the interrupt handler.
+ *
+ *   The logic is based on the 'IBM 3880 Storage Control Reference' manual
+ *   'Chapter 7. 3370 Sense Data'.
+ *
+ * RETURN VALUES
+ *   dasd_era_none      no error 
+ *   dasd_era_fatal     for all fatal (unrecoverable errors)
+ *   dasd_era_recover   for all others.
+ */
+dasd_era_t
+dasd_3370_erp_examine (ccw_req_t * cqr, devstat_t * stat)
+{
+	char *sense = stat->ii.sense.data;
+
+	/* check for successful execution first */
+	if (stat->cstat == 0x00 &&
+	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+		return dasd_era_none;
+	if (sense[0] & 0x80) {	/* CMD reject */
+		return dasd_era_fatal;
+	}
+	if (sense[0] & 0x40) {	/* Drive offline */
+		return dasd_era_recover;
+	}
+	if (sense[0] & 0x20) {	/* Bus out parity */
+		return dasd_era_recover;
+	}
+	if (sense[0] & 0x10) {	/* equipment check */
+		if (sense[1] & 0x80) {
+			return dasd_era_fatal;
+		}
+		return dasd_era_recover;
+	}
+	if (sense[0] & 0x08) {	/* data check */
+		if (sense[1] & 0x80) {
+			return dasd_era_fatal;
+		}
+		return dasd_era_recover;
+	}
+	if (sense[0] & 0x04) {	/* overrun */
+		if (sense[1] & 0x80) {
+			return dasd_era_fatal;
+		}
+		return dasd_era_recover;
+	}
+	if (sense[1] & 0x40) {	/* invalid blocksize */
+		return dasd_era_fatal;
+	}
+	if (sense[1] & 0x04) {	/* file protected */
+		return dasd_era_recover;
+	}
+	if (sense[1] & 0x01) {	/* operation incomplete */
+		return dasd_era_recover;
+	}
+	if (sense[2] & 0x80) {	/* check data erroor */
+		return dasd_era_recover;
+	}
+	if (sense[2] & 0x10) {	/* Env. data present */
+		return dasd_era_recover;
+	}
+	/* examine the 24 byte sense data */
+	return dasd_era_recover;
+
+}				/* END dasd_3370_erp_examine */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_3990_erp.c linux/drivers/s390/block/dasd_3990_erp.c
--- v2.4.1/linux/drivers/s390/block/dasd_3990_erp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_3990_erp.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,152 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_3990_erp.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *                  Horst  Hummel    <Horst.Hummel@de.ibm.com> 
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+
+#include <asm/ccwcache.h>
+#include <asm/dasd.h>
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#define PRINTK_HEADER "dasd_erp(3990)"
+#endif /* PRINTK_HEADER */
+
+/*
+ * DASD_3990_ERP_EXAMINE_32 
+ *
+ * DESCRIPTION
+ *   Checks only for fatal/no/recoverable error. 
+ *   A detailed examination of the sense data is done later outside
+ *   the interrupt handler.
+ *
+ * RETURN VALUES
+ *   dasd_era_none      no error 
+ *   dasd_era_fatal     for all fatal (unrecoverable errors)
+ *   dasd_era_recover   for recoverable others.
+ */
+dasd_era_t
+dasd_3990_erp_examine_32 (char *sense)
+{
+
+	switch (sense[25]) {
+	case 0x00:
+		return dasd_era_none;
+	case 0x01:
+		return dasd_era_fatal;
+	default:
+		return dasd_era_recover;
+	}
+
+}				/* end dasd_3990_erp_examine_32 */
+
+/*
+ * DASD_3990_ERP_EXAMINE_24 
+ *
+ * DESCRIPTION
+ *   Checks only for fatal (unrecoverable) error. 
+ *   A detailed examination of the sense data is done later outside
+ *   the interrupt handler.
+ *
+ *   Each bit configuration leading to an action code 2 (Exit with
+ *   programming error or unusual condition indication)
+ *   and 10 (disabled interface) are handled as fatal error´s.
+ * 
+ *   All other configurations are handled as recoverable errors.
+ *
+ * RETURN VALUES
+ *   dasd_era_fatal     for all fatal (unrecoverable errors)
+ *   dasd_era_recover   for all others.
+ */
+dasd_era_t
+dasd_3990_erp_examine_24 (char *sense)
+{
+
+	/* check for 'Command Recejct' whithout environmental data present  */
+	if (sense[0] & 0x80) {
+                if (sense[2] &0x10){
+                        return dasd_era_recover;
+                } else {
+                        return dasd_era_fatal;
+                }
+        }
+	
+        /* check for 'Invalid Track Format' whithout environmental data present  */
+	if (sense[1] & 0x40) {
+                if (sense[2] &0x10){
+                        return dasd_era_recover;
+                } else {
+                        return dasd_era_fatal;
+                }
+	}
+	/* check for 'No Record Found'                                */
+	if (sense[1] & 0x08) {
+		return dasd_era_fatal;
+	}
+	/* return recoverable for all others                          */
+	return dasd_era_recover;
+
+}				/* END dasd_3990_erp_examine_24 */
+
+/*
+ * DASD_3990_ERP_EXAMINE 
+ *
+ * DESCRIPTION
+ *   Checks only for fatal/no/recover error. 
+ *   A detailed examination of the sense data is done later outside
+ *   the interrupt handler.
+ *
+ *   The logic is based on the 'IBM 3990 Storage Control  Reference' manual
+ *   'Chapter 7. Error Recovery Procedures'.
+ *
+ * RETURN VALUES
+ *   dasd_era_none      no error 
+ *   dasd_era_fatal     for all fatal (unrecoverable errors)
+ *   dasd_era_recover   for all others.
+ */
+dasd_era_t
+dasd_3990_erp_examine (ccw_req_t * cqr, devstat_t * stat)
+{
+
+	char *sense = stat->ii.sense.data;
+
+	/* check for successful execution first */
+	if (stat->cstat == 0x00 &&
+	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+		return dasd_era_none;
+
+	/* distinguish between 24 and 32 byte sense data */
+	if (sense[27] & 0x80) {
+
+		/* examine the 32 byte sense data */
+		return dasd_3990_erp_examine_32 (sense);
+
+	} else {
+
+		/* examine the 24 byte sense data */
+		return dasd_3990_erp_examine_24 (sense);
+
+	}			/* end distinguish between 24 and 32 byte sense data */
+
+}				/* END dasd_3990_erp_examine */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_3990_erp.h linux/drivers/s390/block/dasd_3990_erp.h
--- v2.4.1/linux/drivers/s390/block/dasd_3990_erp.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_3990_erp.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,17 @@
+ccw_req_t *dasd_3990_erp_com_rej (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_int_req (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_bus_out (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_equip_check (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_data_check (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_overrun (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_inv_format (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_EOC (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_env_data (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_no_rec (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_file_prot (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_perm (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_first_log (ccw_req_t *, devstat_t *);
+ccw_req_t *dasd_3990_erp_add_erp (ccw_req_t *, devstat_t *);	/* tbd - delete */
+
+ccw_req_t *dasd_3990_erp_action (ccw_req_t *);
+ccw_req_t *dasd_2105_erp_action (ccw_req_t *);
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_9336_erp.c linux/drivers/s390/block/dasd_9336_erp.c
--- v2.4.1/linux/drivers/s390/block/dasd_9336_erp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_9336_erp.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,64 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_9336_erp.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+
+#include <asm/ccwcache.h>
+#include <asm/dasd.h>
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#define PRINTK_HEADER "dasd_erp(9336)"
+#endif				/* PRINTK_HEADER */
+
+/*
+ * DASD_9336_ERP_EXAMINE 
+ *
+ * DESCRIPTION
+ *   Checks only for fatal/no/recover error. 
+ *   A detailed examination of the sense data is done later outside
+ *   the interrupt handler.
+ *
+ *   The logic is based on the 'IBM 3880 Storage Control Reference' manual
+ *   'Chapter 7. 9336 Sense Data'.
+ *
+ * RETURN VALUES
+ *   dasd_era_none      no error 
+ *   dasd_era_fatal     for all fatal (unrecoverable errors)
+ *   dasd_era_recover   for all others.
+ */
+dasd_era_t
+dasd_9336_erp_examine (ccw_req_t * cqr, devstat_t * stat)
+{
+	char *sense = stat->ii.sense.data;
+
+	/* check for successful execution first */
+	if (stat->cstat == 0x00 &&
+	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+		return dasd_era_none;
+
+	/* examine the 24 byte sense data */
+	return dasd_era_recover;
+
+}				/* END dasd_9336_erp_examine */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_9343_erp.c linux/drivers/s390/block/dasd_9343_erp.c
--- v2.4.1/linux/drivers/s390/block/dasd_9343_erp.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_9343_erp.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,23 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_9345_erp.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+
+#include <asm/ccwcache.h>
+#include <asm/dasd.h>
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#define PRINTK_HEADER "dasd_erp(9343)"
+#endif				/* PRINTK_HEADER */
+
+dasd_era_t
+dasd_9343_erp_examine (ccw_req_t * cqr, devstat_t * stat)
+{
+	if (stat->cstat == 0x00 &&
+	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+		return dasd_era_none;
+	return dasd_era_recover;
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_ccwstuff.c linux/drivers/s390/block/dasd_ccwstuff.c
--- v2.4.1/linux/drivers/s390/block/dasd_ccwstuff.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_ccwstuff.c	Wed Dec 31 16:00:00 1969
@@ -1,419 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_ccwstuff.c
- * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
- */
-
-#include <linux/stddef.h>
-#include <linux/kernel.h>
-#include <linux/malloc.h>
-#include <linux/dasd.h>
-#include <asm/atomic.h>
-
-#include "dasd_types.h"
-
-#define PRINTK_HEADER "dasd_ccw:"
-#define MAX_CP_POWER 9		/* Maximum allowed index */
-#define CP_PER_PAGE_POWER 9	/* Maximum index, fitting on page */
-
-#define get_free_pages __get_free_pages
-
-/* Stuff for the handling task_list */
-dasd_chanq_t *cq_head = NULL;	/* head of task_list */
-atomic_t chanq_tasks;
-
-/* Array of freelists for the channel programs' -space */
-static ccw1_t *ccwarea[CP_PER_PAGE_POWER + 1] =
-{NULL,};
-
-/* array of pages retrieved for internal use */
-#define MAX_DASD_PAGES 64
-static int dasd_page_count = 0;
-static long dasd_page[MAX_DASD_PAGES];
-
-static spinlock_t ccw_lock=SPIN_LOCK_UNLOCKED;	/* spinlock for ccwareas */
-static spinlock_t cq_lock=SPIN_LOCK_UNLOCKED;	/* spinlock for cq_head */
-
-void
-ccwarea_enq (int index, ccw1_t * area)
-{
-	FUNCTION_ENTRY ("ccwarea_enq");
-#if DASD_PARANOIA > 2
-	if (!area) {
-		INTERNAL_CHECK ("zero area %s\n", "");
-	}
-	if (index > CP_PER_PAGE_POWER) {
-		INTERNAL_CHECK ("index too large %d\n", index);
-	}
-#endif
-	*(ccw1_t **) area = ccwarea[index];
-	ccwarea[index] = area;
-	FUNCTION_EXIT ("ccwarea_enq");
-	return;
-}
-
-ccw1_t *
-ccwarea_deq (int index)
-{
-	ccw1_t *cp;
-	FUNCTION_ENTRY ("ccwarea_deq");
-#if DASD_PARANOIA > 2
-	if (index > CP_PER_PAGE_POWER) {
-		INTERNAL_CHECK ("index too large %d\n", index);
-	}
-#endif
-	cp = ccwarea[index];
-	ccwarea[index] = *(ccw1_t **) ccwarea[index];
-#if DASD_PARANOIA > 2
-	if (!cp) {
-		INTERNAL_CHECK ("returning NULL %s\n", "");
-	}
-#endif
-	FUNCTION_EXIT ("ccwarea_deq");
-	return cp;
-}
-
-ccw1_t *
-request_cpa (int index)
-{
-	ccw1_t *freeblk;
-	FUNCTION_ENTRY ("request_cpa");
-	if (index > MAX_CP_POWER) {
-		INTERNAL_ERROR ("index too large %d\n", index);
-		freeblk = NULL;
-		goto exit;
-	}
-	if (index > CP_PER_PAGE_POWER) {
-		int pc = 1 << (index - CP_PER_PAGE_POWER);
-		do {
-			freeblk = (ccw1_t *) get_free_pages (GFP_ATOMIC, index - CP_PER_PAGE_POWER);
-			if (dasd_page_count + pc >= MAX_DASD_PAGES) {
-				PRINT_WARN ("Requesting too many pages...");
-			} else {
-				int i;
-				for (i = 0; i < pc; i++)
-					dasd_page[dasd_page_count++] =
-						(long) freeblk + i * PAGE_SIZE;
-			}
-			FUNCTION_CONTROL ("requesting index %d", index);
-			if ( ! freeblk ) {
-				panic ("No memory received\n");
-			}
-		} while (!freeblk);
-		memset(freeblk,0,PAGE_SIZE<<(index-CP_PER_PAGE_POWER));
-		goto exit;
-	}
-	while (ccwarea[index] == NULL) {
-		ccw1_t *blk;
-		if (index == CP_PER_PAGE_POWER) {
-			do {
-				blk = (ccw1_t *) get_free_page (GFP_ATOMIC);
-				if (dasd_page_count + 1 >= MAX_DASD_PAGES) {
-					PRINT_WARN ("Requesting too many pages...");
-				} else {
-					dasd_page[dasd_page_count++] =
-						(long) blk;
-				}
-				if (blk == NULL) {
-					PRINT_WARN ("Can't allocate page!\n");
-				}
-			} while ( ! blk );
-			memset(blk,0,PAGE_SIZE);
-			ccwarea_enq (CP_PER_PAGE_POWER, blk);
-			continue;
-		}
-		blk = request_cpa (index + 1);
-#if DASD_PARANOIA > 1
-		if (!blk) {
-			PRINT_WARN ("retrieved NULL");
-		}
-#endif				/* DASD_PARANOIA */
-		ccwarea_enq (index, blk);
-		ccwarea_enq (index, blk + (1 << index));
-	}
-#if DASD_PARANOIA > 2
-	if (!ccwarea[index]) {
-		INTERNAL_ERROR ("ccwarea is NULL\n%s", "");
-	}
-#endif				/* DASD_PARANOIA */
-
-	freeblk = ccwarea_deq (index);
-#if DASD_PARANOIA > 1
-	if (!freeblk) {
-		INTERNAL_ERROR ("freeblk is NULL\n%s", "");
-	}
-#endif				/* DASD_PARANOIA */
-      exit:
-	FUNCTION_EXIT ("request_cpa");
-	return freeblk;
-}
-
-ccw1_t *
-request_cp (int size)
-{
-	ccw1_t *freeblk;
-	int index;
-	int blksize;
-	/* Determine the index of ccwarea to look at */
-	for (index = 0, blksize = 1;
-	     size > blksize;
-	     index++, blksize = blksize << 1) {
-	}
-	if (index > MAX_CP_POWER) {
-		INTERNAL_ERROR ("index too large %d\n", index);
-	}
-	spin_lock (&ccw_lock);
-	freeblk = request_cpa (index);
-	spin_unlock (&ccw_lock);
-	if (freeblk == NULL) {
-		printk (KERN_WARNING PRINTK_HEADER
-			"No way to deliver free ccw space\n");
-	}
-	return freeblk;
-}
-
-void
-release_cp (int size, ccw1_t * area)
-{
-	int index;
-	int blksize;
-	/* Determine the index of ccwarea to look at */
-	for (index = 0, blksize = 1;
-	     size > blksize;
-	     index++, blksize = blksize << 1) {
-	}
-	if (index > MAX_CP_POWER) {
-		INTERNAL_ERROR ("index too large %d\n", index);
-	} else if (index > CP_PER_PAGE_POWER) {
-		free_pages ((unsigned long) area,
-			    index - CP_PER_PAGE_POWER);
-		INTERNAL_CHECK ("large index used: %d\n", index);
-	} else {
-		spin_lock (&ccw_lock);
-		ccwarea_enq (index, area);
-		spin_unlock (&ccw_lock);
-	}
-	return;
-}
-
-/* ---------------------------------------------------------- */
-
-static cqr_t *cqrp = NULL;
-static spinlock_t cqr_lock=SPIN_LOCK_UNLOCKED;
-
-void
-cqf_enq (cqr_t * cqf)
-{
-	*(cqr_t **) cqf = cqrp;
-	cqrp = cqf;
-}
-
-cqr_t *
-cqf_deq (void)
-{
-	cqr_t *cqr = cqrp;
-	cqrp = *(cqr_t **) cqrp;
-	return cqr;
-}
-
-cqr_t *
-request_cq (void)
-{
-	cqr_t *cqr = NULL;
-	int i;
-	cqr_t *area;
-
-	spin_lock (&cqr_lock);
-	while (cqrp == NULL) {
-		do {
-			area = (cqr_t *) get_free_page (GFP_ATOMIC);
-			if (area == NULL) {
-				printk (KERN_WARNING PRINTK_HEADER
-					"No memory for chanq area\n");
-			}
-		} while ( ! area );
-		memset(area,0,PAGE_SIZE);
-		if (dasd_page_count + 1 >= MAX_DASD_PAGES) {
-			PRINT_WARN ("Requesting too many pages...");
-		} else {
-			dasd_page[dasd_page_count++] =
-				(long) area;
-		}
-		for (i = 0; i < 4096 / sizeof (cqr_t); i++) {
-				cqf_enq (area + i);
-		}
-	}
-	cqr = cqf_deq ();
-	spin_unlock (&cqr_lock);
-	return cqr;
-}
-
-void
-release_cq (cqr_t * cqr)
-{
-	spin_lock (&cqr_lock);
-	cqf_enq (cqr);
-	spin_unlock (&cqr_lock);
-	return;
-}
-
-/* ----------------------------------------------------------- */
-cqr_t *
-request_cqr (int cpsize, int datasize)
-{
-	cqr_t *cqr = NULL;
-	cqr = request_cq ();
-	if (cqr == NULL) {
-		printk (KERN_WARNING PRINTK_HEADER __FILE__
-			"No memory for chanq request\n");
-		goto exit;
-	}
-	memset (cqr, 0, sizeof (cqr_t));
-	cqr -> magic = DASD_MAGIC;
-	if (cpsize) {
-		cqr->cpaddr = request_cp (cpsize);
-		if (cqr->cpaddr == NULL) {
-			printk (KERN_WARNING PRINTK_HEADER __FILE__
-				"No memory for channel program\n");
-			goto nocp;
-		}
-		cqr->cplength = cpsize;
-	}
-	if (datasize) {
-		do {
-			cqr->data = (char *) kmalloc (datasize, GFP_ATOMIC);
-			if (cqr->data == NULL) {
-				printk (KERN_WARNING PRINTK_HEADER __FILE__
-					"No memory for cqr data area\n");
-			}
-		} while (!cqr->data);
-		memset (cqr->data,0,datasize);
-	}
-	goto exit;
- nocp:
-	release_cq (cqr);
-	cqr = NULL;
- exit:
-	return cqr;
-}
-
-int
-release_cqr (cqr_t * cqr)
-{
-	int rc = 0;
-	if (cqr == NULL) {
-		rc = -ENOENT;
-		return rc;
-	}
-	if (cqr->data) {
-		kfree (cqr->data);
-	}
-	if (cqr->dstat) {
-		kfree (cqr->dstat);
-	}
-	if (cqr->cpaddr) {
-		release_cp (cqr->cplength, cqr->cpaddr);
-	}
-	cqr -> magic = dasd_MAGIC;
-	release_cq (cqr);
-	return rc;
-}
-
-/* -------------------------------------------------------------- */
-void
-dasd_chanq_enq (dasd_chanq_t * q, cqr_t * cqr)
-{
-	if (q->head != NULL) {
-		q->tail->next = cqr;
-	} else
-		q->head = cqr;
-	cqr->next = NULL;
-	q->tail = cqr;
-	q->queued_requests ++;
-	if (atomic_compare_and_swap(CQR_STATUS_FILLED,
-				    CQR_STATUS_QUEUED,
-				    &cqr->status)) {
-		PRINT_WARN ("q_cqr: %p status changed %d\n", 
-			    cqr,atomic_read(&cqr->status));
-		atomic_set(&cqr->status,CQR_STATUS_QUEUED);
-	}
-}
-
-int
-dasd_chanq_deq (dasd_chanq_t * q, cqr_t * cqr)
-{
-	cqr_t *prev;
-
-	if (cqr == NULL)
-		return -ENOENT;
-	if (cqr == (cqr_t *) q->head) {
-		q->head = cqr->next;
-		if (q->head == NULL)
-			q->tail = NULL;
-	} else {
-		prev = (cqr_t *) q->head; 
-		while (prev && prev->next != cqr)
-			prev = prev->next;
-		if (prev == NULL)
-			return -ENOENT;
-		prev->next = cqr->next;
-		if (prev->next == NULL)
-			q->tail = prev;
-	}
-	cqr->next = NULL;
-	q->queued_requests --;
-	return release_cqr(cqr);
-}
-
-/* -------------------------------------------------------------------------- */
-void
-cql_enq_head (dasd_chanq_t * q)
-{
-	if (q == NULL) {
-		INTERNAL_ERROR ("NULL queue passed%s\n", "");
-		return;
-	}
-	if (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE) {
-		PRINT_WARN("Queue already active");
-		return;
-	}
-	spin_lock(&cq_lock);
-	atomic_set_mask(DASD_CHANQ_ACTIVE,&q->flags);
-	q->next_q = cq_head;
-	cq_head = q;
-	spin_unlock(&cq_lock);
-}
-
-void
-cql_deq (dasd_chanq_t * q)
-{
-	dasd_chanq_t *c;
-
-        if (cq_head == NULL) {
-                INTERNAL_ERROR ("Channel queue is empty%s\n", "");
-		return;
-	}
-	if (q == NULL) {
-		INTERNAL_ERROR ("NULL queue passed%s\n", "");
-		return;
-	}
-	spin_lock(&cq_lock);
-	if (! (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE)) {
-		PRINT_WARN("Queue not active\n");
-	}
-	else if (cq_head == q) {
-		cq_head = q->next_q;
-	} else {
-		c = cq_head;
-		while (c->next_q && c->next_q != q)
-			c = c->next_q;
-		if (c->next_q != q)
-			INTERNAL_ERROR ("Entry not in queue%s\n", "");
-		else
-			c->next_q = q->next_q;
-	}
-	q->next_q = NULL;
-	atomic_clear_mask(DASD_CHANQ_ACTIVE,&q->flags);
-	spin_unlock(&cq_lock);
-}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_ccwstuff.h linux/drivers/s390/block/dasd_ccwstuff.h
--- v2.4.1/linux/drivers/s390/block/dasd_ccwstuff.h	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_ccwstuff.h	Wed Dec 31 16:00:00 1969
@@ -1,9 +0,0 @@
-extern atomic_t chanq_tasks;
-extern dasd_chanq_t *cq_head;
-
-cqr_t *request_cqr (int, int);
-int release_cqr (cqr_t *);
-int dasd_chanq_enq (dasd_chanq_t *, cqr_t *);
-int dasd_chanq_deq (dasd_chanq_t *, cqr_t *);
-void cql_enq_head (dasd_chanq_t * q);
-void cql_deq (dasd_chanq_t * q);
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_diag.c linux/drivers/s390/block/dasd_diag.c
--- v2.4.1/linux/drivers/s390/block/dasd_diag.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_diag.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,571 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_diag.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Based on.......: linux/drivers/s390/block/mdisk.c
+ * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+
+ * History of changes
+ * 07/13/00 Added fixup sections for diagnoses ans saved some registers
+ * 07/14/00 fixed constraints in newly generated inline asm
+ * 10/05/00 adapted to 'new' DASD driver
+ */
+
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <asm/debug.h>
+
+#include <linux/malloc.h>
+#include <linux/hdreg.h>	/* HDIO_GETGEO                      */
+#include <linux/blk.h>
+#include <asm/ccwcache.h>
+#include <asm/dasd.h>
+
+#include <asm/ebcdic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/s390dyn.h>
+
+#include "dasd_diag.h"
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#endif				/* PRINTK_HEADER */
+#define PRINTK_HEADER DASD_NAME"(diag):"
+
+dasd_discipline_t dasd_diag_discipline;
+
+typedef struct
+dasd_diag_private_t {
+	dasd_diag_characteristics_t rdc_data;
+	diag_rw_io_t iob;
+	diag_init_io_t iib;
+	unsigned long *label;
+} dasd_diag_private_t;
+
+static __inline__ int
+dia210 (void *devchar)
+{
+	int rc;
+
+	__asm__ __volatile__ ("    diag  %1,0,0x210\n"
+			      "0:  ipm   %0\n"
+			      "    srl   %0,28\n"
+			      "1:\n"
+			      ".section .fixup,\"ax\"\n"
+			      "2:  lhi   %0,3\n"
+			      "    bras  1,3f\n"
+			      "    .long 1b\n"
+			      "3:  l     1,0(1)\n"
+			      "    br    1\n"
+			      ".previous\n"
+			      ".section __ex_table,\"a\"\n"
+			      "    .align 4\n"
+			      "    .long 0b,2b\n"
+			      ".previous\n"
+			      :"=d"   (rc)
+			      :"d"    ((void *) __pa (devchar))
+			      :"1");
+	return rc;
+}
+
+static __inline__ int
+dia250 (void *iob, int cmd)
+{
+	int rc;
+
+	__asm__ __volatile__ ("    lr    1,%1\n"
+			      "    diag  1,%2,0x250\n"
+			      "1:\n"
+			      ".section .fixup,\"ax\"\n"
+			      "2:  lhi   %0,3\n"
+			      "    bras  1,3f\n"
+			      "    .long 1b\n"
+			      "3:  l     1,0(1)\n"
+			      "    br    1\n"
+			      ".previous\n"
+			      ".section __ex_table,\"a\"\n"
+			      "    .align 4\n"
+			      "    .long 1b,2b\n"
+			      ".previous\n"
+			      :"=d"   (rc)
+			      :"d"    ((void *) __pa (iob)), "0" (cmd)
+			      :"1");
+	return rc;
+}
+
+static __inline__ int
+mdsk_init_io (dasd_device_t * device, int blocksize, int offset, int size)
+{
+	dasd_diag_private_t *private = (dasd_diag_private_t *) device->private;
+	diag_init_io_t *iib = &private->iib;
+	int rc;
+
+	memset (iib, 0, sizeof (diag_init_io_t));
+
+	iib->dev_nr = device->devinfo.devno;
+	iib->block_size = blocksize;
+	iib->offset = offset;
+	iib->start_block = 0;
+	iib->end_block = size;
+
+	rc = dia250 (iib, INIT_BIO);
+
+	return rc;
+}
+
+static __inline__ int
+mdsk_term_io (dasd_device_t * device)
+{
+	dasd_diag_private_t *private = (dasd_diag_private_t *) device->private;
+	diag_init_io_t *iib = &private->iib;
+	int rc;
+
+	memset (iib, 0, sizeof (diag_init_io_t));
+	iib->dev_nr = device->devinfo.devno;
+	rc = dia250 (iib, TERM_BIO);
+	return rc;
+}
+
+int
+dasd_start_diag (ccw_req_t * cqr)
+{
+	int rc;
+	dasd_device_t *device = cqr->device;
+	dasd_diag_private_t *private;
+	diag_rw_io_t *iob;
+
+	private = (dasd_diag_private_t *) device->private;
+	iob = &private->iob;
+
+	iob->dev_nr = device->devinfo.devno;
+	iob->key = 0;
+	iob->flags = 2;
+	iob->block_count = cqr->cplength >> 1;
+	iob->interrupt_params = (u32) cqr;
+	iob->bio_list = __pa (cqr->cpaddr);
+
+	asm volatile ("STCK %0":"=m" (cqr->startclk));
+	rc = dia250 (iob, RW_BIO);
+	if (rc > 8) {
+		PRINT_WARN ("dia250 returned CC %d\n", rc);
+		check_then_set (&cqr->status,
+					       CQR_STATUS_QUEUED,
+					       CQR_STATUS_ERROR);
+	} else {
+		if (cqr->expires) {
+			cqr->expires += cqr->startclk;
+		}
+		check_then_set (&cqr->status,
+					       CQR_STATUS_QUEUED,
+					       CQR_STATUS_IN_IO);
+		rc = 0;
+	}
+	return rc;
+}
+
+void
+dasd_ext_handler (struct pt_regs *regs, __u16 code)
+{
+	ccw_req_t *cqr;
+	int ip = S390_lowcore.ext_params;
+	char status = *((char *) S390_lowcore.ext_params + 5);
+	dasd_device_t *device;
+	int done_fast_io = 0;
+	int devno;
+
+	if (!ip) {		/* no intparm: unsolicited interrupt */
+		printk (KERN_WARNING PRINTK_HEADER
+			"caught unsolicited interrupt\n");
+		return;
+	}
+	if (ip & 0x80000001) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"caught spurious interrupt with parm %08x\n",
+			ip);
+		return;
+	}
+	cqr = (ccw_req_t *) ip;
+	device = (dasd_device_t *) cqr->device;
+	devno = device->devinfo.devno;
+	if (device == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			" INT on devno 0x%04X  = /dev/%s (%d:%d)"
+			" belongs to NULL device\n",
+			devno, device->name, MAJOR (device->kdev), MINOR (device->kdev));
+	}
+	if (strncmp (device->discipline->ebcname, (char *) &cqr->magic, 4)) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"0x%04X : /dev/%s (%d:%d)"
+			" magic number of ccw_req_t 0x%08X doesn't match"
+			" discipline 0x%08X\n",
+			devno, device->name,
+			MAJOR (device->kdev), MINOR (device->kdev),
+			cqr->magic, *(int *) (&device->discipline->name));
+		return;
+	}
+	asm volatile ("STCK %0":"=m" (cqr->stopclk));
+	switch (status) {
+	case 0x00:
+		check_then_set (&cqr->status,
+					       CQR_STATUS_IN_IO,
+					       CQR_STATUS_DONE);
+		if ( device->level == DASD_DEVICE_LEVEL_ANALYSIS_PENDING)
+					device->level = DASD_DEVICE_LEVEL_ANALYSIS_PREPARED;
+		if (cqr->next &&
+		    (cqr->next->status == CQR_STATUS_QUEUED)) {
+			if (dasd_start_diag (cqr->next) == 0) {
+				done_fast_io = 1;
+			}
+		}
+		break;
+	case 0x01:
+	case 0x02:
+	case 0x03:
+	default:
+		check_then_set (&cqr->status,
+					       CQR_STATUS_IN_IO,
+					       CQR_STATUS_FAILED);
+		break;
+	}
+	wake_up (&device->wait_q);
+	dasd_schedule_bh (device);
+}
+
+static int
+dasd_diag_check_characteristics (struct dasd_device_t *device)
+{
+	int rc = 0;
+	int bsize;
+	int label_block;
+	dasd_diag_private_t *private;
+	dasd_diag_characteristics_t *rdc_data;
+	ccw_req_t *cqr;
+	long *label;
+	int sb;
+
+	if (device == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+		   "Null device pointer passed to characteristics checker\n");
+		return -ENODEV;
+	}
+	if (device->private == NULL) {
+                device->private = kmalloc (sizeof (dasd_diag_private_t), GFP_KERNEL);
+                if (device->private == NULL) {
+                        printk (KERN_WARNING PRINTK_HEADER
+                                "memory allocation failed for private data\n");
+                        return -ENOMEM;
+                }
+	}
+	private = (dasd_diag_private_t *) device->private;
+	rdc_data = (void *) &(private->rdc_data);
+        
+	rdc_data->dev_nr = device->devinfo.devno;
+	rdc_data->rdc_len = sizeof (dasd_diag_characteristics_t);
+        
+	if (dia210 (rdc_data) != 0) {
+                goto nodiag;
+	}
+	if (rdc_data->vdev_class != DEV_CLASS_FBA &&
+	    rdc_data->vdev_class != DEV_CLASS_ECKD &&
+	    rdc_data->vdev_class != DEV_CLASS_CKD) {
+                goto nodiag;
+	}
+#if 0
+	printk (KERN_INFO PRINTK_HEADER
+		"%04X: %04X on real %04X/%02X\n",
+		rdc_data->dev_nr,
+		rdc_data->vdev_type,
+		rdc_data->rdev_type, rdc_data->rdev_model);
+#endif
+	/* Figure out position of label block */
+	if (private->rdc_data.vdev_class == DEV_CLASS_FBA) {
+		label_block = 1;
+	} else if (private->rdc_data.vdev_class == DEV_CLASS_ECKD ||
+		   private->rdc_data.vdev_class == DEV_CLASS_CKD) {
+		label_block = 2;
+	} else {
+                goto nodiag;
+	}
+	private->label = (long *) get_free_page (GFP_KERNEL);
+	label = private->label;
+	mdsk_term_io (device);	/* first terminate all outstanding operations */
+	/* figure out blocksize of device */
+	for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
+		diag_bio_t *bio;
+		diag_rw_io_t *iob = &private->iob;
+                
+		rc = mdsk_init_io (device, bsize, 0, 64);
+		if (rc > 4) {
+			continue;
+		}
+		cqr = ccw_alloc_request (dasd_diag_discipline.name, sizeof(diag_bio_t)/sizeof(ccw1_t), 0);
+		if (cqr == NULL) {
+			printk (KERN_WARNING PRINTK_HEADER
+                                "No memory to allocate initialization request\n");
+                        free_page(private->label);
+                        kfree(private);
+                        device->private = NULL;
+                        return -ENOMEM;
+		}
+		bio = (diag_bio_t *) (cqr->cpaddr);
+		memset (bio, 0, sizeof (diag_bio_t));
+		bio->type = MDSK_READ_REQ;
+		bio->block_number = label_block + 1;
+		bio->buffer = __pa (private->label);
+		cqr->device = device;
+		cqr->status= CQR_STATUS_FILLED;
+		memset (iob, 0, sizeof (diag_rw_io_t));
+		iob->dev_nr = rdc_data->dev_nr;
+		iob->block_count = 1;
+		iob->interrupt_params = cqr;
+		iob->bio_list = __pa (bio);
+		rc = dia250 (iob, RW_BIO);
+		if (rc == 0) {
+			if (label[3] != bsize) {
+                                goto nodiag;
+			}
+			if (label[0] != 0xc3d4e2f1) {	/* != CMS1 */
+                                goto nodiag;
+			}
+			if (label[13] == 0) {
+                                goto nodiag;
+			}
+			break;
+		}
+		mdsk_term_io (device);
+	}
+        if ( bsize > PAGE_SIZE )
+                goto nodiag;
+	device->sizes.bp_block = bsize;
+	device->sizes.s2b_shift = 0;	/* bits to shift 512 to get a block */
+	for (sb = 512; sb < bsize; sb = sb << 1)
+		device->sizes.s2b_shift++;
+        goto good;
+ nodiag:
+        kfree(private);
+        device -> private = NULL;
+        rc = -ENODEV;
+ good:
+	return rc;
+}
+
+static int
+dasd_diag_do_analysis (struct dasd_device_t *device)
+{
+	int sb;
+	dasd_diag_private_t *private = (dasd_diag_private_t *) device->private;
+
+	long *label = private->label;
+
+	/* real size of the volume */
+	device->sizes.blocks = label[7];
+	printk (KERN_INFO PRINTK_HEADER
+		"/dev/%s (%04X): capacity (%dkB blks): %ldkB\n",
+		device->name, device->devinfo.devno,
+		(device->sizes.bp_block >> 10),
+		(device->sizes.blocks << device->sizes.s2b_shift) >> 1);
+        free_page(private->label);
+	return 0;
+}
+
+static int
+dasd_diag_fill_geometry (struct dasd_device_t *device, struct hd_geometry *geo)
+{
+	int rc = 0;
+	dasd_diag_private_t *private = (dasd_diag_private_t *) device->private;
+	unsigned long sectors = device->sizes.blocks << device->sizes.s2b_shift;
+	unsigned long tracks = sectors >> 6;
+	unsigned long trk_rem = sectors & ((1 << 6) - 1);	/* 64k per track */
+	unsigned long cyls = tracks >> 4;
+	unsigned long cyls_rem = tracks & ((1 << 4) - 1);	/* 16 head per cyl */
+
+	switch (device->sizes.bp_block) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		return -EINVAL;
+	}
+	geo->cylinders = cyls;
+	geo->heads = 16;
+	geo->sectors = 128 >> device->sizes.s2b_shift;
+	if (private->rdc_data.vdev_class == DEV_CLASS_FBA) {
+		geo->start = 1;
+	} else if (private->rdc_data.vdev_class == DEV_CLASS_ECKD ||
+		   private->rdc_data.vdev_class == DEV_CLASS_CKD) {
+		geo->start = 2;
+	} else {
+		return -EINVAL;
+	}
+	return rc;
+}
+
+static dasd_era_t
+dasd_diag_examine_error (ccw_req_t * cqr, devstat_t * stat)
+{
+	return dasd_era_fatal;
+}
+
+static dasd_erp_action_fn_t
+dasd_diag_erp_action (ccw_req_t * cqr)
+{
+	return default_erp_action;
+}
+
+static dasd_erp_postaction_fn_t
+dasd_diag_erp_postaction (ccw_req_t * cqr)
+{
+	if (cqr->function == default_erp_action)
+		return default_erp_postaction;
+	printk (KERN_WARNING PRINTK_HEADER
+		"unknown ERP action %p\n",
+		cqr->function);
+	return NULL;
+}
+
+static ccw_req_t *
+dasd_diag_build_cp_from_req (dasd_device_t * device, struct request *req)
+{
+	ccw_req_t *rw_cp = NULL;
+	struct buffer_head *bh;
+	int rw_cmd;
+	int noblk = req->nr_sectors >> device->sizes.s2b_shift;
+	int byt_per_blk = device->sizes.bp_block;
+	int block;
+	diag_bio_t *bio;
+	int bhct;
+	long size;
+
+	if (!noblk) {
+		PRINT_ERR ("No blocks to read/write...returning\n");
+		return NULL;
+	}
+	if (req->cmd == READ) {
+		rw_cmd = MDSK_READ_REQ;
+	} else if (req->cmd == WRITE) {
+		rw_cmd = MDSK_WRITE_REQ;
+	}
+	bhct = 0;
+	for (bh = req->bh; bh; bh = bh->b_reqnext) {
+		if (bh->b_size > byt_per_blk)
+			for (size = 0; size < bh->b_size; size += byt_per_blk)
+				bhct++;
+		else
+			bhct++;
+	}
+	/* Build the request */
+	rw_cp = dasd_alloc_request (dasd_diag_discipline.name, bhct << 1, 0);
+	if (!rw_cp) {
+		return NULL;
+	}
+	bio = (diag_bio_t *) (rw_cp->cpaddr);
+
+	block = req->sector >> device->sizes.s2b_shift;
+	for (bh = req->bh; bh; bh = bh->b_reqnext) {
+		if (bh->b_size >= byt_per_blk) {
+			memset (bio, 0, sizeof (diag_bio_t));
+			for (size = 0; size < bh->b_size; size += byt_per_blk) {
+				bio->type = rw_cmd;
+				bio->block_number = block + 1;
+				bio->buffer = __pa (bh->b_data + size);
+				bio++;
+				block++;
+			}
+		} else {
+			PRINT_WARN ("Cannot fulfill request smaller than block\n");
+			ccw_free_request (rw_cp);
+			return NULL;
+		}
+	}
+	rw_cp->device = device;
+	rw_cp->expires = 5 * 0xf424000;		/* 5 seconds */
+	rw_cp->req = req;
+	check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED);
+	return rw_cp;
+}
+
+static char *
+dasd_diag_dump_sense (struct dasd_device_t *device, ccw_req_t * req)
+{
+	char *page = (char *) get_free_page (GFP_KERNEL);
+	int len;
+	if (page == NULL) {
+		return NULL;
+	}
+	len = sprintf (page, KERN_WARNING PRINTK_HEADER
+		       "device %04X on irq %d: I/O status report:\n",
+		       device->devinfo.devno, device->devinfo.irq);
+
+	return page;
+}
+
+dasd_discipline_t dasd_diag_discipline =
+{
+	name:"DIAG",
+	ebcname:"DIAG",
+	check_characteristics:dasd_diag_check_characteristics,
+	do_analysis:dasd_diag_do_analysis,
+	fill_geometry:dasd_diag_fill_geometry,
+	start_IO:dasd_start_diag,
+	examine_error:dasd_diag_examine_error,
+	erp_action:dasd_diag_erp_action,
+	erp_postaction:dasd_diag_erp_postaction,
+	build_cp_from_req:dasd_diag_build_cp_from_req,
+	dump_sense:dasd_diag_dump_sense,
+	int_handler:dasd_ext_handler
+};
+
+int
+dasd_diag_init (void)
+{
+	int rc = 0;
+	if (MACHINE_IS_VM) {
+		printk (KERN_INFO PRINTK_HEADER
+		   "%s discipline initializing\n", dasd_diag_discipline.name);
+		ASCEBC (dasd_diag_discipline.ebcname, 4);
+		ctl_set_bit (0, 9);
+		register_external_interrupt (0x2603, dasd_ext_handler);
+		dasd_discipline_enq (&dasd_diag_discipline);
+	} else {
+		printk (KERN_INFO PRINTK_HEADER
+			"Machine is not VM: %s discipline not initializing\n", dasd_diag_discipline.name);
+		rc = -EINVAL;
+	}
+	return rc;
+}
+
+void
+dasd_diag_cleanup( void ) {
+        if ( MACHINE_IS_VM ) {
+          printk ( KERN_INFO PRINTK_HEADER
+                   "%s discipline cleaning up\n", dasd_diag_discipline.name);
+          dasd_discipline_deq(&dasd_diag_discipline);
+          unregister_external_interrupt (0x2603, dasd_ext_handler);
+          ctl_clear_bit (0, 9);
+        } else {
+          printk ( KERN_INFO PRINTK_HEADER
+                   "Machine is not VM: %s discipline not initializing\n", dasd_diag_discipline.name);
+        }
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_diag.h linux/drivers/s390/block/dasd_diag.h
--- v2.4.1/linux/drivers/s390/block/dasd_diag.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_diag.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,75 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd_diag.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Based on.......: linux/drivers/s390/block/mdisk.h
+ * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ */
+
+#define MDSK_WRITE_REQ 0x01
+#define MDSK_READ_REQ  0x02
+
+#define INIT_BIO        0x00
+#define RW_BIO          0x01
+#define TERM_BIO        0x02
+
+#define DEV_CLASS_FBA   0x01
+#define DEV_CLASS_ECKD  0x04
+#define DEV_CLASS_CKD   0x04
+
+typedef struct dasd_diag_characteristics_t {
+	u16 dev_nr;
+	u16 rdc_len;
+	u8 vdev_class;
+	u8 vdev_type;
+	u8 vdev_status;
+	u8 vdev_flags;
+	u8 rdev_class;
+	u8 rdev_type;
+	u8 rdev_model;
+	u8 rdev_features;
+} __attribute__             ((packed, aligned (4))) 
+
+dasd_diag_characteristics_t;
+
+typedef struct diag_bio_t {
+	u8 type;
+	u8 status;
+	u16 spare1;
+	u32 block_number;
+	u32 alet;
+	u32 buffer;
+} __attribute__ ((packed, aligned (8))) 
+
+diag_bio_t;
+
+typedef struct diag_init_io_t {
+	u16 dev_nr;
+	u16 spare1[11];
+	u32 block_size;
+	u32 offset;
+	u32 start_block;
+	u32 end_block;
+	u32 spare2[6];
+} __attribute__ ((packed, aligned (8))) 
+
+diag_init_io_t;
+
+typedef struct diag_rw_io_t {
+	u16 dev_nr;
+	u16 spare1[11];
+	u8 key;
+	u8 flags;
+	u16 spare2;
+	u32 block_count;
+	u32 alet;
+	u32 bio_list;
+	u32 interrupt_params;
+	u32 spare3[5];
+} __attribute__ ((packed, aligned (8))) 
+
+diag_rw_io_t;
+
+int dasd_diag_init (void);
+void dasd_diag_cleanup(void);
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_eckd.c linux/drivers/s390/block/dasd_eckd.c
--- v2.4.1/linux/drivers/s390/block/dasd_eckd.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_eckd.c	Tue Feb 13 14:13:44 2001
@@ -3,289 +3,129 @@
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+
+ * History of changes (starts July 2000)
+ * 07/11/00 Enabled rotational position sensing
+ * 07/14/00 Reorganized the format process for better ERP
+ * 07/20/00 added experimental support for 2105 control unit (ESS)
+ * 07/24/00 increased expiration time and added the missing zero
+ * 08/07/00 added some bits to define_extent for ESS support
+ * 09/20/00 added reserve and release ioctls
+ * 10/04/00 changed RW-CCWS to R/W Key and Data
+ * 10/10/00 reverted last change according to ESS exploitation
+ * 10/10/00 now dequeuing init_cqr before freeing *ouch*
+ * 26/10/00 fixed ITPM20144ASC (problems when accesing a device formatted by VIF)
  */
 
+#include <linux/config.h>
 #include <linux/stddef.h>
 #include <linux/kernel.h>
-
-#ifdef MODULE
-#include <linux/module.h>
-#endif				/* MODULE */
+#include <asm/debug.h>
 
 #include <linux/malloc.h>
-#include <linux/dasd.h>
-#include <asm/io.h>
+#include <linux/hdreg.h>	/* HDIO_GETGEO                      */
+#include <linux/blk.h>
+#include <asm/ccwcache.h>
+#include <asm/idals.h>
+#include <asm/dasd.h>
 
+#include <asm/ebcdic.h>
+#include <asm/io.h>
 #include <asm/irq.h>
+#include <asm/s390dyn.h>
 
-#include "dasd_types.h"
-#include "dasd_ccwstuff.h"
-
+#include "dasd_eckd.h"
 
 #ifdef PRINTK_HEADER
 #undef PRINTK_HEADER
 #endif				/* PRINTK_HEADER */
-#define PRINTK_HEADER "dasd(eckd):"
+#define PRINTK_HEADER DASD_NAME"(eckd): "
 
 #define ECKD_C0(i) (i->home_bytes)
-#define ECKD_F(i) (i -> formula)
+#define ECKD_F(i) (i->formula)
 #define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):(i->factors.f_0x02.f1))
 #define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):(i->factors.f_0x02.f2))
 #define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):(i->factors.f_0x02.f3))
 #define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0)
 #define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0)
-#define ECKD_F6(i) (i -> factor6)
-#define ECKD_F7(i) (i -> factor7)
-#define ECKD_F8(i) (i -> factor8)
+#define ECKD_F6(i) (i->factor6)
+#define ECKD_F7(i) (i->factor7)
+#define ECKD_F8(i) (i->factor8)
 
-#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
-
-#define DASD_ECKD_CCW_READ_HOME_ADDRESS 0x0a
+#define DASD_ECKD_CCW_WRITE 0x05
+#define DASD_ECKD_CCW_READ 0x06
 #define DASD_ECKD_CCW_WRITE_HOME_ADDRESS 0x09
-
-#define DASD_ECKD_CCW_READ_RECORD_ZERO 0x16
-#define DASD_ECKD_CCW_WRITE_RECORD_ZERO 0x15
-
+#define DASD_ECKD_CCW_READ_HOME_ADDRESS 0x0a
+#define DASD_ECKD_CCW_WRITE_KD 0x0d
+#define DASD_ECKD_CCW_READ_KD 0x0e
 #define DASD_ECKD_CCW_READ_COUNT 0x12
-#define DASD_ECKD_CCW_READ 0x06
-#define DASD_ECKD_CCW_READ_MT 0x86
-#define DASD_ECKD_CCW_WRITE 0x05
-#define DASD_ECKD_CCW_WRITE_MT 0x85
+#define DASD_ECKD_CCW_WRITE_RECORD_ZERO 0x15
+#define DASD_ECKD_CCW_READ_RECORD_ZERO 0x16
+#define DASD_ECKD_CCW_WRITE_CKD 0x1d
 #define DASD_ECKD_CCW_READ_CKD 0x1e
+#define DASD_ECKD_CCW_LOCATE_RECORD 0x47
+#define DASD_ECKD_CCW_DEFINE_EXTENT 0x63
+#define DASD_ECKD_CCW_WRITE_MT 0x85
+#define DASD_ECKD_CCW_READ_MT 0x86
+#define DASD_ECKD_CCW_WRITE_KD_MT 0x8d
+#define DASD_ECKD_CCW_READ_KD_MT 0x8e
+#define DASD_ECKD_CCW_RELEASE 0x94
 #define DASD_ECKD_CCW_READ_CKD_MT 0x9e
-#define DASD_ECKD_CCW_WRITE_CKD 0x1d
 #define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d
+#define DASD_ECKD_CCW_RESERVE 0xB4
 
-typedef
-struct {
-	__u16 cyl;
-	__u16 head;
-} __attribute__ ((packed))
-
-ch_t;
-
-typedef
-struct {
-	__u16 cyl;
-	__u16 head;
-	__u32 sector;
-} __attribute__ ((packed))
-
-chs_t;
-
-typedef
-struct {
-	__u16 cyl;
-	__u16 head;
-	__u8 record;
-} __attribute__ ((packed))
-
-chr_t;
-
-typedef
-struct {
-	__u16 cyl;
-	__u16 head;
-	__u32 sector;
-} geom_t;
-
-typedef struct {
-	struct {
-		struct {
-			unsigned char identifier:2;
-			unsigned char token_id:1;
-			unsigned char sno_valid:1;
-			unsigned char subst_sno:1;
-			unsigned char recNED:1;
-			unsigned char emuNED:1;
-			unsigned char reserved:1;
-		} __attribute__ ((packed)) flags;
-		__u8 descriptor;
-		__u8 dev_class;
-		__u8 reserved;
-		unsigned char dev_type[6];
-		unsigned char dev_model[3];
-		unsigned char HDA_manufacturer[3];
-		unsigned char HDA_location[2];
-		unsigned char HDA_seqno[12];
-		__u16 ID;
-	} __attribute__ ((packed)) ned1;
-	struct {
-		struct {
-			unsigned char identifier:2;
-			unsigned char token_id:1;
-			unsigned char sno_valid:1;
-			unsigned char subst_sno:1;
-			unsigned char recNED:1;
-			unsigned char emuNED:1;
-			unsigned char reserved:1;
-		} __attribute__ ((packed)) flags;
-		__u8 descriptor;
-		__u8 reserved[2];
-		unsigned char dev_type[6];
-		unsigned char dev_model[3];
-		unsigned char DASD_manufacturer[3];
-		unsigned char DASD_location[2];
-		unsigned char DASD_seqno[12];
-		__u16 ID;
-	} __attribute__ ((packed)) ned2;
-	struct {
-		struct {
-			unsigned char identifier:2;
-			unsigned char token_id:1;
-			unsigned char sno_valid:1;
-			unsigned char subst_sno:1;
-			unsigned char recNED:1;
-			unsigned char emuNED:1;
-			unsigned char reserved:1;
-		} __attribute__ ((packed)) flags;
-		__u8 descriptor;
-		__u8 reserved[2];
-		unsigned char cont_type[6];
-		unsigned char cont_model[3];
-		unsigned char cont_manufacturer[3];
-		unsigned char cont_location[2];
-		unsigned char cont_seqno[12];
-		__u16 ID;
-	} __attribute__ ((packed)) ned3;
-	struct {
-		struct {
-			unsigned char identifier:2;
-			unsigned char token_id:1;
-			unsigned char sno_valid:1;
-			unsigned char subst_sno:1;
-			unsigned char recNED:1;
-			unsigned char emuNED:1;
-			unsigned char reserved:1;
-		} __attribute__ ((packed)) flags;
-		__u8 descriptor;
-		__u8 reserved[2];
-		unsigned char cont_type[6];
-		unsigned char empty[3];
-		unsigned char cont_manufacturer[3];
-		unsigned char cont_location[2];
-		unsigned char cont_seqno[12];
-		__u16 ID;
-	} __attribute__ ((packed)) ned4;
-	unsigned char ned5[32];
-	unsigned char ned6[32];
-	unsigned char ned7[32];
-	struct {
-		struct {
-			unsigned char identifier:2;
-			unsigned char reserved:6;
-		} __attribute__ ((packed)) flags;
-		__u8 selector;
-		__u16 interfaceID;
-		__u32 reserved;
-		__u16 subsystemID;
-		struct {
-			unsigned char sp0:1;
-			unsigned char sp1:1;
-			unsigned char reserved:5;
-			unsigned char scluster:1;
-		} __attribute__ ((packed)) spathID;
-		__u8 unit_address;
-		__u8 dev_ID;
-		__u8 dev_address;
-		__u8 adapterID;
-		__u16 link_address;
-		struct {
-			unsigned char parallel:1;
-			unsigned char escon:1;
-			unsigned char reserved:1;
-			unsigned char ficon:1;
-			unsigned char reserved2:4;
-		} __attribute__ ((packed)) protocol_type;
-		struct {
-			unsigned char PID_in_236:1;
-			unsigned char reserved:7;
-		} __attribute__ ((packed)) format_flags;
-		__u8 log_dev_address;
-		unsigned char reserved2[12];
-	} __attribute__ ((packed)) neq;
-
-} __attribute__ ((packed))
-
-eckd_confdata_t;
-
-typedef
-struct {
-	struct {
-		unsigned char perm:2;	/* Permissions on this extent */
-		unsigned char reserved:1;
-		unsigned char seek:2;	/* Seek control */
-		unsigned char auth:2;	/* Access authorization */
-		unsigned char pci:1;	/* PCI Fetch mode */
-	} __attribute__ ((packed)) mask;
-	struct {
-		unsigned char mode:2;	/* Architecture mode */
-		unsigned char ckd:1;	/* CKD Conversion */
-		unsigned char operation:3;	/* Operation mode */
-		unsigned char cfw:1;	/* Cache fast write */
-		unsigned char dfw:1;	/* DASD fast write */
-	} __attribute__ ((packed)) attributes;
-	__u16 short blk_size;	/* Blocksize */
-	__u16 fast_write_id;
-	__u8 unused;
-	__u8 reserved;
-	ch_t beg_ext;
-	ch_t end_ext;
-} __attribute__ ((packed, aligned (32)))
-
-DE_eckd_data_t;
-
-typedef
-struct {
-	struct {
-		unsigned char orientation:2;
-		unsigned char operation:6;
-	} __attribute__ ((packed)) operation;
-	struct {
-		unsigned char last_bytes_used:1;
-		unsigned char reserved:6;
-		unsigned char read_count_suffix:1;
-	} __attribute__ ((packed)) auxiliary;
-	__u8 unused;
-	__u8 count;
-	ch_t seek_addr;
-	chr_t search_arg;
-	__u8 sector;
-	__u16 length;
-} __attribute__ ((packed, aligned (32)))
-
-LO_eckd_data_t;
-
-/* Stuff for handling home addresses */
-typedef struct {
-	__u8 skip_control[14];
-	__u16 cell_number;
-	__u8 physical_addr[3];
-	__u8 flag;
-	ch_t track_addr;
-	__u8 reserved;
-	__u8 key_length;
-	__u8 reserved2[2];
-} __attribute__ ((packed, aligned (32)))
+dasd_discipline_t dasd_eckd_discipline;
 
-eckd_home_t;
+typedef struct
+dasd_eckd_private_t {
+	dasd_eckd_characteristics_t rdc_data;
+	dasd_eckd_confdata_t conf_data;
+	eckd_count_t count_area;
+	ccw_req_t *init_cqr;
+} dasd_eckd_private_t;
 
+#ifdef CONFIG_DASD_DYNAMIC
+static
+devreg_t dasd_eckd_known_devices[] =
+{
+	{
+		ci:
+		{hc:
+		 {ctype:0x3990, dtype:0x3390}},
+		flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+		oper_func:dasd_oper_handler
+	},
+	{
+		ci:
+		{hc:
+		 {ctype:0x3990, dtype:0x3380}},
+		flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+		oper_func:dasd_oper_handler
+	},
+	{
+		ci:
+		{hc:
+		 {ctype:0x9343, dtype:0x9345}},
+		flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+		oper_func:dasd_oper_handler
+	}
+};
+#endif
 
-static unsigned int
+static inline unsigned int
 round_up_multiple (unsigned int no, unsigned int mult)
 {
 	int rem = no % mult;
 	return (rem ? no - rem + mult : no);
-/*      return (no % mult ? no - (no % mult) + mult : no); */
 }
 
-static unsigned int
+static inline unsigned int
 ceil_quot (unsigned int d1, unsigned int d2)
 {
 	return (d1 + (d2 - 1)) / d2;
 }
 
-static int
+static inline int
 bytes_per_record (dasd_eckd_characteristics_t * rdc,
 		  int kl,	/* key length */
 		  int dl /* data length */ )
@@ -332,21 +172,21 @@
 	return *(unsigned int *) (rdc->byte_per_track) >> 8;
 }
 
-static unsigned int
+static inline unsigned int
 recs_per_track (dasd_eckd_characteristics_t * rdc,
 		unsigned int kl, unsigned int dl)
 {
 	int rpt = 0;
 	int dn;
-        switch ( rdc -> dev_type ) {
-	case 0x3380: 
+	switch (rdc->dev_type) {
+	case 0x3380:
 		if (kl)
 			return 1499 / (15 +
 				       7 + ceil_quot (kl + 12, 32) +
 				       ceil_quot (dl + 12, 32));
 		else
 			return 1499 / (15 + ceil_quot (dl + 12, 32));
-	case 0x3390: 
+	case 0x3390:
 		dn = ceil_quot (dl + 6, 232) + 1;
 		if (kl) {
 			int kn = ceil_quot (kl + 6, 232) + 1;
@@ -356,42 +196,42 @@
 		} else
 			return 1729 / (10 +
 				       9 + ceil_quot (dl + 6 * dn, 34));
-	case 0x9345: 
-	        dn = ceil_quot (dl + 6, 232) + 1;
-                if (kl) {
-                        int kn = ceil_quot (kl + 6, 232) + 1;
-                        return 1420 / (18 +
-                                       7 + ceil_quot (kl + 6 * kn, 34) +
-                                       ceil_quot (dl + 6 * dn, 34));
-                } else
-                        return 1420 / (18 +
-                                       7 + ceil_quot (dl + 6 * dn, 34));
+	case 0x9345:
+		dn = ceil_quot (dl + 6, 232) + 1;
+		if (kl) {
+			int kn = ceil_quot (kl + 6, 232) + 1;
+			return 1420 / (18 +
+				       7 + ceil_quot (kl + 6 * kn, 34) +
+				       ceil_quot (dl + 6 * dn, 34));
+		} else
+			return 1420 / (18 +
+				       7 + ceil_quot (dl + 6 * dn, 34));
 	}
 	return rpt;
 }
 
-static
-void
+static inline void
 define_extent (ccw1_t * de_ccw,
 	       DE_eckd_data_t * data,
 	       int trk,
 	       int totrk,
 	       int cmd,
-	       dasd_information_t * info)
+	       dasd_device_t * device)
 {
 	ch_t geo, beg, end;
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
 
-	geo.cyl = info->rdc_data->eckd.no_cyl;
-	geo.head = info->rdc_data->eckd.trk_per_cyl;
+	geo.cyl = private->rdc_data.no_cyl;
+	geo.head = private->rdc_data.trk_per_cyl;
 	beg.cyl = trk / geo.head;
 	beg.head = trk % geo.head;
 	end.cyl = totrk / geo.head;
 	end.head = totrk % geo.head;
 
 	memset (de_ccw, 0, sizeof (ccw1_t));
-	de_ccw->cmd_code = CCW_DEFINE_EXTENT;
+	de_ccw->cmd_code = DASD_ECKD_CCW_DEFINE_EXTENT;
 	de_ccw->count = 16;
-	de_ccw->cda = (void *) virt_to_phys (data);
+	set_normalized_cda (de_ccw, __pa (data));
 
 	memset (data, 0, sizeof (DE_eckd_data_t));
 	switch (cmd) {
@@ -401,13 +241,18 @@
 	case DASD_ECKD_CCW_READ_MT:
 	case DASD_ECKD_CCW_READ_CKD:	/* Fallthrough */
 	case DASD_ECKD_CCW_READ_CKD_MT:
+	case DASD_ECKD_CCW_READ_KD:
+	case DASD_ECKD_CCW_READ_KD_MT:
 	case DASD_ECKD_CCW_READ_COUNT:
 		data->mask.perm = 0x1;
-                data->attributes.operation = 0x3; /* enable seq. caching */
+		data->attributes.operation = 0x3;	/* enable seq. caching */
 		break;
 	case DASD_ECKD_CCW_WRITE:
 	case DASD_ECKD_CCW_WRITE_MT:
-                data->attributes.operation = 0x3; /* enable seq. caching */
+	case DASD_ECKD_CCW_WRITE_KD:
+	case DASD_ECKD_CCW_WRITE_KD_MT:
+		data->mask.perm = 0x02;
+		data->attributes.operation = 0x3;	/* enable seq. caching */
 		break;
 	case DASD_ECKD_CCW_WRITE_CKD:
 	case DASD_ECKD_CCW_WRITE_CKD_MT:
@@ -424,6 +269,9 @@
 		break;
 	}
 	data->attributes.mode = 0x3;
+	if (private->rdc_data.cu_type == 0x2105) {
+		data->reserved |= 0x40;
+	}
 	data->beg_ext.cyl = beg.cyl;
 	data->beg_ext.head = beg.head;
 	data->end_ext.cyl = end.cyl;
@@ -437,18 +285,21 @@
 	       int rec_on_trk,
 	       int no_rec,
 	       int cmd,
-	       dasd_information_t * info)
+	       dasd_device_t * device,
+	       int reclen)
 {
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
 	ch_t geo =
-	{info->rdc_data->eckd.no_cyl,
-	 info->rdc_data->eckd.trk_per_cyl};
+	{private->rdc_data.no_cyl,
+	 private->rdc_data.trk_per_cyl};
 	ch_t seek =
 	{trk / (geo.head), trk % (geo.head)};
-	int reclen = info->sizes.bp_block;
+	int sector;
+
 	memset (lo_ccw, 0, sizeof (ccw1_t));
 	lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD;
 	lo_ccw->count = 16;
-	lo_ccw->cda = (void *) virt_to_phys (data);
+	set_normalized_cda (lo_ccw, __pa (data));
 
 	memset (data, 0, sizeof (LO_eckd_data_t));
 	switch (cmd) {
@@ -461,7 +312,7 @@
 		data->operation.operation = 0x16;
 		break;
 	case DASD_ECKD_CCW_WRITE_RECORD_ZERO:
-		data->operation.orientation = 0x3;
+		data->operation.orientation = 0x1;
 		data->operation.operation = 0x03;
 		data->count++;
 		break;
@@ -472,6 +323,8 @@
 		break;
 	case DASD_ECKD_CCW_WRITE:
 	case DASD_ECKD_CCW_WRITE_MT:
+	case DASD_ECKD_CCW_WRITE_KD:
+	case DASD_ECKD_CCW_WRITE_KD_MT:
 		data->auxiliary.last_bytes_used = 0x1;
 		data->length = reclen;
 		data->operation.operation = 0x01;
@@ -484,6 +337,8 @@
 		break;
 	case DASD_ECKD_CCW_READ:
 	case DASD_ECKD_CCW_READ_MT:
+	case DASD_ECKD_CCW_READ_KD:
+	case DASD_ECKD_CCW_READ_KD_MT:
 		data->auxiliary.last_bytes_used = 0x1;
 		data->length = reclen;
 		data->operation.operation = 0x06;
@@ -496,462 +351,789 @@
 		break;
 	case DASD_ECKD_CCW_READ_COUNT:
 		data->operation.operation = 0x06;
-                break;
+		break;
 	default:
 		INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd);
 	}
+	switch (private->rdc_data.dev_type) {
+	case 0x3390:{
+			int dn, d;
+			dn = ceil_quot (reclen + 6, 232);
+			d = 9 + ceil_quot (reclen + 6 * (dn + 1), 34);
+			sector = (49 + (rec_on_trk - 1) * (10 + d)) / 8;
+			break;
+		}
+	case 0x3380:{
+			int d;
+			d = 7 + ceil_quot (reclen + 12, 32);
+			sector = (39 + (rec_on_trk - 1) * (8 + d)) / 7;
+			break;
+		}
+	case 0x9345:
+	default:
+		sector = 0;
+	}
+	data->sector = sector;
 	memcpy (&(data->seek_addr), &seek, sizeof (ch_t));
 	memcpy (&(data->search_arg), &seek, sizeof (ch_t));
 	data->search_arg.record = rec_on_trk;
 	data->count += no_rec;
 }
 
-void
-dasd_eckd_print_error (devstat_t * stat)
+static int
+dasd_eckd_id_check (s390_dev_info_t * info)
 {
-	int sct, sl;
-	char *sense = stat->ii.sense.data;
-	PRINT_WARN ("IRQ on devno %x: with intparm:%x DS:0x%02x CS:0x%02x\n",
-		    stat->devno, stat->intparm, stat->dstat, stat->cstat);
-	PRINT_WARN ("Failing CCW: %p\n", (ccw1_t *) stat->cpa);
-	for (sl = 0; sl < 4; sl++) {
-		PRINT_DEBUG ("Sense:");
-		for (sct = 0; sct < 8; sct++) {
-			printk (" %2d:0x%02x",
-				8 * sl + sct, sense[8 * sl + sct]);
-		}
-		printk ("\n");
-	}
-	if (sense[27] & 0x80) {	/* 32 Byte Sense Data */
-		PRINT_INFO ("Sense Data is 32 Byte information\n");
-		PRINT_INFO ("Format: %x Exception class %x\n",
-			    sense[6] & 0x0f, sense[22] >> 4);
-	} else {		/* 24 Byte Sense Data */
-		PRINT_INFO ("Sense Data is 24 Byte information\n");
-		PRINT_INFO ("FMT: %x MSG %x, %s MSGb to SYSOP\n",
-			    sense[7] >> 4, sense[7] & 0x0f,
-			    sense[1] & 0x10 ? "" : "no");
+	if (info->sid_data.cu_type == 0x3990 ||
+	    info->sid_data.cu_type == 0x2105)
+		if (info->sid_data.dev_type == 0x3390)
+			return 0;
+	if (info->sid_data.cu_type == 0x3990 ||
+	    info->sid_data.cu_type == 0x2105)
+		if (info->sid_data.dev_type == 0x3380)
+			return 0;
+	if (info->sid_data.cu_type == 0x9343)
+		if (info->sid_data.dev_type == 0x9345)
+			return 0;
+	return -ENODEV;
+}
+
+static int
+dasd_eckd_check_characteristics (struct dasd_device_t *device)
+{
+	int rc = -ENODEV;
+	void *conf_data;
+	void *rdc_data;
+	int conf_len;
+	dasd_eckd_private_t *private;
+
+	if (device == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+		   "Null device pointer passed to characteristics checker\n");
+		return -ENODEV;
+	}
+        if (device->private == NULL) {
+                device->private = kmalloc (sizeof (dasd_eckd_private_t), GFP_KERNEL);
+                if (device->private == NULL) {
+                        printk (KERN_WARNING PRINTK_HEADER
+                                "memory allocation failed for private data\n");
+                        return -ENOMEM;
+                }
+        }
+	private = (dasd_eckd_private_t *) device->private;
+	rdc_data = (void *) &(private->rdc_data);
+	rc = read_dev_chars (device->devinfo.irq, &rdc_data, 64);
+	if (rc) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"Read device characteristics returned error %d\n", rc);
+		return rc;
 	}
+	printk (KERN_INFO PRINTK_HEADER
+	    "%04X on sch %d: %04X/%02X(CU:%04X/%02X) Cyl:%d Head:%d Sec:%d\n",
+		device->devinfo.devno, device->devinfo.irq,
+		private->rdc_data.dev_type, private->rdc_data.dev_model,
+		private->rdc_data.cu_type, private->rdc_data.cu_model.model,
+		private->rdc_data.no_cyl, private->rdc_data.trk_per_cyl,
+		private->rdc_data.sec_per_trk);
+	rc = 0 ? 0 : read_conf_data (device->devinfo.irq, &conf_data, &conf_len, LPM_ANYPATH);
+	if (rc) {
+		if (rc == -EOPNOTSUPP)
+			return 0;
+		printk (KERN_WARNING PRINTK_HEADER
+			"Read configuration data returned error %d\n", rc);
+		return rc;
+	}
+	if (conf_len != sizeof (dasd_eckd_confdata_t)) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"sizes of configuration data mismatch %d (read) vs %ld (expected)\n",
+			conf_len, sizeof (dasd_eckd_confdata_t));
+		return rc;
+	}
+	if (conf_data == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No configuration data retrieved\n");
+		return -ENOMEM;
+	}
+	memcpy (&private->conf_data, conf_data, sizeof (dasd_eckd_confdata_t));
+	printk (KERN_INFO PRINTK_HEADER
+                "%04X on sch %d: %04X/%02X(CU:%04X/%02X): Configuration data read\n",
+		device->devinfo.devno, device->devinfo.irq,
+		private->rdc_data.dev_type, private->rdc_data.dev_model,
+		private->rdc_data.cu_type, private->rdc_data.cu_model.model);
+	device->sizes.bp_block = 4096;
+	device->sizes.s2b_shift = 3;
+	device->sizes.blocks = (private->rdc_data.no_cyl *
+				private->rdc_data.trk_per_cyl *
+				recs_per_track (&private->rdc_data,
+						0, device->sizes.bp_block));
+	return 0;
 }
 
-int
-dasd_eckd_format_track (int di, int trk, int bs)
+static ccw_req_t *
+dasd_eckd_init_analysis (struct dasd_device_t *device)
 {
-	int rc = 0;
-	int i;
-	int flags = 0x00;	/* FORMAT_R0 = 0x01, FORMAT_HA = 0x03 */
-        dasd_information_t * info=dasd_info[di];
-	cqr_t *fcp;
+	ccw_req_t *cqr = NULL;
+	ccw1_t *ccw;
 	DE_eckd_data_t *DE_data;
 	LO_eckd_data_t *LO_data;
-	eckd_count_t *ct_data;
-	eckd_count_t *r0_data;
-	ccw1_t *last_ccw;
-        int retries = 5;
-
-	int rpt = recs_per_track (&(info->rdc_data->eckd), 0, bs);
-	int cyl = trk / info->rdc_data->eckd.trk_per_cyl;
-	int head = trk % info->rdc_data->eckd.trk_per_cyl;
-
-	fcp = request_cqr (2 + 1 + rpt,
-			   sizeof (DE_eckd_data_t) +
-			   sizeof (LO_eckd_data_t) +
-			   (rpt + 1) * sizeof (eckd_count_t));
-        fcp -> devindex=di;
-	DE_data = (DE_eckd_data_t *) fcp->data;
-	LO_data = (LO_eckd_data_t *) (((long) DE_data) +
-				      sizeof (DE_eckd_data_t));
-	r0_data = (eckd_count_t *) (((long) LO_data) +
-				    sizeof (LO_eckd_data_t));
-	ct_data = (eckd_count_t *) (((long) r0_data) +
-				    sizeof (eckd_count_t));
-	last_ccw = fcp->cpaddr;
-	switch (flags) {
-	case 0x03:
-		define_extent (last_ccw, DE_data, trk, trk,
-			       DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info);
-		last_ccw->flags = CCW_FLAG_CC;
-		last_ccw++;
-		locate_record (last_ccw, LO_data, trk, 0, rpt,
-			       DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info);
-		last_ccw->flags = CCW_FLAG_CC;
-		last_ccw++;
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	eckd_count_t *count_data = &(private->count_area);
+
+	cqr = ccw_alloc_request (dasd_eckd_discipline.name, 3 + 1, sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t));
+	if (cqr == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No memory to allocate initialization request\n");
+		return NULL;
+	} else {
+		private->init_cqr = cqr;
+	}
+	DE_data = cqr->data;
+	LO_data = cqr->data + sizeof (DE_eckd_data_t);
+	ccw = cqr->cpaddr;
+	define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, device);
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	locate_record (ccw, LO_data, 0, 0, 1, DASD_ECKD_CCW_READ_COUNT, device, 0);
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
+	ccw->count = 8;
+	set_normalized_cda (ccw, __pa (count_data));
+	cqr->device = device;
+	cqr->retries = 0;
+	cqr->status = CQR_STATUS_FILLED;
+
+	return cqr;
+}
+
+static int
+dasd_eckd_do_analysis (struct dasd_device_t *device)
+{
+	int rc = 0;
+	int sb, rpt;
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	int bs = private->count_area.dl;
+
+	dasd_chanq_deq (&device->queue, private->init_cqr);
+	ccw_free_request (private->init_cqr);
+	private->init_cqr = NULL;
+	memset (&(device->sizes), 0, sizeof (dasd_sizes_t));
+	switch (bs) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		device->sizes.bp_block = bs;
 		break;
-	case 0x01:
-		define_extent (last_ccw, DE_data, trk, trk,
-			       DASD_ECKD_CCW_WRITE_RECORD_ZERO, info);
-		last_ccw->flags = CCW_FLAG_CC;
-		last_ccw++;
-		locate_record (last_ccw, LO_data, trk, 0, rpt,
-			       DASD_ECKD_CCW_WRITE_RECORD_ZERO, info);
-		last_ccw->flags = CCW_FLAG_CC;
-		last_ccw++;
+	default:
+		printk (KERN_INFO PRINTK_HEADER
+			"/dev/%s (%04X): invalid blocksize %d\n"
+			KERN_INFO PRINTK_HEADER
+		 "/dev/%s (%04X): capacity (at 4kB blks): %dkB at %dkB/trk\n",
+			device->name, device->devinfo.devno, bs,
+			device->name, device->devinfo.devno,
+		   (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl *
+		    recs_per_track (&private->rdc_data, 0, 4096)),
+			recs_per_track (&private->rdc_data, 0, 4096));
+		return -EMEDIUMTYPE;
+	}
+	device->sizes.s2b_shift = 0;	/* bits to shift 512 to get a block */
+	for (sb = 512; sb < bs; sb = sb << 1)
+		device->sizes.s2b_shift++;
+
+	rpt = recs_per_track (&private->rdc_data, 0, device->sizes.bp_block);
+	device->sizes.blocks = (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl *
+	      recs_per_track (&private->rdc_data, 0, device->sizes.bp_block));
+
+	printk (KERN_INFO PRINTK_HEADER
+		"/dev/%s (%04X): capacity (%dkB blks): %dkB at %dkB/trk\n",
+		device->name, device->devinfo.devno,
+		(device->sizes.bp_block >> 10),
+		(private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl *
+	      recs_per_track (&private->rdc_data, 0, device->sizes.bp_block) *
+		 (device->sizes.bp_block >> 9)) >> 1,
+		(recs_per_track (&private->rdc_data, 0, device->sizes.bp_block) * device->sizes.bp_block) >> 10);
+	return 0;
+
+	return rc;
+}
+
+static int
+dasd_eckd_fill_geometry (struct dasd_device_t *device, struct hd_geometry *geo)
+{
+	int rc = 0;
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	switch (device->sizes.bp_block) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		return -EINVAL;
+	}
+	geo->cylinders = private->rdc_data.no_cyl;
+	geo->heads = private->rdc_data.trk_per_cyl;
+	geo->sectors = recs_per_track (&(private->rdc_data), 0, device->sizes.bp_block);
+	geo->start = 2;
+	return rc;
+}
+
+static ccw_req_t *
+dasd_eckd_format_device (dasd_device_t * device, format_data_t * fdata)
+{
+	int i;
+	ccw_req_t *fcp = NULL;
+	DE_eckd_data_t *DE_data = NULL;
+	LO_eckd_data_t *LO_data = NULL;
+	eckd_count_t *ct_data = NULL;
+	eckd_count_t *r0_data = NULL;
+	eckd_home_t *ha_data = NULL;
+	ccw1_t *last_ccw = NULL;
+	void *last_data = NULL;
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	int trk = fdata->start_unit;
+	int bs = fdata->blksize == DASD_FORMAT_DEFAULT_BLOCKSIZE ? 4096 : fdata->blksize;
+	int flags = fdata->intensity == DASD_FORMAT_DEFAULT_INTENSITY ? 0 : fdata->intensity;
+
+	int rpt = recs_per_track (&(private->rdc_data), 0, bs);
+	int cyl = trk / private->rdc_data.trk_per_cyl;
+	int head = trk % private->rdc_data.trk_per_cyl;
+	int wrccws = rpt;
+	int datasize = sizeof (DE_eckd_data_t) + sizeof (LO_eckd_data_t);
+
+	if (((fdata->stop_unit == DASD_FORMAT_DEFAULT_STOP_UNIT) &&
+	 trk >= (private->rdc_data.no_cyl * private->rdc_data.trk_per_cyl)) ||
+	    ((fdata->stop_unit != DASD_FORMAT_DEFAULT_STOP_UNIT) &&
+	     trk > fdata->stop_unit)) {
+		DASD_MESSAGE(KERN_INFO, device,"Track %d reached! ending.", trk);
+		return NULL;
+	}
+	switch (bs) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
 		break;
+	default:
+		printk (KERN_WARNING PRINTK_HEADER "Invalid blocksize %d...terminating!\n", bs);
+		return NULL;
+	}
+	switch (flags) {
 	case 0x00:
-		define_extent (last_ccw, DE_data, trk, trk,
-			       DASD_ECKD_CCW_WRITE_CKD, info);
-		last_ccw->flags = CCW_FLAG_CC;
-		last_ccw++;
-		locate_record (last_ccw, LO_data, trk, 0, rpt,
-			       DASD_ECKD_CCW_WRITE_CKD, info);
-                LO_data->length = bs;
-		last_ccw->flags = CCW_FLAG_CC;
-		last_ccw++;
+	case 0x01:
+	case 0x03:
+	case 0x04:		/* make track invalid */
 		break;
 	default:
-		PRINT_WARN ("Unknown format flags...%d\n", flags);
-		return -EINVAL;
+		printk (KERN_WARNING PRINTK_HEADER "Invalid flags 0x%x...terminating!\n", flags);
+		return NULL;
 	}
-	if (flags & 0x02) {
-		PRINT_WARN ("Unsupported format flag...%d\n", flags);
-		return -EINVAL;
+
+	/* print status line */
+	if ((private->rdc_data.no_cyl < 20) ?
+	    (trk % private->rdc_data.no_cyl == 0) :
+	    (trk % private->rdc_data.no_cyl == 0 &&
+	     (trk / private->rdc_data.no_cyl) %
+	     (private->rdc_data.no_cyl / 20))) {
+		DASD_MESSAGE(KERN_INFO, device, "Format Cylinder: %d Flags: %d\n",
+			trk / private->rdc_data.trk_per_cyl,
+			flags);
 	}
-	if (flags & 0x01) {	/* write record zero */
-		memset (r0_data, 0, sizeof (eckd_count_t));
-		r0_data->cyl = cyl;
-		r0_data->head = head;
-		r0_data->record = 0;
-		r0_data->kl = 0;
-		r0_data->dl = 8;
-		last_ccw->cmd_code = 0x03;
-		last_ccw->count = 8;
-		last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI;
-		last_ccw->cda = (void *) virt_to_phys (r0_data);
-		last_ccw++;
-	}
-	/* write remaining records */
-	for (i = 0; i < rpt; i++, last_ccw++) {
-		memset (ct_data + i, 0, sizeof (eckd_count_t));
-		(ct_data + i)->cyl = cyl;
-		(ct_data + i)->head = head;
-		(ct_data + i)->record = i + 1;
-		(ct_data + i)->kl = 0;
-		(ct_data + i)->dl = bs;
-		last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
-		last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI;
-		last_ccw->count = 8;
-		last_ccw->cda = (void *)
-                        virt_to_phys (ct_data + i);
-	}
-	(last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC);
-        fcp -> devindex = di;
-        fcp -> flags = DASD_DO_IO_SLEEP;
-        do {
-                DECLARE_WAITQUEUE(wait, current);
-                unsigned long flags;
-                int irq;
-                int cs;
-
-                irq = dasd_info[fcp->devindex]->info.irq;
-                s390irq_spin_lock_irqsave (irq, flags);
-                atomic_set(&fcp->status,CQR_STATUS_QUEUED);
-                rc = dasd_start_IO ( fcp );
-                add_wait_queue (&dasd_waitq, &wait);
-                do {
-                        current->state = TASK_UNINTERRUPTIBLE;
-                        s390irq_spin_unlock_irqrestore (irq, flags);
-                        schedule ();
-                        s390irq_spin_lock_irqsave (irq, flags);
-                } while (((cs = atomic_read (&fcp->status)) !=
-                          CQR_STATUS_DONE) &&
-                         (cs != CQR_STATUS_ERROR));
-                remove_wait_queue (&dasd_waitq, &wait);
-		s390irq_spin_unlock_irqrestore (irq, flags);
-
-                retries --;
-	} while ( (rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE)) &&
-                  retries);
-        if ((rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE)))
-                rc = -EIO;
-	release_cqr (fcp);
-	return rc;
+	if (flags & 0x04) {
+                rpt = 1;
+		wrccws = 1;
+                bs = 8;
+	} else {
+		if (flags & 0x1) {
+			wrccws++;
+			datasize += sizeof (eckd_count_t);
+		}
+		if (flags & 0x2) {
+			wrccws++;
+			datasize += sizeof (eckd_home_t);
+		}
+	}
+	fcp = ccw_alloc_request (dasd_eckd_discipline.name,
+				 wrccws + 2 + 1,
+				 datasize + rpt * sizeof (eckd_count_t));
+	if (fcp != NULL) {
+		fcp->device = device;
+                fcp->retries = 2;       /* set retry counter to enable ERP */
+		last_data = fcp->data;
+		DE_data = (DE_eckd_data_t *) last_data;
+		last_data = (void *) (DE_data + 1);
+		LO_data = (LO_eckd_data_t *) last_data;
+		last_data = (void *) (LO_data + 1);
+		if (flags & 0x2) {
+			ha_data = (eckd_home_t *) last_data;
+			last_data = (void *) (ha_data + 1);
+		}
+		if (flags & 0x1) {
+			r0_data = (eckd_count_t *) last_data;
+			last_data = (void *) (r0_data + 1);
+		}
+		ct_data = (eckd_count_t *) last_data;
+
+		last_ccw = fcp->cpaddr;
+
+		switch (flags) {
+		case 0x03:
+			define_extent (last_ccw, DE_data, trk, trk,
+				    DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device);
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			locate_record (last_ccw, LO_data, trk, 0, wrccws,
+				       DASD_ECKD_CCW_WRITE_HOME_ADDRESS, device, device->sizes.bp_block);
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			break;
+		case 0x01:
+			define_extent (last_ccw, DE_data, trk, trk,
+				     DASD_ECKD_CCW_WRITE_RECORD_ZERO, device);
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			locate_record (last_ccw, LO_data, trk, 0, wrccws,
+				       DASD_ECKD_CCW_WRITE_RECORD_ZERO, device, device->sizes.bp_block);
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			memset (r0_data, 0, sizeof (eckd_count_t));
+			break;
+		case 0x00:
+			define_extent (last_ccw, DE_data, trk, trk,
+				       DASD_ECKD_CCW_WRITE_CKD, device);
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			locate_record (last_ccw, LO_data, trk, 0, wrccws,
+				       DASD_ECKD_CCW_WRITE_CKD, device, device->sizes.bp_block);
+			LO_data->length = bs;
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			break;
+		case 0x04:
+			define_extent (last_ccw, DE_data, trk, trk,
+				       DASD_ECKD_CCW_WRITE_CKD, device);
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			locate_record (last_ccw, LO_data, trk, 0, wrccws,
+				       DASD_ECKD_CCW_WRITE_CKD, device, 0);
+			LO_data->length = bs;
+			last_ccw->flags |= CCW_FLAG_CC;
+			last_ccw++;
+			break;
+		default:
+			PRINT_WARN ("Unknown format flags...%d\n", flags);
+			return NULL;
+		}
+		if (flags & 0x02) {
+			PRINT_WARN ("Unsupported format flag...%d\n", flags);
+			return NULL;
+		}
+		if (flags & 0x01) {	/* write record zero */
+			r0_data->cyl = cyl;
+			r0_data->head = head;
+			r0_data->record = 0;
+			r0_data->kl = 0;
+			r0_data->dl = 8;
+			last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_RECORD_ZERO;
+			last_ccw->count = 8;
+			last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
+			set_normalized_cda (last_ccw, __pa (r0_data));
+			last_ccw++;
+		}
+		/* write remaining records */
+		for (i = 0; i < rpt; i++) {
+			memset (ct_data + i, 0, sizeof (eckd_count_t));
+			(ct_data + i)->cyl = cyl;
+			(ct_data + i)->head = head;
+			(ct_data + i)->record = i + 1;
+			(ct_data + i)->kl = 0;
+			(ct_data + i)->dl = bs;
+			last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD;
+			last_ccw->flags |= CCW_FLAG_CC | CCW_FLAG_SLI;
+			last_ccw->count = 8;
+			set_normalized_cda (last_ccw, __pa (ct_data + i));
+			last_ccw++;
+		}
+		(last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC);
+		fcp->device = device;
+		fcp->status = CQR_STATUS_FILLED;
+	}
+	return fcp;
 }
 
-int
-dasd_eckd_ck_devinfo (dev_info_t * info)
+static dasd_era_t
+dasd_eckd_examine_error (ccw_req_t * cqr, devstat_t * stat)
 {
-	return 0;
+	dasd_device_t *device = (dasd_device_t *) cqr->device;
+
+	if (stat->cstat == 0x00 &&
+	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+		return dasd_era_none;
+
+	switch (device->devinfo.sid_data.cu_type) {
+	case 0x3990:
+	case 0x2105:
+		return dasd_3990_erp_examine (cqr, stat);
+	case 0x9343:
+		return dasd_9343_erp_examine (cqr, stat);
+	default:
+		printk (KERN_WARNING PRINTK_HEADER
+			"default (unknown CU type) - RECOVERABLE return \n");
+		return dasd_era_recover;
+	}
 }
 
-cqr_t *
-dasd_eckd_build_req (int devindex,
-		     struct request * req)
+static dasd_erp_action_fn_t
+dasd_eckd_erp_action (ccw_req_t * cqr)
 {
-	cqr_t *rw_cp = NULL;
-	ccw1_t *ccw;
+	dasd_device_t *device = (dasd_device_t *) cqr->device;
+        
+	switch (device->devinfo.sid_data.cu_type) {
+	case 0x3990:
+	case 0x2105:
+                /*  return dasd_3990_erp_action; */
+	case 0x9343:
+                /* Return dasd_9343_erp_action; */
+	default:
+		return default_erp_action;
+	}
+}
 
+static dasd_erp_postaction_fn_t
+dasd_eckd_erp_postaction (ccw_req_t * cqr)
+{
+	if (cqr->function != default_erp_action)
+                printk (KERN_WARNING PRINTK_HEADER
+                        "unknown ERP action [<%p>]\n",
+                        cqr->function);
+	return default_erp_postaction;
+}
+
+static ccw_req_t *
+dasd_eckd_build_cp_from_req (dasd_device_t * device, struct request *req)
+{
+	ccw_req_t *rw_cp = NULL;
+	int rw_cmd;
+	int bhct;
+	long size;
+	ccw1_t *ccw;
 	DE_eckd_data_t *DE_data;
 	LO_eckd_data_t *LO_data;
 	struct buffer_head *bh;
-	int rw_cmd;
-	dasd_information_t *info = dasd_info[devindex];
-	int blk_per_trk = recs_per_track (&(info->rdc_data->eckd),
-					  0, info->sizes.bp_block);
-	int byt_per_blk = info->sizes.bp_block;
-	int noblk = req-> nr_sectors >> info->sizes.s2b_shift;
-	int btrk = (req->sector >> info->sizes.s2b_shift) / blk_per_trk;
-	int etrk = ((req->sector + req->nr_sectors - 1) >>
-		    info->sizes.s2b_shift) / blk_per_trk;
-
-        if ( ! noblk ) {
-                PRINT_ERR("No blocks to write...returning\n");
-                return NULL;
-        }
+	dasd_eckd_private_t *private = (dasd_eckd_private_t *) device->private;
+	int byt_per_blk = device->sizes.bp_block;
+	int shift = device->sizes.s2b_shift;
+	int blk_per_trk = recs_per_track (&(private->rdc_data), 0, byt_per_blk);
+	int btrk = (req->sector >> shift) / blk_per_trk;
+	int etrk = ((req->sector + req->nr_sectors - 1) >> shift) / blk_per_trk;
 
 	if (req->cmd == READ) {
 		rw_cmd = DASD_ECKD_CCW_READ_MT;
-	} else
-#if DASD_PARANOIA > 2
-	if (req->cmd == WRITE)
-#endif				/* DASD_PARANOIA */
-	{
+	} else if (req->cmd == WRITE) {
 		rw_cmd = DASD_ECKD_CCW_WRITE_MT;
-	}
-#if DASD_PARANOIA > 2
-	else {
+	} else {
 		PRINT_ERR ("Unknown command %d\n", req->cmd);
 		return NULL;
 	}
-#endif				/* DASD_PARANOIA */
 	/* Build the request */
-	rw_cp = request_cqr (2 + noblk,
-			     sizeof (DE_eckd_data_t) +
-			     sizeof (LO_eckd_data_t));
-        if ( ! rw_cp ) {
-          return NULL;
-        }
+	/* count bhs to prevent errors, when bh smaller than block */
+	bhct = 0;
+	for (bh = req->bh; bh; bh = bh->b_reqnext) {
+		if (bh->b_size > byt_per_blk)
+			for (size = 0; size < bh->b_size; size += byt_per_blk)
+				bhct++;
+		else
+			bhct++;
+	}
+
+	rw_cp = dasd_alloc_request (dasd_eckd_discipline.name,
+				    2 + bhct + 1,
+				    sizeof (DE_eckd_data_t) +
+				    sizeof (LO_eckd_data_t));
+	if (!rw_cp) {
+		return NULL;
+	}
 	DE_data = rw_cp->data;
 	LO_data = rw_cp->data + sizeof (DE_eckd_data_t);
 	ccw = rw_cp->cpaddr;
 
-	define_extent (ccw, DE_data, btrk, etrk, rw_cmd, info);
-	ccw->flags = CCW_FLAG_CC;
+	define_extent (ccw, DE_data, btrk, etrk, rw_cmd, device);
+	ccw->flags |= CCW_FLAG_CC;
 	ccw++;
-	locate_record (ccw, LO_data, btrk,
-		       (req->sector >> info->sizes.s2b_shift) %
-		       blk_per_trk + 1,
-		       req->nr_sectors >> info->sizes.s2b_shift,
-		       rw_cmd, info);
-	ccw->flags = CCW_FLAG_CC;
-	for (bh = req->bh; bh; bh = bh->b_reqnext) {
-                long size;
-		for (size = 0; size < bh->b_size; size += byt_per_blk) {
-                        ccw++;
-                        ccw->flags = CCW_FLAG_CC;
-                        ccw->cmd_code = rw_cmd;
-                        ccw->count = byt_per_blk;
-                        ccw->cda = (void *) virt_to_phys (bh->b_data + size);
+	locate_record (ccw, LO_data, btrk, (req->sector >> shift) % blk_per_trk + 1,
+	    req->nr_sectors >> shift, rw_cmd, device, device->sizes.bp_block);
+	ccw->flags |= CCW_FLAG_CC;
+	for (bh = req->bh; bh != NULL;) {
+		if (bh->b_size > byt_per_blk) {
+			for (size = 0; size < bh->b_size; size += byt_per_blk) {
+				ccw++;
+				ccw->flags |= CCW_FLAG_CC;
+				ccw->cmd_code = rw_cmd;
+				ccw->count = byt_per_blk;
+				set_normalized_cda (ccw, __pa (bh->b_data + size));
+			}
+			bh = bh->b_reqnext;
+		} else {	/* group N bhs to fit into byt_per_blk */
+			for (size = 0; bh != NULL && size < byt_per_blk;) {
+				ccw++;
+				ccw->flags |= CCW_FLAG_DC;
+				ccw->cmd_code = rw_cmd;
+				ccw->count = bh->b_size;
+				set_normalized_cda (ccw, __pa (bh->b_data));
+				size += bh->b_size;
+				bh = bh->b_reqnext;
+			}
+			if (size != byt_per_blk) {
+				PRINT_WARN ("Cannot fulfill small request %ld vs. %d (%ld sects)\n",
+					    size,
+					    byt_per_blk,
+					    req->nr_sectors);
+
+				ccw_free_request (rw_cp);
+				return NULL;
+			}
+			ccw->flags &= ~CCW_FLAG_DC;
+			ccw->flags |= CCW_FLAG_CC;
 		}
 	}
 	ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC);
+	rw_cp->device = device;
+	rw_cp->expires = 5 * TOD_MIN;	/* 5 minutes */
+	rw_cp->req = req;
+	rw_cp->lpm = LPM_ANYPATH;
+	rw_cp->retries = 2;
+	asm volatile ("STCK %0":"=m" (rw_cp->buildclk));
+	check_then_set (&rw_cp->status,
+				       CQR_STATUS_EMPTY,
+				       CQR_STATUS_FILLED);
 	return rw_cp;
 }
-
-cqr_t *
-dasd_eckd_rw_label (int devindex, int rw, char *buffer)
+#if 0
+int
+dasd_eckd_cleanup_request (ccw_req_t * cqr)
 {
-	int cmd_code = 0x03;
-	dasd_information_t *info = dasd_info[devindex];
-	cqr_t *cqr;
-	ccw1_t *ccw;
+	int ret = 0;
+	struct request *req = cqr->req;
+	dasd_device_t *device = cqr->device;
+	int byt_per_blk = device->sizes.bp_block;
+
+	for (bh = req->bh; bh != NULL;) {
+		if (bh->b_size > byt_per_blk) {
+			for (size = 0; size < bh->b_size; size += byt_per_blk) {
+				ccw++;
+				ccw->flags |= CCW_FLAG_CC;
+				ccw->cmd_code = rw_cmd;
+				ccw->count = byt_per_blk;
+				set_normalized_cda (ccw, __pa (bh->b_data + size));
+			}
+			bh = bh->b_reqnext;
+		} else {	/* group N bhs to fit into byt_per_blk */
+			for (size = 0; bh != NULL && size < byt_per_blk;) {
+				ccw++;
+				ccw->flags |= CCW_FLAG_DC;
+				ccw->cmd_code = rw_cmd;
+				ccw->count = bh->b_size;
+				set_normalized_cda (ccw, __pa (bh->b_data));
+				size += bh->b_size;
+				bh = bh->b_reqnext;
+			}
+		}
+	}
+	return ret;
+}
+#endif
+ccw_req_t *
+dasd_eckd_reserve (struct dasd_device_t * device)
+{
+	ccw_req_t *cqr = ccw_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0);
+	if (cqr == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No memory to allocate initialization request\n");
+		return NULL;
+	}
+	cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RESERVE;
+	cqr->device = device;
+	cqr->retries = 0;
+	cqr->status = CQR_STATUS_FILLED;
+	return cqr;
+}
 
-	switch (rw) {
-	case READ:
-		cmd_code = DASD_ECKD_CCW_READ;
-		break;
-	case WRITE:
-		cmd_code = DASD_ECKD_CCW_WRITE;
-		break;
-#if DASD_PARANOIA > 2
-	default:
-		INTERNAL_ERROR ("unknown cmd %d", rw);
+ccw_req_t *
+dasd_eckd_release (struct dasd_device_t * device)
+{
+	ccw_req_t *cqr = ccw_alloc_request (dasd_eckd_discipline.name, 1 + 1, 0);
+	if (cqr == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+			"No memory to allocate initialization request\n");
 		return NULL;
-#endif				/* DASD_PARANOIA */
 	}
-	cqr = request_cqr (3, sizeof (DE_eckd_data_t) +
-			   sizeof (LO_eckd_data_t));
-	ccw = cqr->cpaddr;
-	define_extent (ccw, cqr->data, 0, 0, cmd_code, info);
-	ccw->flags |= CCW_FLAG_CC;
-	ccw++;
-	locate_record (ccw, cqr->data + 1, 0, 2, 1, cmd_code, info);
-	ccw->flags |= CCW_FLAG_CC;
-	ccw++;
-	ccw->cmd_code = cmd_code;
-	ccw->flags |= CCW_FLAG_SLI;
-	ccw->count = sizeof (dasd_volume_label_t);
-	ccw->cda = (void *) virt_to_phys ((void *) buffer);
+	cqr->cpaddr->cmd_code = DASD_ECKD_CCW_RELEASE;
+	cqr->device = device;
+	cqr->retries = 0;
+	cqr->status = CQR_STATUS_FILLED;
 	return cqr;
 
 }
 
-void
-dasd_eckd_print_char (dasd_characteristics_t * i)
+static inline ccw1_t *
+dasd_eckd_find_cmd (ccw_req_t * cqr, int cmd)
 {
-        dasd_eckd_characteristics_t * c = 
-                (dasd_eckd_characteristics_t *)i;
-	PRINT_INFO ("%x/%x (%x/%x) Cyl: %d Head: %d Sec: %d \n",
-		    c->dev_type, c->dev_model,
-		    c->cu_type, c->cu_model.model,
-		    c->no_cyl, c->trk_per_cyl,
-		    c->sec_per_trk);
-	PRINT_INFO ("Estimate: %d Byte/trk %d byte/kByte %d kByte/trk \n",
-		    bytes_per_track (c),
-		    bytes_per_record (c, 0, 1024),
-		    recs_per_track (c, 0, 1024));
-};
+	ccw1_t *cp;
 
-int
-dasd_eckd_ck_char (dasd_characteristics_t * i)
+	cp = cqr->cpaddr;
+        do {
+		if (cp->cmd_code == cmd)
+			return cp;
+		if (cp->cmd_code == CCW_CMD_TIC) {
+			cp = (ccw1_t *)cp->cda;
+                        continue;
+		} 
+                if ( cp->flags & (CCW_FLAG_DC | CCW_FLAG_CC) ) {
+                        cp ++;
+                        continue;
+		}
+                break;
+	} while ( 1 );
+        return NULL;
+}
+
+ccw_req_t *
+dasd_eckd_merge_cp ( dasd_device_t *device )
 {
-	int rc = 0;
-	dasd_eckd_print_char (i);
-	return rc;
+        ccw_req_t * cqr;
+        return NULL;
 }
 
-int
-dasd_eckd_format (int devindex, format_data_t * fdata)
+static char *
+dasd_eckd_dump_sense (struct dasd_device_t *device, ccw_req_t * req)
 {
-	int rc = 0;
-	int i;
-	dasd_information_t *info = dasd_info[devindex];
-	format_data_t fd;
+	char *page = (char *) get_free_page (GFP_KERNEL);
+	devstat_t *stat = &device->dev_status;
+	char *sense = stat->ii.sense.data;
+	int len, sl, sct;
 
-	if (!fdata) {
-		fd.start_unit = 0;
-		fd.stop_unit = info->rdc_data->eckd.no_cyl *
-                        info->rdc_data->eckd.trk_per_cyl - 1;
-		fd.blksize = 4096;
-	} else {
-		memcpy (&fd, fdata, sizeof (format_data_t));
-		if ( fd.stop_unit == -1 ) {
-                        fd.stop_unit = info->rdc_data->eckd.no_cyl *
-                                info->rdc_data->eckd.trk_per_cyl - 1;
-		}
-                if ( fd.blksize == 0 ) {
-                        fd.blksize = 4096;
-                }
+	if (page == NULL) {
+		return NULL;
 	}
-        PRINT_INFO("Formatting device %d from %d to %d with bs %d\n",
-                   devindex,fd.start_unit,fd.stop_unit,fd.blksize);
-        if ( fd.start_unit > fd.stop_unit ) {
-                PRINT_WARN ("start unit .gt. stop unit\n");
-                return -EINVAL;
+	len = sprintf (page, KERN_WARNING PRINTK_HEADER
+		       "device %04X on irq %d: I/O status report:\n",
+		       device->devinfo.devno, device->devinfo.irq);
+	len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+			"in req: %p CS: 0x%02X DS: 0x%02X\n",
+			req, stat->cstat, stat->dstat);
+	len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+			"Failing CCW: %p\n", (void *) stat->cpa);
+        {
+            ccw1_t *act = req -> cpaddr;
+            int i = req -> cplength;
+            do {
+#if 0
+                printk ( KERN_INFO "CCW %p: %08X %08X\n", 
+                         act,((int*)act)[0],((int*)act)[1]);
+                printk ( KERN_INFO "DAT: %08X %08X %08X %08X\n", 
+                         ((int*)act->cda)[0],((int*)act->cda)[1],
+                         ((int*)act->cda)[2],((int*)act->cda)[3]);
+#endif
+                act ++;
+            } while ( --i );
         }
-        if ( (fd.start_unit > info->rdc_data->eckd.no_cyl *
-              info->rdc_data->eckd.trk_per_cyl - 1) ) {
-                PRINT_WARN ("start unit beyond end of disk\n");
-                return -EINVAL;
-        }
-        if ( (fd.stop_unit > info->rdc_data->eckd.no_cyl *
-              info->rdc_data->eckd.trk_per_cyl - 1) ) {
-                PRINT_WARN ("stop unit beyond end of disk\n");
-                return -EINVAL;
-        }
-        switch (fd.blksize) {
-        case 512:
-        case 1024:
-        case 2048:
-        case 4096:
-                break;
-        default:
-                PRINT_WARN ("invalid blocksize\n");
-                return -EINVAL;
-        }
-	for (i = fd.start_unit; i <= fd.stop_unit; i++) {
-                /* print 20 messages per disk at all */
-                if ( ! ( i % (info->rdc_data->eckd.trk_per_cyl  *
-                                (info->rdc_data->eckd.no_cyl / 20 ) )))  {
-                        PRINT_INFO ("Format %d Cylinder: %d\n",devindex,
-                                    i/info->rdc_data->eckd.trk_per_cyl);
-                }
-		rc = dasd_eckd_format_track (devindex, i, fd.blksize);
-		if (rc) {
-			PRINT_WARN ("Formatting of Track %d failed...exiting\n", i);
-			break;
+	if (stat->flag & DEVSTAT_FLAG_SENSE_AVAIL) {
+		for (sl = 0; sl < 4; sl++) {
+			len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+					"Sense(hex) %2d-%2d:",
+					(8 * sl),
+					((8 * sl) + 7));
+
+			for (sct = 0; sct < 8; sct++) {
+				len += sprintf (page + len, " %02x",
+						sense[8 * sl + sct]);
+			}
+			len += sprintf (page + len, "\n");
+		}
+
+		if (sense[27] & DASD_SENSE_BIT_0) {
+			/* 24 Byte Sense Data */
+			len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+				     "24 Byte: %x MSG %x, %s MSGb to SYSOP\n",
+					sense[7] >> 4, sense[7] & 0x0f,
+					sense[1] & 0x10 ? "" : "no");
+		} else {
+			/* 32 Byte Sense Data */
+			len += sprintf (page + len, KERN_WARNING PRINTK_HEADER
+				   "32 Byte: Format: %x Exception class %x\n",
+					sense[6] & 0x0f, sense[22] >> 4);
 		}
 	}
-        PRINT_INFO("Formated device %d from %d to %d with bs %d\n",
-                   devindex,fd.start_unit,fd.stop_unit,fd.blksize);
-	return rc;
+	return page;
 }
 
-cqr_t *
-dasd_eckd_fill_sizes_first (int di)
+dasd_discipline_t dasd_eckd_discipline =
 {
-	cqr_t *rw_cp = NULL;
-	ccw1_t *ccw;
-	DE_eckd_data_t *DE_data;
-	LO_eckd_data_t *LO_data;
-	dasd_information_t *info = dasd_info[di];
-	eckd_count_t *count_data= &(info->private.eckd.count_data);
-	rw_cp = request_cqr (3,
-			     sizeof (DE_eckd_data_t) +
-			     sizeof (LO_eckd_data_t));
-	DE_data = rw_cp->data;
-	LO_data = rw_cp->data + sizeof (DE_eckd_data_t);
-	ccw = rw_cp->cpaddr;
-	define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, info);
-	ccw->flags = CCW_FLAG_CC;
-	ccw++;
-	locate_record (ccw, LO_data, 0, 1, 1, DASD_ECKD_CCW_READ_COUNT, info);
-	ccw->flags = CCW_FLAG_CC;
-	ccw++;
-	ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT;
-	ccw->count = 8;
-	ccw->cda = (void *) __pa (count_data);
-	rw_cp->devindex = di;
-        atomic_set(&rw_cp->status,CQR_STATUS_FILLED);
-	return rw_cp;
-}
+	name:"ECKD",
+	ebcname:"ECKD",
+	id_check:dasd_eckd_id_check,
+	check_characteristics:dasd_eckd_check_characteristics,
+	init_analysis:dasd_eckd_init_analysis,
+	do_analysis:dasd_eckd_do_analysis,
+	fill_geometry:dasd_eckd_fill_geometry,
+	start_IO:dasd_start_IO,
+	format_device:dasd_eckd_format_device,
+	examine_error:dasd_eckd_examine_error,
+	erp_action:dasd_eckd_erp_action,
+	erp_postaction:dasd_eckd_erp_postaction,
+	build_cp_from_req:dasd_eckd_build_cp_from_req,
+	dump_sense:dasd_eckd_dump_sense,
+	int_handler:dasd_int_handler,
+	reserve:dasd_eckd_reserve,
+	release:dasd_eckd_release,
+	merge_cp:dasd_eckd_merge_cp
+};
 
-int dasd_eckd_fill_sizes_last (int devindex) 
+int
+dasd_eckd_init (void)
 {
-	int sb;
-	dasd_information_t *in = dasd_info[devindex];
-	int bs = in->private.eckd.count_data.dl;
-	if (bs <= 0) {
-                PRINT_INFO("Cannot figure out blocksize. did you format the disk?\n");
-                memset (&(in -> sizes), 0, sizeof(dasd_sizes_t ));
-                return -EMEDIUMTYPE;
-	} else {
-		in->sizes.bp_block = bs;
+	int rc = 0;
+	printk (KERN_INFO PRINTK_HEADER
+		"%s discipline initializing\n", dasd_eckd_discipline.name);
+	ASCEBC (dasd_eckd_discipline.ebcname, 4);
+	dasd_discipline_enq (&dasd_eckd_discipline);
+#ifdef CONFIG_DASD_DYNAMIC
+        {
+	int i;
+	for (i = 0; i < sizeof (dasd_eckd_known_devices) / sizeof (devreg_t); i++) {
+		printk (KERN_INFO PRINTK_HEADER
+			"We are interested in: CU %04X/%02x DEV: %04X/%02Xi\n",
+			dasd_eckd_known_devices[i].ci.hc.ctype,
+			dasd_eckd_known_devices[i].ci.hc.cmode,
+			dasd_eckd_known_devices[i].ci.hc.dtype,
+			dasd_eckd_known_devices[i].ci.hc.dmode);
+		s390_device_register (&dasd_eckd_known_devices[i]);
 	}
-	in->sizes.bp_sector = in->sizes.bp_block;
-        
-	in->sizes.b2k_shift = 0; /* bits to shift a block to get 1k */
-	for (sb = 1024; sb < bs; sb = sb << 1)
-                in->sizes.b2k_shift++;
-        
-	in->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */
-	for (sb = 512; sb < bs; sb = sb << 1)
-                in->sizes.s2b_shift++;
-        
-	in->sizes.blocks = in->rdc_data->eckd.no_cyl *
-                in->rdc_data->eckd.trk_per_cyl *
-                recs_per_track (&(in->rdc_data->eckd), 0, bs);
-	in->sizes.kbytes = in->sizes.blocks << in->sizes.b2k_shift;
-        
-	PRINT_INFO ("Verified: %d B/trk %d B/Blk(%d B) %d Blks/trk %d kB/trk \n",
-		    bytes_per_track (&(in->rdc_data->eckd)),
-		    bytes_per_record (&(in->rdc_data->eckd), 0, in->sizes.bp_block),
-                    in->sizes.bp_block,
-		    recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block),
-		    (recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block) <<
-                     in->sizes.b2k_shift ));
-                    return 0;
-}
-
-dasd_operations_t dasd_eckd_operations =
-{
-	ck_devinfo:	dasd_eckd_ck_devinfo,
-	get_req_ccw:	dasd_eckd_build_req,
-	rw_label:	dasd_eckd_rw_label,
-	ck_characteristics: 	dasd_eckd_ck_char,
-	fill_sizes_first:	dasd_eckd_fill_sizes_first,
-	fill_sizes_last:	dasd_eckd_fill_sizes_last,
-	dasd_format:	dasd_eckd_format,
-};
+        }
+#endif				/* CONFIG_DASD_DYNAMIC */
+	return rc;
+}
+
+void
+dasd_eckd_cleanup( void ) {
+        printk ( KERN_INFO PRINTK_HEADER
+                 "%s discipline cleaning up\n", dasd_eckd_discipline.name);
+#ifdef CONFIG_DASD_DYNAMIC
+        {
+	int i;
+        for ( i=0; i<sizeof(dasd_eckd_known_devices)/sizeof(devreg_t); i++) {
+		printk (KERN_INFO PRINTK_HEADER
+			"We are interested in: CU %04X/%02x DEV: %04X/%02Xi\n",
+			dasd_eckd_known_devices[i].ci.hc.ctype,
+			dasd_eckd_known_devices[i].ci.hc.cmode,
+			dasd_eckd_known_devices[i].ci.hc.dtype,
+			dasd_eckd_known_devices[i].ci.hc.dmode);
+		s390_device_register(&dasd_eckd_known_devices[i]);
+	}
+        } 
+#endif /* CONFIG_DASD_DYNAMIC */
+        dasd_discipline_deq(&dasd_eckd_discipline);
+}
 
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_eckd.h linux/drivers/s390/block/dasd_eckd.h
--- v2.4.1/linux/drivers/s390/block/dasd_eckd.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_eckd.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,308 @@
+#ifndef DASD_ECKD_H
+#define DASD_ECKD_H
+
+#include "dasd_3990_erp.h"
+
+typedef
+struct eckd_count_t {
+	__u16 cyl;
+	__u16 head;
+	__u8 record;
+	__u8 kl;
+	__u16 dl;
+} __attribute__ ((packed)) 
+
+eckd_count_t;
+
+typedef
+struct ch_t {
+	__u16 cyl;
+	__u16 head;
+} __attribute__ ((packed)) 
+
+ch_t;
+
+typedef
+struct chs_t {
+	__u16 cyl;
+	__u16 head;
+	__u32 sector;
+} __attribute__ ((packed)) 
+
+chs_t;
+
+typedef
+struct chr_t {
+	__u16 cyl;
+	__u16 head;
+	__u8 record;
+} __attribute__ ((packed)) 
+
+chr_t;
+
+typedef
+struct geom_t {
+	__u16 cyl;
+	__u16 head;
+	__u32 sector;
+} __attribute__ ((packed)) 
+
+geom_t;
+
+typedef struct eckd_home_t {
+	__u8 skip_control[14];
+	__u16 cell_number;
+	__u8 physical_addr[3];
+	__u8 flag;
+	ch_t track_addr;
+	__u8 reserved;
+	__u8 key_length;
+	__u8 reserved2[2];
+} __attribute__ ((packed)) 
+
+eckd_home_t;
+
+typedef
+struct DE_eckd_data_t {
+	struct {
+		unsigned char perm:2;	/* Permissions on this extent */
+		unsigned char reserved:1;
+		unsigned char seek:2;	/* Seek control */
+		unsigned char auth:2;	/* Access authorization */
+		unsigned char pci:1;	/* PCI Fetch mode */
+	} __attribute__ ((packed)) mask;
+	struct {
+		unsigned char mode:2;	/* Architecture mode */
+		unsigned char ckd:1;	/* CKD Conversion */
+		unsigned char operation:3;	/* Operation mode */
+		unsigned char cfw:1;	/* Cache fast write */
+		unsigned char dfw:1;	/* DASD fast write */
+	} __attribute__ ((packed)) attributes;
+	__u16 short blk_size;	/* Blocksize */
+	__u16 fast_write_id;
+	__u8 unused;
+	__u8 reserved;
+	ch_t beg_ext;
+	ch_t end_ext;
+} __attribute__ ((packed)) 
+
+DE_eckd_data_t;
+
+typedef
+struct LO_eckd_data_t {
+	struct {
+		unsigned char orientation:2;
+		unsigned char operation:6;
+	} __attribute__ ((packed)) operation;
+	struct {
+		unsigned char last_bytes_used:1;
+		unsigned char reserved:6;
+		unsigned char read_count_suffix:1;
+	} __attribute__ ((packed)) auxiliary;
+	__u8 unused;
+	__u8 count;
+	ch_t seek_addr;
+	chr_t search_arg;
+	__u8 sector;
+	__u16 length;
+} __attribute__ ((packed)) 
+
+LO_eckd_data_t;
+
+typedef
+struct dasd_eckd_characteristics_t {
+	__u16 cu_type;
+	struct {
+		unsigned char support:2;
+		unsigned char async:1;
+		unsigned char reserved:1;
+		unsigned char cache_info:1;
+		unsigned char model:3;
+	} __attribute__ ((packed)) cu_model;
+	__u16 dev_type;
+	__u8 dev_model;
+	struct {
+		unsigned char mult_burst:1;
+		unsigned char RT_in_LR:1;
+		unsigned char reserved1:1;
+		unsigned char RD_IN_LR:1;
+		unsigned char reserved2:4;
+		unsigned char reserved3:8;
+		unsigned char defect_wr:1;
+		unsigned char reserved4:2;
+		unsigned char striping:1;
+		unsigned char reserved5:4;
+		unsigned char cfw:1;
+		unsigned char reserved6:2;
+		unsigned char cache:1;
+		unsigned char dual_copy:1;
+		unsigned char dfw:1;
+		unsigned char reset_alleg:1;
+		unsigned char sense_down:1;
+	} __attribute__ ((packed)) facilities;
+	__u8 dev_class;
+	__u8 unit_type;
+	__u16 no_cyl;
+	__u16 trk_per_cyl;
+	__u8 sec_per_trk;
+	__u8 byte_per_track[3];
+	__u16 home_bytes;
+	__u8 formula;
+	union {
+		struct {
+			__u8 f1;
+			__u16 f2;
+			__u16 f3;
+		} __attribute__ ((packed)) f_0x01;
+		struct {
+			__u8 f1;
+			__u8 f2;
+			__u8 f3;
+			__u8 f4;
+			__u8 f5;
+		} __attribute__ ((packed)) f_0x02;
+	} __attribute__ ((packed)) factors;
+	__u16 first_alt_trk;
+	__u16 no_alt_trk;
+	__u16 first_dia_trk;
+	__u16 no_dia_trk;
+	__u16 first_sup_trk;
+	__u16 no_sup_trk;
+	__u8 MDR_ID;
+	__u8 OBR_ID;
+	__u8 director;
+	__u8 rd_trk_set;
+	__u16 max_rec_zero;
+	__u8 reserved1;
+	__u8 RWANY_in_LR;
+	__u8 factor6;
+	__u8 factor7;
+	__u8 factor8;
+	__u8 reserved2[3];
+	__u8 reserved3[10];
+} __attribute__             ((packed)) 
+
+dasd_eckd_characteristics_t;
+
+typedef struct dasd_eckd_confdata_t {
+	struct {
+		struct {
+			unsigned char identifier:2;
+			unsigned char token_id:1;
+			unsigned char sno_valid:1;
+			unsigned char subst_sno:1;
+			unsigned char recNED:1;
+			unsigned char emuNED:1;
+			unsigned char reserved:1;
+		} __attribute__ ((packed)) flags;
+		__u8 descriptor;
+		__u8 dev_class;
+		__u8 reserved;
+		unsigned char dev_type[6];
+		unsigned char dev_model[3];
+		unsigned char HDA_manufacturer[3];
+		unsigned char HDA_location[2];
+		unsigned char HDA_seqno[12];
+		__u16 ID;
+	} __attribute__ ((packed)) ned1;
+	struct {
+		struct {
+			unsigned char identifier:2;
+			unsigned char token_id:1;
+			unsigned char sno_valid:1;
+			unsigned char subst_sno:1;
+			unsigned char recNED:1;
+			unsigned char emuNED:1;
+			unsigned char reserved:1;
+		} __attribute__ ((packed)) flags;
+		__u8 descriptor;
+		__u8 reserved[2];
+		unsigned char dev_type[6];
+		unsigned char dev_model[3];
+		unsigned char DASD_manufacturer[3];
+		unsigned char DASD_location[2];
+		unsigned char DASD_seqno[12];
+		__u16 ID;
+	} __attribute__ ((packed)) ned2;
+	struct {
+		struct {
+			unsigned char identifier:2;
+			unsigned char token_id:1;
+			unsigned char sno_valid:1;
+			unsigned char subst_sno:1;
+			unsigned char recNED:1;
+			unsigned char emuNED:1;
+			unsigned char reserved:1;
+		} __attribute__ ((packed)) flags;
+		__u8 descriptor;
+		__u8 reserved[2];
+		unsigned char cont_type[6];
+		unsigned char cont_model[3];
+		unsigned char cont_manufacturer[3];
+		unsigned char cont_location[2];
+		unsigned char cont_seqno[12];
+		__u16 ID;
+	} __attribute__ ((packed)) ned3;
+	struct {
+		struct {
+			unsigned char identifier:2;
+			unsigned char token_id:1;
+			unsigned char sno_valid:1;
+			unsigned char subst_sno:1;
+			unsigned char recNED:1;
+			unsigned char emuNED:1;
+			unsigned char reserved:1;
+		} __attribute__ ((packed)) flags;
+		__u8 descriptor;
+		__u8 reserved[2];
+		unsigned char cont_type[6];
+		unsigned char empty[3];
+		unsigned char cont_manufacturer[3];
+		unsigned char cont_location[2];
+		unsigned char cont_seqno[12];
+		__u16 ID;
+	} __attribute__ ((packed)) ned4;
+	unsigned char ned5[32];
+	unsigned char ned6[32];
+	unsigned char ned7[32];
+	struct {
+		struct {
+			unsigned char identifier:2;
+			unsigned char reserved:6;
+		} __attribute__ ((packed)) flags;
+		__u8 selector;
+		__u16 interfaceID;
+		__u32 reserved;
+		__u16 subsystemID;
+		struct {
+			unsigned char sp0:1;
+			unsigned char sp1:1;
+			unsigned char reserved:5;
+			unsigned char scluster:1;
+		} __attribute__ ((packed)) spathID;
+		__u8 unit_address;
+		__u8 dev_ID;
+		__u8 dev_address;
+		__u8 adapterID;
+		__u16 link_address;
+		struct {
+			unsigned char parallel:1;
+			unsigned char escon:1;
+			unsigned char reserved:1;
+			unsigned char ficon:1;
+			unsigned char reserved2:4;
+		} __attribute__ ((packed)) protocol_type;
+		struct {
+			unsigned char PID_in_236:1;
+			unsigned char reserved:7;
+		} __attribute__ ((packed)) format_flags;
+		__u8 log_dev_address;
+		unsigned char reserved2[12];
+	} __attribute__ ((packed)) neq;
+} __attribute__      ((packed)) 
+
+dasd_eckd_confdata_t;
+
+int dasd_eckd_init (void);
+void dasd_eckd_cleanup(void);
+#endif				/* DASD_ECKD_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_erp.c linux/drivers/s390/block/dasd_erp.c
--- v2.4.1/linux/drivers/s390/block/dasd_erp.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_erp.c	Wed Dec 31 16:00:00 1969
@@ -1,21 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_erp.c
- * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
- */
-
-#include <asm/irq.h>
-#include <linux/dasd.h>
-#include "dasd_erp.h"
-#include "dasd_types.h"
-
-dasd_era_t 
-dasd_erp_examine ( cqr_t * cqr)
-{
-  devstat_t *stat = cqr->dstat ;
-  if ( stat->cstat == 0x00 && 
-       stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END ) )
-    return dasd_era_none;
-  return dasd_era_fatal;
-}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_erp.h linux/drivers/s390/block/dasd_erp.h
--- v2.4.1/linux/drivers/s390/block/dasd_erp.h	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_erp.h	Wed Dec 31 16:00:00 1969
@@ -1,15 +0,0 @@
-/* 
- * File...........: linux/drivers/s390/block/dasd_erp.h
- * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
- */
-
-#include "dasd_types.h"
-
-typedef enum {
-  dasd_era_fatal = -1,
-  dasd_era_none = 0
-} dasd_era_t;
-
-dasd_era_t dasd_erp_examine ( cqr_t * );
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_fba.c linux/drivers/s390/block/dasd_fba.c
--- v2.4.1/linux/drivers/s390/block/dasd_fba.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_fba.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,439 @@
+
+/* 
+ * File...........: linux/drivers/s390/block/dasd_fba.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ */
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <asm/debug.h>
+
+#include <linux/malloc.h>
+#include <linux/hdreg.h>	/* HDIO_GETGEO                      */
+#include <linux/blk.h>
+#include <asm/ccwcache.h>
+#include <asm/idals.h>
+#include <asm/dasd.h>
+
+#include <asm/ebcdic.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/s390dyn.h>
+
+#include "dasd_fba.h"
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#endif				/* PRINTK_HEADER */
+#define PRINTK_HEADER DASD_NAME"(fba):"
+
+#define DASD_FBA_CCW_WRITE 0x41
+#define DASD_FBA_CCW_READ 0x42
+#define DASD_FBA_CCW_LOCATE 0x43
+#define DASD_FBA_CCW_DEFINE_EXTENT 0x63
+
+dasd_discipline_t dasd_fba_discipline;
+
+typedef struct
+dasd_fba_private_t {
+	dasd_fba_characteristics_t rdc_data;
+} dasd_fba_private_t;
+
+#ifdef CONFIG_DASD_DYNAMIC
+static
+devreg_t dasd_fba_known_devices[] =
+{
+	{
+		ci:
+		{hc:
+		 {ctype:0x6310, dtype:0x9336}},
+		flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+		oper_func:dasd_oper_handler
+	},
+	{
+		ci:
+		{hc:
+		 {ctype:0x3880, dtype:0x3370}},
+		flag:DEVREG_MATCH_CU_TYPE | DEVREG_MATCH_DEV_TYPE,
+		oper_func:dasd_oper_handler
+	}
+};
+#endif
+static inline void
+define_extent (ccw1_t * ccw, DE_fba_data_t * DE_data, int rw,
+	       int blksize, int beg, int nr)
+{
+	memset (DE_data, 0, sizeof (DE_fba_data_t));
+	ccw->cmd_code = DASD_FBA_CCW_DEFINE_EXTENT;
+	ccw->count = 16;
+	set_normalized_cda (ccw, __pa (DE_data));
+	if (rw == WRITE)
+		(DE_data->mask).perm = 0x0;
+	else if (rw == READ)
+		(DE_data->mask).perm = 0x1;
+	else
+		DE_data->mask.perm = 0x2;
+	DE_data->blk_size = blksize;
+	DE_data->ext_loc = beg;
+	DE_data->ext_end = nr - 1;
+}
+
+static inline void
+locate_record (ccw1_t * ccw, LO_fba_data_t * LO_data, int rw, int block_nr,
+	       int block_ct)
+{
+	memset (LO_data, 0, sizeof (LO_fba_data_t));
+	ccw->cmd_code = DASD_FBA_CCW_LOCATE;
+	ccw->count = 8;
+	set_normalized_cda (ccw, __pa (LO_data));
+	if (rw == WRITE)
+		LO_data->operation.cmd = 0x5;
+	else if (rw == READ)
+		LO_data->operation.cmd = 0x6;
+	else
+		LO_data->operation.cmd = 0x8;
+	LO_data->blk_nr = block_nr;
+	LO_data->blk_ct = block_ct;
+}
+
+static int
+dasd_fba_id_check (s390_dev_info_t * info)
+{
+        if (info->sid_data.cu_type == 0x3880)
+                if (info->sid_data.dev_type == 0x3370)
+                        return 0;
+	if (info->sid_data.cu_type == 0x6310)
+		if (info->sid_data.dev_type == 0x9336)
+			return 0;
+	return -ENODEV;
+}
+
+static int
+dasd_fba_check_characteristics (struct dasd_device_t *device)
+{
+	int rc = -ENODEV;
+	void *rdc_data;
+	dasd_fba_private_t *private;
+
+	if (device == NULL) {
+		printk (KERN_WARNING PRINTK_HEADER
+		   "Null device pointer passed to characteristics checker\n");
+		return -ENODEV;
+	}
+	if (device->private == NULL) {
+		device->private = kmalloc (sizeof (dasd_fba_private_t), GFP_KERNEL);
+		if (device->private == NULL) {
+			printk (KERN_WARNING PRINTK_HEADER
+				"memory allocation failed for private data\n");
+			return -ENOMEM;
+		}
+	}
+	private = (dasd_fba_private_t *) device->private;
+	rdc_data = (void *) &(private->rdc_data);
+	rc = read_dev_chars (device->devinfo.irq, &rdc_data, 32);
+	if (rc) {
+            printk (KERN_WARNING PRINTK_HEADER
+                    "Read device characteristics returned error %d\n", rc);
+            kfree(private);
+            device->private=NULL;
+            return rc;
+	}
+	printk (KERN_INFO PRINTK_HEADER
+		"%04X on sch %d: %04X/%02X(CU:%04X/%02X) %dMB at(%d B/blk)\n",
+		device->devinfo.devno, device->devinfo.irq,
+                device->devinfo.sid_data.dev_type, device->devinfo.sid_data.dev_model,
+                device->devinfo.sid_data.cu_type, device->devinfo.sid_data.cu_model,
+		(private->rdc_data.blk_bdsa *
+		 (private->rdc_data.blk_size >> 9)) >> 11,
+		private->rdc_data.blk_size);
+	return 0;
+}
+
+static int
+dasd_fba_do_analysis (struct dasd_device_t *device)
+{
+	int rc = 0;
+	int sb;
+	dasd_fba_private_t *private = (dasd_fba_private_t *) device->private;
+	int bs = private->rdc_data.blk_size;
+
+	memset (&(device->sizes), 0, sizeof (dasd_sizes_t));
+	switch (bs) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		device->sizes.bp_block = bs;
+		break;
+	default:
+		printk (KERN_INFO PRINTK_HEADER
+			"/dev/%s (%04X): unknown blocksize %d\n",
+			device->name, device->devinfo.devno, bs);
+		return -EMEDIUMTYPE;
+	}
+	device->sizes.s2b_shift = 0;	/* bits to shift 512 to get a block */
+	for (sb = 512; sb < bs; sb = sb << 1)
+		device->sizes.s2b_shift++;
+
+	device->sizes.blocks = (private->rdc_data.blk_bdsa);
+
+	return rc;
+}
+
+static int
+dasd_fba_fill_geometry (struct dasd_device_t *device, struct hd_geometry *geo)
+{
+	int rc = 0;
+	unsigned long sectors = device->sizes.blocks << device->sizes.s2b_shift;
+	unsigned long tracks = sectors >> 6;
+	unsigned long cyls = tracks >> 4;
+
+	switch (device->sizes.bp_block) {
+	case 512:
+	case 1024:
+	case 2048:
+	case 4096:
+		break;
+	default:
+		return -EINVAL;
+	}
+	geo->cylinders = cyls;
+	geo->heads = 16;
+	geo->sectors = 128 >> device->sizes.s2b_shift;
+	geo->start = 1;
+	return rc;
+}
+
+static dasd_era_t
+dasd_fba_examine_error (ccw_req_t * cqr, devstat_t * stat)
+{
+	dasd_device_t *device = (dasd_device_t *) cqr->device;
+	if (stat->cstat == 0x00 &&
+	    stat->dstat == (DEV_STAT_CHN_END | DEV_STAT_DEV_END))
+		return dasd_era_none;
+
+	switch (device->devinfo.sid_data.dev_model) {
+	case 0x3370:
+		return dasd_3370_erp_examine (cqr, stat);
+	case 0x9336:
+		return dasd_9336_erp_examine (cqr, stat);
+	default:
+		return dasd_era_recover;
+	}
+}
+
+static dasd_erp_action_fn_t
+dasd_fba_erp_action (ccw_req_t * cqr)
+{
+	return default_erp_action;
+}
+
+static dasd_erp_postaction_fn_t
+dasd_fba_erp_postaction (ccw_req_t * cqr)
+{
+	if (cqr->function == default_erp_action)
+		return default_erp_postaction;
+	printk (KERN_WARNING PRINTK_HEADER
+		"unknown ERP action %p\n",
+		cqr->function);
+	return NULL;
+}
+
+static ccw_req_t *
+dasd_fba_build_cp_from_req (dasd_device_t * device, struct request *req)
+{
+	ccw_req_t *rw_cp = NULL;
+	int rw_cmd;
+	int bhct;
+	long size;
+	ccw1_t *ccw;
+	DE_fba_data_t *DE_data;
+	LO_fba_data_t *LO_data;
+	struct buffer_head *bh;
+	dasd_fba_private_t *private = (dasd_fba_private_t *) device->private;
+	int byt_per_blk = device->sizes.bp_block;
+
+	if (req->cmd == READ) {
+		rw_cmd = DASD_FBA_CCW_READ;
+	} else if (req->cmd == WRITE) {
+		rw_cmd = DASD_FBA_CCW_WRITE;
+	} else {
+		PRINT_ERR ("Unknown command %d\n", req->cmd);
+		return NULL;
+	}
+	/* Build the request */
+	/* count bhs to prevent errors, when bh smaller than block */
+	bhct = 0;
+	for (bh = req->bh; bh; bh = bh->b_reqnext) {
+		if (bh->b_size > byt_per_blk)
+			for (size = 0; size < bh->b_size; size += byt_per_blk)
+				bhct++;
+		else
+			bhct++;
+	}
+
+	rw_cp = dasd_alloc_request (dasd_fba_discipline.name,
+				    2 + bhct,
+				    sizeof (DE_fba_data_t) +
+				    sizeof (LO_fba_data_t));
+	if (!rw_cp) {
+		return NULL;
+	}
+	DE_data = rw_cp->data;
+	LO_data = rw_cp->data + sizeof (DE_fba_data_t);
+	ccw = rw_cp->cpaddr;
+
+	define_extent (ccw, DE_data, req->cmd, byt_per_blk,
+		       req->sector, req->nr_sectors);
+	ccw->flags |= CCW_FLAG_CC;
+	ccw++;
+	locate_record (ccw, LO_data, req->cmd, 0, req->nr_sectors);
+	ccw->flags |= CCW_FLAG_CC;
+
+	for (bh = req->bh; bh;) {
+		if (bh->b_size > byt_per_blk) {
+			for (size = 0; size < bh->b_size; size += byt_per_blk) {
+				ccw++;
+				if (private->rdc_data.mode.bits.data_chain) {
+					ccw->flags |= CCW_FLAG_DC;
+				} else {
+					ccw->flags |= CCW_FLAG_CC;
+				}
+				ccw->cmd_code = rw_cmd;
+				ccw->count = byt_per_blk;
+				set_normalized_cda (ccw, __pa (bh->b_data + size));
+			}
+			bh = bh->b_reqnext;
+		} else {	/* group N bhs to fit into byt_per_blk */
+			for (size = 0; bh != NULL && size < byt_per_blk;) {
+				ccw++;
+				if (private->rdc_data.mode.bits.data_chain) {
+					ccw->flags |= CCW_FLAG_DC;
+				} else {
+					PRINT_WARN ("Cannot chain chunks smaller than one block\n");
+					ccw_free_request (rw_cp);
+					return NULL;
+				}
+				ccw->cmd_code = rw_cmd;
+				ccw->count = bh->b_size;
+				set_normalized_cda (ccw, __pa (bh->b_data));
+				size += bh->b_size;
+				bh = bh->b_reqnext;
+			}
+			ccw->flags &= ~CCW_FLAG_DC;
+			ccw->flags |= CCW_FLAG_CC;
+			if (size != byt_per_blk) {
+				PRINT_WARN ("Cannot fulfill request smaller than block\n");
+				ccw_free_request (rw_cp);
+				return NULL;
+			}
+		}
+	}
+	ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC);
+
+	rw_cp->device = device;
+	rw_cp->expires = 5 * TOD_MIN;		/* 5 minutes */
+	rw_cp->req = req;
+	check_then_set (&rw_cp->status, CQR_STATUS_EMPTY, CQR_STATUS_FILLED);
+	return rw_cp;
+}
+
+static char *
+dasd_fba_dump_sense (struct dasd_device_t *device, ccw_req_t * req)
+{
+	char *page = (char *) get_free_page (GFP_KERNEL);
+	int len;
+	if (page == NULL) {
+		return NULL;
+	}
+	len = sprintf (page, KERN_WARNING PRINTK_HEADER
+		       "device %04X on irq %d: I/O status report:\n",
+		       device->devinfo.devno, device->devinfo.irq);
+
+	return page;
+}
+
+dasd_discipline_t dasd_fba_discipline =
+{
+	name:"FBA ",
+	ebcname:"FBA ",
+	id_check:dasd_fba_id_check,
+	check_characteristics:dasd_fba_check_characteristics,
+	do_analysis:dasd_fba_do_analysis,
+	fill_geometry:dasd_fba_fill_geometry,
+	start_IO:dasd_start_IO,
+	examine_error:dasd_fba_examine_error,
+	erp_action:dasd_fba_erp_action,
+	erp_postaction:dasd_fba_erp_postaction,
+	build_cp_from_req:dasd_fba_build_cp_from_req,
+	dump_sense:dasd_fba_dump_sense,
+	int_handler:dasd_int_handler
+};
+
+
+int
+dasd_fba_init (void)
+{
+	int rc = 0;
+	printk (KERN_INFO PRINTK_HEADER
+		"%s discipline initializing\n", dasd_fba_discipline.name);
+	ASCEBC (dasd_fba_discipline.ebcname, 4);
+	dasd_discipline_enq (&dasd_fba_discipline);
+#ifdef CONFIG_DASD_DYNAMIC 
+        {
+            int i;
+            for (i = 0; i < sizeof (dasd_fba_known_devices) / sizeof (devreg_t); i++) {
+		printk (KERN_INFO PRINTK_HEADER
+			"We are interested in: CU %04X/%02x DEV: %04X/%02Xi\n",
+			dasd_fba_known_devices[i].ci.hc.ctype,
+			dasd_fba_known_devices[i].ci.hc.cmode,
+			dasd_fba_known_devices[i].ci.hc.dtype,
+			dasd_fba_known_devices[i].ci.hc.dmode);
+		s390_device_register (&dasd_fba_known_devices[i]);
+            }
+        }
+#endif				/* CONFIG_DASD_DYNAMIC */
+        return rc;
+}
+
+void
+dasd_fba_cleanup( void ) {
+        printk ( KERN_INFO PRINTK_HEADER
+                 "%s discipline cleaning up\n", dasd_fba_discipline.name);
+#ifdef CONFIG_DASD_DYNAMIC
+        {
+	int i;
+        for ( i=0; i<sizeof(dasd_fba_known_devices)/sizeof(devreg_t); i++) {
+                printk (KERN_INFO PRINTK_HEADER
+                        "We are interested in: CU %04X/%02x DEV: %04X/%02Xi\n",
+                        dasd_fba_known_devices[i].ci.hc.ctype,
+                        dasd_fba_known_devices[i].ci.hc.cmode,
+                        dasd_fba_known_devices[i].ci.hc.dtype,
+                        dasd_fba_known_devices[i].ci.hc.dmode);
+                s390_device_register(&dasd_fba_known_devices[i]);
+        }
+        }
+#endif /* CONFIG_DASD_DYNAMIC */
+        dasd_discipline_deq(&dasd_fba_discipline);
+}
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_fba.h linux/drivers/s390/block/dasd_fba.h
--- v2.4.1/linux/drivers/s390/block/dasd_fba.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/dasd_fba.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,76 @@
+
+#ifndef DASD_FBA_H
+#define DASD_FBA_H
+
+typedef
+struct DE_fba_data_t {
+	struct {
+		unsigned char perm:2;	/* Permissions on this extent */
+		unsigned char zero:2;	/* Must be zero */
+		unsigned char da:1;	/* usually zero */
+		unsigned char diag:1;	/* allow diagnose */
+		unsigned char zero2:2;	/* zero */
+	} __attribute__ ((packed)) mask;
+	__u8 zero;		/* Must be zero */
+	__u16 blk_size;		/* Blocksize */
+	__u32 ext_loc;		/* Extent locator */
+	__u32 ext_beg;		/* logical number of block 0 in extent */
+	__u32 ext_end;		/* logocal number of last block in extent */
+} __attribute__ ((packed)) 
+
+DE_fba_data_t;
+
+typedef
+struct LO_fba_data_t {
+	struct {
+		unsigned char zero:4;
+		unsigned char cmd:4;
+	} __attribute__ ((packed)) operation;
+	__u8 auxiliary;
+	__u16 blk_ct;
+	__u32 blk_nr;
+} __attribute__ ((packed)) 
+
+LO_fba_data_t;
+
+typedef
+struct dasd_fba_characteristics_t {
+	union {
+		__u8 c;
+		struct {
+			unsigned char reserved:1;
+			unsigned char overrunnable:1;
+			unsigned char burst_byte:1;
+			unsigned char data_chain:1;
+			unsigned char zeros:4;
+		} __attribute__ ((packed)) bits;
+	} __attribute__ ((packed)) mode;
+	union {
+		__u8 c;
+		struct {
+			unsigned char zero0:1;
+			unsigned char removable:1;
+			unsigned char shared:1;
+			unsigned char zero1:1;
+			unsigned char mam:1;
+			unsigned char zeros:3;
+		} __attribute__ ((packed)) bits;
+	} __attribute__ ((packed)) features;
+	__u8 dev_class;
+	__u8 unit_type;
+	__u16 blk_size;
+	__u32 blk_per_cycl;
+	__u32 blk_per_bound;
+	__u32 blk_bdsa;
+	__u32 reserved0;
+	__u16 reserved1;
+	__u16 blk_ce;
+	__u32 reserved2;
+	__u16 reserved3;
+} __attribute__            ((packed)) 
+
+dasd_fba_characteristics_t;
+
+int dasd_fba_init (void);
+void dasd_fba_cleanup(void);
+#endif				/* DASD_FBA_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_mdsk.c linux/drivers/s390/block/dasd_mdsk.c
--- v2.4.1/linux/drivers/s390/block/dasd_mdsk.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_mdsk.c	Wed Dec 31 16:00:00 1969
@@ -1,14 +0,0 @@
-#include <linux/dasd.h>
-#include "dasd_types.h"
-#include "dasd_erp.h"
-
-dasd_operations_t dasd_mdsk_operations =
-{
-  NULL,
-  /*	dasd_mdsk_ck_devinfo,
-	dasd_mdsk_build_req,
-	dasd_mdsk_rw_label,
-	dasd_mdsk_ck_char,
-	dasd_mdsk_fill_sizes,
-	dasd_mdsk_format, */
-};
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_proc.c linux/drivers/s390/block/dasd_proc.c
--- v2.4.1/linux/drivers/s390/block/dasd_proc.c	Sun May 21 20:34:37 2000
+++ linux/drivers/s390/block/dasd_proc.c	Wed Dec 31 16:00:00 1969
@@ -1,68 +0,0 @@
-/*
-  Structure of the proc filesystem:
-  /proc/dasd/
-  /proc/dasd/devices                  # List of devices
-  /proc/dasd/ddabcd                   # Device node for devno abcd            
-  /proc/dasd/ddabcd1                  # Device node for partition abcd  
-  /proc/dasd/abcd                     # Device information for devno abcd
-*/
-
-#include <linux/proc_fs.h>
-
-#include <linux/dasd.h>
-
-#include "dasd_types.h"
-
-int dasd_proc_read_devices ( char *, char **, off_t, int);
-#ifdef DASD_PROFILE
-extern int dasd_proc_read_statistics ( char *, char **, off_t, int);
-extern int dasd_proc_read_debug ( char *, char **, off_t, int);
-#endif /* DASD_PROFILE */
-
-static struct proc_dir_entry *dasd_proc_root_entry;
-
-void
-dasd_proc_init ( void )
-{
-	dasd_proc_root_entry = proc_mkdir("dasd", NULL);
-	create_proc_info_entry("devices",0,&dasd_proc_root_entry,dasd_proc_read_devices);
-#ifdef DASD_PROFILE
-	create_proc_info_entry("statistics",0,&dasd_proc_root_entry,dasd_proc_read_statistics);
-	create_proc_info_entry("debug",0,&dasd_proc_root_entry,dasd_proc_read_debug);
-#endif /* DASD_PROFILE */
-}
-
-
-int 
-dasd_proc_read_devices ( char * buf, char **start, off_t off, int len)
-{
-	int i;
-	len = sprintf ( buf, "dev# MAJ minor node        Format\n");
-	for ( i = 0; i < DASD_MAX_DEVICES; i++ ) {
-		dasd_information_t *info = dasd_info[i];
-		if ( ! info ) 
-			continue;
-		if ( len >= PAGE_SIZE - 80 )
-			len += sprintf ( buf + len, "terminated...\n");
-		len += sprintf ( buf + len,
-				 "%04X %3d %5d /dev/dasd%c",
-				 dasd_info[i]->info.devno,
-				 DASD_MAJOR,
-				 i << PARTN_BITS,
-				 'a' + i );
-                if (info->flags == DASD_INFO_FLAGS_NOT_FORMATTED) {
-			len += sprintf ( buf + len, "    n/a");
-		} else {
-			len += sprintf ( buf + len, " %6d", 
-					 info->sizes.bp_block);
-		}
-		len += sprintf ( buf + len, "\n");
-	} 
-	return len;
-}
-
-
-void 
-dasd_proc_add_node (int di) 
-{
-}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_profile.c linux/drivers/s390/block/dasd_profile.c
--- v2.4.1/linux/drivers/s390/block/dasd_profile.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_profile.c	Wed Dec 31 16:00:00 1969
@@ -1,208 +0,0 @@
-#include <linux/mm.h>
-
-#include <linux/dasd.h>
-
-#include "dasd_types.h"
-
-#define PRINTK_HEADER "dasd_profile:"
-
-static long dasd_io_reqs=0; /* number of requests processed at all */
-static long dasd_io_secs[16]; /* histogram of request's sizes */
-static long dasd_io_times[16]; /* histogram of requests's times */
-static long dasd_io_timps[16]; /* histogram of requests's times per sector */
-static long dasd_io_time1[16]; /* histogram of time from build to start */
-static long dasd_io_time2[16]; /* histogram of time from start to irq */
-static long dasd_io_time2ps[16]; /* histogram of time from start to irq */
-static long dasd_io_time3[16]; /* histogram of time from irq to end */
-
-void
-dasd_profile_add ( cqr_t *cqr )
-{
-	int ind;
-	long strtime,irqtime,endtime,tottime;
-	long tottimeps,sectors;
-	long help;
-	if ( ! cqr -> req ) 
-	  return;
-	sectors = cqr -> req -> nr_sectors;
-	strtime = ((cqr->startclk - cqr->buildclk) >> 12);
-	irqtime = ((cqr->stopclk - cqr->startclk) >> 12);
-	endtime = ((cqr->endclk - cqr->stopclk) >> 12);
-	tottime = ((cqr->endclk - cqr->buildclk) >> 12);
-	tottimeps = tottime / sectors;
-
-	if (! dasd_io_reqs ++){
-	  for ( ind = 0; ind < 16; ind ++) {
-		dasd_io_secs[ind] = 0;
-		dasd_io_times[ind]=0;
-		dasd_io_timps[ind]=0;
-		dasd_io_time1[ind]=0;
-		dasd_io_time2[ind]=0;
-		dasd_io_time2ps[ind]=0;
-		dasd_io_time3[ind]=0;
-	  }
-	};
-	
-	for ( ind = 0, help = sectors >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_secs[ind] ++;
-
-	for ( ind = 0, help = tottime >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_times[ind] ++;
-
-	for ( ind = 0, help = tottimeps >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_timps[ind] ++;
-
-	for ( ind = 0, help = strtime >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_time1[ind] ++;
-
-	for ( ind = 0, help = irqtime >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_time2[ind] ++;
-
-	for ( ind = 0, help = (irqtime/sectors) >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_time2ps[ind] ++;
-
-	for ( ind = 0, help = endtime >> 3; 
-	      ind < 15 && help; 
-	      help = help >> 1,ind ++);
-	dasd_io_time3[ind] ++;
-}
-
-int 
-dasd_proc_read_statistics ( char * buf, char **start, 
-			    off_t off, int len, int d)
-{
-	int i;
-	int shift, help;
-	
-	for ( shift = 0, help = dasd_io_reqs; 
-	      help > 8192; 
-	      help = help >> 1,shift ++);
-	len = sprintf ( buf, "%ld dasd I/O requests\n", dasd_io_reqs); 
-	len += sprintf ( buf+len, "__<4 ___8 __16 __32 __64 _128 _256 _512 __1k __2k __4k __8k _16k _32k _64k >64k\n");
-	len += sprintf ( buf+len, "Histogram of sizes (512B secs)\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_secs[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	len += sprintf ( buf+len, "Histogram of I/O times\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_times[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	len += sprintf ( buf+len, "Histogram of I/O times per sector\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_timps[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	len += sprintf ( buf+len, "Histogram of I/O time till ssch\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_time1[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	len += sprintf ( buf+len, "Histogram of I/O time between ssch and irq\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_time2[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	len += sprintf ( buf+len, "Histogram of I/O time between ssch and irq per sector\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_time2ps[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	len += sprintf ( buf+len, "Histogram of I/O time between irq and end\n");
-	for ( i = 0; i < 16; i ++) {
-		len += sprintf ( buf+len, "%4ld ",dasd_io_time3[i] >> shift );
-	}
-	len += sprintf ( buf+len, "\n");
-	return len;
-}
-typedef
-struct {
-	union {
-		unsigned long long  clock;
-		struct {
-			unsigned int ts1;
-			unsigned int ts2 : 20;
-			unsigned int unused : 8;
-			unsigned int cpu : 4;
-		} __attribute__ ((packed)) s;
-	} __attribute__ ((packed)) u;
-	unsigned long caller_address;
-	unsigned long tag;
-} __attribute__ ((packed)) dasd_debug_entry;
-
-static dasd_debug_entry *dasd_debug_area = NULL;
-static dasd_debug_entry *dasd_debug_actual;
-static spinlock_t debug_lock = SPIN_LOCK_UNLOCKED;
-
-void 
-dasd_debug ( unsigned long tag )
-{
-	long flags;
-	dasd_debug_entry *d;
-	/* initialize in first call ... */
-	if ( ! dasd_debug_area ) {
-		dasd_debug_actual = dasd_debug_area = 
-			(dasd_debug_entry *) get_free_page (GFP_ATOMIC);
-		if ( ! dasd_debug_area ) {
-			PRINT_WARN("No debug area allocated\n");
-			return;
-		}
-		memset (dasd_debug_area,0,PAGE_SIZE);
-	}
-	/* renormalize to page */
-	spin_lock_irqsave(&debug_lock,flags);
-	dasd_debug_actual = (dasd_debug_entry *)
-		( (unsigned long) dasd_debug_area +
-		  ( ( (unsigned long)dasd_debug_actual -
-		      (unsigned long)dasd_debug_area ) % PAGE_SIZE ) );
-	d = dasd_debug_actual ++;
-	spin_unlock_irqrestore(&debug_lock,flags);
-	/* write CPUID to lowest 12 bits of clock... */
-	__asm__ __volatile__ ( "STCK  %0"
-			       :"=m" (d->u.clock));
-	d->tag = tag;
-	d -> caller_address = (unsigned long) __builtin_return_address(0);
-	d->u.s.cpu = smp_processor_id();
-}
-
-int 
-dasd_proc_read_debug ( char * buf, char **start, 
-		       off_t off, int len, int dd)
-{
-	dasd_debug_entry *d;
-	char tag[9] = { 0, };
-	long flags;
-	spin_lock_irqsave(&debug_lock,flags);
-	len = 0;
-       	for( d = dasd_debug_area; 
-	     len < 4068 ;
-	     d ++ ) {
-		if ( *(char*)(&d->tag) == 'D' ) {
-			memcpy(tag,&(d->tag),4);
-			tag[4]=0;
-		}
-		else {
-			sprintf(tag,"%08lx", d->tag);
-			tag[8]=0;
-		}
-		len += sprintf ( buf+len,
-				 "%x %08x%05x %08lx (%8s)\n",
-				 d->u.s.cpu, d->u.s.ts1, d->u.s.ts2,
-				 d->caller_address,tag);
-	}
-	spin_unlock_irqrestore(&debug_lock,flags);
-	return len;
-}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/dasd_types.h linux/drivers/s390/block/dasd_types.h
--- v2.4.1/linux/drivers/s390/block/dasd_types.h	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/block/dasd_types.h	Wed Dec 31 16:00:00 1969
@@ -1,284 +0,0 @@
-/*
- * File...........: linux/drivers/s390/block/dasd_types.h
- * Author.........: Holger Smolinski <Holger.Smolinski@de.ibm.com>
- * Created........: 08/31/1999
- * Last Modified..: 09/29/1999
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
-
- * List of Changes:
- - Initial Release as of 09/29/1999
-
- * Description
-
- * Restrictions
-
- * Known Bugs
-
- * Todo-List
-
- */
-
-#ifndef DASD_TYPES_H
-#define DASD_TYPES_H
-
-#include <linux/config.h>
-#include <linux/dasd.h>
-#include <linux/blkdev.h>
-
-#include <asm/irq.h>
-
-#define CCW_DEFINE_EXTENT 0x63
-#define CCW_LOCATE_RECORD 0x43
-#define CCW_READ_DEVICE_CHARACTERISTICS 0x64
-
-typedef
-enum {
-	dasd_none = -1,
-#ifdef CONFIG_DASD_ECKD
-	dasd_eckd,
-#endif				/* CONFIG_DASD_ECKD */
-#ifdef CONFIG_DASD_MDSK                                        
-        dasd_mdsk,                                             
-#endif                          /* CONFIG_DASD_MDSK */         
-#ifdef CONFIG_DASD_CKD                                        
-        dasd_ckd,                                             
-#endif                          /* CONFIG_DASD_CKD */         
-        dasd_end
-} dasd_type_t;
-
-typedef
-struct {
-	__u16 cu_type;
-	struct {
-		unsigned char support:2;
-		unsigned char async:1;
-		unsigned char reserved:1;
-		unsigned char cache_info:1;
-		unsigned char model:3;
-	} __attribute__ ((packed)) cu_model;
-	__u16 dev_type;
-	__u8 dev_model;
-	struct {
-		unsigned char mult_burst:1;
-		unsigned char RT_in_LR:1;
-		unsigned char reserved1:1;
-		unsigned char RD_IN_LR:1;
-		unsigned char reserved2:4;
-		unsigned char reserved3:8;
-		unsigned char defect_wr:1;
-		unsigned char reserved4:2;
-		unsigned char striping:1;
-		unsigned char reserved5:4;
-		unsigned char cfw:1;
-		unsigned char reserved6:2;
-		unsigned char cache:1;
-		unsigned char dual_copy:1;
-		unsigned char dfw:1;
-		unsigned char reset_alleg:1;
-		unsigned char sense_down:1;
-	} __attribute__ ((packed)) facilities;
-	__u8 dev_class;
-	__u8 unit_type;
-	__u16 no_cyl;
-	__u16 trk_per_cyl;
-	__u8 sec_per_trk;
-	__u8 byte_per_track[3];
-	__u16 home_bytes;
-	__u8 formula;
-	union {
-		struct {
-			__u8 f1;
-			__u16 f2;
-			__u16 f3;
-		} __attribute__ ((packed)) f_0x01;
-		struct {
-			__u8 f1;
-			__u8 f2;
-			__u8 f3;
-			__u8 f4;
-			__u8 f5;
-		} __attribute__ ((packed)) f_0x02;
-	} __attribute__ ((packed)) factors;
-	__u16 first_alt_trk;
-	__u16 no_alt_trk;
-	__u16 first_dia_trk;
-	__u16 no_dia_trk;
-	__u16 first_sup_trk;
-	__u16 no_sup_trk;
-	__u8 MDR_ID;
-	__u8 OBR_ID;
-	__u8 director;
-	__u8 rd_trk_set;
-	__u16 max_rec_zero;
-	__u8 reserved1;
-	__u8 RWANY_in_LR;
-	__u8 factor6;
-	__u8 factor7;
-	__u8 factor8;
-	__u8 reserved2[3];
-	__u8 reserved3[10];
-} __attribute__ ((packed, aligned (32))) 
-
-dasd_eckd_characteristics_t;
-
-/* eckd count area */
-typedef struct {
-	__u16 cyl;
-	__u16 head;
-	__u8 record;
-	__u8 kl;
-	__u16 dl;
-} __attribute__ ((packed))
-
-eckd_count_t;
-
-#ifdef CONFIG_DASD_CKD
-struct dasd_ckd_characteristics {
-	char info[64];
-};
-
-#endif				/* CONFIG_DASD_CKD */
-
-#ifdef CONFIG_DASD_ECKD
-struct dasd_eckd_characteristics {
-	char info[64];
-};
-
-#endif				/* CONFIG_DASD_ECKD */
-
-typedef
-union {
-	char __attribute__ ((aligned (32))) bytes[64];
-#ifdef CONFIG_DASD_CKD
-	struct dasd_ckd_characteristics ckd;
-#endif				/* CONFIG_DASD_CKD */
-#ifdef CONFIG_DASD_ECKD
-	dasd_eckd_characteristics_t eckd;
-#endif				/* CONFIG_DASD_ECKD */
-} __attribute__ ((aligned (32))) 
-
-dasd_characteristics_t;
-
-#define CQR_STATUS_EMPTY  0x00
-#define CQR_STATUS_FILLED 0x01
-#define CQR_STATUS_QUEUED 0x02
-#define CQR_STATUS_IN_IO  0x04
-#define CQR_STATUS_DONE   0x08
-#define CQR_STATUS_RETRY  0x10
-#define CQR_STATUS_ERROR  0x20
-#define CQR_STATUS_FAILED 0x40
-#define CQR_STATUS_SLEEP  0x80
-
-#define CQR_FLAGS_SLEEP   0x01
-#define CQR_FLAGS_WAIT    0x02
-#define CQR_FLAGS_NOLOCK  0x04
-#define CQR_FLAGS_NORETRY 0x08
-
-typedef
-struct cqr_t {
-	unsigned int    magic;    /* magic number should be "DASD" */
-	atomic_t status;	/* current status of request */
-	unsigned short retries; /* counter for retry in error case */
-	unsigned short cplength;/* Length of channel program  (CP) */
-	unsigned short devindex;/* device number */
-	unsigned short flags;    /* Flags for execution */
-	
-	void * data;		/* additional data area for CP */
-	ccw1_t *cpaddr;		/* Address of CP */
-	struct request *req;	/* backpointer to struct request */
-	struct cqr_t *next;     /* forward chain in chanq */
-	struct cqr_t *int4cqr;  /* which cqr ist the nect PCI for? */
-	unsigned long long buildclk;
-	unsigned long long startclk;
-	unsigned long long stopclk;
-	unsigned long long endclk;
-	devstat_t *dstat;	/* savearea for devstat */
-	spinlock_t lock;
-	int options;
-} __attribute__ ((packed)) 
-cqr_t;
-
-typedef
-struct {
-	unsigned long int kbytes;
-	unsigned int bp_sector;
-	unsigned int bp_block;
-	unsigned int blocks;
-	unsigned int s2b_shift;
-	unsigned int b2k_shift;
-	unsigned int label_block;
-} dasd_sizes_t;
-
-#define DASD_CHANQ_ACTIVE 0x01
-#define DASD_CHANQ_BUSY 0x02
-#define DASD_REQUEST_Q_BROKEN 0x04
-
-typedef
-struct dasd_chanq_t {
-	volatile cqr_t *head;
-	volatile cqr_t *tail;
-	spinlock_t q_lock;	/* lock for queue operations */
-	spinlock_t f_lock;	/* lock for flag operations */
-	int queued_requests;
-	atomic_t flags;
-	atomic_t dirty_requests;
-	struct dasd_chanq_t *next_q;	/* pointer to next queue */
-} __attribute__ ((packed, aligned (16))) 
-dasd_chanq_t;
-
-#define DASD_INFO_FLAGS_INITIALIZED 0x01
-#define DASD_INFO_FLAGS_NOT_FORMATTED 0x02
-#define DASD_INFO_FLAGS_PARTNS_DETECTED 0x04
-
-typedef
-struct dasd_information_t {
-	devstat_t dev_status;
-	dasd_characteristics_t *rdc_data;
-	dasd_volume_label_t *label;
-	dasd_type_t type;
-	dev_info_t info;
-	dasd_sizes_t sizes;
-	dasd_chanq_t queue;
-	int open_count;
-	spinlock_t lock;
-	struct semaphore sem;
-	unsigned long flags;
-	int irq;
-	struct proc_dir_entry *proc_device;
-	devfs_handle_t devfs_entry;
-	union {
-		struct {
-			eckd_count_t count_data;
-		} eckd;
-		struct {
-			char dummy;
-		} fba;
-		struct {
-			char dummy;
-		} mdsk;
-		struct {
-			char dummy;
-		} ckd;
-	} private;
-} dasd_information_t;
-
-typedef struct {
-	int start_unit;
-	int stop_unit;
-	int blksize;
-} format_data_t;
-
-typedef
-struct {
-	int (*ck_devinfo) (dev_info_t *);
-	cqr_t *(*get_req_ccw) (int, struct request *);
-	cqr_t *(*rw_label) (int, int, char *);
-	int (*ck_characteristics) (dasd_characteristics_t *);
-	cqr_t *(*fill_sizes_first) (int);
-	int (*fill_sizes_last) (int);
-	int (*dasd_format) (int, format_data_t *);
-} dasd_operations_t;
-
-extern dasd_information_t *dasd_info[];
-
-#endif				/* DASD_TYPES_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/mdisk.c linux/drivers/s390/block/mdisk.c
--- v2.4.1/linux/drivers/s390/block/mdisk.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/s390/block/mdisk.c	Wed Dec 31 16:00:00 1969
@@ -1,790 +0,0 @@
-/*
- *  drivers/s390/block/mdisk.c
- *    VM minidisk device driver.
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner (hp@de.ibm.com)
- */
-
-
-#ifndef __KERNEL__
-#  define __KERNEL__
-#endif
-
-#define __NO_VERSION__
-#include <linux/config.h>
-#include <linux/version.h>
-
-char kernel_version [] = UTS_RELEASE;
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>              /* printk()                         */
-#include <linux/malloc.h>              /* kmalloc()                        */
-#include <linux/vmalloc.h>             /* vmalloc()                        */
-#include <linux/fs.h>                  /* everything...                    */
-#include <linux/errno.h>               /* error codes                      */
-#include <linux/timer.h>
-#include <linux/types.h>               /* size_t                           */
-#include <linux/fcntl.h>               /* O_ACCMODE                        */
-#include <linux/hdreg.h>               /* HDIO_GETGEO                      */
-#include <linux/init.h>                /* initfunc                         */
-#include <linux/interrupt.h>
-#include <linux/ctype.h>
-
-#include <asm/system.h>                /* cli(), *_flags                   */
-#include <asm/uaccess.h>               /* access_ok                        */
-#include <asm/io.h>                    /* virt_to_phys                     */
-
-	 /* Added statement HSM 12/03/99 */
-#include <asm/irq.h>
-
-#define MAJOR_NR MDISK_MAJOR /* force definitions on in blk.h */
-
-#include <linux/blk.h>
-
-
-#include "mdisk.h"        /* local definitions */
-
-/*
- * structure for all device specific information
- */
-
-typedef struct mdisk_Dev {
-	u32 vdev;   /* vdev of mindisk */
-	u32 size;   /* size in blocks */
-	u32 status; /* status of last io operation */
-	u32 nr_bhs; /* number of buffer of last io operation */
-        u32 blksize; /* blksize from minidisk */
-        u32 blkmult; /* multiplier between blksize and 512 HARDSECT */
-        u32 blkshift; /* loe2 of multiplier above */
-	/*
-	 * each device has own iob and bio,
-	 * it's possible to run io in parallel
-	 * not used yet due to only one CURRENT per MAJOR
-	 */
-	
-	mdisk_rw_io_t* iob;      /* each device has it own iob and bio */
-	mdisk_bio_t*   bio;
-	 /* Added statement HSM 12/03/99 */
-	devstat_t dev_status;    /* Here we hold the I/O status */
-
-	int usage;               /* usage counter */
-
-	struct tq_struct tqueue; /* per device task queue */
-} mdisk_Dev;
-
-
-/*
- * appended to global structures in mdisk_init;
- */
-
-static int mdisk_blksizes[MDISK_DEVS];
-static int mdisk_sizes[MDISK_DEVS] = { 0 };
-static int mdisk_hardsects[MDISK_DEVS];
-static int mdisk_maxsectors[MDISK_DEVS];
-
-/*
- *  structure hold device specific information
- */
-
-static mdisk_Dev mdisk_devices[MDISK_DEVS];
-static mdisk_rw_io_t mdisk_iob[MDISK_DEVS] __attribute__ ((aligned(8)));
-static mdisk_bio_t mdisk_bio[MDISK_DEVS][256]__attribute__ ((aligned(8)));
-
-
-/*
- * Parameter parsing
- */
-struct {
-        long vdev[MDISK_DEVS];
-	long size[MDISK_DEVS];
-	long offset[MDISK_DEVS];
-        long blksize[MDISK_DEVS];
-} mdisk_setup_data;
-
-/*
- * Parameter parsing function, called from init/main.c
- * vdev    : virtual device number
- * size    : size in kbyte
- * offset  : offset after which minidisk is available
- * blksize : blocksize minidisk is formated
- * Format is: mdisk=<vdev>:<size>:<offset>:<blksize>,<vdev>:<size>:<offset>...
- * <vdev>:<size>:<offset>:<blksize> can be shortened to <vdev>:<size> with offset=0,blksize=512
- */
-int __init mdisk_setup(char *str)
-{
-	char *cur = str;
-	int vdev, size, offset=0,blksize;
-	static int i = 0;
-	if (!i)
-	        memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data));
-
-        while (*cur != 0) {
-	        blksize=MDISK_HARDSECT;
-		vdev = size = offset = 0;
-		if (!isxdigit(*cur)) goto syntax_error;
-		vdev = simple_strtoul(cur,&cur,16);
-		if (*cur != 0 && *cur != ',') { 
-		if (*cur++ != ':') goto syntax_error;
-		if (!isxdigit(*cur)) goto syntax_error;
-		size = simple_strtoul(cur,&cur,16);
-		if (*cur == ':') { /* another colon -> offset specified */
-			cur++;
-			if (!isxdigit(*cur)) goto syntax_error;
-			offset = simple_strtoul(cur,&cur,16);
-			if (*cur == ':') { /* another colon -> blksize */
-			  cur++;
-			  if (!isxdigit(*cur)) goto syntax_error;
-			  blksize = simple_strtoul(cur,&cur,16);
-			}
-		}
-		if (*cur != ',' && *cur != 0) goto syntax_error;
-		} 
-		if (*cur == ',') cur++;
-		if (i >= MDISK_DEVS) {
-			printk(KERN_WARNING "mnd: too many devices\n");
-			return 1;
-		}
-		mdisk_setup_data.vdev[i] = vdev;
-		mdisk_setup_data.size[i] = size;
-		mdisk_setup_data.offset[i] = offset;
-		mdisk_setup_data.blksize[i] = blksize;
-
-		i++;
-	}
-	
-	return 1;
-
-syntax_error:
-        printk(KERN_WARNING "mnd: syntax error in parameter string: %s\n", str);
-	return 0;
-}
-
-__setup("mdisk=", mdisk_setup);
-
-/*
- * Open and close
- */
-
-static int mdisk_open (struct inode *inode, struct file *filp)
-{
-	mdisk_Dev *dev; /* device information */
-	int num = MINOR(inode->i_rdev);
-	
-	/* 
-	 * size 0 means device not installed
-	 */
-	if ((num >= MDISK_DEVS) || (mdisk_sizes[num] == 0))
-		return -ENODEV;
-	MOD_INC_USE_COUNT;
-	dev = &mdisk_devices[num];
-	dev->usage++;
-	return 0;          /* success */
-}
-
-static int mdisk_release (struct inode *inode, struct file *filp)
-{
-	mdisk_Dev *dev = &mdisk_devices[MINOR(inode->i_rdev)];
-	
-	/*
-	 * flush device
-	 */
-	
-	fsync_dev(inode->i_rdev);
-	dev->usage--;
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-
-/*
- * The mdisk() implementation
- */
-
-static int mdisk_ioctl (struct inode *inode, struct file *filp,
-                 unsigned int cmd, unsigned long arg)
-{
-	int err,rc, size=0;
-	struct hd_geometry *geo = (struct hd_geometry *)arg;
-	mdisk_Dev *dev = mdisk_devices + MINOR(inode->i_rdev);
-	
-	switch(cmd) {
-		
-	case BLKGETSIZE:
-	        rc = copy_to_user ((long *) arg, &dev->size, sizeof (long));
-		printk(KERN_WARNING "mnd: ioctl BLKGETSIZE %d\n",dev->size);
-		return rc;
-	case BLKFLSBUF: /* flush */
-		if (!suser()) return -EACCES; /* only root */
-		fsync_dev(inode->i_rdev);
-		invalidate_buffers(inode->i_rdev);
-		return 0;
-		
-	case BLKRAGET: /* return the readahead value */
-		if (!arg)  return -EINVAL;
-		err = access_ok(VERIFY_WRITE, (long *) arg, sizeof(long));
-		if (err) return err;
-		put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
-		return 0;
-		
-	case BLKRASET: /* set the readahead value */
-		if (!suser()) return -EACCES;
-		if (arg > 0xff) return -EINVAL; /* limit it */
-		read_ahead[MAJOR(inode->i_rdev)] = arg;
-		return 0;
-		
-	case BLKRRPART: /* re-read partition table: can't do it */
-		return -EINVAL;
-		
-	case HDIO_GETGEO:
-		/*
-		 * get geometry of device -> linear
-		 */
-		size = dev->size;
-		if (geo==NULL) return -EINVAL;
-		err = access_ok(VERIFY_WRITE, geo, sizeof(*geo));
-		if (err) return err;
-		put_user(1,    &geo->cylinders);
-		put_user(1,    &geo->heads);
-		put_user(size, &geo->sectors);
-		put_user(0,    &geo->start);
-		return 0;
-	}
-	
-	return -EINVAL; /* unknown command */
-}
-
-/*
- * The file operations
- */
-
-static struct block_device_operations mdisk_fops = {
-	ioctl:        mdisk_ioctl,
-	open:         mdisk_open,
-        release:      mdisk_release,
-};
-
-/*
- * The 'low level' IO function
- */
-
-
-static __inline__ int
-dia250(void* iob,int cmd)
-{
-	int rc;
-	
-	iob = (void*) virt_to_phys(iob);
-
-	asm volatile ("    lr    2,%1\n"
-		      "    lr    3,%2\n"
-		      "    .long 0x83230250\n"
-		      "    lr    %0,3"
-		      : "=d" (rc)
-		      : "d" (iob) , "d" (cmd)
-		      : "2", "3" );
-	return rc;
-}
-/*
- * Init of minidisk device
- */
-
-static __inline__ int
-mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size)
-{
-	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
-	int rc;
-
-	memset(iob,0,sizeof(mdisk_init_io_t));
-	
-	iob->dev_nr = dev->vdev;
-	iob->block_size = blocksize;
-	iob->offset     = offset;
-	iob->start_block= 0;
-	iob->end_block  = size;
-	
-	rc = dia250(iob,INIT_BIO);
-	
-	/*
-	 * clear for following io once
-	 */
-	
-	memset(iob,0,sizeof(mdisk_rw_io_t));
-	
-	return rc;
-}
-
-/*
- * release of minidisk device
- */
-
-static __inline__ int
-mdisk_term_io(mdisk_Dev *dev)
-{
-	mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob;
-	
-	memset(iob,0,sizeof(mdisk_init_io_t));
-	
-	iob->dev_nr = dev->vdev;
-	
-	return dia250(iob,TERM_BIO);
-}
-
-/*
- * setup and start of minidisk io request
- */
-
-static __inline__ int
-mdisk_rw_io_clustered (mdisk_Dev *dev,
-                       mdisk_bio_t* bio_array,
-                       int length,
-                       int req,
-                       int sync)
-{
-	int rc;
-	mdisk_rw_io_t *iob = dev->iob;
-	
-	iob->dev_nr      = dev->vdev;
-	iob->key         = 0;
-	iob->flags       = sync;
-	
-	iob->block_count = length;
-	iob->interrupt_params = req;
-	iob->bio_list     = virt_to_phys(bio_array);
-	
-	rc = dia250(iob,RW_BIO);
-	return rc;
-}
-
-
-
-/*
- * The device characteristics function
- */
-
-static __inline__ int
-dia210(void* devchar)
-{
-	int rc;
-
-	devchar = (void*) virt_to_phys(devchar);
-
-	asm volatile ("    lr    2,%1\n"
-		      "    .long 0x83200210\n"
-		      "    ipm   %0\n"
-		      "    srl   %0,28"
-		      : "=d" (rc)
-		      : "d" (devchar)
-		      : "2" );
-	return rc;
-}
-/*
- * read the label of a minidisk and extract its characteristics
- */
-
-static __inline__ int
-mdisk_read_label (mdisk_Dev *dev, int i)
-{
-	static mdisk_dev_char_t devchar;
-	static long label[1024];
-	int block, b;
-	int rc;
-	mdisk_bio_t *bio;
-
-	devchar.dev_nr = dev -> vdev;
-	devchar.rdc_len = sizeof(mdisk_dev_char_t);
-
-	if (dia210(&devchar) == 0) {
-		if (devchar.vdev_class == DEV_CLASS_FBA) {
-			block = 2;
-		}
-		else {
-			block = 3;
-		}
-		bio = dev->bio;
-		for (b=512;b<4097;b=b*2) {
-			rc = mdisk_init_io(dev, b, 0, 64);
-			if (rc > 4) {
-				continue;
-			}
-			memset(&bio[0], 0, sizeof(mdisk_bio_t));
-			bio[0].type = MDISK_READ_REQ;
-			bio[0].block_number = block;
-			bio[0].buffer = virt_to_phys(&label);
-			dev->nr_bhs = 1;
-			if (mdisk_rw_io_clustered(dev,
-			                          &bio[0],
-			                          1,
-			                          (unsigned long) dev,
-			                          MDISK_SYNC)
-			    == 0 ) {
-				if (label[0] != 0xc3d4e2f1) { /* CMS1 */
-					printk ( KERN_WARNING "mnd: %4lX "
-					         "is not CMS format\n",
-					         mdisk_setup_data.vdev[i]);
-					rc = mdisk_term_io(dev);
-					return 1;
-				}
-				if (label[13] == 0) {
-					printk ( KERN_WARNING "mnd: %4lX "
-		   		         "is not reserved\n",
-					         mdisk_setup_data.vdev[i]);
-					rc = mdisk_term_io(dev);
-					return 2;
-				}
-				mdisk_setup_data.size[i] =
-				   (label[7] - 1 - label[13]) *
-				   (label[3] >> 9) >> 1;
-				mdisk_setup_data.blksize[i] = label[3];
-				mdisk_setup_data.offset[i] = label[13] + 1;
-				rc = mdisk_term_io(dev);
-				return rc;
-			}
-			rc = mdisk_term_io(dev);
-		}
-		printk ( KERN_WARNING "mnd: Cannot read label of %4lX "
-			 "- is it formatted?\n",
-			 mdisk_setup_data.vdev[i]);
-		return 3;
-	}
-	return 4;
-}
-
-
-
-
-
-/*
- * this handles a clustered request in success case
- * all buffers are detach and marked uptodate to the kernel
- * then CURRENT->bh is set to the last processed but not
- * update buffer
- */
-
-static __inline__ void
-mdisk_end_request(int nr_bhs)
-{
-	int i;
-	struct buffer_head *bh;
-	struct request *req;
-
-	if (nr_bhs > 1) {
-		req = CURRENT;
-		bh  = req->bh;
-		
-		for (i=0; i < nr_bhs-1; i++) {
-			req->bh = bh->b_reqnext;
-			bh->b_reqnext = NULL;
-			bh->b_end_io(bh,1);
-			bh = req->bh;			
-		}
-		
-		/*
-		 * set CURRENT to last processed, not marked buffer
-		 */
-		req->buffer = bh->b_data;
-		req->current_nr_sectors = bh->b_size >> 9;
-		CURRENT = req;
-	}
-	end_request(1);
-}
-
-
-
-/*
- * Block-driver specific functions
- */
-
-void mdisk_request(request_queue_t *queue)
-{
-	mdisk_Dev *dev;
-	mdisk_bio_t *bio;
-	struct buffer_head *bh;
-	unsigned int sector, nr, offset;
-	int rc,rw,i;
-
-	i = 0;
-	while(CURRENT) {
-		INIT_REQUEST;
-		
-		/* Check if the minor number is in range */
-		if (DEVICE_NR(CURRENT_DEV) > MDISK_DEVS) {
-			static int count = 0;
-			if (count++ < 5) /* print the message at most five times */
-				printk(KERN_WARNING "mnd: request for minor %d out of range\n",
-				       DEVICE_NR(CURRENT_DEV)  )       ;
-			end_request(0);
-			continue;
-		}
-		
-		/*
-		 * Pointer to device structure, from the static array
-		 */
-		dev = mdisk_devices + DEVICE_NR(CURRENT_DEV);
-		
-		/*
-		 * check, if operation is past end of devices
-		 */
-		if (CURRENT->nr_sectors + CURRENT->sector > dev->size) {
-			static int count = 0;
-			if (count++ < 5)
-				printk(KERN_WARNING "mnd%c: request past end of device\n",
-				       DEVICE_NR(CURRENT_DEV));
-			end_request(0);
-			continue;
-		}
-		
-		/*
-		 * do command (read or write)
-		 */
-		switch(CURRENT->cmd) {
-		case READ:
-			rw = MDISK_READ_REQ;
-			break;
-		case WRITE:
-			rw = MDISK_WRITE_REQ;
-			break;
-		default:
-			/* can't happen */
-			end_request(0);
-			continue;
-		}
-		
-		/*
-		 * put the clustered requests in mdisk_bio array
-		 * nr_sectors is checked against max_sectors in make_request
-		 * nr_sectors and sector are always blocks of 512 
-		 * but bh_size depends on the filesystems size
-		 */
-		sector = CURRENT->sector>>dev->blkshift;
-		bh     = CURRENT->bh;
-		bio    = dev->bio;
-		dev->nr_bhs = 0;
-		
-		/*
-		 * sector is translated to block in minidisk context
-		 * 
-		 */
-		offset = 0;
-
-
-		
-		for (nr = 0,i = 0; 
-		     nr < CURRENT->nr_sectors && bh;
-		     nr+=dev->blkmult, sector++,i++) {
-			memset(&bio[i], 0, sizeof(mdisk_bio_t));
-			bio[i].type   = rw;
-			bio[i].block_number = sector;
-			bio[i].buffer  = virt_to_phys(bh->b_data+offset);
-			offset += dev->blksize;
-			if (bh->b_size <= offset) {
-				offset = 0;
-				bh = bh->b_reqnext;
-				dev->nr_bhs++;
-			}
-		}
-
-		if (( rc = mdisk_rw_io_clustered(dev, &bio[0], i,
-						 (unsigned long) dev,
-#ifdef CONFIG_MDISK_SYNC
-						 MDISK_SYNC
-#else
-						 MDISK_ASYNC
-#endif
-			)) > 8 ) {
-			printk(KERN_WARNING "mnd%c: %s request failed rc %d"
-			       " sector %ld nr_sectors %ld \n",
-			       DEVICE_NR(CURRENT_DEV),
-			       rw == MDISK_READ_REQ ? "read" : "write",
-			       rc, CURRENT->sector, CURRENT->nr_sectors);
-			end_request(0);
-			continue;
-		}
-		i = 0;		
-		/*
-		 * Synchron: looping to end of request (INIT_REQUEST has return)
-		 * Asynchron: end_request done in bottom half
-		 */
-#ifdef CONFIG_MDISK_SYNC
-		mdisk_end_request(dev->nr_bhs);
-#else
-		if (rc == 0)
-		        mdisk_end_request(dev->nr_bhs);
-		else
-		return;
-#endif	
-	}
-}
-
-
-/*
- * mdisk interrupt handler called when read/write request finished
- * queues and marks a bottom half.
- *
- */
-void do_mdisk_interrupt(void)
-{
-        u16 code;
-	mdisk_Dev *dev;
-	
-	code = S390_lowcore.cpu_addr;
-
-	if ((code >> 8) != 0x03) {
-	  printk("mnd: wrong sub-interruption code %d",code>>8);
-	  return;
-	}
-
-	/*
-	 * pointer to devives structure given as external interruption
-	 * parameter
-	 */
-	dev = (mdisk_Dev*) S390_lowcore.ext_params;
-	dev->status = code & 0x00ff;
-
-	queue_task(&dev->tqueue, &tq_immediate);
-	mark_bh(IMMEDIATE_BH);
-}
-
-/*
- * the bottom half checks the status of request
- * on success it calls end_request and calls mdisk_request
- * if more transfer to do
- */
-
-static void
-do_mdisk_bh(void *data)
-{
-	mdisk_Dev *dev = (mdisk_Dev*) data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&io_request_lock, flags);
-	/*
-	 * check for status of asynchronous rw
-	 */
-	if (dev->status != 0x00) {
-		printk("mnd: status of async rw %d",dev->status);
-		end_request(0);
-	} else {
-		/*
-		 * end request for clustered requests
-		 */
-	  if (CURRENT)
-		mdisk_end_request(dev->nr_bhs);
-	}
-
-	/*
-	 * if more to do, call mdisk_request
-	 */
-	if (CURRENT)
-		mdisk_request(NULL);
-	spin_unlock_irqrestore(&io_request_lock, flags);
-}
-
-void /* Added fuction HSM 12/03/99 */
-mdisk_handler (int cpu, void *ds, struct pt_regs *regs)
-{
-	printk (KERN_ERR "mnd: received I/O interrupt... shouldn't happen\n");
-}
-
-int __init mdisk_init(void)
-{
-        int rc,i;
-        mdisk_Dev *dev;
-	request_queue_t *q;
-
-	/*
-	 * register block device
-	 */
-	if (register_blkdev(MAJOR_NR,"mnd",&mdisk_fops) < 0) {
-		printk("mnd: unable to get major %d for mini disk\n"
-		       ,MAJOR_NR);
-		return MAJOR_NR;
-	}
-        q = BLK_DEFAULT_QUEUE(MAJOR_NR);
-        blk_init_queue(q, mdisk_request);
-        blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
-	
-	/*
-	 * setup sizes for available devices
-	 */
-	read_ahead[MAJOR_NR] = MDISK_RAHEAD;	/* 8 sector (4kB) read-ahead */
-	blk_size[MAJOR_NR] = mdisk_sizes;       /* size of reserved mdisk    */
-	blksize_size[MAJOR_NR] = mdisk_blksizes;   /* blksize of device      */
-	hardsect_size[MAJOR_NR] = mdisk_hardsects;
-	max_sectors[MAJOR_NR]   = mdisk_maxsectors;
-	blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST);
-	
-	for (i=0;i<MDISK_DEVS;i++) {
-		if (mdisk_setup_data.vdev[i] == 0) {
-			continue;
-		}
-		/* Added block HSM 12/03/99 */
-		if ( request_irq(get_irq_by_devno(mdisk_setup_data.vdev[i]),
-				 mdisk_handler, 0, "mnd",
-				 &(mdisk_devices[i].dev_status)) ){
-			printk ( KERN_WARNING "mnd: Cannot acquire I/O irq of"
-				 " %4lX for paranoia reasons, skipping\n",
-				 mdisk_setup_data.vdev[i]);
-			continue;
-		}
-		/*
-		 * open VM minidisk low level device
-		 */
-		dev = &mdisk_devices[i];
-		dev->bio=mdisk_bio[i];
-		dev->iob=&mdisk_iob[i];
-		dev->vdev = mdisk_setup_data.vdev[i];
-
-		if ( mdisk_setup_data.size[i] == 0 )
-		        rc = mdisk_read_label(dev, i);
-		dev->size = mdisk_setup_data.size[i] * 2; /* buffer 512 b */
-		dev->blksize = mdisk_setup_data.blksize[i]; 
-		dev->tqueue.routine = do_mdisk_bh;
-		dev->tqueue.data = dev;
-		dev->blkmult = dev->blksize/512;
-		dev->blkshift = 
-		  dev->blkmult==1?0:
-		  dev->blkmult==2?1:
-		  dev->blkmult==4?2:
-		  dev->blkmult==8?3:-1;
-
-		mdisk_sizes[i] = mdisk_setup_data.size[i];
-		mdisk_blksizes[i]  = mdisk_setup_data.blksize[i];
-		mdisk_hardsects[i] = mdisk_setup_data.blksize[i];
-
-		/*
-		 * max sectors for one clustered req  
-		 */
-		mdisk_maxsectors[i] = MDISK_MAXSECTORS*dev->blkmult;
-
-		rc = mdisk_init_io(dev,
-				   mdisk_setup_data.blksize[i],
-				   mdisk_setup_data.offset[i],/* offset in vdev*/
-				   dev->size>>dev->blkshift  /* size in blocks */
-			);
-		if (rc > 4) {
-			printk("mnd%c: init failed (rc: %d)\n",'a'+i,rc);
-			mdisk_sizes[i] = 0;
-			continue;
-		}
-		
-		/*
-		 * set vdev in device structure for further rw access
-		 * vdev and size given by linload
-		 */
-		printk("mnd%c: register device at major %X with %d blocks %d blksize \n",
-		       'a' + i, MAJOR_NR, dev->size>>dev->blkshift,dev->blkmult*512);
-	}
-	
-	/*
-	 * enable service-signal external interruptions,
-	 * Control Register 0 bit 22 := 1
-	 * (besides PSW bit 7 must be set to 1 somewhere for external
-	 * interruptions)
-	 */
-        ctl_set_bit(0, 9);
-	
-        return 0;
-}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/mdisk.h linux/drivers/s390/block/mdisk.h
--- v2.4.1/linux/drivers/s390/block/mdisk.h	Thu Oct 26 23:35:48 2000
+++ linux/drivers/s390/block/mdisk.h	Wed Dec 31 16:00:00 1969
@@ -1,94 +0,0 @@
-/*
- *  drivers/s390/block/mdisk.h
- *    VM minidisk device driver.
- *
- *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner (hp@de.ibm.com)
- */
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define MDISK_DEVS 8                   /* for disks                        */
-#define MDISK_RAHEAD 8                 /* read ahead                       */
-#define MDISK_BLKSIZE 1024             /* 1k blocks                        */
-#define MDISK_HARDSECT 512             /* FIXME -- 512 byte blocks         */
-#define MDISK_MAXSECTORS 256           /* max sectors for one request      */
-
-
-
-/* 
- * low level io defines for diagnose 250
- */
-
-#define MDISK_WRITE_REQ 0x01                                                 
-#define MDISK_READ_REQ  0x02                                                   
-
-#define MDISK_SYNC      0x00
-#define MDISK_ASYNC     0x02
-#define INIT_BIO        0x00
-#define RW_BIO          0x01
-#define TERM_BIO        0x02
-
-/*
- * This stucture is used for clustered request
- * up to 256 different request can be handled with one invocation
- */
-
-typedef struct {
-        u8      type;
-        u8      status;
-        u16     spare1;
-        u32     block_number;
-        u32     alet;
-        u32     buffer;
-} mdisk_bio_t;
-
-typedef struct {
-        u16     dev_nr;
-        u16     spare1[11];
-        u32     block_size;
-        u32     offset;
-        u32     start_block;
-        u32     end_block;
-        u32     spare2[6];
-} mdisk_init_io_t;
- 
-typedef struct {
-        u16     dev_nr;
-        u16     spare1[11];
-        u8      key;
-        u8      flags;
-        u16     spare2;
-        u32     block_count;
-        u32     alet;
-        u32     bio_list;
-        u32     interrupt_params;
-        u32     spare3[5];
-} mdisk_rw_io_t;
-
-/*
- * low level definitions for Diagnose 210
- */
-
-#define DEV_CLASS_FBA   0x01
-
-/*
- * Data structures for Diagnose 210
- */
-
-typedef struct {
-        u16     dev_nr;
-        u16     rdc_len;
-        u8      vdev_class;
-        u8      vdev_type;
-        u8      vdev_status;
-        u8      vdev_flags;
-        u8      rdev_class;
-        u8      rdev_type;
-        u8      rdev_model;
-        u8      rdev_features;
-} mdisk_dev_char_t;
-
-                                                                               
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/xpram.c linux/drivers/s390/block/xpram.c
--- v2.4.1/linux/drivers/s390/block/xpram.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/xpram.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,1231 @@
+
+/*
+ * Xpram.c -- the S/390 expanded memory RAM-disk
+ *           
+ * significant parts of this code are based on
+ * the sbull device driver presented in
+ * A. Rubini: Linux Device Drivers
+ *
+ * Author of XPRAM specific coding: Reinhard Buendgen
+ *                                  buendgen@de.ibm.com
+ *
+ * External interfaces:
+ *   Interfaces to linux kernel
+ *        xpram_setup: read kernel parameters   (see init/main.c)
+ *        xpram_init:  initialize device driver (see drivers/block/ll_rw_blk.c)
+ *   Module interfaces
+ *        init_module
+ *        cleanup_module
+ *   Device specific file operations
+ *        xpram_iotcl
+ *        xpram_open
+ *        xpram_release
+ *
+ * "ad-hoc" partitioning:         
+ *    the expanded memory can be partitioned among several devices 
+ *    (with different minors). The partitioning set up can be
+ *    set by kernel or module parameters (int devs & int sizes[])
+ *
+ *    module parameters: devs= and sizes=
+ *    kernel parameters: xpram_parts=
+ *      note: I did not succeed in parsing numbers 
+ *            for module parameters of type string "s" ?!?
+ *
+ * Other kenel files/modules affected(gerp for "xpram" or "XPRAM":
+ *    drivers/s390/Config.in
+ *    drivers/s390/block/Makefile
+ *    include/linux/blk.h
+ *    include/linux/major.h
+ *    init/main.c
+ *    drivers/block//ll_rw_blk.c
+ *
+ *
+ * Potential future improvements:
+ *   request clustering: first coding started not yet tested or integrated
+ *                       I doubt that it really pays off 
+ *   generic hard disk support to replace ad-hoc partitioning
+ *
+ * Tested with 2.2.14 (under VM)
+ */
+
+#ifdef MODULE
+#  ifndef __KERNEL__
+#    define __KERNEL__
+#  endif
+#  define __NO_VERSION__ /* don't define kernel_version in module.h */
+#endif /* MODULE */
+
+#include <linux/module.h>
+#include <linux/version.h>
+
+#ifdef MODULE
+char kernel_version [] = UTS_RELEASE; 
+#endif
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#  define XPRAM_VERSION 24
+#else
+#  define XPRAM_VERSION 22
+#endif 
+
+#if (XPRAM_VERSION == 24)
+#  include <linux/config.h>
+#  include <linux/init.h>
+#endif /* V24 */
+#include <linux/sched.h>
+#include <linux/kernel.h> /* printk() */
+#include <linux/malloc.h> /* kmalloc() */
+#if (XPRAM_VERSION == 24)
+#  include <linux/devfs_fs_kernel.h>
+#endif /* V24 */
+#include <linux/fs.h>     /* everything... */
+#include <linux/errno.h>  /* error codes */
+#include <linux/timer.h>
+#include <linux/types.h>  /* size_t */
+#include <linux/ctype.h>  /* isdigit, isxdigit */
+#include <linux/fcntl.h>  /* O_ACCMODE */
+#include <linux/hdreg.h>  /* HDIO_GETGEO */
+
+#include <asm/system.h>   /* cli(), *_flags */
+#include <asm/uaccess.h>  /* put_user */
+
+#if (XPRAM_VERSION == 24)
+#define MAJOR_NR xpram_major /* force definitions on in blk.h */
+int xpram_major;   /* must be declared before including blk.h */
+
+#define DEVICE_NR(device) MINOR(device)   /* xpram has no partition bits */
+#define DEVICE_NAME "xpram"               /* name for messaging */
+#define DEVICE_INTR xpram_intrptr         /* pointer to the bottom half */
+#define DEVICE_NO_RANDOM                  /* no entropy to contribute */
+#define DEVICE_OFF(d)                     /* do-nothing */
+
+#include <linux/blk.h>
+
+#include "xpram.h"        /* local definitions */
+
+__setup("xpram_parts=", xpram_setup);
+#endif /* V24 */
+
+/*
+   define the debug levels:
+   - 0 No debugging output to console or syslog
+   - 1 Log internal errors to syslog, ignore check conditions 
+   - 2 Log internal errors and check conditions to syslog
+   - 3 Log internal errors to console, log check conditions to syslog
+   - 4 Log internal errors and check conditions to console
+   - 5 panic on internal errors, log check conditions to console
+   - 6 panic on both, internal errors and check conditions
+ */
+#define XPRAM_DEBUG 4
+
+#define PRINTK_HEADER XPRAM_NAME
+
+#if XPRAM_DEBUG > 0
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER "debug:" x )
+#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER "info:" x )
+#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER "warning:" x )
+#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER "error:" x )
+#define PRINT_FATAL(x...) panic ( PRINTK_HEADER "panic:"x )
+#else
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER "debug:"  x )
+#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER "info:" x )
+#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER "warning:" x )
+#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER "error:" x )
+#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER "panic:" x )
+#endif	
+
+#if (XPRAM_VERSION == 22)
+#define MAJOR_NR xpram_major /* force definitions on in blk.h */
+int xpram_major;   /* must be declared before including blk.h */
+
+#define DEVICE_NR(device) MINOR(device)   /* xpram has no partition bits */
+#define DEVICE_NAME "xpram"               /* name for messaging */
+#define DEVICE_INTR xpram_intrptr         /* pointer to the bottom half */
+#define DEVICE_NO_RANDOM                  /* no entropy to contribute */
+
+
+#define DEVICE_OFF(d) /* do-nothing */
+
+#define DEVICE_REQUEST *xpram_dummy_device_request  /* dummy function variable 
+						     * to prevent warnings 
+						     */#include <linux/blk.h>
+
+#include "xpram.h"        /* local definitions */
+#endif /* V22 */
+
+/*
+ * Non-prefixed symbols are static. They are meant to be assigned at
+ * load time. Prefixed symbols are not static, so they can be used in
+ * debugging. They are hidden anyways by register_symtab() unless
+ * XPRAM_DEBUG is defined.
+ */
+
+static int major    = XPRAM_MAJOR;
+static int devs     = XPRAM_DEVS;
+static int rahead   = XPRAM_RAHEAD;
+static int sizes[XPRAM_MAX_DEVS] = { 0, };
+static int blksize  = XPRAM_BLKSIZE;
+static int hardsect = XPRAM_HARDSECT;
+
+int xpram_devs, xpram_rahead;
+int xpram_blksize, xpram_hardsect;
+int xpram_mem_avail = 0;
+int xpram_sizes[XPRAM_MAX_DEVS];
+
+
+MODULE_PARM(devs,"i");
+MODULE_PARM(sizes,"1-" __MODULE_STRING(XPRAM_MAX_DEVS) "i"); 
+
+MODULE_PARM_DESC(devs, "number of devices (\"partitions\"), " \
+		 "the default is " __MODULE_STRING(XPRAM_DEVS) "\n");
+MODULE_PARM_DESC(sizes, "list of device (partition) sizes " \
+		 "the defaults are 0s \n" \
+		 "All devices with size 0 equally partition the "
+		 "remaining space on the expanded strorage not "
+		 "claimed by explicit sizes\n");
+
+
+
+/* The following items are obtained through kmalloc() in init_module() */
+
+Xpram_Dev *xpram_devices = NULL;
+int *xpram_blksizes = NULL;
+int *xpram_hardsects = NULL;
+int *xpram_offsets = NULL;   /* partition offsets */
+
+#define MIN(x,y) ((x) < (y) ? (x) : (y))
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+/* 
+ *              compute nearest multiple of 4 , argument must be non-negative
+ *              the macros used depends on XPRAM_KB_IN_PG = 4 
+ */
+
+#define NEXT4(x) ((x & 0x3) ? (x+4-(x &0x3)) : (x))   /* increment if needed */
+#define LAST4(x) ((x & 0x3) ? (x-4+(x & 0x3)) : (x))  /* decrement if needed */
+
+#if 0               /* this is probably not faster than the previous code */
+#define NEXT4(x)   ((((x-1)>>2)>>2)+4)             /* increment if needed */
+#define LAST4(x)   (((x+3)>>2)<<2)                 /* decrement if needed */
+#endif
+
+/* integer formats */
+#define XPRAM_INVALF -1    /* invalid     */
+#define XPRAM_HEXF    0    /* hexadecimal */
+#define XPRAM_DECF    1    /* decimal     */
+
+/* 
+ *    parsing operations (needed for kernel parameter parsing)
+ */
+
+/* -------------------------------------------------------------------------
+ * sets the string pointer after the next comma 
+ *
+ * argument:    strptr pointer to string
+ * side effect: strptr points to endof string or to position of the next 
+ *              comma 
+ * ------------------------------------------------------------------------*/
+static void
+xpram_scan_to_next_comma (char **strptr)
+{
+	while ( ((**strptr) != ',') && (**strptr) )
+		(*strptr)++;
+}
+
+/* -------------------------------------------------------------------------
+ * interpret character as hex-digit
+ *
+ * argument: c charcter
+ * result: c interpreted as hex-digit
+ * note: can be used to read digits for any base <= 16
+ * ------------------------------------------------------------------------*/
+static int
+xpram_get_hexdigit (char c)
+{
+	if ((c >= '0') && (c <= '9'))
+		return c - '0';
+	if ((c >= 'a') && (c <= 'f'))
+		return c + 10 - 'a';
+	if ((c >= 'A') && (c <= 'F'))
+		return c + 10 - 'A';
+	return -1;
+}
+
+/*--------------------------------------------------------------------------
+ * Check format of unsigned integer
+ *
+ * Argument: strptr pointer to string 
+ * result:   -1 if strptr does not start with a digit 
+ *                (does not start an integer)
+ *           0  if strptr starts a positive hex-integer with "0x" 
+ *           1  if strptr start a positive decimal integer
+ *
+ * side effect: if strptr start a positive hex-integer then strptr is
+ *              set to the character after the "0x"
+ *-------------------------------------------------------------------------*/
+static int
+xpram_int_format(char **strptr)
+{
+	if ( !isdigit(**strptr) )
+		return XPRAM_INVALF;
+	if ( (**strptr == '0') 
+	     && ( (*((*strptr)+1) == 'x') || (*((*strptr) +1) == 'X') ) 
+	     && isdigit(*((*strptr)+3)) ) {
+		*strptr=(*strptr)+2;
+		return XPRAM_HEXF;
+	} else return XPRAM_DECF;
+}
+
+/*--------------------------------------------------------------------------
+ * Read non-negative decimal integer
+ *
+ * Argument: strptr pointer to string starting with a non-negative integer
+ *           in decimal format
+ * result:   the value of theinitial integer pointed to by strptr
+ *
+ * side effect: strptr is set to the first character following the integer
+ *-------------------------------------------------------------------------*/
+
+static int
+xpram_read_decint (char ** strptr)
+{
+	int res=0;
+	while ( isdigit(**strptr) ) {
+		res = (res*10) + xpram_get_hexdigit(**strptr);
+		(*strptr)++;
+	}
+	return res;
+}
+
+/*--------------------------------------------------------------------------
+ * Read non-negative hex-integer
+ *
+ * Argument: strptr pointer to string starting with a non-negative integer
+ *           in hexformat (without "0x" prefix)
+ * result:   the value of the initial integer pointed to by strptr
+ *
+ * side effect: strptr is set to the first character following the integer
+ *-------------------------------------------------------------------------*/
+
+static int
+xpram_read_hexint (char ** strptr)
+{
+	int res=0;
+	while ( isxdigit(**strptr) ) {
+		res = (res<<4) + xpram_get_hexdigit(**strptr);
+		(*strptr)++;
+	}
+	return res;
+}
+/*--------------------------------------------------------------------------
+ * Read non-negative integer
+ *
+ * Argument: strptr pointer to string starting with a non-negative integer
+             (either in decimal- or in hex-format
+ * result:   the value of the initial integer pointed to by strptr
+ *           in case of a parsing error the result is -EINVAL
+ *
+ * side effect: strptr is set to the first character following the integer
+ *-------------------------------------------------------------------------*/
+
+static int
+xpram_read_int (char ** strptr)
+{
+	switch (  xpram_int_format(strptr) ) {
+	case XPRAM_INVALF: return -EINVAL;
+	case XPRAM_HEXF:   return xpram_read_hexint(strptr);
+	case XPRAM_DECF:   return xpram_read_decint(strptr);
+	default: return -EINVAL;
+	}
+}
+
+/*--------------------------------------------------------------------------
+ * Read size
+ *
+ * Argument: strptr pointer to string starting with a non-negative integer
+ *           followed optionally by a size modifier:
+ *             k or K for kilo (default),
+ *             m or M for mega
+ *             g or G for giga
+ * result:   the value of the initial integer pointed to by strptr
+ *           multiplied by the modifier value devided by 1024
+ *           in case of a parsing error the result is -EINVAL
+ *
+ * side effect: strptr is set to the first character following the size
+ *-------------------------------------------------------------------------*/
+
+static int
+xpram_read_size (char ** strptr)
+{
+	int res;
+  
+	res=xpram_read_int(strptr);
+	if ( res < 0 )return res;
+	switch ( **strptr ) {
+	case 'g':
+	case 'G': res=res*1024;
+	case 'm':
+	case 'M': res=res*1024;
+	case 'k' :
+	case 'K' : (* strptr)++;
+	}
+  
+	return res;
+}
+
+
+/*--------------------------------------------------------------------------
+ * Read tail of comma separated size list  ",i1,i2,...,in"
+ *
+ * Arguments:strptr pointer to string. It is assumed that the string has
+ *                  the format (","<size>)*
+ *           maxl integer describing the maximal number of elements in the
+                  list pointed to by strptr, max must be > 0.
+ *           ilist array of dimension >= maxl of integers to be modified
+ *
+ * result:   -EINVAL if the list is longer than maxl
+ *           0 otherwise
+ *
+ * side effects: for j=1,...,n ilist[ij] is set to the value of ij if it is
+ *               a valid non-negative integer and to -EINVAL otherwise
+ *               if no comma is found where it is expected an entry in
+ *               ilist is set to -EINVAL
+ *-------------------------------------------------------------------------*/
+static int
+xpram_read_size_list_tail (char ** strptr, int maxl, int * ilist)
+{ 
+	int i=0;
+	char *str = *strptr;
+	int res=0;
+
+	while ( (*str == ',') && (i < maxl) ) {
+		str++;      
+		ilist[i] = xpram_read_size(&str);
+		if ( ilist[i] == -EINVAL ) {
+			xpram_scan_to_next_comma(&str);
+			res = -EINVAL;
+		}
+		i++;
+	}
+	return res;
+#if 0  /* be lenient about trailing stuff */
+	if ( *str != 0 && *str != ' ' ) {
+		ilist[MAX(i-1,0)] = -EINVAL;
+		return -EINVAL;
+	} else return 0;
+#endif
+}
+
+
+/*
+ *   expanded memory operations
+ */
+
+
+/*--------------------------------------------------------------------*/
+/* Copy expanded memory page (4kB) into main memory                   */
+/* Arguments                                                          */
+/*           page_addr:    address of target page                     */
+/*           xpage_index:  index of expandeded memory page            */
+/* Return value                                                       */
+/*           0:            if operation succeeds                      */
+/*           non-0:       otherwise                                   */
+/*--------------------------------------------------------------------*/
+long xpram_page_in (unsigned long page_addr, unsigned long xpage_index)
+{
+	int cc=0;
+	unsigned long real_page_addr = __pa(page_addr);
+#ifndef CONFIG_ARCH_S390X
+	__asm__ __volatile__ (
+		"   lr  1,%1         \n"   /* r1 = real_page_addr            */
+		"   lr  2,%2         \n"   /* r2 = xpage_index               */
+		"   .long 0xb22e0012 \n"   /* pgin r1,r2                     */
+		/* copy page from expanded memory */
+		"0: ipm  %0          \n"   /* save status (cc & program mask */
+		"   srl  %0,28       \n"   /* cc into least significant bits */
+                "1:                  \n"   /* we are done                    */
+                ".section .fixup,\"ax\"\n" /* start of fix up section        */
+                "2: lhi    %0,2      \n"   /* return unused condition code 2 */
+                "   bras 1,3f        \n"   /* safe label 1: in r1 and goto 3 */
+                "   .long 1b         \n"   /* literal containing label 1     */
+                "3: l    1,0(1)      \n"   /* load label 1 address into r1   */
+                "   br   1           \n"   /* goto label 1 (across sections) */
+                ".previous           \n"   /* back in text section           */
+                ".section __ex_table,\"a\"\n" /* start __extable             */
+                "   .align 4         \n"
+                "   .long 0b,2b      \n"   /* failure point 0, fixup code 2  */
+                ".previous           \n"
+		: "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
+		);
+#else /* CONFIG_ARCH_S390X */
+	__asm__ __volatile__ (
+		"   lgr  1,%1        \n"   /* r1 = real_page_addr            */
+		"   lgr  2,%2        \n"   /* r2 = xpage_index               */
+		"   .long 0xb22e0012 \n"   /* pgin r1,r2                     */
+		/* copy page from expanded memory */
+		"0: ipm  %0          \n"   /* save status (cc & program mask */
+		"   srl  %0,28       \n"   /* cc into least significant bits */
+                "1:                  \n"   /* we are done                    */
+                ".section .fixup,\"ax\"\n" /* start of fix up section        */
+                "2: lghi %0,2        \n"   /* return unused condition code 2 */
+                "   jg   1b          \n"   /* goto label 1 above             */
+                ".previous           \n"   /* back in text section           */
+                ".section __ex_table,\"a\"\n" /* start __extable             */
+                "   .align 8         \n"
+                "   .quad 0b,2b      \n"   /* failure point 0, fixup code 2  */
+                ".previous           \n"
+		: "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
+		);
+#endif /* CONFIG_ARCH_S390X */
+	switch (cc) {
+	case 0: return 0;
+	case 1: return -EIO;
+        case 2: return -ENXIO;
+	case 3: return -ENXIO;
+	default: return -EIO;  /* should not happen */
+	};
+}
+
+/*--------------------------------------------------------------------*/
+/* Copy a 4kB page of main memory to an expanded memory page          */
+/* Arguments                                                          */
+/*           page_addr:    address of source page                     */
+/*           xpage_index:  index of expandeded memory page            */
+/* Return value                                                       */
+/*           0:            if operation succeeds                      */
+/*           non-0:        otherwise                                  */
+/*--------------------------------------------------------------------*/
+long xpram_page_out (unsigned long page_addr, unsigned long xpage_index)
+{
+	int cc=0;
+	unsigned long real_page_addr = __pa(page_addr);
+#ifndef CONFIG_ARCH_S390X
+	__asm__ __volatile__ (
+		"  lr  1,%1        \n"   /* r1 = mem_page                  */
+		"  lr  2,%2        \n"   /* r2 = rpi                       */
+		" .long 0xb22f0012 \n"   /* pgout r1,r2                    */
+                                /* copy page from expanded memory */
+		"0: ipm  %0        \n"   /* save status (cc & program mask */
+                " srl  %0,28       \n"   /* cc into least significant bits */
+                "1:                  \n"   /* we are done                    */
+                ".section .fixup,\"ax\"\n" /* start of fix up section        */
+                "2: lhi   %0,2       \n"   /* return unused condition code 2 */
+                "   bras 1,3f        \n"   /* safe label 1: in r1 and goto 3 */
+                "   .long 1b         \n"   /* literal containing label 1     */
+                "3: l    1,0(1)      \n"   /* load label 1 address into r1   */
+                "   br   1           \n"   /* goto label 1 (across sections) */
+                ".previous           \n"   /* back in text section           */
+                ".section __ex_table,\"a\"\n" /* start __extable             */
+                "   .align 4         \n"
+                "   .long 0b,2b      \n"   /* failure point 0, fixup code 2  */
+                ".previous           \n"
+		: "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
+		);
+#else /* CONFIG_ARCH_S390X */
+	__asm__ __volatile__ (
+		"  lgr  1,%1       \n"   /* r1 = mem_page                  */
+		"  lgr  2,%2       \n"   /* r2 = rpi                       */
+		" .long 0xb22f0012 \n"   /* pgout r1,r2                    */
+                                         /* copy page from expanded memory */
+		"0: ipm  %0        \n"   /* save status (cc & program mask */
+                "  srl  %0,28      \n"   /* cc into least significant bits */
+                "1:                \n"   /* we are done                    */
+                ".section .fixup,\"ax\"\n" /* start of fix up section      */
+                "2: lghi %0,2      \n"   /* return unused condition code 2 */
+                "   jg   1b        \n"   /* goto label 1 above             */
+                ".previous         \n"   /* back in text section           */
+                ".section __ex_table,\"a\"\n" /* start __extable           */
+                "   .align 8       \n"
+                "   .quad 0b,2b    \n"   /* failure point 0, fixup code 2  */
+                ".previous         \n"
+		: "=d" (cc) : "d" (real_page_addr), "d" (xpage_index) : "cc", "1", "2"
+		);
+#endif  /* CONFIG_ARCH_S390X */
+	switch (cc) {
+	case 0: return 0;
+	case 1: return -EIO;
+        case 2: { PRINT_ERR("expanded storage lost!\n"); return -ENXIO; }
+	case 3: return -ENXIO;
+	default: return -EIO;  /* should not happen */
+        }
+}
+
+/*--------------------------------------------------------------------*/
+/* Measure expanded memory                                            */
+/* Return value                                                       */
+/*           size of expanded memory in kB (must be a multipe of 4)   */
+/*--------------------------------------------------------------------*/
+int xpram_size(void)
+{
+	int cc=0;  
+        unsigned long base=0;
+	unsigned long po, pi, rpi;   /* page index order, page index */
+
+	unsigned long mem_page = __get_free_page(GFP_KERNEL);
+
+	/* for po=0,1,2,... try to move in page number base+(2^po)-1 */
+	pi=1;   
+	for (po=0; po <= 32; po++) { /* pi = 2^po */
+		cc=xpram_page_in(mem_page,base+pi-1);
+		if ( cc ) break;
+		pi <<= 1;  
+	}
+	if ( cc && (po < 31 ) ) {
+                pi >>=1;
+		base += pi;
+		pi >>=1;
+		for ( ; pi > 0; pi >>= 1) {
+			rpi = pi - 1;
+			cc=xpram_page_in(mem_page,base+rpi);
+			if ( !cc ) base += pi;
+		}
+	}
+	
+	free_page (mem_page);
+
+	if ( cc && (po < 31) ) 
+		return (XPRAM_KB_IN_PG * base);
+	else          /* return maximal value possible */
+		return INT_MAX;
+}
+
+/*
+ * Open and close
+ */
+
+int xpram_open (struct inode *inode, struct file *filp)
+{
+	Xpram_Dev *dev; /* device information */
+	int num = MINOR(inode->i_rdev);
+
+
+	if (num >= xpram_devs) return -ENODEV;
+	dev = xpram_devices + num;
+
+	PRINT_DEBUG("calling xpram_open for device %d\n",num);
+        PRINT_DEBUG("  size %dkB, name %s, usage: %d\n", 
+                     dev->size,dev->device_name, atomic_read(&(dev->usage)));
+
+	atomic_inc(&(dev->usage));
+	MOD_INC_USE_COUNT;
+	return 0;          /* success */
+}
+
+int xpram_release (struct inode *inode, struct file *filp)
+{
+	Xpram_Dev *dev = xpram_devices + MINOR(inode->i_rdev);
+
+	PRINT_DEBUG("calling xpram_release for device %d (size %dkB, usage: %d)\n",MINOR(inode->i_rdev) ,dev->size,atomic_read(&(dev->usage)));
+
+	/*
+	 * If the device is closed for the last time, start a timer
+	 * to release RAM in half a minute. The function and argument
+	 * for the timer have been setup in init_module()
+	 */
+	if (!atomic_dec_return(&(dev->usage))) {
+		/* but flush it right now */
+		fsync_dev(inode->i_rdev);
+		invalidate_buffers(inode->i_rdev);
+	}
+	MOD_DEC_USE_COUNT;
+	return(0);
+}
+
+
+/*
+ * The ioctl() implementation
+ */
+
+int xpram_ioctl (struct inode *inode, struct file *filp,
+		 unsigned int cmd, unsigned long arg)
+{
+	int err, size;
+	struct hd_geometry *geo = (struct hd_geometry *)arg;
+
+	PRINT_DEBUG("ioctl 0x%x 0x%lx\n", cmd, arg);
+	switch(cmd) {
+
+	case BLKGETSIZE:  /* 0x1260 */
+		/* Return the device size, expressed in sectors */
+		if (!arg) return -EINVAL; /* NULL pointer: not valid */
+		err= 0; /* verify_area_20(VERIFY_WRITE, (long *) arg, sizeof(long)); 
+			 *  if (err) return err;
+			 */
+		put_user ( 1024* xpram_sizes[MINOR(inode->i_rdev)]
+                           / XPRAM_SOFTSECT,
+			   (long *) arg);
+		return 0;
+
+	case BLKFLSBUF: /* flush, 0x1261 */
+		fsync_dev(inode->i_rdev);
+		if ( suser() )invalidate_buffers(inode->i_rdev);
+		return 0;
+
+	case BLKRAGET: /* return the readahead value, 0x1263 */
+		if (!arg)  return -EINVAL;
+		err = 0; /* verify_area_20(VERIFY_WRITE, (long *) arg, sizeof(long));
+		          * if (err) return err;
+                          */
+		put_user(read_ahead[MAJOR(inode->i_rdev)], (long *)arg);
+
+		return 0;
+
+	case BLKRASET: /* set the readahead value, 0x1262 */
+		if (!suser()) return -EACCES;
+		if (arg > 0xff) return -EINVAL; /* limit it */
+		read_ahead[MAJOR(inode->i_rdev)] = arg;
+                atomic_eieio();
+		return 0;
+
+	case BLKRRPART: /* re-read partition table: can't do it, 0x1259 */
+		return -EINVAL;
+
+
+#if (XPRAM_VERSION == 22)
+		RO_IOCTLS(inode->i_rdev, arg); /* the default RO operations 
+                                                * BLKROSET
+						* BLKROGET
+                                                */
+#endif /* V22 */
+
+	case HDIO_GETGEO:
+		/*
+		 * get geometry: we have to fake one...  trim the size to a
+		 * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
+		 * whatever cylinders. Tell also that data starts at sector. 4.
+		 */
+		size = xpram_mem_avail * 1024 / XPRAM_SOFTSECT;
+		/* size = xpram_mem_avail * 1024 / xpram_hardsect; */
+		size &= ~0x3f; /* multiple of 64 */
+		if (geo==NULL) return -EINVAL;
+                /* 
+                 * err=verify_area_20(VERIFY_WRITE, geo, sizeof(*geo));
+		 * if (err) return err;
+                 */
+
+		put_user(size >> 6, &geo->cylinders);
+		put_user(        4, &geo->heads);
+		put_user(       16, &geo->sectors);
+		put_user(        4, &geo->start);
+
+		return 0;
+	}
+
+	return -EINVAL; /* unknown command */
+}
+
+/*
+ * The file operations
+ */
+
+#if (XPRAM_VERSION == 22)
+struct file_operations xpram_fops = {
+	NULL,          /* lseek: default */
+	block_read,
+	block_write,
+	NULL,          /* xpram_readdir */
+	NULL,          /* xpram_select */
+	xpram_ioctl,
+	NULL,          /* xpram_mmap */
+	xpram_open,
+	NULL,          /* flush */
+	xpram_release,
+	block_fsync,
+	NULL,          /* xpram_fasync */
+        NULL,
+        NULL
+};
+#endif /* V22 */
+
+#if (XPRAM_VERSION == 24)
+struct block_device_operations xpram_devops =
+{
+	ioctl:   xpram_ioctl,
+	open:    xpram_open,
+	release: xpram_release,
+};
+#endif /* V24 */
+
+/*
+ * Block-driver specific functions
+ */
+
+void xpram_request(request_queue_t * queue)
+{
+	Xpram_Dev *device;
+	/*     u8 *ptr;          */
+	/*    int size;          */
+
+	unsigned long page_no;         /* expanded memory page number */
+	unsigned long sects_to_copy;   /* number of sectors to be copied */
+        char * buffer;                 /* local pointer into buffer cache */
+	int dev_no;                    /* device number of request */
+	int fault;                     /* faulty access to expanded memory */
+#if ( XPRAM_VERSION == 24 )	
+        struct request * current_req;      /* working request */
+#else 
+#       define current_req CURRENT
+#endif /* V24 */
+
+	while(1) {
+		INIT_REQUEST;
+
+		fault=0;
+#if ( XPRAM_VERSION == 24 )
+		current_req = blkdev_entry_next_request (&queue->queue_head);
+#endif /* V24 */
+		dev_no = DEVICE_NR(current_req->rq_dev); 
+		/* Check if the minor number is in range */
+		if ( dev_no > xpram_devs ) {
+			static int count = 0;
+			if (count++ < 5) /* print the message at most five times */
+				PRINT_WARN(" request for unknown device\n");
+			end_request(0);
+			continue;
+		}
+
+		/* pointer to device structure, from the global array */
+		device = xpram_devices + dev_no;   
+		sects_to_copy = current_req->current_nr_sectors;
+                /* does request exceed size of device ? */
+		if ( XPRAM_SEC2KB(sects_to_copy) > xpram_sizes[dev_no] ) {
+			PRINT_WARN(" request past end of device\n");
+			end_request(0);
+			continue;
+		}
+
+                /* Does request start at page boundery? -- paranoia */
+#if 0
+		PRINT_DEBUG(" req %lx, sect %lx, to copy %lx, buf addr %lx\n", (unsigned long) current_req, current_req->sector, sects_to_copy, (unsigned long) current_req->buffer);
+#endif
+                buffer = current_req->buffer;
+#if XPRAM_SEC_IN_PG != 1
+                /* Does request start at an expanded storage page boundery? */
+                if ( current_req->sector &  (XPRAM_SEC_IN_PG - 1) ) {
+			PRINT_WARN(" request does not start at an expanded storage page boundery\n");
+			PRINT_WARN(" referenced sector: %ld\n",current_req->sector);
+			end_request(0);
+			continue;
+		}
+		/* Does request refere to partial expanded storage pages? */
+                if ( sects_to_copy & (XPRAM_SEC_IN_PG - 1) ) {
+			PRINT_WARN(" request referes to a partial expanded storage page\n");
+			end_request(0);
+			continue;
+		}
+#endif /*  XPRAM_SEC_IN_PG != 1 */
+		/* Is request buffer aligned with kernel pages? */
+		if ( ((unsigned long)buffer) & (XPRAM_PGSIZE-1) ) {
+			PRINT_WARN(" request buffer is not aligned with kernel pages\n");
+			end_request(0);
+			continue;
+		}
+
+                /* which page of expanded storage is affected first? */
+		page_no = (xpram_offsets[dev_no] >> XPRAM_KB_IN_PG_ORDER)
+			+ (current_req->sector >> XPRAM_SEC_IN_PG_ORDER); 
+
+#if 0 
+		PRINT_DEBUG("request: %d ( dev %d, copy %d sectors, at page %d ) \n", current_req->cmd,dev_no,sects_to_copy,page_no);
+#endif
+
+		switch(current_req->cmd) {
+		case READ:
+			do {
+				if ( (fault=xpram_page_in((unsigned long)buffer,page_no)) ) {
+					PRINT_WARN("xpram(dev %d): page in failed for page %ld.\n",dev_no,page_no);
+					break;
+				}
+				sects_to_copy -= XPRAM_SEC_IN_PG;
+                                buffer += XPRAM_PGSIZE;
+				page_no++;
+			} while ( sects_to_copy > 0 );
+			break;
+		case WRITE:
+			do {
+				if ( (fault=xpram_page_out((unsigned long)buffer,page_no)) 
+					) {
+					PRINT_WARN("xpram(dev %d): page out failed for page %ld.\n",dev_no,page_no);
+					break;
+				}
+				sects_to_copy -= XPRAM_SEC_IN_PG;
+				buffer += XPRAM_PGSIZE;
+				page_no++;
+			} while ( sects_to_copy > 0 );
+			break;
+		default:
+			/* can't happen */
+			end_request(0);
+			continue;
+		}
+		if ( fault ) end_request(0);
+		else end_request(1); /* success */
+	}
+}
+
+/*
+ *    Kernel interfaces
+ */
+
+/*
+ * Parses the kernel parameters given in the kernel parameter line.
+ * The expected format is 
+ *           <number_of_partitions>[","<partition_size>]*
+ * where 
+ *           devices is a positive integer that initializes xpram_devs
+ *           each size is a non-negative integer possibly followed by a
+ *           magnitude (k,K,m,M,g,G), the list of sizes initialises 
+ *           xpram_sizes
+ *
+ * Arguments
+ *           str: substring of kernel parameter line that contains xprams
+ *                kernel parameters. 
+ *           ints: not used -- not in Version > 2.3 any more
+ *
+ * Result    0 on success, -EINVAl else -- only for Version > 2.3
+ *
+ * Side effects
+ *           the global variabls devs is set to the value of 
+ *           <number_of_partitions> and sizes[i] is set to the i-th
+ *           partition size (if provided). A parsing error of a value
+ *           results in this value being set to -EINVAL.
+ */
+#if (XPRAM_VERSION == 22)
+void xpram_setup (char *str, int *ints)
+#else 
+int xpram_setup (char *str)
+#endif /* V22 */
+{
+	devs = xpram_read_int(&str);
+	if ( devs != -EINVAL ) 
+	  if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) {
+			PRINT_ERR("error while reading xpram parameters.\n");
+#if (XPRAM_VERSION == 24)
+			return -EINVAL;
+#endif /* V24 */
+			  }
+#if (XPRAM_VERSION == 24)
+	  else return 0;
+	else return -EINVAL;
+#elif (XPRAM_VERSION == 22)
+	return; 
+#endif /* V24/V22 */
+}
+
+/*
+ * initialize xpram device driver
+ *
+ * Result: 0 ok
+ *         negative number: negative error code
+ */
+
+int xpram_init(void)
+{
+	int result, i;
+	int mem_usable;       /* net size of expanded memory */
+	int mem_needed=0;     /* size of expanded memory needed to fullfill
+			       * requirements of non-zero parameters in sizes
+			       */
+
+	int mem_auto_no=0;    /* number of (implicit) zero parameters in sizes */
+	int mem_auto;         /* automatically determined device size          */
+#if (XPRAM_VERSION == 24)
+	int minor_length;     /* store the length of a minor (w/o '\0') */
+        int minor_thresh;     /* threshhold for minor lenght            */
+
+        request_queue_t *q;   /* request queue */
+#endif /* V24 */
+
+				/*
+				 * Copy the (static) cfg variables to public prefixed ones to allow
+				 * snoozing with a debugger.
+				 */
+
+	xpram_rahead   = rahead;
+	xpram_blksize  = blksize;
+	xpram_hardsect = hardsect;
+
+	PRINT_INFO("initializing: %s\n","");
+				/* check arguments */
+	xpram_major    = major;
+	if ( (devs <= 0) || (devs > XPRAM_MAX_DEVS) ) {
+		PRINT_ERR("invalid number %d of devices\n",devs);
+                PRINT_ERR("Giving up xpram\n");
+		return -EINVAL;
+	}
+	xpram_devs     = devs;
+	for (i=0; i < xpram_devs; i++) {
+		if ( sizes[i] < 0 ) {
+			PRINT_ERR("Invalid partition size %d kB\n",xpram_sizes[i]);
+                        PRINT_ERR("Giving up xpram\n");
+			return -EINVAL;
+		} else {
+		  xpram_sizes[i] = NEXT4(sizes[i]);  /* page align */
+			if ( sizes[i] ) mem_needed += xpram_sizes[i];
+			else mem_auto_no++;
+		}
+	}
+
+	PRINT_DEBUG("  major %d \n", xpram_major);
+	PRINT_INFO("  number of devices (partitions): %d \n", xpram_devs);
+	for (i=0; i < xpram_devs; i++) {
+		if ( sizes[i] )
+			PRINT_INFO("  size of partition %d: %d kB\n", i, xpram_sizes[i]);
+		else
+			PRINT_INFO("  size of partition %d to be set automatically\n",i);
+	}
+	PRINT_DEBUG("  memory needed (for sized partitions): %d kB\n", mem_needed);
+	PRINT_DEBUG("  partitions to be sized automatically: %d\n", mem_auto_no);
+
+#if 0
+				/* Hardsect can't be changed :( */
+                                /* I try it any way. Yet I must distinguish
+                                 * between hardsects (to be changed to 4096)
+                                 * and soft sectors, hard-coded for buffer 
+                                 * sizes within the requests
+                                 */
+	if (hardsect != 512) {
+		PRINT_ERR("Can't change hardsect size\n");
+		hardsect = xpram_hardsect = 512;
+	}
+#endif
+        PRINT_INFO("  hardsector size: %dB \n",xpram_hardsect);
+
+	/*
+	 * Register your major, and accept a dynamic number
+	 */
+#if (XPRAM_VERSION == 22)
+	result = register_blkdev(xpram_major, "xpram", &xpram_fops);
+#elif (XPRAM_VERSION == 24)
+	result = devfs_register_blkdev(xpram_major, "xpram", &xpram_devops);
+#endif /* V22/V24 */
+	
+	if (result < 0) {
+		PRINT_ERR("Can't get major %d\n",xpram_major);
+                PRINT_ERR("Giving up xpram\n");
+		return result;
+	}
+	if (xpram_major == 0) xpram_major = result; /* dynamic */
+	major = xpram_major; /* Use `major' later on to save typing */
+
+	result = -ENOMEM; /* for the possible errors */
+
+	/* 
+	 * measure expanded memory
+	 */
+
+	xpram_mem_avail = xpram_size();
+	if (!xpram_mem_avail) {
+		PRINT_ERR("No or not enough expanded memory available\n");
+                PRINT_ERR("Giving up xpram\n");
+		result = -ENODEV;
+		goto fail_malloc;
+	}
+	PRINT_INFO("  %d kB expanded memory found.\n",xpram_mem_avail );
+
+	/*
+	 * Assign the other needed values: request, rahead, size, blksize,
+	 * hardsect. All the minor devices feature the same value.
+	 * Note that `xpram' defines all of them to allow testing non-default
+	 * values. A real device could well avoid setting values in global
+	 * arrays if it uses the default values.
+	 */
+
+#if (XPRAM_VERSION == 22)
+	blk_dev[major].request_fn = xpram_request;
+#elif (XPRAM_VERSION == 24)
+	q = BLK_DEFAULT_QUEUE (major);
+	blk_init_queue (q, xpram_request);
+	blk_queue_headactive (BLK_DEFAULT_QUEUE (major), 0);
+#endif /* V22/V24 */
+	read_ahead[major] = xpram_rahead;
+
+	/* we want to have XPRAM_UNUSED blocks security buffer between devices */
+	mem_usable=xpram_mem_avail-(XPRAM_UNUSED*(xpram_devs-1));
+	if ( mem_needed > mem_usable ) {
+		PRINT_ERR("Not enough expanded memory available\n");
+                PRINT_ERR("Giving up xpram\n");
+		goto fail_malloc;
+	}
+
+	/*
+	 * partitioning:
+	 * xpram_sizes[i] != 0; partition i has size xpram_sizes[i] kB
+	 * else:             ; all partitions i with xpram_sizesxpram_size[i] 
+	 *                     partition equally the remaining space
+	 */
+
+	if ( mem_auto_no ) {
+		mem_auto=LAST4((mem_usable-mem_needed)/mem_auto_no);
+		PRINT_INFO("  automatically determined partition size: %d kB\n", mem_auto);
+		for (i=0; i < xpram_devs; i++) 
+			if (xpram_sizes[i] == 0) xpram_sizes[i] = mem_auto;
+	}
+	blk_size[major]=xpram_sizes;
+
+	xpram_offsets = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
+	if (!xpram_offsets) {
+		PRINT_ERR("Not enough memory for xpram_offsets\n");
+                PRINT_ERR("Giving up xpram\n");
+		goto fail_malloc;
+	}
+	xpram_offsets[0] = 0;
+	for (i=1; i < xpram_devs; i++) 
+		xpram_offsets[i] = xpram_offsets[i-1] + xpram_sizes[i-1] + XPRAM_UNUSED;
+
+#if 0
+	for (i=0; i < xpram_devs; i++)
+		PRINT_DEBUG(" device(%d) offset = %d kB, size = %d kB\n",i, xpram_offsets[i], xpram_sizes[i]);
+#endif
+
+	xpram_blksizes = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
+	if (!xpram_blksizes) {
+		PRINT_ERR("Not enough memory for xpram_blksizes\n");
+                PRINT_ERR("Giving up xpram\n");
+		goto fail_malloc_blksizes;
+	}
+	for (i=0; i < xpram_devs; i++) /* all the same blocksize */
+		xpram_blksizes[i] = xpram_blksize;
+	blksize_size[major]=xpram_blksizes;
+
+	xpram_hardsects = kmalloc(xpram_devs * sizeof(int), GFP_KERNEL);
+	if (!xpram_hardsects) {
+		PRINT_ERR("Not enough memory for xpram_hardsects\n");
+                PRINT_ERR("Giving up xpram\n");
+		goto fail_malloc_hardsects;
+	}
+	for (i=0; i < xpram_devs; i++) /* all the same hardsect */
+		xpram_hardsects[i] = xpram_hardsect;
+	hardsect_size[major]=xpram_hardsects;
+   
+	/* 
+	 * allocate the devices -- we can't have them static, as the number
+	 * can be specified at load time
+	 */
+
+	xpram_devices = kmalloc(xpram_devs * sizeof (Xpram_Dev), GFP_KERNEL);
+	if (!xpram_devices) {
+		PRINT_ERR("Not enough memory for xpram_devices\n");
+                PRINT_ERR("Giving up xpram\n");
+		goto fail_malloc_devices;
+	}
+	memset(xpram_devices, 0, xpram_devs * sizeof (Xpram_Dev));
+#if (XPRAM_VERSION == 24)
+        minor_length = 1;
+        minor_thresh = 10;
+#endif /* V24 */
+	for (i=0; i < xpram_devs; i++) {
+		/* data and usage remain zeroed */
+		xpram_devices[i].size = xpram_sizes[i];  /* size in kB not in bytes */
+		atomic_set(&(xpram_devices[i].usage),0);
+#if (XPRAM_VERSION == 24)
+                if (i == minor_thresh) {
+		  minor_length++;
+		  minor_thresh *= 10;
+		}
+                xpram_devices[i].device_name = 
+                  kmalloc(1 + strlen(XPRAM_DEVICE_NAME_PREFIX) + minor_length,GFP_KERNEL);
+		if ( xpram_devices[i].device_name == NULL ) {
+		  PRINT_ERR("Not enough memory for xpram_devices[%d].device_name\n",i);
+                  PRINT_ERR("Giving up xpram\n");
+		  goto fail_devfs_register;
+		}
+                sprintf(xpram_devices[i].device_name,XPRAM_DEVICE_NAME_PREFIX "%d",i);
+
+	PRINT_DEBUG("initializing xpram_open for device %d\n",i);
+        PRINT_DEBUG("  size %dkB, name %s, usage: %d\n", 
+                     xpram_devices[i].size,xpram_devices[i].device_name, atomic_read(&(xpram_devices[i].usage)));
+
+#if 0  /* WHY? */
+                xpram_devices[i].devfs_entry =
+		  devfs_register(NULL /* devfs root dir */,
+                                 xpram_devices[i].device_name, 0,
+                                 0 /* flags */,
+				 XPRAM_MAJOR,i,
+                                 0755 /* access mode */,
+				 0 /* uid */, 0 /* gid */,
+                                 &xpram_devops,
+				 (void *) &(xpram_devices[i])
+				 );
+		if ( xpram_devices[i].devfs_entry == NULL ) {
+		  PRINT_ERR("devfs system registry failed\n");
+		  PRINT_ERR("Giving up xpram\n");
+		  goto fail_devfs_register;
+		}
+#endif  /* WHY? */
+#endif /* V24 */
+				 
+	}
+
+	return 0; /* succeed */
+
+	/* clean up memory in case of failures */
+#if (XPRAM_VERSION == 24)
+ fail_devfs_register:
+        for (i=0; i < xpram_devs; i++) {
+	  if ( xpram_devices[i].device_name )
+	    kfree(xpram_devices[i].device_name);
+	}
+	kfree(xpram_devices);
+#endif /* V24 */
+ fail_malloc_blksizes:
+	kfree (xpram_offsets);
+ fail_malloc_hardsects:
+	kfree (xpram_blksizes);
+	blksize_size[major] = NULL;
+ fail_malloc_devices:
+	kfree(xpram_hardsects);
+	hardsect_size[major] = NULL;
+ fail_malloc:
+	read_ahead[major] = 0;
+#if (XPRAM_VERSION == 22)
+	blk_dev[major].request_fn = NULL;
+#endif /* V22 */
+	/* ???	unregister_chrdev(major, "xpram"); */
+	unregister_blkdev(major, "xpram");
+	return result;
+}
+
+/*
+ * Finally, the module stuff
+ */
+
+int init_module(void)
+{
+	int rc = 0;
+
+	PRINT_INFO ("trying to load module\n");
+	rc = xpram_init ();
+	if (rc == 0) {
+		PRINT_INFO ("Module loaded successfully\n");
+	} else {
+		PRINT_WARN ("Module load returned rc=%d\n", rc);
+	}
+	return rc;
+}
+
+void cleanup_module(void)
+{
+	int i;
+
+				/* first of all, flush it all and reset all the data structures */
+
+
+	for (i=0; i<xpram_devs; i++)
+		fsync_dev(MKDEV(xpram_major, i)); /* flush the devices */
+
+#if (XPRAM_VERSION == 22)
+	blk_dev[major].request_fn = NULL;
+#endif /* V22 */
+	read_ahead[major] = 0;
+	blk_size[major] = NULL;
+	kfree(blksize_size[major]);
+	blksize_size[major] = NULL;
+	kfree(hardsect_size[major]);
+	hardsect_size[major] = NULL;
+	kfree(xpram_offsets);
+
+				/* finally, the usual cleanup */
+	unregister_blkdev(major, "xpram");
+	kfree(xpram_devices);
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/block/xpram.h linux/drivers/s390/block/xpram.h
--- v2.4.1/linux/drivers/s390/block/xpram.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/block/xpram.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,70 @@
+
+/*
+ * xpram.h -- definitions for the char module
+ *
+ *********/
+
+
+#include <linux/ioctl.h>
+#include <asm/atomic.h>
+#include <linux/major.h>
+
+/* version dependencies have been confined to a separate file */
+
+/*
+ * Macros to help debugging
+ */
+
+#define XPRAM_NAME "xpram"  /* name of device/module */
+#define XPRAM_DEVICE_NAME_PREFIX "slram" /* Prefix device name for major 35 */
+#define XPRAM_DEVS 1        /* one partition */
+#define XPRAM_RAHEAD 8      /* no real read ahead */
+#define XPRAM_PGSIZE 4096   /* page size of (expanded) mememory pages
+                             * according to S/390 architecture
+                             */
+#define XPRAM_BLKSIZE XPRAM_PGSIZE  /* must be equalt to page size ! */
+#define XPRAM_HARDSECT XPRAM_PGSIZE /* FIXME -- we have to deal with both
+                                     * this hard sect size and in some cases
+                                     * hard coded 512 bytes which I call
+                                     * soft sects:
+                                     */
+#define XPRAM_SOFTSECT 512
+#define XPRAM_MAX_DEVS 32   /* maximal number of devices (partitions) */
+#define XPRAM_MAX_DEVS1 33  /* maximal number of devices (partitions) +1 */
+
+/* The following macros depend on the sizes above */
+
+#define XPRAM_KB_IN_PG 4                     /* 4 kBs per page */
+#define XPRAM_KB_IN_PG_ORDER 2               /* 2^? kBs per page */
+
+/* Eventhough XPRAM_HARDSECT is set to 4k some data structures use hard
+ * coded 512 byte sa sector size
+ */
+#define XPRAM_SEC2KB(x) ((x >> 1) + (x & 1)) /* modifier used to compute size 
+                                                in kB from number of sectors */
+#define XPRAM_SEC_IN_PG 8                    /* 8 sectors per page */
+#define XPRAM_SEC_IN_PG_ORDER 3              /* 2^? sectors per page */
+
+#define XPRAM_UNUSED 40                     /* unused space between devices, 
+                                             * in kB, i.e.
+                                             * must be a multiple of 4
+                                             */
+/*
+ * The xpram device is removable: if it is left closed for more than
+ * half a minute, it is removed. Thus use a usage count and a
+ * kernel timer
+ */
+
+typedef struct Xpram_Dev {
+   int            size;   /* size in KB not in Byte - RB - */
+   atomic_t       usage;
+   char *         device_name;   /* device name prefix in devfs */
+   devfs_handle_t devfs_entry;   /* handle needed to unregister dev from devfs */
+   u8 *data;
+}              Xpram_Dev;
+
+/* 2.2: void xpram_setup (char *, int *); */
+/* begin 2.3 */
+int xpram_setup (char *);
+/* end 2.3 */
+int xpram_init(void);
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/ccwcache.c linux/drivers/s390/ccwcache.c
--- v2.4.1/linux/drivers/s390/ccwcache.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/ccwcache.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,303 @@
+/* 
+ * File...........: linux/drivers/s390/ccwcache.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ *                  Martin Schiwdefsky <schwidefsky@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
+ 
+ * History of changes
+ * 11/14/00 redesign by Martin Schwidefsky
+ */
+
+#include <linux/malloc.h>
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#include <linux/spinlock.h>
+#else
+#include <asm/spinlock.h>
+#endif
+
+#include <asm/debug.h>
+#include <asm/ccwcache.h>
+#include <asm/ebcdic.h>
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#define CCW_CACHE_SLAB_TYPE (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA)
+#define CCW_CACHE_TYPE (GFP_ATOMIC | GFP_DMA)
+#else
+#define CCW_CACHE_SLAB_TYPE (SLAB_HWCACHE_ALIGN)
+#define CCW_CACHE_TYPE (GFP_ATOMIC)
+#define kmem_cache_destroy(x) do {} while(0)
+#endif
+
+#ifdef PRINTK_HEADER
+#undef PRINTK_HEADER
+#endif
+#define PRINTK_HEADER "ccwcache"
+
+/* pointer to list of allocated requests */
+static ccw_req_t *ccwreq_actual = NULL;
+static spinlock_t ccwchain_lock;
+
+/* pointer to debug area */
+static debug_info_t *debug_area = NULL;
+
+/* SECTION: Handling of the dynamically allocated kmem slabs */
+
+/* a name template for the cache-names */
+static char ccw_name_template[] = "ccwcache-\0\0\0\0"; /* fill name with zeroes! */
+/* the cache's names */
+static char ccw_cache_name[CCW_NUMBER_CACHES][sizeof(ccw_name_template)+1]; 
+/* the caches itself*/
+static kmem_cache_t *ccw_cache[CCW_NUMBER_CACHES]; 
+
+/* SECTION: (de)allocation of ccw_req_t */
+
+/* 
+ * void enchain ( ccw_req_t *request )
+ * enchains the request to the ringbuffer
+ */
+static inline void 
+enchain ( ccw_req_t *request )
+{
+	unsigned long flags;
+
+	/* Sanity checks */
+	if ( request == NULL )
+		BUG();
+	spin_lock_irqsave(&ccwchain_lock,flags);
+	if ( ccwreq_actual == NULL ) { /* queue empty */
+		ccwreq_actual = request;
+		request->int_prev = ccwreq_actual;
+		request->int_next = ccwreq_actual;
+	} else {
+		request->int_next = ccwreq_actual;
+		request->int_prev = ccwreq_actual->int_prev;
+		request->int_prev->int_next = request;
+		request->int_next->int_prev = request;
+	}
+	spin_unlock_irqrestore(&ccwchain_lock,flags);
+}
+
+/* 
+ * void dechain ( ccw_req_t *request )
+ * dechains the request from the ringbuffer
+ */
+static inline void 
+dechain ( ccw_req_t *request )
+{
+	unsigned long flags;
+
+	/* Sanity checks */
+	if ( request == NULL || 
+	     request->int_next == NULL ||
+	     request->int_prev == NULL)
+		BUG();
+	/* first deallocate request from list of allocates requests */
+	spin_lock_irqsave(&ccwchain_lock,flags);
+	if ( request -> int_next == request -> int_prev ) {
+		ccwreq_actual = NULL;
+	} else {
+		if ( ccwreq_actual == request ) {
+			ccwreq_actual = request->int_next;
+		}
+		request->int_prev->int_next = request->int_next;
+		request->int_next->int_prev = request->int_prev;
+	}
+	spin_unlock_irqrestore(&ccwchain_lock,flags);
+}
+
+/* 
+ * ccw_req_t *ccw_alloc_request ( int cplength, int datasize )
+ * allocates a ccw_req_t, that 
+ * - can hold a CP of cplength CCWS
+ * - can hold additional data up to datasize 
+ */
+ccw_req_t *
+ccw_alloc_request ( char *magic, int cplength, int datasize )
+{
+	ccw_req_t * request = NULL;
+        int size_needed;
+	int data_offset, ccw_offset;
+	int cachind;
+
+	/* Sanity checks */
+	if ( magic == NULL || datasize > PAGE_SIZE ||
+	     cplength == 0 || (cplength*sizeof(ccw1_t)) > PAGE_SIZE)
+		BUG();
+	debug_text_event ( debug_area, 1, "ALLC");
+	debug_text_event ( debug_area, 1, magic);
+	debug_int_event ( debug_area, 1, cplength);
+	debug_int_event ( debug_area, 1, datasize);
+
+	/* We try to keep things together in memory */
+	size_needed = (sizeof (ccw_req_t) + 7) & -8;
+	data_offset = ccw_offset = 0;
+	if (size_needed + datasize <= PAGE_SIZE) {
+		/* Keep data with the request */
+		data_offset = size_needed;
+		size_needed += (datasize + 7) & -8;
+	}
+	if (size_needed + cplength*sizeof(ccw1_t) <= PAGE_SIZE) {
+		/* Keep CCWs with request */
+		ccw_offset = size_needed;
+		size_needed += cplength*sizeof(ccw1_t);
+	}
+
+	/* determine cache index for the requested size */
+	for (cachind = 0; cachind < CCW_NUMBER_CACHES; cachind ++ )
+	   if ( size_needed < (SMALLEST_SLAB << cachind) ) 
+			break;
+
+	/* Try to fulfill the request from a cache */
+	if ( ccw_cache[cachind] == NULL )
+		BUG();
+	request = kmem_cache_alloc ( ccw_cache[cachind], CCW_CACHE_TYPE );
+	if (request == NULL)
+		return NULL;
+	memset ( request, 0, (SMALLEST_SLAB << cachind));
+	request->cache = ccw_cache[cachind];
+
+	/* Allocate memory for the extra data */
+	if (data_offset == 0) {
+		/* Allocated memory for extra data with kmalloc */
+	    request->data = (void *) kmalloc(datasize, CCW_CACHE_TYPE );
+		if (request->data == NULL) {
+			printk(KERN_WARNING PRINTK_HEADER 
+			       "Couldn't allocate data area\n");
+			kmem_cache_free(request->cache, request);
+			return NULL;
+		}
+	} else
+		/* Extra data already allocated with the request */
+		request->data = (void *) ((addr_t) request + data_offset);
+
+	/* Allocate memory for the channel program */
+	if (ccw_offset == 0) {
+		/* Allocated memory for the channel program with kmalloc */
+		request->cpaddr = (ccw1_t *) kmalloc(cplength*sizeof(ccw1_t),
+						     CCW_CACHE_TYPE);
+		if (request->cpaddr == NULL) {
+			printk (KERN_DEBUG PRINTK_HEADER
+				"Couldn't allocate ccw area\n");
+			if (data_offset == 0)
+				kfree(request->data);
+			kmem_cache_free(request->cache, request);
+			return NULL;
+		}
+	} else
+		/* Channel program already allocated with the request */
+		request->cpaddr = (ccw1_t *) ((addr_t) request + ccw_offset);
+
+	memset ( request->data, 0, datasize );
+	memset ( request->cpaddr, 0, cplength*sizeof(ccw1_t) );
+	strncpy ( (char *)(&request->magic), magic, 4);
+
+	ASCEBC((char *)(&request->magic),4);
+	request -> cplength = cplength;
+	request -> datasize = datasize;
+	/* enqueue request to list of allocated requests */
+	enchain(request);
+	debug_int_event ( debug_area, 1, (long)request);
+	return request;
+}
+
+/* 
+ * void ccw_free_request ( ccw_req_t * )
+ * deallocates the ccw_req_t, given as argument
+ */
+
+void
+ccw_free_request ( ccw_req_t * request )
+{
+        int size_needed;
+
+	debug_text_event ( debug_area, 1, "FREE");
+	debug_int_event ( debug_area, 1, (long)request);
+
+	/* Sanity checks */
+	if ( request == NULL || request->cache == NULL)
+                BUG();
+
+        dechain ( request);
+	/* Free memory allocated with kmalloc
+         * make the same decisions as in ccw_alloc_requets */
+	size_needed = (sizeof (ccw_req_t) + 7) & -8;
+	if (size_needed + request->datasize <= PAGE_SIZE)
+		/* We kept the data with the request */
+		size_needed += (request->datasize + 7) & -8;
+	else
+		kfree(request->data);
+	if (size_needed + request->cplength*sizeof(ccw1_t) > PAGE_SIZE)
+		/* We kept the CCWs with request */
+                kfree(request->cpaddr);
+        kmem_cache_free(request -> cache, request);
+}
+
+/* SECTION: initialization and cleanup functions */
+
+/* 
+ * ccwcache_init
+ * called as an initializer function for the ccw memory management
+ */
+
+int
+ccwcache_init (void)
+{
+	int rc = 0;
+	int cachind;
+
+        /* initialize variables */
+	spin_lock_init(&ccwchain_lock);
+
+	/* allocate a debug area */
+	debug_area = debug_register( "ccwcache", 2, 4,sizeof(void*));
+	if ( debug_area == NULL )
+                BUG();
+
+        debug_register_view(debug_area,&debug_hex_ascii_view);
+        debug_register_view(debug_area,&debug_raw_view);
+	debug_text_event ( debug_area, 0, "INIT");
+
+	/* First allocate the kmem caches */
+	for ( cachind = 0; cachind < CCW_NUMBER_CACHES; cachind ++ ) {
+		int slabsize = SMALLEST_SLAB << cachind;
+		debug_text_event ( debug_area, 1, "allc");
+		debug_int_event ( debug_area, 1, slabsize);
+		sprintf ( ccw_cache_name[cachind], 
+			  "%s%d%c", ccw_name_template, slabsize, 0);
+		ccw_cache[cachind] = 
+			kmem_cache_create( ccw_cache_name[cachind], 
+					   slabsize, 0,
+					   CCW_CACHE_SLAB_TYPE,
+					   NULL, NULL );
+		debug_int_event ( debug_area, 1, (long)ccw_cache[cachind]);
+		if (ccw_cache[cachind] == NULL)
+			panic ("Allocation of CCW cache failed\n");
+	}
+	return rc;
+}
+
+/* 
+ * ccwcache_cleanup
+ * called as a cleanup function for the ccw memory management
+ */
+
+void
+ccwcache_cleanup (void)
+{
+	int cachind;
+
+	/* Shrink the caches, if available */
+	for ( cachind = 0; cachind < CCW_NUMBER_CACHES; cachind ++ ) {
+		if ( ccw_cache[cachind] ) {
+			if ( kmem_cache_shrink(ccw_cache[cachind]) == 0 ) {
+				ccw_cache[cachind] = NULL;
+			}
+			kmem_cache_destroy(ccw_cache[cachind]);
+		}
+	}
+	debug_unregister( debug_area );
+}
+
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/Makefile linux/drivers/s390/char/Makefile
--- v2.4.1/linux/drivers/s390/char/Makefile	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/char/Makefile	Tue Feb 13 14:13:44 2001
@@ -2,15 +2,32 @@
 
 CFLAFS += 
 O_TARGET := s390-char.o
-O_OBJS    :=         
-M_OBJS   :=
 
-ifeq ($(CONFIG_3215_CONSOLE),y)
-  O_OBJS += con3215.o
-endif
+obj-$(CONFIG_3215_CONSOLE) += con3215.o
+
+obj-$(CONFIG_HWC) += hwc_con.o hwc_rw.o hwc_tty.o
 
-ifeq ($(CONFIG_HWC),y)
-  O_OBJS += hwc_con.o hwc_rw.o hwc_tty.o
+# stuff for building tape390.o
+T390_OBJS = tape.o
+ifeq ($(CONFIG_S390_TAPE_CHAR),y)
+  T390_OBJS += tapechar.o
+endif
+ifeq ($(CONFIG_S390_TAPE_BLOCK),y)
+  T390_OBJS += tapeblock.o
+endif
+ifeq ($(CONFIG_S390_TAPE_3480),y)
+  T390_OBJS += tape3480.o
+  CONFIG_S390_TAPE_NEED_34xx = y 
+endif
+ifeq ($(CONFIG_S390_TAPE_3490),y)
+  T390_OBJS += tape3490.o
+  CONFIG_S390_TAPE_NEED_34xx = y
+endif
+ifeq ($(CONFIG_S390_TAPE_NEED_34xx),y) 
+  T390_OBJS += tape34xx.o
 endif
+obj-$(CONFIG_S390_TAPE) += tape390.o
 
+tape390.o: $(T390_OBJS)
+	$(LD) -r -o $@ $(T390_OBJS)
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/con3215.c linux/drivers/s390/char/con3215.c
--- v2.4.1/linux/drivers/s390/char/con3215.c	Wed Nov 15 00:41:03 2000
+++ linux/drivers/s390/char/con3215.c	Tue Feb 13 14:13:44 2001
@@ -5,6 +5,10 @@
  *  S390 version
  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ *  Updated:
+ *   Aug-2000: Added tab support
+ *             Dan Morrison, IBM Corporation (dmorriso@cse.buffalo.edu)
  */
 
 #include <linux/config.h>
@@ -16,11 +20,12 @@
 #include <linux/console.h>
 #include <linux/interrupt.h>
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/bootmem.h>
 #include <asm/io.h>
 #include <asm/ebcdic.h>
 #include <asm/uaccess.h>
+#include <asm/delay.h>
 
 #include "../../../arch/s390/kernel/cpcmd.h"
 #include <asm/irq.h>
@@ -31,8 +36,9 @@
 #define RAW3215_INBUF_SIZE  256	      /* input buffer size */
 #define RAW3215_MIN_SPACE   128	      /* minimum free space for wakeup */
 #define RAW3215_MIN_WRITE   1024      /* min. length for immediate output */
-#define RAW3215_MAX_CCWLEN  3968      /* max. bytes to write with one ccw */
-#define RAW3215_NR_CCWS	    ((RAW3215_BUFFER_SIZE/RAW3215_MAX_CCWLEN)+2)
+#define RAW3215_MAX_BYTES   3968      /* max. bytes to write with one ssch */
+#define RAW3215_MAX_NEWLINE 50        /* max. lines to write with one ssch */
+#define RAW3215_NR_CCWS	    3
 #define RAW3215_TIMEOUT	    HZ/10     /* time for delayed output */
 
 #define RAW3215_FIXED	    1	      /* 3215 console device is not be freed */
@@ -45,6 +51,8 @@
 #define RAW3215_FLUSHING    128	      /* set to flush buffer (no delay) */
 #define RAW3215_BH_PENDING  256       /* indication for bh scheduling */
 
+#define TAB_STOP_SIZE	    8         /* tab stop size */
+
 struct _raw3215_info;		      /* forward declaration ... */
 
 int raw3215_condevice = -1;           /* preset console device */
@@ -61,7 +69,8 @@
  */
 typedef struct _raw3215_req {
 	raw3215_type type;	      /* type of the request */
-	int start, end;		      /* start/end index into output buffer */
+	int start, len;		      /* start index & len in output buffer */
+        int delayable;                /* indication to wait for more data */
 	int residual;		      /* residual count for read request */
 	ccw1_t ccws[RAW3215_NR_CCWS]; /* space for the channel program */
 	struct _raw3215_info *info;   /* pointer to main structure */
@@ -75,6 +84,7 @@
 	char *inbuf;		      /* pointer to input buffer */
 	int head;		      /* first free byte in output buffer */
 	int count;		      /* number of bytes in output buffer */
+        int written;                  /* number of bytes in write requests */
 	devstat_t devstat;	      /* device status structure for do_IO */
 	struct tty_struct *tty;	      /* pointer to tty structure if present */
 	struct tq_struct tqueue;      /* task queue to bottom half */
@@ -85,6 +95,7 @@
 	char *message;                /* pending message from raw3215_irq */
 	int msg_dstat;                /* dstat for pending message */
 	int msg_cstat;                /* cstat for pending message */
+	int line_pos;		      /* position on the line (for tabs) */
 } raw3215_info;
 
 static raw3215_info *raw3215[NR_3215];	/* array of 3215 devices structures */
@@ -143,35 +154,15 @@
 }
 
 /*
- * Get a write request structure. That is either a new or the last
- * queued write request. The request structure is set up in 
- * raw3215_mk_write_ccw.
- */
-static raw3215_req *raw3215_mk_write_req(raw3215_info *raw)
-{
-	raw3215_req *req;
-
-	/* check if there is a queued write request */
-	req = raw->queued_write;
-	if (req == NULL) {
-		/* no queued write request, use new req structure */
-		req = raw3215_alloc_req();
-		req->type = RAW3215_WRITE;
-		req->info = raw;
-		req->start = raw->head;
-	} else
-		raw->queued_write = NULL;
-	return req;
-}
-
-/*
- * Get a read request structure. If there is a queued read request
- * it is used, but that shouldn't happen because a 3215 terminal
- * won't accept a new read before the old one is completed.
+ * Set up a read request that reads up to 160 byte from the 3215 device.
+ * If there is a queued read request it is used, but that shouldn't happen
+ * because a 3215 terminal won't accept a new read before the old one is
+ * completed.
  */
-static raw3215_req *raw3215_mk_read_req(raw3215_info *raw)
+static void raw3215_mk_read_req(raw3215_info *raw)
 {
 	raw3215_req *req;
+        ccw1_t *ccw;
 
 	/* there can only be ONE read request at a time */
 	req = raw->queued_read;
@@ -180,24 +171,66 @@
 		req = raw3215_alloc_req();
 		req->type = RAW3215_READ;
 		req->info = raw;
-	} else
-		raw->queued_read = NULL;
-	return req;
+                raw->queued_read = req;
+	}
+
+        ccw = req->ccws;
+        ccw->cmd_code = 0x0A; /* read inquiry */
+        ccw->flags = 0x20;    /* ignore incorrect length */
+        ccw->count = 160;
+        ccw->cda = (__u32) __pa(raw->inbuf);
 }
 
 /*
  * Set up a write request with the information from the main structure.
- * A ccw chain is created that writes everything in the output buffer
- * to the 3215 device.
+ * A ccw chain is created that writes as much as possible from the output
+ * buffer to the 3215 device. If a queued write exists it is replaced by
+ * the new, probably lengthened request.
  */
-static int raw3215_mk_write_ccw(raw3215_info *raw, raw3215_req *req)
+static void raw3215_mk_write_req(raw3215_info *raw)
 {
+        raw3215_req *req;
 	ccw1_t *ccw;
-	int len, count, ix;
+	int len, count, ix, lines;
+
+        if (raw->count <= raw->written)
+                return;
+        /* check if there is a queued write request */
+        req = raw->queued_write;
+        if (req == NULL) {
+                /* no queued write request, use new req structure */
+                req = raw3215_alloc_req();
+                req->type = RAW3215_WRITE;
+                req->info = raw;
+                raw->queued_write = req;
+        } else {
+                raw->written -= req->len;
+        }
 
 	ccw = req->ccws;
-	req->end = (raw->head - 1) & (RAW3215_BUFFER_SIZE - 1);
-	len = ((req->end - req->start) & (RAW3215_BUFFER_SIZE - 1)) + 1;
+        req->start = (raw->head - raw->count + raw->written) &
+                     (RAW3215_BUFFER_SIZE - 1);
+        /*
+         * now we have to count newlines. We can at max accept
+         * RAW3215_MAX_NEWLINE newlines in a single ssch due to
+         * a restriction in VM
+         */
+        lines = 0;
+        ix = req->start;
+        while (lines < RAW3215_MAX_NEWLINE && ix != raw->head) {
+                if (raw->buffer[ix] == 0x15)
+                        lines++;
+                ix = (ix + 1) & (RAW3215_BUFFER_SIZE - 1);
+        }
+	len = ((ix - 1 - req->start) & (RAW3215_BUFFER_SIZE - 1)) + 1;
+        if (len > RAW3215_MAX_BYTES)
+                len = RAW3215_MAX_BYTES;
+        req->len = len;
+        raw->written += len;
+
+        /* set the indication if we should try to enlarge this request */
+        req->delayable = (ix == raw->head) && (len < RAW3215_MIN_WRITE);
+
 	ix = req->start;
 	while (len > 0) {
 		if (ccw > req->ccws)
@@ -205,31 +238,26 @@
 		ccw->cmd_code = 0x01; /* write, auto carrier return */
 		ccw->flags = 0x20;    /* ignore incorrect length ind.  */
 		ccw->cda =
-			(void *) virt_to_phys(raw->buffer + ix);
-		count = (len > RAW3215_MAX_CCWLEN) ? 
-			RAW3215_MAX_CCWLEN : len;
+			(__u32) __pa(raw->buffer + ix);
+		count = len;
 		if (ix + count > RAW3215_BUFFER_SIZE)
-			count = RAW3215_BUFFER_SIZE-ix;
+			count = RAW3215_BUFFER_SIZE - ix;
 		ccw->count = count;
 		len -= count;
 		ix = (ix + count) & (RAW3215_BUFFER_SIZE - 1);
 		ccw++;
 	}
-	return len;
-}
-
-/*
- * Set up a read request that reads up to 160 byte from the 3215 device.
- */
-static void raw3215_mk_read_ccw(raw3215_info *raw, raw3215_req *req)
-{
-	ccw1_t *ccw;
-
-	ccw = req->ccws;
-	ccw->cmd_code = 0x0A; /* read inquiry */
-	ccw->flags = 0x20;    /* ignore incorrect length */
-	ccw->count = 160;
-	ccw->cda = (void *) virt_to_phys(raw->inbuf);
+        /*
+         * Add a NOP to the channel program. 3215 devices are purely
+         * emulated and its much better to avoid the channel end
+         * interrupt in this case.
+         */
+        if (ccw > req->ccws)
+                ccw[-1].flags |= 0x40; /* use command chaining */
+        ccw->cmd_code = 0x03; /* NOP */
+        ccw->flags = 0;
+        ccw->cda = 0;
+        ccw->count = 1;
 }
 
 /*
@@ -245,7 +273,7 @@
 	    !(raw->flags & (RAW3215_WORKING | RAW3215_THROTTLED))) {
 		/* dequeue request */
 		raw->queued_read = NULL;
-		res = do_IO(raw->irq, req->ccws, (__u32) req, 0, 0);
+		res = do_IO(raw->irq, req->ccws, (unsigned long) req, 0, 0);
 		if (res != 0) {
 			/* do_IO failed, put request back to queue */
 			raw->queued_read = req;
@@ -258,7 +286,7 @@
 	    !(raw->flags & (RAW3215_WORKING | RAW3215_STOPPED))) {
 		/* dequeue request */
 		raw->queued_write = NULL;
-		res = do_IO(raw->irq, req->ccws, (__u32) req, 0, 0);
+		res = do_IO(raw->irq, req->ccws, (unsigned long) req, 0, 0);
 		if (res != 0) {
 			/* do_IO failed, put request back to queue */
 			raw->queued_write = req;
@@ -280,6 +308,7 @@
 	if (raw->flags & RAW3215_TIMER_RUNS) {
 		del_timer(&raw->timer);
 		raw->flags &= ~RAW3215_TIMER_RUNS;
+                raw3215_mk_write_req(raw);
 		raw3215_start_io(raw);
 	}
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
@@ -298,10 +327,10 @@
 	if (raw->queued_read != NULL)
 		raw3215_start_io(raw);
 	else if (raw->queued_write != NULL) {
-		if (raw->count >= RAW3215_MIN_WRITE ||
+		if ((raw->queued_write->delayable == 0) ||
 		    (raw->flags & RAW3215_FLUSHING)) {
 			/* execute write requests bigger than minimum size */
-			raw3215_start_io(raw);
+                        raw3215_start_io(raw);
 			if (raw->flags & RAW3215_TIMER_RUNS) {
 				del_timer(&raw->timer);
 				raw->flags &= ~RAW3215_TIMER_RUNS;
@@ -330,7 +359,8 @@
 
 	raw = (raw3215_info *) data;
 	s390irq_spin_lock_irqsave(raw->irq, flags);
-	raw3215_try_io((raw3215_info *) data);
+        raw3215_mk_write_req(raw);
+        raw3215_try_io(raw);
         raw->flags &= ~RAW3215_BH_PENDING;
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
 	/* Check for pending message from raw3215_irq */
@@ -357,6 +387,8 @@
         if (raw->flags & RAW3215_BH_PENDING)
                 return;       /* already pending */
         raw->flags |= RAW3215_BH_PENDING;
+	INIT_LIST_HEAD(&raw->tqueue.list);
+	raw->tqueue.sync = 0;
         raw->tqueue.routine = raw3215_softint;
         raw->tqueue.data = raw;
         queue_task(&raw->tqueue, &tq_immediate);
@@ -417,9 +449,7 @@
 		if ((raw = raw3215_find_info(irq)) == NULL)
 			return;              /* That shouldn't happen ... */
 		/* Setup a read request */
-		req = raw3215_mk_read_req(raw);
-		raw3215_mk_read_ccw(raw, req);
-		raw->queued_read = req;
+		raw3215_mk_read_req(raw);
                 if (MACHINE_IS_P390)
                         memset(raw->inbuf, 0, RAW3215_INBUF_SIZE);
                 raw3215_sched_bh(raw);
@@ -427,7 +457,8 @@
 	case 0x08:
 	case 0x0C:
 		/* Channel end interrupt. */
-		raw = req->info;
+		if ((raw = req->info) == NULL)
+                        return;              /* That shouldn't happen ... */
 		if (req->type == RAW3215_READ) {
 			/* store residual count, then wait for device end */
 			req->residual = stat->rescnt;
@@ -436,7 +467,8 @@
 			break;
 	case 0x04:
 		/* Device end interrupt. */
-		raw = req->info;
+                if ((raw = req->info) == NULL)
+                        return;              /* That shouldn't happen ... */
 		if (req->type == RAW3215_READ && raw->tty != NULL) {
 			tty = raw->tty;
                         count = 160 - req->residual;
@@ -449,28 +481,28 @@
 				count = TTY_FLIPBUF_SIZE - tty->flip.count - 1;
 			EBCASC(raw->inbuf, count);
 			if (count == 2 && (
-                            /* hat is 0xb0 in codepage 037 (US etc.) and thus */
-                            /* converted to 0x5e in ascii ('^') */
-                            strncmp(raw->inbuf, "^c", 2) == 0 ||
-                            /* hat is 0xb0 in several other codepages (German,*/
-                            /* UK, ...) and thus converted to ascii octal 252 */
-                            strncmp(raw->inbuf, "\252c", 2) == 0) ) {
+			    /* hat is 0xb0 in codepage 037 (US etc.) and thus */
+			    /* converted to 0x5e in ascii ('^') */
+			    strncmp(raw->inbuf, "^c", 2) == 0 ||
+			    /* hat is 0xb0 in several other codepages (German,*/
+			    /* UK, ...) and thus converted to ascii octal 252 */
+			    strncmp(raw->inbuf, "\252c", 2) == 0) ) {
 				/* emulate a control C = break */
 				tty->flip.count++;
 				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 				*tty->flip.char_buf_ptr++ = INTR_CHAR(tty);
 				tty_flip_buffer_push(raw->tty);
 			} else if (count == 2 && (
-                                   strncmp(raw->inbuf, "^d", 2) == 0 ||
-                                    strncmp(raw->inbuf, "\252d", 2) == 0) ) {
+				   strncmp(raw->inbuf, "^d", 2) == 0 ||
+				    strncmp(raw->inbuf, "\252d", 2) == 0) ) {
 				/* emulate a control D = end of file */
 				tty->flip.count++;
 				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
 				*tty->flip.char_buf_ptr++ = EOF_CHAR(tty);
 				tty_flip_buffer_push(raw->tty);
 			} else if (count == 2 && (
-                                   strncmp(raw->inbuf, "^z", 2) == 0 ||
-                                    strncmp(raw->inbuf, "\252z", 2) == 0) ) {
+				   strncmp(raw->inbuf, "^z", 2) == 0 ||
+				    strncmp(raw->inbuf, "\252z", 2) == 0) ) {
 				/* emulate a control Z = suspend */
 				tty->flip.count++;
 				*tty->flip.flag_buf_ptr++ = TTY_NORMAL;
@@ -480,8 +512,9 @@
 				memcpy(tty->flip.char_buf_ptr,
 				       raw->inbuf, count);
 				if (count < 2 ||
-                                    (strncmp(raw->inbuf+count-2, "^n", 2) ||
-                                    strncmp(raw->inbuf+count-2, "\252n", 2)) ) {					/* don't add the auto \n */
+				    (strncmp(raw->inbuf+count-2, "^n", 2) ||
+				    strncmp(raw->inbuf+count-2, "\252n", 2)) ) {
+					/* don't add the auto \n */
 					tty->flip.char_buf_ptr[count] = '\n';
 					memset(tty->flip.flag_buf_ptr,
 					       TTY_NORMAL, count + 1);
@@ -494,9 +527,9 @@
 				tty_flip_buffer_push(raw->tty);
 			}
 		} else if (req->type == RAW3215_WRITE) {
-			raw->count -= ((req->end - req->start) &
-				       (RAW3215_BUFFER_SIZE - 1)) + 1;
-		}
+			raw->count -= req->len;
+                        raw->written -= req->len;
+		} 
 		raw->flags &= ~RAW3215_WORKING;
 		raw3215_free_req(req);
 		/* check for empty wait */
@@ -513,9 +546,10 @@
                         return;              /* That shouldn't happen ... */
                 if (raw == NULL) break;
 		if (req != NULL && req->type != RAW3215_FREE) {
-		        if (req->type == RAW3215_WRITE) 
-			        raw->count -= ((req->end - req->start) &
-				              (RAW3215_BUFFER_SIZE-1))+1;
+		        if (req->type == RAW3215_WRITE) {
+			        raw->count -= req->len;
+                                raw->written -= req->len;
+                        }
                         raw->flags &= ~RAW3215_WORKING;
                         raw3215_free_req(req);
 		}
@@ -530,13 +564,40 @@
 }
 
 /*
+ * Wait until length bytes are available int the output buffer.
+ * Has to be called with the s390irq lock held. Can be called
+ * disabled.
+ */
+void raw3215_make_room(raw3215_info *raw, unsigned int length)
+{
+	while (RAW3215_BUFFER_SIZE - raw->count < length) {
+		/* there might be a request pending */
+		raw->flags |= RAW3215_FLUSHING;
+		raw3215_mk_write_req(raw);
+		raw3215_try_io(raw);
+		raw->flags &= ~RAW3215_FLUSHING;
+		if (wait_cons_dev(raw->irq) != 0) {
+			/* that shouldn't happen */
+			raw->count = 0;
+			raw->written = 0;
+		}
+		/* Enough room freed up ? */
+		if (RAW3215_BUFFER_SIZE - raw->count >= length)
+			break;
+		/* there might be another cpu waiting for the lock */
+		s390irq_spin_unlock(raw->irq);
+		udelay(100);
+		s390irq_spin_lock(raw->irq);
+	}
+}
+
+/*
  * String write routine for 3215 devices
  */
 static int
 raw3215_write(raw3215_info *raw, const char *str,
 	      int from_user, unsigned int length)
 {
-	raw3215_req *req;
 	unsigned long flags;
 	int ret, c;
 	int count;
@@ -548,16 +609,8 @@
 					     RAW3215_BUFFER_SIZE : length;
 		length -= count;
 
-		while (RAW3215_BUFFER_SIZE - raw->count < count) {
-			/* there might be a request pending */
-			raw3215_try_io(raw);
-			if (wait_cons_dev(raw->irq) != 0) {
-				/* that shouldn't happen */
-				raw->count = 0;
-			} 
-		}
+                raw3215_make_room(raw, count);
 
-		req = raw3215_mk_write_req(raw);
 		/* copy string to output buffer and convert it to EBCDIC */
 		if (from_user) {
 			while (1) {
@@ -577,6 +630,7 @@
 				raw->head = (raw->head + c) &
 					    (RAW3215_BUFFER_SIZE - 1);
 				raw->count += c;
+				raw->line_pos += c;
 				str += c;
 				count -= c;
 				ret += c;
@@ -593,17 +647,18 @@
 				raw->head = (raw->head + c) &
 					    (RAW3215_BUFFER_SIZE - 1);
 				raw->count += c;
+				raw->line_pos += c;
 				str += c;
 				count -= c;
 				ret += c;
 			}
 		}
-		raw3215_mk_write_ccw(raw, req);
-		raw->queued_write = req;
-		/* start or queue request */
-		raw3215_try_io(raw);
+                if (!(raw->flags & RAW3215_WORKING)) {
+                        raw3215_mk_write_req(raw);
+		        /* start or queue request */
+		        raw3215_try_io(raw);
+                }
 		s390irq_spin_unlock_irqrestore(raw->irq, flags);
-
 	}
 
 	return ret;
@@ -612,29 +667,36 @@
 /*
  * Put character routine for 3215 devices
  */
+	
 static void raw3215_putchar(raw3215_info *raw, unsigned char ch)
 {
-	raw3215_req *req;
 	unsigned long flags;
+        unsigned int length, i;
 
 	s390irq_spin_lock_irqsave(raw->irq, flags);
-	while (RAW3215_BUFFER_SIZE - raw->count < 1) {
-		/* there might be a request pending */
-		raw3215_try_io(raw);
-		if (wait_cons_dev(raw->irq) != 0) {
-			/* that shouldn't happen */
-			raw->count = 0;
-		}
+	if (ch == '\t') {
+		length = TAB_STOP_SIZE - (raw->line_pos%TAB_STOP_SIZE);
+		raw->line_pos += length;
+		ch = ' ';
+        } else if (ch == '\n') {
+		length = 1;
+		raw->line_pos = 0;
+	} else {
+		length = 1;
+		raw->line_pos++;
 	}
+        raw3215_make_room(raw, length);
 
-	req = raw3215_mk_write_req(raw);
-	raw->buffer[raw->head] = (char) _ascebc[(int) ch];
-	raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1);
-	raw->count++;
-	raw3215_mk_write_ccw(raw, req);
-	raw->queued_write = req;
-	/* start or queue request */
-	raw3215_try_io(raw);
+	for (i = 0; i < length; i++) {
+		raw->buffer[raw->head] = (char) _ascebc[(int) ch];
+		raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1);
+		raw->count++;
+	}
+        if (!(raw->flags & RAW3215_WORKING)) {
+                raw3215_mk_write_req(raw);
+	        /* start or queue request */
+	        raw3215_try_io(raw);
+        }
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
 }
 
@@ -667,8 +729,10 @@
 	if (request_irq(raw->irq, raw3215_irq, SA_INTERRUPT,
 			"3215 terminal driver", &raw->devstat) != 0)
 		return -1;
+	raw->line_pos = 0;
 	raw->flags |= RAW3215_ACTIVE;
 	s390irq_spin_lock_irqsave(raw->irq, flags);
+        set_cons_dev(raw->irq);
 	raw3215_try_io(raw);
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
 
@@ -680,7 +744,7 @@
  */
 static void raw3215_shutdown(raw3215_info *raw)
 {
-	DECLARE_WAITQUEUE(wait, current);
+        DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 
 	if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED))
@@ -707,7 +771,7 @@
 static int
 raw3215_find_dev(int number)
 {
-	dev_info_t dinfo;
+	s390_dev_info_t dinfo;
 	int irq;
 	int count;
 
@@ -739,7 +803,8 @@
         if (!MACHINE_IS_VM && !MACHINE_IS_P390)
                 return 0;
 	raw = raw3215[0];  /* 3215 console is the first one */
-	if (raw->irq == -1) /* now console device found in con3215_init */
+	if (raw == NULL || raw->irq == -1)
+                /* console device not found in con3215_init */
 		return -1;
 	return raw3215_startup(raw);
 }
@@ -751,16 +816,29 @@
 con3215_write(struct console *co, const char *str, unsigned int count)
 {
 	raw3215_info *raw;
+	int i;
 
 	if (count <= 0)
 		return;
-	raw = raw3215[0];  /* console 3215 is the first one */
-	raw3215_write(raw, str, 0, count);
+        raw = raw3215[0];       /* console 3215 is the first one */
+        while (count > 0) {
+                for (i = 0; i < count; i++)
+                        if (str[i] == '\t' || str[i] == '\n')
+                                break;
+                raw3215_write(raw, str, 0, i);
+		count -= i;
+		str += i;
+                if (count > 0) {
+			raw3215_putchar(raw, *str);
+			count--;
+			str++;
+                }
+        }
 }
 
 kdev_t con3215_device(struct console *c)
 {
-	return MKDEV(TTY_MAJOR, c->index);
+	return MKDEV(TTY_MAJOR, c->index + 64 );
 }
 
 /*
@@ -774,16 +852,7 @@
 
 	raw = raw3215[0];  /* console 3215 is the first one */
 	s390irq_spin_lock_irqsave(raw->irq, flags);
-	while (raw->count > 0) {
-		/* there might be a request pending */
-		raw->flags |= RAW3215_FLUSHING;
-		raw3215_try_io(raw);
-		if (wait_cons_dev(raw->irq) != 0) {
-			/* that shouldn't happen */
-			raw->count = 0;
-		}
-		raw->flags &= ~RAW3215_FLUSHING;
-	}
+	raw3215_make_room(raw, RAW3215_BUFFER_SIZE);
 	s390irq_spin_unlock_irqrestore(raw->irq, flags);
 }
 
@@ -823,7 +892,7 @@
 	raw = raw3215[line];
 	if (raw == NULL) {
 		raw = kmalloc(sizeof(raw3215_info) +
-			      RAW3215_INBUF_SIZE, GFP_KERNEL);
+			      RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA);
 		if (raw == NULL)
 			return -ENOMEM;
 		raw->irq = raw3215_find_dev(line);
@@ -833,7 +902,8 @@
 		}
 		raw->inbuf = (char *) raw + sizeof(raw3215_info);
 		memset(raw, 0, sizeof(raw3215_info));
-		raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL);
+		raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE,
+					       GFP_KERNEL|GFP_DMA);
 		if (raw->buffer == NULL) {
 			kfree(raw);
 			return -ENOMEM;
@@ -886,7 +956,12 @@
 	raw3215_info *raw;
 				
 	raw = (raw3215_info *) tty->driver_data;
-	return RAW3215_BUFFER_SIZE - raw->count;
+
+	/* Subtract TAB_STOP_SIZE to allow for a tab, 8 <<< 64K */
+	if ((RAW3215_BUFFER_SIZE - raw->count - TAB_STOP_SIZE) >= 0)
+		return RAW3215_BUFFER_SIZE - raw->count - TAB_STOP_SIZE;
+	else
+		return 0;
 }
 
 /*
@@ -896,7 +971,7 @@
 		    const unsigned char *buf, int count)
 {
 	raw3215_info *raw;
-	int ret;
+	int ret = 0;
 				
 	if (!tty)
 		return 0;
@@ -1041,17 +1116,18 @@
 	raw3215_freelist = NULL;
 	spin_lock_init(&raw3215_freelist_lock);
 	for (i = 0; i < NR_3215_REQ; i++) {
-		req = (raw3215_req *) alloc_bootmem(sizeof(raw3215_req));
+                req = (raw3215_req *) alloc_bootmem_low(sizeof(raw3215_req));
 		req->next = raw3215_freelist;
 		raw3215_freelist = req;
 	}
 
 #ifdef CONFIG_3215_CONSOLE
-	raw3215[0] = raw = (raw3215_info *) 
-		alloc_bootmem(sizeof(raw3215_info));
+        raw3215[0] = raw = (raw3215_info *)
+                alloc_bootmem_low(sizeof(raw3215_info));
 	memset(raw, 0, sizeof(raw3215_info));
-	raw->buffer = (char *) alloc_bootmem(RAW3215_BUFFER_SIZE);
-	raw->inbuf = (char *) alloc_bootmem(RAW3215_INBUF_SIZE);
+        raw->buffer = (char *) alloc_bootmem_low(RAW3215_BUFFER_SIZE);
+        raw->inbuf = (char *) alloc_bootmem_low(RAW3215_INBUF_SIZE);
+
 	/* Find the first console */
 	raw->irq = raw3215_find_dev(0);
 	raw->flags |= RAW3215_FIXED;
@@ -1061,13 +1137,10 @@
 
 	if (raw->irq != -1) {
 		register_console(&con3215);
-		s390irq_spin_lock(raw->irq);
-		set_cons_dev(raw->irq);
-		s390irq_spin_unlock(raw->irq);
 	} else {
-		free_bootmem((unsigned long) raw->inbuf, RAW3215_INBUF_SIZE);
-		free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE);
-		free_bootmem((unsigned long) raw, sizeof(raw3215_info));
+                free_bootmem((unsigned long) raw->inbuf, RAW3215_INBUF_SIZE);
+                free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE);
+                free_bootmem((unsigned long) raw, sizeof(raw3215_info));
 		raw3215[0] = NULL;
 		printk("Couldn't find a 3215 console device\n");
 	}
@@ -1091,7 +1164,7 @@
 	tty3215_driver.subtype = SYSTEM_TYPE_TTY;
 	tty3215_driver.init_termios = tty_std_termios;
 	tty3215_driver.init_termios.c_iflag = IGNBRK | IGNPAR;
-	tty3215_driver.init_termios.c_oflag = ONLCR;
+	tty3215_driver.init_termios.c_oflag = ONLCR | XTABS;
 	tty3215_driver.init_termios.c_lflag = ISIG;
 	tty3215_driver.flags = TTY_DRIVER_REAL_RAW;
 	tty3215_driver.refcount = &tty3215_refcount;
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/hwc.h linux/drivers/s390/char/hwc.h
--- v2.4.1/linux/drivers/s390/char/hwc.h	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/char/hwc.h	Tue Feb 13 14:13:44 2001
@@ -1,13 +1,13 @@
 /*
  *  drivers/s390/char/hwc.h
- *
+ * 
  *
  *  S390 version
  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Peschke <peschke@fh-brandenburg.de>
  *
- *
- *
+ * 
+ * 
  */
 
 #ifndef __HWC_H__
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/hwc_con.c linux/drivers/s390/char/hwc_con.c
--- v2.4.1/linux/drivers/s390/char/hwc_con.c	Thu Oct 12 14:20:47 2000
+++ linux/drivers/s390/char/hwc_con.c	Tue Feb 13 14:13:44 2001
@@ -29,16 +29,24 @@
 
 void hwc_console_write (struct console *, const char *, unsigned int);
 kdev_t hwc_console_device (struct console *);
+void hwc_console_unblank (void);
 
 #define  HWC_CON_PRINT_HEADER "hwc console driver: "
 
 struct console hwc_console =
 {
 
-	name:		hwc_console_name,
-	write:		hwc_console_write,
-	device:		hwc_console_device,
-	flags:		CON_PRINTBUFFER,
+	hwc_console_name,
+	hwc_console_write,
+	NULL,
+	hwc_console_device,
+	NULL,
+	hwc_console_unblank,
+	NULL,
+	CON_PRINTBUFFER,
+	0,
+	0,
+	NULL
 };
 
 void 
@@ -64,6 +72,12 @@
 	return MKDEV (hwc_console_major, hwc_console_minor);
 }
 
+void 
+hwc_console_unblank (void)
+{
+	hwc_unblank ();
+}
+
 #endif
 
 void __init 
@@ -79,12 +93,12 @@
 
 	if (hwc_init () == 0) {
 
+		hwc_tty_init ();
+
 #ifdef CONFIG_HWC_CONSOLE
 
 		register_console (&hwc_console);
 #endif
-
-		hwc_tty_init ();
 	} else
 		panic (HWC_CON_PRINT_HEADER "hwc initialisation failed !");
 
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/hwc_rw.c linux/drivers/s390/char/hwc_rw.c
--- v2.4.1/linux/drivers/s390/char/hwc_rw.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/char/hwc_rw.c	Tue Feb 13 14:13:44 2001
@@ -6,14 +6,13 @@
  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Martin Peschke <peschke@fh-brandenburg.de>
  *
+ * 
  *
- *
- *
- *
- *
+ * 
+ * 
+ * 
  */
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/errno.h>
@@ -28,6 +27,7 @@
 #include <asm/bitops.h>
 #include <asm/setup.h>
 #include <asm/page.h>
+#include <asm/s390_ext.h>
 
 #ifndef MIN
 #define MIN(a,b) ((a<b) ? a : b)
@@ -118,12 +118,16 @@
 static unsigned char
  _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
 
-typedef u32 kmem_pages_t;
+/* pedantic: long because we use set_bit on it --RR */
+typedef long kmem_pages_t;
 
 #define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)
 
 #define HWC_TIMER_RUNS	1
-#define FLUSH_HWCBS	2
+#define HWC_FLUSH	2
+#define HWC_INIT	4
+#define HWC_BROKEN	8
+#define HWC_INTERRUPT	16
 
 static struct {
 
@@ -168,6 +172,8 @@
 
 	unsigned char flags;
 
+	hwc_high_level_calls_t *calls;
+
 	spinlock_t lock;
 
 	struct timer_list write_timer;
@@ -179,7 +185,6 @@
 		8,
 		    0,
 		    80,
-		    CODE_ASCII,
 		    1,
 		    50,
 		    MAX_KMEM_PAGES,
@@ -208,20 +213,24 @@
 	    0,
 	    0,
 	    0,
-	    0
+	    0,
+	    NULL
 
 };
 
+static unsigned long cr0 __attribute__ ((aligned (8)));
+static unsigned long cr0_save __attribute__ ((aligned (8)));
+static unsigned char psw_mask __attribute__ ((aligned (8)));
+
 #define DELAYED_WRITE 0
 #define IMMEDIATE_WRITE 1
 
 static signed int do_hwc_write (int from_user, unsigned char *,
 				unsigned int,
-				unsigned char,
 				unsigned char);
 
 static asmlinkage int 
-internal_print (char write_time, const char *fmt,...)
+internal_print (char write_time, char *fmt,...)
 {
 	va_list args;
 	int i;
@@ -230,7 +239,7 @@
 	va_start (args, fmt);
 	i = vsprintf (buf, fmt, args);
 	va_end (args);
-	return do_hwc_write (0, buf, i, CODE_ASCII, write_time);
+	return do_hwc_write (0, buf, i, write_time);
 }
 
 int 
@@ -246,7 +255,7 @@
 
 	i = vsprintf (buf, fmt, args);
 	va_end (args);
-	retval = do_hwc_write (0, buf, i, CODE_ASCII, IMMEDIATE_WRITE);
+	retval = do_hwc_write (0, buf, i, IMMEDIATE_WRITE);
 
 	spin_unlock_irqrestore (&hwc_data.lock, flags);
 
@@ -296,8 +305,8 @@
 {
 	unsigned int condition_code = 1;
 
-	__asm__ __volatile__ ("L 1, 0(0,%0) \n\t"
-			      "LRA 2, 0(0,%1) \n\t"
+	__asm__ __volatile__ ("L 1, 0(%0) \n\t"
+			      "LRA 2, 0(%1) \n\t"
 			      ".long 0xB2200012 \n\t"
 			      :
 			      :"a" (&hwc_command_word), "a" (hwcb)
@@ -315,7 +324,7 @@
 {
 	u32 param;
 
-	__asm__ __volatile__ ("L %0,128(0,0)\n\t"
+	__asm__ __volatile__ ("L %0,128\n\t"
 			      :"=r" (param));
 
 	return ((unsigned char *) param);
@@ -361,7 +370,7 @@
 
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		__asm__ ("LHI 1,0xe30\n\t"
-			 "LRA 2,0(0,%0) \n\t"
+			 "LRA 2,0(%0) \n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (bad_addr)
@@ -392,7 +401,7 @@
 			page = (unsigned long) BUF_HWCB;
 
 			if (page >= hwc_data.kmem_start &&
-			    page < hwc_data.kmem_end) {
+			    page <= hwc_data.kmem_end) {
 
 				page_nr = (int)
 				    ((page - hwc_data.kmem_start) >> 12);
@@ -423,8 +432,8 @@
 	if (hwc_data.hwcb_count < 2)
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		__asm__ ("LHI 1,0xe31\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (BUF_HWCB), "a" (OUT_HWCB)
@@ -510,7 +519,7 @@
 		    (hwc_data.kmem_start + (page_nr << 12));
 		set_bit (page_nr, &hwc_data.kmem_pages);
 	} else
-		page = (unsigned char *) __get_free_page (GFP_ATOMIC);
+		page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA);
 
 	if (!page)
 		return -ENOMEM;
@@ -573,9 +582,8 @@
 		OUT_HWCB = OUT_HWCB_NEXT;
 
 		if (page >= hwc_data.kmem_start &&
-		    page < hwc_data.kmem_end) {
-
-			memset ((void *) page, 0, PAGE_SIZE);
+		    page <= hwc_data.kmem_end) {
+			/*memset((void *) page, 0, PAGE_SIZE); */
 
 			page_nr = (int) ((page - hwc_data.kmem_start) >> 12);
 			clear_bit (page_nr, &hwc_data.kmem_pages);
@@ -663,8 +671,8 @@
 #ifdef DUMP_HWC_WRITE_ERROR
 	if (condition_code != HWC_COMMAND_INITIATED)
 		__asm__ ("LHI 1,0xe20\n\t"
-			 "L 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "L 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (&condition_code), "a" (OUT_HWCB)
@@ -695,7 +703,7 @@
 
 	release_write_hwcb ();
 
-	hwc_data.flags &= ~FLUSH_HWCBS;
+	hwc_data.flags &= ~HWC_FLUSH;
 }
 
 static int 
@@ -703,79 +711,81 @@
 {
 	write_hwcb_t *hwcb;
 	int retval;
+
+#ifdef DUMP_HWC_WRITE_ERROR
 	unsigned char *param;
 
 	param = ext_int_param ();
-	if (param != hwc_data.current_hwcb)
+	if (param != hwc_data.current_hwcb) {
+		internal_print (
+				       DELAYED_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "write_event_mask_2 : "
+				       "HWCB address does not fit "
+				       "(expected: 0x%x, got: 0x%x).\n",
+				       hwc_data.current_hwcb,
+				       param);
 		return -EINVAL;
+	}
+#endif
 
 	hwcb = (write_hwcb_t *) OUT_HWCB;
 
-#ifdef DUMP_HWC_WRITE_ERROR
-#if 0
-	if (((unsigned char *) hwcb) != param)
+#ifdef DUMP_HWC_WRITE_LIST_ERROR
+	if (((unsigned char *) hwcb) != hwc_data.current_hwcb) {
 		__asm__ ("LHI 1,0xe22\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
-			 "LRA 4,0(0,%2)\n\t"
-			 "LRA 5,0(0,%3)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
+			 "LRA 4,0(%2)\n\t"
+			 "LRA 5,0(%3)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (OUT_HWCB),
 			 "a" (hwc_data.current_hwcb),
 			 "a" (BUF_HWCB),
-			 "a" (param)
+			 "a" (hwcb)
 	      :	 "1", "2", "3", "4", "5");
+	}
 #endif
-	if (hwcb->response_code != 0x0020)
-#if 0
-		internal_print (DELAYED_WRITE, HWC_RW_PRINT_HEADER
-		  "\n************************ error in write_event_data_2()\n"
-				"OUT_HWCB:                    0x%x\n"
-				"BUF_HWCB:                    0x%x\n"
-				"response_code:               0x%x\n"
-				"hwc_data.hwcb_count:        %d\n"
-				"hwc_data.kmem_pages:        0x%x\n"
-				"hwc_data.ioctls.kmem_hwcb:   %d\n"
-				"hwc_data.ioctls.max_hwcb:    %d\n"
-				"hwc_data.kmem_start:        0x%x\n"
-				"hwc_data.kmem_end:          0x%x\n"
-		    "*****************************************************\n",
-				OUT_HWCB,
-				BUF_HWCB,
-				hwcb->response_code,
-				hwc_data.hwcb_count,
-				hwc_data.kmem_pages,
-				hwc_data.ioctls.kmem_hwcb,
-				hwc_data.ioctls.max_hwcb,
-				hwc_data.kmem_start,
-				hwc_data.kmem_end);
-#endif
-	__asm__ ("LHI 1,0xe21\n\t"
-		 "LRA 2,0(0,%0)\n\t"
-		 "LRA 3,0(0,%1)\n\t"
-		 "LRA 4,0(0,%2)\n\t"
-		 "LH 5,0(0,%3)\n\t"
-		 "SRL 5,8(0)\n\t"
-		 "J .+0 \n\t"
-      :
-      :	 "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
-		 "a" (BUF_HWCB),
-		 "a" (&(hwc_data.hwcb_count))
-      :	 "1", "2", "3", "4", "5");
+
+#ifdef DUMP_HWC_WRITE_ERROR
+	if (hwcb->response_code != 0x0020) {
+		__asm__ ("LHI 1,0xe21\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
+			 "LRA 4,0(%2)\n\t"
+			 "LH 5,0(%3)\n\t"
+			 "SRL 5,8\n\t"
+			 "J .+0 \n\t"
+	      :
+	      :	 "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
+			 "a" (BUF_HWCB),
+			 "a" (&(hwc_data.hwcb_count))
+	      :	 "1", "2", "3", "4", "5");
+	}
 #endif
 
 	if (hwcb->response_code == 0x0020) {
 
 		retval = OUT_HWCB_CHAR;
 		release_write_hwcb ();
-	} else
+	} else {
+		internal_print (
+				       DELAYED_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "write_event_data_2 : "
+				       "failed operation "
+				       "(response code: 0x%x "
+				       "HWCB address: 0x%x).\n",
+				       hwcb->response_code,
+				       hwcb);
 		retval = -EIO;
+	}
 
 	hwc_data.current_servc = 0;
 	hwc_data.current_hwcb = NULL;
 
-	if (hwc_data.flags & FLUSH_HWCBS)
+	if (hwc_data.flags & HWC_FLUSH)
 		flush_hwcbs ();
 
 	return retval;
@@ -795,10 +805,10 @@
 #ifdef DUMP_HWC_WRITE_LIST_ERROR
 		if (add_mto (message, count) != count)
 			__asm__ ("LHI 1,0xe32\n\t"
-				 "LRA 2,0(0,%0)\n\t"
-				 "L 3,0(0,%1)\n\t"
-				 "LRA 4,0(0,%2)\n\t"
-				 "LRA 5,0(0,%3)\n\t"
+				 "LRA 2,0(%0)\n\t"
+				 "L 3,0(%1)\n\t"
+				 "LRA 4,0(%2)\n\t"
+				 "LRA 5,0(%3)\n\t"
 				 "J .+0 \n\t"
 		      :
 		      :	 "a" (message), "a" (&hwc_data.kmem_pages),
@@ -864,13 +874,12 @@
 		     int from_user,
 		     unsigned char *msg,
 		     unsigned int count,
-		     unsigned char code,
 		     unsigned char write_time)
 {
 	unsigned int i_msg = 0;
 	unsigned short int spaces = 0;
 	unsigned int processed_characters = 0;
-	unsigned char ch, orig_ch;
+	unsigned char ch;
 	unsigned short int obuf_count;
 	unsigned short int obuf_cursor;
 	unsigned short int obuf_columns;
@@ -887,15 +896,10 @@
 	}
 
 	for (i_msg = 0; i_msg < count; i_msg++) {
-
 		if (from_user)
-			get_user (orig_ch, msg + i_msg);
-		else
-			orig_ch = msg[i_msg];
-		if (code == CODE_EBCDIC)
-			ch = _ebcasc[orig_ch];
+			get_user (ch, msg + i_msg);
 		else
-			ch = orig_ch;
+			ch = msg[i_msg];
 
 		processed_characters++;
 
@@ -981,8 +985,9 @@
 			if (isprint (ch))
 				hwc_data.obuf[hwc_data.obuf_start +
 					      obuf_cursor++]
-				    = (code == CODE_ASCII) ?
-				    _ascebc[orig_ch] : orig_ch;
+				    = (MACHINE_IS_VM) ?
+				    _ascebc[ch] :
+				    _ascebc_500[ch];
 		}
 		if (obuf_cursor > obuf_count)
 			obuf_count = obuf_cursor;
@@ -1044,8 +1049,8 @@
 
 	spin_lock_irqsave (&hwc_data.lock, flags);
 
-	retval = do_hwc_write (from_user, msg, count, hwc_data.ioctls.code,
-			       IMMEDIATE_WRITE);
+	retval = do_hwc_write (from_user, (unsigned char *) msg,
+			       count, IMMEDIATE_WRITE);
 
 	spin_unlock_irqrestore (&hwc_data.lock, flags);
 
@@ -1125,7 +1130,7 @@
 		if (hwc_data.current_servc != HWC_CMDW_WRITEDATA)
 			flush_hwcbs ();
 		else
-			hwc_data.flags |= FLUSH_HWCBS;
+			hwc_data.flags |= HWC_FLUSH;
 	}
 	if (flag & IN_WRITE_BUF) {
 		hwc_data.obuf_cursor = 0;
@@ -1301,13 +1306,17 @@
 	if (hwc_data.ioctls.delim)
 		count = seperate_cases (start, count);
 
-	if (hwc_data.ioctls.echo)
-		do_hwc_write (0, start, count, CODE_EBCDIC, IMMEDIATE_WRITE);
-
-	if (hwc_data.ioctls.code == CODE_ASCII)
+	if (MACHINE_IS_VM)
 		EBCASC (start, count);
+	else
+		EBCASC_500 (start, count);
 
-	store_hwc_input (start, count);
+	if (hwc_data.ioctls.echo) {
+		do_hwc_write (0, start, count, IMMEDIATE_WRITE);
+	}
+	if (hwc_data.calls != NULL)
+		if (hwc_data.calls->move_input != NULL)
+			(hwc_data.calls->move_input) (start, count);
 
 	return count;
 }
@@ -1496,8 +1505,8 @@
 #ifdef DUMP_HWC_READ_ERROR
 	if (condition_code == HWC_NOT_OPERATIONAL)
 		__asm__ ("LHI 1,0xe40\n\t"
-			 "L 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "L 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0 \n\t"
 	      :
 	      :	 "a" (&condition_code), "a" (hwc_data.page)
@@ -1531,8 +1540,8 @@
 	    (hwcb->response_code != 0x60F0) &&
 	    (hwcb->response_code != 0x62F0))
 		__asm__ ("LHI 1,0xe41\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "L 3,0(0,%1)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "L 3,0(%1)\n\t"
 			 "J .+0\n\t"
 	      :
 	      :	 "a" (hwc_data.page), "a" (&(hwcb->response_code))
@@ -1552,6 +1561,13 @@
 
 	case 0x60F0:
 	case 0x62F0:
+		internal_print (
+				       IMMEDIATE_WRITE,
+				       HWC_RW_PRINT_HEADER
+				       "unconditional read: "
+				     "got interrupt and tried to read input, "
+				  "but nothing found (response code=0x%x).\n",
+				       hwcb->response_code);
 		return 0;
 
 	case 0x0100:
@@ -1625,16 +1641,14 @@
 	unsigned int condition_code;
 	int retval;
 
-	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
-
 	condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);
 
 #ifdef DUMP_HWC_INIT_ERROR
 
-	if (condition_code != HWC_COMMAND_INITIATED)
+	if (condition_code == HWC_NOT_OPERATIONAL)
 		__asm__ ("LHI 1,0xe10\n\t"
-			 "L 2,0(0,%0)\n\t"
-			 "LRA 3,0(0,%1)\n\t"
+			 "L 2,0(%0)\n\t"
+			 "LRA 3,0(%1)\n\t"
 			 "J .+0\n\t"
 	      :
 	      :	 "a" (&condition_code), "a" (hwc_data.page)
@@ -1669,28 +1683,34 @@
 	if (hwcb->hwc_receive_mask & ET_PMsgCmd_Mask)
 		hwc_data.write_prio = 1;
 
-	if (hwcb->hwc_send_mask & ET_OpCmd_Mask)
+	if (hwcb->hwc_send_mask & ET_OpCmd_Mask) {
+		internal_print (DELAYED_WRITE,
+				HWC_RW_PRINT_HEADER
+				"capable of receipt of commands\n");
 		hwc_data.read_nonprio = 1;
-
-	if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask)
+	}
+	if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask) {
+		internal_print (DELAYED_WRITE,
+				HWC_RW_PRINT_HEADER
+				"capable of receipt of priority commands\n");
 		hwc_data.read_nonprio = 1;
-
+	}
 	if ((hwcb->response_code != 0x0020) ||
 	    (!hwc_data.write_nonprio) ||
 	    ((!hwc_data.read_nonprio) && (!hwc_data.read_prio)))
 #ifdef DUMP_HWC_INIT_ERROR
 		__asm__ ("LHI 1,0xe11\n\t"
-			 "LRA 2,0(0,%0)\n\t"
-			 "L 3,0(0,%1)\n\t"
+			 "LRA 2,0(%0)\n\t"
+			 "L 3,0(%1)\n\t"
 			 "J .+0\n\t"
 	      :
 	      :	 "a" (hwcb), "a" (&(hwcb->response_code))
 	      :	 "1", "2", "3");
 #else
-		retval = -EIO
+		retval = -EIO;
 #endif
 
-		    hwc_data.current_servc = 0;
+	hwc_data.current_servc = 0;
 	hwc_data.current_hwcb = NULL;
 
 	return retval;
@@ -1720,18 +1740,6 @@
 	} else
 		tmp.columns = ioctls->columns;
 
-	switch (ioctls->code) {
-	case CODE_EBCDIC:
-	case CODE_ASCII:
-		tmp.code = ioctls->code;
-		break;
-	default:
-		if (correct)
-			tmp.code = CODE_ASCII;
-		else
-			retval = -EINVAL;
-	}
-
 	tmp.final_nl = ioctls->final_nl;
 
 	if (ioctls->max_hwcb < 2) {
@@ -1773,9 +1781,55 @@
 }
 
 int 
+do_hwc_init (void)
+{
+	int retval;
+
+	memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
+
+	do {
+
+		retval = write_event_mask_1 ();
+
+		if (retval == -EBUSY) {
+
+			hwc_data.flags |= HWC_INIT;
+
+			__ctl_store (cr0, 0, 0);
+			cr0_save = cr0;
+			cr0 |= 0x00000200;
+			cr0 &= 0xFFFFF3AC;
+			__ctl_load (cr0, 0, 0);
+
+			asm volatile ("STOSM %0,0x01"
+				      :"=m" (psw_mask)::"memory");
+
+			while (!(hwc_data.flags & HWC_INTERRUPT))
+				barrier ();
+
+			asm volatile ("STNSM %0,0xFE"
+				      :"=m" (psw_mask)::"memory");
+
+			__ctl_load (cr0_save, 0, 0);
+
+			hwc_data.flags &= ~HWC_INIT;
+		}
+	} while (retval == -EBUSY);
+
+	if (retval == -EIO) {
+		hwc_data.flags |= HWC_BROKEN;
+		printk (HWC_RW_PRINT_HEADER "HWC not operational\n");
+	}
+	return retval;
+}
+
+void do_hwc_interrupt (struct pt_regs *regs, __u16 code);
+
+int 
 hwc_init (void)
 {
 	int retval;
+
 #ifdef BUFFER_STRESS_TEST
 
 	init_hwcb_t *hwcb;
@@ -1783,17 +1837,11 @@
 
 #endif
 
-#ifdef CONFIG_3215
-	if (MACHINE_IS_VM)
-		return 0;
-#endif
+	if (register_external_interrupt (0x2401, do_hwc_interrupt) != 0)
+		panic ("Couldn't request external interrupts 0x2401");
 
 	spin_lock_init (&hwc_data.lock);
 
-	retval = write_event_mask_1 ();
-	if (retval < 0)
-		return retval;
-
 #ifdef USE_VM_DETECTION
 
 	if (MACHINE_IS_VM) {
@@ -1811,10 +1859,12 @@
 	retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
 
 	hwc_data.kmem_start = (unsigned long)
-	    alloc_bootmem_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
+	    alloc_bootmem_low_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
 	hwc_data.kmem_end = hwc_data.kmem_start +
 	    hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1;
 
+	retval = do_hwc_init ();
+
 	ctl_set_bit (0, 9);
 
 #ifdef BUFFER_STRESS_TEST
@@ -1836,45 +1886,108 @@
 
 #endif
 
-	return retval;
+	return /*retval */ 0;
 }
 
-void 
-do_hwc_interrupt (void)
+signed int 
+hwc_register_calls (hwc_high_level_calls_t * calls)
 {
+	if (calls == NULL)
+		return -EINVAL;
 
-	spin_lock (&hwc_data.lock);
+	if (hwc_data.calls != NULL)
+		return -EBUSY;
 
-	if (!hwc_data.current_servc) {
+	hwc_data.calls = calls;
+	return 0;
+}
 
-		unconditional_read_1 ();
+signed int 
+hwc_unregister_calls (hwc_high_level_calls_t * calls)
+{
+	if (hwc_data.calls == NULL)
+		return -EINVAL;
+
+	if (calls != hwc_data.calls)
+		return -EINVAL;
+
+	hwc_data.calls = NULL;
+	return 0;
+}
 
+void 
+do_hwc_interrupt (struct pt_regs *regs, __u16 code)
+{
+
+	if (hwc_data.flags & HWC_INIT) {
+
+		hwc_data.flags |= HWC_INTERRUPT;
+	} else if (hwc_data.flags & HWC_BROKEN) {
+
+		if (!do_hwc_init ()) {
+			hwc_data.flags &= ~HWC_BROKEN;
+			internal_print (DELAYED_WRITE,
+					HWC_RW_PRINT_HEADER
+					"delayed HWC setup after"
+					" temporary breakdown\n");
+		}
 	} else {
+		spin_lock (&hwc_data.lock);
 
-		switch (hwc_data.current_servc) {
+		if (!hwc_data.current_servc) {
 
-		case HWC_CMDW_WRITEMASK:
+			unconditional_read_1 ();
 
-			write_event_mask_2 ();
-			break;
+		} else {
 
-		case HWC_CMDW_WRITEDATA:
+			switch (hwc_data.current_servc) {
 
-			write_event_data_2 ();
-			break;
+			case HWC_CMDW_WRITEMASK:
 
-		case HWC_CMDW_READDATA:
+				write_event_mask_2 ();
+				break;
 
-			unconditional_read_2 ();
-			break;
-		}
+			case HWC_CMDW_WRITEDATA:
 
-		write_event_data_1 ();
+				write_event_data_2 ();
+				break;
+
+			case HWC_CMDW_READDATA:
+
+				unconditional_read_2 ();
+				break;
+			}
+
+			write_event_data_1 ();
+		}
+		if (hwc_data.calls != NULL)
+			if (hwc_data.calls->wake_up != NULL)
+				(hwc_data.calls->wake_up) ();
+		spin_unlock (&hwc_data.lock);
 	}
+}
 
-	wake_up_hwc_tty ();
+void 
+hwc_unblank (void)
+{
 
+	spin_lock (&hwc_data.lock);
 	spin_unlock (&hwc_data.lock);
+
+	__ctl_store (cr0, 0, 0);
+	cr0_save = cr0;
+	cr0 |= 0x00000200;
+	cr0 &= 0xFFFFF3AC;
+	__ctl_load (cr0, 0, 0);
+
+	asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory");
+
+	while (ALL_HWCB_CHAR)
+		barrier ();
+
+	asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory");
+
+	__ctl_load (cr0_save, 0, 0);
 }
 
 int 
@@ -1904,12 +2017,6 @@
 			goto fault;
 		break;
 
-	case TIOCHWCSCODE:
-		if (get_user (tmp.code, (ioctl_code_t *) arg))
-			goto fault;
-
-		break;
-
 	case TIOCHWCSNL:
 		if (get_user (tmp.final_nl, (ioctl_nl_t *) arg))
 			goto fault;
@@ -1951,12 +2058,6 @@
 	case TIOCHWCGCOLS:
 		if (put_user (tmp.columns, (ioctl_cols_t *) arg))
 			goto fault;
-		break;
-
-	case TIOCHWCGCODE:
-		if (put_user (tmp.code, (ioctl_code_t *) arg))
-			goto fault;
-
 		break;
 
 	case TIOCHWCGNL:
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/hwc_rw.h linux/drivers/s390/char/hwc_rw.h
--- v2.4.1/linux/drivers/s390/char/hwc_rw.h	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/char/hwc_rw.h	Tue Feb 13 14:13:44 2001
@@ -12,31 +12,12 @@
 
 #include <linux/ioctl.h>
 
-#ifndef __HWC_RW_C__
-
-extern int hwc_init (void);
-
-extern int hwc_write (int from_user, const unsigned char *, unsigned int);
-
-extern unsigned int hwc_chars_in_buffer (unsigned char);
-
-extern unsigned int hwc_write_room (unsigned char);
-
-extern void hwc_flush_buffer (unsigned char);
-
-extern signed int hwc_ioctl (unsigned int, unsigned long);
-
-extern void do_hwc_interrupt (void);
-
-extern int hwc_printk (const char *,...);
-
-#else
-
-extern void store_hwc_input (unsigned char *, unsigned int);
+typedef struct {
 
-extern void wake_up_hwc_tty (void);
+	void (*move_input) (unsigned char *, unsigned int);
 
-#endif
+	void (*wake_up) (void);
+} hwc_high_level_calls_t;
 
 #define IN_HWCB      1
 #define IN_WRITE_BUF 2
@@ -45,7 +26,6 @@
 typedef unsigned short int ioctl_htab_t;
 typedef unsigned char ioctl_echo_t;
 typedef unsigned short int ioctl_cols_t;
-typedef unsigned char ioctl_code_t;
 typedef signed char ioctl_nl_t;
 typedef unsigned short int ioctl_obuf_t;
 typedef unsigned char ioctl_case_t;
@@ -55,7 +35,6 @@
 	ioctl_htab_t width_htab;
 	ioctl_echo_t echo;
 	ioctl_cols_t columns;
-	ioctl_code_t code;
 	ioctl_nl_t final_nl;
 	ioctl_obuf_t max_hwcb;
 	ioctl_obuf_t kmem_hwcb;
@@ -73,8 +52,6 @@
 
 #define TIOCHWCSCOLS	_IOW(HWC_IOCTL_LETTER, 2, _hwc_ioctls.columns)
 
-#define TIOCHWCSCODE	_IOW(HWC_IOCTL_LETTER, 3, _hwc_ioctls.code)
-
 #define TIOCHWCSNL	_IOW(HWC_IOCTL_LETTER, 4, _hwc_ioctls.final_nl)
 
 #define TIOCHWCSOBUF	_IOW(HWC_IOCTL_LETTER, 5, _hwc_ioctls.max_hwcb)
@@ -91,8 +68,6 @@
 
 #define TIOCHWCGCOLS	_IOR(HWC_IOCTL_LETTER, 12, _hwc_ioctls.columns)
 
-#define TIOCHWCGCODE	_IOR(HWC_IOCTL_LETTER, 13, _hwc_ioctls.code)
-
 #define TIOCHWCGNL	_IOR(HWC_IOCTL_LETTER, 14, _hwc_ioctls.final_nl)
 
 #define TIOCHWCGOBUF	_IOR(HWC_IOCTL_LETTER, 15, _hwc_ioctls.max_hwcb)
@@ -107,7 +82,30 @@
 
 #define TIOCHWCGCURR	_IOR(HWC_IOCTL_LETTER, 21, _hwc_ioctls)
 
-#define CODE_ASCII              0x0
-#define CODE_EBCDIC             0x1
+#ifndef __HWC_RW_C__
+
+extern int hwc_init (void);
+
+extern int hwc_write (int from_user, const unsigned char *, unsigned int);
+
+extern unsigned int hwc_chars_in_buffer (unsigned char);
+
+extern unsigned int hwc_write_room (unsigned char);
+
+extern void hwc_flush_buffer (unsigned char);
+
+extern void hwc_unblank (void);
+
+extern signed int hwc_ioctl (unsigned int, unsigned long);
+
+extern void do_hwc_interrupt (void);
+
+extern int hwc_printk (const char *,...);
+
+extern signed int hwc_register_calls (hwc_high_level_calls_t *);
+
+extern signed int hwc_unregister_calls (hwc_high_level_calls_t *);
+
+#endif
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/hwc_tty.c linux/drivers/s390/char/hwc_tty.c
--- v2.4.1/linux/drivers/s390/char/hwc_tty.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/char/hwc_tty.c	Tue Feb 13 14:13:44 2001
@@ -33,9 +33,12 @@
 	unsigned short int buf_count;
 
 	spinlock_t lock;
+
+	hwc_high_level_calls_t calls;
 } hwc_tty_data_struct;
 
-static hwc_tty_data_struct hwc_tty_data;
+static hwc_tty_data_struct hwc_tty_data =
+{ /* NULL/0 */ };
 static struct tty_driver hwc_tty_driver;
 static struct tty_struct *hwc_tty_table[1];
 static struct termios *hwc_tty_termios[1];
@@ -44,6 +47,9 @@
 
 extern struct termios tty_std_termios;
 
+void hwc_tty_wake_up (void);
+void hwc_tty_input (unsigned char *, unsigned int);
+
 static int 
 hwc_tty_open (struct tty_struct *tty,
 	      struct file *filp)
@@ -57,18 +63,11 @@
 	hwc_tty_data.tty = tty;
 	tty->low_latency = 0;
 
-	return 0;
-}
+	hwc_tty_data.calls.wake_up = hwc_tty_wake_up;
+	hwc_tty_data.calls.move_input = hwc_tty_input;
+	hwc_register_calls (&(hwc_tty_data.calls));
 
-void 
-wake_up_hwc_tty (void)
-{
-	if (hwc_tty_data.tty == NULL)
-		return;
-	if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
-	    hwc_tty_data.tty->ldisc.write_wakeup)
-		(hwc_tty_data.tty->ldisc.write_wakeup) (hwc_tty_data.tty);
-	wake_up_interruptible (&hwc_tty_data.tty->write_wait);
+	return 0;
 }
 
 static void 
@@ -80,7 +79,12 @@
 			"do not close hwc tty because of wrong device number");
 		return;
 	}
+	if (tty->count > 1)
+		return;
+
 	hwc_tty_data.tty = NULL;
+
+	hwc_unregister_calls (&(hwc_tty_data.calls));
 }
 
 static int 
@@ -147,7 +151,7 @@
 static void 
 hwc_tty_flush_buffer (struct tty_struct *tty)
 {
-	wake_up_hwc_tty ();
+	hwc_tty_wake_up ();
 }
 
 static int 
@@ -164,7 +168,18 @@
 }
 
 void 
-store_hwc_input (unsigned char *buf, unsigned int count)
+hwc_tty_wake_up (void)
+{
+	if (hwc_tty_data.tty == NULL)
+		return;
+	if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
+	    hwc_tty_data.tty->ldisc.write_wakeup)
+		(hwc_tty_data.tty->ldisc.write_wakeup) (hwc_tty_data.tty);
+	wake_up_interruptible (&hwc_tty_data.tty->write_wait);
+}
+
+void 
+hwc_tty_input (unsigned char *buf, unsigned int count)
 {
 	struct tty_struct *tty = hwc_tty_data.tty;
 
@@ -208,7 +223,7 @@
 			tty->flip.count += count;
 		}
 		tty_flip_buffer_push (tty);
-		wake_up_hwc_tty ();
+		hwc_tty_wake_up ();
 	}
 }
 
@@ -238,7 +253,7 @@
 	hwc_tty_driver.termios_locked = hwc_tty_termios_locked;
 
 	hwc_tty_driver.open = hwc_tty_open;
-	hwc_tty_driver.close = NULL /* hwc_tty_close */ ;
+	hwc_tty_driver.close = hwc_tty_close;
 	hwc_tty_driver.write = hwc_tty_write;
 	hwc_tty_driver.put_char = hwc_tty_put_char;
 	hwc_tty_driver.flush_chars = hwc_tty_flush_chars;
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape.c linux/drivers/s390/char/tape.c
--- v2.4.1/linux/drivers/s390/char/tape.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,723 @@
+
+/***********************************************************************
+ *  drivers/s390/char/tape.c
+ *    tape device driver for S/390 tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress... :-)
+ ***********************************************************************
+ */
+
+#include "tapedefs.h"
+
+#include <linux/config.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/proc_fs.h>
+#include <asm/types.h>
+#include <asm/ccwcache.h>
+#include <asm/idals.h>
+#include <asm/ebcdic.h>
+#include <linux/compatmac.h>
+#ifdef MODULE
+#include <linux/module.h>
+#endif   
+#ifdef TAPE_DEBUG
+#include <asm/debug.h>
+#endif
+#ifdef CONFIG_S390_TAPE_DYNAMIC
+#include <asm/s390dyn.h>
+#endif
+#include "tape.h"
+#include "tape3490.h"
+#include "tape3480.h"
+
+#define PRINTK_HEADER "T390:"
+
+/* state handling routines */
+inline void tapestate_set (tape_info_t * tape, int newstate);
+inline int tapestate_get (tape_info_t * tape);
+void tapestate_event (tape_info_t * tape, int event);
+
+/* our globals */
+tape_info_t *first_tape_info = NULL;
+tape_discipline_t *first_discipline = NULL;
+tape_frontend_t *first_frontend = NULL;
+#ifdef TAPE_DEBUG
+debug_info_t *tape_debug_area = NULL;
+#endif
+
+char* state_verbose[TS_SIZE]={
+    "TS_UNUSED",  "TS_IDLE", "TS_DONE", "TS_FAILED",
+    "TS_BLOCK_INIT",
+    "TS_BSB_INIT",
+    "TS_BSF_INIT",
+    "TS_DSE_INIT",
+    "TS_EGA_INIT",
+    "TS_FSB_INIT",
+    "TS_FSF_INIT",
+    "TS_LDI_INIT",
+    "TS_LBL_INIT",
+    "TS_MSE_INIT",
+    "TS_NOP_INIT",
+    "TS_RBA_INIT",
+    "TS_RBI_INIT",
+    "TS_RBU_INIT",
+    "TS_RBL_INIT",
+    "TS_RDC_INIT",
+    "TS_RFO_INIT",
+    "TS_RSD_INIT",
+    "TS_REW_INIT",
+    "TS_REW_RELEASE_INIT",
+    "TS_RUN_INIT",
+    "TS_SEN_INIT",
+    "TS_SID_INIT",
+    "TS_SNP_INIT",
+    "TS_SPG_INIT",
+    "TS_SWI_INIT",
+    "TS_SMR_INIT",
+    "TS_SYN_INIT",
+    "TS_TIO_INIT",
+    "TS_UNA_INIT",
+    "TS_WRI_INIT",
+    "TS_WTM_INIT",
+    "TS_NOT_OPER"};
+
+char* event_verbose[TE_SIZE]= {
+    "TE_START", "TE_DONE", "TE_FAILED", "TE_ERROR", "TE_OTHER"};
+
+#ifdef CONFIG_PROC_FS		/* don't waste space if unused */
+/*
+ * The proc filesystem: function to read and entry
+ */
+int
+tape_read_procmem (char *buf, char **start, off_t offset,
+		   int len, int unused)
+{
+	tape_info_t *tape = first_tape_info;
+	len = sprintf (buf, "minor\tstate\n");
+	do {
+		if (len >= PAGE_SIZE - 80)
+			len += sprintf (buf + len, "terminated...\n");
+		len += sprintf (buf + len,
+				"%d\t%s\n", tape->rew_minor,
+				((tapestate_get (tape) >= 0) && (tapestate_get (tape) < TS_SIZE)) ?
+				state_verbose[tapestate_get (tape)] :
+				"UNKNOWN STATE");
+	} while ((tape = (tape_info_t *) (tape->next)) != NULL);
+	return len;
+}
+
+#endif				/* CONFIG_PROC_FS */
+
+/* SECTION: Managing wrappers for ccwcache */
+
+#define TAPE_EMERGENCY_REQUESTS 16
+
+static ccw_req_t *tape_emergency_req[TAPE_EMERGENCY_REQUESTS] =
+{NULL,};
+static spinlock_t tape_emergency_req_lock = SPIN_LOCK_UNLOCKED;
+
+static void
+tape_init_emergency_req (void)
+{
+	int i;
+	for (i = 0; i < TAPE_EMERGENCY_REQUESTS; i++) {
+		tape_emergency_req[i] = (ccw_req_t *) get_free_page (GFP_KERNEL);
+	}
+}
+
+#ifdef MODULE // We only cleanup the emergency requests on module unload.
+static void
+tape_cleanup_emergency_req (void)
+{
+	int i;
+	for (i = 0; i < TAPE_EMERGENCY_REQUESTS; i++) {
+		if (tape_emergency_req[i])
+			free_page ((long) (tape_emergency_req[i]));
+		else
+			printk (KERN_WARNING PRINTK_HEADER "losing one page for 'in-use' emergency request\n");
+	}
+}
+#endif
+
+ccw_req_t *
+tape_alloc_request (char *magic, int cplength, int datasize)
+{
+	ccw_req_t *rv = NULL;
+	int i;
+	if ((rv = ccw_alloc_request (magic, cplength, datasize)) != NULL) {
+		return rv;
+	}
+	if (cplength * sizeof (ccw1_t) + datasize + sizeof (ccw_req_t) > PAGE_SIZE) {
+		return NULL;
+	}
+	spin_lock (&tape_emergency_req_lock);
+	for (i = 0; i < TAPE_EMERGENCY_REQUESTS; i++) {
+		if (tape_emergency_req[i] != NULL) {
+			rv = tape_emergency_req[i];
+			tape_emergency_req[i] = NULL;
+		}
+	}
+	spin_unlock (&tape_emergency_req_lock);
+	if (rv) {
+		memset (rv, 0, PAGE_SIZE);
+		rv->cache = (kmem_cache_t *) (tape_emergency_req + i);
+		strncpy ((char *) (&rv->magic), magic, 4);
+		ASCEBC ((char *) (&rv->magic), 4);
+		rv->cplength = cplength;
+		rv->datasize = datasize;
+		rv->data = (void *) ((long) rv + PAGE_SIZE - datasize);
+		rv->cpaddr = (ccw1_t *) ((long) rv + sizeof (ccw_req_t));
+	}
+	return rv;
+}
+
+void
+tape_free_request (ccw_req_t * request)
+{
+	if (request->cache >= (kmem_cache_t *) tape_emergency_req &&
+	    request->cache <= (kmem_cache_t *) (tape_emergency_req + TAPE_EMERGENCY_REQUESTS)) {
+		*((ccw_req_t **) (request->cache)) = request;
+	} else {
+		clear_normalized_cda ((ccw1_t *) (request->cpaddr));	// avoid memory leak caused by modeset_byte
+
+		ccw_free_request (request);
+	}
+}
+
+/*
+ * Allocate a ccw request and reserve it for tape driver
+ */
+inline
+ ccw_req_t *
+tape_alloc_ccw_req (tape_info_t * tape, int cplength, int datasize)
+{
+	char tape_magic_id[] = "tape";
+	ccw_req_t *cqr = NULL;
+
+	if (!tape)
+		return NULL;
+	cqr = tape_alloc_request (tape_magic_id, cplength, datasize);
+
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+		PRINT_WARN ("empty CQR generated\n");
+#endif
+	}
+	cqr->magic = TAPE_MAGIC;	/* sets an identifier for tape driver   */
+	cqr->device = tape;	/* save pointer to tape info    */
+	return cqr;
+}
+
+/*
+ * Find the tape_info_t structure associated with irq
+ */
+static inline tape_info_t *
+tapedev_find_info (int irq)
+{
+	tape_info_t *tape;
+
+	tape = first_tape_info;
+	if (tape != NULL)
+		do {
+			if (tape->devinfo.irq == irq)
+				break;
+		} while ((tape = (tape_info_t *) tape->next) != NULL);
+	return tape;
+}
+
+#define QUEUE_THRESHOLD 5
+
+/*
+ * Tape interrupt routine, called from Ingo's I/O layer
+ */
+void
+tape_irq (int irq, void *int_parm, struct pt_regs *regs)
+{
+	tape_info_t *tape = tapedev_find_info (irq);
+
+	/* analyse devstat and fire event */
+	if (tape->devstat.dstat & DEV_STAT_UNIT_CHECK) {
+		tapestate_event (tape, TE_ERROR);
+	} else if (tape->devstat.dstat & (DEV_STAT_DEV_END)) {
+		tapestate_event (tape, TE_DONE);
+	} else
+		tapestate_event (tape, TE_OTHER);
+}
+
+int 
+tape_oper_handler ( int irq, struct _devreg *dreg) {
+    tape_info_t* tape=first_tape_info;
+    tape_info_t* newtape;
+    int rc,tape_num,retries=0;
+    s390_dev_info_t dinfo;
+    tape_discipline_t* disc;
+    long lockflags;
+    while ((tape!=NULL) && (tape->devinfo.irq!=irq)) 
+        tape=tape->next;
+    if (tape!=NULL) {
+        // irq is (still) used by tape. tell ingo to try again later
+        PRINT_WARN ("Oper handler for irq %d called while irq still (internaly?) used.\n",irq);
+        return -EAGAIN;
+    }
+    // irq is not used by tape
+    rc = get_dev_info_by_irq (irq, &dinfo);
+    if (rc == -ENODEV) {
+        retries++;
+        if (retries > 5)
+            return -ENODEV;
+    }
+    disc = first_discipline;
+    while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))
+        disc = (tape_discipline_t *) (disc->next);
+    
+    if ((disc == NULL) || (rc == -ENODEV))
+        return -ENODEV;
+    
+    /* Allocate tape structure  */
+    tape = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);
+    if (tape == NULL) {
+        PRINT_INFO (KERN_ERR "tape: can't allocate memory for "
+                    "tape info structure\n");
+        return -ENOBUFS;
+    }
+    tape->discipline = disc;
+    disc->tape = tape;
+    tape_num=0;
+    newtape=first_tape_info;
+    while (newtape!=NULL) {
+        if (newtape->rew_minor==tape_num) {
+            // tape num in use. try next one
+            tape_num+=2;
+            newtape=first_tape_info;
+        } else {
+            // tape num not used by newtape. look at next tape info
+            newtape=newtape->next;
+        }
+    }
+    rc = tape_setup (tape, irq, tape_num);
+    if (rc) {
+        kfree (tape);
+        return -ENOBUFS;
+    }
+    s390irq_spin_lock_irqsave (irq,lockflags);
+    if (first_tape_info == NULL) {
+        first_tape_info = tape;
+    } else {
+        newtape = first_tape_info;
+        while (newtape->next != NULL)
+            newtape = newtape->next;
+        newtape->next = tape;
+    }
+    s390irq_spin_unlock_irqrestore (irq, lockflags);
+    return 0;
+}
+
+
+static void
+tape_noper_handler ( int irq, int status ) {
+    tape_info_t *ti=first_tape_info;
+    tape_info_t *lastti;
+    long lockflags;
+    s390irq_spin_lock_irqsave(irq,lockflags);
+    while (ti!=NULL) {
+        if (ti->devinfo.irq==irq) {
+            tapestate_set(ti,TS_NOT_OPER);
+            if (tapestate_get(ti)!=TS_UNUSED) {
+                // device is in use!
+                PRINT_WARN ("Tape #%d was detached while it was busy. Expect errors!",ti->blk_minor);
+                ti->rc=-ENXIO; 
+                wake_up_interruptible(&ti->wq);
+            } else {
+                // device is unused!
+                if (ti==first_tape_info) {
+                    first_tape_info=ti->next;
+                } else {
+                    lastti=first_tape_info;
+                    while (lastti->next!=ti) lastti=lastti->next;
+                    lastti->next=ti->next;
+                }
+                kfree(ti);
+            }
+            s390irq_spin_unlock_irqrestore(irq,lockflags);
+            return;
+        }
+        ti=ti->next;
+    }
+    s390irq_spin_unlock_irqrestore(irq,lockflags);
+    PRINT_WARN ("Tape not found for irq %d. Device is detached.",irq);
+}
+
+
+void
+tape_dump_sense (devstat_t * stat)
+{
+	int sl, sct;
+	PRINT_WARN ("------------I/O resulted in unit check:-----------\n");
+	for (sl = 0; sl < 4; sl++) {
+		PRINT_WARN ("Sense:");
+		for (sct = 0; sct < 8; sct++) {
+			PRINT_WARN (" %2d:0x%02X", 8 * sl + sct,
+				    stat->ii.sense.data[8 * sl + sct]);
+		}
+		PRINT_WARN ("\n");
+	}
+	PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "
+		    " %02X%02X%02X%02X %02X%02X%02X%02X \n",
+		    stat->ii.sense.data[0], stat->ii.sense.data[1],
+		    stat->ii.sense.data[2], stat->ii.sense.data[3],
+		    stat->ii.sense.data[4], stat->ii.sense.data[5],
+		    stat->ii.sense.data[6], stat->ii.sense.data[7],
+		    stat->ii.sense.data[8], stat->ii.sense.data[9],
+		    stat->ii.sense.data[10], stat->ii.sense.data[11],
+		    stat->ii.sense.data[12], stat->ii.sense.data[13],
+		    stat->ii.sense.data[14], stat->ii.sense.data[15]);
+	PRINT_INFO ("Sense data: %02X%02X%02X%02X %02X%02X%02X%02X "
+		    " %02X%02X%02X%02X %02X%02X%02X%02X \n",
+		    stat->ii.sense.data[16], stat->ii.sense.data[17],
+		    stat->ii.sense.data[18], stat->ii.sense.data[19],
+		    stat->ii.sense.data[20], stat->ii.sense.data[21],
+		    stat->ii.sense.data[22], stat->ii.sense.data[23],
+		    stat->ii.sense.data[24], stat->ii.sense.data[25],
+		    stat->ii.sense.data[26], stat->ii.sense.data[27],
+		    stat->ii.sense.data[28], stat->ii.sense.data[29],
+		    stat->ii.sense.data[30], stat->ii.sense.data[31]);
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"SENSE:");
+        for (sl=0;sl<31;sl++) {
+            debug_int_event (tape_debug_area,3,stat->ii.sense.data[sl]);
+        }
+        debug_int_exception (tape_debug_area,3,stat->ii.sense.data[31]);
+#endif
+}
+
+/*
+ * Setup tape_info_t structure of a tape device
+ */
+int
+tape_setup (tape_info_t * ti, int irq, int minor)
+{
+	long lockflags;
+	int rc = 0;
+
+	rc = get_dev_info_by_irq (irq, &(ti->devinfo));
+	if (rc == -ENODEV) {	/* end of device list */
+		return rc;
+	}
+	ti->rew_minor = minor;
+	ti->nor_minor = minor + 1;
+	ti->blk_minor = minor;
+	/* Register IRQ */
+#ifdef CONFIG_S390_TAPE_DYNAMIC
+        rc = s390_request_irq_special (irq, tape_irq, tape_noper_handler,0, "tape", &(ti->devstat));
+#else
+	rc = s390_request_irq (irq, tape_irq, 0, "tape", &(ti->devstat));
+#endif
+	s390irq_spin_lock_irqsave (irq, lockflags);
+	ti->next = NULL;
+	if (rc) {
+		PRINT_WARN ("Cannot register irq %d, rc=%d\n", irq, rc);
+	} else
+		PRINT_WARN ("Register irq %d for using with discipline %x\n", irq, ti->discipline->cu_type);
+	init_waitqueue_head (&ti->wq);
+	ti->kernbuf = ti->userbuf = ti->discdata = NULL;
+	tapestate_set (ti, TS_UNUSED);
+        ti->discdata=NULL;
+	ti->discipline->setup_assist (ti);
+        ti->wanna_wakeup=0;
+	s390irq_spin_unlock_irqrestore (irq, lockflags);
+	return rc;
+}
+
+/*
+ *      tape_init will register the driver for each tape.
+ */
+int
+tape_init (void)
+{
+	long lockflags;
+	s390_dev_info_t dinfo;
+	tape_discipline_t *disc;
+	tape_info_t *ti = NULL, *tempti = NULL;
+        char *opt_char,*opt_block,*opt_3490,*opt_3480;
+	int irq = 0, rc, retries = 0, tape_num = 0;
+        static int initialized=0;
+
+        if (initialized) // Only init the devices once
+            return 0;
+        initialized=1;
+
+#ifdef TAPE_DEBUG
+        tape_debug_area = debug_register ( "tape", 3, 2, 10);
+        debug_register_view(tape_debug_area,&debug_hex_ascii_view);
+        debug_text_event (tape_debug_area,3,"begin init");
+#endif /* TAPE_DEBUG */
+
+        /* print banner */        
+        PRINT_WARN ("IBM S/390 Tape Device Driver (ALPHA).\n");
+        PRINT_WARN ("(C) IBM Deutschland Entwicklung GmbH, 2000\n");
+        opt_char=opt_block=opt_3480=opt_3490="not present";
+#ifdef CONFIG_S390_TAPE_CHAR
+        opt_char="built in";
+#endif
+#ifdef CONFIG_S390_TAPE_BLOCK
+        opt_block="built in";
+#endif
+#ifdef CONFIG_S390_TAPE_3480
+        opt_3480="built in";
+#endif
+#ifdef CONFIG_S390_TAPE_3490
+        opt_3490="built in";
+#endif
+        /* print feature info */
+        PRINT_WARN ("character device frontend   : %s\n",opt_char);
+        PRINT_WARN ("block device frontend       : %s\n",opt_block);
+        PRINT_WARN ("support for 3480 compatible : %s\n",opt_3480);
+        PRINT_WARN ("support for 3490 compatible : %s\n",opt_3490);
+        
+
+#ifdef CONFIG_S390_TAPE_3490
+	first_discipline = tape3490_init ();
+	first_discipline->next = NULL;
+#endif
+
+#ifdef CONFIG_S390_TAPE_3480
+        if (first_discipline == NULL) {
+            first_discipline = tape3480_init ();
+            first_discipline->next = NULL;
+        } else {
+            first_discipline->next = tape3480_init ();
+            ((tape_discipline_t*) (first_discipline->next))->next=NULL;
+        }
+#endif
+
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"dev detect");
+#endif /* TAPE_DEBUG */
+	/* Allocate the tape structures */
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		rc = get_dev_info_by_irq (irq, &dinfo);
+
+		if (rc == -ENODEV) {
+			retries++;
+			if (retries > 5)
+				irq = NR_IRQS;
+		}
+		disc = first_discipline;
+		while ((disc != NULL) && (disc->cu_type != dinfo.sid_data.cu_type))
+			disc = (tape_discipline_t *) (disc->next);
+
+		if ((disc == NULL) || (rc == -ENODEV))
+			continue;
+#ifdef TAPE_DEBUG
+                debug_text_event (tape_debug_area,3,"det irq:  ");
+                debug_int_event (tape_debug_area,3,irq);
+                debug_text_event (tape_debug_area,3,"cu:       ");
+                debug_int_event (tape_debug_area,3,disc->cu_type);
+#endif /* TAPE_DEBUG */
+		/* Allocate tape structure  */
+		ti = kmalloc (sizeof (tape_info_t), GFP_ATOMIC);
+		if (ti == NULL) {
+#ifdef TAPE_DEBUG
+                    debug_text_exception (tape_debug_area,3,"ti:no mem ");
+#endif /* TAPE_DEBUG */
+                    PRINT_INFO (KERN_ERR "tape: can't allocate memory for "
+				    "tape info structure\n");
+                    continue;
+		}
+		memset(ti,0,sizeof(tape_info_t));
+		ti->discipline = disc;
+		disc->tape = ti;
+		rc = tape_setup (ti, irq, tape_num);
+		if (rc) {
+#ifdef TAPE_DEBUG
+                        debug_text_event (tape_debug_area,3,"tsetup err");
+                        debug_int_exception (tape_debug_area,3,rc);
+#endif /* TAPE_DEBUG */
+			kfree (ti);
+		} else {
+			s390irq_spin_lock_irqsave (irq, lockflags);
+			if (first_tape_info == NULL) {
+				first_tape_info = ti;
+			} else {
+				tempti = first_tape_info;
+				while (tempti->next != NULL)
+					tempti = tempti->next;
+				tempti->next = ti;
+			}
+			tape_num += 2;
+			s390irq_spin_unlock_irqrestore (irq, lockflags);
+		}
+	}
+
+	/* Allocate local buffer for the ccwcache       */
+	tape_init_emergency_req ();
+
+#if 0				// need to register s.th. for proc? FIXME!
+	if (proc_register_dynamic (&proc_root, &proc_root_tape))
+		PRINT_INFO (KERN_ERR "tape: registering "
+			    "/proc/tape failed\n");
+#endif
+
+	return 0;
+}
+
+#ifdef MODULE
+int
+init_module (void)
+{
+#ifdef CONFIG_S390_TAPE_CHAR
+	tapechar_init ();
+#endif
+#ifdef CONFIG_S390_TAPE_BLOCK
+	tapeblock_init ();
+#endif
+	return 0;
+}
+
+void
+cleanup_module (void)
+{
+        tape_info_t *tape ,*temp;
+        tape_frontend_t* frontend, *tempfe;
+        tape_discipline_t* disc ,*tempdi;
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"cleaup mod");
+#endif /* TAPE_DEBUG */
+
+#if 0				/* FIXME: Do we need to register s.th? */
+	proc_unregister (&proc_root, proc_root_tape.low_ino);
+#endif
+
+	tape = first_tape_info;
+	while (tape != NULL) {
+		temp = tape;
+		tape = tape->next;
+                //cleanup a device 
+#ifdef TAPE_DEBUG
+                debug_text_event (tape_debug_area,6,"free irq:");
+                debug_int_event (tape_debug_area,6,temp->devinfo.irq);
+#endif /* TAPE_DEBUG */
+		free_irq (temp->devinfo.irq, &(temp->devstat));
+                if (temp->discdata) kfree (temp->discdata);
+                if (temp->kernbuf) kfree (temp->kernbuf);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) // COMPAT:FIXME
+#else
+                kfree (temp->wq);
+#endif
+                if (temp->cqr) tape_free_request(temp->cqr);
+		kfree (temp);
+	}
+#ifdef CONFIG_S390_TAPE_CHAR
+	tapechar_uninit();
+#endif
+#ifdef CONFIG_S390_TAPE_BLOCK
+        tapeblock_uninit();
+#endif
+        frontend=first_frontend;
+	while (frontend != NULL) {
+		tempfe = frontend;
+		frontend = frontend->next;
+		kfree (tempfe);
+	}
+        disc=first_discipline;
+	while (disc != NULL) {
+		tempdi = disc;
+		disc = disc->next;
+		kfree (tempdi);
+	}
+	/* Deallocate the local buffer for the ccwcache         */
+	tape_cleanup_emergency_req ();
+#ifdef TAPE_DEBUG
+        debug_unregister (tape_debug_area);
+#endif /* TAPE_DEBUG */
+}
+#endif				/* MODULE */
+
+inline void
+tapestate_set (tape_info_t * tape, int newstate)
+{
+    if (tape->tape_state == TS_NOT_OPER) {
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"ts_set err");
+        debug_text_exception (tape_debug_area,3,"dev n.oper");
+#endif /* TAPE_DEBUG */
+    } else {
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,4,"ts. dev:  ");
+        debug_int_event (tape_debug_area,4,tape->blk_minor);
+        debug_text_event (tape_debug_area,4,"old ts:   ");
+        debug_text_event (tape_debug_area,4,(((tapestate_get (tape) < TS_SIZE) &&
+                                             (tapestate_get (tape) >=0 )) ?
+                                            state_verbose[tapestate_get (tape)] :
+                                            "UNKNOWN TS"));
+        debug_text_event (tape_debug_area,4,"new ts:   ");
+        debug_text_event (tape_debug_area,4,(((newstate < TS_SIZE) &&
+                                              (newstate >= 0)) ?
+                                             state_verbose[newstate] :
+                                             "UNKNOWN TS"));
+#endif /* TAPE_DEBUG */
+	tape->tape_state = newstate;
+    }
+}
+
+inline int
+tapestate_get (tape_info_t * tape)
+{
+	return (tape->tape_state);
+}
+
+void
+tapestate_event (tape_info_t * tape, int event)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"te! dev:  ");
+        debug_int_event (tape_debug_area,6,tape->blk_minor);
+        debug_text_event (tape_debug_area,6,"event:");
+        debug_text_event (tape_debug_area,6,((event >=0) &&
+                                            (event < TE_SIZE)) ?
+                         event_verbose[event] : "TE UNKNOWN");
+        debug_text_event (tape_debug_area,6,"state:");
+        debug_text_event (tape_debug_area,6,((tapestate_get(tape) >= 0) &&
+                                            (tapestate_get(tape) < TS_SIZE)) ?
+                         state_verbose[tapestate_get (tape)] :
+                         "TS UNKNOWN");
+#endif /* TAPE_DEBUG */    
+	if ((event >= 0) &&
+	    (event < TE_SIZE) &&
+	    (tapestate_get (tape) >= 0) &&
+	    (tapestate_get (tape) < TS_SIZE) &&
+	    ((*(tape->discipline->event_table))[tapestate_get (tape)][event] != NULL))
+		((*(tape->discipline->event_table))[tapestate_get (tape)][event]) (tape);
+	else {
+#ifdef TAPE_DEBUG
+                debug_text_exception (tape_debug_area,3,"TE UNEXPEC");
+#endif /* TAPE_DEBUG */
+		tape->discipline->default_handler (tape);
+	}
+}
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape.h linux/drivers/s390/char/tape.h
--- v2.4.1/linux/drivers/s390/char/tape.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,185 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape.h
+ *    tape device driver for 3480/3490E tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#ifndef _TAPE_H
+
+#define _TAPE_H
+#include <linux/config.h>
+#include <linux/blkdev.h>
+
+#define  MAX_TAPES                     7        /* Max tapes supported is 7*/
+#define TAPE_MAGIC 0xE3C1D7C5       /* is ebcdic-"TAPE" */
+
+typedef enum {
+    TS_UNUSED=0, TS_IDLE, TS_DONE, TS_FAILED,
+    TS_BLOCK_INIT,
+    TS_BSB_INIT,
+    TS_BSF_INIT,
+    TS_DSE_INIT,
+    TS_EGA_INIT,
+    TS_FSB_INIT,
+    TS_FSF_INIT,
+    TS_LDI_INIT,
+    TS_LBL_INIT,
+    TS_MSE_INIT,
+    TS_NOP_INIT,
+    TS_RBA_INIT,
+    TS_RBI_INIT,
+    TS_RBU_INIT,
+    TS_RBL_INIT,
+    TS_RDC_INIT,
+    TS_RFO_INIT,
+    TS_RSD_INIT,
+    TS_REW_INIT,
+    TS_REW_RELEASE_INIT,
+    TS_RUN_INIT,
+    TS_SEN_INIT,
+    TS_SID_INIT,
+    TS_SNP_INIT,
+    TS_SPG_INIT,
+    TS_SWI_INIT,
+    TS_SMR_INIT,
+    TS_SYN_INIT,
+    TS_TIO_INIT,
+    TS_UNA_INIT,
+    TS_WRI_INIT,
+    TS_WTM_INIT,
+    TS_NOT_OPER,
+    TS_SIZE } tape_stat;
+
+struct _tape_info_t; //Forward declaration
+
+typedef enum {
+    TE_START=0, TE_DONE, TE_FAILED, TE_ERROR, TE_OTHER,
+    TE_SIZE } tape_events;
+
+typedef void (*tape_event_handler_t) (struct _tape_info_t*);
+typedef ccw_req_t* (*tape_ccwgen_t)(struct _tape_info_t* tape,int count);
+typedef ccw_req_t* (*tape_reqgen_t)(struct request* req,struct _tape_info_t* tape,int tapeblock_major);
+typedef ccw_req_t* (*tape_rwblock_t)(const char* data,size_t count,struct _tape_info_t* tape);
+typedef void (*tape_freeblock_t)(ccw_req_t* cqr,struct _tape_info_t* tape);
+typedef void (*tape_setup_assist_t) (struct _tape_info_t*);
+typedef tape_event_handler_t tape_event_table_t[TS_SIZE][TE_SIZE];
+typedef struct _tape_discipline_t {
+    unsigned int cu_type;
+    tape_setup_assist_t setup_assist;
+    tape_reqgen_t bread;
+    tape_freeblock_t free_bread;
+    tape_rwblock_t write_block;
+    tape_freeblock_t free_write_block;
+    tape_rwblock_t read_block;
+    tape_freeblock_t free_read_block;
+    tape_ccwgen_t mtfsf;
+    tape_ccwgen_t mtbsf;
+    tape_ccwgen_t mtfsr;
+    tape_ccwgen_t mtbsr;
+    tape_ccwgen_t mtweof;
+    tape_ccwgen_t mtrew;
+    tape_ccwgen_t mtoffl;
+    tape_ccwgen_t mtnop;
+    tape_ccwgen_t mtbsfm;
+    tape_ccwgen_t mtfsfm;
+    tape_ccwgen_t mteom;
+    tape_ccwgen_t mterase;
+    tape_ccwgen_t mtsetdensity;
+    tape_ccwgen_t mtseek;
+    tape_ccwgen_t mttell;
+    tape_ccwgen_t mtsetdrvbuffer;
+    tape_ccwgen_t mtlock;
+    tape_ccwgen_t mtunlock;
+    tape_ccwgen_t mtload;
+    tape_ccwgen_t mtunload;
+    tape_ccwgen_t mtcompression;
+    tape_ccwgen_t mtsetpart;
+    tape_ccwgen_t mtmkpart;
+    tape_ccwgen_t mtiocget;
+    tape_ccwgen_t mtiocpos;
+    int (*discipline_ioctl_overload)(struct inode *,struct file*, unsigned int,unsigned long);
+    tape_event_table_t* event_table;
+    tape_event_handler_t default_handler;
+    struct _tape_info_t* tape; /* pointer for backreference */
+    void* next;
+} tape_discipline_t  __attribute__ ((aligned(8)));
+
+typedef struct _tape_frontend_t {
+    tape_setup_assist_t device_setup;
+    void* next;
+} tape_frontend_t  __attribute__ ((aligned(8)));
+
+
+typedef struct _tape_info_t {
+    wait_queue_head_t wq;
+    s390_dev_info_t devinfo;             /* device info from Common I/O */
+    int     wanna_wakeup;
+    int     rew_minor;                  /* minor number for the rewinding tape */
+    int     nor_minor;                  /* minor number for the nonrewinding tape */
+    int     blk_minor;                  /* minor number for the block device */
+    devstat_t devstat;	           /* contains irq, devno, status */
+    size_t  block_size;             /* block size of tape        */
+    int    drive_type;              /* Code indicating type of drive */
+    struct file *rew_filp;	           /* backpointer to file structure */
+    struct file *nor_filp;
+    struct file *blk_filp;
+    int tape_state;  /* State of the device. See tape_stat */
+    int rc;          /* Return code. */
+    tape_discipline_t* discipline;
+    request_queue_t request_queue;
+    struct request* current_request;
+    int blk_retries;
+    long position;
+    ccw_req_t* cqr;
+    atomic_t bh_scheduled;
+    struct tq_struct bh_tq;
+    void* discdata;
+    void* kernbuf;
+    void* userbuf;
+    void*  next;
+} tape_info_t  __attribute__ ((aligned(8)));
+
+/* tape initialisation functions */
+int tape_init(void);
+int tape_setup (tape_info_t * ti, int irq, int minor);
+
+/* functoins for alloc'ing ccw stuff */
+inline  ccw_req_t * tape_alloc_ccw_req (tape_info_t* tape, int cplength, int datasize);
+void tape_free_request (ccw_req_t * request);
+
+/* a function for dumping device sense info */
+void tape_dump_sense (devstat_t * stat);
+
+#ifdef CONFIG_S390_TAPE_DYNAMIC
+/* functions for dyn. dev. attach/detach */
+int tape_oper_handler ( int irq, struct _devreg *dreg);
+#endif
+
+/* functions for handling the status of a device */
+inline void tapestate_set (tape_info_t * tape, int newstate);
+inline int tapestate_get (tape_info_t * tape);
+extern char* state_verbose[TS_SIZE];
+extern char* event_verbose[TE_SIZE];
+
+/****************************************************************************/
+
+/* Some linked lists for storing plugins and devices */
+extern tape_info_t *first_tape_info;
+extern tape_discipline_t *first_discipline;
+extern tape_frontend_t *first_frontend;
+
+/* The debug area */
+#ifdef TAPE_DEBUG
+extern debug_info_t *tape_debug_area;
+#endif
+
+#endif /* for ifdef tape.h */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape3480.c linux/drivers/s390/char/tape3480.c
--- v2.4.1/linux/drivers/s390/char/tape3480.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape3480.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,145 @@
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape3480.c
+ *    tape device discipline for 3480 tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#include "tapedefs.h"
+#include <linux/version.h>
+#include <asm/ccwcache.h>	/* CCW allocations      */
+#include <asm/s390dyn.h>
+#include <asm/debug.h>
+#include <linux/compatmac.h>
+#include "tape.h"
+#include "tape34xx.h"
+#include "tape3480.h"
+
+tape_event_handler_t tape3480_event_handler_table[TS_SIZE][TE_SIZE] =
+{
+    /* {START , DONE, FAILED, ERROR, OTHER } */
+	{NULL, tape34xx_unused_done, NULL, tape34xx_unused_error, NULL},	/* TS_UNUSED */
+	{NULL, tape34xx_idle_done, NULL, tape34xx_idle_error, NULL},	/* TS_IDLE */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_DONE */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_FAILED */
+	{NULL, tape34xx_block_done, NULL, tape34xx_block_error, NULL},		/* TS_BLOCK_INIT */
+	{NULL, tape34xx_bsb_init_done, NULL, NULL, NULL},	/* TS_BSB_INIT */
+	{NULL, tape34xx_bsf_init_done, NULL, NULL, NULL},	/* TS_BSF_INIT */
+	{NULL, tape34xx_dse_init_done, NULL, NULL, NULL},	/* TS_DSE_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_EGA_INIT */
+	{NULL, tape34xx_fsb_init_done, NULL, NULL, NULL},	/* TS_FSB_INIT */
+	{NULL, tape34xx_fsf_init_done, NULL, tape34xx_fsf_init_error, NULL},	/* TS_FSF_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_LDI_INIT */
+	{NULL, tape34xx_lbl_init_done, NULL, tape34xx_lbl_init_error, NULL},	/* TS_LBL_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_MSE_INIT */
+	{NULL, tape34xx_nop_init_done, NULL, NULL, NULL},	/* TS_NOP_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBA_INIT */
+	{NULL, tape34xx_rbi_init_done, NULL, NULL, NULL},	/* TS_RBI_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBU_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBL_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RDC_INIT */
+	{NULL, tape34xx_rfo_init_done, NULL, tape34xx_rfo_init_error, NULL},	/* TS_RFO_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RSD_INIT */
+	{NULL, tape34xx_rew_init_done, NULL, tape34xx_rew_init_error, NULL},	/* TS_REW_INIT */
+	{NULL, tape34xx_rew_release_init_done, NULL, tape34xx_rew_release_init_error, NULL},	/* TS_REW_RELEASE_IMIT */
+	{NULL, tape34xx_run_init_done, NULL, tape34xx_run_init_error, NULL},	/* TS_RUN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SEN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SID_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SNP_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SPG_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SWI_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SMR_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SYN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_TIO_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_UNA_INIT */
+	{NULL, tape34xx_wri_init_done, NULL, tape34xx_wri_init_error, NULL},	/* TS_WRI_INIT */
+	{NULL, tape34xx_wtm_init_done, NULL, tape34xx_wtm_init_error, NULL},	/* TS_WTM_INIT */
+        {NULL, NULL, NULL, NULL, NULL}};     /* TS_NOT_OPER */
+
+devreg_t tape3480_devreg = {
+    ci : { hc: { ctype: 0x3480, dtype: 0x3480 } }, 
+    flag: DEVREG_MATCH_CU_TYPE,
+    oper_func: tape_oper_handler
+};
+
+
+void
+tape3480_setup_assist (tape_info_t * tape)
+{
+	tape3480_disc_data_t *data = NULL;
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,6,"3480 dsetu");
+    debug_text_event (tape_debug_area,6,"dev:");
+    debug_int_event (tape_debug_area,6,tape->blk_minor);
+#endif /* TAPE_DEBUG */
+	while (data == NULL)
+		data = kmalloc (sizeof (tape3480_disc_data_t), GFP_KERNEL);
+	data->modeset_byte = 0x00;
+	tape->discdata = (void *) data;
+}
+
+tape_discipline_t *
+tape3480_init (void)
+{
+	tape_discipline_t *disc;
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,3,"3480 init");
+#endif /* TAPE_DEBUG */
+	disc = kmalloc (sizeof (tape_discipline_t), GFP_KERNEL);
+	if (disc == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,3,"disc:nomem");
+#endif /* TAPE_DEBUG */
+		return disc;
+	}
+	disc->cu_type = 0x3480;
+	disc->setup_assist = tape3480_setup_assist;
+	disc->write_block = tape34xx_write_block;
+	disc->free_write_block = tape34xx_free_write_block;
+	disc->read_block = tape34xx_read_block;
+	disc->free_read_block = tape34xx_free_read_block;
+	disc->mtfsf = tape34xx_mtfsf;
+	disc->mtbsf = tape34xx_mtbsf;
+	disc->mtfsr = tape34xx_mtfsr;
+	disc->mtbsr = tape34xx_mtbsr;
+	disc->mtweof = tape34xx_mtweof;
+	disc->mtrew = tape34xx_mtrew;
+	disc->mtoffl = tape34xx_mtoffl;
+	disc->mtnop = tape34xx_mtnop;
+	disc->mtbsfm = tape34xx_mtbsfm;
+	disc->mtfsfm = tape34xx_mtfsfm;
+	disc->mteom = tape34xx_mteom;
+	disc->mterase = tape34xx_mterase;
+	disc->mtsetdensity = tape34xx_mtsetdensity;
+	disc->mtseek = tape34xx_mtseek;
+	disc->mttell = tape34xx_mttell;
+	disc->mtsetdrvbuffer = tape34xx_mtsetdrvbuffer;
+	disc->mtlock = tape34xx_mtlock;
+	disc->mtunlock = tape34xx_mtunlock;
+	disc->mtload = tape34xx_mtload;
+	disc->mtunload = tape34xx_mtunload;
+	disc->mtcompression = tape34xx_mtcompression;
+	disc->mtsetpart = tape34xx_mtsetpart;
+	disc->mtmkpart = tape34xx_mtmkpart;
+	disc->mtiocget = tape34xx_mtiocget;
+	disc->mtiocpos = tape34xx_mtiocpos;
+	disc->discipline_ioctl_overload = tape34xx_ioctl_overload;
+	disc->event_table = &tape3480_event_handler_table;
+	disc->default_handler = tape34xx_default_handler;
+	disc->bread = tape34xx_bread;
+	disc->free_bread = tape34xx_free_bread;
+	disc->tape = NULL;	/* pointer for backreference */
+	disc->next = NULL;
+	s390_device_register(&tape3480_devreg);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,3,"3480 regis");
+#endif /* TAPE_DEBUG */
+	return disc;
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape3480.h linux/drivers/s390/char/tape3480.h
--- v2.4.1/linux/drivers/s390/char/tape3480.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape3480.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,25 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape3480.h
+ *    tape device discipline for 3480 tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#ifndef _TAPE3480_H
+
+#define _TAPE3480_H
+
+
+typedef struct _tape3480_disc_data_t {
+    __u8 modeset_byte;
+} tape3480_disc_data_t  __attribute__ ((packed, aligned(8)));
+tape_discipline_t * tape3480_init (void);
+#endif // _TAPE3480_H
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape3490.c linux/drivers/s390/char/tape3490.c
--- v2.4.1/linux/drivers/s390/char/tape3490.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape3490.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,144 @@
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape3490.c
+ *    tape device discipline for 3490E tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#include "tapedefs.h"
+#include <linux/version.h>
+#include <asm/ccwcache.h>	/* CCW allocations      */
+#include <asm/s390dyn.h>
+#include <asm/debug.h>
+#include <linux/compatmac.h>
+#include "tape.h"
+#include "tape34xx.h"
+#include "tape3490.h"
+
+tape_event_handler_t tape3490_event_handler_table[TS_SIZE][TE_SIZE] =
+{
+    /* {START , DONE, FAILED, ERROR, OTHER } */
+	{NULL, tape34xx_unused_done, NULL, tape34xx_unused_error, NULL},	/* TS_UNUSED */
+	{NULL, tape34xx_idle_done, NULL, tape34xx_idle_error, NULL},	/* TS_IDLE */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_DONE */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_FAILED */
+	{NULL, tape34xx_block_done, NULL, tape34xx_block_error, NULL},		/* TS_BLOCK_INIT */
+	{NULL, tape34xx_bsb_init_done, NULL, NULL, NULL},	/* TS_BSB_INIT */
+	{NULL, tape34xx_bsf_init_done, NULL, NULL, NULL},	/* TS_BSF_INIT */
+	{NULL, tape34xx_dse_init_done, NULL, NULL, NULL},	/* TS_DSE_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_EGA_INIT */
+	{NULL, tape34xx_fsb_init_done, NULL, NULL, NULL},	/* TS_FSB_INIT */
+	{NULL, tape34xx_fsf_init_done, NULL, tape34xx_fsf_init_error, NULL},	/* TS_FSF_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_LDI_INIT */
+	{NULL, tape34xx_lbl_init_done, NULL, tape34xx_lbl_init_error, NULL},	/* TS_LBL_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_MSE_INIT */
+	{NULL, tape34xx_nop_init_done, NULL, NULL, NULL},	/* TS_NOP_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBA_INIT */
+	{NULL, tape34xx_rbi_init_done, NULL, NULL, NULL},	/* TS_RBI_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBU_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBL_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RDC_INIT */
+	{NULL, tape34xx_rfo_init_done, NULL, tape34xx_rfo_init_error, NULL},	/* TS_RFO_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RSD_INIT */
+	{NULL, tape34xx_rew_init_done, NULL, tape34xx_rew_init_error, NULL},	/* TS_REW_INIT */
+	{NULL, tape34xx_rew_release_init_done, NULL, tape34xx_rew_release_init_error, NULL},	/* TS_REW_RELEASE_IMIT */
+	{NULL, tape34xx_run_init_done, NULL, tape34xx_run_init_error, NULL},	/* TS_RUN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SEN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SID_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SNP_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SPG_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SWI_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SMR_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SYN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_TIO_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_UNA_INIT */
+	{NULL, tape34xx_wri_init_done, NULL, tape34xx_wri_init_error, NULL},	/* TS_WRI_INIT */
+	{NULL, tape34xx_wtm_init_done, NULL, tape34xx_wtm_init_error, NULL},	/* TS_WTM_INIT */
+        {NULL, NULL, NULL, NULL, NULL}};     /* TS_NOT_OPER */
+
+devreg_t tape3490_devreg = {
+    ci : { hc: { ctype: 0x3490, dtype: 0x3490 } }, 
+    flag: DEVREG_MATCH_CU_TYPE,
+    oper_func: tape_oper_handler
+};
+
+void
+tape3490_setup_assist (tape_info_t * tape)
+{
+	tape3490_disc_data_t *data = NULL;
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,6,"3490 dsetu");
+    debug_text_event (tape_debug_area,6,"dev:");
+    debug_int_event (tape_debug_area,6,tape->blk_minor);
+#endif /* TAPE_DEBUG */
+	while (data == NULL)
+		data = kmalloc (sizeof (tape3490_disc_data_t), GFP_KERNEL);
+	data->modeset_byte = 0x00;
+	tape->discdata = (void *) data;
+}
+
+tape_discipline_t *
+tape3490_init (void)
+{
+	tape_discipline_t *disc;
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,3,"3490 init");
+#endif /* TAPE_DEBUG */
+	disc = kmalloc (sizeof (tape_discipline_t), GFP_KERNEL);
+	if (disc == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,3,"disc:nomem");
+#endif /* TAPE_DEBUG */
+		return disc;
+	}
+	disc->cu_type = 0x3490;
+	disc->setup_assist = tape3490_setup_assist;
+	disc->write_block = tape34xx_write_block;
+	disc->free_write_block = tape34xx_free_write_block;
+	disc->read_block = tape34xx_read_block;
+	disc->free_read_block = tape34xx_free_read_block;
+	disc->mtfsf = tape34xx_mtfsf;
+	disc->mtbsf = tape34xx_mtbsf;
+	disc->mtfsr = tape34xx_mtfsr;
+	disc->mtbsr = tape34xx_mtbsr;
+	disc->mtweof = tape34xx_mtweof;
+	disc->mtrew = tape34xx_mtrew;
+	disc->mtoffl = tape34xx_mtoffl;
+	disc->mtnop = tape34xx_mtnop;
+	disc->mtbsfm = tape34xx_mtbsfm;
+	disc->mtfsfm = tape34xx_mtfsfm;
+	disc->mteom = tape34xx_mteom;
+	disc->mterase = tape34xx_mterase;
+	disc->mtsetdensity = tape34xx_mtsetdensity;
+	disc->mtseek = tape34xx_mtseek;
+	disc->mttell = tape34xx_mttell;
+	disc->mtsetdrvbuffer = tape34xx_mtsetdrvbuffer;
+	disc->mtlock = tape34xx_mtlock;
+	disc->mtunlock = tape34xx_mtunlock;
+	disc->mtload = tape34xx_mtload;
+	disc->mtunload = tape34xx_mtunload;
+	disc->mtcompression = tape34xx_mtcompression;
+	disc->mtsetpart = tape34xx_mtsetpart;
+	disc->mtmkpart = tape34xx_mtmkpart;
+	disc->mtiocget = tape34xx_mtiocget;
+	disc->mtiocpos = tape34xx_mtiocpos;
+	disc->discipline_ioctl_overload = tape34xx_ioctl_overload;
+	disc->event_table = &tape3490_event_handler_table;
+	disc->default_handler = tape34xx_default_handler;
+	disc->bread = tape34xx_bread;
+	disc->free_bread = tape34xx_free_bread;
+	disc->tape = NULL;	/* pointer for backreference */
+	disc->next = NULL;
+	s390_device_register(&tape3490_devreg);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,3,"3490 regis");
+#endif /* TAPE_DEBUG */
+	return disc;
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape3490.h linux/drivers/s390/char/tape3490.h
--- v2.4.1/linux/drivers/s390/char/tape3490.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape3490.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,25 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape3490.h
+ *    tape device discipline for 3490E tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#ifndef _TAPE3490_H
+
+#define _TAPE3490_H
+
+
+typedef struct _tape3490_disc_data_t {
+    __u8 modeset_byte;
+} tape3490_disc_data_t  __attribute__ ((packed, aligned(8)));
+tape_discipline_t * tape3490_init (void);
+#endif // _TAPE3490_H
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape34xx.c linux/drivers/s390/char/tape34xx.c
--- v2.4.1/linux/drivers/s390/char/tape34xx.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape34xx.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,1964 @@
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape34xx.c
+ *    common tape device discipline for 34xx tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#include "tapedefs.h"
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/stddef.h>
+#include <linux/kernel.h>
+#include <asm/types.h>
+#include <asm/uaccess.h>
+#include <linux/stat.h>
+#include <linux/proc_fs.h>
+#include <asm/ccwcache.h> 
+#include <asm/idals.h>  
+#ifdef CONFIG_S390_TAPE_DYNAMIC
+#include <asm/s390dyn.h>
+#endif
+#include <asm/debug.h>
+#include <linux/compatmac.h>
+#include "tape.h"
+#include "tape34xx.h"
+
+#define PRINTK_HEADER "T34xx:"
+
+tape_event_handler_t tape34xx_event_handler_table[TS_SIZE][TE_SIZE] =
+{
+    /* {START , DONE, FAILED, ERROR, OTHER } */
+	{NULL, tape34xx_unused_done, NULL, tape34xx_unused_error, NULL},	/* TS_UNUSED */
+	{NULL, tape34xx_idle_done, NULL, tape34xx_idle_error, NULL},	/* TS_IDLE */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_DONE */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_FAILED */
+	{NULL, tape34xx_block_done, NULL, tape34xx_block_error, NULL},		/* TS_BLOCK_INIT */
+	{NULL, tape34xx_bsb_init_done, NULL, NULL, NULL},	/* TS_BSB_INIT */
+	{NULL, tape34xx_bsf_init_done, NULL, NULL, NULL},	/* TS_BSF_INIT */
+	{NULL, tape34xx_dse_init_done, NULL, NULL, NULL},	/* TS_DSE_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_EGA_INIT */
+	{NULL, tape34xx_fsb_init_done, NULL, NULL, NULL},	/* TS_FSB_INIT */
+	{NULL, tape34xx_fsf_init_done, NULL, tape34xx_fsf_init_error, NULL},	/* TS_FSF_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_LDI_INIT */
+	{NULL, tape34xx_lbl_init_done, NULL, tape34xx_lbl_init_error, NULL},	/* TS_LBL_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_MSE_INIT */
+	{NULL, tape34xx_nop_init_done, NULL, NULL, NULL},	/* TS_NOP_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBA_INIT */
+	{NULL, tape34xx_rbi_init_done, NULL, NULL, NULL},	/* TS_RBI_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBU_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RBL_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RDC_INIT */
+	{NULL, tape34xx_rfo_init_done, NULL, tape34xx_rfo_init_error, NULL},	/* TS_RFO_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_RSD_INIT */
+	{NULL, tape34xx_rew_init_done, NULL, tape34xx_rew_init_error, NULL},	/* TS_REW_INIT */
+	{NULL, tape34xx_rew_release_init_done, NULL, tape34xx_rew_release_init_error, NULL},	/* TS_REW_RELEASE_IMIT */
+	{NULL, tape34xx_run_init_done, NULL, tape34xx_run_init_error, NULL},	/* TS_RUN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SEN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SID_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SNP_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SPG_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SWI_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SMR_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_SYN_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_TIO_INIT */
+	{NULL, NULL, NULL, NULL, NULL},		/* TS_UNA_INIT */
+	{NULL, tape34xx_wri_init_done, NULL, tape34xx_wri_init_error, NULL},	/* TS_WRI_INIT */
+	{NULL, tape34xx_wtm_init_done, NULL, tape34xx_wtm_init_error, NULL},	/* TS_WTM_INIT */
+	{NULL, NULL, NULL, NULL, NULL}};        /* TS_NOT_OPER */
+
+
+int
+tape34xx_ioctl_overload (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	return -EINVAL;		// no additional ioctls
+
+}
+
+ccw_req_t *
+tape34xx_write_block (const char *data, size_t count, tape_info_t * tape)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	void *mem;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xwbl nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	mem = kmalloc (count, GFP_KERNEL);
+	if (!mem) {
+		tape_free_request (cqr);
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xwbl nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	if (copy_from_user (mem, data, count)) {
+		kfree (mem);
+		tape_free_request (cqr);
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xwbl segf.");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+
+	ccw->cmd_code = WRITE_CMD;
+	ccw->flags = 0;
+	ccw->count = count;
+	set_normalized_cda (ccw, (unsigned long) mem);
+	if ((ccw->cda) == 0) {
+		kfree (mem);
+		tape_free_request (cqr);
+		return NULL;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = mem;
+	tape->userbuf = (void *) data;
+	tapestate_set (tape, TS_WRI_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xwbl ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+void 
+tape34xx_free_write_block (ccw_req_t * cqr, tape_info_t * tape)
+{
+	unsigned long lockflags;
+	ccw1_t *ccw;
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	ccw = cqr->cpaddr;
+	ccw++;
+	clear_normalized_cda (ccw);
+	kfree (tape->kernbuf);
+	tape_free_request (cqr);
+	tape->kernbuf = tape->userbuf = NULL;
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xfwb free");
+#endif /* TAPE_DEBUG */
+}
+
+ccw_req_t *
+tape34xx_read_block (const char *data, size_t count, tape_info_t * tape)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	void *mem;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xrbl nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	mem = kmalloc (count, GFP_KERNEL);
+	if (!mem) {
+		tape_free_request (cqr);
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xrbl nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+
+	ccw->cmd_code = READ_FORWARD;
+	ccw->flags = 0;
+	ccw->count = count;
+	set_normalized_cda (ccw, (unsigned long) mem);
+	if ((ccw->cda) == 0) {
+		kfree (mem);
+		tape_free_request (cqr);
+		return NULL;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = mem;
+	tape->userbuf = (void *) data;
+	tapestate_set (tape, TS_RFO_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xrbl ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+void 
+tape34xx_free_read_block (ccw_req_t * cqr, tape_info_t * tape)
+{
+	unsigned long lockflags;
+	size_t cpysize;
+	ccw1_t *ccw;
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	ccw = cqr->cpaddr;
+	ccw++;
+	cpysize = ccw->count - tape->devstat.rescnt;
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	if (copy_to_user (tape->userbuf, tape->kernbuf, cpysize)) {
+#ifdef TAPE_DEBUG
+	    debug_text_exception (tape_debug_area,6,"xfrb segf.");
+#endif /* TAPE_DEBUG */
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	clear_normalized_cda (ccw);
+	kfree (tape->kernbuf);
+	tape_free_request (cqr);
+	tape->kernbuf = tape->userbuf = NULL;
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xfrb free");
+#endif /* TAPE_DEBUG */
+}
+
+
+/*
+ * The IOCTL interface is implemented in the following section,
+ * excepted the MTRESET, MTSETBLK which are handled by tapechar.c
+ */
+/*
+ * MTFSF: Forward space over 'count' file marks. The tape is positioned
+ * at the EOT (End of Tape) side of the file mark.
+ */
+ccw_req_t *
+tape34xx_mtfsf (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xfsf parm");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xfsf nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = FORSPACEFILE;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 0;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_FSF_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xfsf ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTBSF: Backward space over 'count' file marks. The tape is positioned at
+ * the EOT (End of Tape) side of the last skipped file mark.
+ */
+ccw_req_t *
+tape34xx_mtbsf (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbsf parm");
+#endif /* TAPE_DEBUG */
+	        return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbsf nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = BACKSPACEFILE;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 0;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_BSF_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xbsf ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTFSR: Forward space over 'count' tape blocks (blocksize is set
+ * via MTSETBLK.
+ */
+ccw_req_t *
+tape34xx_mtfsr (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xfsr parm");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xfsr nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = FORSPACEBLOCK;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 0;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_FSB_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xfsr ccwgen");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTBSR: Backward space over 'count' tape blocks.
+ * (blocksize is set via MTSETBLK.
+ */
+ccw_req_t *
+tape34xx_mtbsr (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbsr parm");
+#endif /* TAPE_DEBUG */   
+	        return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbsr nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = BACKSPACEBLOCK;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 0;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_BSB_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xbsr ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTWEOF: Write 'count' file marks at the current position.
+ */
+ccw_req_t *
+tape34xx_mtweof (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xweo parm");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xweo nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = WRITETAPEMARK;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 1;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_WTM_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xweo ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTREW: Rewind the tape.
+ */
+ccw_req_t *
+tape34xx_mtrew (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 3, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xrew nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = REWIND;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_REW_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xrew ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTOFFL: Rewind the tape and put the drive off-line.
+ * Implement 'rewind unload'
+ */
+ccw_req_t *
+tape34xx_mtoffl (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 3, 32);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xoff nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = REWIND_UNLOAD;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = SENSE;
+	ccw->flags = 0;
+	ccw->count = 32;
+	ccw->cda = (unsigned long) cqr->cpaddr;
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_RUN_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xoff ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTNOP: 'No operation'.
+ */
+ccw_req_t *
+tape34xx_mtnop (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 1, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xnop nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) ccw->cmd_code;
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xnop ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTBSFM: Backward space over 'count' file marks.
+ * The tape is positioned at the BOT (Begin Of Tape) side of the
+ * last skipped file mark.
+ */
+ccw_req_t *
+tape34xx_mtbsfm (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbsm parm");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbsm nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = BACKSPACEFILE;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 0;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_BSF_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xbsm ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTFSFM: Forward space over 'count' file marks.
+ * The tape is positioned at the BOT (Begin Of Tape) side
+ * of the last skipped file mark.
+ */
+ccw_req_t *
+tape34xx_mtfsfm (tape_info_t * tape, int count)
+{
+	long lockflags;
+	int i;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count == 0) || (count > 510)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xfsm parm");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	cqr = tape_alloc_ccw_req (tape, 2 + count, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xfsm nomem");
+#endif /* TAPE_DEBUG */	    
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	for (i = 0; i < count; i++) {
+		ccw->cmd_code = FORSPACEFILE;
+		ccw->flags = CCW_FLAG_CC;
+		ccw->count = 0;
+		ccw->cda = (unsigned long) (&(ccw->cmd_code));
+		ccw++;
+	}
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_FSF_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xfsm ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTEOM: positions at the end of the portion of the tape already used
+ * for recordind data. MTEOM positions after the last file mark, ready for
+ * appending another file.
+ * MTRETEN: Retension the tape, i.e. forward space to end of tape and rewind.
+ */
+ccw_req_t *
+tape34xx_mteom (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 4, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xeom nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = FORSPACEFILE;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = CCW_CMD_TIC;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (cqr->cpaddr);
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_FSF_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xeom ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTERASE: erases the tape.
+ */
+ccw_req_t *
+tape34xx_mterase (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 5, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xera nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = REWIND;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = ERASE_GAP;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = DATA_SEC_ERASE;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_DSE_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xera ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTSETDENSITY: set tape density.
+ */
+ccw_req_t *
+tape34xx_mtsetdensity (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xden nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xden ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTSEEK: seek to the specified block.
+ */
+ccw_req_t *
+tape34xx_mtseek (tape_info_t * tape, int count)
+{
+	long lockflags;
+	__u8 *data;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((data = kmalloc (4 * sizeof (__u8), GFP_KERNEL)) == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xsee nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	data[0] = 0x01;
+	data[1] = data[2] = data[3] = 0x00;
+	if (count >= 4194304) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xsee parm");
+#endif /* TAPE_DEBUG */
+		kfree(data);
+		return NULL;
+	}
+	if (((tape34xx_disc_data_t *) tape->discdata)->modeset_byte & 0x08)	// IDRC on
+
+		data[1] = data[1] | 0x80;
+	data[3] += count % 256;
+	data[2] += (count / 256) % 256;
+	data[1] += (count / 65536);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xsee id:");
+	debug_int_event (tape_debug_area,6,count);
+#endif /* TAPE_DEBUG */
+	cqr = tape_alloc_ccw_req (tape, 3, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xsee nomem");
+#endif /* TAPE_DEBUG */
+		kfree (data);
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = LOCATE;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 4;
+	set_normalized_cda (ccw, (unsigned long) data);
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = data;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_LBL_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xsee ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTTELL: Tell block. Return the number of block relative to current file.
+ */
+ccw_req_t *
+tape34xx_mttell (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	void *mem;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xtel nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	mem = kmalloc (8, GFP_KERNEL);
+	if (!mem) {
+		tape_free_request (cqr);
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xtel nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+
+	ccw->cmd_code = READ_BLOCK_ID;
+	ccw->flags = 0;
+	ccw->count = 8;
+	set_normalized_cda (ccw, (unsigned long) mem);
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = mem;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_RBI_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xtel ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTSETDRVBUFFER: Set the tape drive buffer code to number.
+ * Implement NOP.
+ */
+ccw_req_t *
+tape34xx_mtsetdrvbuffer (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xbuf nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xbuf ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTLOCK: Locks the tape drive door.
+ * Implement NOP CCW command.
+ */
+ccw_req_t *
+tape34xx_mtlock (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xloc nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xloc ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTUNLOCK: Unlocks the tape drive door.
+ * Implement the NOP CCW command.
+ */
+ccw_req_t *
+tape34xx_mtunlock (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xulk nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xulk ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTLOAD: Loads the tape.
+ * Implement the NOP CCW command.
+ */
+ccw_req_t *
+tape34xx_mtload (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xloa nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xloa ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTUNLOAD: Rewind the tape and unload it.
+ */
+ccw_req_t *
+tape34xx_mtunload (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 3, 32);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xunl nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = REWIND_UNLOAD;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	ccw++;
+	ccw->cmd_code = SENSE;
+	ccw->flags = 0;
+	ccw->count = 32;
+	ccw->cda = (unsigned long) cqr->cpaddr;
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_RUN_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xunl ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTCOMPRESSION: used to enable compression.
+ * Sets the IDRC on/off.
+ */
+ccw_req_t *
+tape34xx_mtcompression (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	if ((count < 0) || (count > 1)) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xcom parm");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	if (count == 0)
+		((tape34xx_disc_data_t *) tape->discdata)->modeset_byte = 0x00;		// IDRC off
+
+	else
+		((tape34xx_disc_data_t *) tape->discdata)->modeset_byte = 0x08;		// IDRC on
+
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xcom nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xcom ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTSTPART: Move the tape head at the partition with the number 'count'.
+ * Implement the NOP CCW command.
+ */
+ccw_req_t *
+tape34xx_mtsetpart (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xspa nomem");
+#endif /* TAPE_DEBUG */	    
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xspa ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTMKPART: .... dummy .
+ * Implement the NOP CCW command.
+ */
+ccw_req_t *
+tape34xx_mtmkpart (tape_info_t * tape, int count)
+{
+	long lockflags;
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	cqr = tape_alloc_ccw_req (tape, 2, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xnpa nomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->kernbuf = NULL;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_NOP_INIT);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xnpa ccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+
+/*
+ * MTIOCGET: query the tape drive status.
+ */
+ccw_req_t *
+tape34xx_mtiocget (tape_info_t * tape, int count)
+{
+	return NULL;
+}
+
+/*
+ * MTIOCPOS: query the tape position.
+ */
+ccw_req_t *
+tape34xx_mtiocpos (tape_info_t * tape, int count)
+{
+	return NULL;
+}
+
+ccw_req_t * tape34xx_bread (struct request *req,tape_info_t* tape,int tapeblock_major) {
+	ccw_req_t *cqr;
+	ccw1_t *ccw;
+	__u8 *data;
+	int s2b = blksize_size[tapeblock_major][tape->blk_minor]/hardsect_size[tapeblock_major][tape->blk_minor];
+	int realcount;
+	int size,bhct = 0;
+	struct buffer_head* bh;
+	for (bh = req->bh; bh; bh = bh->b_reqnext) {
+		if (bh->b_size > blksize_size[tapeblock_major][tape->blk_minor])
+			for (size = 0; size < bh->b_size; size += blksize_size[tapeblock_major][tape->blk_minor])
+				bhct++;
+		else
+			bhct++;
+	}
+	if ((data = kmalloc (4 * sizeof (__u8), GFP_KERNEL)) == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,3,"xBREDnomem");
+#endif /* TAPE_DEBUG */
+		return NULL;
+	}
+	data[0] = 0x01;
+	data[1] = data[2] = data[3] = 0x00;
+	realcount=req->sector/s2b;
+	if (((tape34xx_disc_data_t *) tape->discdata)->modeset_byte & 0x08)	// IDRC on
+
+		data[1] = data[1] | 0x80;
+	data[3] += realcount % 256;
+	data[2] += (realcount / 256) % 256;
+	data[1] += (realcount / 65536);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xBREDid:");
+	debug_int_event (tape_debug_area,6,realcount);
+#endif /* TAPE_DEBUG */
+	cqr = tape_alloc_ccw_req (tape, 2+bhct+1, 0);
+	if (!cqr) {
+#ifdef TAPE_DEBUG
+	        debug_text_exception (tape_debug_area,6,"xBREDnomem");
+#endif /* TAPE_DEBUG */
+		kfree(data);
+		return NULL;
+	}
+	ccw = cqr->cpaddr;
+	ccw->cmd_code = MODE_SET_DB;
+	ccw->flags = CCW_FLAG_CC;
+	ccw->count = 1;
+	set_normalized_cda (ccw, (unsigned long) (&(((tape34xx_disc_data_t *) tape->discdata)->modeset_byte)));
+	if (realcount!=tape->position) {
+	    ccw++;
+	    ccw->cmd_code = LOCATE;
+	    ccw->flags = CCW_FLAG_CC;
+	    ccw->count = 4;
+	    set_normalized_cda (ccw, (unsigned long) data);
+	}
+	tape->position=realcount+req->nr_sectors/s2b;
+	for (bh=req->bh;bh!=NULL;) {
+	        ccw->flags = CCW_FLAG_CC;
+		if (bh->b_size >= blksize_size[tapeblock_major][tape->blk_minor]) {
+			for (size = 0; size < bh->b_size; size += blksize_size[tapeblock_major][tape->blk_minor]) {
+			        ccw++;
+				ccw->flags = CCW_FLAG_CC;
+				ccw->cmd_code = READ_FORWARD;
+				ccw->count = blksize_size[tapeblock_major][tape->blk_minor];
+				set_normalized_cda (ccw, __pa (bh->b_data + size));
+			}
+			bh = bh->b_reqnext;
+		} else {	/* group N bhs to fit into byt_per_blk */
+			for (size = 0; bh != NULL && size < blksize_size[tapeblock_major][tape->blk_minor];) {
+				ccw++;
+				ccw->flags = CCW_FLAG_DC;
+				ccw->cmd_code = READ_FORWARD;
+				ccw->count = bh->b_size;
+				set_normalized_cda (ccw, __pa (bh->b_data));
+				size += bh->b_size;
+				bh = bh->b_reqnext;
+			}
+			if (size != blksize_size[tapeblock_major][tape->blk_minor]) {
+				PRINT_WARN ("Cannot fulfill small request %d vs. %d (%ld sects)\n",
+					    size,
+					    blksize_size[tapeblock_major][tape->blk_minor],
+					    req->nr_sectors);
+
+				tape_free_request (cqr);
+				kfree(data);
+				return NULL;
+			}
+		}
+	}
+	ccw -> flags &= ~(CCW_FLAG_DC);
+	ccw -> flags |= (CCW_FLAG_CC);
+	ccw++;
+	ccw->cmd_code = NOP;
+	ccw->flags = 0;
+	ccw->count = 0;
+	ccw->cda = (unsigned long) (&(ccw->cmd_code));
+	tape->kernbuf = data;
+	tape->userbuf = NULL;
+	tapestate_set (tape, TS_BLOCK_INIT);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"xBREDccwg");
+#endif /* TAPE_DEBUG */
+	return cqr;
+}
+void tape34xx_free_bread (ccw_req_t* cqr,struct _tape_info_t* tape) {
+    ccw1_t* ccw;
+    for (ccw=(ccw1_t*)cqr->cpaddr;(ccw->flags & CCW_FLAG_CC)||(ccw->flags & CCW_FLAG_DC);ccw++) 
+	if ((ccw->cmd_code == MODE_SET_DB) ||
+	    (ccw->cmd_code == LOCATE) ||
+	    (ccw->cmd_code == READ_FORWARD))
+	    clear_normalized_cda(ccw);
+    tape_free_request(cqr);
+    kfree(tape->kernbuf);
+    tape->kernbuf=NULL;
+}
+
+/* event handlers */
+void
+tape34xx_default_handler (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,6,"xdefhandle");
+#endif /* TAPE_DEBUG */
+	tapestate_set (tape, TS_FAILED);
+	PRINT_ERR ("TAPE34XX: An unexpected Unit Check occured.\n");
+	PRINT_ERR ("TAPE34XX: Please read Documentation/s390/TAPE and report it!\n");
+	PRINT_ERR ("TAPE34XX: Current state is: %s",
+		   (((tapestate_get (tape) < TS_SIZE) && (tapestate_get (tape) >= 0)) ?
+		    state_verbose[tapestate_get (tape)] : "->UNKNOWN STATE<-"));
+	tape_dump_sense (&tape->devstat);
+	tape->rc = -EIO;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_unexpect_uchk_handler (tape_info_t * tape)
+{
+	if ((tape->devstat.ii.sense.data[0] == 0x40) &&
+	    (tape->devstat.ii.sense.data[1] == 0x40) &&
+	    (tape->devstat.ii.sense.data[3] == 0x43)) {
+		// no tape in the drive
+	        PRINT_INFO ("Drive %d not ready. No volume loaded.\n", tape->rew_minor / 2);
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,3,"xuuh nomed");
+#endif /* TAPE_DEBUG */
+		tapestate_set (tape, TS_FAILED);
+		tape->rc = -ENOMEDIUM;
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+	} else if ((tape->devstat.ii.sense.data[0] == 0x42) &&
+		   (tape->devstat.ii.sense.data[1] == 0x44) &&
+		   (tape->devstat.ii.sense.data[3] == 0x3b)) {
+       	        PRINT_INFO ("Media in drive %d was changed!\n",
+			    tape->rew_minor / 2);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,3,"xuuh medchg");
+#endif
+		/* nothing to do. chan end & dev end will be reported when io is finished */
+	} else {
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,3,"xuuh unexp");
+	        debug_text_event (tape_debug_area,3,"state:");
+	        debug_text_event (tape_debug_area,3,((tapestate_get (tape) < TS_SIZE) && 
+						     (tapestate_get (tape) >= 0)) ?
+				  state_verbose[tapestate_get (tape)] : 
+				  "TS UNKNOWN");
+#endif /* TAPE_DEBUG */
+		tape34xx_default_handler (tape);
+	}
+}
+
+void
+tape34xx_unused_done (tape_info_t * tape)
+{
+	if ((tape->devstat.ii.sense.data[0] == 0x40) &&
+	    (tape->devstat.ii.sense.data[1] == 0x40) &&
+	    (tape->devstat.ii.sense.data[3] == 0x43)) {
+	    // A medium was inserted in the drive!
+#ifdef TAPE_DEBUG
+	    debug_text_event (tape_debug_area,6,"xuud med");
+#endif /* TAPE_DEBUG */
+	} else {
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,3,"unsol.irq!");
+	        debug_text_event (tape_debug_area,3,"dev end");
+	        debug_int_exception (tape_debug_area,3,tape->devinfo.irq);
+#endif /* TAPE_DEBUG */
+		PRINT_WARN ("Unsolicited IRQ (Device End) caught in unused state.\n");
+		tape_dump_sense (&tape->devstat);
+	}
+}
+
+void
+tape34xx_unused_error (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,3,"unsol.irq!");
+    debug_text_event (tape_debug_area,3,"unit chk!");
+    debug_int_exception (tape_debug_area,3,tape->devinfo.irq);
+#endif /* TAPE_DEBUG */
+    PRINT_WARN ("Unsolicited IRQ (Unit Check) caught in unused state.\n");
+    tape_dump_sense (&tape->devstat);
+}
+
+void
+tape34xx_idle_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"unsol.irq!");
+        debug_text_event (tape_debug_area,3,"dev end");
+        debug_int_exception (tape_debug_area,3,tape->devinfo.irq);
+#endif /* TAPE_DEBUG */
+	PRINT_WARN ("Unsolicited IRQ (Device End) caught in idle state.\n");
+	tape_dump_sense (&tape->devstat);
+}
+
+void
+tape34xx_idle_error (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"unsol.irq!");
+	debug_text_event (tape_debug_area,3,"unit chk!");
+	debug_int_exception (tape_debug_area,3,tape->devinfo.irq);
+#endif /* TAPE_DEBUG */
+	PRINT_WARN ("Unsolicited IRQ (Unit Check) caught in idle state.\n");
+	tape_dump_sense (&tape->devstat);
+}
+
+void
+tape34xx_block_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"x:bREQdone");
+#endif /* TAPE_DEBUG */
+	tapestate_set(tape,TS_DONE);
+	schedule_tapeblock_exec_IO(tape);
+}
+
+void
+tape34xx_block_error (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"x:xREQfail");
+#endif /* TAPE_DEBUG */
+	tapestate_set(tape,TS_FAILED);
+	schedule_tapeblock_exec_IO(tape);
+}
+
+void
+tape34xx_bsf_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"bsf done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_dse_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"dse done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_fsf_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"fsf done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_fsf_init_error (tape_info_t * tape)
+{
+	if (((tape->devstat.ii.sense.data[0] == 0x08) ||	// sense.data[0]=08 -> first time
+	      (tape->devstat.ii.sense.data[0] == 0x10) ||	// an alternate one...
+	      (tape->devstat.ii.sense.data[0] == 0x12)) &&	// sense.data[1]=12 -> repeated message
+	     (tape->devstat.ii.sense.data[1] == 0x40)) {
+		// end of recorded area!
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"fsf fail");
+        debug_text_exception (tape_debug_area,3,"eoRecArea");
+#endif	/* TAPE_DEBUG */
+		tape->rc = -EIO;
+		tapestate_set (tape, TS_FAILED);
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+	} else {
+		tape34xx_unexpect_uchk_handler (tape);
+	}
+}
+
+void
+tape34xx_fsb_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"fsb done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_bsb_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"bsb done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_lbl_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"lbl done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	//s390irq_spin_unlock(tape->devinfo.irq);
+	tape->wanna_wakeup=1;
+	wake_up (&tape->wq);
+}
+
+void
+tape34xx_lbl_init_error (tape_info_t * tape)
+{
+	if (((tape->devstat.ii.sense.data[0] == 0x00) ||	// sense.data[0]=00 -> first time
+	      (tape->devstat.ii.sense.data[0] == 0x08) ||	// an alternate one...
+	     (tape->devstat.ii.sense.data[0] == 0x10) ||        // alternate, too
+	      (tape->devstat.ii.sense.data[0] == 0x12)) &&	// sense.data[1]=12 -> repeated message
+	     ((tape->devstat.ii.sense.data[1] == 0x40) ||
+	      (tape->devstat.ii.sense.data[1] == 0xc0))) {
+		// block not found!
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"lbl fail");
+        debug_text_exception (tape_debug_area,3,"blk nfound");
+#endif	/* TAPE_DEBUG */
+		tape->rc = -EIO;
+		tapestate_set (tape, TS_FAILED);
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+	} else {
+		tape34xx_unexpect_uchk_handler (tape);
+	}
+}
+
+void
+tape34xx_nop_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"nop done..");
+        debug_text_exception (tape_debug_area,6,"or rew/rel");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	//s390irq_spin_unlock(tape->devinfo.irq);
+	tape->wanna_wakeup=1;
+	wake_up (&tape->wq);
+}
+
+void
+tape34xx_rfo_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"rfo done");
+#endif
+	//BH: use irqsave
+	//s390irq_spin_lock(tape->devinfo.irq);
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	//s390irq_spin_unlock(tape->devinfo.irq);
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_rbi_init_done (tape_info_t * tape)
+{
+	__u8 *data;
+	int i;
+	tapestate_set (tape, TS_FAILED);
+	data = tape->kernbuf;
+	tape->rc = data[3];
+	tape->rc += 256 * data[2];
+	tape->rc += 65536 * (data[1] & 0x3F);
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"rbi done");
+        debug_text_event (tape_debug_area,6,"data:");
+	for (i=0;i<8;i++)
+	    debug_int_event (tape_debug_area,6,data[i]);
+#endif
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_rfo_init_error (tape_info_t * tape)
+{
+	if (((tape->devstat.ii.sense.data[0] == 0x08) ||	// sense.data[0]=08 -> first time
+	      (tape->devstat.ii.sense.data[0] == 0x10) ||	// an alternate one...
+	      (tape->devstat.ii.sense.data[0] == 0x12)) &&	// sense.data[1]=12 -> repeated message
+	     (tape->devstat.ii.sense.data[1] == 0x40)) {
+		// end of recorded area!
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"rfo fail");
+        debug_text_exception (tape_debug_area,3,"eoRecArea");
+#endif	/* TAPE_DEBUG */
+		tape->rc = 0;
+		tapestate_set (tape, TS_FAILED);
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+	} else {
+		switch (tape->devstat.ii.sense.data[3]) {
+		case 0x48:
+#ifdef TAPE_DEBUG
+		        debug_text_event (tape_debug_area,3,"rfo fail");
+                        debug_text_exception (tape_debug_area,3,"recov x48");
+#endif	/* TAPE_DEBUG */
+			//s390irq_spin_lock(tape->devinfo.irq);
+			do_IO (tape->devinfo.irq, tape->cqr->cpaddr, (unsigned long) (tape->cqr), 0x00, tape->cqr->options);
+			//s390irq_spin_unlock(tape->devinfo.irq);
+			break;
+		case 0x2c:
+			PRINT_ERR ("TAPE: Permanent Unit Check. Please check your hardware!");
+#ifdef TAPE_DEBUG
+			debug_text_event (tape_debug_area,3,"rfo fail");
+			debug_text_exception (tape_debug_area,3,"Perm UCK");
+#endif
+			tape->rc = -EIO;
+			tapestate_set (tape, TS_FAILED);
+			tape->wanna_wakeup=1;
+			wake_up_interruptible (&tape->wq);
+			break;
+		default:
+			tape34xx_unexpect_uchk_handler (tape);
+		}
+	}
+}
+
+void
+tape34xx_rew_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"rew done");
+#endif
+	//BH: use irqsave
+	//s390irq_spin_lock(tape->devinfo.irq);
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	//s390irq_spin_unlock(tape->devinfo.irq);
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_rew_release_init_error (tape_info_t * tape)
+{
+	if ((tape->devstat.ii.sense.data[0] == 0x40) &&
+	    (tape->devstat.ii.sense.data[1] == 0x40) &&
+	    (tape->devstat.ii.sense.data[3] == 0x43)) {
+		// no tape in the drive
+		PRINT_INFO ("Drive %d not ready. No volume loaded.\n", tape->rew_minor / 2);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,3,"rewR fail");
+		debug_text_exception (tape_debug_area,3,"no medium");
+#endif
+		tapestate_set (tape, TS_FAILED);
+		tape->rc = -ENOMEDIUM;
+		tape->wanna_wakeup=1;
+		wake_up (&tape->wq);
+	} else {
+		PRINT_ERR ("TAPE34XX: An unexpected Unit Check occured.\n");
+		PRINT_ERR ("TAPE34XX: Please send the following 20 lines of output to cotte@de.ibm.com\n");
+		PRINT_ERR ("TAPE34XX: Current state is: %s",
+			   (((tapestate_get (tape) < TS_SIZE) && (tapestate_get (tape) >= 0)) ?
+		  state_verbose[tapestate_get (tape)] : "->UNKNOWN STATE<-"));
+		tapestate_set (tape, TS_FAILED);
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,3,"rewR unexp");
+	        debug_text_event (tape_debug_area,3,"state:");
+	        debug_text_event (tape_debug_area,3,((tapestate_get (tape) < TS_SIZE) && 
+						     (tapestate_get (tape) >= 0)) ?
+				  state_verbose[tapestate_get (tape)] : 
+				  "TS UNKNOWN");
+#endif /* TAPE_DEBUG */
+		tape_dump_sense (&tape->devstat);
+		tape->rc = -EIO;
+		tape->wanna_wakeup=1;
+		wake_up (&tape->wq);
+	}
+}
+
+void
+tape34xx_rew_release_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"rewR done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	//s390irq_spin_unlock(tape->devinfo.irq);
+	tape->wanna_wakeup=1;
+	wake_up (&tape->wq);
+}
+
+void
+tape34xx_rew_init_error (tape_info_t * tape)
+{
+	tape34xx_unexpect_uchk_handler (tape);
+}
+
+void
+tape34xx_run_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"rew done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_run_init_error (tape_info_t * tape)
+{
+
+	switch (tape->devstat.ii.sense.data[3]) {
+	case 0x52:
+	        // This error is fine for rewind and unload
+	        // It reports that no volume is loaded... 
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"run done");
+#endif	/* TAPE_DEBUG */
+		tapestate_set (tape, TS_DONE);
+		tape->rc = 0;
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+		break;
+	default:
+		tape34xx_unexpect_uchk_handler (tape);
+	}
+}
+
+void
+tape34xx_wri_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"wri done");
+#endif
+	//BH: use irqsave
+	//s390irq_spin_lock(tape->devinfo.irq);
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	//s390irq_spin_unlock(tape->devinfo.irq);
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_wri_init_error (tape_info_t * tape)
+{
+    if ((tape->devstat.ii.sense.data[0]==0x80)&&(tape->devstat.ii.sense.data[1]==0x4a)) {
+	// tape is write protected
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"wri fail");
+        debug_text_exception (tape_debug_area,3,"writProte");
+#endif	/* TAPE_DEBUG */
+	tape->rc = -EACCES;
+	tapestate_set (tape, TS_FAILED);
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+    } else {
+	switch (tape->devstat.ii.sense.data[3]) {
+	case 0x48:
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,3,"wri fail");
+		debug_text_exception (tape_debug_area,3,"recov x48");
+#endif	/* TAPE_DEBUG */
+		//s390irq_spin_lock(tape->devinfo.irq);
+		do_IO (tape->devinfo.irq, tape->cqr->cpaddr, (unsigned long) (tape->cqr), 0x00, tape->cqr->options);
+		//s390irq_spin_unlock(tape->devinfo.irq);
+		break;
+	case 0x2c:
+		PRINT_ERR ("TAPE: Permanent Unit Check. Please check your hardware!\n");
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,3,"wri fail");
+		debug_text_exception (tape_debug_area,3,"Perm UCK");
+#endif
+		tape->rc = -EIO;
+		tapestate_set (tape, TS_FAILED);
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+		break;
+	case 0x38:		//end of tape
+#ifdef TAPE_DEBUG
+		PRINT_WARN ("TAPE: End of Tape reached.\n");
+		debug_text_event (tape_debug_area,3,"wri fail");
+		debug_text_exception (tape_debug_area,3,"EOT!");
+#endif
+		tape->rc = tape->devstat.rescnt;
+		tapestate_set (tape, TS_FAILED);
+		tape->wanna_wakeup=1;
+		wake_up_interruptible (&tape->wq);
+		break;
+	default:
+		tape34xx_unexpect_uchk_handler (tape);
+	}
+    }
+}
+
+void
+tape34xx_wtm_init_done (tape_info_t * tape)
+{
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"wtm done");
+#endif
+	tapestate_set (tape, TS_DONE);
+	tape->rc = 0;
+	tape->wanna_wakeup=1;
+	wake_up_interruptible (&tape->wq);
+}
+
+void
+tape34xx_wtm_init_error (tape_info_t * tape)
+{
+        tape34xx_unexpect_uchk_handler (tape);
+    
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tape34xx.h linux/drivers/s390/char/tape34xx.h
--- v2.4.1/linux/drivers/s390/char/tape34xx.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tape34xx.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,162 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tape34xx.h
+ *    common tape device discipline for 34xx tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#ifndef _TAPE34XX_H
+
+#define _TAPE34XX_H
+
+/*
+ * The CCW commands for the Tape type of command.
+ */
+
+#define         INVALID_00              0x00    /* Invalid cmd      */
+#define         BACKSPACEBLOCK          0x27    /* Back Space block */
+#define         BACKSPACEFILE           0x2f    /* Back Space file */
+#define         DATA_SEC_ERASE          0x97    /* Data security erase */
+#define         ERASE_GAP               0x17    /* Erase Gap */
+#define         FORSPACEBLOCK           0x37    /* Forward space block */
+#define         FORSPACEFILE            0x3F    /* Forward Space file */
+#define         FORCE_STREAM_CNT        0xEB    /* Forced streaming count #   */
+#define         NOP                     0x03    /* No operation  */
+#define         READ_FORWARD            0x02    /* Read forward */
+#define         REWIND                  0x07    /* Rewind */
+#define         REWIND_UNLOAD           0x0F    /* Rewind and Unload */
+#define         SENSE                   0x04    /* Sense */
+#define         NEW_MODE_SET            0xEB    /* Guess it is Mode set */
+#define         WRITE_CMD               0x01    /* Write */
+#define         WRITETAPEMARK           0x1F    /* Write Tape Mark */
+
+#define         ASSIGN                  0xB7    /* 3420 REJECT,3480 OK  */
+#define         CONTROL_ACCESS          0xE3    /* Set high speed */
+#define         DIAG_MODE_SET           0x0B    /* 3420 NOP, 3480 REJECT*/
+#define         LOAD_DISPLAY            0x9F    /* 3420 REJECT,3480 OK  */
+#define         LOCATE                  0x4F    /* 3420 REJ, 3480 NOP   */
+#define         LOOP_WRITE_TO_READ      0x8B    /* 3480 REJECT        */
+#define         MODE_SET_DB             0xDB    /* 3420 REJECT,3480 OK  */
+#define         MODE_SET_C3             0xC3    /* for 3420                */
+#define         MODE_SET_CB             0xCB    /* for 3420                */
+#define         MODE_SET_D3             0xD3    /* for 3420                */
+#define         READ_BACKWARD           0x0C    /*                      */
+#define         READ_BLOCK_ID           0x22    /* 3420 REJECT,3480 OK  */
+#define         READ_BUFFER             0x12    /* 3420 REJECT,3480 OK  */
+#define         READ_BUFF_LOG           0x24    /* 3420 REJECT,3480 OK  */
+#define         RELEASE                 0xD4    /* 3420 NOP, 3480 REJECT*/
+#define         REQ_TRK_IN_ERROR        0x1B    /* 3420 NOP, 3480 REJECT*/
+#define         RESERVE                 0xF4    /* 3420 NOP, 3480 REJECT*/
+#define         SENSE_GROUP_ID          0x34    /* 3420 REJECT,3480 OK  */
+#define         SENSE_ID                0xE4    /* 3420 REJECT,3480 OK */
+#define         READ_DEV_CHAR           0x64    /* Read device characteristics */
+#define         SET_DIAGNOSE            0x4B    /* 3420 NOP, 3480 REJECT*/
+#define         SET_GROUP_ID            0xAF    /* 3420 REJECT,3480 OK  */
+#define         SET_TAPE_WRITE_IMMED    0xC3    /* for 3480                */
+#define         SUSPEND                 0x5B    /* 3420 REJ, 3480 NOP   */
+#define         SYNC                    0x43    /* Synchronize (flush buffer) */
+#define         UNASSIGN                0xC7    /* 3420 REJECT,3480 OK  */
+#define         PERF_SUBSYS_FUNC        0x77    /* 3490 CMD */
+#define         READ_CONFIG_DATA        0xFA    /* 3490 CMD */
+#define         READ_MESSAGE_ID         0x4E    /* 3490 CMD */
+#define         READ_SUBSYS_DATA        0x3E    /* 3490 CMD */
+#define         SET_INTERFACE_ID        0x73    /* 3490 CMD */
+
+#ifndef MIN
+#define MIN(a,b)                ( (a) < (b) ? (a) : (b) )
+#endif
+
+
+#define BLOCKSIZE               4096            /* size of the tape rcds */
+
+#define COMMAND_CHAIN    CCW_FLAG_CC      /* redefine from irq.h */
+#define CHANNEL_END      DEV_STAT_CHN_END /* redefine from irq.h */
+#define DEVICE_END       DEV_STAT_DEV_END /* redefine from irq.h */
+#define UNIT_CHECK       DEV_STAT_UNIT_CHECK  /* redefine from irq.h */
+#define UNIT_EXCEPTION   DEV_STAT_UNIT_EXCEP  /* redefine from irq.h */
+#define CONTROL_UNIT_END DEV_STAT_CU_END      /* redefine from irq.h */
+#define INCORR_LEN       SCHN_STAT_INCORR_LEN /* redefine from irq.h */
+
+typedef struct _tape34xx_disc_data_t {
+    __u8 modeset_byte;
+} tape34xx_disc_data_t  __attribute__ ((packed, aligned(8)));
+
+/* discipline functions */
+int tape34xx_ioctl_overload (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);
+ccw_req_t * tape34xx_write_block (const char *data, size_t count, tape_info_t * tape);
+void tape34xx_free_write_block (ccw_req_t * cqr, tape_info_t * tape);
+ccw_req_t * tape34xx_read_block (const char *data, size_t count, tape_info_t * tape);
+void  tape34xx_free_read_block (ccw_req_t * cqr, tape_info_t * tape);
+void  tape34xx_clear_read_block (ccw_req_t * cqr, tape_info_t * tape);
+ccw_req_t * tape34xx_mtfsf (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtbsf (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtfsr (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtbsr (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtweof (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtrew (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtoffl (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtnop (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtbsfm (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtfsfm (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mteom (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mterase (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtsetdensity (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtseek (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mttell (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtsetdrvbuffer (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtlock (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtunlock (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtload (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtunload (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtcompression (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtsetpart (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtmkpart (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtiocget (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_mtiocpos (tape_info_t * tape, int count);
+ccw_req_t * tape34xx_bread (struct request *req, tape_info_t* tape,int tapeblock_major);
+ccw_req_t * tape34xx_bwrite (struct request *req, tape_info_t* tape,int tapeblock_major);
+void tape34xx_free_bread (ccw_req_t*,struct _tape_info_t*);
+void tape34xx_free_bwrite (ccw_req_t*,struct _tape_info_t*);
+
+/* Event handlers */
+void tape34xx_default_handler (tape_info_t * tape);
+void tape34xx_unexpect_uchk_handler (tape_info_t * tape);
+void tape34xx_unused_done(tape_info_t* tape);
+void tape34xx_unused_error(tape_info_t* tape);
+void tape34xx_idle_done(tape_info_t* tape);
+void tape34xx_idle_error(tape_info_t* tape);
+void tape34xx_block_done(tape_info_t* tape);
+void tape34xx_block_error(tape_info_t* tape);
+void tape34xx_bsf_init_done(tape_info_t* tape);
+void tape34xx_dse_init_done(tape_info_t* tape);
+void tape34xx_fsf_init_done(tape_info_t* tape);
+void tape34xx_fsf_init_error(tape_info_t* tape);
+void tape34xx_bsb_init_done(tape_info_t* tape);
+void tape34xx_fsb_init_done(tape_info_t* tape);
+void tape34xx_lbl_init_done(tape_info_t* tape);
+void tape34xx_lbl_init_error(tape_info_t* tape);
+void tape34xx_nop_init_done(tape_info_t* tape);
+void tape34xx_rfo_init_done(tape_info_t* tape);
+void tape34xx_rfo_init_error(tape_info_t* tape);
+void tape34xx_rbi_init_done(tape_info_t* tape);
+void tape34xx_rew_init_done(tape_info_t* tape);
+void tape34xx_rew_init_error(tape_info_t* tape);
+void tape34xx_rew_release_init_done(tape_info_t* tape);
+void tape34xx_rew_release_init_error(tape_info_t* tape);
+void tape34xx_run_init_done(tape_info_t* tape);
+void tape34xx_run_init_error(tape_info_t* tape);
+void tape34xx_wri_init_done(tape_info_t* tape);
+void tape34xx_wri_init_error(tape_info_t* tape);
+void tape34xx_wtm_init_done(tape_info_t* tape);
+void tape34xx_wtm_init_error(tape_info_t* tape);
+
+extern void schedule_tapeblock_exec_IO (tape_info_t *tape);
+#endif // _TAPE34XX_H
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tapeblock.c linux/drivers/s390/char/tapeblock.c
--- v2.4.1/linux/drivers/s390/char/tapeblock.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tapeblock.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,534 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tapeblock.c
+ *    block device frontend for tape device driver
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#include "tapedefs.h"
+#include <linux/blkdev.h>
+#include <linux/blk.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <asm/ccwcache.h>	/* CCW allocations      */
+#include <asm/debug.h>
+#include <asm/s390dyn.h>
+#include <linux/compatmac.h>
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+#include "tape.h"
+#include "tapeblock.h"
+
+#define PRINTK_HEADER "TBLOCK:"
+
+/*
+ * file operation structure for tape devices
+ */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+static struct block_device_operations tapeblock_fops = {
+#else
+static struct file_operations tapeblock_fops = {
+#endif
+    open    : tapeblock_open,      /* open */
+    release : tapeblock_release,   /* release */
+        };
+
+int    tapeblock_major = 0;
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+static void tape_request_fn (request_queue_t * queue);
+#else
+static void tape_request_fn (void);
+#endif
+
+static request_queue_t* tapeblock_getqueue (kdev_t kdev);
+
+
+void 
+tapeblock_setup(tape_info_t* tape) {
+    blk_size[tapeblock_major][tape->blk_minor]=0; // this will be detected
+    blksize_size[tapeblock_major][tape->blk_minor]=2048; // blocks are 2k by default.
+    hardsect_size[tapeblock_major][tape->blk_minor]=512;
+    blk_init_queue (&tape->request_queue, tape_request_fn); 
+    blk_queue_headactive (&tape->request_queue, 0); 
+}
+
+void
+tapeblock_init(void) {
+    int result;
+    tape_frontend_t* blkfront,*temp;
+    tape_info_t* tape;
+
+    tape_init();
+    /* Register the tape major number to the kernel */
+    result = register_blkdev(tapeblock_major, "tBLK", &tapeblock_fops);
+    if (result < 0) {
+        PRINT_WARN(KERN_ERR "tape: can't get major %d for block device\n", tapeblock_major);
+        panic ("cannot get major number for tape block device");
+    }
+    if (tapeblock_major == 0) tapeblock_major = result;   /* accept dynamic major number*/
+    INIT_BLK_DEV(tapeblock_major,tape_request_fn,tapeblock_getqueue,NULL);
+    read_ahead[tapeblock_major]=TAPEBLOCK_READAHEAD;
+    PRINT_WARN(KERN_ERR " tape gets major %d for block device\n", result);
+    blk_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);
+    memset(blk_size[tapeblock_major],0,256*sizeof(int));
+    blksize_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);
+    memset(blksize_size[tapeblock_major],0,256*sizeof(int));
+    hardsect_size[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);
+    memset(hardsect_size[tapeblock_major],0,256*sizeof(int));
+    max_sectors[tapeblock_major] = (int*) kmalloc (256*sizeof(int),GFP_ATOMIC);
+    memset(max_sectors[tapeblock_major],0,256*sizeof(int));
+    blkfront = kmalloc(sizeof(tape_frontend_t),GFP_KERNEL);
+    if (blkfront==NULL) panic ("no mem for tape block device structure");
+    blkfront->device_setup=tapeblock_setup;
+    blkfront->next=NULL;
+    if (first_frontend==NULL) {
+	first_frontend=blkfront;
+    } else {
+	temp=first_frontend;
+	while (temp->next!=NULL)
+	temp=temp->next;
+	temp->next=blkfront;
+    }
+    tape=first_tape_info;
+    while (tape!=NULL) {
+	tapeblock_setup(tape);
+	tape=tape->next;
+    }
+}
+
+
+void 
+tapeblock_uninit(void) {
+    unregister_blkdev(tapeblock_major, "tBLK");
+}
+
+static int
+tapeblock_open(struct inode *inode, struct file *filp) {
+    tape_info_t *ti;
+    kdev_t dev;
+    int rc;
+    long lockflags;
+
+    inode = filp->f_dentry->d_inode;
+    ti = first_tape_info;
+    while ((ti != NULL) && (ti->blk_minor != MINOR (inode->i_rdev)))
+		ti = (tape_info_t *) ti->next;
+	if (ti == NULL)
+		return -ENODEV;
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"b:open:");
+	debug_int_event (tape_debug_area,6,ti->blk_minor);
+#endif
+	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+	if (tapestate_get (ti) != TS_UNUSED) {
+		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,6,"b:dbusy");
+#endif
+		return -EBUSY;
+	}
+	tapestate_set (ti, TS_IDLE);
+        ti->position=-1;
+        
+	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+    rc=tapeblock_mediumdetect(ti);
+        if (rc) return rc; // in case of errors, we don't have a size of the medium
+	dev = MKDEV (tapeblock_major, MINOR (inode->i_rdev));	/* Get the device */
+	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+	ti->blk_filp = filp;
+	filp->private_data = ti;	/* save the dev.info for later reference */
+        ti->cqr=NULL;
+	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+    
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif				/* MODULE */
+	return 0;
+}
+
+static int
+tapeblock_release(struct inode *inode, struct file *filp) {
+	long lockflags;
+	tape_info_t *ti,*lastti;
+
+	inode = filp->f_dentry->d_inode;
+	ti = first_tape_info;
+	while ((ti != NULL) && (ti->blk_minor != MINOR (inode->i_rdev)))
+		ti = (tape_info_t *) ti->next;
+	if ((ti != NULL) && (tapestate_get (ti) == TS_NOT_OPER)) {
+	    if (ti==first_tape_info) {
+		first_tape_info=ti->next;
+	    } else {
+		lastti=first_tape_info;
+		while (lastti->next!=ti) lastti=lastti->next;
+		lastti->next=ti->next;
+	    }
+	    kfree(ti);    
+	    return 0;
+	}
+	if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) {
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"b:notidle!");
+#endif
+		return -ENXIO;	/* error in tape_release */
+	}
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"b:release:");
+	debug_int_event (tape_debug_area,6,ti->blk_minor);
+#endif
+	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+	tapestate_set (ti, TS_UNUSED);
+	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif				/* MODULE */
+	return 0;
+}
+
+static void
+tapeblock_end_request(tape_info_t* tape) {
+    struct buffer_head *bh;
+    int uptodate;
+    if ((tapestate_get(tape)!=TS_FAILED) &&
+	(tapestate_get(tape)!=TS_DONE))
+       BUG(); // A request has to be completed to end it
+    uptodate=(tapestate_get(tape)==TS_DONE); // is the buffer up to date?
+#ifdef TAPE_DEBUG
+    if (uptodate) {
+	debug_text_event (tape_debug_area,6,"b:done:");
+	debug_int_event (tape_debug_area,6,(long)tape->cqr);
+    } else {
+	debug_text_event (tape_debug_area,3,"b:failed:");
+	debug_int_event (tape_debug_area,3,(long)tape->cqr);
+    }
+#endif
+    // now inform ll_rw_block about a request status
+    while ((bh = tape->current_request->bh) != NULL) {
+	tape->current_request->bh = bh->b_reqnext;
+	bh->b_reqnext = NULL;
+	bh->b_end_io (bh, uptodate);
+    }
+    if (!end_that_request_first (tape->current_request, uptodate, "tBLK")) {
+#ifndef DEVICE_NO_RANDOM
+	add_blkdev_randomness (MAJOR (tape->current_request->rq_dev));
+#endif
+	end_that_request_last (tape->current_request);
+    }
+    tape->discipline->free_bread(tape->cqr,tape);
+    tape->cqr=NULL;
+    tape->current_request=NULL;
+    tapestate_set(tape,TS_IDLE);
+    return;
+}
+
+static void
+tapeblock_exec_IO (tape_info_t* tape) {
+    int rc;
+    struct request* req;
+    if (tape->cqr) { // process done/failed request
+	while ((tapestate_get(tape)==TS_FAILED) &&
+	    tape->blk_retries>0) {
+	    tape->blk_retries--;
+	    tape->position=-1;
+	    tapestate_set(tape,TS_BLOCK_INIT);
+#ifdef TAPE_DEBUG
+	    debug_text_event (tape_debug_area,3,"b:retryreq:");
+	    debug_int_event (tape_debug_area,3,(long)tape->cqr);
+#endif
+	    rc = do_IO (tape->devinfo.irq, tape->cqr->cpaddr, (unsigned long) tape->cqr, 
+			0x00, tape->cqr->options);
+	    if (rc) {
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,3,"b:doIOfail:");
+		debug_int_event (tape_debug_area,3,(long)tape->cqr);
+#endif 
+		continue; // one retry lost 'cause doIO failed
+	    }
+	    return;
+	}
+	tapeblock_end_request (tape); // check state, inform user, free mem, dev=idl
+    }
+    if (tape->cqr!=NULL) BUG(); // tape should be idle now, request should be freed!
+    if (list_empty(&tape->request_queue.queue_head)) { // nothing more to do ;)
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"b:Qempty");
+#endif
+	tapestate_set(tape,TS_IDLE);
+	return;
+    }
+    // queue is not empty, fetch a request and start IO!
+    req=tape->current_request=tape_next_request(&tape->request_queue);
+    if (req==NULL) {
+	BUG(); // Yo. The queue was not reported empy, but no request found. This is _bad_.
+    }
+    if (req->cmd!=READ) { // we only support reading
+	tapestate_set(tape,TS_FAILED);
+	tapeblock_end_request (tape); // check state, inform user, free mem, dev=idl
+	tapestate_set(tape,TS_BLOCK_INIT);
+	schedule_tapeblock_exec_IO(tape);
+	return;
+    }
+    tape->cqr=tape->discipline->bread(req,tape,tapeblock_major); //build channel program from request
+    if (!tape->cqr) {
+	// ccw generation failed. we try again later.
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,3,"b:cqrNULL");
+#endif
+	schedule_tapeblock_exec_IO(tape);
+	tape->current_request=NULL;
+	return;
+    }
+    tape->blk_retries = TAPEBLOCK_RETRIES;
+    rc= do_IO (tape->devinfo.irq, tape->cqr->cpaddr, 
+	       (unsigned long) tape->cqr, 0x00, tape->cqr->options);
+    if (rc) {
+	// okay. ssch failed. we try later.
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,3,"b:doIOfail");
+#endif
+	tape->discipline->free_bread(tape->cqr,tape);
+	tape->cqr=NULL;
+	tape->current_request=NULL;
+	schedule_tapeblock_exec_IO(tape);
+	return;
+    }
+    // our request is in IO. we remove it from the queue and exit
+    tape_dequeue_request (&tape->request_queue,req);
+}
+
+static void 
+do_tape_request (request_queue_t * queue) {
+    tape_info_t* tape;
+    long lockflags;
+    for (tape=first_tape_info;
+	 ((tape!=NULL) && ((&tape->request_queue)!=queue));
+	 tape=tape->next);
+    if (tape==NULL) BUG();
+    s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+    if (tapestate_get(tape)!=TS_IDLE) {
+	s390irq_spin_unlock_irqrestore(tape->devinfo.irq,lockflags);
+	return;
+    }
+    if (tapestate_get(tape)!=TS_IDLE) BUG();
+    tapestate_set(tape,TS_BLOCK_INIT);
+    tapeblock_exec_IO(tape);
+    s390irq_spin_unlock_irqrestore(tape->devinfo.irq,lockflags);
+}
+
+static void
+run_tapeblock_exec_IO (tape_info_t* tape) {
+    long flags_390irq,flags_ior;
+    spin_lock_irqsave (&io_request_lock, flags_ior);
+    s390irq_spin_lock_irqsave(tape->devinfo.irq,flags_390irq);
+    atomic_set(&tape->bh_scheduled,0);
+    tapeblock_exec_IO(tape);
+    s390irq_spin_unlock_irqrestore(tape->devinfo.irq,flags_390irq);
+    spin_unlock_irqrestore (&io_request_lock, flags_ior);
+}
+
+void
+schedule_tapeblock_exec_IO (tape_info_t *tape)
+{
+	/* Protect against rescheduling, when already running */
+        if (atomic_compare_and_swap(0,1,&tape->bh_scheduled)) {
+                return;
+        }
+
+	INIT_LIST_HEAD(&tape->bh_tq.list);
+	tape->bh_tq.sync = 0;
+	tape->bh_tq.routine = (void *) (void *) run_tapeblock_exec_IO;
+	tape->bh_tq.data = tape;
+
+	queue_task (&tape->bh_tq, &tq_immediate);
+	mark_bh (IMMEDIATE_BH);
+	return;
+}
+
+/* wrappers around do_tape_request for different kernel versions */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+static void tape_request_fn (void) {
+    tape_info_t* tape=first_tape_info;
+    while (tape!=NULL) {
+	do_tape_request(&tape->request_queue);
+	tape=tape->next;
+    }
+}
+#else
+static void  tape_request_fn (request_queue_t* queue) {
+    do_tape_request(queue);
+}
+#endif
+
+static request_queue_t* tapeblock_getqueue (kdev_t kdev) {
+    tape_info_t* tape=first_tape_info;
+    while ((tape!=NULL) && (MINOR(kdev)!=tape->blk_minor)) 
+        tape=tape->next;
+    if (tape!=NULL) return &tape->request_queue;
+    return NULL;
+}
+
+static int tapeblock_mediumdetect(tape_info_t* tape) {
+    ccw_req_t* cqr;
+    int losize=1,hisize=1,rc;
+    long lockflags;
+#ifdef TAPE_DEBUG
+    debug_text_event (tape_debug_area,3,"b:medDet");
+#endif
+    while (1) { //is interruped by break
+	hisize=hisize << 1; // try twice the size tested before 
+	cqr=tape->discipline->mtseek (tape, hisize);
+	if (cqr == NULL) {
+#ifdef TAPE_DEBUG
+	    debug_text_event (tape_debug_area,6,"b:ccwg fail");
+#endif
+	    return -ENOSPC;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->cqr = cqr;
+	tape->wanna_wakeup=0;
+	rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	if (rc) return -EIO;
+	wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+	tape->cqr = NULL;
+	tape_free_request (cqr);
+	if (tape->kernbuf) {
+	    kfree (tape->kernbuf);
+	    tape->kernbuf=NULL;
+	}
+	if (signal_pending (current)) {
+		tapestate_set (tape, TS_IDLE);
+		return -ERESTARTSYS;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	if (tapestate_get (tape) == TS_FAILED) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		break;
+	}
+	if (tapestate_get (tape) != TS_DONE) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		return -EIO;
+	}
+	tapestate_set (tape, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	losize=hisize;
+    }
+    cqr = tape->discipline->mtrew (tape, 1);
+    if (cqr == NULL) {
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"b:ccwg fail");
+#endif
+	return -ENOSPC;
+    }
+    s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+    tape->cqr = cqr;
+    tape->wanna_wakeup=0;
+    rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+    s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+    wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+    tape->cqr = NULL;
+    tape_free_request (cqr);
+    if (signal_pending (current)) {
+	tapestate_set (tape, TS_IDLE);
+	return -ERESTARTSYS;
+    }
+    s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+    if (tapestate_get (tape) == TS_FAILED) {
+	tapestate_set (tape, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	return -EIO;
+    }
+    if (tapestate_get (tape) != TS_DONE) {
+	tapestate_set (tape, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	return -EIO;
+    }
+    tapestate_set (tape, TS_IDLE);
+    s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+    while (losize!=hisize) {
+	cqr=tape->discipline->mtseek (tape, (hisize+losize)/2+1);
+	if (cqr == NULL) {
+#ifdef TAPE_DEBUG
+	    debug_text_event (tape_debug_area,6,"b:ccwg fail");
+#endif
+	    return -ENOSPC;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->cqr = cqr;
+	tape->wanna_wakeup=0;
+	rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	if (rc) return -EIO;
+	wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+	tape->cqr = NULL;
+	tape_free_request (cqr);
+	if (tape->kernbuf) {
+	    kfree (tape->kernbuf);
+	    tape->kernbuf=NULL;
+	}
+	if (signal_pending (current)) {
+		tapestate_set (tape, TS_IDLE);
+		return -ERESTARTSYS;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	if (tapestate_get (tape) == TS_FAILED) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		hisize=(hisize+losize)/2;
+		cqr = tape->discipline->mtrew (tape, 1);
+		if (cqr == NULL) {
+#ifdef TAPE_DEBUG
+		    debug_text_event (tape_debug_area,6,"b:ccwg fail");
+#endif
+		    return -ENOSPC;
+		}
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tape->cqr = cqr;
+		tape->wanna_wakeup=0;
+		rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+		tape->cqr = NULL;
+		tape_free_request (cqr);
+		if (signal_pending (current)) {
+		    tapestate_set (tape, TS_IDLE);
+		    return -ERESTARTSYS;
+		}
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		if (tapestate_get (tape) == TS_FAILED) {
+		    tapestate_set (tape, TS_IDLE);
+		    s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		    return -EIO;
+		}
+		if (tapestate_get (tape) != TS_DONE) {
+		    tapestate_set (tape, TS_IDLE);
+		    s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		    return -EIO;
+		}
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		continue;
+	}
+	if (tapestate_get (tape) != TS_DONE) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		return -EIO;
+	}
+	tapestate_set (tape, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	losize=(hisize+losize)/2+1;
+    }
+    blk_size[tapeblock_major][tape->blk_minor]=(losize)*(blksize_size[tapeblock_major][tape->blk_minor]/1024);
+    return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tapeblock.h linux/drivers/s390/char/tapeblock.h
--- v2.4.1/linux/drivers/s390/char/tapeblock.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tapeblock.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,26 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tapechar.h
+ *    character device frontend for tape device driver
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#ifndef TAPEBLOCK_H
+#define TAPEBLOCK_H
+#define PARTN_BITS 0
+
+#define TAPEBLOCK_READAHEAD 30
+#define TAPEBLOCK_MAJOR 0
+static int tapeblock_open(struct inode *, struct file *);
+static int tapeblock_release(struct inode *, struct file *);
+void tapeblock_setup(tape_info_t* tape);
+void schedule_tapeblock_exec_IO (tape_info_t *tape);
+static int tapeblock_mediumdetect(tape_info_t* tape);
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tapechar.c linux/drivers/s390/char/tapechar.c
--- v2.4.1/linux/drivers/s390/char/tapechar.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tapechar.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,697 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tapechar.c
+ *    character device frontend for tape device driver
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#include "tapedefs.h"
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <asm/ccwcache.h>	/* CCW allocations      */
+#include <asm/s390dyn.h>
+#include <asm/debug.h>
+#include <linux/mtio.h>
+#include <asm/uaccess.h>
+#include <linux/compatmac.h>
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+#include "tape.h"
+#include "tapechar.h"
+
+#define PRINTK_HEADER "TCHAR:"
+
+/*
+ * file operation structure for tape devices
+ */
+static struct file_operations tape_fops =
+{
+    //    owner   : THIS_MODULE,
+	llseek:NULL,		/* lseek - default */
+	read:tape_read,		/* read  */
+	write:tape_write,	/* write */
+	readdir:NULL,		/* readdir - bad */
+	poll:NULL,		/* poll */
+	ioctl:tape_ioctl,	/* ioctl */
+	mmap:NULL,		/* mmap */
+	open:tape_open,		/* open */
+	flush:NULL,		/* flush */
+	release:tape_release,	/* release */
+	fsync:NULL,		/* fsync */
+	fasync:NULL,		/* fasync */
+	lock:NULL,
+};
+
+int tape_major = TAPE_MAJOR;
+
+void
+tapechar_setup (tape_info_t * tape)
+{
+    // nothing to do
+}
+
+void
+tapechar_init (void)
+{
+	int result;
+	tape_frontend_t *charfront,*temp;
+	tape_info_t* tape;
+
+	tape_init();
+
+	/* Register the tape major number to the kernel */
+	result = register_chrdev (tape_major, "tape", &tape_fops);
+
+	if (result < 0) {
+		PRINT_WARN (KERN_ERR "tape: can't get major %d\n", tape_major);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,3,"c:initfail");
+		debug_text_event (tape_debug_area,3,"regchrfail");
+#endif /* TAPE_DEBUG */
+		panic ("no major number available for tape char device");
+	}
+	if (tape_major == 0)
+		tape_major = result;	/* accept dynamic major number */
+	PRINT_WARN (KERN_ERR " tape gets major %d for character device\n", result);
+	charfront = kmalloc (sizeof (tape_frontend_t), GFP_KERNEL);
+	if (charfront == NULL) {
+#ifdef TAPE_DEBUG
+                debug_text_event (tape_debug_area,3,"c:initfail");
+		debug_text_event (tape_debug_area,3,"no mem");
+#endif /* TAPE_DEBUG */
+		panic ("no major number available for tape char device");		
+	}
+	charfront->device_setup = tapechar_setup;
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,3,"c:init ok");
+#endif /* TAPE_DEBUG */
+	charfront->next=NULL;
+	if (first_frontend==NULL) {
+	    first_frontend=charfront;
+	} else {
+	    temp=first_frontend;
+	    while (temp->next!=NULL)
+		temp=temp->next;
+	    temp->next=charfront;
+	}
+	tape=first_tape_info;
+	while (tape!=NULL) {
+	    tapechar_setup(tape);
+	    tape=tape->next;
+	}
+}
+
+void
+tapechar_uninit (void)
+{
+	unregister_chrdev (tape_major, "tape");
+}
+
+/*
+ * Tape device read function
+ */
+static ssize_t
+tape_read (struct file *filp, char *data, size_t count, loff_t * ppos)
+{
+	long lockflags;
+	tape_info_t *tape;
+	size_t block_size;
+	ccw_req_t *cqr;
+	int rc;
+#ifdef TAPE_DEBUG
+        debug_text_event (tape_debug_area,6,"c:read");
+#endif /* TAPE_DEBUG */
+	tape = first_tape_info;
+	while ((tape != NULL) && (tape->rew_filp != filp) && (tape->nor_filp != filp))
+		tape = (tape_info_t *) tape->next;
+	if (tape == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:nodev");
+#endif /* TAPE_DEBUG */
+		return -ENODEV;
+	}
+	if (ppos != &filp->f_pos) {
+		/* "A request was outside the capabilities of the device." */
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:ppos wrong");
+#endif /* TAPE_DEBUG */
+		return -EOVERFLOW;	/* errno=75 Value too large for def. data type */
+	}
+	if (tape->block_size == 0) {
+		block_size = count;
+	} else {
+		block_size = tape->block_size;
+	}
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:nbytes:");
+	debug_int_event (tape_debug_area,6,block_size);
+#endif
+	cqr = tape->discipline->read_block (data, block_size, tape);
+	if (!cqr) {
+		return -ENOBUFS;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->cqr = cqr;
+	tape->wanna_wakeup=0;
+	rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+	if (rc) {
+	    tapestate_set(tape,TS_IDLE);
+	    kfree (cqr);
+	    s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	    return rc;
+	}
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+	tape->cqr = NULL;
+	tape->discipline->free_read_block (cqr, tape);
+	if (signal_pending (current)) {
+		tapestate_set (tape, TS_IDLE);
+		return -ERESTARTSYS;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	if (tapestate_get (tape) == TS_FAILED) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		return tape->rc;
+	}
+	if (tapestate_get (tape) != TS_DONE) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		return -EIO;
+	}
+	tapestate_set (tape, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:rbytes:");
+	debug_int_event (tape_debug_area,6,block_size - tape->devstat.rescnt);
+#endif	/* TAPE_DEBUG */
+	filp->f_pos += block_size - tape->devstat.rescnt;
+	return block_size - tape->devstat.rescnt;
+}
+
+/*
+ * Tape device write function
+ */
+static ssize_t
+tape_write (struct file *filp, const char *data, size_t count, loff_t * ppos)
+{
+	long lockflags;
+	tape_info_t *tape;
+	size_t block_size;
+	ccw_req_t *cqr;
+	int nblocks, i, rc;
+	size_t written = 0;
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:write");
+#endif
+	tape = first_tape_info;
+	while ((tape != NULL) && (tape->nor_filp != filp) && (tape->rew_filp != filp))
+		tape = (tape_info_t *) tape->next;
+	if (tape == NULL)
+		return -ENODEV;
+	if (ppos != &filp->f_pos) {
+		/* "A request was outside the capabilities of the device." */
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:ppos wrong");
+#endif
+		return -EOVERFLOW;	/* errno=75 Value too large for def. data type */
+	}
+	if ((tape->block_size != 0) && (count % tape->block_size != 0))
+		return -EIO;
+	if (tape->block_size == 0) {
+		block_size = count;
+		nblocks = 1;
+	} else {
+		block_size = tape->block_size;
+		nblocks = count / (tape->block_size);
+	}
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:nbytes:");
+		debug_int_event (tape_debug_area,6,block_size);
+	        debug_text_event (tape_debug_area,6,"c:nblocks:");
+	        debug_int_event (tape_debug_area,6,nblocks);
+#endif
+	for (i = 0; i < nblocks; i++) {
+		cqr = tape->discipline->write_block (data + i * block_size, block_size, tape);
+		if (!cqr) {
+			return -ENOBUFS;
+		}
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tape->cqr = cqr;
+		tape->wanna_wakeup=0;
+		rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+		tape->cqr = NULL;
+		tape->discipline->free_write_block (cqr, tape);
+		if (signal_pending (current)) {
+			tapestate_set (tape, TS_IDLE);
+			return -ERESTARTSYS;
+		}
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		if (tapestate_get (tape) == TS_FAILED) {
+			tapestate_set (tape, TS_IDLE);
+			s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+			return tape->rc;
+		}
+		if (tapestate_get (tape) != TS_DONE) {
+			tapestate_set (tape, TS_IDLE);
+			s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+			return -EIO;
+		}
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:wbytes:"); 
+		debug_int_event (tape_debug_area,6,block_size - tape->devstat.rescnt);
+#endif
+		filp->f_pos += block_size - tape->devstat.rescnt;
+		written += block_size - tape->devstat.rescnt;
+		if (tape->devstat.rescnt > 0)
+			return written;
+	}
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:wtotal:");
+	debug_int_event (tape_debug_area,6,written);
+#endif
+	return written;
+}
+
+static int
+tape_mtioctop (struct file *filp, short mt_op, int mt_count)
+{
+	tape_info_t *tape;
+	ccw_req_t *cqr = NULL;
+	int rc;
+	long lockflags;
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:mtio");
+	debug_text_event (tape_debug_area,6,"c:ioop:");
+	debug_int_event (tape_debug_area,6,mt_op); 
+	debug_text_event (tape_debug_area,6,"c:arg:");
+	debug_int_event (tape_debug_area,6,mt_count);
+#endif
+	tape = first_tape_info;
+	while ((tape != NULL) && (tape->rew_filp != filp) && (tape->nor_filp != filp))
+		tape = (tape_info_t *) tape->next;
+	if (tape == NULL)
+		return -ENODEV;
+	switch (mt_op) {
+	case MTREW:		// rewind
+
+		cqr = tape->discipline->mtrew (tape, mt_count);
+		break;
+	case MTOFFL:		// put drive offline
+
+		cqr = tape->discipline->mtoffl (tape, mt_count);
+		break;
+	case MTUNLOAD:		// unload the tape
+
+		cqr = tape->discipline->mtunload (tape, mt_count);
+		break;
+	case MTWEOF:		// write tapemark
+
+		cqr = tape->discipline->mtweof (tape, mt_count);
+		break;
+	case MTFSF:		// forward space file
+
+		cqr = tape->discipline->mtfsf (tape, mt_count);
+		break;
+	case MTBSF:		// backward space file
+
+		cqr = tape->discipline->mtbsf (tape, mt_count);
+		break;
+	case MTFSFM:		// forward space file, stop at BOT side
+
+		cqr = tape->discipline->mtfsfm (tape, mt_count);
+		break;
+	case MTBSFM:		// backward space file, stop at BOT side
+
+		cqr = tape->discipline->mtbsfm (tape, mt_count);
+		break;
+	case MTFSR:		// forward space file
+
+		cqr = tape->discipline->mtfsr (tape, mt_count);
+		break;
+	case MTBSR:		// backward space file
+
+		cqr = tape->discipline->mtbsr (tape, mt_count);
+		break;
+	case MTNOP:
+		cqr = tape->discipline->mtnop (tape, mt_count);
+		break;
+	case MTEOM:		// postion at the end of portion
+
+	case MTRETEN:		// retension the tape
+
+		cqr = tape->discipline->mteom (tape, mt_count);
+		break;
+	case MTERASE:
+		cqr = tape->discipline->mterase (tape, mt_count);
+		break;
+	case MTSETDENSITY:
+		cqr = tape->discipline->mtsetdensity (tape, mt_count);
+		break;
+	case MTSEEK:
+		cqr = tape->discipline->mtseek (tape, mt_count);
+		break;
+	case MTSETDRVBUFFER:
+		cqr = tape->discipline->mtsetdrvbuffer (tape, mt_count);
+		break;
+	case MTLOCK:
+		cqr = tape->discipline->mtsetdrvbuffer (tape, mt_count);
+		break;
+	case MTUNLOCK:
+		cqr = tape->discipline->mtsetdrvbuffer (tape, mt_count);
+		break;
+	case MTLOAD:
+		cqr = tape->discipline->mtload (tape, mt_count);
+		break;
+	case MTCOMPRESSION:
+		cqr = tape->discipline->mtcompression (tape, mt_count);
+		break;
+	case MTSETPART:
+		cqr = tape->discipline->mtsetpart (tape, mt_count);
+		break;
+	case MTMKPART:
+		cqr = tape->discipline->mtmkpart (tape, mt_count);
+		break;
+	case MTTELL:		// return number of block relative to current file
+
+		cqr = tape->discipline->mttell (tape, mt_count);
+		break;
+	case MTSETBLK:
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tape->block_size = mt_count;
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,6,"c:setblk:");
+	        debug_int_event (tape_debug_area,6,mt_count);
+#endif
+		return 0;
+	case MTRESET:
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tape->kernbuf = tape->userbuf = NULL;
+		tapestate_set (tape, TS_IDLE);
+		tape->block_size = 0;
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,6,"c:devreset:");
+		debug_int_event (tape_debug_area,6,tape->blk_minor);
+#endif
+		return 0;
+	default:
+#ifdef TAPE_DEBUG
+	    debug_text_event (tape_debug_area,6,"c:inv.mtio");
+#endif
+		return -EINVAL;
+	}
+	if (cqr == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:ccwg fail");
+#endif
+		return -ENOSPC;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	tape->cqr = cqr;
+	tape->wanna_wakeup=0;
+	rc = do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+	tape->cqr = NULL;
+	if (tape->kernbuf != NULL) {
+		kfree (tape->kernbuf);
+		tape->kernbuf = NULL;
+	}
+	tape_free_request (cqr);
+	if (signal_pending (current)) {
+		tapestate_set (tape, TS_IDLE);
+		return -ERESTARTSYS;
+	}
+	s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+	if (((mt_op == MTEOM) || (mt_op == MTRETEN)) && (tapestate_get (tape) == TS_FAILED))
+		tapestate_set (tape, TS_DONE);
+	if (tapestate_get (tape) == TS_FAILED) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		return tape->rc;
+	}
+	if (tapestate_get (tape) != TS_DONE) {
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		return -EIO;
+	}
+	tapestate_set (tape, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+	switch (mt_op) {
+	case MTRETEN:		//need to rewind the tape after moving to eom
+
+		return tape_mtioctop (filp, MTREW, 1);
+	case MTFSFM:		//need to skip back over the filemark
+
+		return tape_mtioctop (filp, MTBSFM, 1);
+	case MTBSF:		//need to skip forward over the filemark
+
+		return tape_mtioctop (filp, MTFSF, 1);
+	}
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:mtio done");
+#endif
+	return 0;
+}
+
+/*
+ * Tape device io controls.
+ */
+static int
+tape_ioctl (struct inode *inode, struct file *filp,
+	    unsigned int cmd, unsigned long arg)
+{
+	long lockflags;
+	tape_info_t *tape;
+	ccw_req_t *cqr;
+	struct mtop op;		/* structure for MTIOCTOP */
+	struct mtpos pos;	/* structure for MTIOCPOS */
+	struct mtget get;
+
+	int rc;
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:ioct");
+#endif
+	tape = first_tape_info;
+	while ((tape != NULL) &&
+	       (tape->rew_minor != MINOR (inode->i_rdev)) &&
+	       (tape->nor_minor != MINOR (inode->i_rdev)))
+		tape = (tape_info_t *) tape->next;
+	if (tape == NULL) {
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,6,"c:nodev");
+#endif
+		return -ENODEV;
+	}
+	// check for discipline ioctl overloading
+	if ((rc = tape->discipline->discipline_ioctl_overload (inode, filp, cmd, arg))
+	    != -EINVAL) {
+#ifdef TAPE_DEBUG
+	    debug_text_event (tape_debug_area,6,"c:ioverloa");
+#endif
+	    return rc;
+	}
+
+	switch (cmd) {
+	case MTIOCTOP:		/* tape op command */
+		if (copy_from_user (&op, (char *) arg, sizeof (struct mtop)))
+			 return -EFAULT;
+		return (tape_mtioctop (filp, op.mt_op, op.mt_count));
+	case MTIOCPOS:		/* query tape position */
+		cqr = tape->discipline->mttell (tape, 0);
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tape->cqr = cqr;
+		tape->wanna_wakeup=0;
+		do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+		pos.mt_blkno = tape->rc;
+		tape->cqr = NULL;
+		if (tape->kernbuf != NULL) {
+			kfree (tape->kernbuf);
+			tape->kernbuf = NULL;
+		}
+		tape_free_request (cqr);
+		if (signal_pending (current)) {
+			tapestate_set (tape, TS_IDLE);
+			return -ERESTARTSYS;
+		}
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		if (copy_to_user ((char *) arg, &pos, sizeof (struct mtpos)))
+			 return -EFAULT;
+		return 0;
+	case MTIOCGET:
+		get.mt_erreg = tape->rc;
+		cqr = tape->discipline->mttell (tape, 0);
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tape->cqr = cqr;
+		tape->wanna_wakeup=0;
+		do_IO (tape->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		wait_event_interruptible (tape->wq,tape->wanna_wakeup);
+		get.mt_blkno = tape->rc;
+		get.mt_fileno = 0;
+		get.mt_type = MT_ISUNKNOWN;
+		get.mt_resid = tape->devstat.rescnt;
+		get.mt_dsreg = tape->devstat.ii.sense.data[3];
+		get.mt_gstat = 0;
+		if (tape->devstat.ii.sense.data[1] & 0x08)
+			get.mt_gstat &= GMT_BOT (1);	// BOT
+
+		if (tape->devstat.ii.sense.data[1] & 0x02)
+			get.mt_gstat &= GMT_WR_PROT (1);	// write protected
+
+		if (tape->devstat.ii.sense.data[1] & 0x40)
+			get.mt_gstat &= GMT_ONLINE (1);		//drive online
+
+		tape->cqr = NULL;
+		if (tape->kernbuf != NULL) {
+			kfree (tape->kernbuf);
+			tape->kernbuf = NULL;
+		}
+		tape_free_request (cqr);
+		if (signal_pending (current)) {
+			tapestate_set (tape, TS_IDLE);
+			return -ERESTARTSYS;
+		}
+		s390irq_spin_lock_irqsave (tape->devinfo.irq, lockflags);
+		tapestate_set (tape, TS_IDLE);
+		s390irq_spin_unlock_irqrestore (tape->devinfo.irq, lockflags);
+		if (copy_to_user ((char *) arg, &get, sizeof (struct mtget)))
+			 return -EFAULT;
+		return 0;
+	default:
+#ifdef TAPE_DEBUG
+	        debug_text_event (tape_debug_area,3,"c:ioct inv");
+#endif	    
+		return -EINVAL;
+	}
+}
+
+/*
+ * Tape device open function.
+ */
+static int
+tape_open (struct inode *inode, struct file *filp)
+{
+	tape_info_t *ti;
+	kdev_t dev;
+	long lockflags;
+
+	inode = filp->f_dentry->d_inode;
+	ti = first_tape_info;
+	while ((ti != NULL) &&
+	       (ti->rew_minor != MINOR (inode->i_rdev)) &&
+	       (ti->nor_minor != MINOR (inode->i_rdev)))
+		ti = (tape_info_t *) ti->next;
+	if (ti == NULL)
+		return -ENODEV;
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:open:");
+	debug_int_event (tape_debug_area,6,ti->blk_minor);
+#endif
+	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+	if (tapestate_get (ti) != TS_UNUSED) {
+		s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+#ifdef TAPE_DEBUG
+		debug_text_event (tape_debug_area,6,"c:dbusy");
+#endif
+		return -EBUSY;
+	}
+	tapestate_set (ti, TS_IDLE);
+	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+
+	dev = MKDEV (tape_major, MINOR (inode->i_rdev));	/* Get the device */
+	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+	if (ti->rew_minor == MINOR (inode->i_rdev))
+		ti->rew_filp = filp;	/* save for later reference     */
+	else
+		ti->nor_filp = filp;
+	filp->private_data = ti;	/* save the dev.info for later reference */
+	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+
+#ifdef MODULE
+	MOD_INC_USE_COUNT;
+#endif				/* MODULE */
+	return 0;
+}
+
+/*
+ * Tape device release function.
+ */
+static int
+tape_release (struct inode *inode, struct file *filp)
+{
+	long lockflags;
+	tape_info_t *ti,*lastti;
+	ccw_req_t *cqr = NULL;
+	int rc;
+
+	inode = filp->f_dentry->d_inode;
+	ti = first_tape_info;
+	while ((ti != NULL) && (ti->rew_minor != MINOR (inode->i_rdev)) && (ti->nor_minor != MINOR (inode->i_rdev)))
+		ti = (tape_info_t *) ti->next;
+	if ((ti != NULL) && (tapestate_get (ti) == TS_NOT_OPER)) {
+	    if (ti==first_tape_info) {
+		first_tape_info=ti->next;
+	    } else {
+		lastti=first_tape_info;
+		while (lastti->next!=ti) lastti=lastti->next;
+		lastti->next=ti->next;
+	    }
+	    kfree(ti);    
+	    return 0;
+	}
+	if ((ti == NULL) || (tapestate_get (ti) != TS_IDLE)) {
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:notidle!");
+#endif
+		return -ENXIO;	/* error in tape_release */
+	}
+#ifdef TAPE_DEBUG
+	debug_text_event (tape_debug_area,6,"c:release:");
+	debug_int_event (tape_debug_area,6,ti->blk_minor);
+#endif
+	if (ti->rew_minor == MINOR (inode->i_rdev)) {
+		cqr = ti->discipline->mtrew (ti, 1);
+		if (cqr != NULL) {
+#ifdef TAPE_DEBUG
+		        debug_text_event (tape_debug_area,6,"c:rewrelea");
+#endif
+			s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+			tapestate_set (ti, TS_REW_RELEASE_INIT);
+			ti->cqr = cqr;
+			ti->wanna_wakeup=0;
+			rc = do_IO (ti->devinfo.irq, cqr->cpaddr, (unsigned long) cqr, 0x00, cqr->options);
+			s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+			wait_event (ti->wq,ti->wanna_wakeup);
+			ti->cqr = NULL;
+			tape_free_request (cqr);
+		}
+	}
+	s390irq_spin_lock_irqsave (ti->devinfo.irq, lockflags);
+	tapestate_set (ti, TS_UNUSED);
+	s390irq_spin_unlock_irqrestore (ti->devinfo.irq, lockflags);
+#ifdef MODULE
+	MOD_DEC_USE_COUNT;
+#endif				/* MODULE */
+	return 0;
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tapechar.h linux/drivers/s390/char/tapechar.h
--- v2.4.1/linux/drivers/s390/char/tapechar.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tapechar.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,27 @@
+
+/***************************************************************************
+ *
+ *  drivers/s390/char/tapechar.h
+ *    character device frontend for tape device driver
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress...:-)
+ ****************************************************************************
+ */
+
+#ifndef TAPECHAR_H
+#define TAPECHAR_H
+#define  TAPE_MAJOR                    0        /* get dynamic major since no major officialy defined for tape */
+/*
+ * Prototypes for tape_fops
+ */
+static ssize_t tape_read(struct file *, char *, size_t, loff_t *);
+static ssize_t tape_write(struct file *, const char *, size_t, loff_t *);
+static int tape_ioctl(struct inode *,struct file *,unsigned int,unsigned long);
+static int tape_open (struct inode *,struct file *);
+static int tape_release (struct inode *,struct file *);
+#endif /* TAPECHAR_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/char/tapedefs.h linux/drivers/s390/char/tapedefs.h
--- v2.4.1/linux/drivers/s390/char/tapedefs.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/char/tapedefs.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,60 @@
+/***********************************************************************
+ *  drivers/s390/char/tapedefs.h
+ *    tape device driver for S/390 tapes.
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Tuan Ngo-Anh <ngoanh@de.ibm.com>
+ *               Carsten Otte <cotte@de.ibm.com>
+ *
+ *  UNDER CONSTRUCTION: Work in progress... :-)
+ ***********************************************************************
+ */
+
+#define TAPE_DEBUG
+#define CONFIG_S390_TAPE_DYNAMIC //use dyn. dev. attach/detach
+#define TAPEBLOCK_RETRIES 20
+
+
+/* Kernel Version Compatibility section */
+#include <linux/version.h>
+#include <linux/blkdev.h>
+#include <linux/blk.h>
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+        blk_dev[d_major].queue = d_queue_fn; \
+} while(0)
+static inline struct request * 
+tape_next_request( request_queue_t *queue ) 
+{
+        return blkdev_entry_next_request(&queue->queue_head);
+}
+static inline void 
+tape_dequeue_request( request_queue_t * q, struct request *req )
+{
+        blkdev_dequeue_request (req);
+}
+#else 
+typedef struct request *request_queue_t;
+#define init_waitqueue_head(x) do { *x = NULL; } while(0)
+#define blk_init_queue(x,y) do {} while(0)
+#define blk_queue_headactive(x,y) do {} while(0)
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+        blk_dev[d_major].request_fn = d_request_fn; \
+        blk_dev[d_major].queue = d_queue_fn; \
+        blk_dev[d_major].current_request = d_current; \
+} while(0)
+static inline struct request *
+tape_next_request( request_queue_t *queue ) 
+{
+    return *queue;
+}
+static inline void 
+tape_dequeue_request( request_queue_t * q, struct request *req )
+{
+        *q = req->next;
+        req->next = NULL;
+}
+#endif 
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/ebcdic.c linux/drivers/s390/ebcdic.c
--- v2.4.1/linux/drivers/s390/ebcdic.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/ebcdic.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,246 @@
+/*
+ *  arch/s390/kernel/ebcdic.c
+ *    ECBDIC -> ASCII, ASCII -> ECBDIC conversion tables.
+ *
+ *  S390 version
+ *    Copyright (C) 1998 IBM Corporation
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#include <asm/types.h>
+
+/*
+ * ASCII -> EBCDIC
+ */
+__u8 _ascebc[256] =
+{
+ /*00  NL    SH    SX    EX    ET    NQ    AK    BL */
+     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
+ /*08  BS    HT    LF    VT    FF    CR    SO    SI */
+     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /*10  DL    D1    D2    D3    D4    NK    SN    EB */
+     0x10, 0x11, 0x12, 0x13, 0x3C, 0x15, 0x32, 0x26,
+ /*18  CN    EM    SB    EC    FS    GS    RS    US */
+     0x18, 0x19, 0x3F, 0x27, 0x1C, 0x1D, 0x1E, 0x1F,
+ /*20  SP     !     "     #     $     %     &     ' */
+     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
+ /*28   (     )     *     +     ,     -    .      / */
+     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
+ /*30   0     1     2     3     4     5     6     7 */
+     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
+ /*38   8     9     :     ;     <     =     >     ? */
+     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
+ /*40   @     A     B     C     D     E     F     G */
+     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
+ /*48   H     I     J     K     L     M     N     O */
+     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
+ /*50   P     Q     R     S     T     U     V     W */
+     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
+ /*58   X     Y     Z     [     \     ]     ^     _ */
+     0xE7, 0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
+ /*60   `     a     b     c     d     e     f     g */
+     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ /*68   h     i     j     k     l     m     n     o */
+     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
+ /*70   p     q     r     s     t     u     v     w */
+     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
+ /*78   x     y     z     {     |     }     ~    DL */
+     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
+     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0xFF
+};
+
+/*
+ * EBCDIC -> ASCII
+ */
+__u8 _ebcasc[256] =
+{
+ /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
+          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+ /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
+          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
+                                  -ENP  ->LF             */
+          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+ /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
+                                                    -IUS */
+          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
+                                  -INP                   */
+          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+ /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
+                       -SW                               */ 
+          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+ /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
+          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+ /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
+          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+ /* 0x40    SP   RSP           �ä              ----       */
+          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+ /* 0x48                       .     <     (     +     | */
+          0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+ /* 0x50     &                                      ---- */
+          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+ /* 0x58           �ß     !     $     *     )     ;       */
+          0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
+ /* 0x60     -     /  ----     �Ä  ----  ----  ----       */
+          0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
+ /* 0x68              ----     ,     %     _     >     ? */ 
+          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+ /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
+          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+ /* 0x78     *     `     :     #     @     '     =     " */
+          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+ /* 0x80     *     a     b     c     d     e     f     g */
+          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+ /* 0x88     h     i              ----  ----  ----       */
+          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+ /* 0x90     �°     j     k     l     m     n     o     p */
+          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+ /* 0x98     q     r                    ----        ---- */
+          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+ /* 0xA0           ~     s     t     u     v     w     x */
+          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ /* 0xA8     y     z              ----  ----  ----  ---- */
+          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+ /* 0xB0     ^                    ----     �§  ----       */
+          0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+ /* 0xB8        ----     [     ]  ----  ----  ----  ---- */
+          0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
+ /* 0xC0     {     A     B     C     D     E     F     G */
+          0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
+ /* 0xC8     H     I  ----           �ö              ---- */
+          0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+ /* 0xD0     }     J     K     L     M     N     O     P */
+          0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
+ /* 0xD8     Q     R  ----           �ü                   */
+          0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+ /* 0xE0     \           S     T     U     V     W     X */
+          0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ /* 0xE8     Y     Z        ----     �Ö  ----  ----  ---- */
+          0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
+ /* 0xF0     0     1     2     3     4     5     6     7 */
+          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ /* 0xF8     8     9  ----  ----     �Ü  ----  ----  ---- */
+          0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07
+};
+
+/*
+ * EBCDIC (capitals) -> ASCII (small case)
+ */
+__u8 _ebcasc_reduce_case[256] =
+{
+ /* 0x00   NUL   SOH   STX   ETX  *SEL    HT  *RNL   DEL */
+          0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
+
+ /* 0x08   -GE  -SPS  -RPT    VT    FF    CR    SO    SI */
+          0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+
+ /* 0x10   DLE   DC1   DC2   DC3  -RES   -NL    BS  -POC
+                                  -ENP  ->LF             */
+          0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
+
+ /* 0x18   CAN    EM  -UBS  -CU1  -IFS  -IGS  -IRS  -ITB
+                                                    -IUS */
+          0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+
+ /* 0x20   -DS  -SOS    FS  -WUS  -BYP    LF   ETB   ESC
+                                  -INP                   */
+          0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
+
+ /* 0x28   -SA  -SFE   -SM  -CSP  -MFA   ENQ   ACK   BEL
+                       -SW                               */ 
+          0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
+
+ /* 0x30  ----  ----   SYN   -IR   -PP  -TRN  -NBS   EOT */
+          0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
+
+ /* 0x38  -SBS   -IT  -RFF  -CU3   DC4   NAK  ----   SUB */
+          0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
+
+ /* 0x40    SP   RSP           �ä              ----       */
+          0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
+
+ /* 0x48                       .     <     (     +     | */
+          0x87, 0xA4, 0x9B, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
+
+ /* 0x50     &                                      ---- */
+          0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
+
+ /* 0x58           �ß     !     $     *     )     ;       */
+          0x8D, 0xE1, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0xAA,
+
+ /* 0x60     -     /  ----     �Ä  ----  ----  ----       */
+          0x2D, 0x2F, 0x07, 0x84, 0x07, 0x07, 0x07, 0x8F,
+
+ /* 0x68              ----     ,     %     _     >     ? */ 
+          0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
+
+ /* 0x70  ----        ----  ----  ----  ----  ----  ---- */
+          0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+
+ /* 0x78     *     `     :     #     @     '     =     " */
+          0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
+
+ /* 0x80     *     a     b     c     d     e     f     g */
+          0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+
+ /* 0x88     h     i              ----  ----  ----       */
+          0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
+
+ /* 0x90     �°     j     k     l     m     n     o     p */
+          0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+
+ /* 0x98     q     r                    ----        ---- */
+          0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
+
+ /* 0xA0           ~     s     t     u     v     w     x */
+          0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+
+ /* 0xA8     y     z              ----  ----  ----  ---- */
+          0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
+
+ /* 0xB0     ^                    ----     �§  ----       */
+          0x5E, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
+
+ /* 0xB8        ----     [     ]  ----  ----  ----  ---- */
+          0xAB, 0x07, 0x5B, 0x5D, 0x07, 0x07, 0x07, 0x07,
+
+ /* 0xC0     {     A     B     C     D     E     F     G */
+          0x7B, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
+
+ /* 0xC8     H     I  ----           �ö              ---- */
+          0x68, 0x69, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
+
+ /* 0xD0     }     J     K     L     M     N     O     P */
+          0x7D, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
+
+ /* 0xD8     Q     R  ----           �ü                   */
+          0x71, 0x72, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
+
+ /* 0xE0     \           S     T     U     V     W     X */
+          0x5C, 0xF6, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+
+ /* 0xE8     Y     Z        ----     �Ö  ----  ----  ---- */
+          0x79, 0x7A, 0xFD, 0x07, 0x94, 0x07, 0x07, 0x07,
+
+ /* 0xF0     0     1     2     3     4     5     6     7 */
+          0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+
+ /* 0xF8     8     9  ----  ----     �Ü  ----  ----  ---- */
+          0x38, 0x39, 0x07, 0x07, 0x81, 0x07, 0x07, 0x07
+};
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/idals.c linux/drivers/s390/idals.c
--- v2.4.1/linux/drivers/s390/idals.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/idals.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,47 @@
+/* 
+   * File...........: linux/drivers/s390x/idals.c
+   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+   * Bugreports.to..: <Linux390@de.ibm.com>
+   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
+   
+   * History of changes
+   * 07/24/00 new file
+   * 12/13/00 changed IDALs to 4kByte-IDALs
+ */
+
+#include <linux/config.h>
+#include <linux/malloc.h>
+
+#include <asm/irq.h>
+#include <asm/idals.h>
+
+#ifdef CONFIG_ARCH_S390X
+void 
+set_normalized_cda ( ccw1_t * cp, unsigned long address )
+{
+	int nridaws;
+	idaw_t *idal;
+        int count = cp->count;
+
+	if (cp->flags & CCW_FLAG_IDA)
+		BUG();
+	if (((address + count) >> 31) == 0) { /* do we really need  '+count'? */
+		cp -> cda = address;
+		return;
+	}
+        nridaws = ((address & 4095L) + count + 4095L) >> 12;
+	idal = idal_alloc(nridaws);
+	if ( idal == NULL ) {
+		/* probably we should have a fallback here */
+		panic ("Cannot allocate memory for IDAL\n");
+	}
+	cp->flags |= CCW_FLAG_IDA;
+	cp->cda = (__u32)(unsigned long)(idaw_t *)idal;
+        do {
+		*idal++ = address;
+		address = (address & -4096L) + 4096;
+		nridaws --;
+        } while ( nridaws > 0 );
+	return;
+}
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/misc/Makefile linux/drivers/s390/misc/Makefile
--- v2.4.1/linux/drivers/s390/misc/Makefile	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/misc/Makefile	Tue Feb 13 14:13:44 2001
@@ -2,12 +2,8 @@
 
 CFLAFS += 
 O_TARGET := s390-misc.o
-O_OBJS    :=         
-M_OBJS   := 
 
-ifeq ($(CONFIG_CHANDEV),y)
-  O_OBJS += chandev.o
-endif
+obj-$(CONFIG_CHANDEV) += chandev.o
 
 include $(TOPDIR)/Rules.make
 
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/misc/chandev.c linux/drivers/s390/misc/chandev.c
--- v2.4.1/linux/drivers/s390/misc/chandev.c	Fri Jul 21 14:21:58 2000
+++ linux/drivers/s390/misc/chandev.c	Tue Feb 13 14:13:44 2001
@@ -1,17 +1,15 @@
 /*
  *  drivers/s390/misc/chandev.c
- *    common channel device layer
  *
- *  S390 version
  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ * 
+ *  Generic channel device initialisation support. 
  */
-
 #define __KERNEL_SYSCALLS__
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/ctype.h>
-#include <asm/queue.h>
 #include <asm/uaccess.h>
 #include <linux/slab.h>
 #include <asm/irq.h>
@@ -20,260 +18,1847 @@
 #include <asm/chandev.h>
 #include <linux/proc_fs.h>
 #include <linux/vmalloc.h>
+#include <asm/s390dyn.h>
+#include <asm/queue.h>
+
+typedef struct chandev_model_info chandev_model_info;
+struct chandev_model_info
+{
+	struct chandev_model_info *next;
+	chandev_type chan_type;
+	s32 cu_type;      /* control unit type  -1 = don't care */
+	s16 cu_model;     /* control unit model -1 = don't care */
+	s32 dev_type;     /* device type -1 = don't care */
+	s16 dev_model;    /* device model -1 = don't care */
+	u8  max_port_no;
+	int      auto_msck_recovery;
+	devreg_t drinfo;
+};
+
+typedef struct chandev chandev;
+struct chandev
+{
+	struct chandev *next;
+	chandev_model_info *model_info;
+	u16 cu_type;      /* control unit type */
+	u8  cu_model;     /* control unit model */
+	u16 dev_type;     /* device type */
+	u8  dev_model;    /* device model */
+	u16 devno;
+	unsigned int irq;
+	int owned;
+};
+
+typedef struct chandev_noauto_range chandev_noauto_range;
+struct chandev_noauto_range
+{
+	struct chandev_noauto_range *next;
+	u16     lo_devno;
+	u16     hi_devno;
+};
+
+typedef struct chandev_force chandev_force;
+struct chandev_force
+{
+	struct chandev_force *next;
+	chandev_type chan_type;
+	s32     devif_num; /* -1 don't care e.g. tr0 implies 0 */
+        u16     read_devno;
+	u16     write_devno;
+        s16     port_protocol_no; /* where available e.g. lcs,-1 don't care */
+	u8      checksum_received_ip_pkts;
+	u8      use_hw_stats; /* where available e.g. lcs */
+};
+
+typedef struct chandev_probelist chandev_probelist;
+struct chandev_probelist
+{
+	struct chandev_probelist *next;
+	chandev_probefunc       probefunc;
+	chandev_shutdownfunc    shutdownfunc;
+	chandev_reoperfunc      reoperfunc;
+	chandev_type            chan_type;
+	int                     devices_found;
+};
+
+
+
+#define default_msck_bits ((1<<(not_oper-1))|(1<<(no_path-1))|(1<<(revalidate-1))|(1<<(gone-1)))
+
+
+static char *msck_status_strs[]=
+{
+	"good",
+	"not_operational",
+	"no_path",
+	"revalidate",
+	"device_gone"
+};
+
+typedef struct chandev_msck_range chandev_msck_range;
+struct chandev_msck_range
+{
+	struct chandev_msck_range *next;
+	u16     lo_devno;
+	u16     hi_devno;
+	int      auto_msck_recovery;
+};
+
+static chandev_msck_range *chandev_msck_range_head=NULL;
+
+typedef struct chandev_irqinfo chandev_irqinfo;
+struct chandev_irqinfo
+{
+	chandev_irqinfo      *next;
+	chandev_msck_status  msck_status;
+	u16                  devno;
+	unsigned int         irq;
+	void                 (*handler)(int, void *, struct pt_regs *);
+	unsigned long        irqflags;
+	void                 *dev_id;
+	char                 devname[0];
+};
+
+
+chandev_irqinfo *chandev_irqinfo_head=NULL;
+
+typedef struct chandev_parms chandev_parms;
+struct chandev_parms
+{
+	chandev_parms      *next;
+	chandev_type       chan_type;
+	char               parmstr[0];
+};
+
+chandev_parms *chandev_parms_head=NULL;
+
+
+typedef struct chandev_activelist chandev_activelist;
+struct chandev_activelist
+{
+	struct chandev_activelist *next;
+	chandev_irqinfo         *read_irqinfo;
+	chandev_irqinfo         *write_irqinfo;
+	u16                     cu_type;      /* control unit type */
+	u8                      cu_model;     /* control unit model */
+	u16                     dev_type;     /* device type */
+	u8                      dev_model;    /* device model */
+	chandev_probefunc       probefunc;
+	chandev_shutdownfunc    shutdownfunc;
+	chandev_reoperfunc      reoperfunc;
+	chandev_unregfunc       unreg_dev;
+	chandev_type            chan_type;
+	u8                      port_no;
+	chandev_category        category;
+	int                     saved_busy_flag;
+	
+
+	void                    *dev_ptr;
+	char                    devname[0];
+};
+
+
 
 static chandev_model_info *chandev_models_head=NULL;
-static chandev *chandev_head=NULL;
+/* The only reason chandev_head is a queue is so that net devices */
+/* will be by default named in the order of their irqs */
+static qheader chandev_head={NULL,NULL};
 static chandev_noauto_range *chandev_noauto_head=NULL;
 static chandev_force *chandev_force_head=NULL;
 static chandev_probelist *chandev_probelist_head=NULL;
+static chandev_activelist *chandev_activelist_head=NULL;
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
 static int use_devno_names=FALSE;
+#endif
 static int chandev_conf_read=FALSE;
+static int chandev_initialised=FALSE;
 
-static void *chandev_alloc_listmember(list **listhead,size_t size)
+
+static unsigned long chandev_last_machine_check;
+
+
+static struct tq_struct chandev_msck_task_tq;
+static atomic_t chandev_msck_thread_lock;
+static atomic_t chandev_new_msck;
+static unsigned long chandev_last_startmsck_list_update;
+
+typedef struct chandev_startmsck_list chandev_startmsck_list;
+struct chandev_startmsck_list
+{
+	chandev_startmsck_list    *next;
+	chandev_msck_status       pre_recovery_action_status;
+	chandev_msck_status       post_recovery_action_status;
+	char                      devname[0];
+};
+
+
+static chandev_startmsck_list *startlist_head=NULL;
+static chandev_startmsck_list *mscklist_head=NULL;
+
+
+
+
+static void chandev_read_conf(void);
+
+#if LINUX_VERSION_CODE >=KERNEL_VERSION(2,3,0)
+typedef struct net_device  net_device;
+#else
+typedef struct device  net_device;
+
+static inline void init_waitqueue_head(wait_queue_head_t *q)
 {
-	void *newmember=kmalloc(size, GFP_KERNEL);
-	if(newmember)
-		add_to_list(listhead,newmember);
-	return(newmember);
+	*q=NULL;
 }
+#endif
 
-void chandev_free_listmember(list **listhead,list *member)
+#if LINUX_VERSION_CODE<KERNEL_VERSION(2,3,45)
+static __inline__ void netif_stop_queue(net_device *dev)
 {
-	if(remove_from_list(listhead,member))
-		kfree(member);
-	else
-		printk(KERN_CRIT"chandev_free_listmember detected nonexistant"
-		       "listmember listhead=%p member %p\n",listhead,member);
+	dev->tbusy=1;
 }
 
-void chandev_free_all(list **listhead)
+static __inline__ void netif_start_queue(net_device *dev)
 {
-	while(*listhead)
-		chandev_free_listmember(listhead,*listhead);
+	dev->tbusy=0;
 }
+#endif
+
+
+
+#define CHANDEV_INVALID_LOCK_OWNER            -1
+static long                 chandev_lock_owner;
+static int                  chandev_lock_cnt; 
+static spinlock_t           chandev_spinlock;
+
+typedef struct chandev_not_oper_struct chandev_not_oper_struct;
+
+struct  chandev_not_oper_struct
+{
+	chandev_not_oper_struct *next;
+	int irq;
+	int status;
+};
+
+
+/* May as well try to keep machine checks in the order they happen so
+ * we use qheader for chandev_not_oper_head instead of list.
+ */
+static qheader chandev_not_oper_head={NULL,NULL};
+static spinlock_t           chandev_not_oper_spinlock;
+static char           exec_script[]="/bin/chandev";
+
+#define chandev_interrupt_check() \
+if(in_interrupt())                \
+     printk(KERN_WARNING __FUNCTION__ " called under interrupt this shouldn't happen\n")
+
+
+#define for_each(variable,head) \
+for((variable)=(head);(variable)!=NULL;(variable)=(variable)->next)
+
+
+#define CHANDEV_USE_KERNEL_THREADS (LINUX_VERSION_CODE<KERNEL_VERSION(2,4,0))
+
+#if CHANDEV_USE_KERNEL_THREADS
+static void chandev_start_msck_thread(void *unused);
+#if LINUX_VERSION_CODE<KERNEL_VERSION(2,3,0)
+#define chandev_daemonize(name,mask,use_init_fs) s390_daemonize(name,mask)
+#else
+#define chandev_daemonize(args...) s390_daemonize(args)
+#endif
+typedef int chandev_task_retval;
+#define chandev_task_return(val) return(val)       
+#else
+#define chandev_daemonize(noargs...)
+#define chandev_task_retval void
+#define chandev_task_return(val) return
+#endif
+
 
-void chandev_add_model(chandev_type chan_type,u16 cu_type,u8 cu_model,u8 max_port_no)
+static void chandev_lock(void)
 {
-	chandev_model_info *newmodel;
+	chandev_interrupt_check();
+	eieio();
+	if(chandev_lock_owner!=(long)current)
+	{
+		spin_lock(&chandev_spinlock);
+		chandev_lock_cnt=1;
+		chandev_lock_owner=(long)current;
+	}
+	else
+		chandev_lock_cnt++;
+	if(chandev_lock_cnt<0||chandev_lock_cnt>100)
+			panic("odd lock_cnt in lcs %d lcs_chan_lock",chandev_lock_cnt);
+}
 
-	if((newmodel=chandev_alloc_listmember(
-		(list **)&chandev_models_head,sizeof(chandev_model_info))))
+
+static void chandev_unlock(void)
+{
+	if(chandev_lock_owner!=(long)current)
+		panic("chandev_unlock: current=%lx"
+		      " chandev_lock_owner=%lx chandev_lock_cnt=%d\n",
+		      (long)current,
+		      chandev_lock_owner,
+		      chandev_lock_cnt);
+	if(--chandev_lock_cnt==0)
 	{
-		newmodel->chan_type=chan_type;
-		newmodel->cu_type=cu_type;
-		newmodel->cu_model=cu_model;
-		newmodel->max_port_no=max_port_no;
+		chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
+		spin_unlock(&chandev_spinlock);
 	}
+	if(chandev_lock_cnt<0)
+		panic("odd lock_cnt in lcs %d lcs_chan_unlock",chandev_lock_cnt);
 }
 
-
-void chandev_remove(chandev *member)
+int chandev_full_unlock(void)
 {
-	chandev_free_listmember((list **)&chandev_head,(list *)member);
+	int ret_lock_cnt=chandev_lock_cnt;
+	chandev_lock_cnt=0;
+	chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
+	spin_unlock(&chandev_spinlock);
+	return(ret_lock_cnt);
 }
 
 
-void chandev_remove_all(void)
+
+
+void *chandev_alloc(size_t size)
 {
-	chandev_free_all((list **)&chandev_head);
+	void *mem=kmalloc(size,GFP_ATOMIC);
+	if(mem)
+		memset(mem,0,size);
+	return(mem);
 }
 
-void chandev_remove_model(chandev_model_info *model)
+static void chandev_add_to_list(list **listhead,void *member)
 {
-	chandev *curr_chandev;
-	for(curr_chandev=chandev_head;curr_chandev!=NULL;
-		    curr_chandev=curr_chandev->next)
-		if(curr_chandev->model_info==model)
-			chandev_remove(curr_chandev);
-	chandev_free_listmember((list **)&chandev_models_head,(list *)model);
+	chandev_lock();
+	add_to_list(listhead,member);
+	chandev_unlock();
 }
 
-void chandev_remove_all_models(void)
+static void chandev_queuemember(qheader *qhead,void *member)
 {
-	while(chandev_models_head)
-		chandev_remove_model(chandev_models_head);
+	chandev_lock();
+	enqueue_tail(qhead,(queue *)member);
+	chandev_unlock();
 }
 
-void chandev_del_model(u16 cu_type,u8 cu_model)
+static int chandev_remove_from_list(list **listhead,list *member)
 {
-	chandev_model_info *curr_model;
-	for(curr_model=chandev_models_head;curr_model!=NULL;
-		    curr_model=curr_model->next)
-		if(curr_model->cu_type==cu_type&&curr_model->cu_model==cu_model)
-			chandev_remove_model(curr_model);			
+	int retval;
+
+	chandev_lock();
+	retval=remove_from_list(listhead,member);
+	chandev_unlock();
+	return(retval);
 }
 
-static void chandev_init_default_models(void)
+static int chandev_remove_from_queue(qheader *qhead,queue *member)
 {
-	/* P390/Planter 3172 emulation assume maximum 16 to be safe. */
-	chandev_add_model(lcs,0x3088,0x1,15);	
-
-	/* 3172/2216 Paralell the 2216 allows 16 ports per card the */
-	/* the original 3172 only allows 4 we will assume the max of 16 */
-	chandev_add_model(lcs|ctc,0x3088,0x8,15);
+	int retval;
+	
+	chandev_lock();
+	retval=remove_from_queue(qhead,member);
+	chandev_unlock();
+	return(retval);
+}
 
-	/* 3172/2216 Escon serial the 2216 allows 16 ports per card the */
-	/* the original 3172 only allows 4 we will assume the max of 16 */
-	chandev_add_model(lcs|escon,0x3088,0x1F,15);
 
-	/* Only 2 ports allowed on OSA2 cards model 0x60 */
-	chandev_add_model(lcs,0x3088,0x60,1);
 
-	/* Osa-D we currently aren't too emotionally involved with this */
-	chandev_add_model(osad,0x3088,0x62,0);
+void chandev_free_listmember(list **listhead,list *member)
+{
+	if(member)
+	{
+		if(chandev_remove_from_list(listhead,member))
+			kfree(member);
+		else
+			printk(KERN_CRIT"chandev_free_listmember detected nonexistant"
+			       "listmember listhead=%p member %p\n",listhead,member);
+	}
 }
 
-void chandev_add(dev_info_t  *newdevinfo,chandev_model_info *newmodelinfo)
+void chandev_free_queuemember(qheader *qhead,queue *member)
 {
-	chandev *new_chandev;
-
-	if((new_chandev=chandev_alloc_listmember(
-		(list **)&chandev_head,sizeof(chandev))))
+	if(member)
 	{
-		new_chandev->model_info=newmodelinfo;
-		new_chandev->devno=newdevinfo->devno;
-		new_chandev->irq=newdevinfo->irq;
+		if(chandev_remove_from_queue(qhead,member))
+			kfree(member);
+		else
+			printk(KERN_CRIT"chandev_free_listmember detected nonexistant"
+			       "listmember qhead=%p member %p\n",qhead,member);
 	}
 }
 
 
-void chandev_collect_devices(void)
+
+void chandev_free_all_list(list **listhead)
 {
-	int curr_irq,loopcnt=0,err;
-	dev_info_t   curr_devinfo;
-	chandev_model_info *curr_model;
-     
+	list *head;
 
-	for(curr_irq=get_irq_first();curr_irq>=0; curr_irq=get_irq_next(curr_irq))
-	{
-		/* check read chandev
-		 * we had to do the cu_model check also because ctc devices
-		 * have the same cutype & after asking some people
-		 * the model numbers are given out pseudo randomly so
-		 * we can't just take a range of them also the dev_type & models are 0
-		 */
-		loopcnt++;
-		if(loopcnt>0x10000)
-		{
-			printk(KERN_ERR"chandev_collect_devices detected infinite loop bug in get_irq_next\n");
-			break;
-		}
-		if((err=get_dev_info_by_irq(curr_irq,&curr_devinfo)))
+	while((head=remove_listhead(listhead)))
+		kfree(head);
+}
+
+void chandev_free_all_queue(qheader *qhead)
+{
+	while(qhead->head)
+		chandev_free_queuemember(qhead,qhead->head);
+}
+
+
+struct files_struct *chandev_new_files_struct(void)
+{
+        struct files_struct *newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
+	if (!newf) 
+		return(NULL);
+	memset(newf,0,sizeof(struct files_struct));
+	atomic_set(&newf->count, 1);
+	newf->file_lock	    = RW_LOCK_UNLOCKED;
+	newf->next_fd	    = 0;
+	newf->max_fds	    = NR_OPEN_DEFAULT;
+	newf->max_fdset	    = __FD_SETSIZE;
+	newf->close_on_exec = &newf->close_on_exec_init;
+	newf->open_fds	    = &newf->open_fds_init;
+	newf->fd	    = &newf->fd_array[0];
+	return(newf);
+}
+/*
+ * Mostly robbed from kmod.c
+ */
+
+static inline void
+use_init_fs_context(void)
+{
+	struct fs_struct *our_fs, *init_fs;
+	struct dentry *root, *pwd;
+	struct vfsmount *rootmnt, *pwdmnt;
+
+	/*
+	 * Make modprobe's fs context be a copy of init's.
+	 *
+	 * We cannot use the user's fs context, because it
+	 * may have a different root than init.
+	 * Since init was created with CLONE_FS, we can grab
+	 * its fs context from "init_task".
+	 *
+	 * The fs context has to be a copy. If it is shared
+	 * with init, then any chdir() call in modprobe will
+	 * also affect init and the other threads sharing
+	 * init_task's fs context.
+	 *
+	 * We created the exec_modprobe thread without CLONE_FS,
+	 * so we can update the fields in our fs context freely.
+	 */
+
+	init_fs = init_task.fs;
+	read_lock(&init_fs->lock);
+	rootmnt = mntget(init_fs->rootmnt);
+	root = dget(init_fs->root);
+	pwdmnt = mntget(init_fs->pwdmnt);
+	pwd = dget(init_fs->pwd);
+	read_unlock(&init_fs->lock);
+
+	/* FIXME - unsafe ->fs access */
+	our_fs = current->fs;
+	our_fs->umask = init_fs->umask;
+	set_fs_root(our_fs, rootmnt, root);
+	set_fs_pwd(our_fs, pwdmnt, pwd);
+	write_lock(&our_fs->lock);
+	if (our_fs->altroot) {
+		struct vfsmount *mnt = our_fs->altrootmnt;
+		struct dentry *dentry = our_fs->altroot;
+		our_fs->altrootmnt = NULL;
+		our_fs->altroot = NULL;
+		write_unlock(&our_fs->lock);
+		dput(dentry);
+		mntput(mnt);
+	} else 
+		write_unlock(&our_fs->lock);
+	dput(root);
+	mntput(rootmnt);
+	dput(pwd);
+	mntput(pwdmnt);
+}
+
+
+static int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
+{
+	int err;
+	wait_queue_head_t    wait;
+
+
+	current->session = 1;
+	current->pgrp = 1;
+
+	/* We copy this off init & can't go until this is set up */
+	init_waitqueue_head(&wait);
+	while(init_task.fs->root==NULL)
+	{
+		sleep_on_timeout(&wait,HZ);
+	}
+	use_init_fs_context();
+
+	/* Prevent parent user process from sending signals to child.
+	   Otherwise, if the modprobe program does not exist, it might
+	   be possible to get a user defined signal handler to execute
+	   as the super user right after the execve fails if you time
+	   the signal just right.
+	*/
+	spin_lock_irq(&current->sigmask_lock);
+	flush_signals(current);
+	flush_signal_handlers(current);
+	spin_unlock_irq(&current->sigmask_lock);
+	 /* current->files sometimes was null this means we need */
+	 /* to build our own */
+	 exit_files(current);
+	 if((current->files=chandev_new_files_struct())==NULL)
+	 {
+		 printk("chandev_new_files_struct allocation failed\n");
+		 return(0);
+	 }
+	 
+	/* Drop the "current user" thing */
+	{
+		struct user_struct *user = current->user;
+		current->user = INIT_USER;
+		atomic_inc(&INIT_USER->__count);
+		atomic_inc(&INIT_USER->processes);
+		atomic_dec(&user->processes);
+		free_uid(user);
+	}
+
+	/* Take all effective privileges.. */
+	current->uid = current->euid = current->fsuid = 0;
+	cap_set_full(current->cap_effective);
+	/* Allow execve & open args to be in kernel space. */
+	set_fs(KERNEL_DS);
+	/* We need stdin out & err for scripts */
+	if (open("/dev/console", O_RDWR, 0)< 0)
+		printk("chandev exec_usermode_helper unable to open an initial console.\n");
+	(void) dup(0);
+	(void) dup(0);
+
+	
+        /* Go, go, go... */
+        err=execve(program_path, argv, envp);
+	return err;
+}
+
+static int exec_start_script(void *unused)
+{
+	
+	char **argv,*tempname;
+	int retval=-ENOMEM;
+	int loopcnt,argc;
+	size_t allocsize;
+	chandev_startmsck_list *member;
+	wait_queue_head_t      wait;
+	static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+	
+	init_waitqueue_head(&wait);
+	s390_daemonize("chandev_script",0,FALSE);
+	for(loopcnt=0;loopcnt<10&&(jiffies-chandev_last_startmsck_list_update)<HZ;loopcnt++)
+	{
+		sleep_on_timeout(&wait,HZ);
+	}
+	chandev_lock();
+	argc=1;
+	if(startlist_head)
+		argc++;
+	for_each(member,startlist_head)
+		argc++;
+	if(mscklist_head)
+		argc+=3;
+	for_each(member,mscklist_head)
+		argc++;
+
+	allocsize=(argc+1)*sizeof(char *);
+        /* Warning possible stack overflow */
+	/* We can't kmalloc the parameters here as execve will */
+	/* not return if successful */
+	argv=alloca(allocsize);
+	if(argv)
+	{
+		memset(argv,0,allocsize);
+		argc=0;
+		argv[argc++]=exec_script;
+		if(startlist_head)
+			argv[argc++]="start";
+		for_each(member,startlist_head)
 		{
-			printk("chandev_collect_devices get_dev_info_by_irq reported err=%X on irq %d\n"
-			       "should not happen\n",err,curr_irq);
-			continue;
+			tempname=alloca(strlen(member->devname)+1);
+			if(tempname)
+			{
+				strcpy(tempname,member->devname);
+				argv[argc++]=tempname;
+			}
+			else
+				goto Fail;
 		}
-		for(curr_model=chandev_models_head;curr_model!=NULL;
-		    curr_model=curr_model->next)
+		if(mscklist_head)
+			argv[argc++]="machine_check";
+		for_each(member,mscklist_head)
 		{
-			if((curr_model->cu_type==curr_devinfo.sid_data.cu_type)&&
-			   (curr_model->cu_model==curr_devinfo.sid_data.cu_model)
-			   &&((curr_devinfo.status&DEVSTAT_DEVICE_OWNED)==0))
-				chandev_add(&curr_devinfo,curr_model);
+			tempname=alloca(strlen(member->devname)+1);
+			if(tempname)
+			{
+				strcpy(tempname,member->devname);
+				argv[argc++]=tempname;
+			}
+			else
+				goto Fail;
+			argv[loopcnt++]=msck_status_strs[member->pre_recovery_action_status];
+			argv[loopcnt++]=msck_status_strs[member->post_recovery_action_status];
 		}
+		chandev_free_all_list((list **)&startlist_head);
+		chandev_free_all_list((list **)&mscklist_head);
+		chandev_unlock();
+		/* We are basically execve'ing here there normally is no */
+		/* return */
+		retval=exec_usermodehelper(exec_script, argv, envp);
+		goto Fail2;
 	}
+ Fail:
+	
+	chandev_unlock();
+ Fail2:
+	/* We don't really need to report /bin/chandev not existing */
+	if(retval!=-ENOENT)
+	   printk("exec_start_script failed retval=%d\n",retval);
+	return(0);
 }
 
-void chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_devno,
-u16 write_devno,s16 port_no,u8 do_ip_checksumming,u8 use_hw_stats)
 
+void *chandev_allocstr(const char *str,size_t offset)
 {
-	chandev_force *new_chandev_force;
+	char *member;
 
-	if((new_chandev_force=chandev_alloc_listmember(
-		(list **)&chandev_force_head,sizeof(chandev_force))))
+	if((member=chandev_alloc(offset+strlen(str)+1)))
 	{
-		new_chandev_force->chan_type=chan_type;
-		new_chandev_force->devif_num=devif_num;
-		new_chandev_force->read_devno=read_devno;
-		new_chandev_force->write_devno=write_devno;
-		new_chandev_force->port_no=port_no;
-		new_chandev_force->do_ip_checksumming=do_ip_checksumming;
-		new_chandev_force->use_hw_stats=use_hw_stats;
+		strcpy(&member[offset],str);
 	}
+	return((void *)member);
 }
 
-void chandev_del_force(u16 read_devno)
+
+static int chandev_add_to_startmsck_list(chandev_startmsck_list **listhead,char *devname,
+chandev_msck_status pre_recovery_action_status,chandev_msck_status post_recovery_action_status)
 {
-	chandev_force *curr_force;
-	for(curr_force=chandev_force_head;curr_force!=NULL;
-		    curr_force=curr_force->next)
+	int retval;
+	chandev_startmsck_list *member;
+	int pid;
+	
+	chandev_lock();
+	/* remove operations still outstanding for this device */
+	for_each(member,startlist_head)
+		if(strcmp(member->devname,devname)==0)
+			chandev_remove_from_list((list **)&startlist_head,(list *)member);
+	for_each(member,mscklist_head)
+		if(strcmp(member->devname,devname)==0)
+			chandev_remove_from_list((list **)&mscklist_head,(list *)member);
+	
+
+	if((member=chandev_allocstr(devname,offsetof(chandev_startmsck_list,devname))))
 	{
-		if(curr_force->read_devno==read_devno)
-			chandev_free_listmember((list **)&chandev_force_head,
-						(list *)curr_force);
+		member->pre_recovery_action_status=pre_recovery_action_status;
+		member->post_recovery_action_status=post_recovery_action_status;
+		add_to_list((list **)listhead,(list *)member);
+		chandev_last_startmsck_list_update=jiffies;
+		chandev_unlock();
+		/* We do CLONE_FILES so we can exit_files to get rid of it */
+                /* cheaply & allocate a new one we need current->files &  */
+                /* some tasks have current->files==NULL */
+		pid = kernel_thread(exec_start_script,NULL,CLONE_FILES|SIGCHLD);
+		if(pid<0)
+		{
+			printk("error making kernel thread for exec_start_script\n");
+			retval=pid;
+		}
+		else
+			return(0);
+
+	}
+	else
+	{
+		printk("chandev_add_to_startmscklist memory allocation failed devname=%s\n",devname);
+		retval=-ENOMEM;
 	}
+	chandev_unlock();
+	return(retval);
 }
 
-void chandev_pack_args(char *str)
+
+
+
+
+int chandev_oper_func(int irq,devreg_t *dreg)
 {
-	char *newstr=str;
-	while(*str)
+	chandev_last_machine_check=jiffies;
+	if(atomic_dec_and_test(&chandev_msck_thread_lock))
 	{
-		if(isspace(*str))
-			str++;
-		else
-			*newstr++=*str++;
+#if CHANDEV_USE_KERNEL_THREADS
+		queue_task(&chandev_msck_task_tq,&tq_scheduler);
+#else
+		schedule_task(&chandev_msck_task_tq);
+#endif
 	}
-	*newstr=0;
+	atomic_set(&chandev_new_msck,TRUE);
+	return(0);
 }
 
-typedef enum
-{ 
-	isnull=0,
-	isstr=1,
-	isnum=2,
-	iscomma=4,
-} chandev_strval;
-
-chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong)
+static void chandev_not_oper_handler(int irq,int status )
 {
-	char *cur=*str;
-	chandev_strval  retval=isnull;
+	chandev_not_oper_struct *new_not_oper;
 
-	int len=strlen(teststr);
-	if(strncmp(teststr,*str,len)==0)
+	chandev_last_machine_check=jiffies;
+	if((new_not_oper=kmalloc(sizeof(chandev_not_oper_struct),GFP_ATOMIC)))
 	{
-		*str+=len;
-		retval=isstr;
-		*endlong=simple_strtol(cur,str,0);
-		if(cur!=*str)
-			retval|=isnum;
-		if(**str==',')
-			retval|=iscomma;
+		new_not_oper->irq=irq;
+		new_not_oper->status=status;
+		spin_lock(&chandev_not_oper_spinlock);
+		enqueue_tail(&chandev_not_oper_head,(queue *)new_not_oper);
+		spin_unlock(&chandev_not_oper_spinlock);
+		if(atomic_dec_and_test(&chandev_msck_thread_lock))
+		{
+#if CHANDEV_USE_KERNEL_THREADS
+			queue_task(&chandev_msck_task_tq,&tq_scheduler);
+#else
+			schedule_task(&chandev_msck_task_tq);
+#endif
+		}
 	}
-	return(retval);
+	else
+		printk("chandev_not_oper_handler failed to allocate memory & "
+		       "lost a not operational interrupt %d %x",
+		       irq,status);
 }
 
-static char *argstrs[]=
+chandev_irqinfo *chandev_get_irqinfo_by_irq(int irq)
 {
-	"noauto",
-	"lcs",
-	"ctc",
-	"escon",
-	"del_force",
-	"use_devno_names"
-	"dont_use_devno_names",
-	"add_model"
-	"del_model"
-	"del_all_models"
-};
+	chandev_irqinfo *curr_irqinfo;
+	for_each(curr_irqinfo,chandev_irqinfo_head)
+		if(irq==curr_irqinfo->irq)
+			return(curr_irqinfo);
+	return(NULL);
+}
 
-typedef enum
+chandev *chandev_get_by_irq(int irq)
 {
-	stridx_mult=16,
-	first_stridx=0,
-	noauto_stridx=first_stridx,
-	lcs_stridx,
-	ctc_stridx,
-	escon_stridx,
-	del_force_stridx,
-	use_devno_names_stridx,
-	dont_use_devno_names_stridx,
-	add_model_stridx,
-	del_model_stridx,
-	del_all_models_stridx,
+	chandev *curr_chandev;
+
+	for_each(curr_chandev,(chandev *)chandev_head.head)
+		if(curr_chandev->irq==irq)
+		{
+			return(curr_chandev);
+		}
+	return(NULL);
+}
+
+chandev_activelist *chandev_get_activelist_by_irq(int irq)
+{
+	chandev_activelist *curr_device;
+
+	for_each(curr_device,chandev_activelist_head)
+	{
+			if(curr_device->read_irqinfo->irq==irq||
+			   curr_device->write_irqinfo->irq==irq)
+				return(curr_device);
+	}
+	return(NULL);
+}
+
+
+
+int chandev_request_irq(unsigned int   irq,
+                      void           (*handler)(int, void *, struct pt_regs *),
+                      unsigned long  irqflags,
+                      const char    *devname,
+                      void          *dev_id)
+{
+	chandev_irqinfo *new_irqinfo;
+	chandev_activelist *curr_device;
+	s390_dev_info_t         devinfo;
+	int          retval;
+	
+
+	chandev_lock();
+	if((curr_device=chandev_get_activelist_by_irq(irq)))
+	{
+		printk("chandev_request_irq failed devname=%s irq=%d "
+		       "it already belongs to %s shutdown this device first.\n",
+		       devname,irq,curr_device->devname);
+		chandev_unlock();
+		return(-EPERM);
+	}
+	/* remove any orphan irqinfo left lying around. */
+        if((new_irqinfo=chandev_get_irqinfo_by_irq(irq)))
+		chandev_remove_from_list((list **)chandev_irqinfo_head,
+					 (list *)new_irqinfo);
+	chandev_unlock();
+	if((new_irqinfo=chandev_allocstr(devname,offsetof(chandev_irqinfo,devname))))
+	{
+		
+		if((retval=get_dev_info_by_irq(irq,&devinfo))||
+		   (retval=s390_request_irq_special(irq,handler,
+						chandev_not_oper_handler,
+						irqflags,devname,dev_id)))
+			kfree(new_irqinfo);
+		else
+		{
+			new_irqinfo->irq=irq;
+			new_irqinfo->handler=handler;
+			new_irqinfo->dev_id=dev_id;
+			new_irqinfo->devno=devinfo.devno;
+			chandev_add_to_list((list **)&chandev_irqinfo_head,new_irqinfo);
+		}
+	}
+	else
+	{
+		printk("chandev_request_irq memory allocation failed devname=%s irq=%d\n",devname,irq);
+		retval=-ENOMEM;
+	}
+	return(retval);
+}
+
+
+
+void chandev_sprint_type_model(char *buff,s32 type,s16 model)
+{
+	if(type==-1)
+		strcpy(buff,"    *    ");
+	else
+		sprintf(buff," 0x%04x  ",(int)type);
+	buff+=strlen(buff);
+	if(model==-1)
+		strcpy(buff,"    *   ");
+	else
+		sprintf(buff," 0x%02x  ",(int)model);
+}
+
+void chandev_sprint_devinfo(char *buff,s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model)
+{
+	chandev_sprint_type_model(buff,cu_type,cu_model);
+	chandev_sprint_type_model(&buff[strlen(buff)],dev_type,dev_model);
+}
+
+void chandev_remove_parms(chandev_type chan_type,int exact_match)
+{
+	chandev_parms      *curr_parms;
+
+	chandev_lock();
+	for_each(curr_parms,chandev_parms_head)
+	{
+		if((chan_type&(curr_parms->chan_type)&&!exact_match)||
+		    (chan_type==(curr_parms->chan_type)&&exact_match))
+		    chandev_free_listmember((list **)&chandev_parms_head,(list *)curr_parms);
+	}
+	chandev_unlock();
+}
+
+void chandev_add_parms(chandev_type chan_type,char *parmstr)
+{
+	chandev_parms      *new_parms;
+	
+	if((new_parms=chandev_allocstr(parmstr,offsetof(chandev_parms,parmstr))))
+	{
+		chandev_remove_parms(chan_type,TRUE);
+		new_parms->chan_type=chan_type;
+		chandev_add_to_list((list **)&chandev_parms_head,(void *)new_parms);
+	}
+	else
+		printk("chandev_add_parmstr memory request failed\n");
+}
+
+
+void chandev_add_model(chandev_type chan_type,s32 cu_type,s16 cu_model,
+		       s32 dev_type,s16 dev_model,u8 max_port_no,int auto_msck_recovery)
+{
+	chandev_model_info *newmodel;
+	int                err;
+	char buff[40];
+
+	if((newmodel=chandev_alloc(sizeof(chandev_model_info))))
+	{
+		devreg_t *drinfo=&newmodel->drinfo;
+		newmodel->chan_type=chan_type;
+		newmodel->cu_type=cu_type;
+		newmodel->cu_model=cu_model;
+		newmodel->dev_type=dev_type;
+		newmodel->dev_model=dev_model;
+		newmodel->max_port_no=max_port_no;
+		newmodel->auto_msck_recovery=auto_msck_recovery;
+		
+		if(cu_type==-1&&dev_type==-1)
+		{
+			chandev_sprint_devinfo(buff,newmodel->cu_type,newmodel->cu_model,
+					       newmodel->dev_type,newmodel->dev_model);
+			printk(KERN_INFO"can't call s390_device_register for this device chan_type/chan_model/dev_type/dev_model %s\n",buff);
+			kfree(newmodel);
+			return;
+		}
+		/* We ignore errors as they are likely to
+		   occur owing to incompatibilities with
+		   Ingos layer 
+		*/
+		drinfo->flag=DEVREG_TYPE_DEVCHARS;
+		if(dev_model==-1)
+			drinfo->flag|=(dev_type==-1 ? DEVREG_NO_DEV_INFO:DEVREG_MATCH_DEV_TYPE);
+		if(cu_model==-1)
+			drinfo->flag|=(cu_type==-1 ? DEVREG_NO_CU_INFO:DEVREG_MATCH_CU_TYPE);
+		else if(dev_model!=-1&&cu_type!=-1)
+			drinfo->flag|=DEVREG_EXACT_MATCH;
+		drinfo->ci.hc.ctype=cu_type;
+		drinfo->ci.hc.cmode=cu_model;
+		drinfo->ci.hc.dtype=dev_type;
+		drinfo->ci.hc.dmode=dev_model;
+		drinfo->oper_func=chandev_oper_func;
+		if((err=s390_device_register(&newmodel->drinfo)))
+		{
+			chandev_sprint_devinfo(buff,newmodel->cu_type,newmodel->cu_model,
+					       newmodel->dev_type,newmodel->dev_model);
+			printk("s390_device_register failed in chandev_add_model"
+			       " this is nothing to worry about chan_type/chan_model/dev_type/dev_model %s\n",buff);
+			drinfo->oper_func=NULL;
+		}
+		chandev_add_to_list((list **)&chandev_models_head,newmodel);
+	}
+}
+
+
+void chandev_remove(chandev *member)
+{
+	chandev_free_queuemember(&chandev_head,(queue *)member);
+}
+
+
+void chandev_remove_all(void)
+{
+	chandev_free_all_queue(&chandev_head);
+}
+
+void chandev_remove_model(chandev_model_info *model)
+{
+	chandev *curr_chandev;
+
+	chandev_lock();
+	for_each(curr_chandev,(chandev *)chandev_head.head)
+		if(curr_chandev->model_info==model)
+			chandev_remove(curr_chandev);
+	if(model->drinfo.oper_func)
+		s390_device_unregister(&model->drinfo);
+	chandev_free_listmember((list **)&chandev_models_head,(list *)model);
+	chandev_unlock();
+}
+
+void chandev_remove_all_models(void)
+{
+	chandev_lock();
+	while(chandev_models_head)
+		chandev_remove_model(chandev_models_head);
+	chandev_unlock();
+}
+
+void chandev_del_model(s32 cu_type,s16 cu_model,s32 dev_type,s16 dev_model)
+{
+	chandev_model_info *curr_model;
+	
+	chandev_lock();
+	for_each(curr_model,chandev_models_head)
+		if((curr_model->cu_type==cu_type||cu_type==-1)&&
+		   (curr_model->cu_model==cu_model||cu_model==-1)&&
+		   (curr_model->dev_type==dev_type||dev_type==-1)&&
+		   (curr_model->dev_model==dev_model||dev_model==-1))
+			chandev_remove_model(curr_model);			
+	chandev_unlock();
+}
+
+static void chandev_init_default_models(void)
+{
+	/* P390/Planter 3172 emulation assume maximum 16 to be safe. */
+	chandev_add_model(lcs,0x3088,0x1,-1,-1,15,default_msck_bits);	
+
+	/* 3172/2216 Paralell the 2216 allows 16 ports per card the */
+	/* the original 3172 only allows 4 we will assume the max of 16 */
+	chandev_add_model(lcs|ctc,0x3088,0x8,-1,-1,15,default_msck_bits);
+
+	/* 3172/2216 Escon serial the 2216 allows 16 ports per card the */
+	/* the original 3172 only allows 4 we will assume the max of 16 */
+	chandev_add_model(lcs|escon,0x3088,0x1F,-1,-1,15,default_msck_bits);
+
+	/* Only 2 ports allowed on OSA2 cards model 0x60 */
+	chandev_add_model(lcs,0x3088,0x60,-1,-1,1,default_msck_bits);
+	/* qeth has relative adapter concept so we give it 16 */
+	chandev_add_model(qeth,0x1731,0x1,0x1732,0x1,15,default_msck_bits);
+	/* Osa-D we currently aren't too emotionally involved with this */
+	chandev_add_model(osad,0x3088,0x62,-1,-1,0,default_msck_bits);
+}
+
+
+void chandev_del_noauto(u16 devno)
+{
+	chandev_noauto_range *curr_noauto;
+	chandev_lock();
+	for_each(curr_noauto,chandev_noauto_head)
+		if(curr_noauto->lo_devno<=devno&&curr_noauto->hi_devno>=devno)
+			chandev_free_listmember((list **)&chandev_noauto_head,(list *)curr_noauto); 
+	chandev_unlock();
+}
+
+void chandev_del_msck(u16 devno)
+{
+	chandev_msck_range *curr_msck_range;
+	chandev_lock();
+	for_each(curr_msck_range,chandev_msck_range_head)
+		if(curr_msck_range->lo_devno<=devno&&curr_msck_range->hi_devno>=devno)
+			chandev_free_listmember((list **)&chandev_msck_range_head,(list *)curr_msck_range); 
+	chandev_unlock();
+}
+
+
+void chandev_add(s390_dev_info_t  *newdevinfo,chandev_model_info *newmodelinfo)
+{
+	chandev *new_chandev=NULL;
+
+	if((new_chandev=chandev_alloc(sizeof(chandev))))
+	{
+		new_chandev->model_info=newmodelinfo;
+		new_chandev->cu_type=newdevinfo->sid_data.cu_type; /* control unit type */
+		new_chandev->cu_model=newdevinfo->sid_data.cu_model; /* control unit model */
+		new_chandev->dev_type=newdevinfo->sid_data.dev_type; /* device type */
+		new_chandev->dev_model=newdevinfo->sid_data.dev_model; /* device model */
+		new_chandev->devno=newdevinfo->devno;
+		new_chandev->irq=newdevinfo->irq;
+		new_chandev->owned=(newdevinfo->status&DEVSTAT_DEVICE_OWNED ? TRUE:FALSE);
+		chandev_queuemember(&chandev_head,new_chandev);
+	}
+}
+
+void chandev_unregister_probe(chandev_probefunc probefunc)
+{
+	chandev_probelist *curr_probe;
+
+	chandev_lock();
+	for_each(curr_probe,chandev_probelist_head)
+		if(curr_probe->probefunc==probefunc)
+			chandev_free_listmember((list **)&chandev_probelist_head,
+						(list *)curr_probe);
+	chandev_unlock();
+}
+
+
+void chandev_reset(void)
+{
+	chandev_lock();
+	chandev_remove_all_models();
+	chandev_free_all_list((list **)&chandev_noauto_head);
+	chandev_free_all_list((list **)&chandev_msck_range_head);
+	chandev_free_all_list((list **)&chandev_force_head);
+	chandev_remove_parms(-1,FALSE);
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	use_devno_names=FALSE;
+#endif
+	chandev_conf_read=FALSE;
+	chandev_unlock();
+}
+
+
+chandev_model_info *chandev_is_chandev(int irq,s390_dev_info_t *devinfo)
+{
+	chandev_model_info *curr_model=NULL;
+	int err;
+	if((err=get_dev_info_by_irq(irq,devinfo)))
+	{
+		printk("chandev_is_chandev get_dev_info_by_irq reported err=%X on irq %d\n"
+		       "should not happen\n",err,irq);
+			return(NULL);
+	}
+	chandev_lock();
+	for_each(curr_model,chandev_models_head)
+	{
+		if(((curr_model->cu_type==devinfo->sid_data.cu_type)||(curr_model->cu_type==-1))&&
+		   ((curr_model->cu_model==devinfo->sid_data.cu_model)||(curr_model->cu_model==-1))&&
+		   ((curr_model->dev_type==devinfo->sid_data.dev_type)||(curr_model->dev_type==-1))&&
+		   ((curr_model->dev_model==devinfo->sid_data.dev_model)||(curr_model->dev_model==-1)))
+			break;
+	}
+	chandev_unlock();
+	return(curr_model);
+}
+
+void chandev_collect_devices(void)
+{
+	int curr_irq,loopcnt=0;
+	s390_dev_info_t   curr_devinfo;
+	chandev_model_info *curr_model;
+     
+
+	for(curr_irq=get_irq_first();curr_irq>=0; curr_irq=get_irq_next(curr_irq))
+	{
+		/* check read chandev
+		 * we had to do the cu_model check also because ctc devices
+		 * have the same cutype & after asking some people
+		 * the model numbers are given out pseudo randomly so
+		 * we can't just take a range of them also the dev_type & models are 0
+		 */
+		loopcnt++;
+		if(loopcnt>0x10000)
+		{
+			printk(KERN_ERR"chandev_collect_devices detected infinite loop bug in get_irq_next\n");
+			break;
+		}
+		chandev_lock();
+		if((curr_model=chandev_is_chandev(curr_irq,&curr_devinfo)))
+			chandev_add(&curr_devinfo,curr_model);
+		chandev_unlock();
+	}
+}
+
+void chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_devno,
+u16 write_devno,s16 port_protocol_no,u8 checksum_received_ip_pkts,u8 use_hw_stats)
+
+{
+	chandev_force *new_chandev_force;
+
+	if((new_chandev_force=chandev_alloc(sizeof(chandev_force))))
+	{
+		new_chandev_force->chan_type=chan_type;
+		new_chandev_force->devif_num=devif_num;
+		new_chandev_force->read_devno=read_devno;
+		new_chandev_force->write_devno=write_devno;
+		new_chandev_force->port_protocol_no=port_protocol_no;
+		new_chandev_force->checksum_received_ip_pkts=checksum_received_ip_pkts;
+		new_chandev_force->use_hw_stats=use_hw_stats;
+		chandev_add_to_list((list **)&chandev_force_head,new_chandev_force);
+	}
+}
+
+void chandev_del_force(u16 read_devno)
+{
+	chandev_force *curr_force;
+	
+	chandev_lock();
+	for_each(curr_force,chandev_force_head)
+	{
+		if(curr_force->read_devno==read_devno)
+			chandev_free_listmember((list **)&chandev_force_head,
+						(list *)curr_force);
+	}
+	chandev_unlock();
+}
+
+
+void chandev_shutdown(chandev_activelist *curr_device)
+{
+	chandev_lock();
+
+	if(curr_device->category==network_device)
+	{
+		/* unregister_netdev calls the dev->close so we shouldn't do this */
+		/* this otherwise we crash */
+		if(curr_device->unreg_dev)
+			curr_device->unreg_dev(curr_device->dev_ptr); 
+	}
+	curr_device->shutdownfunc(curr_device->dev_ptr);
+	kfree(curr_device->dev_ptr);
+	chandev_free_listmember((list **)&chandev_irqinfo_head,(list *)curr_device->read_irqinfo);
+	chandev_free_listmember((list **)&chandev_irqinfo_head,(list *)curr_device->write_irqinfo);
+	chandev_free_listmember((list **)&chandev_activelist_head,
+				(list *)curr_device);
+	chandev_unlock();
+}
+
+void chandev_shutdown_all(void)
+{
+	while(chandev_activelist_head)
+		chandev_shutdown(chandev_activelist_head);
+}
+void chandev_shutdown_by_name(char *devname)
+{
+	chandev_activelist *curr_device;
+
+	chandev_lock();
+	for_each(curr_device,chandev_activelist_head)
+		if(strcmp(devname,curr_device->devname)==0)
+		{
+			chandev_shutdown(curr_device);
+			break;
+		}
+	chandev_unlock();
+}
+
+static chandev_activelist *chandev_active(u16 devno)
+{
+	chandev_activelist *curr_device;
+
+	for_each(curr_device,chandev_activelist_head)
+		if(curr_device->read_irqinfo->devno==devno||
+		   curr_device->write_irqinfo->devno==devno)
+		{
+			return(curr_device);
+		}
+	return(NULL);
+}
+
+void chandev_shutdown_by_devno(u16 devno)
+{
+	chandev_activelist *curr_device;
+
+	chandev_lock();
+	curr_device=chandev_active(devno);
+	if(curr_device)
+		chandev_shutdown(curr_device);
+	chandev_unlock();
+}
+
+
+int chandev_pack_args(char *str)
+{
+	char *newstr=str,*next;
+	int strcnt=1;
+
+	while(*str)
+	{
+		next=str+1;
+		/*remove dead spaces */
+		if(isspace(*str)&&isspace(*next))
+		{
+			str++;
+			continue;
+		}
+		if(isspace(*str)||((*str)=='-'))
+		{
+			*str=',';
+			goto pack_dn;
+		}
+		if(((*str)==';')&&(*next))
+		{
+			strcnt++;
+			*str=0;
+		}
+	pack_dn:
+		*newstr++=*str++;
+		
+	}
+	*newstr=0;
+	return(strcnt);
+}
+
+typedef enum
+{ 
+	isnull=0,
+	isstr=1,
+	isnum=2,
+	iscomma=4,
+} chandev_strval;
+
+chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong)
+{
+	char *cur;
+	chandev_strval  retval=isnull;
+
+	int len=strlen(teststr);
+	if(strncmp(teststr,*str,len)==0)
+	{
+		*str+=len;
+		retval=isstr;
+		cur=*str;
+		*endlong=simple_strtol(cur,str,0);
+		if(cur!=*str)
+			retval|=isnum;
+		if(**str==',')
+		{
+			retval|=iscomma;
+			*str+=1;
+		}
+		else if(**str!=0)
+			retval=isnull;
+	}
+	return(retval);
+}
+
+
+int chandev_initdevice(chandev_probeinfo *probeinfo,void *dev_ptr,u8 port_no,char *devname,chandev_category category,chandev_unregfunc unreg_dev)
+{
+	chandev_activelist *newdevice;
+
+	chandev_interrupt_check();
+	if(probeinfo->newdevice!=NULL)
+	{
+		printk("probeinfo->newdevice!=NULL in chandev_initdevice for %s",devname);
+		return(-EPERM);
+	}
+	
+
+	if((newdevice=chandev_allocstr(devname,offsetof(chandev_activelist,devname))))
+	{
+		probeinfo->newdevice=newdevice;
+		chandev_lock();
+		newdevice->read_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->read_irq);
+		newdevice->write_irqinfo=chandev_get_irqinfo_by_irq(probeinfo->write_irq);
+		chandev_unlock();
+		if(newdevice->read_irqinfo==NULL||newdevice->write_irqinfo==NULL)
+		{
+			printk("chandev_initdevice, it appears that chandev_request_irq was not "
+			       "called for devname=%s read_irq=%d write_irq=%d\n",devname,probeinfo->read_irq,probeinfo->write_irq);
+			kfree(newdevice);
+			return(-EPERM);
+		}
+		newdevice->cu_type=probeinfo->cu_type;
+		newdevice->cu_model=probeinfo->cu_model;
+		newdevice->dev_type=probeinfo->dev_type;
+		newdevice->dev_model=probeinfo->dev_model;
+		newdevice->chan_type=probeinfo->chan_type;		
+		newdevice->dev_ptr=dev_ptr;
+		newdevice->port_no=port_no;
+		newdevice->category=category;
+		newdevice->unreg_dev=unreg_dev;
+		return(0);
+	}
+	return(-ENOMEM);
+}
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+struct net_device *dev, int sizeof_priv, char *basename, 
+struct net_device *(*init_netdevfunc)(struct net_device *dev, int sizeof_priv),
+void (*unreg_netdevfunc)(struct net_device *dev))
+#else
+struct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+struct device *dev, int sizeof_priv, char *basename,
+struct device *(*init_netdevfunc)(struct device *dev, int sizeof_priv),
+void (*unreg_netdevfunc)(struct device *dev))
+#endif
+{
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	struct net_device *retdevice=NULL;
+	int new_device = 0;
+#else
+	struct device *retdevice=NULL;
+#endif
+
+	if (!init_netdevfunc) 
+	{
+		printk("init_netdevfunc=NULL in chandev_initnetdevice, it should not be valid.\n");
+		return NULL;
+	}
+	if (!unreg_netdevfunc) 
+	{
+		printk("unreg_netdevfunc=NULL in chandev_initnetdevice, it should not be valid.\n");
+		return NULL;
+	}
+
+	chandev_interrupt_check();
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+        /* Allocate a device if one is not provided. */
+        if (dev == NULL) 
+	{
+		/* ensure 32-byte alignment of the private area */
+		int alloc_size = sizeof (*dev) + sizeof_priv + 31;
+
+		dev = (struct net_device *) kmalloc (alloc_size, GFP_KERNEL);
+		if (dev == NULL) 
+		{
+			printk(KERN_ERR "chandev_initnetdevice: Unable to allocate device memory.\n");
+			return NULL;
+		}
+
+		memset(dev, 0, alloc_size);
+
+		if (sizeof_priv)
+			dev->priv = (void *) (((long)(dev + 1) + 31) & ~31);
+
+		if (probeinfo->devif_num != -1) 
+			sprintf(dev->name,"%s%d",basename,(int)probeinfo->devif_num);
+		else if (use_devno_names) 
+			sprintf(dev->name,"%s0x%04x",basename,(int)probeinfo->read_devno);
+
+		new_device = 1;
+	}
+#endif
+
+	retdevice=init_netdevfunc(dev,sizeof_priv);
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	/* Register device if necessary */
+	if (retdevice && new_device)
+		register_netdev(retdevice);
+#endif
+
+	if (retdevice) 
+	{
+		if (chandev_initdevice(probeinfo,retdevice,port_no,retdevice->name,
+				      network_device,(chandev_unregfunc)unreg_netdevfunc)) 
+		{
+			unreg_netdevfunc(retdevice);
+			retdevice = NULL;
+		}
+	}
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	/* We allocated it, so we should free it on error */
+	if (!retdevice && new_device) 
+		kfree(dev);
+#endif
+
+	return retdevice;
+}
+
+
+
+
+int chandev_doprobe(chandev_force *force,chandev *read_chandev,
+chandev *write_chandev)
+{
+	chandev_probelist *probe;
+	chandev_model_info *model_info;
+	chandev_probeinfo probeinfo;
+	int               rc=-1,hint=-1;
+	chandev_activelist *newdevice;
+	chandev_probefunc  probefunc;
+	int                saved_lock_cnt;
+	chandev_parms      *curr_parms;
+
+	memset(&probeinfo,0,sizeof(probeinfo));
+	model_info=read_chandev->model_info;
+	if(read_chandev->model_info!=write_chandev->model_info||
+	   (force&&((force->chan_type&model_info->chan_type)==0))||
+	   (!force&&((read_chandev->cu_type!=write_chandev->cu_type)||
+		    (read_chandev->cu_model!=write_chandev->cu_model)||
+		    (read_chandev->dev_type!=write_chandev->dev_type)||
+		   (read_chandev->dev_model!=write_chandev->dev_model))))
+		return(-1); /* inconsistent */
+	for_each(probe,chandev_probelist_head)
+	{
+		probeinfo.chan_type=(probe->chan_type&model_info->chan_type);
+		if(probeinfo.chan_type)
+		{
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+			if(use_devno_names)
+				probeinfo.devif_num=read_chandev->devno;
+			else
+#endif
+				probeinfo.devif_num=-1;
+			probeinfo.read_irq=read_chandev->irq;
+			probeinfo.write_irq=write_chandev->irq;
+			probeinfo.read_devno=read_chandev->devno;
+			probeinfo.write_devno=write_chandev->devno;
+			probeinfo.max_port_no=model_info->max_port_no;
+			probeinfo.cu_type=read_chandev->cu_type;
+			probeinfo.cu_model=read_chandev->cu_model;
+			probeinfo.dev_type=read_chandev->dev_type;
+			probeinfo.dev_model=read_chandev->dev_model;
+			for_each(curr_parms,chandev_parms_head)
+			{
+				if(probe->chan_type==curr_parms->chan_type)
+				{
+					probeinfo.parmstr=curr_parms->parmstr;
+					break;
+				}
+			}
+			if(force)
+			{
+				probeinfo.port_protocol_no=force->port_protocol_no;
+				if(force->devif_num!=-1)
+					probeinfo.devif_num=force->devif_num;
+				probeinfo.checksum_received_ip_pkts=force->checksum_received_ip_pkts;
+				probeinfo.use_hw_stats=force->use_hw_stats;
+				
+			}
+			else
+			{
+				probeinfo.port_protocol_no=-1;
+				probeinfo.checksum_received_ip_pkts=FALSE;
+				probeinfo.use_hw_stats=FALSE;
+				if(probe->chan_type&lcs)
+				{
+					if((probeinfo.read_devno&1)||
+					   ((probeinfo.read_devno|1)!=
+					    (probeinfo.write_devno)))
+						return(-1);
+					hint=(read_chandev->devno&0xFF)>>1;
+					if(hint>model_info->max_port_no)
+					{
+				/* The card is possibly emulated e.g P/390 */
+				/* or possibly configured to use a shared */
+				/* port configured by osa-sf. */
+						hint=0;
+					}
+				}
+			}
+			probeinfo.hint_port_no=hint;
+			probefunc=probe->probefunc;
+			saved_lock_cnt=chandev_full_unlock();
+			/* We have to leave the lock go here */
+			/* as probefunctions can call schedule & */
+                        /* reenter to do a kernel thread & we may deadlock */
+			rc=probefunc(&probeinfo);
+			chandev_lock();
+			chandev_lock_cnt=saved_lock_cnt;
+			if(rc==0)
+			{
+				newdevice=probeinfo.newdevice;
+				if(newdevice)
+				{
+					newdevice->probefunc=probe->probefunc;
+					newdevice->shutdownfunc=probe->shutdownfunc;
+					newdevice->reoperfunc=probe->reoperfunc;
+					probe->devices_found++;
+					chandev_add_to_list((list **)&chandev_activelist_head,
+							    newdevice);
+					chandev_add_to_startmsck_list(&startlist_head,
+								      newdevice->devname,good,good);
+					
+				}
+				else
+				{
+					printk("chandev_initdevice either failed or wasn't called for device read_irq=0x%04x\n",probeinfo.read_irq);
+				}
+				break;
+			}
+		}
+	}
+	return(rc);
+}
+
+
+int chandev_request_irq_from_irqinfo(chandev_irqinfo *irqinfo,chandev *this_chandev)
+{
+	int retval=s390_request_irq_special(irqinfo->irq,
+				   irqinfo->handler,
+				   chandev_not_oper_handler,
+				   irqinfo->irqflags,
+				   irqinfo->devname,
+				   irqinfo->dev_id);
+	if(retval==0)
+		this_chandev->owned=TRUE;
+	return(retval);
+}
+
+void chandev_irqallocerr(chandev_irqinfo *irqinfo,int err)
+{
+	printk("chandev_probe failed to realloc irq=%d for %s err=%d\n",irqinfo->irq,irqinfo->devname,err);
+}
+
+void chandev_probe(void)
+{
+	chandev *read_chandev,*write_chandev,*curr_chandev;
+	chandev_force *curr_force;
+	chandev_noauto_range *curr_noauto;
+	chandev_activelist *curr_device;
+	chandev_irqinfo *curr_irqinfo;
+	s390_dev_info_t curr_devinfo;
+	int  err;
+	int auto_msck_recovery;
+	chandev_msck_status prevstatus;
+	chandev_msck_range *curr_msck_range;
+
+
+	chandev_interrupt_check();
+	chandev_collect_devices();
+	chandev_lock();
+	for_each(curr_irqinfo,chandev_irqinfo_head)
+	{
+		if((curr_device=chandev_get_activelist_by_irq(curr_irqinfo->irq)))
+		{
+			prevstatus=curr_irqinfo->msck_status;
+			if(curr_irqinfo->msck_status!=good)
+			{
+				curr_chandev=chandev_get_by_irq(curr_irqinfo->irq);
+				if(curr_chandev)
+				{
+					auto_msck_recovery=curr_chandev->model_info->
+						auto_msck_recovery;
+				}
+				else
+					goto remove;
+				for_each(curr_msck_range,chandev_msck_range_head)
+				{
+					if(curr_msck_range->lo_devno<=
+					   curr_irqinfo->devno&&
+					   curr_msck_range->hi_devno>=
+					   curr_irqinfo->devno)
+					{
+						auto_msck_recovery=
+							curr_msck_range->
+							auto_msck_recovery;
+						break;
+					}
+				}
+				if((1<<(curr_irqinfo->msck_status-1))&auto_msck_recovery)
+				{
+					if(curr_irqinfo->msck_status==revalidate)
+					{
+						if((get_dev_info_by_irq(curr_irqinfo->irq,&curr_devinfo)==0))
+						{
+							curr_irqinfo->devno=curr_devinfo.devno;
+							curr_irqinfo->msck_status=good;
+							goto remove;
+						}
+					}
+					else
+					{
+						if((curr_chandev=chandev_get_by_irq(curr_irqinfo->irq)))
+						{
+							/* Has the device reappeared */
+							if(curr_chandev->cu_type==curr_device->cu_type&&
+							   curr_chandev->cu_model==curr_device->cu_model&&
+							   curr_chandev->dev_type==curr_device->dev_type&&
+							   curr_chandev->dev_model==curr_device->dev_model&&
+							   curr_chandev->devno==curr_irqinfo->devno)
+							{
+								if((err=chandev_request_irq_from_irqinfo(curr_irqinfo,curr_chandev))==0)
+									curr_irqinfo->msck_status=good;
+								else
+									chandev_irqallocerr(curr_irqinfo,err);
+							}
+					
+						}
+					}
+				}
+			}
+			if(curr_irqinfo->msck_status==good&&prevstatus!=good)
+			{
+				if(curr_device->reoperfunc)
+					curr_device->reoperfunc(curr_device->dev_ptr,
+								(curr_device->read_irqinfo==curr_irqinfo),
+								prevstatus);
+				if(curr_device->category==network_device&&
+				   curr_device->write_irqinfo==curr_irqinfo)
+				{
+					net_device *dev=(net_device *)curr_device->dev_ptr;
+					if(dev->flags&IFF_UP)
+						netif_start_queue(dev);
+				}
+				chandev_add_to_startmsck_list(&mscklist_head,curr_device->devname,
+							      prevstatus,curr_irqinfo->msck_status);
+			}
+		}
+		/* This is required because the device can go & come back */
+                /* even before we realize it is gone owing to the waits in our kernel threads */
+		/* & the device will be marked as not owned but its status will be good */
+                /* & an attempt to accidently reprobe it may be done. */ 
+		remove:
+		chandev_remove(chandev_get_by_irq(curr_irqinfo->irq));
+		
+	}
+	/* extra sanity */
+	for_each(curr_chandev,(chandev *)chandev_head.head)
+		if(curr_chandev->owned)
+			chandev_remove(curr_chandev);
+	for_each(curr_force,chandev_force_head)
+	{
+		for_each(read_chandev,(chandev *)chandev_head.head)
+			if(read_chandev->devno==curr_force->read_devno&&
+				!chandev_active(curr_force->read_devno))
+			{
+				for_each(write_chandev,(chandev *)chandev_head.head)
+					if(write_chandev->devno==
+					   curr_force->write_devno&&
+					   !chandev_active(curr_force->write_devno))
+					{
+						if(chandev_doprobe(curr_force,
+								read_chandev,
+								write_chandev)==0)
+						{
+							chandev_remove(read_chandev);
+							chandev_remove(write_chandev);
+							goto chandev_probe_skip;
+						}
+					}
+			}
+	chandev_probe_skip:
+	}
+	for_each(curr_chandev,(chandev *)chandev_head.head)
+	{
+		for_each(curr_noauto,chandev_noauto_head)
+		{
+			if(curr_chandev->devno>=curr_noauto->lo_devno&&
+			   curr_chandev->devno<=curr_noauto->hi_devno)
+			{
+				chandev_remove(curr_chandev);
+				break;
+			}
+		}
+	}
+	for_each(curr_chandev,(chandev *)chandev_head.head)
+	{
+		if(curr_chandev->next&&curr_chandev->model_info==
+		   curr_chandev->next->model_info)
+		{
+			
+			chandev_doprobe(NULL,curr_chandev,curr_chandev->next);
+			curr_chandev=curr_chandev->next;
+		}
+	}
+	chandev_unlock();
+	chandev_remove_all();
+}
+
+static void chandev_not_oper_func(int irq,int status)
+{
+	chandev_irqinfo *curr_irqinfo;
+	chandev_activelist *curr_device;
+	
+	chandev_lock();
+	for_each(curr_irqinfo,chandev_irqinfo_head)
+		if(curr_irqinfo->irq==irq)
+		{
+			switch(status)
+			{
+				/* Currently defined but not used in kernel */
+				/* Despite being in specs */
+			case DEVSTAT_NOT_OPER:
+				curr_irqinfo->msck_status=not_oper;
+				break;
+#ifdef DEVSTAT_NO_PATH
+				/* Kernel hasn't this defined currently. */
+				/* Despite being in specs */
+			case DEVSTAT_NO_PATH:
+				curr_irqinfo->msck_status=no_path;
+				break;
+#endif
+			case DEVSTAT_REVALIDATE:
+				curr_irqinfo->msck_status=revalidate;
+				break;
+			case DEVSTAT_DEVICE_GONE:
+				curr_irqinfo->msck_status=gone;
+				break;
+			}
+			for_each(curr_device,chandev_activelist_head)
+			{
+				if(curr_device->write_irqinfo==curr_irqinfo)
+				{
+					if(curr_device->category==network_device)
+					{
+						net_device *dev=(net_device *)curr_device->dev_ptr;
+						if(dev->flags&IFF_UP)
+							netif_stop_queue(dev);
+					}
+				}
+				break;
+			}
+			break;
+		}
+	chandev_unlock();
+}
+
+
+static chandev_task_retval chandev_msck_task(void *unused)
+{
+	int loopcnt,not_oper_probe_required=FALSE;
+	wait_queue_head_t    wait;
+	chandev_not_oper_struct *new_not_oper;
+
+	chandev_daemonize("chandev_msck_kernel_thread",0,TRUE);
+	/* This loop exists because machine checks tend to come in groups & we have
+           to wait for the other devnos to appear also */
+	init_waitqueue_head(&wait);
+	for(loopcnt=0;loopcnt<10||(jiffies-chandev_last_machine_check)<HZ;loopcnt++)
+	{
+		sleep_on_timeout(&wait,HZ);
+	}
+	atomic_set(&chandev_msck_thread_lock,1);
+	while(!atomic_compare_and_swap(TRUE,FALSE,&chandev_new_msck));
+	{
+		chandev_probe();
+	}
+	while(TRUE)
+	{
+		
+		unsigned long        flags; 
+		spin_lock_irqsave(&chandev_not_oper_spinlock,flags);
+		new_not_oper=(chandev_not_oper_struct *)dequeue_head(&chandev_not_oper_head);
+		spin_unlock_irqrestore(&chandev_not_oper_spinlock,flags);
+		if(new_not_oper)
+		{
+			chandev_not_oper_func(new_not_oper->irq,new_not_oper->status);
+			not_oper_probe_required=TRUE;
+			kfree(new_not_oper);
+		}
+		else
+			break;
+	}
+	if(not_oper_probe_required)
+		chandev_probe();
+	chandev_task_return(0);
+}
+
+
+
+#if CHANDEV_USE_KERNEL_THREADS
+static void chandev_start_msck_thread(void *unused)
+{
+	/* tq_scheduler sometimes leaves interrupts disabled from do bottom half */
+	__sti();
+	kernel_thread((int (*)(void *))chandev_msck_task,
+		      (void*)NULL,0);
+}
+#endif
+
+
+
+static char *argstrs[]=
+{
+	"noauto",
+	"del_noauto",
+	"ctc",
+	"escon",
+	"lcs",
+	"osad",
+	"qeth",
+	"claw",
+	"add_parms",
+	"del_parms",
+	"del_force",
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	"use_devno_names",
+	"dont_use_devno_names",
+#endif
+	"add_model",
+	"del_model",
+	"auto_msck",
+	"del_auto_msck",
+	"del_all_models",
+	"reset_conf_clean",
+	"reset_conf",
+	"shutdown",
+	"reprobe",
+	"unregister_probe",
+	"read_conf",
+	"dont_read_conf",
+};
+
+typedef enum
+{
+	stridx_mult=256,
+	first_stridx=0,
+	noauto_stridx=first_stridx,
+	del_noauto_stridx,
+	ctc_stridx,
+	escon_stridx,
+	lcs_stridx,
+	osad_stridx,
+        qeth_stridx,
+	claw_stridx,
+	add_parms_stridx,
+	del_parms_stridx,
+	del_force_stridx,
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	use_devno_names_stridx,
+	dont_use_devno_names_stridx,
+#endif
+	add_model_stridx,
+	del_model_stridx,
+	auto_msck_stridx,
+	del_auto_msck_stridx,
+	del_all_models_stridx,
+	reset_conf_clean_stridx,
+	reset_conf_stridx,
+	shutdown_stridx,
+	reprobe_stridx,
+	unregister_probe_stridx,
+	read_conf_stridx,
+	dont_read_conf_stridx,
 	last_stridx,
 } chandev_str_enum;
 
@@ -281,303 +1866,423 @@
 {
 	chandev_noauto_range *new_range;
 
-	if((new_range=chandev_alloc_listmember(
-		(list **)&chandev_noauto_head,sizeof(chandev_noauto_range))))
+	if((new_range=chandev_alloc(sizeof(chandev_noauto_range))))
+	{
+		new_range->lo_devno=lo_devno;
+		new_range->hi_devno=hi_devno;
+		chandev_add_to_list((list **)&chandev_noauto_head,new_range);
+	}
+}
+
+
+void chandev_add_msck_range(u16 lo_devno,u16 hi_devno,int auto_msck_recovery)
+{
+	chandev_msck_range *new_range;
+
+	if((new_range=chandev_alloc(sizeof(chandev_msck_range))))
 	{
 		new_range->lo_devno=lo_devno;
 		new_range->hi_devno=hi_devno;
+		new_range->auto_msck_recovery=auto_msck_recovery;
+		chandev_add_to_list((list **)&chandev_msck_range_head,new_range);
 	}
 }
 
+
+
 static char chandev_keydescript[]=
-"chan_type key bitfield\nctc=0x1,escon=0x2,lcs=0x4,lcs=0x4,osad=0x8,claw=0x16\n";
+"\nchan_type key bitfield ctc=0x1,escon=0x2,lcs=0x4,osad=0x8,qeth=0x10,claw=0x20\n";
+
+
+#if  CONFIG_ARCH_S390X
+/* We need this as we sometimes use this to evaluate pointers */
+typedef long chandev_int; 
+#else
+typedef int chandev_int;
+#endif
+
 
-static void chandev_print_args(void)
+#if (LINUX_VERSION_CODE<KERNEL_VERSION(2,3,0)) || (CONFIG_ARCH_S390X)
+/*
+ * Read an int from an option string; if available accept a subsequent
+ * comma as well.
+ *
+ * Return values:
+ * 0 : no int in string
+ * 1 : int found, no subsequent comma
+ * 2 : int found including a subsequent comma
+ */
+static chandev_int chandev_get_option(char **str,chandev_int *pint)
 {
-	printk("valid chandev arguments are" 
-                "<> indicate optional parameters | indicate a choice.\n");
-	printk("noauto,<lo_devno>,<hi_devno>\n"
-               "don't probe a range of device numbers for channel devices\n");
-	printk("lcs|ctc|escon<devif_num>,read_devno,write_devno,<port_no>,"
-	       "<do_ip_checksumming>,<use_hw_stats>\n");
-	printk("e.g. ctc0,0x7c00,0x7c01,-1,0,0\n");
-	printk("     tells the channel layer to force ctc0 if detected to use\n"
-	       "     cuu's 7c00 & 7c01 port ( rel adapter no ) is invalid for\n"
-	       "     ctc's so use -1 don't do checksumming on received ip\n"
-               "     packets & as ctc doesn't have hardware stats ignore this\n"
-               "     parameter\n\n");
-	printk("del_force read_devno\n"
-       "delete a forced channel device from force list.\n");
-	printk("use_devno_names, tells the channel layer to assign device\n"
-               "names based on the read channel cuu number\n"
-	       "e.g. a token ring read channel 0x7c00 would have an interface"
-	       "called tr0x7c00 this avoids name collisions on devices.");
-	printk("add_model chan_type cu_model max_port no\n"
-	       "tells the channel layer to probe for the device described\n");
-	printk("%s use max_port_no of 0 for devices where this field "
-       "is invalid.\n",chandev_keydescript);
-	printk("del_model cu_type cu_model\n");
-	printk("del_all_models\n");
+    char *cur = *str;
+
+    if (!cur || !(*cur)) return 0;
+    *pint = simple_strtol(cur,str,0);
+    if (cur==*str) return 0;
+    if (**str==',') {
+        (*str)++;
+        return 2;
+    }
+
+    return 1;
 }
 
+static char *chandev_get_options(char *str, int nints, chandev_int *ints)
+{
+	int res,i=1;
+
+    while (i<nints) {
+        res = chandev_get_option(&str, ints+i);
+        if (res==0) break;
+        i++;
+        if (res==1) break;
+    }
+	ints[0] = i-1;
+	return(str);
+}
+#else
+#define chandev_get_option get_option
+#define chandev_get_options get_options
+#endif
 
-static int chandev_setup(char *str)
+static int chandev_setup(char *instr,char *errstr,int lineno)
 {
 	chandev_strval   val=isnull;
 	chandev_str_enum stridx;
 	long             endlong;
 	chandev_type     chan_type;
-#define CHANDEV_MAX_EXTRA_INTS 5
-	int ints[CHANDEV_MAX_EXTRA_INTS+1];
+	char             *str,*currstr,*interpretstr=NULL;
+	int              cnt,strcnt;
+#define CHANDEV_MAX_EXTRA_INTS 8
+	chandev_int ints[CHANDEV_MAX_EXTRA_INTS+1];
 	memset(ints,0,sizeof(ints));
-	chandev_pack_args(str);
-	for(stridx=first_stridx;stridx<last_stridx;stridx++)
-		if((val=chandev_strcmp(argstrs[stridx],&str,&endlong)))
-			break;
-	if(val)
+	currstr=alloca(strlen(instr)+1);
+	strcpy(currstr,instr);
+	strcnt=chandev_pack_args(currstr);
+	for(cnt=1;cnt<=strcnt;cnt++)
 	{
-		if(val&iscomma)
-			get_options(str,CHANDEV_MAX_EXTRA_INTS,ints);
-		else
-			ints[0]=0;
-		val=(((chandev_strval)stridx)*stridx_mult)+(val&~isstr);
-		switch(val)
-		{
-		case noauto_stridx*stridx_mult:
-		case (noauto_stridx*stridx_mult)|iscomma:
-			switch(ints[0])
-			{
-			case 0: 
-				chandev_free_all((list **)&chandev_noauto_head);
-				chandev_add_noauto(0,0xffff);
-				break;
-			case 1:
-				ints[2]=ints[1];
-			case 2:
-				chandev_add_noauto(ints[1],ints[2]);
-			
+		interpretstr=currstr;
+		for(stridx=first_stridx;stridx<last_stridx;stridx++)
+		{
+			str=currstr;
+			if((val=chandev_strcmp(argstrs[stridx],&str,&endlong)))
+				break;
+		}
+		currstr=str;
+		if(val)
+		{
+			if(val&iscomma)
+			{
+				if(stridx==add_parms_stridx&&(val==(isstr|iscomma)))
+				{
+					str=currstr;
+					if(chandev_get_option(&str,&ints[0])==2)
+					{
+						chandev_add_parms(ints[0],str);
+						currstr=str+strlen(str)+1;
+						continue;
+					}
+					else
+						goto BadArgs;
+				}
+				else
+					currstr=chandev_get_options(str,CHANDEV_MAX_EXTRA_INTS,ints)+1;
 			}
-			break;
-		case (ctc_stridx*stridx_mult)|isnum|iscomma:
-		case (escon_stridx*stridx_mult)|isnum|iscomma:
-		case (lcs_stridx*stridx_mult)|isnum|iscomma:
+			else
+			{
+				ints[0]=0;
+				currstr++;
+			}
+			val=(((chandev_strval)stridx)*stridx_mult)+(val&~isstr);
 			switch(val)
 			{
-			case (ctc_stridx*stridx_mult)|isnum|iscomma:
-				chan_type=ctc;
+			case noauto_stridx*stridx_mult:
+			case (noauto_stridx*stridx_mult)|iscomma:
+				switch(ints[0])
+				{
+				case 0: 
+					chandev_free_all_list((list **)&chandev_noauto_head);
+					chandev_add_noauto(0,0xffff);
+					break;
+				case 1:
+					ints[2]=ints[1];
+				case 2:
+					chandev_add_noauto(ints[1],ints[2]);
+					break;
+				default:
+					goto BadArgs;
+				}
 				break;
-			case (escon_stridx*stridx_mult)|isnum|iscomma:
-				chan_type=escon;
+			case (auto_msck_stridx*stridx_mult)|iscomma:
+				switch(ints[0])
+				{
+				case 1:
+					chandev_free_all_list((list **)&chandev_msck_range_head);
+					chandev_add_msck_range(0,0xffff,ints[1]);
+					break;
+				case 2:
+					chandev_add_msck_range(ints[1],ints[1],ints[2]);
+					break;
+				case 3:
+					chandev_add_msck_range(ints[1],ints[2],ints[3]);
+					break;
+				default:
+					goto BadArgs;
+					
+				}
+			case del_auto_msck_stridx*stridx_mult:
+			case (del_auto_msck_stridx*stridx_mult)|iscomma:
+				switch(ints[0])
+				{
+				case 0:
+					chandev_free_all_list((list **)&chandev_msck_range_head);
+					break;
+				case 1:
+					chandev_del_msck(ints[1]);
+				default:
+					goto BadArgs;
+				}
+			case del_noauto_stridx*stridx_mult:
+				chandev_free_all_list((list **)&chandev_noauto_head);
 				break;
+			case (del_noauto_stridx*stridx_mult)|iscomma:
+				if(ints[0]==1)
+					chandev_del_noauto(ints[1]);
+				else
+					goto BadArgs;
+				break;
+			case (ctc_stridx*stridx_mult)|isnum|iscomma:
+			case (escon_stridx*stridx_mult)|isnum|iscomma:
 			case (lcs_stridx*stridx_mult)|isnum|iscomma:
-				chan_type=lcs;
+			case (osad_stridx*stridx_mult)|isnum|iscomma:
+			case (qeth_stridx*stridx_mult)|isnum|iscomma:
+			case (claw_stridx*stridx_mult)|isnum|iscomma:
+				switch(val)
+				{
+				case (ctc_stridx*stridx_mult)|isnum|iscomma:
+					chan_type=ctc;
+					break;
+				case (escon_stridx*stridx_mult)|isnum|iscomma:
+					chan_type=escon;
+					break;
+				case (lcs_stridx*stridx_mult)|isnum|iscomma:
+					chan_type=lcs;
+					break;
+				case (osad_stridx*stridx_mult)|isnum|iscomma:
+					chan_type=osad;
+					break;
+				case (qeth_stridx*stridx_mult)|isnum|iscomma:
+					chan_type=qeth;
+					break;
+				case (claw_stridx*stridx_mult)|isnum|iscomma:
+					chan_type=claw;
+					break;
+				default:
+					goto BadArgs;
+				}
+				chandev_add_force(chan_type,endlong,ints[1],ints[2],
+						  ints[3],ints[4],ints[5]);
 				break;
-			default:
-				goto BadArgs;
-			}
-			chandev_add_force(chan_type,endlong,ints[1],ints[2],
-					  ints[3],ints[4],ints[5]);
-			break;
-		case (del_force_stridx*stridx_mult)|iscomma:
-			if(ints[0]!=1)
-				goto BadArgs;
-			chandev_del_force(ints[1]);
-			break;
-		case (use_devno_names_stridx*stridx_mult):
-			use_devno_names=1;
-			break;
-		case (dont_use_devno_names_stridx*stridx_mult):
-			use_devno_names=0;
-	        case (add_model_stridx*stridx_mult)|iscomma:
-			if(ints[0]<3)
-				goto BadArgs;
-			if(ints[0]==3)
-			{
+			case (del_parms_stridx*stridx_mult):
+				ints[1]=-1;
+			case (del_parms_stridx*stridx_mult)|iscomma:
+				if(ints[0]==1)
+					ints[2]=FALSE;
+				if(ints[0]>2)
+					goto BadArgs;
+				chandev_remove_parms(ints[1],ints[2]);
+				break;
+			case (del_force_stridx*stridx_mult)|iscomma:
+				if(ints[0]!=1)
+					goto BadArgs;
+				chandev_del_force(ints[1]);
+				break;
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+			case (use_devno_names_stridx*stridx_mult):
+				use_devno_names=1;
+				break;
+			case (dont_use_devno_names_stridx*stridx_mult):
+				use_devno_names=0;
+#endif
+			case (add_model_stridx*stridx_mult)|iscomma:
+				if(ints[0]<3)
+					goto BadArgs;
+				if(ints[0]==3)
+					ints[4]=-1;
+				if(ints[0]<=4)
+					ints[5]=-1;
+				if(ints[0]<=5)
+					ints[6]=-1;
+				if(ints[0]<=6)
+					ints[7]=default_msck_bits;
+				ints[0]=7;
+				chandev_add_model(ints[1],ints[2],ints[3],
+						  ints[4],ints[5],ints[6],ints[7]);
+				break;
+			case (del_model_stridx*stridx_mult)|iscomma:
+				if(ints[0]<2||ints[0]>4)
+					goto BadArgs;
+				if(ints[0]<3)
+					ints[3]=-2;
+				if(ints[0]<4)
+					ints[4]=-2;
 				ints[0]=4;
-				ints[4]=-1;
-			}
-			chandev_add_model(ints[1],ints[2],ints[3],ints[4]);
-		break;
-		case (del_model_stridx*stridx_mult)|iscomma:
-			if(ints[0]!=2)
+				chandev_del_model(ints[1],ints[2],ints[3],ints[4]);
+				break;
+			case del_all_models_stridx*stridx_mult:
+				chandev_remove_all_models();
+				break;
+			case reset_conf_stridx*stridx_mult:
+				chandev_reset();
+				chandev_init_default_models();
+				break;
+			case reset_conf_clean_stridx*stridx_mult:
+				chandev_reset();
+				break;
+			case shutdown_stridx*stridx_mult:
+				chandev_shutdown_all();
+				break;
+			case (shutdown_stridx*stridx_mult)|iscomma:
+				switch(ints[0])
+				{
+				case 0:
+					if(strlen(str))
+						chandev_shutdown_by_name(str);
+					else
+						goto BadArgs;
+					break;
+				case 1:
+					chandev_shutdown_by_devno(ints[1]);
+					break;
+				default:
+					goto BadArgs;
+				}
+				break;
+			case reprobe_stridx*stridx_mult:
+				chandev_probe();
+				break;
+			case unregister_probe_stridx*stridx_mult:
+				chandev_free_all_list((list **)&chandev_probelist_head);
+				break;
+			case (unregister_probe_stridx*stridx_mult)|iscomma:
+				if(ints[0]!=1)
+					goto BadArgs;
+				chandev_unregister_probe((chandev_probefunc)ints[1]);
+				break;
+			case read_conf_stridx*stridx_mult:
+				chandev_read_conf();
+				break;
+			case dont_read_conf_stridx*stridx_mult:
+				chandev_conf_read=TRUE;
+				break;
+			default:
 				goto BadArgs;
-			chandev_del_model(ints[1],ints[2]);
-			break;
-		case del_all_models_stridx*stridx_mult:
-			chandev_remove_all_models();
-			break;
-		default:
+			}		
+		}
+		else
 			goto BadArgs;
-		}		
 	}
 	return(1);
  BadArgs:
-	chandev_print_args();
+	printk("chandev_setup bad argument %s",instr);
+	if(errstr)
+	{
+                printk("%s %d interpreted as %s",errstr,lineno,interpretstr);
+		if(strcnt>1)
+			printk(" before semicolon no %d",cnt);
+	}
+	printk(".\n Type man chandev for more info.\n\n");
 	return(0);
 }
-
-__setup("chandev=",chandev_setup);
-
-int chandev_doprobe(chandev_force *force,chandev *read_chandev,
-chandev *write_chandev)
+#define CHANDEV_KEYWORD "chandev="
+static int chandev_setup_bootargs(char *str,int paramno)
 {
-	chandev_probelist *probe;
-	chandev_model_info *model_info;
-	chandev_probeinfo probeinfo;
-	int  retval=-1,hint=-1;
+	int len;
+
+	char *copystr;
+	for(len=0;str[len]!=0&&!isspace(str[len]);len++);
+	copystr=alloca(len+1);
+	strncpy(copystr,str,len);
+	copystr[len]=0;
+	if(chandev_setup(copystr,"at "CHANDEV_KEYWORD" bootparam no",paramno)==0)
+		return(0);
+	return(len);
 
-	model_info=read_chandev->model_info;
-	if(read_chandev->model_info!=write_chandev->model_info||
-	   (force&&((force->chan_type&model_info->chan_type)==0)))
-		return(-1); /* inconsistent */
-	for(probe=chandev_probelist_head;
-	    probe!=NULL;
-	    probe=probe->next)
-	{
-		if(probe->chan_type&model_info->chan_type)
-		{
-			if(use_devno_names)
-				probeinfo.devif_num=read_chandev->devno;
-			else
-				probeinfo.devif_num=-1;
-			probeinfo.read_irq=read_chandev->irq;
-			probeinfo.write_irq=write_chandev->irq;
-			
-			probeinfo.max_port_no=model_info->max_port_no;
-			if(force)
-			{
-				probeinfo.forced_port_no=force->port_no;
-				if(force->devif_num!=-1)
-					probeinfo.devif_num=force->devif_num;
-				probeinfo.do_ip_checksumming=force->do_ip_checksumming;
-				probeinfo.use_hw_stats=force->use_hw_stats;
-				
-			}
-			else
-			{
-				probeinfo.forced_port_no=-1;
-				probeinfo.do_ip_checksumming=FALSE;
-				probeinfo.use_hw_stats=FALSE;
-				if(probe->chan_type&lcs)
-				{
-					hint=(read_chandev->devno&0xFF)>>1;
-					if(hint>model_info->max_port_no)
-					{
-				/* The card is possibly emulated e.g P/390 */
-				/* or possibly configured to use a shared */
-				/* port configured by osa-sf. */
-						hint=0;
-					}
-				}
-			}
-			probeinfo.hint_port_no=hint;
-			retval=probe->probefunc(&probeinfo);
-			if(retval==0)
-				break;
-		}
-	}
-	return(retval);
 }
 
-void chandev_probe(void)
+/*
+  We can't parse using a __setup function as kmalloc isn't available
+  at this time.
+ */
+static void __init chandev_parse_args(void)
 {
-	chandev *read_chandev,*write_chandev,*curr_chandev;
-	chandev_force *curr_force;
-	chandev_noauto_range *curr_noauto;
+#define CHANDEV_KEYWORD "chandev="
+	extern char saved_command_line[];
+	int cnt,len,paramno=1;
 
-	chandev_collect_devices();
-	for(curr_force=chandev_force_head;curr_force!=NULL;
-		    curr_force=curr_force->next)
-	{
-		for(read_chandev=chandev_head;
-		    read_chandev!=NULL;
-		    read_chandev=read_chandev->next)
-			if(read_chandev->devno==curr_force->read_devno)
-			{
-				for(write_chandev=chandev_head;
-				    write_chandev!=NULL;
-				    write_chandev=write_chandev->next)
-					if(write_chandev->devno==
-					   curr_force->write_devno)
-					{
-						if(chandev_doprobe(curr_force,
-								read_chandev,
-								write_chandev)==0)
-						{
-							chandev_remove(read_chandev);
-							chandev_remove(write_chandev);
-							goto chandev_probe_skip;
-						}
-					}
-			}
-	chandev_probe_skip:
-	}
-	for(curr_chandev=chandev_head;
-		    curr_chandev!=NULL;
-		    curr_chandev=curr_chandev->next)
-	{
-		for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL;
-		    curr_noauto=curr_noauto->next)
-		{
-			if(curr_chandev->devno>=curr_noauto->lo_devno&&
-			   curr_chandev->devno<=curr_noauto->hi_devno)
-			{
-				chandev_remove(curr_chandev);
-				break;
-			}
-		}
-	}
-	for(curr_chandev=chandev_head;curr_chandev!=NULL;
-	    curr_chandev=curr_chandev->next)
+	len=strlen(saved_command_line)-sizeof(CHANDEV_KEYWORD);
+	for(cnt=0;cnt<len;cnt++)
 	{
-		if(curr_chandev->next&&curr_chandev->model_info==
-		   curr_chandev->next->model_info)
+		if(strncmp(&saved_command_line[cnt],CHANDEV_KEYWORD,
+			   sizeof(CHANDEV_KEYWORD)-1)==0)
 		{
-			
-			chandev_doprobe(NULL,curr_chandev,curr_chandev->next);
-			curr_chandev=curr_chandev->next;
+			cnt+=(sizeof(CHANDEV_KEYWORD)-1);	
+			cnt+=chandev_setup_bootargs(&saved_command_line[cnt],paramno);
+			paramno++;
 		}
 	}
-	chandev_remove_all();
 }
 
 int chandev_do_setup(char *buff,int size)
 {
-	int curr,startline=0,comment=FALSE,newline=FALSE,oldnewline=TRUE;
-	int rc=1;
+	int curr,comment=FALSE,newline=FALSE,oldnewline=TRUE;
+	char *startline=NULL,*endbuff=&buff[size];
+
+	int lineno=0;
 
-	buff[size]=0;
-	for(curr=0;curr<=size;curr++)
+	*endbuff=0;
+	for(;buff<=endbuff;curr++,buff++)
 	{
-		if(buff[curr]=='#')
-		{
-			comment=TRUE;
-			newline=FALSE;
-		}
-		else if(buff[curr]==10||buff[curr]==13||buff[curr]==0)
+		if(*buff==0xa||*buff==0xc||*buff==0)
 		{
-			buff[curr]=0;
-			comment=FALSE;
+			if(*buff==0xa||*buff==0)
+				lineno++;
+			*buff=0;
 			newline=TRUE;
 		}
-		if(comment==FALSE&&curr>startline
-		   &&((oldnewline==TRUE&&newline==FALSE)||curr==size))
+		else
+		{ 
+			newline=FALSE;
+			if(*buff=='#')
+				comment=TRUE;
+		}
+		if(comment==TRUE)
+			*buff=0;
+		if(startline==NULL&&isalpha(*buff))
+			startline=buff;
+		if(startline&&(buff>startline)&&(oldnewline==FALSE)&&(newline==TRUE))
 		{
-			if((rc=chandev_setup(&buff[startline]))==0)
-				break;
-			startline=curr+1;
+			if((chandev_setup(startline," on line no",lineno))==0)
+				return(-EINVAL);
+			startline=NULL;
 		}
+		if(newline)
+			comment=FALSE;
 	        oldnewline=newline;
 	}
-	return(rc);
+	return(0);
 }
-void chandev_read_conf(void)
+
+
+static void chandev_read_conf(void)
 {
 #define CHANDEV_FILE "/etc/chandev.conf"
 	struct stat statbuf;
 	char        *buff;
 	int         curr,left,len,fd;
 
+	if(in_interrupt()||current->fs->root==NULL)
+		return;
 	chandev_conf_read=TRUE;
 	set_fs(KERNEL_DS);
 	if(stat(CHANDEV_FILE,&statbuf)==0)
@@ -606,34 +2311,12 @@
 	set_fs(USER_DS);
 }
 
-void chandev_register_and_probe(chandev_probefunc probefunc,chandev_type chan_type)
+static void chandev_read_conf_if_necessary(void)
 {
-	chandev_probelist *new_probe;
 	if(!chandev_conf_read)
 		chandev_read_conf();
-	if((new_probe=chandev_alloc_listmember((list **)&
-		chandev_probelist_head,sizeof(chandev_probelist))))
-	{
-		new_probe->probefunc=probefunc;
-		new_probe->chan_type=chan_type;
-		chandev_probe();
-	}
-}
-
-void chandev_unregister(chandev_probefunc probefunc)
-{
-	 chandev_probelist *curr_probe=NULL;
-		
-	for(curr_probe=chandev_probelist_head;curr_probe!=NULL;
-		    curr_probe=curr_probe->next)
-	{
-		if(curr_probe->probefunc==probefunc)
-			chandev_free_listmember((list **)&chandev_probelist_head,
-						(list *)curr_probe);
-	}
 }
 
-
 #ifdef CONFIG_PROC_FS
 #define chandev_printf(exitchan,args...)     \
 splen=sprintf(spbuff,##args);                \
@@ -645,53 +2328,222 @@
 if(currlen>=length)                          \
        goto exitchan;
 
-
+void sprintf_msck(char *buff,int auto_msck_recovery)
+{
+	chandev_msck_status idx;
+	int first_time=TRUE;
+	buff[0]=0;
+	for(idx=first_msck;idx<last_msck;idx++)
+	{
+		if((1<<(idx-1))&auto_msck_recovery)
+		{
+			buff+=sprintf(buff,"%s%s",(first_time ? "":","),
+				      msck_status_strs[idx]);
+			first_time=FALSE;
+		}
+	}
+}
 
 static int chandev_read_proc(char *page, char **start, off_t offset,
 			  int length, int *eof, void *data)
 {
 	char *spbuff=*start=page;
-	int    currlen=0,splen;
+	int    currlen=0,splen=0;
 	off_t  spoffset=0;
 	chandev_model_info *curr_model;
 	chandev_noauto_range *curr_noauto;
 	chandev_force *curr_force;
+	chandev_activelist *curr_device;
+	chandev_probelist  *curr_probe;
+	chandev_msck_range *curr_msck_range;
+	s390_dev_info_t   curr_devinfo;
+	int pass,chandevs_detected,curr_irq,loopcnt;
+	chandev_irqinfo *read_irqinfo,*write_irqinfo;
+	char buff[40],buff2[80];    
+
+	chandev_lock();
+	chandev_read_conf_if_necessary();
+	chandev_printf(chan_exit,"\n%s\n"
+		       "*'s for cu/dev type/models indicate don't cares\n",chandev_keydescript);
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+	chandev_printf(chan_exit,"\nuse_devno_names: %s\n\n",use_devno_names ? "on":"off");
+#endif
+	if(chandev_models_head)
+	{
+		chandev_printf(chan_exit,"Channels enabled for detection\n");      
+		chandev_printf(chan_exit,"  chan     cu      cu     dev   dev    max     auto recovery\n");
+		chandev_printf(chan_exit,"  type    type    model  type  model  port_no.      type    \n");
+		chandev_printf(chan_exit,"============================================================\n");
+		for_each(curr_model,chandev_models_head)
+		{
+			
+			
+			chandev_sprint_devinfo(buff,curr_model->cu_type,
+					       curr_model->cu_model,
+					       curr_model->dev_type,
+					       curr_model->dev_model);
+			sprintf_msck(buff2,curr_model->auto_msck_recovery);
+			chandev_printf(chan_exit,"  0x%02x  %s%3d %s\n",
+				       curr_model->chan_type,buff,
+				       (int)curr_model->max_port_no,buff2);         
+		}
+	}
+        
+	if(chandev_noauto_head)
+	{
+		chandev_printf(chan_exit,"\nNo auto devno ranges\n");
+		chandev_printf(chan_exit,"   From        To   \n");
+		chandev_printf(chan_exit,"====================\n");
+		for_each(curr_noauto,chandev_noauto_head)
+		{
+			chandev_printf(chan_exit,"  0x%04x     0x%04x\n",
+				       curr_noauto->lo_devno,
+				       curr_noauto->hi_devno);
+		}
+	}
+	if(chandev_msck_range_head)
+	{
+		
+		chandev_printf(chan_exit,"\nAutomatic machine check recovery devno ranges\n");
+		chandev_printf(chan_exit,"   From        To   automatic recovery type\n");
+		chandev_printf(chan_exit,"===========================================\n");
+		for_each(curr_msck_range,chandev_msck_range_head)
+		{
+			sprintf_msck(buff2,curr_msck_range->auto_msck_recovery);
+			chandev_printf(chan_exit,"  0x%04x     0x%04x %s\n",
+				       curr_msck_range->lo_devno,
+				       curr_msck_range->hi_devno,buff2)
+		}
+	}
+	if(chandev_force_head)
+	{
+		chandev_printf(chan_exit,"\nForced devices\n");
+		chandev_printf(chan_exit,"  chan defif read   write     port         ip    hw\n");
+		chandev_printf(chan_exit,"  type  num  devno  devno  protocol no.  chksum stats\n");
+		chandev_printf(chan_exit,"======================================================\n");
+		for_each(curr_force,chandev_force_head)
+		{
+			chandev_printf(chan_exit,"  0x%02x  %3d  0x%04x 0x%04x       %3d       %1d    %1d\n",
+				       curr_force->chan_type,curr_force->devif_num,
+				       curr_force->read_devno,curr_force->write_devno,
+				       curr_force->port_protocol_no,curr_force->checksum_received_ip_pkts,
+				       curr_force->use_hw_stats);
+		}
+	}
+	if(chandev_probelist_head)
+	{
+#if CONFIG_ARCH_S390X
+		chandev_printf(chan_exit,"\nRegistered probe functions\n"
+			       		 "probefunc            shutdownfunc         reoperfunc         chan  devices\n"
+                                         "                                                             type   found\n"
+			                 "==========================================================================\n");
+#else
+		chandev_printf(chan_exit,"\nRegistered probe functions\n"
+			                 "probefunc   shutdownfunc  reoperfunc chan  devices\n"
+                                         "                                     type   found\n"
+			                 "==================================================\n");
+#endif
+		for_each(curr_probe,chandev_probelist_head)
+		{
+			chandev_printf(chan_exit,"0x%p   0x%p   0x%p   0x%02x      %d\n",
+				       curr_probe->probefunc,
+				       curr_probe->shutdownfunc,
+				       curr_probe->reoperfunc,
+				       curr_probe->chan_type,
+				       curr_probe->devices_found);
+		}
+	}
+	if(chandev_activelist_head)
+	{
+#if CONFIG_ARCH_S390X
+		chandev_printf(chan_exit,
+			       "\nInitialised Devices\n"
+			       " read   write  read   write chan port  dev             dev        read msck   write msck\n"
+			       " irq    irq    devno  devno type no.   ptr             name        status      status   \n"
+			       "========================================================================================\n");
+#else
+		chandev_printf(chan_exit,
+			       "\nInitialised Devices\n"
+			       " read   write  read   write chan port  dev     dev        read msck   write msck\n"
+			       " irq    irq    devno  devno type no.   ptr     name        status      status   \n"
+			       "================================================================================\n");
+#endif
+		/* We print this list backwards for cosmetic reasons */
+		for(curr_device=chandev_activelist_head;
+		    curr_device->next!=NULL;curr_device=curr_device->next);
+		while(curr_device)
+		{
+			read_irqinfo=curr_device->read_irqinfo;
+			write_irqinfo=curr_device->write_irqinfo;
+			chandev_printf(chan_exit,
+				       "0x%04x 0x%04x 0x%04x 0x%04x 0x%02x %2d 0x%p %-10s   %-12s %-12s\n",
+				       curr_device->read_irqinfo->irq,curr_device->write_irqinfo->irq,
+				       (int)read_irqinfo->devno,
+				       (int)write_irqinfo->devno,
+				       curr_device->chan_type,(int)curr_device->port_no,
+				       curr_device->dev_ptr,curr_device->devname,
+				       msck_status_strs[read_irqinfo->msck_status],
+				       msck_status_strs[write_irqinfo->msck_status]);
+			get_prev((list *)chandev_activelist_head,
+				 (list *)curr_device,
+				 (list **)&curr_device);
+		}
+	}
+	chandevs_detected=FALSE;
+	for(pass=FALSE;pass<=TRUE;pass++)
+	{
+		if(pass&&chandevs_detected)
+		{
+			chandev_printf(chan_exit,"\nchannels detected\n");
+			chandev_printf(chan_exit,"              chan    cu    cu   dev    dev   in   chandev\n");
+			chandev_printf(chan_exit,"  irq  devno  type   type  model type  model  use    reg.\n");
+			chandev_printf(chan_exit,"==========================================================\n");
+		}
+		for(curr_irq=get_irq_first(),loopcnt=0;curr_irq>=0; curr_irq=get_irq_next(curr_irq),loopcnt++)
+		{
+			if(loopcnt>0x10000)
+			{
+				printk(KERN_ERR"chandev_read_proc detected infinite loop bug in get_irq_next\n");
+				goto chan_error;
+			}
+			if((curr_model=chandev_is_chandev(curr_irq,&curr_devinfo)))
+			{
+				chandevs_detected=TRUE;
+				if(pass)
+				{
+					chandev_printf(chan_exit,"0x%04x 0x%04x 0x%02x  0x%04x 0x%02x  0x%04x 0x%02x  %-5s %-5s\n",
+						       curr_irq,curr_devinfo.devno,
+						       curr_model->chan_type,
+						       (int)curr_devinfo.sid_data.cu_type,
+						       (int)curr_devinfo.sid_data.cu_model,
+						       (int)curr_devinfo.sid_data.dev_type,
+						       (int)curr_devinfo.sid_data.dev_model,
+						       (curr_devinfo.status&DEVSTAT_DEVICE_OWNED) ? "yes":"no",
+						       (chandev_get_irqinfo_by_irq(curr_irq) ? "yes":"no"));
+						       
+						       
+				}
+					
+			}
 
+		}
+	}
+	if(chandev_parms_head)
+	{
+		chandev_parms      *curr_parms;
 
-	chandev_printf(chan_exit,"Channels enabled for detection\n");      
-	chandev_printf(chan_exit,"chan_type   cu_type       cu_model    max_port_no\n");
-	chandev_printf(chan_exit,"=================================================\n");
-	for(curr_model=chandev_models_head;curr_model!=NULL;
-	    curr_model=curr_model->next)
-	{
-		chandev_printf(chan_exit,"0x%02x       0x%04x         0x%02x        %d\n",
-		       curr_model->chan_type,(int)curr_model->cu_type,
-		       (int)curr_model->cu_model,(int)curr_model->max_port_no);         
-	}
-	
-        chandev_printf(chan_exit,"%s",chandev_keydescript);
-	chandev_printf(chan_exit,"No auto devno ranges\n");
-	chandev_printf(chan_exit,"   From        To   \n");
-	chandev_printf(chan_exit,"====================\n");
-	for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL;
-		    curr_noauto=curr_noauto->next)
-	{
-		chandev_printf(chan_exit,"0x%4x       0x%4x\n",
-			       curr_noauto->lo_devno,
-			       curr_noauto->hi_devno);
-	}
-	chandev_printf(chan_exit,"\nForced devices\n");
-	chandev_printf(chan_exit,"chan_type defif_num read_devno write_devno port_no ip_cksum hw_stats\n");
-	chandev_printf(chan_exit,"====================================================================\n");
-	for(curr_force=chandev_force_head;curr_force!=NULL;
-		    curr_force=curr_force->next)
-	{
-	chandev_printf(chan_exit,"0x%2x   %d  0x%4x 0x%4x  %4d    %1d   %1d\n",
-		       curr_force->chan_type,curr_force->devif_num,
-		       curr_force->read_devno,curr_force->write_devno,
-		       curr_force->port_no,curr_force->do_ip_checksumming,
-		       curr_force->use_hw_stats);
+		chandev_printf(chan_exit,"\n driver specific parameters\n");
+		chandev_printf(chan_exit,"chan    driver\n");
+		chandev_printf(chan_exit,"type  parameters\n");
+		chandev_printf(chan_exit,"=============================================================================\n");
+		for_each(curr_parms,chandev_parms_head)
+		{
+			chandev_printf(chan_exit,"0x%02x    %s\n",
+				       curr_parms->chan_type,
+				       curr_parms->parmstr);
+		}
 	}
+ chan_error:
 	*eof=TRUE;
  chan_exit:
 	if(currlen>length) {
@@ -700,6 +2552,7 @@
                  */
 		currlen-=splen;
 	}
+	chandev_unlock();
 	return(currlen);
 }
 
@@ -709,7 +2562,8 @@
 {
 	int         rc;
 	char        *buff;
-
+	
+	chandev_read_conf_if_necessary();
 	buff=vmalloc(count+1);
 	if(buff)
 	{
@@ -741,19 +2595,93 @@
 
 
 #endif
-static int __init chandev_init(void)
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+static  
+#endif
+int __init chandev_init(void)
 {
-	chandev_init_default_models();
+	if(!chandev_initialised)
+	{
+		chandev_parse_args();
+		chandev_init_default_models();
 #if CONFIG_PROC_FS
-	chandev_create_proc();
+		chandev_create_proc();
+#endif
+		chandev_msck_task_tq.routine=
+#if CHANDEV_USE_KERNEL_THREADS
+		chandev_start_msck_thread;
+#else
+		chandev_msck_task;
 #endif
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+		INIT_LIST_HEAD(&chandev_msck_task_tq.list);
+		chandev_msck_task_tq.sync=0;
+#endif
+		chandev_msck_task_tq.data=NULL;
+		chandev_last_startmsck_list_update=chandev_last_machine_check=jiffies-HZ;
+		atomic_set(&chandev_msck_thread_lock,1);
+		chandev_lock_owner=CHANDEV_INVALID_LOCK_OWNER;
+		chandev_lock_cnt=0;
+		spin_lock_init(&chandev_spinlock);
+		spin_lock_init(&chandev_not_oper_spinlock);
+		chandev_initialised=TRUE;
+		atomic_set(&chandev_new_msck,FALSE);
+	}
 	return(0);
 }
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
 __initcall(chandev_init);
+#endif
 
+int chandev_register_and_probe(chandev_probefunc probefunc,
+			       chandev_shutdownfunc shutdownfunc,
+			       chandev_reoperfunc reoperfunc,
+			       chandev_type chan_type)
+{
+	chandev_probelist *new_probe;
+	/* Avoid chicked & egg situations where we may be called before we */
+	/* are initialised. */
 
+	chandev_interrupt_check();
+	if(!chandev_initialised)
+		chandev_init();
+	chandev_read_conf_if_necessary();
+	if((new_probe=chandev_alloc(sizeof(chandev_probelist))))
+	{
+		new_probe->probefunc=probefunc;
+		new_probe->shutdownfunc=shutdownfunc;
+		new_probe->reoperfunc=reoperfunc;
+		new_probe->chan_type=chan_type;
+		new_probe->devices_found=0;
+		chandev_add_to_list((list **)&chandev_probelist_head,new_probe);
+		chandev_probe();
+	}
+	return(new_probe ? new_probe->devices_found:0);
+}
 
-
-
-
+void chandev_unregister(chandev_probefunc probefunc,int call_shutdown)
+{
+	chandev_probelist *curr_probe=NULL;
+	chandev_activelist *curr_device;
+	
+	chandev_interrupt_check();
+	chandev_lock();
+	for_each(curr_probe,chandev_probelist_head)
+	{
+		if(curr_probe->probefunc==probefunc)
+		{
+			for_each(curr_device,chandev_activelist_head)
+				if(curr_device->probefunc==probefunc)
+				{
+					if(call_shutdown)
+					{
+						chandev_shutdown(curr_device);
+					}
+				}
+			chandev_free_listmember((list **)&chandev_probelist_head,
+						(list *)curr_probe);
+		}
+	}
+	chandev_unlock();
+}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/Makefile linux/drivers/s390/net/Makefile
--- v2.4.1/linux/drivers/s390/net/Makefile	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/net/Makefile	Tue Feb 13 14:13:44 2001
@@ -1,16 +1,20 @@
 all: s390-net.o
 
-CFLAFS += 
+CFLAGS += 
 O_TARGET := s390-net.o
-O_OBJS    :=         
-M_OBJS   :=
+
+obj-y    := iucv.o
 
 ifeq ($(CONFIG_CTC),y)
-  O_OBJS += ctc.o
+  obj-y += ctcmain.o fsm.o
+else
+  ifeq ($(CONFIG_CTC),m)
+  obj-m += ctc.o
+ctc.o: ctcmain.o fsm.o
+	$(LD) -r ctcmain.o fsm.o -o $@
+  endif
 endif
 
-ifeq ($(CONFIG_IUCV),y)
-  O_OBJS += iucv.o
-endif
+obj-$(CONFIG_IUCV) += iucv.o netiucv.o
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/ctc.c linux/drivers/s390/net/ctc.c
--- v2.4.1/linux/drivers/s390/net/ctc.c	Mon Dec 11 12:39:45 2000
+++ linux/drivers/s390/net/ctc.c	Tue Feb 13 14:13:44 2001
@@ -46,7 +46,7 @@
 #include <linux/version.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
@@ -128,7 +128,8 @@
  *
  */  
 
-static int channel_tab_initialized = 0;     /* channel[] structure initialized */
+/* long req'd by set_bit --RR */
+static long channel_tab_initialized = 0;     /* channel[] structure initialized */
 
 struct devicelist {  
         unsigned int  devno;
@@ -394,7 +395,7 @@
         int        m;
         int        c;
         int        irq;
-        dev_info_t temp;
+        s390_dev_info_t temp;
         
         for (m = 0; m < CHANNEL_MEDIA;  m++) { 
                 for (c = 0; c < MAX_CHANNEL_DEVICES; c++){
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/ctcmain.c linux/drivers/s390/net/ctcmain.c
--- v2.4.1/linux/drivers/s390/net/ctcmain.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/net/ctcmain.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,3464 @@
+/*
+ * $Id: ctcmain.c,v 1.11 2000/12/15 19:34:54 bird Exp $
+ *
+ * CTC / ESCON network driver
+ *
+ * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Author(s): Fritz Elfert (elfert@de.ibm.com, felfert@millenux.com)
+ * Fixes by : Jochen Röhrig (roehrig@de.ibm.com)
+ * 	      Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * Documentation used:
+ *  - Principles of Operation (IBM doc#: SA22-7201-06)
+ *  - Common IO/-Device Commands and Self Description (IBM doc#: SA22-7204-02)
+ *  - Common IO/-Device Commands and Self Description (IBM doc#: SN22-5535)
+ *  - ESCON Channel-to-Channel Adapter (IBM doc#: SA22-7203-00)
+ *  - ESCON I/O Interface (IBM doc#: SA22-7202-029
+ *
+ * and the source of the original CTC driver by:
+ *  Dieter Wellerdiek (wel@de.ibm.com)
+ *  Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *  Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *  Jochen Röhrig (roehrig@de.ibm.com)
+ *
+ * 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: ctcmain.c,v $
+ * Revision 1.11  2000/12/15 19:34:54  bird
+ * struct ctc_priv_t: set type of tbusy to "unsigned long"
+ *
+ * Revision 1.10  2000/12/14 16:49:50  bird
+ * ch_action_txretry(): added missing clear_normalized_cda()
+ *
+ * Revision 1.9  2000/12/14 13:56:53  felfert
+ * Eliminated a compiler warning when building in old kernel.
+ *
+ * Revision 1.8  2000/12/14 13:11:59  felfert
+ * static ccws now separately allocated.
+ * remove locally allocated ccw for setup.
+ *
+ * Revision 1.7  2000/12/14 03:32:15  bird
+ * Fixes for >2GB memory.   Switch on checksumming.
+ *
+ * Revision 1.6  2000/12/07 20:08:30  felfert
+ * Modified RX channel initialization to be compatible with VM TCP
+ *
+ * Revision 1.5  2000/12/07 18:15:05  felfert
+ * Added workaround against VM TCP bug.
+ * Fixed an error message.
+ *
+ * Revision 1.4  2000/12/06 16:55:57  felfert
+ * Removed check for double call of ctc_setup().
+ * ctc_setup can now handle mutiple calls.
+ *
+ * Revision 1.3  2000/12/06 16:48:44  felfert
+ * New initialization.
+ * Removed old cvs log from 2.2 kernel.
+ *
+ * Revision 1.2  2000/12/06 14:13:46  felfert
+ * New unified configuration.
+ *
+ * Revision 1.1  2000/11/30 11:21:08  bird
+ * Support for new ctc driver
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+
+#include <linux/signal.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ip.h>
+#include <linux/if_arp.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/ctype.h>
+#include <net/dst.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+#include <asm/uaccess.h>
+
+#define CTC_USE_IDALS 1
+#if CTC_USE_IDALS
+#  include <asm/idals.h>
+#else
+#  define set_normalized_cda(ccw, addr) ((ccw)->cda = (addr))
+#  define clear_normalized_cda(ccw)
+#endif
+
+#include <asm/irq.h>
+
+#include "fsm.h"
+
+#ifdef MODULE
+MODULE_AUTHOR("(C) 2000 IBM Corp. by Fritz Elfert (felfert@millenux.com)");
+MODULE_DESCRIPTION("Linux for S/390 CTC/Escon Driver");
+MODULE_PARM(ctc, "s");
+MODULE_PARM_DESC(ctc,
+"One or more definitions in the same format like the kernel param for ctc.\n"
+"E.g.: ctc0:0x700:0x701:0:ctc1:0x702:0x703:0\n");
+
+char *ctc = NULL;
+#else
+/**
+ * Number of devices in monolithic (not module) driver version.
+ */
+#define MAX_STATIC_DEVICES 16
+#endif /* MODULE */
+
+#undef DEBUG
+
+/**
+ * CCW commands, used in this driver.
+ */
+#define CCW_CMD_WRITE		0x01
+#define CCW_CMD_READ		0x02
+#define CCW_CMD_SET_EXTENDED	0xc3
+#define CCW_CMD_PREPARE		0xe3
+
+#define CTC_PROTO_S390          0
+#define CTC_PROTO_LINUX         1
+#define CTC_PROTO_MAX           1
+
+#define CTC_BUFSIZE_LIMIT       65535
+#define CTC_BUFSIZE_DEFAULT     32768
+
+#define CTC_TIMEOUT_5SEC        5000
+
+#define CTC_INITIAL_BLOCKLEN    2
+
+#define READ			0
+#define WRITE			1
+
+/**
+ * Enum for classifying detected devices.
+ */
+enum channel_types {
+        /**
+	 * Device is not a channel.
+	 */
+	channel_type_none,
+
+	/**
+	 * Device is a channel, but we don't know
+	 * anything about it.
+	 */
+	channel_type_unknown,
+
+        /**
+	 * Device is a CTC/A.
+	 */
+	channel_type_ctca,
+
+	/**
+	 * Device is a ESCON channel.
+	 */
+	channel_type_escon,
+	/**
+	 * Device is an unsupported model.
+	 */
+	channel_type_unsupported
+};
+
+typedef enum channel_types channel_type_t;
+
+static int ctc_no_auto;
+
+/**
+ * If running on 64 bit, this must be changed. XXX Why? (bird)
+ */
+typedef unsigned long intparm_t;
+
+#if LINUX_VERSION_CODE < 0x020300
+typedef struct device      net_device;
+#else
+typedef struct net_device  net_device;
+#endif
+
+/**
+ * Definition of a per device parameter block
+ */
+#define MAX_PARAM_NAME_LEN 11
+typedef struct param_t {
+	struct param_t *next;
+	int            read_dev;
+	int            write_dev;
+	__u16          proto;
+	char           name[MAX_PARAM_NAME_LEN];
+} param;
+
+static param *params;
+
+typedef struct {
+	unsigned long maxmulti;
+	unsigned long maxcqueue;
+	unsigned long doios_single;
+	unsigned long doios_multi;
+	unsigned long txlen;
+	unsigned long tx_time;
+	struct timeval send_stamp;
+} ctc_profile;
+
+/**
+ * Definition of one channel
+ */
+typedef struct channel_t {
+
+        /**
+	 * Pointer to next channel in list.
+	 */
+	struct channel_t    *next;
+
+	__u16               devno;
+	int                 irq;
+
+	/**
+	 * Type of this channel.
+	 * CTC/A or Escon for valid channels.
+	 */
+	channel_type_t      type;
+
+        /**
+	 * Misc. flags. See CHANNEL_FLAGS_... below
+	 */
+	__u32               flags;
+
+	/**
+	 * The protocol of this channel (currently always 0)
+	 */
+	__u16               protocol;
+
+	/**
+	 * I/O and irq related stuff
+	 */
+	ccw1_t              *ccw;
+	devstat_t           *devstat;
+
+	/**
+	 * Bottom half task queue.
+	 */
+	struct tq_struct    tq;
+
+	/**
+	 * RX/TX buffer for init sequence.
+	 */
+	__u16               dummy_buf;
+
+	/**
+	 * RX buffer size
+	 */
+	int                 max_bufsize;
+
+	/**
+	 * Receive buffer.
+	 */
+	struct sk_buff      *rx_skb;
+
+	/**
+	 * Universal I/O queue.
+	 */
+	struct sk_buff_head io_queue;
+
+	/**
+	 * TX queue for collecting skb's during busy.
+	 */
+	struct sk_buff_head collect_queue;
+
+	/**
+	 * Amount of data in collect_queue.
+	 */
+	int                 collect_len;
+
+	/**
+	 * spinlock for collect_queue and collect_len
+	 */
+	spinlock_t          collect_lock;
+
+	/**
+	 * Pointer to dynamic allocated CCWs for TX
+	 */
+	ccw1_t              *dccw;
+
+	/**
+	 * Number of dynamic allocated CCWs needed for clearing IDALs.
+	 */
+	int                 dccw_count;
+
+	/**
+	 * Timer for detecting unresposive
+	 * I/O operations.
+	 */
+	fsm_timer           timer;
+
+	/**
+	 * Retry counter for misc. operations.
+	 */
+	int                 retry;
+
+	/**
+	 * The finite state machine of this channel
+	 */
+	fsm_instance        *fsm;
+
+	/**
+	 * The corresponding net_device this channel
+	 * belongs to.
+	 */
+	net_device          *netdev;
+
+	ctc_profile         prof;
+} channel;
+
+#define CHANNEL_FLAGS_READ   0
+#define CHANNEL_FLAGS_WRITE  1
+#define CHANNEL_FLAGS_INUSE  2
+#define CHANNEL_FLAGS_RWMASK 1
+#define CHANNEL_DIRECTION(f) (f & CHANNEL_FLAGS_RWMASK)
+
+/**
+ * Linked list of all detected channels.
+ */
+static channel *channels;
+
+typedef struct ctc_priv_t {
+	struct net_device_stats stats;
+#if LINUX_VERSION_CODE >= 0x02032D
+	unsigned long           tbusy;
+#endif
+	/**
+	 * The finite state machine of this interface.
+	 */
+	fsm_instance            *fsm;
+	channel                 *channel[2];
+	struct proc_dir_entry   *proc_dentry;
+	struct proc_dir_entry   *proc_stat_entry;
+	struct proc_dir_entry   *proc_ctrl_entry;
+} ctc_priv;
+
+/**
+ * Definition of our link level header.
+ */
+typedef struct ll_header_t {
+	__u16	      length;
+	__u16	      type;
+	__u16	      unused;
+} ll_header;
+#define LL_HEADER_LENGTH (sizeof(ll_header))
+
+/**
+ * Compatibility macros for busy handling
+ * of network devices.
+ */
+#if LINUX_VERSION_CODE < 0x02032D
+static __inline__ void ctc_clear_busy(net_device *dev)
+{
+	clear_bit(0 ,(void *)&dev->tbusy);
+	mark_bh(NET_BH);
+}
+
+static __inline__ int ctc_test_and_set_busy(net_device *dev)
+{
+	return(test_and_set_bit(0, (void *)&dev->tbusy));
+}
+
+#define SET_DEVICE_START(device, value) dev->start = value
+#else
+static __inline__ void ctc_clear_busy(net_device *dev)
+{
+	clear_bit(0, &(((ctc_priv *)dev->priv)->tbusy));
+	netif_start_queue(dev);
+}
+
+static __inline__ int ctc_test_and_set_busy(net_device *dev)
+{
+	netif_stop_queue(dev);
+	return test_and_set_bit(0, &((ctc_priv *)dev->priv)->tbusy);
+}
+
+#define SET_DEVICE_START(device, value)
+#endif
+
+/**
+ * Print Banner.
+ */
+static void print_banner(void) {
+	static int printed;
+	char vbuf[] = "$Revision: 1.11 $";
+	char *version = vbuf;
+
+	if (printed)
+		return;
+	if ((version = strchr(version, ':'))) {
+		char *p = strchr(version + 1, '$');
+		if (p)
+			*p = '\0';
+	} else
+		version = " ??? ";
+	printk(KERN_INFO "CTC driver Version%s initialized\n", version);
+	printed = 1;
+}
+
+/**
+ * Return type of a detected device.
+ */
+static channel_type_t channel_type (senseid_t *id) {
+	channel_type_t type = channel_type_none;
+
+	switch (id->cu_type) {
+		case 0x3088:
+			switch (id->cu_model) {
+				case 0x08:
+					/**
+					 * 3088-08 = CTCA
+					 */
+					type = channel_type_ctca;
+					break;
+
+				case 0x1F:
+					/**
+					 * 3088-1F = ESCON channel
+					 */
+					type = channel_type_escon;
+					break;
+
+					/**
+					 * 3088-01 = P390 OSA emulation
+					 */
+				case 0x01:
+					/* fall thru */
+
+					/**
+					 * 3088-60 = OSA/2 adapter
+					 */
+				case 0x60:
+					/* fall thru */
+
+					/**
+					 * 3088-61 = CISCO 7206 CLAW proto
+					 * on ESCON
+					 */
+				case 0x61:
+					/* fall thru */
+
+					/**
+					 * 3088-62 = OSA/D device
+					 */
+				case 0x62:
+					type = channel_type_unsupported;
+					break;
+
+				default:
+					type = channel_type_unknown;
+					printk(KERN_INFO
+					       "channel: Unknown model found "
+					       "3088-%02x\n", id->cu_model);
+			}
+			break;
+
+		default:
+			type = channel_type_none;
+	}
+	return type;
+}
+
+/**
+ * States of the interface statemachine.
+ */
+enum dev_states {
+	DEV_STATE_STOPPED,
+	DEV_STATE_STARTWAIT_RXTX,
+	DEV_STATE_STARTWAIT_RX,
+	DEV_STATE_STARTWAIT_TX,
+	DEV_STATE_STOPWAIT_RXTX,
+	DEV_STATE_STOPWAIT_RX,
+	DEV_STATE_STOPWAIT_TX,
+	DEV_STATE_RUNNING,
+	/**
+	 * MUST be always the last element!!
+	 */
+	NR_DEV_STATES
+};
+
+static const char *dev_state_names[] = {
+	"Stopped",
+	"StartWait RXTX",
+	"StartWait RX",
+	"StartWait TX",
+	"StopWait RXTX",
+	"StopWait RX",
+	"StopWait TX",
+	"Running",
+};
+
+/**
+ * Events of the interface statemachine.
+ */
+enum dev_events {
+	DEV_EVENT_START,
+	DEV_EVENT_STOP,
+	DEV_EVENT_RXUP,
+	DEV_EVENT_TXUP,
+	DEV_EVENT_RXDOWN,
+	DEV_EVENT_TXDOWN,
+	/**
+	 * MUST be always the last element!!
+	 */
+	NR_DEV_EVENTS
+};
+
+static const char *dev_event_names[] = {
+	"Start",
+	"Stop",
+	"RX up",
+	"TX up",
+	"RX down",
+	"TX down",
+};
+
+/**
+ * Events of the channel statemachine
+ */
+enum ch_events {
+	/**
+	 * Events, representing return code of
+	 * I/O operations (do_IO, halt_IO et al.)
+	 */
+	CH_EVENT_IO_SUCCESS,
+	CH_EVENT_IO_EBUSY,
+	CH_EVENT_IO_ENODEV,
+	CH_EVENT_IO_EIO,
+	CH_EVENT_IO_UNKNOWN,
+
+	CH_EVENT_ATTNBUSY,
+	CH_EVENT_ATTN,
+	CH_EVENT_BUSY,
+
+	/**
+	 * Events, representing unit-check
+	 */
+	CH_EVENT_UC_RCRESET,
+	CH_EVENT_UC_RSRESET,
+	CH_EVENT_UC_TXTIMEOUT,
+	CH_EVENT_UC_TXPARITY,
+	CH_EVENT_UC_HWFAIL,
+	CH_EVENT_UC_RXPARITY,
+	CH_EVENT_UC_ZERO,
+	CH_EVENT_UC_UNKNOWN,
+
+	/**
+	 * Events, representing subchannel-check
+	 */
+	CH_EVENT_SC_UNKNOWN,
+
+	/**
+	 * Event, representing normal IRQ
+	 */
+	CH_EVENT_IRQ,
+	CH_EVENT_FINSTAT,
+
+	/**
+	 * Event, representing timer expiry.
+	 */
+	CH_EVENT_TIMER,
+
+	/**
+	 * Events, representing commands from upper levels.
+	 */
+	CH_EVENT_START,
+	CH_EVENT_STOP,
+
+	/**
+	 * MUST be always the last element!!
+	 */
+	NR_CH_EVENTS,
+};
+
+static const char *ch_event_names[] = {
+	"do_IO success",
+	"do_IO busy",
+	"do_IO enodev",
+	"do_IO ioerr",
+	"do_IO unknown",
+
+	"Status ATTN & BUSY",
+	"Status ATTN",
+	"Status BUSY",
+
+	"Unit check remote reset",
+	"Unit check remote system reset",
+	"Unit check TX timeout",
+	"Unit check TX parity",
+	"Unit check Hardware failure",
+	"Unit check RX parity",
+	"Unit check ZERO",
+	"Unit check Unknown",
+
+	"SubChannel check Unknown",
+
+	"IRQ normal",
+	"IRQ final",
+
+	"Timer",
+
+	"Start",
+	"Stop",
+};
+
+/**
+ * States of the channel statemachine.
+ */
+enum ch_states {
+	/**
+	 * Channel not assigned to any device,
+	 * initial state, direction invalid
+	 */
+	CH_STATE_IDLE,
+
+	/**
+	 * Channel assigned but not operating
+	 */
+	CH_STATE_STOPPED,
+	CH_STATE_STARTWAIT,
+	CH_STATE_STARTRETRY,
+	CH_STATE_SETUPWAIT,
+	CH_STATE_RXINIT,
+	CH_STATE_TXINIT,
+	CH_STATE_RX,
+	CH_STATE_TX,
+	CH_STATE_RXIDLE,
+	CH_STATE_TXIDLE,
+	CH_STATE_RXERR,
+	CH_STATE_TXERR,
+	CH_STATE_TERM,
+	CH_STATE_DTERM,
+
+	/**
+	 * MUST be always the last element!!
+	 */
+	NR_CH_STATES,
+};
+
+static const char *ch_state_names[] = {
+	"Idle",
+	"Stopped",
+	"StartWait",
+	"StartRetry",
+	"SetupWait",
+	"RX init",
+	"TX init",
+	"RX",
+	"TX",
+	"RX idle",
+	"TX idle",
+	"RX error",
+	"TX error",
+	"Terminating",
+	"Restarting",
+};
+
+
+/**
+ * Dump header and first 16 bytes of an sk_buff for debugging purposes.
+ *
+ * @param skb    The sk_buff to dump.
+ * @param offset Offset relative to skb-data, where to start the dump.
+ */
+static void ctc_dump_skb(struct sk_buff *skb, int offset)
+{
+	unsigned char *p = skb->data;
+	__u16 bl;
+	ll_header *header;
+	int i;
+
+	p += offset;
+	bl = *((__u16*)p);
+	p += 2;
+	header = (ll_header *)p;
+	p -= 2;
+	
+	printk(KERN_DEBUG "dump:\n");
+	printk(KERN_DEBUG "blocklen=%d %04x\n", bl, bl);
+
+	printk(KERN_DEBUG "h->length=%d %04x\n", header->length,
+	       header->length); 
+	printk(KERN_DEBUG "h->type=%04x\n", header->type); 
+	printk(KERN_DEBUG "h->unused=%04x\n", header->unused);
+	if (bl > 16)
+		bl = 16;
+	printk(KERN_DEBUG "data: ");
+	for (i = 0; i < bl; i++)
+		printk("%02x ", *p++);
+	printk("\n");
+}
+
+/**
+ * Bottom half routine.
+ *
+ * @param ch The channel to work on.
+ */
+static void ctc_bh(channel *ch)
+{
+	net_device     *dev = ch->netdev;
+	ctc_priv       *privptr = (ctc_priv *)dev->priv;
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&ch->io_queue))) {
+		__u16 len = *((__u16*)skb->data);
+
+		skb_put(skb, 2 + LL_HEADER_LENGTH);
+		skb_pull(skb, 2);
+		skb->dev = dev;
+		skb->ip_summed = CHECKSUM_NONE;
+		while (len > 0) {
+			ll_header *header = (ll_header *)skb->data;
+			skb_pull(skb, LL_HEADER_LENGTH);
+			if ((ch->protocol == CTC_PROTO_S390) &&
+			    (header->type != ETH_P_IP)) {
+				/**
+				 * Check packet type only if we stick strictly
+				 * to S/390's protocol of OS390. This only
+				 * supports IP. Otherwise allow any packet
+				 * type.
+				 */
+				printk(KERN_WARNING
+				       "%s Illegal packet type 0x%04x "
+				       "received, dropping\n",
+				       dev->name, header->type);
+				ctc_dump_skb(skb, -6);
+				privptr->stats.rx_dropped++;
+				privptr->stats.rx_frame_errors++;
+				dev_kfree_skb(skb);
+				goto again;
+			}
+			skb->protocol = ntohs(header->type);
+			header->length -= LL_HEADER_LENGTH;
+			if ((header->length > dev->mtu) ||
+			    (header->length == 0)) {
+				printk(KERN_WARNING
+				       "%s Illegal packet size %d "
+				       "received (MTU=%d), "
+				       "dropping\n", dev->name, header->length,
+				       dev->mtu);
+				ctc_dump_skb(skb, -6);
+				privptr->stats.rx_dropped++;
+				privptr->stats.rx_length_errors++;
+				dev_kfree_skb(skb);
+				goto again;
+			}
+			skb_put(skb, header->length);
+			skb->mac.raw = skb->data;
+			/**
+			 * Set truesize here to make the kernel's
+			 * socket layer happy. If this is not done,
+			 * the RX-routines of the socket code are dropping
+			 * most of the received packets, because they "think"
+			 * there isn't enough buffer space for the incoming
+			 * data.
+			 */
+			skb->truesize = skb->len;
+			len -= (LL_HEADER_LENGTH + header->length);
+			if (len > 0) {
+				/**
+				 * Clone the skb only if there are still
+				 * sub-packets.
+				 */
+				struct sk_buff *skb2 =
+					skb_clone(skb, GFP_ATOMIC);
+				if (!skb2) {
+					printk(KERN_WARNING "%s Out of memory"
+					       " in ctc_bh\n",
+					       dev->name);
+					privptr->stats.rx_dropped++;
+					dev_kfree_skb(skb);
+					goto again;
+				}
+				netif_rx(skb2);
+				privptr->stats.rx_packets++;
+				privptr->stats.rx_bytes += skb2->len;
+				/**
+				 * Advance pointers to next sub-packet.
+				 */
+				skb_pull(skb, header->length);
+				skb_put(skb, LL_HEADER_LENGTH);
+			} else {
+				netif_rx(skb);
+				privptr->stats.rx_packets++;
+				privptr->stats.rx_bytes += skb->len;
+			}
+		}
+	again:
+	}
+	return;
+}
+
+/**
+ * Check return code of a preceeding do_IO, halt_IO etc...
+ *
+ * @param ch          The channel, the error belongs to.
+ * @param return_code The error code to inspect.
+ */
+static void inline ccw_check_return_code (channel *ch, int return_code)
+{
+	switch (return_code) {
+		case 0:
+			fsm_event(ch->fsm, CH_EVENT_IO_SUCCESS, ch);
+			break;
+		case -EBUSY:
+			printk(KERN_INFO "ch-%04x: Busy !\n", ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_IO_EBUSY, ch);
+			break;
+		case -ENODEV:
+			printk(KERN_EMERG
+			       "ch-%04x: Invalid device called for IO\n",
+			       ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_IO_ENODEV, ch);
+			break;
+		case -EIO:
+			printk(KERN_EMERG
+			       "ch-%04x: Status pending... \n", ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_IO_EIO, ch);
+			break;
+		default:
+			printk(KERN_EMERG
+			       "ch-%04x: Unknown error in do_IO %04x\n",
+			       ch->devno, return_code);
+			fsm_event(ch->fsm, CH_EVENT_IO_UNKNOWN, ch);
+	}
+}
+
+/**
+ * Check sense of a unit check.
+ *
+ * @param ch    The channel, the sense code belongs to.
+ * @param sense The sense code to inspect.
+ */
+static void inline ccw_unit_check (channel *ch, unsigned char sense) {
+	if (sense & SNS0_INTERVENTION_REQ) {
+		if (sense & 0x01)  {
+			printk(KERN_DEBUG
+			       "ch-%04x: Interface disc. or Sel. reset "
+			       "(remote)\n", ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_UC_RCRESET, ch);
+		} else {
+			printk(KERN_DEBUG "ch-%04x: System reset (remote)\n",
+			       ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_UC_RSRESET, ch);
+		}
+	} else if (sense & SNS0_EQUIPMENT_CHECK) {
+		if (sense & SNS0_BUS_OUT_CHECK) {
+			printk(KERN_WARNING
+			       "ch-%04x: Hardware malfunction (remote)\n",
+			       ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_UC_HWFAIL, ch);
+		} else {
+			printk(KERN_WARNING
+			       "ch-%04x: Read-data parity error (remote)\n",
+			       ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_UC_RXPARITY, ch);
+		}
+	} else if (sense & SNS0_BUS_OUT_CHECK) {
+		if (sense & 0x04) {
+			printk(KERN_WARNING
+			       "ch-%04x: Data-streaming timeout)\n",
+			       ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_UC_TXTIMEOUT, ch);
+		} else {
+			printk(KERN_WARNING
+			       "ch-%04x: Data-transfer parity error\n",
+			       ch->devno);
+			fsm_event(ch->fsm, CH_EVENT_UC_TXPARITY, ch);
+		}
+	} else if (sense == 0) {
+		printk(KERN_DEBUG "ch-%04x: Unit check\n", ch->devno);
+		fsm_event(ch->fsm, CH_EVENT_UC_ZERO, ch);
+	} else {
+		printk(KERN_WARNING
+		       "ch-%04x: Unit Check with sense code: %02x\n",
+		       ch->devno, sense);
+		fsm_event(ch->fsm, CH_EVENT_UC_UNKNOWN, ch);
+	}
+}
+
+static void ctc_purge_skb_queue(struct sk_buff_head *q)
+{
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(q))) {
+		atomic_dec(&skb->users);
+		dev_kfree_skb(skb);
+	}
+}
+
+/**
+ * Dummy NOP action for statemachines
+ */
+static void fsm_action_nop(fsm_instance *fi, int event, void *arg)
+{
+}
+
+/**
+ * Actions for channel - statemachines.
+ *****************************************************************************/
+
+/**
+ * Normal data has been send. Free the corresponding
+ * skb (it's in io_queue), reset dev->tbusy and
+ * revert to idle state.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_txdone(fsm_instance *fi, int event, void *arg)
+{
+	channel        *ch = (channel *)arg;
+	net_device     *dev = ch->netdev;
+	ctc_priv       *privptr = dev->priv;
+	struct sk_buff *skb;
+	int            first = 1;
+	int            i;
+
+	struct timeval done_stamp = xtime;
+	unsigned long duration = 
+		(done_stamp.tv_sec - ch->prof.send_stamp.tv_sec) * 1000000 +
+		done_stamp.tv_usec - ch->prof.send_stamp.tv_usec;
+	if (duration > ch->prof.tx_time)
+		ch->prof.tx_time = duration;
+
+	if (ch->devstat->rescnt != 0)
+		printk(KERN_DEBUG "%s: TX not complete, remaining %d bytes\n",
+		       dev->name, ch->devstat->rescnt);
+	
+	fsm_deltimer(&ch->timer);
+	while ((skb = skb_dequeue(&ch->io_queue))) {
+		privptr->stats.tx_packets++;
+		privptr->stats.tx_bytes += skb->len - LL_HEADER_LENGTH;
+		if (first) {
+			privptr->stats.tx_bytes += 2;
+			first = 0;
+		}
+		atomic_dec(&skb->users);
+		dev_kfree_skb(skb);
+	}
+	spin_lock(&ch->collect_lock);
+	if (ch->dccw) {
+		for (i = 0; i < ch->dccw_count; i++)
+			clear_normalized_cda(&ch->dccw[i]);
+		kfree(ch->dccw);
+		ch->dccw = NULL;
+	}
+	if (ch->collect_len > 0) {
+		int rc;
+
+		ch->dccw_count = skb_queue_len(&ch->collect_queue) + 1;
+		if (ch->prof.maxmulti < (ch->collect_len + 2))
+			ch->prof.maxmulti = ch->collect_len + 2;
+		if (ch->prof.maxcqueue < ch->dccw_count)
+			ch->prof.maxcqueue = ch->dccw_count;
+
+		ch->dccw = kmalloc(ch->dccw_count *
+				   sizeof(ccw1_t), GFP_ATOMIC|GFP_DMA);
+		if (!ch->dccw) {
+			spin_unlock(&ch->collect_lock);
+			printk(KERN_WARNING
+			       "%s: Unable to alloc dynamic ccws\n",
+			       dev->name);
+			return;
+		}
+
+		ch->dccw[0].cmd_code = CCW_CMD_PREPARE;
+		ch->dccw[0].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->dccw[0].count    = 0;
+		ch->dccw[0].cda	     = 0;
+		i = 1;
+		while ((skb = skb_dequeue(&ch->collect_queue))) {
+			ch->prof.txlen += (skb->len - LL_HEADER_LENGTH);
+			if (i == 1)
+				*((__u16 *)skb_push(skb, 2)) =
+					ch->collect_len + 2;
+			ch->dccw[i].cmd_code = CCW_CMD_WRITE;
+			ch->dccw[i].flags    = CCW_FLAG_SLI |
+				((skb_queue_len(&ch->collect_queue))
+				 ? CCW_FLAG_DC : 0);
+			ch->dccw[i].count    = skb->len;
+			set_normalized_cda(&ch->dccw[i],
+					   virt_to_phys(skb->data));
+			skb_queue_tail(&ch->io_queue, skb);
+			i++;
+		}
+		ch->collect_len = 0;
+		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+		ch->prof.send_stamp = xtime;
+		rc = do_IO(ch->irq, ch->dccw, (intparm_t)ch, 0xff, 0);
+		ch->prof.doios_multi++;
+		if (rc != 0) {
+			fsm_deltimer(&ch->timer);
+			i = 0;
+			while ((skb = skb_dequeue(&ch->io_queue))) {
+				privptr->stats.tx_dropped++;
+				privptr->stats.tx_errors++;
+				atomic_dec(&skb->users);
+				dev_kfree_skb(skb);
+				i++;
+			}
+			kfree(ch->dccw);
+			ch->dccw = NULL;
+			if (i != ch->dccw_count)
+				printk(KERN_WARNING "ctc: i != nccws !!!\n");
+			ccw_check_return_code(ch, rc);
+		}
+	} else
+		fsm_newstate(fi, CH_STATE_TXIDLE);
+	ctc_clear_busy(dev);
+	spin_unlock(&ch->collect_lock);
+}
+
+/**
+ * Initial data is sent.
+ * Notify device statemachine that we are up and
+ * running.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_txidle(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+
+	fsm_deltimer(&ch->timer);
+	fsm_newstate(fi, CH_STATE_TXIDLE);
+	fsm_event(((ctc_priv *)ch->netdev->priv)->fsm, DEV_EVENT_TXUP,
+		  ch->netdev);
+}
+
+/**
+ * Got normal data, check for sanity, queue it up, allocate new buffer
+ * trigger bottom half, and initiate next read.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_rx(fsm_instance *fi, int event, void *arg)
+{
+	channel        *ch = (channel *)arg;
+	net_device     *dev = ch->netdev;
+	ctc_priv       *privptr = dev->priv;
+	int            len = ch->max_bufsize - ch->devstat->rescnt;
+	struct sk_buff *skb = ch->rx_skb;
+	__u16          block_len = *((__u16*)skb->data);
+	char           *saved_data = skb->data;
+	int            queued = 0;
+	int            rc;
+
+	fsm_deltimer(&ch->timer);
+	if (len < 8) {
+		printk(KERN_WARNING "%s: got packet with length < 8\n",
+		       dev->name);
+		privptr->stats.rx_dropped++;
+		privptr->stats.rx_length_errors++;
+		goto again;
+	}
+	if (len > ch->max_bufsize) {
+		printk(KERN_WARNING "%s: got packet with length > %d\n",
+		       dev->name, ch->max_bufsize);
+		privptr->stats.rx_dropped++;
+		privptr->stats.rx_length_errors++;
+		goto again;
+	}
+	/**
+	 * VM TCP seems to have a bug sending 2 trailing bytes of garbage.
+	 */
+	if ((len < block_len) ||
+	    ((len > block_len) && (ch->protocol != CTC_PROTO_S390)) ||
+	    ((len > (block_len + 2)) && (ch->protocol == CTC_PROTO_S390))) {
+		printk(KERN_WARNING
+		       "%s: got block length %d != rx length %d\n", dev->name,
+		       block_len, len);
+		*((__u16*)skb->data) = len;
+		ctc_dump_skb(skb, 0);
+		privptr->stats.rx_dropped++;
+		privptr->stats.rx_length_errors++;
+		goto again;
+	}
+	block_len -= 2;
+	if (block_len > 0) {
+		*((__u16*)skb->data) = block_len;
+		skb_queue_tail(&ch->io_queue, skb);
+		queued++;
+	}
+ again:
+	if (queued) {
+		queue_task(&ch->tq, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);
+		ch->rx_skb = dev_alloc_skb(ch->max_bufsize);
+		if (ch->rx_skb == NULL) {
+			printk(KERN_WARNING "%s: Couldn't alloc rx_skb in "
+			       "ch_action_rx\n", dev->name);
+			/* TODO: retry after bottom half */
+			return;
+		}
+	} else {
+		skb->data = skb->tail = saved_data;
+		skb->len = 0;
+	}
+	ch->ccw[1].count = ch->max_bufsize;
+	set_normalized_cda(&ch->ccw[1], virt_to_phys(ch->rx_skb->data));
+	rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);
+	if (rc != 0)
+		ccw_check_return_code(ch, rc);
+}
+
+/**
+ * Initialize connection by sending a __u16 of value 0.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_firstio(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	int     rc;
+
+	if (fsm_getstate(fi) == CH_STATE_TXIDLE)
+		printk(KERN_DEBUG "ch-%04x: remote side issued READ?, "
+		       "init ...\n", ch->devno);
+	fsm_deltimer(&ch->timer);
+	/**
+	 * Don´t setup a timer for receiving the initial RX frame
+	 * if in compatibility mode, since VM TCP delays the initial
+	 * frame until it has some data to send.
+	 */
+	if ((CHANNEL_DIRECTION(ch->flags) == WRITE) ||
+	    (ch->protocol != CTC_PROTO_S390))
+		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+
+	ch->dummy_buf    = CTC_INITIAL_BLOCKLEN;
+	ch->ccw[1].count = 2; /* Transfer only length */
+	set_normalized_cda(&ch->ccw[1], virt_to_phys(&ch->dummy_buf));
+	fsm_newstate(fi, (CHANNEL_DIRECTION(ch->flags) == READ)
+		     ? CH_STATE_RXINIT : CH_STATE_TXINIT);
+	rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		fsm_newstate(fi, CH_STATE_SETUPWAIT);
+		ccw_check_return_code(ch, rc);
+	}
+	/**
+	 * If in compatibility mode since we don´t setup a timer, we
+	 * also signal RX channel up immediately. This enables us
+	 * to send packets early which in turn usually triggers some
+	 * reply from VM TCP which brings up the RX channel to it´s
+	 * final state.
+	 */
+	if ((CHANNEL_DIRECTION(ch->flags) == READ) &&
+	    (ch->protocol == CTC_PROTO_S390)) {
+		net_device *dev = ch->netdev;
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXUP, dev);
+	}
+}
+
+/**
+ * Got initial data, check it. If OK,
+ * notify device statemachine that we are up and
+ * running.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_rxidle(fsm_instance *fi, int event, void *arg)
+{
+	channel    *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+	int        rc;
+
+	fsm_deltimer(&ch->timer);
+	if (ch->dummy_buf >= CTC_INITIAL_BLOCKLEN) {
+		ch->rx_skb = dev_alloc_skb(ch->max_bufsize);
+		if (ch->rx_skb == NULL) {
+			printk(KERN_WARNING "%s: Couldn't alloc rx_skb in "
+			       "ch_action_rxidle\n", dev->name);
+			return;
+		}
+		ch->ccw[1].count = ch->max_bufsize;
+		set_normalized_cda(&ch->ccw[1],
+				   virt_to_phys(ch->rx_skb->data));
+		fsm_newstate(fi, CH_STATE_RXIDLE);
+		rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);
+		if (rc != 0) {
+			fsm_newstate(fi, CH_STATE_RXINIT);
+			ccw_check_return_code(ch, rc);
+		} else
+			fsm_event(((ctc_priv *)dev->priv)->fsm,
+				  DEV_EVENT_RXUP, dev);
+	} else {
+		printk(KERN_DEBUG "%s: Initial RX count %d not %d\n",
+		       dev->name, ch->dummy_buf, CTC_INITIAL_BLOCKLEN);
+		ch_action_firstio(fi, event, arg);
+	}
+}
+
+/**
+ * Set channel into extended mode.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_setmode(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	int     rc;
+	unsigned long saveflags;
+
+	fsm_deltimer(&ch->timer);
+	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+	fsm_newstate(fi, CH_STATE_SETUPWAIT);
+	if (event == CH_EVENT_TIMER)
+		s390irq_spin_lock_irqsave(ch->irq, saveflags);
+	rc = do_IO(ch->irq, &ch->ccw[3], (intparm_t)ch, 0xff, 0);
+	if (event == CH_EVENT_TIMER)
+		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		fsm_newstate(fi, CH_STATE_STARTWAIT);
+		ccw_check_return_code(ch, rc);
+	} else
+		ch->retry = 0;
+}
+
+/**
+ * Setup channel.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_start(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	unsigned long saveflags;
+	int     rc;
+	net_device *dev;
+
+	if (ch == NULL) {
+		printk(KERN_WARNING "ch_action_start ch=NULL\n");
+		return;
+	}
+	if (ch->netdev == NULL) {
+		printk(KERN_WARNING "ch_action_start dev=NULL, irq=%d\n",
+		       ch->irq);
+		return;
+	}
+
+ dev = ch->netdev;
+
+#ifdef DEBUG
+	printk(KERN_DEBUG "%s: %s channel start\n", dev->name,
+	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+#endif
+
+	INIT_LIST_HEAD(&ch->tq.list);
+	ch->tq.sync    = 0;
+	ch->tq.routine = (void *)(void *)ctc_bh;
+	ch->tq.data    = ch;
+
+	ch->ccw[0].cmd_code = CCW_CMD_PREPARE;
+	ch->ccw[0].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
+	ch->ccw[0].count    = 0;
+	ch->ccw[0].cda	    = 0;
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		ch->ccw[1].cmd_code = CCW_CMD_READ;
+		ch->ccw[1].flags    = CCW_FLAG_SLI;
+		ch->ccw[1].count    = 0;
+		ch->ccw[1].cda	    = 0;
+	} else {
+		ch->ccw[1].cmd_code = CCW_CMD_WRITE;
+		ch->ccw[1].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
+		ch->ccw[1].count    = 0;
+		ch->ccw[1].cda	    = 0;
+	}
+	ch->ccw[2].cmd_code = CCW_CMD_NOOP;	 /* jointed CE + DE */
+	ch->ccw[2].flags    = CCW_FLAG_SLI;
+	ch->ccw[2].count    = 0;
+	ch->ccw[2].cda	    = 0;
+	fsm_newstate(fi, CH_STATE_STARTWAIT);
+	fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
+	s390irq_spin_lock_irqsave(ch->irq, saveflags);
+	rc = halt_IO(ch->irq, (intparm_t)ch, 0);
+	s390irq_spin_unlock_irqrestore(ch->irq, saveflags);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		ccw_check_return_code(ch, rc);
+	}
+#ifdef DEBUG
+	printk(KERN_DEBUG "ctc: %s(): leaving\n", __FUNCTION__);
+#endif
+}
+
+/**
+ * Shutdown a channel.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_haltio(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	unsigned long saveflags;
+	int     rc;
+	int     oldstate;
+
+	fsm_deltimer(&ch->timer);
+	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+	if (event == CH_EVENT_STOP)
+		s390irq_spin_lock_irqsave(ch->irq, saveflags);
+	oldstate = fsm_getstate(fi);
+	fsm_newstate(fi, CH_STATE_TERM);
+	rc = halt_IO (ch->irq, (intparm_t)ch, 0);
+	if (event == CH_EVENT_STOP)
+		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		fsm_newstate(fi, oldstate);
+		ccw_check_return_code(ch, rc);
+	}
+}
+
+/**
+ * A channel has successfully been halted.
+ * Cleanup it's queue and notify interface statemachine.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_stopped(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	if (ch->dccw) {
+		printk(KERN_WARNING "ch_action_stopped: dccw !NULL\n");
+		return;
+	}
+	fsm_deltimer(&ch->timer);
+	fsm_newstate(fi, CH_STATE_STOPPED);
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		skb_queue_purge(&ch->io_queue);
+		if (ch->rx_skb != NULL) {
+			dev_kfree_skb(ch->rx_skb);
+			ch->rx_skb = NULL;
+		}
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+	} else {
+		ctc_purge_skb_queue(&ch->io_queue);
+		spin_lock(&ch->collect_lock);
+		ctc_purge_skb_queue(&ch->collect_queue);
+		if (ch->dccw)
+			kfree(ch->dccw);
+		ch->dccw = NULL;
+		ch->collect_len = 0;
+		spin_unlock(&ch->collect_lock);
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+	}
+}
+
+/**
+ * Handle error during setup of channel.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_setuperr(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	/**
+	 * Special case: Got UC_RCRESET on setmode.
+	 * This means that remote side isn't setup. In this case
+	 * simply retry after some 10 secs...
+	 */
+	if ((fsm_getstate(fi) == CH_STATE_SETUPWAIT) &&
+	    ((event == CH_EVENT_UC_RCRESET) ||
+	     (event == CH_EVENT_UC_RSRESET)   )         ) {
+		fsm_newstate(fi, CH_STATE_STARTRETRY);
+		fsm_deltimer(&ch->timer);
+		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+		if (CHANNEL_DIRECTION(ch->flags) == READ) {
+			int rc = halt_IO (ch->irq, (intparm_t)ch, 0);
+			if (rc != 0)
+				ccw_check_return_code(ch, rc);
+		}
+		return;
+	}
+
+	printk(KERN_DEBUG "%s: Error %s during %s channel setup state=%s\n",
+	       dev->name, ch_event_names[event],
+	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX",
+	       fsm_getstate_str(fi));
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		fsm_newstate(fi, CH_STATE_RXERR);
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+	} else {
+		fsm_newstate(fi, CH_STATE_TXERR);
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+	}
+}
+
+/**
+ * Restart a channel after an error.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_restart(fsm_instance *fi, int event, void *arg)
+{
+	unsigned long saveflags;
+	int   oldstate;
+	int   rc;
+
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	printk(KERN_DEBUG "%s: %s channel restart\n", dev->name,
+	       (CHANNEL_DIRECTION(ch->flags) == READ) ? "RX" : "TX");
+
+	fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+	oldstate = fsm_getstate(fi);
+	fsm_newstate(fi, CH_STATE_STARTWAIT);
+	if (event == CH_EVENT_TIMER)
+		s390irq_spin_lock_irqsave(ch->irq, saveflags);
+	rc = halt_IO (ch->irq, (intparm_t)ch, 0);
+	if (event == CH_EVENT_TIMER)
+		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);
+	if (rc != 0) {
+		fsm_deltimer(&ch->timer);
+		fsm_newstate(fi, oldstate);
+		ccw_check_return_code(ch, rc);
+	}
+}
+
+/**
+ * Handle error during RX initial handshake (exchange of
+ * 0-length block header)
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_rxiniterr(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	if (event == CH_EVENT_TIMER) {
+		fsm_deltimer(&ch->timer);
+		printk(KERN_DEBUG "%s: Timeout during RX init handshake\n",
+		       dev->name);
+		if (ch->retry++ < 3)
+			ch_action_restart(fi, event, arg);
+		else {
+			fsm_newstate(fi, CH_STATE_RXERR);
+			fsm_event(((ctc_priv *)dev->priv)->fsm,
+				  DEV_EVENT_RXDOWN, dev);
+		}
+	} else
+		printk(KERN_WARNING "%s: Error during RX init handshake\n",
+		       dev->name);
+}
+
+/**
+ * Notify device statemachine if we gave up initialization
+ * of RX channel.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_rxinitfail(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	fsm_newstate(fi, CH_STATE_RXERR);
+	printk(KERN_WARNING "%s: RX initialization failed\n", dev->name);
+	printk(KERN_WARNING "%s: RX <-> RX connection detected\n", dev->name);
+	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+}
+
+/**
+ * Handle RX Unit check remote reset (remote disconnected)
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_rxdisc(fsm_instance *fi, int event, void *arg)
+{
+	channel    *ch = (channel *)arg;
+	channel    *ch2;
+	net_device *dev = ch->netdev;
+
+	fsm_deltimer(&ch->timer);
+	printk(KERN_DEBUG "%s: Got remote disconnect, re-initializing ...\n",
+	       dev->name);
+
+	/**
+	 * Notify device statemachine
+	 */
+	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+
+	fsm_newstate(fi, CH_STATE_DTERM);
+	ch2 = ((ctc_priv *)dev->priv)->channel[WRITE];
+	fsm_newstate(ch2->fsm, CH_STATE_DTERM);
+
+	halt_IO(ch->irq, (intparm_t)ch, 0);
+	halt_IO(ch2->irq, (intparm_t)ch2, 0);
+}
+
+/**
+ * Handle error during TX channel initialization.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_txiniterr(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	if (event == CH_EVENT_TIMER) {
+		fsm_deltimer(&ch->timer);
+		printk(KERN_DEBUG "%s: Timeout during TX init handshake\n",
+		       dev->name);
+		if (ch->retry++ < 3)
+			ch_action_restart(fi, event, arg);
+		else {
+			fsm_newstate(fi, CH_STATE_TXERR);
+			fsm_event(((ctc_priv *)dev->priv)->fsm,
+				  DEV_EVENT_TXDOWN, dev);
+		}
+	} else
+		printk(KERN_WARNING "%s: Error during TX init handshake\n",
+		       dev->name);
+}
+
+/**
+ * Handle TX timeout by retrying operation.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_txretry(fsm_instance *fi, int event, void *arg)
+{
+	channel    *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+	unsigned long saveflags;
+
+	fsm_deltimer(&ch->timer);
+	if (ch->retry++ > 3) {
+		printk(KERN_DEBUG "%s: TX retry failed, restarting channel\n",
+		       dev->name);
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+		ch_action_restart(fi, event, arg);
+	} else {
+		struct sk_buff *skb;
+
+		printk(KERN_DEBUG "%s: TX retry %d\n", dev->name, ch->retry);
+		if ((skb = skb_peek(&ch->io_queue))) {
+			int rc = 0;
+
+			fsm_addtimer(&ch->timer, 1000, CH_EVENT_TIMER, ch);
+			if (event == CH_EVENT_TIMER)
+				s390irq_spin_lock_irqsave(ch->irq, saveflags);
+			if (ch->dccw)
+				rc = do_IO(ch->irq, ch->dccw, (intparm_t)ch,
+					   0xff, 0);
+			else {
+				clear_normalized_cda(&ch->ccw[1]);
+				ch->ccw[1].count = skb->len;
+				set_normalized_cda(&ch->ccw[1],
+						   virt_to_phys(skb->data));
+				rc = do_IO(ch->irq, &ch->ccw[0],
+					   (intparm_t)ch, 0xff, 0);
+			}
+			if (event == CH_EVENT_TIMER)
+				s390irq_spin_unlock_irqrestore(ch->irq,
+							       saveflags);
+			if (rc != 0) {
+				fsm_deltimer(&ch->timer);
+				ccw_check_return_code(ch, rc);
+				ctc_purge_skb_queue(&ch->io_queue);
+			}
+		}
+	}
+
+}
+
+/**
+ * Handle fatal errors during an I/O command.
+ *
+ * @param fi    An instance of a channel statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from channel * upon call.
+ */
+static void ch_action_iofatal(fsm_instance *fi, int event, void *arg)
+{
+	channel *ch = (channel *)arg;
+	net_device *dev = ch->netdev;
+
+	fsm_deltimer(&ch->timer);
+	if (CHANNEL_DIRECTION(ch->flags) == READ) {
+		printk(KERN_DEBUG "%s: RX I/O error\n", dev->name);
+		fsm_newstate(fi, CH_STATE_RXERR);
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_RXDOWN, dev);
+	} else {
+		printk(KERN_DEBUG "%s: TX I/O error\n", dev->name);
+		fsm_newstate(fi, CH_STATE_TXERR);
+		fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_TXDOWN, dev);
+	}
+}
+
+/**
+ * The statemachine for a channel.
+ */
+static const fsm_node ch_fsm[] = {
+	{ CH_STATE_STOPPED,    CH_EVENT_STOP,       fsm_action_nop       },
+	{ CH_STATE_STOPPED,    CH_EVENT_START,      ch_action_start      },
+	{ CH_STATE_STOPPED,    CH_EVENT_FINSTAT,    fsm_action_nop       },
+
+	{ CH_STATE_STARTWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_STARTWAIT,  CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_STARTWAIT,  CH_EVENT_FINSTAT,    ch_action_setmode    },
+	{ CH_STATE_STARTWAIT,  CH_EVENT_TIMER,      ch_action_setuperr   },
+	{ CH_STATE_STARTWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_STARTWAIT,  CH_EVENT_IO_EIO,     ch_action_iofatal    },
+
+	{ CH_STATE_STARTRETRY, CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_STARTRETRY, CH_EVENT_TIMER,      ch_action_setmode    },
+	{ CH_STATE_STARTRETRY, CH_EVENT_FINSTAT,    fsm_action_nop       },
+
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_FINSTAT,    ch_action_firstio    },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_UC_RCRESET, ch_action_setuperr   },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_UC_RSRESET, ch_action_setuperr   },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_TIMER,      ch_action_setmode    },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_SETUPWAIT,  CH_EVENT_IO_EIO,     ch_action_iofatal    },
+
+	{ CH_STATE_RXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_RXINIT,     CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_RXINIT,     CH_EVENT_FINSTAT,    ch_action_rxidle     },
+	{ CH_STATE_RXINIT,     CH_EVENT_UC_RCRESET, ch_action_rxiniterr  },
+	{ CH_STATE_RXINIT,     CH_EVENT_UC_RSRESET, ch_action_rxiniterr  },
+	{ CH_STATE_RXINIT,     CH_EVENT_TIMER,      ch_action_rxiniterr  },
+	{ CH_STATE_RXINIT,     CH_EVENT_ATTNBUSY,   ch_action_rxinitfail },
+	{ CH_STATE_RXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_RXINIT,     CH_EVENT_IO_EIO,     ch_action_iofatal    },
+	{ CH_STATE_RXINIT,     CH_EVENT_UC_ZERO,    ch_action_firstio    },
+
+	{ CH_STATE_RXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_RXIDLE,     CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_RXIDLE,     CH_EVENT_FINSTAT,    ch_action_rx         },
+	{ CH_STATE_RXIDLE,     CH_EVENT_UC_RCRESET, ch_action_rxdisc     },
+//	{ CH_STATE_RXIDLE,     CH_EVENT_UC_RSRESET, ch_action_rxretry    },
+	{ CH_STATE_RXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_RXIDLE,     CH_EVENT_IO_EIO,     ch_action_iofatal    },
+
+	{ CH_STATE_TXINIT,     CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_TXINIT,     CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_TXINIT,     CH_EVENT_FINSTAT,    ch_action_txidle     },
+	{ CH_STATE_TXINIT,     CH_EVENT_UC_RCRESET, ch_action_txiniterr  },
+	{ CH_STATE_TXINIT,     CH_EVENT_UC_RSRESET, ch_action_txiniterr  },
+	{ CH_STATE_TXINIT,     CH_EVENT_TIMER,      ch_action_txiniterr  },
+	{ CH_STATE_TXINIT,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_TXINIT,     CH_EVENT_IO_EIO,     ch_action_iofatal    },
+
+	{ CH_STATE_TXIDLE,     CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_TXIDLE,     CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_TXIDLE,     CH_EVENT_FINSTAT,    ch_action_firstio    },
+	{ CH_STATE_TXIDLE,     CH_EVENT_UC_RCRESET, fsm_action_nop       },
+	{ CH_STATE_TXIDLE,     CH_EVENT_UC_RSRESET, fsm_action_nop       },
+	{ CH_STATE_TXIDLE,     CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_TXIDLE,     CH_EVENT_IO_EIO,     ch_action_iofatal    },
+
+	{ CH_STATE_TERM,       CH_EVENT_STOP,       fsm_action_nop       },
+	{ CH_STATE_TERM,       CH_EVENT_START,      ch_action_restart    },
+	{ CH_STATE_TERM,       CH_EVENT_FINSTAT,    ch_action_stopped    },
+	{ CH_STATE_TERM,       CH_EVENT_UC_RCRESET, fsm_action_nop       },
+	{ CH_STATE_TERM,       CH_EVENT_UC_RSRESET, fsm_action_nop       },
+
+	{ CH_STATE_DTERM,      CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_DTERM,      CH_EVENT_START,      ch_action_restart    },
+	{ CH_STATE_DTERM,      CH_EVENT_FINSTAT,    ch_action_setmode    },
+	{ CH_STATE_DTERM,      CH_EVENT_UC_RCRESET, fsm_action_nop       },
+	{ CH_STATE_DTERM,      CH_EVENT_UC_RSRESET, fsm_action_nop       },
+
+	{ CH_STATE_TX,         CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_TX,         CH_EVENT_START,      fsm_action_nop       },
+	{ CH_STATE_TX,         CH_EVENT_FINSTAT,    ch_action_txdone     },
+	{ CH_STATE_TX,         CH_EVENT_UC_RCRESET, ch_action_txretry    },
+	{ CH_STATE_TX,         CH_EVENT_UC_RSRESET, ch_action_txretry    },
+	{ CH_STATE_TX,         CH_EVENT_TIMER,      ch_action_txretry    },
+	{ CH_STATE_TX,         CH_EVENT_IO_ENODEV,  ch_action_iofatal    },
+	{ CH_STATE_TX,         CH_EVENT_IO_EIO,     ch_action_iofatal    },
+
+	{ CH_STATE_RXERR,      CH_EVENT_STOP,       ch_action_haltio     },
+	{ CH_STATE_TXERR,      CH_EVENT_STOP,       ch_action_haltio     },
+};
+
+static const int CH_FSM_LEN = sizeof(ch_fsm) / sizeof(fsm_node);
+
+/**
+ * Functions related to setup and device detection.
+ *****************************************************************************/
+
+/**
+ * Add a new channel to the list of channels.
+ * Keeps the channel list sorted.
+ *
+ * @param irq   The IRQ to be used by the new channel.
+ * @param devno The device number of the new channel.
+ * @param type  The type class of the new channel.
+ *
+ * @return 0 on success, !0 on error.
+ */
+static int add_channel(int irq, __u16 devno, channel_type_t type)
+{
+	channel **c = &channels;
+	channel *ch;
+	char name[10];
+	int ret = -1;
+
+	if ((ch = (channel *)kmalloc(sizeof(channel), GFP_KERNEL)) == NULL)
+		goto out;
+	memset(ch, 0, sizeof(channel));
+	if ((ch->ccw = (ccw1_t *)kmalloc(sizeof(ccw1_t) * 5,
+					 GFP_KERNEL|GFP_DMA)) == NULL)
+		goto out_ch;
+
+	/**
+	 * "static" ccws are used in the following way:
+	 *
+	 * ccw[0..2] (Channel program for generic I/O):
+	 *           0: prepare
+	 *           1: read or write (depending on direction)
+	 *           2: nop
+	 * ccw[3..4] (Channel program for initial channel setup):
+	 *           3: set extended mode
+	 *           4: nop
+	 *
+	 * ch->ccw[0..2] are initialized in ch_action_start because
+	 * the channel's direction is yet unknown here.
+	 */
+	ch->ccw[3].cmd_code = CCW_CMD_SET_EXTENDED;
+	ch->ccw[3].flags    = CCW_FLAG_SLI;
+	ch->ccw[3].count    = 0;
+	ch->ccw[3].cda      = 0;
+	
+	ch->ccw[4].cmd_code = CCW_CMD_NOOP;
+	ch->ccw[4].flags    = CCW_FLAG_SLI;
+	ch->ccw[4].count    = 0;
+	ch->ccw[4].cda      = 0;
+
+	ch->irq = irq;
+	ch->devno = devno;
+	ch->type = type;
+	sprintf(name, "ch-%04x", devno);
+	ch->fsm = init_fsm(name, ch_state_names,
+			ch_event_names, NR_CH_STATES, NR_CH_EVENTS,
+			ch_fsm, CH_FSM_LEN, GFP_KERNEL);
+	if (ch->fsm == NULL)
+		goto out_ccw;
+	fsm_newstate(ch->fsm, CH_STATE_IDLE);
+	if ((ch->devstat = (devstat_t*)kmalloc(sizeof(devstat_t), GFP_KERNEL))
+	    == NULL)
+		goto out_ccw;
+	memset(ch->devstat, 0, sizeof(devstat_t));
+	while (*c && ((*c)->devno < devno))
+		c = &(*c)->next;
+	if ((*c)->devno == devno) {
+		printk(KERN_DEBUG
+		       "ctc: add_channel: device %04x already in list\n",
+		       (*c)->devno);
+		ret = 0;
+		goto out_devstat;
+	}
+	fsm_settimer(ch->fsm, &ch->timer);
+	skb_queue_head_init(&ch->io_queue);
+	skb_queue_head_init(&ch->collect_queue);
+	ch->next = *c;
+	*c = ch;
+	return 0;
+out_devstat:
+	kfree(ch->devstat);
+out_ccw:
+	kfree(ch->ccw);
+out_ch:
+	kfree(ch);
+out:
+	if (ret)
+		printk(KERN_WARNING "ctc: Out of memory in add_channel\n");
+	return ret;
+}
+
+/**
+ * scan for all channels and create an entry in the channels list
+ * for every supported channel.
+ *
+ * @param print_result Flag: If !0, print a final result.
+ */
+static void channel_scan(int print_result)
+{
+	int	   irq;
+	int        nr_escon = 0;
+	int        nr_ctca  = 0;
+	s390_dev_info_t di;
+
+	for (irq = 0; irq < NR_IRQS; irq++) {
+		if (get_dev_info_by_irq(irq, &di) == 0) {
+			if ((di.status == DEVSTAT_NOT_OPER) ||
+			    (di.status == DEVSTAT_DEVICE_OWNED))
+				continue;
+			switch (channel_type(&di.sid_data)) {
+				case channel_type_ctca:
+					/* CTC/A */
+					if (!add_channel(irq, di.devno,
+							 channel_type_ctca))
+						nr_ctca++;
+					break;
+				case channel_type_escon:
+					/* ESCON */
+					if (!add_channel(irq, di.devno,
+							 channel_type_escon))
+						nr_escon++;
+					break;
+			default:
+			}
+		}
+	}
+	if (print_result) {
+		if (nr_escon + nr_ctca)
+			printk(KERN_INFO
+			       "ctc: %d CTC/A channel%s and %d ESCON "
+			       "channel%s found.\n",
+			       nr_ctca, (nr_ctca == 1) ? "s" : "",
+			       nr_escon, (nr_escon == 1) ? "s" : "");
+		else
+			printk(KERN_INFO "ctc: No channel devices found.\n");
+	}
+}
+
+/**
+ * Release a specific channel in the channel list.
+ *
+ * @param ch Pointer to channel struct to be released.
+ */
+static void channel_free(channel *ch)
+{
+	ch->flags &= ~CHANNEL_FLAGS_INUSE;
+	fsm_newstate(ch->fsm, CH_STATE_IDLE);
+}
+
+
+/**
+ * Get a specific channel from the channel list.
+ *
+ * @param type Type of channel we are interested in.
+ * @param devno Device number of channel we are interested in.
+ * @param direction Direction we want to use this channel for.
+ *
+ * @return Pointer to a channel or NULL if no matching channel available.
+ */
+static channel *channel_get(channel_type_t type, int devno, int direction)
+{
+	channel *ch = channels;
+
+#ifdef DEBUG
+	printk(KERN_DEBUG
+	       "ctc: %s(): searching for ch with devno %d and type %d\n",
+	       __FUNCTION__, devno, type);
+#endif
+
+	while (ch && ((ch->devno != devno) || (ch->type != type))) {
+#ifdef DEBUG
+		printk(KERN_DEBUG
+		       "ctc: %s(): ch=0x%p (devno=%d, type=%d\n",
+		       __FUNCTION__, ch, ch->devno, ch->type);
+#endif
+		ch = ch->next;
+	}
+#ifdef DEBUG
+	printk(KERN_DEBUG
+	       "ctc: %s(): ch=0x%pq (devno=%d, type=%d\n",
+	       __FUNCTION__, ch, ch->devno, ch->type);
+#endif
+	if (!ch) {
+		printk(KERN_WARNING "ctc: %s(): channel with devno %d "
+		       "and type %d not found in channel list\n",
+	       __FUNCTION__, devno, type);
+	}
+	else {
+		if (ch->flags & CHANNEL_FLAGS_INUSE)
+			ch = NULL;
+		else {
+			ch->flags |= CHANNEL_FLAGS_INUSE;
+			ch->flags &= ~CHANNEL_FLAGS_RWMASK;
+			ch->flags |= (direction == WRITE)
+				? CHANNEL_FLAGS_WRITE:CHANNEL_FLAGS_READ;
+			fsm_newstate(ch->fsm, CH_STATE_STOPPED);
+		}
+	}
+	return ch;
+}
+
+
+/**
+ * Get the next free channel from the channel list
+ *
+ * @param type Type of channel we are interested in.
+ * @param direction Direction we want to use this channel for.
+ *
+ * @return Pointer to a channel or NULL if no matching channel available.
+ */
+static channel *channel_get_next(channel_type_t type, int direction)
+{
+	channel *ch = channels;
+
+	while (ch && (ch->type != type || (ch->flags & CHANNEL_FLAGS_INUSE)))
+		ch = ch->next;
+	if (ch) {
+		ch->flags |= CHANNEL_FLAGS_INUSE;
+		ch->flags &= ~CHANNEL_FLAGS_RWMASK;
+		ch->flags |= (direction == WRITE)
+			? CHANNEL_FLAGS_WRITE:CHANNEL_FLAGS_READ;
+		fsm_newstate(ch->fsm, CH_STATE_STOPPED);
+	}
+	return ch;
+}
+
+/**
+ * Return the channel type by name.
+ *
+ * @param name Name of network interface.
+ *
+ * @return Type class of channel to be used for that interface.
+ */
+static channel_type_t inline extract_channel_media(char *name)
+{
+	channel_type_t ret = channel_type_unknown;
+
+	if (name != NULL) {
+		if (strncmp(name, "ctc", 3) == 0)
+			ret = channel_type_ctca;
+		if (strncmp(name, "escon", 5) == 0)
+			ret = channel_type_escon;
+	}
+	return ret;
+}
+
+/**
+ * Find a channel in the list by its IRQ.
+ *
+ * @param irq IRQ to search for.
+ *
+ * @return Pointer to channel or NULL if no matching channel found.
+ */
+static channel *find_channel_by_irq(int irq)
+{
+	channel *ch = channels;
+	while (ch && (ch->irq != irq))
+		ch = ch->next;
+	return ch;
+}
+
+/**
+ * Main IRQ handler.
+ *
+ * @param irq     The IRQ to handle.
+ * @param intparm IRQ params.
+ * @param regs    CPU registers.
+ */
+static void ctc_irq_handler (int irq, void *intparm, struct pt_regs *regs)
+{
+	devstat_t  *devstat = (devstat_t *)intparm;
+	channel    *ch = (channel *)devstat->intparm;
+	net_device *dev;
+
+	/**
+	 * Check for unsolicited interrupts.
+	 * If intparm is NULL, then loop over all our known
+	 * channels and try matching the irq number.
+	 */
+	if (ch == NULL) {
+		if ((ch = find_channel_by_irq(irq)) == NULL) {
+			printk(KERN_WARNING
+			       "ctc: Got unsolicited irq: %04x c-%02x d-%02x"
+			       "f-%02x\n", devstat->devno, devstat->cstat,
+			       devstat->dstat, devstat->flag);
+			goto done;
+		}
+	}
+
+	clear_normalized_cda(&ch->ccw[1]);
+	dev = (net_device *)(ch->netdev);
+	if (dev == NULL) {
+		printk(KERN_CRIT
+		       "ctc: ctc_irq_handler dev = NULL irq=%d, ch=0x%p\n",
+		       irq, ch);
+		goto done;
+	}
+	if (intparm == NULL)
+		printk(KERN_DEBUG "%s: Channel %04x found by IRQ %d\n",
+		       dev->name, ch->devno, irq);
+
+#ifdef DEBUG
+	printk(KERN_DEBUG
+	       "%s: interrupt for device: %04x received c-%02x d-%02x "
+	       "f-%02x\n", dev->name, devstat->devno, devstat->cstat,
+	       devstat->dstat, devstat->flag);
+#endif
+
+	/* Check for good subchannel return code, otherwise error message */
+	if (devstat->cstat) {
+		fsm_event(ch->fsm, CH_EVENT_SC_UNKNOWN, ch);
+		printk(KERN_WARNING
+		       "%s: subchannel check for device: %04x - %02x %02x "
+		       "%02x\n", dev->name, ch->devno, devstat->cstat,
+		       devstat->dstat, devstat->flag);
+		goto done;
+	}
+
+	/* Check the reason-code of a unit check */
+	if (devstat->dstat & DEV_STAT_UNIT_CHECK) {
+		ccw_unit_check(ch, devstat->ii.sense.data[0]);
+		goto done;
+	}
+	if (devstat->dstat & DEV_STAT_BUSY) {
+		if (devstat->dstat & DEV_STAT_ATTENTION)
+			fsm_event(ch->fsm, CH_EVENT_ATTNBUSY, ch);
+		else
+			fsm_event(ch->fsm, CH_EVENT_BUSY, ch);
+		goto done;
+	}
+	if (devstat->dstat & DEV_STAT_ATTENTION) {
+		fsm_event(ch->fsm, CH_EVENT_ATTN, ch);
+		goto done;
+	}
+	if (devstat->flag & DEVSTAT_FINAL_STATUS)
+		fsm_event(ch->fsm, CH_EVENT_FINSTAT, ch);
+	else
+		fsm_event(ch->fsm, CH_EVENT_IRQ, ch);
+
+ done:
+}
+
+/**
+ * Actions for interface - statemachine.
+ *****************************************************************************/
+
+/**
+ * Startup channels by sending CH_EVENT_START to each channel.
+ *
+ * @param fi    An instance of an interface statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from net_device * upon call.
+ */
+static void dev_action_start(fsm_instance *fi, int event, void *arg)
+{
+	net_device *dev = (net_device *)arg;
+	ctc_priv   *privptr = dev->priv;
+	int        direction;
+
+	fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+	for (direction = READ; direction <= WRITE; direction++) {
+		channel *ch = privptr->channel[direction];
+		fsm_event(ch->fsm, CH_EVENT_START, ch);
+	}
+}
+
+/**
+ * Shutdown channels by sending CH_EVENT_STOP to each channel.
+ *
+ * @param fi    An instance of an interface statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from net_device * upon call.
+ */
+static void dev_action_stop(fsm_instance *fi, int event, void *arg)
+{
+	net_device *dev = (net_device *)arg;
+	ctc_priv   *privptr = dev->priv;
+	int        direction;
+
+	fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+	for (direction = READ; direction <= WRITE; direction++) {
+		channel *ch = privptr->channel[direction];
+		fsm_event(ch->fsm, CH_EVENT_STOP, ch);
+	}
+}
+
+/**
+ * Called from channel statemachine
+ * when a channel is up and running.
+ *
+ * @param fi    An instance of an interface statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from net_device * upon call.
+ */
+static void dev_action_chup(fsm_instance *fi, int event, void *arg)
+{
+	net_device *dev = (net_device *)arg;
+
+	switch (fsm_getstate(fi)) {
+		case DEV_STATE_STARTWAIT_RXTX:
+			if (event == DEV_EVENT_RXUP)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+			else
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+			break;
+		case DEV_STATE_STARTWAIT_RX:
+			if (event == DEV_EVENT_RXUP) {
+				fsm_newstate(fi, DEV_STATE_RUNNING);
+				printk(KERN_INFO
+				       "%s: connected with remote side\n",
+				       dev->name);
+				ctc_clear_busy(dev);
+			}
+			break;
+		case DEV_STATE_STARTWAIT_TX:
+			if (event == DEV_EVENT_TXUP) {
+				fsm_newstate(fi, DEV_STATE_RUNNING);
+				printk(KERN_INFO
+				       "%s: connected with remote side\n",
+				       dev->name);
+				ctc_clear_busy(dev);
+			}
+			break;
+		case DEV_STATE_STOPWAIT_TX:
+			if (event == DEV_EVENT_RXUP)
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+			break;
+		case DEV_STATE_STOPWAIT_RX:
+			if (event == DEV_EVENT_TXUP)
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_RXTX);
+			break;
+	}
+}
+
+/**
+ * Called from channel statemachine
+ * when a channel has been shutdown.
+ *
+ * @param fi    An instance of an interface statemachine.
+ * @param event The event, just happened.
+ * @param arg   Generic pointer, casted from net_device * upon call.
+ */
+static void dev_action_chdown(fsm_instance *fi, int event, void *arg)
+{
+	switch (fsm_getstate(fi)) {
+		case DEV_STATE_RUNNING:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_TX);
+			else
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RX);
+			break;
+		case DEV_STATE_STARTWAIT_RX:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+			break;
+		case DEV_STATE_STARTWAIT_TX:
+			if (event == DEV_EVENT_RXDOWN)
+				fsm_newstate(fi, DEV_STATE_STARTWAIT_RXTX);
+			break;
+		case DEV_STATE_STOPWAIT_RXTX:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_RX);
+			else
+				fsm_newstate(fi, DEV_STATE_STOPWAIT_TX);
+			break;
+		case DEV_STATE_STOPWAIT_RX:
+			if (event == DEV_EVENT_RXDOWN)
+				fsm_newstate(fi, DEV_STATE_STOPPED);
+			break;
+		case DEV_STATE_STOPWAIT_TX:
+			if (event == DEV_EVENT_TXDOWN)
+				fsm_newstate(fi, DEV_STATE_STOPPED);
+			break;
+	}
+}
+
+static const fsm_node dev_fsm[] = {
+	{ DEV_STATE_STOPPED,        DEV_EVENT_START,   dev_action_start  },
+
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_START,   dev_action_start  },
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_RXDOWN,  dev_action_chdown },
+	{ DEV_STATE_STOPWAIT_RXTX,  DEV_EVENT_TXDOWN,  dev_action_chdown },
+
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_START,   dev_action_start  },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXUP,    dev_action_chup   },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_TXUP,    dev_action_chup   },
+	{ DEV_STATE_STOPWAIT_RX,    DEV_EVENT_RXDOWN,  dev_action_chdown },
+
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_START,   dev_action_start  },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_RXUP,    dev_action_chup   },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXUP,    dev_action_chup   },
+	{ DEV_STATE_STOPWAIT_TX,    DEV_EVENT_TXDOWN,  dev_action_chdown },
+
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_STOP,    dev_action_stop   },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXUP,    dev_action_chup   },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXUP,    dev_action_chup   },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_RXDOWN,  dev_action_chdown },
+	{ DEV_STATE_STARTWAIT_RXTX, DEV_EVENT_TXDOWN,  dev_action_chdown },
+
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_STOP,    dev_action_stop   },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXUP,    dev_action_chup   },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_TXUP,    dev_action_chup   },
+	{ DEV_STATE_STARTWAIT_TX,   DEV_EVENT_RXDOWN,  dev_action_chdown },
+
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_STOP,    dev_action_stop   },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_RXUP,    dev_action_chup   },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXUP,    dev_action_chup   },
+	{ DEV_STATE_STARTWAIT_RX,   DEV_EVENT_TXDOWN,  dev_action_chdown },
+
+	{ DEV_STATE_RUNNING,        DEV_EVENT_STOP,    dev_action_stop   },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_RXDOWN,  dev_action_chdown },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_TXDOWN,  dev_action_chdown },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_TXUP,    fsm_action_nop    },
+	{ DEV_STATE_RUNNING,        DEV_EVENT_RXUP,    fsm_action_nop    },
+};
+
+static const int DEV_FSM_LEN = sizeof(dev_fsm) / sizeof(fsm_node);
+
+/**
+ * Transmit a packet.
+ * This is a helper function for ctc_tx().
+ *
+ * @param ch Channel to be used for sending.
+ * @param skb Pointer to struct sk_buff of packet to send.
+ *            The linklevel header has already been set up
+ *            by ctc_tx().
+ *
+ * @return 0 on success, -ERRNO on failure. (Never fails.)
+ */
+static int transmit_skb(channel *ch, struct sk_buff *skb) {
+	unsigned long saveflags;
+	ll_header header;
+	int       rc = 0;
+
+	if (fsm_getstate(ch->fsm) != CH_STATE_TXIDLE) {
+		int l = skb->len + LL_HEADER_LENGTH;
+
+		spin_lock_irqsave(&ch->collect_lock, saveflags);
+		if (ch->collect_len + l > ch->max_bufsize - 2)
+			rc = -EBUSY;
+		else {
+			atomic_inc(&skb->users);
+			header.length = l;
+			header.type = skb->protocol;
+			header.unused = 0;
+			memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+			       LL_HEADER_LENGTH);
+			skb_queue_tail(&ch->collect_queue, skb);
+			ch->collect_len += l;
+		}
+		spin_unlock_irqrestore(&ch->collect_lock, saveflags);
+	} else {
+		__u16 block_len;
+
+		/**
+		 * Protect skb against beeing free'd by upper
+		 * layers.
+		 */
+		atomic_inc(&skb->users);
+		ch->prof.txlen += skb->len;
+		header.length = skb->len + LL_HEADER_LENGTH;
+		header.type = skb->protocol;
+		header.unused = 0;
+		memcpy(skb_push(skb, LL_HEADER_LENGTH), &header,
+		       LL_HEADER_LENGTH);
+		block_len = skb->len + 2;
+		*((__u16 *)skb_push(skb, 2)) = block_len;
+		skb_queue_tail(&ch->io_queue, skb);
+		ch->retry = 0;
+		fsm_newstate(ch->fsm, CH_STATE_TX);
+		fsm_addtimer(&ch->timer, CTC_TIMEOUT_5SEC, CH_EVENT_TIMER, ch);
+		ch->ccw[1].count = block_len;
+		set_normalized_cda(&ch->ccw[1], virt_to_phys(skb->data));
+		s390irq_spin_lock_irqsave(ch->irq, saveflags);
+		ch->prof.send_stamp = xtime;
+		rc = do_IO(ch->irq, &ch->ccw[0], (intparm_t)ch, 0xff, 0);
+		s390irq_spin_unlock_irqrestore(ch->irq, saveflags);
+		ch->prof.doios_single++;
+		if (rc != 0) {
+			fsm_deltimer(&ch->timer);
+			ccw_check_return_code(ch, rc);
+			skb_dequeue_tail(&ch->io_queue);
+			/**
+			 * Remove our header. It gets added
+			 * again on retransmit.
+			 */
+			skb_pull(skb, LL_HEADER_LENGTH + 2);
+		}
+	}
+
+	return rc;
+}
+
+/**
+ * Interface API for upper network layers
+ *****************************************************************************/
+
+/**
+ * Open an interface.
+ * Called from generic network layer when ifconfig up is run.
+ *
+ * @param dev Pointer to interface struct.
+ *
+ * @return 0 on success, -ERRNO on failure. (Never fails.)
+ */
+static int ctc_open(net_device *dev) {
+	MOD_INC_USE_COUNT;
+	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_START, dev);
+	return 0;
+}
+
+/**
+ * Close an interface.
+ * Called from generic network layer when ifconfig down is run.
+ *
+ * @param dev Pointer to interface struct.
+ *
+ * @return 0 on success, -ERRNO on failure. (Never fails.)
+ */
+static int ctc_close(net_device *dev) {
+	SET_DEVICE_START(dev, 0);
+	fsm_event(((ctc_priv *)dev->priv)->fsm, DEV_EVENT_STOP, dev);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/**
+ * Start transmission of a packet.
+ * Called from generic network device layer.
+ *
+ * @param skb Pointer to buffer containing the packet.
+ * @param dev Pointer to interface struct.
+ *
+ * @return 0 if packet consumed, !0 if packet rejected.
+ *         Note: If we return !0, then the packet is free'd by
+ *               the generic network layer.
+ */
+static int ctc_tx(struct sk_buff *skb, net_device *dev)
+{
+	int       rc = 0;
+	ctc_priv  *privptr = (ctc_priv *)dev->priv;
+
+	/**
+	 * Some sanity checks ...
+	 */
+	if (skb == NULL) {
+		printk(KERN_WARNING "%s: NULL sk_buff passed\n", dev->name);
+		privptr->stats.tx_dropped++;
+		return 0;
+	}
+	if (skb_headroom(skb) < (LL_HEADER_LENGTH + 2)) {
+		printk(KERN_WARNING "%s: Got sk_buff with head room < %ld bytes\n",
+				dev->name, LL_HEADER_LENGTH + 2);
+		dev_kfree_skb(skb);
+		privptr->stats.tx_dropped++;
+		return 0;
+	}
+
+	/**
+	 * If channels are not running, try to restart them
+	 * notify anybody about a link failure and throw
+	 * away packet. 
+	 */
+	if (fsm_getstate(privptr->fsm) != DEV_STATE_RUNNING) {
+		fsm_event(privptr->fsm, DEV_EVENT_START, dev);
+		dst_link_failure(skb);
+		dev_kfree_skb(skb);
+		privptr->stats.tx_dropped++;
+		privptr->stats.tx_errors++;
+		privptr->stats.tx_carrier_errors++;
+		return 0;
+	}
+
+	if (ctc_test_and_set_busy(dev))
+		return -EBUSY;
+
+	dev->trans_start = jiffies;
+	if (transmit_skb(privptr->channel[WRITE], skb) != 0)
+		rc = 1;
+	ctc_clear_busy(dev);
+	return rc;
+}
+
+
+/**
+ * Sets MTU of an interface.
+ *
+ * @param dev     Pointer to interface struct.
+ * @param new_mtu The new MTU to use for this interface.
+ *
+ * @return 0 on success, -EINVAL if MTU is out of valid range.
+ *         (valid range is 576 .. 65527). If VM is on the
+ *         remote side, maximum MTU is 32760, however this is
+ *         <em>not</em> checked here.
+ */
+static int ctc_change_mtu(net_device *dev, int new_mtu) {
+	ctc_priv  *privptr = (ctc_priv *)dev->priv;
+
+	if ((new_mtu < 576) || (new_mtu > 65527) ||
+	    (new_mtu > (privptr->channel[READ]->max_bufsize -
+			LL_HEADER_LENGTH - 2)))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	dev->hard_header_len = LL_HEADER_LENGTH + 2;
+	return 0;
+}
+
+
+/**
+ * Returns interface statistics of a device.
+ *
+ * @param dev Pointer to interface struct.
+ *
+ * @return Pointer to stats struct of this interface.
+ */
+static struct net_device_stats *ctc_stats(net_device *dev) {
+	return &((ctc_priv *)dev->priv)->stats;
+}
+
+/**
+ * procfs related structures and routines
+ *****************************************************************************/
+
+static net_device *find_netdev_by_ino(unsigned long ino)
+{
+	channel *ch = channels;
+	net_device *dev = NULL;
+	ctc_priv *privptr;
+
+	while (ch) {
+		if (ch->netdev != dev) {
+			dev = ch->netdev;
+			privptr = (ctc_priv *)dev->priv;
+
+			if ((privptr->proc_ctrl_entry->low_ino == ino) ||
+			    (privptr->proc_stat_entry->low_ino == ino))
+				return dev;
+		}
+		ch = ch->next;
+	}
+	return NULL;
+}
+
+#if LINUX_VERSION_CODE < 0x020363
+/**
+ * Lock the module, if someone changes into
+ * our proc directory.
+ */
+static void ctc_fill_inode(struct inode *inode, int fill)
+{
+	if (fill) {
+		MOD_INC_USE_COUNT;
+	} else
+		MOD_DEC_USE_COUNT;
+}
+#endif
+
+#define CTRL_BUFSIZE 40
+
+static int ctc_ctrl_open(struct inode *inode, struct file *file)
+{
+	file->private_data = kmalloc(CTRL_BUFSIZE, GFP_KERNEL);
+	if (file->private_data == NULL)
+		return -ENOMEM;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int ctc_ctrl_close(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static ssize_t ctc_ctrl_write(struct file *file, const char *buf, size_t count,
+			   loff_t *off)
+{
+	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
+	net_device   *dev;
+	ctc_priv     *privptr;
+	char         *e;
+	int          bs1;
+	char         tmp[40];
+
+	if (!(dev = find_netdev_by_ino(ino)))
+		return -ENODEV;
+	if (off != &file->f_pos)
+		return -ESPIPE;
+
+	privptr = (ctc_priv *)dev->priv;
+
+	if (count >= 39)
+		return -EINVAL;
+
+	if (copy_from_user(tmp, buf, count))
+		return -EFAULT;
+	tmp[count+1] = '\0';
+	bs1 = simple_strtoul(tmp, &e, 0);
+	if ((bs1 > CTC_BUFSIZE_LIMIT) ||
+	    (bs1 < (dev->mtu - LL_HEADER_LENGTH - 2)) ||
+	    (e && (!isspace(*e))))
+		return -EINVAL;
+	privptr->channel[READ]->max_bufsize =
+		privptr->channel[WRITE]->max_bufsize = bs1;
+
+	return count;
+}
+
+static ssize_t ctc_ctrl_read(struct file *file, char *buf, size_t count,
+			  loff_t *off)
+{
+	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
+	char *sbuf = (char *)file->private_data;
+	net_device *dev;
+	ctc_priv *privptr;
+	ssize_t ret = 0;
+	char *p = sbuf;
+	int l;
+
+	if (!(dev = find_netdev_by_ino(ino)))
+		return -ENODEV;
+	if (off != &file->f_pos)
+		return -ESPIPE;
+
+	privptr = (ctc_priv *)dev->priv;
+
+	if (file->f_pos == 0)
+		sprintf(sbuf, "%d\n", privptr->channel[READ]->max_bufsize);
+
+	l = strlen(sbuf);
+	p = sbuf;
+	if (file->f_pos < l) {
+		p += file->f_pos;
+		l = strlen(p);
+		ret = (count > l) ? l : count;
+		if (copy_to_user(buf, p, ret))
+			return -EFAULT;
+	}
+	file->f_pos += ret;
+	return ret;
+}
+
+#define STATS_BUFSIZE 2048
+
+static int ctc_stat_open(struct inode *inode, struct file *file)
+{
+	file->private_data = kmalloc(STATS_BUFSIZE, GFP_KERNEL);
+	if (file->private_data == NULL)
+		return -ENOMEM;
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int ctc_stat_close(struct inode *inode, struct file *file)
+{
+	kfree(file->private_data);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+static ssize_t ctc_stat_write(struct file *file, const char *buf, size_t count,
+			      loff_t *off)
+{
+	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
+	net_device *dev;
+	ctc_priv *privptr;
+
+	if (!(dev = find_netdev_by_ino(ino)))
+		return -ENODEV;
+	privptr = (ctc_priv *)dev->priv;
+	privptr->channel[WRITE]->prof.maxmulti = 0;
+	privptr->channel[WRITE]->prof.maxcqueue = 0;
+	privptr->channel[WRITE]->prof.doios_single = 0;
+	privptr->channel[WRITE]->prof.doios_multi = 0;
+	privptr->channel[WRITE]->prof.txlen = 0;
+	privptr->channel[WRITE]->prof.tx_time = 0;
+	return count;
+}
+
+static ssize_t ctc_stat_read(struct file *file, char *buf, size_t count,
+			      loff_t *off)
+{
+	unsigned int ino = ((struct inode *)file->f_dentry->d_inode)->i_ino;
+	char *sbuf = (char *)file->private_data;
+	net_device *dev;
+	ctc_priv *privptr;
+	ssize_t ret = 0;
+	char *p = sbuf;
+	int l;
+
+	if (!(dev = find_netdev_by_ino(ino)))
+		return -ENODEV;
+	if (off != &file->f_pos)
+		return -ESPIPE;
+
+	privptr = (ctc_priv *)dev->priv;
+
+	if (file->f_pos == 0) {
+		p += sprintf(p, "Device FSM state: %s\n",
+			     fsm_getstate_str(privptr->fsm));
+		p += sprintf(p, "RX channel FSM state: %s\n",
+			     fsm_getstate_str(privptr->channel[READ]->fsm));
+		p += sprintf(p, "TX channel FSM state: %s\n",
+			     fsm_getstate_str(privptr->channel[WRITE]->fsm));
+		p += sprintf(p, "Max. TX buffer used: %ld\n",
+			     privptr->channel[WRITE]->prof.maxmulti);
+		p += sprintf(p, "Max. chained CCWs: %ld\n",
+			     privptr->channel[WRITE]->prof.maxcqueue);
+		p += sprintf(p, "TX single write ops: %ld\n",
+			     privptr->channel[WRITE]->prof.doios_single);
+		p += sprintf(p, "TX multi write ops: %ld\n",
+			     privptr->channel[WRITE]->prof.doios_multi);
+		p += sprintf(p, "Netto bytes written: %ld\n",
+			     privptr->channel[WRITE]->prof.txlen);
+		p += sprintf(p, "Max. TX IO-time: %ld\n",
+			     privptr->channel[WRITE]->prof.tx_time);
+	}
+	l = strlen(sbuf);
+	p = sbuf;
+	if (file->f_pos < l) {
+		p += file->f_pos;
+		l = strlen(p);
+		ret = (count > l) ? l : count;
+		if (copy_to_user(buf, p, ret))
+			return -EFAULT;
+	}
+	file->f_pos += ret;
+	return ret;
+}
+
+static struct file_operations ctc_stat_fops = {
+	read:    ctc_stat_read,
+	write:   ctc_stat_write,
+	open:    ctc_stat_open,
+	release: ctc_stat_close,
+};
+
+static struct file_operations ctc_ctrl_fops = {
+	read:    ctc_ctrl_read,
+	write:   ctc_ctrl_write,
+	open:    ctc_ctrl_open,
+	release: ctc_ctrl_close,
+};
+
+static struct inode_operations ctc_stat_iops = {
+#if LINUX_VERSION_CODE < 0x020363
+	default_file_ops: &ctc_stat_fops
+#endif
+};
+static struct inode_operations ctc_ctrl_iops = {
+#if LINUX_VERSION_CODE < 0x020363
+	default_file_ops: &ctc_ctrl_fops
+#endif
+};
+
+static struct proc_dir_entry stat_entry = {
+	0,                           /* low_ino */
+	10,                          /* namelen */
+	"statistics",                /* name    */
+	S_IFREG | S_IRUGO | S_IWUSR, /* mode    */
+	1,                           /* nlink   */
+	0,                           /* uid     */
+	0,                           /* gid     */
+	0,                           /* size    */
+	&ctc_stat_iops               /* ops     */
+};
+
+static struct proc_dir_entry ctrl_entry = {
+	0,                           /* low_ino */
+	10,                          /* namelen */
+	"buffersize",                /* name    */
+	S_IFREG | S_IRUSR | S_IWUSR, /* mode    */
+	1,                           /* nlink   */
+	0,                           /* uid     */
+	0,                           /* gid     */
+	0,                           /* size    */
+	&ctc_ctrl_iops               /* ops     */
+};
+
+#if LINUX_VERSION_CODE < 0x020363
+static struct proc_dir_entry ctc_dir = {
+	0,                           /* low_ino  */
+	3,                           /* namelen  */
+	"ctc",                       /* name     */
+	S_IFDIR | S_IRUGO | S_IXUGO, /* mode     */
+	2,                           /* nlink    */
+	0,                           /* uid      */
+	0,                           /* gid      */
+	0,                           /* size     */
+	0,                           /* ops      */
+	0,                           /* get_info */
+	ctc_fill_inode               /* fill_ino (for locking) */
+};
+
+static struct proc_dir_entry ctc_template =
+{
+	0,                           /* low_ino  */
+	0,                           /* namelen  */
+	"",                          /* name     */
+	S_IFDIR | S_IRUGO | S_IXUGO, /* mode     */
+	2,                           /* nlink    */
+	0,                           /* uid      */
+	0,                           /* gid      */
+	0,                           /* size     */
+	0,                           /* ops      */
+	0,                           /* get_info */
+	ctc_fill_inode               /* fill_ino (for locking) */
+};
+#else
+static struct proc_dir_entry *ctc_dir = NULL;
+static struct proc_dir_entry *ctc_template = NULL;
+#endif
+
+/**
+ * Create the driver's main directory /proc/net/ctc
+ */
+static void ctc_proc_create_main(void) {
+	/**
+	 * If not registered, register main proc dir-entry now
+	 */
+#if LINUX_VERSION_CODE > 0x020362
+	if (!ctc_dir)
+		ctc_dir = proc_mkdir("ctc", proc_net);
+#else
+	if (ctc_dir.low_ino == 0)
+		proc_net_register(&ctc_dir);
+#endif
+}
+
+#ifdef MODULE
+/**
+ * Destroy /proc/net/ctc
+ */
+static void ctc_proc_destroy_main(void) {
+#if LINUX_VERSION_CODE > 0x020362
+	remove_proc_entry("ctc", proc_net);
+#else
+	proc_net_unregister(ctc_dir.low_ino);
+#endif
+}
+#endif MODULE
+
+/**
+ * Create a device specific subdirectory in /proc/net/ctc/ with the
+ * same name like the device. In that directory, create 2 entries
+ * "statistics" and "buffersize".
+ *
+ * @param dev The device for which the subdirectory should be created.
+ *
+ */
+static void ctc_proc_create_sub(net_device *dev) {
+	ctc_priv *privptr = dev->priv;
+
+#if LINUX_VERSION_CODE > 0x020362
+	privptr->proc_dentry = proc_mkdir(dev->name, ctc_dir);
+	privptr->proc_stat_entry =
+		create_proc_entry("statistics",
+				  S_IFREG | S_IRUSR | S_IWUSR,
+				  privptr->proc_dentry);
+	privptr->proc_stat_entry->proc_fops = &ctc_stat_fops;
+	privptr->proc_stat_entry->proc_iops = &ctc_stat_iops;
+	privptr->proc_ctrl_entry =
+		create_proc_entry("buffersize",
+				  S_IFREG | S_IRUSR | S_IWUSR,
+				  privptr->proc_dentry);
+	privptr->proc_ctrl_entry->proc_fops = &ctc_ctrl_fops;
+	privptr->proc_ctrl_entry->proc_iops = &ctc_ctrl_iops;
+#else
+	privptr->proc_dentry->name = dev->name;
+	privptr->proc_dentry->namelen = strlen(dev->name);
+	proc_register(&ctc_dir, privptr->proc_dentry);
+	proc_register(privptr->proc_dentry, privptr->proc_stat_entry);
+	proc_register(privptr->proc_dentry, privptr->proc_ctrl_entry);
+#endif
+}
+
+#ifdef MODULE
+/**
+ * Destroy a device specific subdirectory.
+ *
+ * @param privptr Pointer to device private data.
+ */
+static void ctc_proc_destroy_sub(ctc_priv *privptr) {
+#if LINUX_VERSION_CODE > 0x020362
+	remove_proc_entry("statistics", privptr->proc_dentry);
+	remove_proc_entry("buffersize", privptr->proc_dentry);
+	remove_proc_entry(privptr->proc_dentry->name, ctc_dir);
+#else
+	proc_unregister(privptr->proc_dentry,
+			privptr->proc_stat_entry->low_ino);
+	proc_unregister(privptr->proc_dentry,
+			privptr->proc_ctrl_entry->low_ino);
+	proc_unregister(&ctc_dir,
+			privptr->proc_dentry->low_ino);
+#endif
+}
+#endif MODULE
+
+/**
+ * Setup related routines
+ *****************************************************************************/
+
+/**
+ * Parse a portion of the setup string describing a single device or option
+ * providing the following syntax:
+ *
+ * [Device/OptionName[:int1][:int2][:int3]]
+ *
+ *
+ * @param setup    Pointer to a pointer to the remainder of the parameter
+ *                 string to be parsed. On return, the content of this
+ *                 pointer is updated to point to the first character after
+ *                 the parsed portion (e.g. possible start of next portion)
+ *                 NOTE: The string pointed to must be writeable, since a
+ *                 \0 is written for termination of the device/option name.
+ *
+ * @param dev_name Pointer to a pointer to the name of the device whose
+ *                 parameters are parsed. On return, this is set to the
+ *                 name of the device/option.
+ *
+ * @param ints     Pointer to an array of integer parameters. On return,
+ *                 element 0 is set to the number of parameters found.
+ *
+ * @param maxip    Maximum number of ints to parse.
+ *                 (ints[] must have size maxip+1)
+ *
+ * @return     0 if string "setup" was empty, !=0 otherwise
+ */
+static int parse_opts(char **setup, char **dev_name, int *ints, int maxip) {
+	char *cur = *setup;
+	int i = 1;
+	int rc = 0;
+	int in_name = 1;
+	int noauto = 0;
+
+#ifdef DEBUG
+	printk(KERN_DEBUG
+	       "ctc: parse_opts(): *setup='%s', maxip=%d\n", *setup, maxip);
+#endif
+	if (*setup) {
+		*dev_name = *setup;
+
+		if (strncmp(cur, "ctc", 3) && strncmp(cur, "escon", 5) &&
+		    strncmp(cur, "noauto", 6)) {
+			if ((*setup = strchr(cur, ':')))
+				*(*setup)++ = '\0';
+			printk(KERN_WARNING
+			       "ctc: Invalid device name or option '%s'\n",
+			       cur);
+			return 1;
+		}
+		switch (*cur) {
+			case 'c':
+				cur += 3;
+				break;
+			case 'e':
+				cur += 5;
+				break;
+			case 'n':
+				cur += 6;
+				*cur++ = '\0';
+				noauto = 1;
+		}
+		if (!noauto) {
+			while (cur &&
+			       (*cur == '-' || isdigit(*cur)) &&
+			       i <= maxip) {
+				if (in_name) {
+					cur++;
+					if (*cur == ':') {
+						*cur++ = '\0';
+						in_name = 0;
+					}
+				} else {
+					ints[i++] =
+						simple_strtoul(cur, NULL, 0);
+#ifdef DEBUG
+					printk(KERN_DEBUG
+					       "ctc: %s: ints[%d]=%d\n",
+					       __FUNCTION__,
+					       i-1, ints[i-1]);
+#endif
+					if ((cur = strchr(cur, ':')) != NULL)
+						cur++;
+				}
+			}
+		}
+		ints[0] = i - 1;
+		*setup = cur;
+		if (cur && (*cur == ':'))
+			(*setup)++;
+		rc = 1;
+	}
+	return rc;
+}
+
+/**
+ *
+ * Allocate one param struct
+ *
+ * If the driver is loaded as a module this functions is called during
+ *   module set up and we can allocate the struct by using kmalloc()
+ *
+ * If the driver is statically linked into the kernel this function is called
+ * when kmalloc() is not yet available so we must allocate from a static array
+ *
+ */
+#ifdef MODULE
+#define alloc_param() ((param *)kmalloc(sizeof(param), GFP_KERNEL));
+#else
+static param parms_array[MAX_STATIC_DEVICES];
+static param *next_param = parms_array;
+#define alloc_param() ((next_param<parms_array+MAX_STATIC_DEVICES)?next_param++:NULL)
+#endif MODULE
+
+/**
+ * Returns commandline parameter using device name as key.
+ *
+ * @param name Name of interface to get parameters from.
+ *
+ * @return Pointer to corresponting param struct, NULL if not found.
+ */
+static param *find_param(char *name) {
+	param *p = params;
+
+	while (p && strcmp(p->name, name))
+		p = p->next;
+	return p;
+}
+
+/**
+ * maximum number of integer parametes that may be specified
+ * for one device in the setup string
+ */
+#define CTC_MAX_INTPARMS 3
+
+/**
+ * Parse configuration options for all interfaces.
+ *
+ * This function is called from two possible locations:
+ *  - If built as module, this function is called from init_module().
+ *  - If built in monolithic kernel, this function is called from within
+ *    init/main.c.
+ * Parsing is always done here.
+ *
+ * Valid parameters are:
+ *
+ *
+ *   [NAME[:0xRRRR[:0xWWWW[:P]]]]
+ *
+ *     where P       is the channel protocol (always 0)
+ *	      0xRRRR is the cu number for the read channel
+ *	      0xWWWW is the cu number for the write channel
+ *	      NAME   is either ctc0 ... ctcN for CTC/A
+ *                      or     escon0 ... esconN for Escon.
+ *                      or     noauto
+ *                             which switches off auto-detection of channels.
+ *
+ * @param setup    The parameter string to parse. MUST be writeable!
+ * @param ints     Pointer to an array of ints. Only for kernel 2.2,
+ *                 builtin (not module) version. With kernel 2.2,
+ *                 normally all integer-parameters, preceeding some
+ *                 configuration-string are pre-parsed in init/main.c
+ *                 and handed over here.
+ *                 To simplify 2.2/2.4 compatibility, by definition,
+ *                 our parameters always start with a string and ints
+ *                 is always unset and ignored.
+ */
+#ifdef MODULE
+   static void ctc_setup(char *setup)
+#  define ctc_setup_return return
+#else MODULE
+#  if LINUX_VERSION_CODE < 0x020300
+     __initfunc(void ctc_setup(char *setup, int *ints))
+#    define ctc_setup_return return
+#    define ints local_ints
+#  else
+     static int __init ctc_setup(char *setup)
+#    define ctc_setup_return return(1)
+#  endif
+#endif MODULE
+{
+	int write_dev;
+	int read_dev;
+	int proto;
+	param *par;
+	char *dev_name;
+	int ints[CTC_MAX_INTPARMS+1];
+
+	while (parse_opts(&setup, &dev_name, ints, CTC_MAX_INTPARMS)) {
+		write_dev = -1;
+		read_dev = -1;
+		proto = CTC_PROTO_S390;
+#ifdef DEBUG
+		printk(KERN_DEBUG
+		       "ctc: ctc_setup(): setup='%s' dev_name='%s',"
+		       " ints[0]=%d)\n",
+		       setup, dev_name, ints[0]);
+#endif DEBUG
+		if (dev_name == NULL) {
+			/**
+			 * happens if device name is not specified in
+			 * parameter line (cf. init/main.c:get_options()
+			 */
+			printk(KERN_WARNING
+			       "ctc: %s(): Device name not specified\n",
+			       __FUNCTION__);
+			ctc_setup_return;
+		}
+
+#ifdef DEBUG
+		printk(KERN_DEBUG "name=´%s´ argc=%d\n", dev_name, ints[0]);
+#endif
+
+		if (strcmp(dev_name, "noauto") == 0) {
+			printk(KERN_INFO "ctc: autoprobing disabled\n");
+			ctc_no_auto = 1;
+			continue;
+		}
+
+		if (find_param(dev_name) != NULL) {
+			printk(KERN_WARNING
+			       "ctc: Definition for device %s already set. "
+			       "Ignoring second definition\n", dev_name);
+			continue;
+		}
+
+		switch (ints[0]) {
+			case 3: /* protocol type passed */
+				proto = ints[3];
+				if (proto > CTC_PROTO_MAX) {
+					printk(KERN_WARNING
+					       "%s: wrong protocol type "
+					       "passed\n", dev_name);
+					ctc_setup_return;
+				}
+			case 2: /* write channel passed */
+				write_dev = ints[2];
+			case 1: /* read channel passed */
+				read_dev = ints[1];
+				if (write_dev == -1)
+					write_dev = read_dev + 1;
+				break;
+			default:
+				printk(KERN_WARNING
+				       "ctc: wrong number of parameter "
+				       "passed (is: %d, expected: [1..3]\n",
+				       ints[0]);
+				ctc_setup_return;
+		}
+		par = alloc_param();
+		if (!par) {
+#ifdef MODULE
+			printk(KERN_WARNING
+			       "ctc: Couldn't allocate setup param block\n");
+#else
+			printk(KERN_WARNING
+			       "ctc: Number of device definitions in "
+			       " kernel commandline exceeds builtin limit "
+			       " of %d devices.\n", MAX_STATIC_DEVICES);
+#endif
+			ctc_setup_return;
+		}
+		par->read_dev = read_dev;
+		par->write_dev = write_dev;
+		par->proto = proto;
+		strncpy(par->name, dev_name, MAX_PARAM_NAME_LEN);
+		par->next = params;
+		params = par;
+#ifdef DEBUG
+		printk(KERN_DEBUG "%s: protocol=%x read=%04x write=%04x\n",
+		       dev_name, proto, read_dev, write_dev);
+#endif
+	}
+	ctc_setup_return;
+}
+
+#if LINUX_VERSION_CODE >= 0x020300
+__setup("ctc=", ctc_setup);
+#endif
+
+/**
+ *
+ * Setup an interface.
+ *
+ * Like ctc_setup(), ctc_probe() can be called from two different locations:
+ *  - If built as module, it is called from within init_module().
+ *  - If built in monolithic kernel, it is called from within generic network
+ *    layer during initialization for every corresponding device, declared in
+ *    drivers/net/Space.c
+ *
+ * @param dev Pointer to net_device to be initialized.
+ *
+ * @return 0 on success, !0 on failure.
+ */
+int ctc_probe(net_device *dev)
+{
+	int            devno[2];
+	__u16          proto;
+	int            rc;
+	int            direction;
+	channel_type_t type;
+	ctc_priv       *privptr;
+	param          *par;
+
+	ctc_proc_create_main();
+
+	/**
+	 * Scan for available channels only the first time,
+	 * ctc_probe gets control.
+	 */
+	if (channels == NULL)
+		channel_scan(1);
+
+	type = extract_channel_media(dev->name);
+	if (type == channel_type_unknown)
+		return -ENODEV;
+
+	par = find_param(dev->name);
+	if (par) {
+		devno[READ] = par->read_dev;
+		devno[WRITE] = par->write_dev;
+		proto = par->proto;
+	} else {
+		if (ctc_no_auto)
+			return -ENODEV;
+		else {
+			devno[READ] = -1;
+			devno[WRITE] = -1;
+			proto = CTC_PROTO_S390;
+		}
+	}
+
+	dev->priv = kmalloc(sizeof(ctc_priv)
+			    + sizeof(ctc_template)
+			    + sizeof(stat_entry)
+			    + sizeof(ctrl_entry)
+			    , GFP_KERNEL);
+	if (dev->priv == NULL)
+		return -ENOMEM;
+	memset(dev->priv, 0, sizeof(ctc_priv));
+	privptr = (ctc_priv *)dev->priv;
+        privptr->proc_dentry = (struct proc_dir_entry *)
+		(((char *)privptr) + sizeof(ctc_priv));
+        privptr->proc_stat_entry = (struct proc_dir_entry *)
+		(((char *)privptr) + sizeof(ctc_priv) +
+		 sizeof(ctc_template));
+        privptr->proc_ctrl_entry = (struct proc_dir_entry *)
+		(((char *)privptr) + sizeof(ctc_priv) +
+		 sizeof(ctc_template) + sizeof(stat_entry));
+	memcpy(privptr->proc_dentry, &ctc_template, sizeof(ctc_template));
+	memcpy(privptr->proc_stat_entry, &stat_entry, sizeof(stat_entry));
+	memcpy(privptr->proc_ctrl_entry, &ctrl_entry, sizeof(ctrl_entry));
+	privptr->fsm = init_fsm(dev->name, dev_state_names,
+			dev_event_names, NR_DEV_STATES, NR_DEV_EVENTS,
+			dev_fsm, DEV_FSM_LEN, GFP_KERNEL);
+	fsm_newstate(privptr->fsm, DEV_STATE_STOPPED);
+	if (privptr->fsm == NULL) {
+		kfree(privptr);
+		return -ENOMEM;
+	}
+	dev->mtu	         = CTC_BUFSIZE_DEFAULT - LL_HEADER_LENGTH - 2; 
+	dev->hard_start_xmit     = ctc_tx;
+	dev->open	         = ctc_open;
+	dev->stop	         = ctc_close;
+	dev->get_stats	         = ctc_stats;
+	dev->change_mtu          = ctc_change_mtu;
+	dev->hard_header_len     = LL_HEADER_LENGTH + 2;
+	dev->addr_len            = 0;
+	dev->type                = ARPHRD_SLIP;
+	dev->tx_queue_len        = 100;
+	SET_DEVICE_START(dev, 1);
+	dev_init_buffers(dev);
+	dev->flags	         = IFF_POINTOPOINT | IFF_NOARP;
+	for (direction = READ; direction <= WRITE; direction++) {
+		if ((ctc_no_auto == 0) || (devno[direction] == -1))
+			privptr->channel[direction] =
+				channel_get_next(type, direction);
+		else
+			privptr->channel[direction] =
+				channel_get(type, devno[direction], direction);
+		if (privptr->channel[direction] == NULL) {
+			if (direction == WRITE) {
+				free_irq(privptr->channel[READ]->irq,
+					 privptr->channel[READ]->devstat);
+				channel_free(privptr->channel[READ]);
+			}
+			kfree_fsm(privptr->fsm);
+			kfree(dev->priv);
+			dev->priv = NULL;
+			return -ENODEV;
+		}
+		privptr->channel[direction]->netdev = dev;
+		privptr->channel[direction]->protocol = proto;
+		privptr->channel[direction]->max_bufsize = CTC_BUFSIZE_DEFAULT;
+		rc = request_irq(privptr->channel[direction]->irq,
+				 (void *)ctc_irq_handler, SA_INTERRUPT,
+				 dev->name,
+				 privptr->channel[direction]->devstat);
+		if (rc) {
+			printk(KERN_WARNING
+			       "%s: requested irq %d is busy rc=%02x\n",
+			       dev->name, privptr->channel[direction]->irq,
+			       rc);
+			if (direction == WRITE) {
+				free_irq(privptr->channel[READ]->irq,
+					 privptr->channel[READ]->devstat);
+				channel_free(privptr->channel[READ]);
+			}
+			channel_free(privptr->channel[direction]);
+			kfree_fsm(privptr->fsm);
+			kfree(dev->priv);
+			dev->priv = NULL;
+			return -EBUSY;
+		}
+	}
+
+	/**
+	 * register subdir in /proc/net/ctc
+	 */
+	ctc_proc_create_sub(dev);
+
+	print_banner();
+
+	printk(KERN_INFO
+	       "%s: read: ch %04x (irq %04x), write: ch %04x (irq %04x) proto: %d\n",
+	       dev->name, privptr->channel[READ]->devno,
+	       privptr->channel[READ]->irq, privptr->channel[WRITE]->devno,
+	       privptr->channel[WRITE]->irq, proto);
+
+	return 0;
+}
+
+/**
+ * Module related routines
+ *****************************************************************************/
+
+#ifdef MODULE
+/**
+ * Prepare to be unloaded. Free IRQ's and release all resources.
+ * This is called just before this module is unloaded. It is
+ * <em>not</em> called, if the usage count is !0, so we don't need to check
+ * for that.
+ */
+void cleanup_module(void) {
+	channel *c = channels;
+
+	/* we are called if all interfaces are down only, so no need
+	 * to bother around with locking stuff
+	 */
+	channels = NULL;
+	while (c) {
+		channel *oldc = c;
+		if (c->netdev && c->netdev->priv) {
+			net_device *nd = c->netdev;
+			ctc_priv *privptr = (ctc_priv *)nd->priv;
+
+			fsm_deltimer(&privptr->channel[READ]->timer);
+			fsm_deltimer(&privptr->channel[WRITE]->timer);
+			free_irq(privptr->channel[READ]->irq,
+				 privptr->channel[READ]->devstat);
+			free_irq(privptr->channel[WRITE]->irq,
+				 privptr->channel[WRITE]->devstat);
+			kfree_fsm(privptr->channel[READ]->fsm);
+			kfree_fsm(privptr->channel[WRITE]->fsm);
+			unregister_netdev(nd);
+			kfree_fsm(privptr->fsm);
+			privptr->channel[READ]->netdev = NULL;
+			privptr->channel[WRITE]->netdev = NULL;
+			ctc_proc_destroy_sub(privptr);
+			kfree(privptr);
+			kfree(nd);
+			if (c->netdev != NULL)
+				printk(KERN_EMERG
+				       "ctc: PANIC: channel list corrupted\n");
+		}
+		c = c->next;
+		kfree(oldc->ccw);
+		kfree(oldc);
+	}
+	ctc_proc_destroy_main();
+	printk(KERN_INFO "CTC driver unloaded\n");
+}
+
+#define ctc_init init_module
+#endif MODULE
+
+/**
+ * Initialize module.
+ * This is called just after the module is loaded.
+ *
+ * @return 0 on success, !0 on error.
+ */
+int ctc_init(void) {
+	int   cnt[2];
+	int   itype;
+	int   activated;
+	param *par;
+
+	print_banner();
+
+#ifdef DEBUG
+	printk(KERN_DEBUG
+	       "ctc: init_module(): got string '%s'\n", setup);
+#endif
+
+#ifdef MODULE
+	ctc_setup(ctc);
+#endif
+	activated = 0;
+	par = params;
+	for (itype = 0; itype < 2; itype++) {
+		net_device *dev = NULL;
+		char       *bname = (itype) ? "escon" : "ctc";
+		int        nlen = strlen(bname);
+		cnt[itype] = 0;
+		do {
+			dev = kmalloc(sizeof(net_device)
+#if LINUX_VERSION_CODE < 0x020300
+				      + 11 /* name + zero */
+#endif
+				      , GFP_KERNEL);
+			if (!dev)
+				return -ENOMEM;
+			memset(dev, 0, sizeof(net_device));
+#if LINUX_VERSION_CODE < 0x020300
+			dev->name = (unsigned char *)dev + sizeof(net_device);
+#endif
+			if (par && par->name) {
+				char *p;
+				int  n;
+
+				sprintf(dev->name, "%s", par->name);
+				par = par->next;
+				for (p = dev->name; p && *p; p++)
+					if (isdigit(*p))
+						break;
+				if (p && *p) {
+					n = simple_strtoul(p, NULL, 0);
+					if (n >= cnt[itype] &&
+					    (!strncmp(par->name, bname, nlen)))
+						cnt[itype] = n + 1;
+				}
+			} else {
+				if (ctc_no_auto) {
+					itype = 3;
+					kfree(dev);
+					dev = NULL;
+					break;
+				}
+				sprintf(dev->name, "%s%d", bname,
+					(cnt[itype])++);
+			}
+#ifdef DEBUG
+			printk(KERN_DEBUG "ctc: %s(): probing for device %s\n",
+						 __FUNCTION__, dev->name);
+#endif			
+			if (ctc_probe(dev) == 0) {
+#ifdef DEBUG
+				printk(KERN_DEBUG
+				       "ctc: %s(): probing succeeded\n",
+				       __FUNCTION__);
+				printk(KERN_DEBUG
+				       "ctc: %s(): registering device %s\n",
+				       __FUNCTION__, dev->name);
+#endif			
+				if (register_netdev(dev) != 0) {
+					ctc_priv *privptr =
+						(ctc_priv *)dev->priv;
+					printk(KERN_WARNING
+					       "ctc: Couldn't register %s\n",
+					       dev->name);
+					free_irq(privptr->channel[READ]->irq,
+						 privptr->channel[READ]->devstat);
+					free_irq(privptr->channel[WRITE]->irq,
+						 privptr->channel[WRITE]->devstat);
+					channel_free(privptr->channel[READ]);
+					channel_free(privptr->channel[WRITE]);
+					kfree(dev->priv);
+					kfree(dev);
+				} else {
+#ifdef DEBUG
+					printk(KERN_DEBUG
+					       "ctc: %s(): register succeed\n",
+					       __FUNCTION__);
+#endif			
+					activated++;
+				}
+				
+			} else {
+#ifdef DEBUG
+				printk(KERN_DEBUG
+				       "ctc: %s(): probing failed\n",
+				       __FUNCTION__);
+#endif			
+				kfree(dev);
+				dev = NULL;
+			}
+		} while (dev);
+	}
+	if (!activated) {
+		printk(KERN_WARNING "ctc: No devices registered\n");
+		return -ENODEV;
+	}
+	return 0;
+}
+
+#ifndef MODULE
+#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0))
+__initcall(ctc_init);
+#endif /* LINUX_VERSION_CODE */
+#endif /* MODULE */
+
+/* --- This is the END my friend --- */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/fsm.c linux/drivers/s390/net/fsm.c
--- v2.4.1/linux/drivers/s390/net/fsm.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/net/fsm.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,230 @@
+/**
+ * $Id: fsm.c,v 1.1 2000/11/30 11:21:08 bird Exp $
+ *
+ * A generic FSM based on fsm used in isdn4linux
+ *
+ * $Log: fsm.c,v $
+ * Revision 1.1  2000/11/30 11:21:08  bird
+ * Support for new ctc driver
+ *
+ * Revision 1.2  2000/11/10 17:25:11  felfert
+ * Changes for kernel 2.4
+ *
+ * Revision 1.1  2000/11/03 16:58:45  felfert
+ * Initial import
+ *
+ *
+ */
+
+#include "fsm.h"
+#include <linux/version.h>
+
+fsm_instance *
+init_fsm(char *name, const char **state_names, const char **event_names, int nr_states,
+		int nr_events, const fsm_node *tmpl, int tmpl_len, int order)
+{
+	int i;
+	fsm_instance *this;
+	fsm_function_t *m;
+	fsm *f;
+
+	this = (fsm_instance *)kmalloc(sizeof(fsm_instance), order);
+	if (this == NULL) {
+		printk(KERN_WARNING
+			"fsm(%s): init_fsm: Couldn't alloc instance\n", name);
+		return NULL;
+	}
+	memset(this, 0, sizeof(fsm_instance));
+	strncpy(this->name, name, sizeof(this->name));
+
+	f = (fsm *)kmalloc(sizeof(fsm), order);
+	if (f == NULL) {
+		printk(KERN_WARNING
+			"fsm(%s): init_fsm: Couldn't alloc fsm\n", name);
+		kfree_fsm(this);
+		return NULL;
+	}
+	memset(f, 0, sizeof(fsm));
+	f->nr_events = nr_events;
+	f->nr_states = nr_states;
+	f->event_names = event_names;
+	f->state_names = state_names;
+	this->f = f;
+
+	m = (fsm_function_t *)kmalloc(
+			sizeof(fsm_function_t) * nr_states * nr_events, order);
+	if (m == NULL) {
+		printk(KERN_WARNING
+			"fsm(%s): init_fsm: Couldn't alloc jumptable\n", name);
+		kfree_fsm(this);
+		return NULL;
+	}
+	memset(m, 0, sizeof(fsm_function_t) * f->nr_states * f->nr_events);
+	f->jumpmatrix = m;
+
+	for (i = 0; i < tmpl_len; i++) {
+		if ((tmpl[i].cond_state >= nr_states) ||
+		    (tmpl[i].cond_event >= nr_events)   ) {
+			printk(KERN_ERR
+				"fsm(%s): init_fsm: Bad template l=%d st(%ld/%ld) ev(%ld/%ld)\n",
+				name, i, (long)tmpl[i].cond_state, (long)f->nr_states,
+				(long)tmpl[i].cond_event, (long)f->nr_events);
+			kfree_fsm(this);
+			return NULL;
+		} else
+			m[nr_states * tmpl[i].cond_event + tmpl[i].cond_state] =
+				tmpl[i].function;
+	}
+	return this;
+}
+
+void
+kfree_fsm(fsm_instance *this)
+{
+	if (this) {
+		if (this->f) {
+			if (this->f->jumpmatrix)
+				kfree(this->f->jumpmatrix);
+			kfree(this->f);
+		}
+		kfree(this);
+	} else
+		printk(KERN_WARNING
+			"fsm: kfree_fsm called with NULL argument\n");
+}
+
+#if FSM_DEBUG_HISTORY
+void
+fsm_print_history(fsm_instance *fi)
+{
+	int idx = 0;
+	int i;
+
+	if (fi->history_size >= FSM_HISTORY_SIZE)
+		idx = fi->history_index;
+
+	printk(KERN_DEBUG "fsm(%s): History:\n", fi->name);
+	for (i = 0; i < fi->history_size; i++) {
+		int e = fi->history[idx].event;
+		int s = fi->history[idx++].state;
+		idx %= FSM_HISTORY_SIZE;
+		if (e == -1)
+			printk(KERN_DEBUG "  S=%s\n",
+			       fi->f->state_names[s]);
+		else
+			printk(KERN_DEBUG "  S=%s E=%s\n",
+			       fi->f->state_names[s],
+			       fi->f->event_names[e]);
+	}
+	fi->history_size = fi->history_index = 0;
+}
+
+void
+fsm_record_history(fsm_instance *fi, int state, int event)
+{
+	fi->history[fi->history_index].state = state;
+	fi->history[fi->history_index++].event = event;
+	fi->history_index %= FSM_HISTORY_SIZE;
+	if (fi->history_size < FSM_HISTORY_SIZE)
+		fi->history_size++;
+}
+#endif
+
+const char *
+fsm_getstate_str(fsm_instance *fi)
+{
+	int st = atomic_read(&fi->state);
+	if (st >= fi->f->nr_states)
+		return "Invalid";
+	return fi->f->state_names[st];
+}
+
+static void
+fsm_expire_timer(fsm_timer *this)
+{
+#if FSM_TIMER_DEBUG
+	printk(KERN_DEBUG "fsm(%s): Timer %p expired\n",
+	       this->fi->name, this);
+#endif
+	fsm_event(this->fi, this->expire_event, this->event_arg);
+}
+
+void
+fsm_settimer(fsm_instance *fi, fsm_timer *this)
+{
+	this->fi = fi;
+	this->tl.function = (void *)fsm_expire_timer;
+	this->tl.data = (long)this;
+#if FSM_TIMER_DEBUG
+	printk(KERN_DEBUG "fsm(%s): Create timer %p\n", fi->name,
+	       this);
+#endif
+	init_timer(&this->tl);
+}
+
+void
+fsm_deltimer(fsm_timer *this)
+{
+#if FSM_TIMER_DEBUG
+	printk(KERN_DEBUG "fsm(%s): Delete timer %p\n", this->fi->name,
+		this);
+#endif
+	del_timer(&this->tl);
+}
+
+int
+fsm_addtimer(fsm_timer *this, int millisec, int event, void *arg)
+{
+
+#if FSM_TIMER_DEBUG
+	printk(KERN_DEBUG "fsm(%s): Add timer %p %dms\n",
+	       this->fi->name, this, millisec);
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020300
+	if (this->tl.list.next || this->tl.list.prev) {
+		printk(KERN_WARNING "fsm(%s): timer already active!\n",
+			this->fi->name);
+		return -1;
+	}
+#else
+	if (this->tl.next || this->tl.prev) {
+		printk(KERN_WARNING "fsm(%s): timer already active!\n",
+			this->fi->name);
+		return -1;
+	}
+#endif
+	init_timer(&this->tl);
+	this->tl.function = (void *)fsm_expire_timer;
+	this->tl.data = (long)this;
+	this->expire_event = event;
+	this->event_arg = arg;
+	this->tl.expires = jiffies + (millisec * HZ) / 1000;
+	add_timer(&this->tl);
+	return 0;
+}
+
+void
+fsm_modtimer(fsm_timer *this, int millisec, int event, void *arg)
+{
+
+#if FSM_TIMER_DEBUG
+	printk(KERN_DEBUG "fsm(%s): Restart timer %p %dms\n",
+		this->fi->name, this, millisec);
+#endif
+
+#if LINUX_VERSION_CODE >= 0x020300
+	if (this->tl.list.next || this->tl.list.prev)
+		del_timer(&this->tl);
+#else
+	if (this->tl.next || this->tl.prev)
+		del_timer(&this->tl);
+#endif
+	init_timer(&this->tl);
+	this->tl.function = (void *)fsm_expire_timer;
+	this->tl.data = (long)this;
+	this->expire_event = event;
+	this->event_arg = arg;
+	this->tl.expires = jiffies + (millisec * HZ) / 1000;
+	add_timer(&this->tl);
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/fsm.h linux/drivers/s390/net/fsm.h
--- v2.4.1/linux/drivers/s390/net/fsm.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/net/fsm.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,273 @@
+/* $Id: fsm.h,v 1.1 2000/11/30 11:21:08 bird Exp $
+ *
+ * $Log: fsm.h,v $
+ * Revision 1.1  2000/11/30 11:21:08  bird
+ * Support for new ctc driver
+ *
+ * Revision 1.1  2000/11/03 16:58:45  felfert
+ * Initial import
+ *
+ *
+ */
+#ifndef _FSM_H_
+#define _FSM_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/timer.h>
+#include <linux/time.h>
+#include <linux/malloc.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <asm/atomic.h>
+
+/**
+ * Define this to get debugging messages.
+ */
+#define FSM_DEBUG         0
+
+/**
+ * Define this to get debugging massages for
+ * timer handling.
+ */
+#define FSM_TIMER_DEBUG   0
+
+/**
+ * Define these to record a history of
+ * Events/Statechanges and print it if a
+ * action_function is not found.
+ */
+#define FSM_DEBUG_HISTORY 0
+#define FSM_HISTORY_SIZE  40
+
+struct fsm_instance_t;
+
+/**
+ * Definition of an action function, called by a FSM
+ */
+typedef void (*fsm_function_t)(struct fsm_instance_t *, int, void *);
+
+/**
+ * Internal jump table for a FSM
+ */
+typedef struct {
+	fsm_function_t *jumpmatrix;
+	int nr_events;
+	int nr_states;
+	const char **event_names;
+	const char **state_names;
+} fsm;
+
+#if FSM_DEBUG_HISTORY
+/**
+ * Element of State/Event history used for debugging.
+ */
+typedef struct {
+	int state;
+	int event;
+} fsm_history;
+#endif
+
+/**
+ * Representation of a FSM
+ */
+typedef struct fsm_instance_t {
+	fsm *f;
+	atomic_t state;
+	char name[16];
+	void *userdata;
+	int userint;
+#if FSM_DEBUG_HISTORY
+	int         history_index;
+	int         history_size;
+	fsm_history history[FSM_HISTORY_SIZE];
+#endif
+} fsm_instance;
+
+/**
+ * Description of a state-event combination
+ */
+typedef struct {
+	int cond_state;
+	int cond_event;
+	fsm_function_t function;
+} fsm_node;
+
+/**
+ * Description of a FSM Timer.
+ */
+typedef struct {
+	fsm_instance *fi;
+	struct timer_list tl;
+	int expire_event;
+	void *event_arg;
+} fsm_timer;
+
+/**
+ * Creates an FSM
+ *
+ * @param name        Name of this instance for logging purposes.
+ * @param state_names An array of names for all states for logging purposes.
+ * @param event_names An array of names for all events for logging purposes.
+ * @param nr_states   Number of states for this instance.
+ * @param nr_events   Number of events for this instance.
+ * @param tmpl        An array of fsm_nodes, describing this FSM.
+ * @param tmpl_len    Length of the describing array.
+ * @param order       Parameter for allocation of the FSM data structs.
+ */
+fsm_instance * init_fsm(char *name, const char **state_names,
+			const char **event_names,
+			int nr_states, int nr_events, const fsm_node *tmpl,
+			int tmpl_len, int order);
+
+/**
+ * Releases an FSM
+ *
+ * @param fi Pointer to an FSM, previously created with init_fsm.
+ */
+extern void kfree_fsm(fsm_instance *fi);
+
+#if FSM_DEBUG_HISTORY
+extern void
+fsm_print_history(fsm_instance *fi);
+
+extern void
+fsm_record_history(fsm_instance *fi, int state, int event);
+#endif
+
+/**
+ * Emits an event to a FSM.
+ * If an action function is defined for the current state/event combination,
+ * this function is called.
+ *
+ * @param fi    Pointer to FSM which should receive the event.
+ * @param event The event do be delivered.
+ * @param arg   A generic argument, handed to the action function.
+ *
+ * @return      0  on success,
+ *              1  if current state or event is out of range
+ *              !0 if state and event in range, but no action defined.
+ */
+extern __inline__ int
+fsm_event(fsm_instance *fi, int event, void *arg)
+{
+	fsm_function_t r;
+	int state = atomic_read(&fi->state);
+
+	if ((state >= fi->f->nr_states) ||
+	    (event >= fi->f->nr_events)       ) {
+		printk(KERN_ERR "fsm(%s): Invalid state st(%ld/%ld) ev(%d/%ld)\n",
+			fi->name, (long)state,(long)fi->f->nr_states, event,
+			(long)fi->f->nr_events);
+#if FSM_DEBUG_HISTORY
+		fsm_print_history(fi);
+#endif
+		return 1;
+	}
+	r = fi->f->jumpmatrix[fi->f->nr_states * event + state];
+	if (r) {
+#if FSM_DEBUG
+		printk(KERN_DEBUG "fsm(%s): state %s event %s\n",
+		       fi->name, fi->f->state_names[state],
+		       fi->f->event_names[event]);
+#endif
+#if FSM_DEBUG_HISTORY
+		fsm_record_history(fi, state, event);
+#endif
+		r(fi, event, arg);
+		return 0;
+	} else {
+#if FSM_DEBUG || FSM_DEBUG_HISTORY
+		printk(KERN_DEBUG "fsm(%s): no function for event %s in state %s\n",
+		       fi->name, fi->f->event_names[event],
+		       fi->f->state_names[state]);
+#endif
+#if FSM_DEBUG_HISTORY
+		fsm_print_history(fi);
+#endif
+		return !0;
+	}
+}
+
+/**
+ * Modifies the state of an FSM.
+ * This does <em>not</em> trigger an event or calls an action function.
+ *
+ * @param fi    Pointer to FSM
+ * @param state The new state for this FSM.
+ */
+extern __inline__ void
+fsm_newstate(fsm_instance *fi, int newstate)
+{
+	atomic_set(&fi->state,newstate);
+#if FSM_DEBUG_HISTORY
+	fsm_record_history(fi, newstate, -1);
+#endif
+#if FSM_DEBUG
+	printk(KERN_DEBUG "fsm(%s): New state %s\n", fi->name,
+		fi->f->state_names[newstate]);
+#endif
+}
+
+/**
+ * Retrieves the state of an FSM
+ *
+ * @param fi Pointer to FSM
+ *
+ * @return The current state of the FSM.
+ */
+extern __inline__ int
+fsm_getstate(fsm_instance *fi)
+{
+	return atomic_read(&fi->state);
+}
+
+/**
+ * Retrieves the name of the state of an FSM
+ *
+ * @param fi Pointer to FSM
+ *
+ * @return The current state of the FSM in a human readable form.
+ */
+extern const char *fsm_getstate_str(fsm_instance *fi);
+
+/**
+ * Initializes a timer for an FSM.
+ * This prepares an fsm_timer for usage with fsm_addtimer.
+ *
+ * @param fi    Pointer to FSM
+ * @param timer The timer to be initialized.
+ */
+extern void fsm_settimer(fsm_instance *fi, fsm_timer *);
+
+/**
+ * Clears a pending timer of an FSM instance.
+ *
+ * @param timer The timer to clear.
+ */
+extern void fsm_deltimer(fsm_timer *timer);
+
+/**
+ * Adds and starts a timer to an FSM instance.
+ *
+ * @param timer    The timer to be added. The field fi of that timer
+ *                 must have been set to point to the instance.
+ * @param millisec Duration, after which the timer should expire.
+ * @param event    Event, to trigger if timer expires.
+ * @param arg      Generic argument, provided to expiry function.
+ *
+ * @return         0 on success, -1 if timer is already active.
+ */
+extern int fsm_addtimer(fsm_timer *timer, int millisec, int event, void *arg);
+
+/**
+ * Modifies a timer of an FSM.
+ *
+ * @param timer    The timer to modify.
+ * @param millisec Duration, after which the timer should expire.
+ * @param event    Event, to trigger if timer expires.
+ * @param arg      Generic argument, provided to expiry function.
+ */
+extern void fsm_modtimer(fsm_timer *timer, int millisec, int event, void *arg);
+
+#endif /* _FSM_H_ */
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/iucv.c linux/drivers/s390/net/iucv.c
--- v2.4.1/linux/drivers/s390/net/iucv.c	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/net/iucv.c	Tue Feb 13 14:13:44 2001
@@ -1,1178 +1,2050 @@
 /*
  *  drivers/s390/net/iucv.c
- *    Network driver for VM using iucv
+ *    Support for VM IUCV functions for use by other part of the
+ *    kernel or loadable modules.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Stefan Hegewald <hegewald@de.ibm.com>
- *               Hartmut Penner <hpenner@de.ibm.com>
- * 
- *    2.3 Updates Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- *                Martin Schwidefsky (schwidefsky@de.ibm.com)
- *                
-
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Xenia Tkatschow (xenia@us.ibm.com)
+ *               Alan Altmark (Alan_Altmark@us.ibm.com)
  */
 
-#ifndef __KERNEL__
-#define __KERNEL__
-#endif
-
+#include <linux/config.h>
 #include <linux/version.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>              /* printk()                         */
-#include <linux/malloc.h>              /* kmalloc()                        */
-#include <linux/errno.h>               /* error codes                      */
-#include <linux/types.h>               /* size_t                           */
-#include <linux/interrupt.h>           /* mark_bh                          */
-#include <linux/netdevice.h>           /* struct net_device, and other headers */
-#include <linux/inetdevice.h>          /* struct net_device, and other headers */
-#include <linux/if_arp.h>
-#include <linux/rtnetlink.h>
-#include <linux/ip.h>                  /* struct iphdr                     */
-#include <linux/tcp.h>                 /* struct tcphdr                    */
-#include <linux/skbuff.h>
+#include <linux/spinlock.h>
+#include <linux/kernel.h>
+#include <linux/malloc.h>
 #include <linux/init.h>
-#include <linux/string.h>
-#include <asm/checksum.h>
-#include <asm/io.h>
-#include <asm/string.h>
-
+#include <linux/tqueue.h>
+#include <linux/interrupt.h>
+#include <asm/atomic.h>
 #include "iucv.h"
+#include <asm/io.h>
+#include <asm/s390_ext.h>
+#include <asm/ebcdic.h>
 
-
-
-
-#define DEBUG123
-#define MAX_DEVICES  10
-
-extern char _ascebc[];
-
-/* 
- *  global structures 
- */
-static char iucv_userid[MAX_DEVICES][8];
-static char iucv_ascii_userid[MAX_DEVICES][8];
-static int  iucv_pathid[MAX_DEVICES] = {0};
-static unsigned char iucv_ext_int_buffer[40] __attribute__((aligned (8))) ={0};
-static unsigned char glob_command_buffer[40] __attribute__((aligned (8)));
-
-#if LINUX_VERSION_CODE>=0x20300
-typedef struct net_device  net_device;
-#else
-typedef struct device  net_device;
-#endif
-net_device iucv_devs[];
-
-
-/* This structure is private to each device. It is used to pass */
-/* packets in and out, so there is place for a packet           */
-struct iucv_priv {
-    struct net_device_stats stats;
-    int packetlen;
-    int status;
-    u8 *packetdata;
-    int pathid;                    /* used device */
-    unsigned char command_buffer[40] __attribute__((aligned (8)));
-    unsigned char ext_int_buffer[40] __attribute__((aligned (8)));
-    u8* receive_buffer;
-    int receive_buffer_len;
-    u8* send_buffer;
-    int send_buffer_len;    
-    char * new_send_buf;       /* send buffer ptr */
-    unsigned char recv_buf[2048];  /* size is just a guess */
-    unsigned char userid[8];
-};
-
-struct iucv_header {
-  short len;
-};
-
-
-
-static __inline__ int netif_is_busy(net_device *dev)
-{
-#if LINUX_VERSION_CODE<0x02032D
-	return(dev->tbusy);
-#else
-	return(test_bit(__LINK_STATE_XOFF,&dev->flags));
-#endif
-}
-
-
-
-#if LINUX_VERSION_CODE<0x02032D
-#define netif_enter_interrupt(dev) dev->interrupt=1
-#define netif_exit_interrupt(dev) dev->interrupt=0
-#define netif_start(dev) dev->start=1
-#define netif_stop(dev) dev->start=0
-
-static __inline__ void netif_stop_queue(net_device *dev)
-{
-	dev->tbusy=1;
-}
-
-static __inline__ void netif_start_queue(net_device *dev)
-{
-	dev->tbusy=0;
-}
-
-static __inline__ void netif_wake_queue(net_device *dev)
-{
-	dev->tbusy=0;
-	mark_bh(NET_BH);
-}
-
-#else
-#define netif_enter_interrupt(dev)
-#define netif_exit_interrupt(dev)
-#define netif_start(dev)
-#define netif_stop(dev)
-#endif
-
-
-
-/*
- * Following the iucv primitives 
- */
-
-
-extern inline void b2f0(int code,void* parm)
-{
-  asm volatile ("LR    1,%1\n\tLR    0,%0\n\t.long 0xb2f01000" ::
-                "d" (code) ,"a" (parm) :"0", "1");
-}
-
-int iucv_enable(void *parms)
-{
-  MASK_T *parm = parms;
-  memset(parms,0,sizeof(parm));
-  parm->ipmask = 0xF8;
-  b2f0(SETMASK,parm);
-  memset(parms,0,sizeof(parm));
-  parm->ipmask = 0xF8;
-  b2f0(SETCMASK,parm);
-  return parm->iprcode;
-}
-
-
-int iucv_declare_buffer(void *parms, DCLBFR_T *buffer)
-{
-  DCLBFR_T *parm = parms;
-  memset(parms,0,sizeof(parm));
-  parm->ipflags1= 0x00;
-  parm->ipbfadr1 = virt_to_phys(buffer);
-  b2f0(DECLARE_BUFFER, parm);
-  return parm->iprcode;
-}
-
-
-int iucv_retrieve_buffer(void *parms)
-{
-  DCLBFR_T *parm = parms;
-  memset(parms,0x0,sizeof(parm));
-  parm->iprcode = 0x0;
-  b2f0(RETRIEVE_BUFFER, parm);
-  return parm->iprcode;
-}
-
-
-int iucv_connect(void *parms,
-                 const char *userid,
-                 const char *host,
-                 const char *ipusr,
-                 unsigned short * used_pathid)
-{
-  CONNECT_T *parm = parms;                              /* ipflags was 0x60*/
-  memset(parms,0x0,sizeof(parm));
-  parm->ipflags1 = 0x80;
-  parm->ipmsglim = 0x0a;
-  memcpy(parm->ipvmid,userid,8);
-  if (ipusr)
-    memcpy(parm->ipuser,ipusr,16);
-  memcpy(parm->iptarget,host,8);
-  b2f0(CONNECT, parm);
-  *used_pathid = parm->ippathid;
-  return parm->iprcode;
-}
-
-
-
-int iucv_accept(void *parms,int pathid)
-{
-#ifdef DEBUG
-  int i=0;
-#endif
-  ACCEPT_T *parm = parms;
-  memset(parms,0,sizeof(parm));
-  parm->ippathid = pathid;
-  parm->ipflags1 = 0x80;
-  parm->ipmsglim = 0x0a;
-#ifdef DEBUG
-  printk("iucv: iucv_accept input.\n");
-  for (i=0;i<40; i++)
-  {
-    printk("%02x ",((char *)parms)[i]);
-  }
-  printk("\n");
-#endif
-  b2f0(ACCEPT, parm);
-  return parm->iprcode;
-}
-
-
-
-int iucv_receive(void *parms,void *bufferarray,int len)
-{
+#undef KERN_DEBUG
+#define KERN_DEBUG KERN_EMERG
+//#define DEBUG3
+//#define DEBUG         /* Turns Printk's on                         */
+//#define DEBUG2        /* This prints the parameter list before and */
+		      /* after the b2f0 call to cp                 */
+#ifdef CONFIG_MODULES
+#define EXPORT_SYMTAB
+#include <linux/module.h>
+#endif
+#undef NULL
+#define NULL 0
+#define ADDED_STOR 64		/* ADDITIONAL STORAGE FOR PATHID @'S */
+ulong declare_flag = 0;
+static uchar iucv_external_int_buffer[40];
+struct tq_struct short_task;	/* automatically initialized to zero */
+static iucv_interrupt_ops_t my_ops;
+spinlock_t lock = SPIN_LOCK_UNLOCKED;
+
+static void do_int (iucv_ConnectionPending *);
+
+/***************INTERRUPT HANDLING DEFINITIONS***************/
+typedef struct _iucv_packet {
+	struct _iucv_packet *next;
+	uchar data[40];
+} iucv_packet;
+struct tq_struct short_task;
+static spinlock_t iucv_packets_lock = SPIN_LOCK_UNLOCKED;
+iucv_packet *iucv_packets_head, *iucv_packets_tail;
+
+static atomic_t bh_scheduled = ATOMIC_INIT (0);
+void bottom_half_interrupt (void);
+
+/************FUNCTION ID'S****************************/
+#define accept          10
+#define connect         11
+#define declare_buffer  12
+#define purge           9
+#define query           0
+#define quiesc          13
+#define receive         5
+#define reject          8
+#define reply           6
+#define resume          14
+#define retrieve_buffer 2
+#define send            4
+#define setmask         16
+#define sever           15
+
+/*****************************************************************/
+/*  Structure: handler                                           */
+/*  members: next - is a pointer to next handler on chain        */
+/*           prev - is a pointer to prev handler on chain        */
+/*           vmid - 8 char array of machine identification       */
+/*           user_data - 16 char array for user identification   */
+/*           mask - 24 char array used to compare the 2 previous */
+/*           interrupt_table - functions for interrupts          */
+/*           start - pointer to start of block of pointers to    */
+/*                   handler_table_entries                       */
+/*           end - pointer to end of block of pointers to        */
+/*                 handler_table_entries                         */
+/*           size - ulong, size of block                         */
+/*           pgm_data - ulong, program data                      */
+/* NOTE: Keep vmid and user_data together in this order          */
+/*****************************************************************/
+typedef struct {
+	ulong *next;
+	ulong *prev;
+	uchar vmid[8];
+	uchar user_data[16];
+	uchar mask[24];
+	iucv_interrupt_ops_t *interrupt_table;
+	ulong *start;
+	ulong *end;
+	ulong size;
+	ulong pgm_data;
+} handler;
+
+/*******************************************************************/
+/* Structure: handler_table_entry                                  */
+/* members: addrs - pointer to a handler                           */
+/*          pathid - ushort containing path identification         */
+/*          pgm_data - ulong, program data                         */
+/*******************************************************************/
+typedef struct {
+	handler *addrs;
+	ushort pathid;
+	ulong pgm_data;
+} handler_table_entry;
+
+/* main_table: array of pointers to handler_tables         */
+static handler_table_entry *main_table[128];
+/* handler_anchor: points to first handler on chain        */
+static handler *handler_anchor;
+
+/****************FIVE  STRUCTURES************************************/
+/* Data struct 1: iparml_control                                    */
+/*                Used for iucv_accept                              */
+/*                         iucv_connect                             */
+/*                         iucv_quiesce                             */
+/*                         iucv_resume                              */
+/*                         iucv_sever                               */
+/*                         iucv_retrieve_buffer                     */
+/* Data struct 2: iparml_dpl  (data in parameter list)              */
+/*                Used for iucv_send_prmmsg                         */
+/*                         iucv_send2way_prmmsg                     */
+/*                         iucv_send2way_prmmsg_array               */
+/*                         iucv_reply_prmmsg                        */
+/* Data struct 3: iparml_db    (data in a buffer)                   */
+/*                Used for iucv_receive                             */
+/*                         iucv_receive_array                       */
+/*                         iucv_receive_simple                      */
+/*                         iucv_reject                              */
+/*                         iucv_reply                               */
+/*                         iucv_reply_array                         */
+/*                         iucv_send                                */
+/*                         iucv_send_simple                         */
+/*                         iucv_send_array                          */
+/*                         iucv_send2way                            */
+/*                         iucv_send2way_array                      */
+/*                         iucv_declare_buffer                      */
+/* Data struct 4: iparml_purge                                      */
+/*                Used for iucv_purge                               */
+/*                         iucv_query                               */
+/* Data struct 5: iparml_set_mask                                   */
+/*                Used for iucv_set_mask                            */
+/********************************************************************/
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iprcode;
+	ushort ipmsglim;
+	ushort res1;
+	uchar ipvmid[8];
+	uchar ipuser[16];
+	uchar iptarget[8];
+} iparml_control;
+
+/******************/
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iprcode;
+	ulong ipmsgid;
+	ulong iptrgcls;
+	uchar iprmmsg[8];
+	ulong ipsrccls;
+	ulong ipmsgtag;
+	ulong ipbfadr2;
+	ulong ipbfln2f;
+	ulong res;
+} iparml_dpl;
+
+/*******************/
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iprcode;
+	ulong ipmsgid;
+	ulong iptrgcls;
+	ulong ipbfadr1;
+	ulong ipbfln1f;
+	ulong ipsrccls;
+	ulong ipmsgtag;
+	ulong ipbfadr2;
+	ulong ipbfln2f;
+	ulong res;
+} iparml_db;
+
+/********************/
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iprcode;
+	ulong ipmsgid;
+	uchar ipaudit[4];
+	uchar res1[4];
+	ulong res2;
+	ulong ipsrccls;
+	ulong ipmsgtag;
+	ulong res3[3];
+} iparml_purge;
+
+/*******************/
+typedef struct {
+	uchar ipmask;
+	uchar res1[2];
+	uchar iprcode;
+	ulong res2[9];
+} iparml_set_mask;
+
+/*********************INTERNAL FUNCTIONS*****************************/
+/********************************************************************/
+/* Name: b2f0                                                       */
+/* Purpose: this function calls cp to execute iucv commands.        */
+/* Input: code - int, identifier of iucv call to cp.                */
+/*        parm - void *, pointer to 40 byte iparml area passed to cp */
+/* Output: iprcode- return code from iucv call to cp                */
+/********************************************************************/
+/* Assembler code performing iucv call                             */
+/*******************************************************************/
+inline ulong
+b2f0 (int code, void *parm)
+{
+	uchar *iprcode;		/* used to extract iprcode */
+#ifdef DEBUG2
+	int i;
+	uchar *prt_parm;
+	prt_parm = (uchar *) (parm);
+	printk (KERN_DEBUG "parameter list before b2f0 call\n");
+	for (i = 0; i < 40; i++)
+		printk (KERN_DEBUG "%02x ", prt_parm[i]);
+	printk (KERN_DEBUG "\n");
+#endif
+	asm volatile ("LRA   1,0(%1)\n\t"
+		      "LR    0,%0\n\t"
+		      ".long 0xb2f01000"
+		      : : "d" (code), "a" (parm) : "0", "1");
+#ifdef DEBUG2
+	printk (KERN_DEBUG "parameter list after b2f0 call\n");
+	for (i = 0; i < 40; i++)
+		printk (KERN_DEBUG "%02x ", prt_parm[i]);
+	printk (KERN_DEBUG "\n");
+#endif
+	iprcode = (uchar *) (parm + 3);
+	return (ulong) (*iprcode);
+}
+
+/**************************************************************/
+/* Name: iucv_retrieve_buffer                                 */
+/* Purpose: terminates all use of iucv                        */
+/* Input: void                                                */
+/* Output: Return code from CP                                */
+/**************************************************************/
+int
+iucv_retrieve_buffer (void)
+{
+	iparml_control parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_retrieve_buffer\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	b2f0_result = b2f0 (retrieve_buffer, &parm);
+	if (b2f0_result == NULL)
+		declare_flag = 0;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_retrieve_buffer\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_declare_buffer                                  */
+/* Purpose: specifies the guests real address of an external  */
+/*          interrupt.                                        */
+/* Input: bfr - pointer to  buffer                            */
+/* Output: iprcode - return code from b2f0 call               */
+/* Note : See output options for b2f0 call                    */
+/**************************************************************/
+int
+iucv_declare_buffer (uchar * bfr)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "Entering iucv_declare_buffer\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ipbfadr1 = virt_to_phys (bfr);
+	b2f0_result = b2f0 (declare_buffer, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "Address of EIB = %p\n", bfr);
+	printk (KERN_DEBUG "Exiting iucv_declare_buffer\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: add_pathid                                           */
+/* Purpose: adds a path id to the system                      */
+/* Input: pathid - ushort, pathid to enter system             */
+/*        handle - iucv_handle_t, address of handler to add to */
+/*        pgm_data - ulong, pathid identifier.                */
+/* Output: 0: successful addition of pathid                   */
+/**************************************************************/
+int
+add_pathid (ushort pathid, iucv_handle_t handle, ulong pgm_data)
+{
+	ulong index1, index2;	/* index1 into main_table */
+	ulong add_flag = 0;
+	ulong old_size = 0, new_size = 0;
+	uchar *to, *from;	/* pointer for copying the table */
+	handler_table_entry *P = 0;	/*P is a pointer to H_T_E */
+	handler *Q = 0;		/*Q is a pointer to handler */
+	ulong *X = 0;		/*Points to array of pointers */
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering add_pathid\n");
+#endif
+	Q = (handler *) handle;	/* Q points to a handler    */
+	/*
+	 * main_table has 128 entries.
+	 * 128*512 = 65536 maximum number of pathid's allowed
+	 */
+	index1 = ((ulong) pathid) / 512;
+	index2 = ((ulong) pathid) % 512;
+#ifdef DEBUG
+	printk (KERN_DEBUG "index1 = %d\n ", (int) index1);
+	printk (KERN_DEBUG "index2 = %d\n ", (int) index2);
+	printk (KERN_DEBUG "Q is pointing to %p ", Q);
+#endif
+	spin_lock (&lock);
+	/*
+	 * If NULL then handler table does not exist and need to get storage
+	 *  and have main_table[index1] point to it
+	 * If allocating storage failed, return
+	 */
+	if (main_table[index1] == NULL) {
+		main_table[index1] = (handler_table_entry *) kmalloc
+		    (512 * sizeof (handler_table_entry), GFP_KERNEL);
+		if (main_table[index1] == NULL) {
+			spin_unlock (&lock);
+			return -ENOBUFS;
+		}
+		memset (main_table[index1], 0,
+			512 * sizeof (handler_table_entry));
 #ifdef DEBUG
-  int i=0;
+		printk (KERN_DEBUG "address of table H_T is %p \n",
+			main_table[index1]);
 #endif
-  RECEIVE_T *parm = parms;
-  memset(parms,0x0,sizeof(parm));
-  /*parm->ipflags1 = 0x42;*/
-  parm->ipflags1 = 0x0;
-  parm->ipmsgid  = 0x0;
-  parm->iptrgcls = 0x0;
-  parm->ipbfadr1 = (ULONG) virt_to_phys(bufferarray);
-  parm->ipbfln1f  = len;
-  parm->ipbfln2f  = 0x0;
-  b2f0(RECEIVE, parm);
-  if (parm->iprcode == 0)
-    len = parm->ipbfln1f;
-//  len = len-parm->ipbfln1f;
-#ifdef DEBUG
-  printk("iucv: iucv_receive command input:\n");
-   for (i=0;i<40;i++)  /* show iucv buffer before send */
-    {
-      printk("%02x ",((char *)parms)[i]);
-    }
-  printk("\n");
-
-  printk("iucv: iucv_receive data buffer:\n");
-  for (i=0;i<len;i++)  /* show data received */
-   {
-     printk("%02x ",((char *)bufferarray)[i]);
-   }
-  printk("\n");
-  printk("received length: %02x ",len);
-
+	}
+	/*
+	 * P points to a handler table entry (H_T_E) in which all entries in
+	 * that structure should be NULL. If they're not NULL, then there
+	 * is a bad pointer and it will return(-2) immediately, otherwise
+	 * data will be entered into H_T_E.
+	 */
+	P = main_table[index1];
+	if ((P + index2)->addrs) {
+#ifdef DEBUG
+		printk (KERN_DEBUG "main_table[index1] = %p \n",
+			main_table[index1]);
+		printk (KERN_DEBUG "P+index2 = %p \n", P + index2);
+		printk (KERN_DEBUG "(P+index2)->addrs is %p \n",
+			(P + index2)->addrs);
+#endif
+		spin_unlock (&lock);
+		printk (KERN_DEBUG "bad pointer1\n");
+		return (-2);
+	}
+	(P + index2)->addrs = handle;
+	/*
+	 * checking if address of handle is valid, if it's not valid,
+	 * unlock the lock and return(-2) immediately.
+	 */
+	if ((P + index2)->addrs == NULL) {
+		spin_unlock (&lock);
+		printk (KERN_DEBUG "bad pointer2\n");
+		return (-2);
+	}
+	(P + index2)->pathid = pathid;
+	if (pgm_data)
+		(P + index2)->pgm_data = pgm_data;
+	else
+		(P + index2)->pgm_data = Q->pgm_data;
+	/*
+	 * Step thru the table of addresses of pathid's to find the first
+	 * available entry (NULL). If an entry is found, add the pathid,
+	 * unlock and exit. If an available entry is not found, allocate a
+	 * new, larger table, copy over the old table and deallocate the
+	 * old table and add the pathid.
+	 */
+#ifdef DEBUG
+	printk (KERN_DEBUG "address of handle is %p\n", handle);
+	printk (KERN_DEBUG "&(Q->start) is %p\n", &(Q->start));
+	printk (KERN_DEBUG "&(Q->end) is %p\n", &(Q->end));
+	printk (KERN_DEBUG "start of pathid table is %p\n", (Q->start));
+	printk (KERN_DEBUG "end of pathid table is %p\n", (Q->end));
+	for (X = (Q->start); X < (Q->end); X++)
+		printk (KERN_DEBUG "X = %p ", X);
+	printk (KERN_DEBUG "\n");
+#endif
+	for (X = (Q->start); X < (Q->end); X++) {
+		if (*X == NULL) {
+#ifdef DEBUG
+			printk (KERN_DEBUG "adding pathid, %p = P+index2\n",
+				(P + index2));
+#endif
+			*X = (ulong) (P + index2);
+			add_flag = 1;
+		}
+		if (add_flag == 1)
+			break;
+	}
+	if (add_flag == 0) {	/* element not added to list */
+		X = Q->start;
+		old_size = Q->size;
+		new_size = old_size + ADDED_STOR;	/* size of new table */
+		from = (uchar *) (Q->start);	/* address of old table */
+		(*Q).start = kmalloc (new_size * sizeof (ulong), GFP_KERNEL);
+		if ((Q->start) == NULL) {
+			spin_unlock (&lock);
+			return -ENOBUFS;
+		}
+		memset ((*Q).start, 0, new_size * sizeof (ulong));
+		to = (uchar *) (Q->start);	/* address of new table */
+		/* copy old table to new  */
+		memcpy (to, from, old_size * (sizeof (ulong)));
+#ifdef DEBUG
+		printk (KERN_DEBUG "Getting a new pathid table\n");
+		printk (KERN_DEBUG "to is %p \n", to);
+		printk (KERN_DEBUG "from is %p \n", from);
+#endif
+		Q->size = new_size;	/* storing new size of table */
+		Q->end = (Q->start) + (Q->size);
+		X = Q->start + old_size;	/* next blank in table */
+		*X = (ulong) (P + index2);	/* adding element to new table */
+#ifdef DEBUG
+		printk (KERN_DEBUG "Q->size is %u \n", (int) (Q->size));
+		printk (KERN_DEBUG "Q->end is %p \n", Q->end);
+		printk (KERN_DEBUG "Q->start is %p \n", Q->start);
+		printk (KERN_DEBUG "X is %p \n", X);
+		printk (KERN_DEBUG "*X is %u \n", (int) (*X));
 #endif
-  return parm->iprcode;
-}
-
-
-int iucv_send(void *parms,int pathid,void *bufferarray,int len,
-              void *recv_buf, int recv_len)
-{
+		kfree (from);	/* free old table */
+	}
+	spin_unlock (&lock);
 #ifdef DEBUG
-  int i=0;
+	printk (KERN_DEBUG "exiting add_pathid\n");
 #endif
-  SEND_T *parm = parms;
-  memset(parms,0x0,sizeof(parm));
-  /*  parm->ipflags1 = 0x48; ??*/
-  parm->ippathid = pathid;
-  parm->ipflags1 = 0x14;                       /* any options ?? */
-  parm->ipmsgid  = 0x0;
-  parm->iptrgcls = 0x0;
-  parm->ipbfadr1 = virt_to_phys(bufferarray);
-  parm->ipbfln1f = len;
-  parm->ipsrccls = 0x0;
-  parm->ipmsgtag = 0x0;
-  parm->ipbfadr2 = virt_to_phys(recv_buf);
-  parm->ipbfln2f = recv_len;
-
+	return (0);
+}				/* end of add_pathid function */
 
+/***********************EXTERNAL FUNCTIONS***************************/
+/**************************************************************/
+/* Name: iucv_query                                           */
+/* Purpose: determines how large an external interrupt buffer */
+/*          IUCV requires to store information                */
+/* Input : bufsize - ulong: size of interrupt buffer          */
+/*         - filled in by function and returned to caller     */
+/*         conmax  - ulong: maximum number of connections that */
+/*           can be outstanding for this VM                   */
+/*         - filled in by function and returned to caller     */
+/* Output: void                                               */
+/**************************************************************/
+void
+iucv_query (ulong * bufsize, ulong * conmax)
+{
+	iparml_purge parm;	/* DOESN'T MATTER WHICH IPARML IS USED    */
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_purge\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	/*
+	 * Assembler instruction calling b2f0  and storing R0 and R1
+	 */
+	asm volatile ("LRA   1,0(%3)\n\t"
+		      "LR    0,%2\n\t"
+		      ".long 0xb2f01000\n\t"
+		      "ST    0,%0\n\t"
+		      "ST    1,%1\n\t":"=m" (*bufsize),
+		      "=m" (*conmax):"d" (query), "a" (&parm):"0", "1");
+	return;
+}
+
+/**************************************************************/
+/* Name: iucv_purge                                           */
+/* Purpose: cancels a message you have sent                   */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong, mid of message                      */
+/*        srccls - ulong, sourse message class                */
+/*        audit  - uchar[4], info about ansync. error condit. */
+/*                 filled in by function and passed back      */
+/* Output: void                                               */
+/* NOTE: pathid is required, flag is always turned on         */
+/**************************************************************/
+int
+iucv_purge (ulong msgid, ushort pathid, ulong srccls, uchar audit[4])
+{
+	iparml_purge parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_purge\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ipmsgid = msgid;
+	parm.ippathid = pathid;
+	parm.ipsrccls = srccls;
+	parm.ipflags1 |= specify_pathid;	/* pathid id flag */
+	if (parm.ipmsgid)
+		parm.ipflags1 |= specify_msgid;
+	if (parm.ipsrccls)
+		parm.ipflags1 |= source_class;
+	b2f0_result = b2f0 (purge, &parm);
+	if (b2f0_result != NULL)
+		return b2f0_result;
+	memcpy (audit, parm.ipaudit, 4);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_purge\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_quiesce                                         */
+/* Purpose: temporarily suspends incoming messages            */
+/* Input: pathid - ushort, pathid                             */
+/*        user_data - uchar[16], user id                      */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: see b2f0 output list                                 */
+/**************************************************************/
+int
+iucv_quiesce (ushort pathid, uchar user_data[16])
+{
+	iparml_control parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_quiesce\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	memcpy (parm.ipuser, user_data, 16);
+	parm.ippathid = pathid;
+	b2f0_result = b2f0 (quiesc, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_quiesce\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_resume                                          */
+/* Purpose: restores communication over a quiesced path       */
+/* Input: pathid - ushort, pathid                             */
+/*        user_data - uchar[16], user id                      */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: see b2f0 output list                                 */
+/**************************************************************/
+int
+iucv_resume (ushort pathid, uchar user_data[16])
+{
+	iparml_control parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_resume\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	memcpy (parm.ipuser, user_data, 16);
+	parm.ippathid = pathid;
+	b2f0_result = b2f0 (resume, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_resume\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_reject                                          */
+/* Purpose: rejects a message                                 */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong, mid of message                      */
+/*        trgcls - ulong, target message class                */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: pathid is required field, flag always turned on      */
+/*       RESTRICTION: target class cannot be zero             */
+/* NOTE: see b2f0 output list                                 */
+/**************************************************************/
+int
+iucv_reject (ushort pathid, ulong msgid, ulong trgcls)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_reject\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ipmsgid = msgid;
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipflags1 |= specify_pathid;	/* flag for pathid */
+	if (parm.ipmsgid)
+		parm.ipflags1 |= specify_msgid;
+	if (parm.iptrgcls)
+		parm.ipflags1 |= target_class;
+	b2f0_result = b2f0 (reject, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_reject\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_setmask                                         */
+/* Purpose: enables or disables certain iucv external interr. */
+/* Input: non_priority_interrupts - uchar                     */
+/*        priority_interrupts - uchar                         */
+/*        non_priority_completion_interrupts - uchar          */
+/*        priority_completion_interrupts) - uchar             */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: see b2f0 output list                                 */
+/**************************************************************/
+int
+iucv_setmask (uchar non_priority_interrupts,
+	      uchar priority_interrupts,
+	      uchar non_priority_completion_interrupts,
+	      uchar priority_completion_interrupts)
+{
+	iparml_set_mask parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_setmask\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	if (non_priority_interrupts)
+		parm.ipmask |= 0x80;
+	if (priority_interrupts)
+		parm.ipmask |= 0x40;
+	if (non_priority_completion_interrupts)
+		parm.ipmask |= 0x20;
+	if (priority_completion_interrupts)
+		parm.ipmask |= 0x10;
+	b2f0_result = b2f0 (setmask, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_setmask\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_sever                                           */
+/* Purpose: terminates an iucv path to another machine        */
+/* Input: pathid - ushort, pathid                             */
+/*        user_data - uchar[16], user id                      */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: see b2f0 output list                                 */
+/**************************************************************/
+int
+iucv_sever (ushort pathid, uchar user_data[16])
+{
+	ulong index1, index2;
+	ulong b2f0_result;
+	handler_table_entry *P = 0;
+	handler *Q = 0;
+	ulong *X;
+	iparml_control parm;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_sever\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	memcpy (parm.ipuser, user_data, 16);
+	parm.ippathid = pathid;
+	b2f0_result = b2f0 (sever, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+	index1 = ((ulong) pathid) / 512;
+	index2 = ((ulong) pathid) % 512;
+	spin_lock (&lock);
+	P = main_table[index1];
+	if (((P + index2)->addrs) == NULL) {	/* called from interrupt code */
+		spin_unlock (&lock);
+		return (-2);	/* bad pointer */
+	}
+	Q = (*(P + index2)).addrs;
 #ifdef DEBUG
-  printk("iucv: iucv_send command input:\n");
-  for (i=0;i<40;i++)  /* show iucv buffer before send */
-   {
-     printk("%02x ",((char *)parms)[i]);
-   }
-  printk("\n");
-
-  printk("iucv: iucv_send data buffer:\n");
-  for (i=0;i<len;i++)  /* show send data before send */
-   {
-     printk("%02x ",((char *)bufferarray)[i]);
-   }
-  printk("\n");
-#endif
-
-  b2f0(SEND, parm);
-
-#ifdef DEBUGXX
- printk("iucv: iucv_send buffer after send:\n");
- for (i=0;i<len;i++) /* show send buffer after send */
-   {
-     printk("%1x",((char *)bufferarray)[i]);
-   }
-   printk("\n");
-#endif
-
-  return parm->iprcode;
-}
-
-
-
-int iucv_sever(void *parms)
-{
-  SEVER_T *parm = parms;
-  memset(parms,0x0,sizeof(parm));
-  parm->ippathid = 0x0;
-  parm->ipflags1 = 0x0;
-  parm->iprcode  = 0xF;
-  memset(parm->ipuser,0,16);
-  b2f0(SEVER, parm);
-  return parm->iprcode;
-}
-
-
+	printk (KERN_DEBUG "pathid is %d\n", pathid);
+	printk (KERN_DEBUG "index1 is %d\n", (int) index1);
+	printk (KERN_DEBUG "index2 is %d\n", (int) index2);
+	printk (KERN_DEBUG "H_T_E is %p\n", P);
+	printk (KERN_DEBUG "address of handler is %p\n", Q);
+	for (X = ((*Q).start); X < ((*Q).end); X++)
+		printk (KERN_DEBUG " %x ", (int) (*X));
+	printk (KERN_DEBUG "\n above is pathid table\n");
+#endif
+/********************************************************************/
+/* Searching the pathid address table for matching address, once    */
+/* found, NULL the field. Then Null the H_T_E fields.               */
+/********************************************************************/
+	for (X = ((*Q).start); X < ((*Q).end); X++)
+		if (*X == (ulong) (P + index2)) {
+#ifdef DEBUG
+			printk (KERN_DEBUG "found a path to sever\n");
+			printk (KERN_DEBUG "severing %d \n", (int) (*X));
+#endif
+			*X = NULL;
+			(*(P + index2)).addrs = NULL;	/*clearing the fields */
+			(*(P + index2)).pathid = 0;
+			(*(P + index2)).pgm_data = 0;
+		}
+	spin_unlock (&lock);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_sever\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_receive                                         */
+/* Purpose: receives incoming message                         */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - *ulong, mid of message                     */
+/*        trgcls - *ulong, target message class               */
+/*        buffer - pointer of buffer                          */
+/*        buflen - length of buffer                           */
+/*        adds_curr_buffer - pointer to updated buffer address*/
+/*                           to write to                      */
+/*        adds_curr_length - pointer to updated length in     */
+/*                           buffer available to write to     */
+/*        reply_required - uchar *, flag                      */
+/*        priority_msg - uchar *, flag                        */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: pathid must be specified, flag being turned on       */
+/* RESTRICTIONS: target class CANNOT be zero because the code */
+/* checks for a non-NULL value to turn flag on, therefore if  */
+/* target class = zero, flag will not be turned on.           */
+/**************************************************************/
+int
+iucv_receive (ushort pathid, ulong * msgid, ulong * trgcls,
+	      void *buffer, ulong buflen,
+	      uchar * reply_required,
+	      uchar * priority_msg,
+	      ulong * adds_curr_buffer, ulong * adds_curr_length)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_receive\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ipmsgid = *msgid;
+	parm.ippathid = pathid;
+	parm.iptrgcls = *trgcls;
+	parm.ipflags1 |= specify_pathid;	/* turning pathid flag */
+	if (parm.ipmsgid)
+		parm.ipflags1 |= 0x05;
+	if (parm.iptrgcls)
+		parm.ipflags1 |= target_class;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = buflen;
+	b2f0_result = b2f0 (receive, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+	if (msgid)
+		*msgid = parm.ipmsgid;
+	if (trgcls)
+		*trgcls = parm.iptrgcls;
+	if (parm.ipflags1 & prior_msg)
+		if (priority_msg)
+			*priority_msg = 0x01;	/*yes, priority msg */
+	if (!(parm.ipflags1 & 0x10))	/*& with X'10'     */
+		if (reply_required)
+			*reply_required = 0x01;	/*yes, reply required */
+	if (!(parm.ipflags1 & parm_data)) {	/*msg not in parmlist */
+		if (adds_curr_length)
+			*adds_curr_length = parm.ipbfln1f;
+		if (adds_curr_buffer)
+			*adds_curr_buffer = parm.ipbfadr1;
+	} else {
+		if ((buflen) >= 8) {
+			if (buffer)
+				memcpy ((char *) buffer,
+					(char *) parm.ipbfadr1, 8);
+			if (adds_curr_length)
+				*adds_curr_length = ((buflen) - 8);
+			if (adds_curr_buffer)
+				*adds_curr_buffer = (ulong) buffer + 8;
+		} else {
+			parm.iprcode |= 0x05;
+			b2f0_result = (ulong) parm.iprcode;
+		}
+	}
 #ifdef DEBUG
-/*--------------------------*/
-/* Dump buffer formatted    */
-/*--------------------------*/
-static void dumpit(char* buf, int len)
-{
-  int i;
-  for (i=0;i<len;i++) {
-    if (!(i%16)&&i!=0)
-      printk("\n");
-    else if (!(i%4)&&i!=0)
-      printk(" ");
-    printk(  "%02X",buf[i]);
-  }
-  if (len%16)
-    printk(  "\n");
-}
+	printk (KERN_DEBUG "exiting iucv_receive\n");
 #endif
-
-
-
-/*--------------------------*/
-/* Get device from pathid   */
-/*--------------------------*/
-net_device * get_device_from_pathid(int pathid)
-{
-   int i;
-    for (i=0;i<=MAX_DEVICES;i++)
-    {
-      if (iucv_pathid[i] == pathid)
-        return &iucv_devs[i];
-    }
-    printk("iucv: get_device_from_pathid: no device for pathid %X\n",pathid);
- return 0;
+	return b2f0_result;
 }
 
-
-
-/*--------------------------*/
-/* Get device from userid   */
-/*--------------------------*/
-net_device * get_device_from_userid(char * userid)
-{
-   int i;
-   net_device * dev;
-   struct iucv_priv *privptr;
-      for (i=0;i<=MAX_DEVICES;i++)
-      {
-        dev = &iucv_devs[i];
-        privptr = (struct iucv_priv *)(dev->priv);
-        if (memcmp(privptr->userid,userid,8)==0)
-          return &iucv_devs[i];
-      }
-      printk("iucv: get_device_from_uid: no device for userid %s\n",userid);
-   return 0;
+/**************************************************************/
+/* Name: iucv_receive_simple                                  */
+/* Purpose: receives fully-qualified message                  */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong, id of message                       */
+/*        trgcls - ulong, target message class                */
+/*        buffer - pointer of buffer                          */
+/*        buflen - length of buffer                           */
+/* Output: iprcode - return code from b2f0 call               */
+/**************************************************************/
+int
+iucv_receive_simple (ushort pathid, ulong msgid, ulong trgcls,
+		     void *buffer, ulong buflen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+	pr_debug ("entering iucv_receive_simple\n");
+
+	memset (&(parm), 0, sizeof (parm));
+	parm.ipmsgid = msgid;
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipflags1 = IPFGMID + IPFGPID + IPFGMCL;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = buflen;
+
+	b2f0_result = b2f0 (receive, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+
+	if (parm.ipflags1 & IPRMDATA) {	/*msg in parmlist */
+		if ((buflen) >= 8)
+			memcpy ((char *) buffer, (char *) parm.ipbfadr1, 8);
+		else
+			b2f0_result = 5;
+	}
+	pr_debug ("exiting iucv_receive_simple\n");
+	return b2f0_result;
 }
 
-
-/*--------------------------*/
-/* Open iucv Device Driver */
-/*--------------------------*/
-int iucv_open(net_device *dev)
-{
-    int rc;
-    unsigned short iucv_used_pathid;
-    struct iucv_priv *privptr;
-    char iucv_host[8]   ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
-    char vmident[16]    ={0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
-                          0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40};
-
-#ifdef DEBUG
-    printk(  "iucv: iucv_open, device: %s\n",dev->name);
-#endif
-
-    privptr = (struct iucv_priv *)(dev->priv);
-    if(privptr->pathid != -1) {
-       netif_start(dev);
-       netif_start_queue(dev);
-       return 0;
-    }
-    if ((rc = iucv_connect(privptr->command_buffer,
-                           privptr->userid,
-                           iucv_host,
-                           vmident,
-                           &iucv_used_pathid))!=0) {
-      printk(  "iucv: iucv connect failed with rc %X\n",rc);
-      iucv_retrieve_buffer(privptr->command_buffer);
-      return -ENODEV;
-    }
-
-    privptr->pathid = iucv_used_pathid;
-    iucv_pathid[dev-iucv_devs]=privptr->pathid;
-
+/**************************************************************/
+/* Name: iucv_receive_array                                   */
+/* Purpose: receives incoming message                         */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  -* ulong, mid of message                     */
+/*        trgcls -* ulong, target message class               */
+/*        buffer - pointer of iucv_array_t                    */
+/*        buflen - ulong , length of buffer                   */
+/*        reply_required - uchar *, flag returned to caller   */
+/*        priority_msg - uchar *, flag returned to caller     */
+/*        adds_curr_buffer - pointer to updated buffer array  */
+/*                   to write to                              */
+/*        adds_curr_length - pointer to updated length in     */
+/*                   buffer available to write to             */
+/* Output: iprcode - return code from b2f0 call               */
+/* NOTE: pathid must be specified, flag being turned on       */
+/* RESTRICTIONS: target class CANNOT be zero because the code */
+/* checks for a non-NULL value to turn flag on, therefore if  */
+/* target class = if target class = zero flag will not be     */
+/* turned on, therefore if target class is specified it cannot */
+/* be zero.                                                   */
+/**************************************************************/
+int
+iucv_receive_array (ushort pathid, ulong * msgid, ulong * trgcls,
+		    iucv_array_t * buffer, ulong * buflen,
+		    uchar * reply_required,
+		    uchar * priority_msg,
+		    ulong * adds_curr_buffer, ulong * adds_curr_length)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_receive_array\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ipmsgid = *msgid;
+	parm.ippathid = pathid;
+	parm.iptrgcls = *trgcls;
+	parm.ipflags1 |= array;	/* using an address list  */
+	parm.ipflags1 |= specify_pathid;	/*turning on pathid flag */
+	if (parm.ipmsgid)
+		parm.ipflags1 |= 0x05;
+	if (parm.iptrgcls)
+		parm.ipflags1 |= target_class;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = *buflen;
+	b2f0_result = b2f0 (receive, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+	if (msgid)
+		*msgid = parm.ipmsgid;
+	if (trgcls)
+		*trgcls = parm.iptrgcls;
+	if (parm.ipflags1 & prior_msg)
+		if (priority_msg)
+			*priority_msg = 0x01;	/*yes, priority msg */
+	if (!(parm.ipflags1 & 0x10))	/*& with X'10'     */
+		if (reply_required)
+			*reply_required = 0x01;	/*yes, reply required */
+	if (!(parm.ipflags1 & parm_data)) {	/*msg not in parmlist */
+		if (adds_curr_length)
+			*adds_curr_length = parm.ipbfln1f;
+		if (adds_curr_buffer)
+			*adds_curr_buffer = parm.ipbfadr1;
+	} else {
+		if ((buffer->length) >= 8) {
+			memcpy ((char *) buffer->address,
+				(char *) parm.ipbfadr1, 8);
+			if (adds_curr_buffer)
+				*adds_curr_buffer =
+				    (ulong) ((buffer->address) + 8);
+			if (adds_curr_length)
+				*adds_curr_length = ((buffer->length) - 8);
+
+		} else {
+			parm.iprcode |= 0x05;
+			b2f0_result = (ulong) parm.iprcode;
+		}
+	}
 #ifdef DEBUG
-    printk(  "iucv: iucv_connect ended with rc: %X\n",rc);
-    printk(  "iucv[%d] pathid %X \n",(int)(dev-iucv_devs),privptr->pathid);
+	printk (KERN_DEBUG "exiting iucv_receive\n");
 #endif
-    netif_start(dev);
-    netif_start_queue(dev);
-    return 0;
+	return b2f0_result;
 }
 
-
-
-/*-----------------------------------------------------------------------*/
-/* Receive a packet: retrieve, encapsulate and pass over to upper levels */
-/*-----------------------------------------------------------------------*/
-void iucv_rx(net_device *dev, int len, unsigned char *buf)
-{
-
-  struct sk_buff *skb;
-  struct iucv_priv *privptr = (struct iucv_priv *)dev->priv;
-
-#ifdef DEBUG
-  printk(  "iucv: iucv_rx len: %X, device %s\n",len,dev->name);
-  printk(  "iucv rx: received orig:\n");
-  dumpit(buf,len);
-#endif
-
-  /* strip iucv header now */
-  len = len - 2;   /* short header */
-  buf = buf + 2;   /* short header */
-
-  skb = dev_alloc_skb(len+2); /* why +2 ? alignment ? */
-  if (!skb) {
-    printk(  "iucv rx: low on mem, returning...\n");
-    return;
-  }
-  skb_reserve(skb, 2);                        /* align IP on 16B boundary*/
-  memcpy(skb_put(skb, len), buf, len);
-#ifdef DEBUG
-  printk(  "iucv rx: data before netif_rx()\n");
-  dumpit(buf,len);
-#endif
-
-  /* Write metadata, and then pass to the receive level */
-  skb->mac.raw = skb->data;
-  skb->pkt_type = PACKET_HOST;
-  skb->dev = dev;
-  skb->protocol = htons(ETH_P_IP);
-  skb->ip_summed = CHECKSUM_UNNECESSARY;                /* don't check it*/
-  privptr->stats.rx_packets++;
-  netif_rx(skb);
-
-  return;
-} /* end  iucv_rx() */
-
-
-
-
-/*----------------------------*/
-/* handle interrupts          */
-/*----------------------------*/
-void do_iucv_interrupt(void)
-{
-  int rc;
-  struct in_device *indev;
-  struct in_ifaddr *inaddr;
-  unsigned long len=0;
-  net_device *dev=0;
-  struct iucv_priv *privptr;
-  INTERRUPT_T * extern_int_buffer;
-  unsigned short iucv_data_len=0;
-  unsigned short iucv_next=0;
-  unsigned char * rcvptr;
-  
-  /* get own buffer: */
-  extern_int_buffer = (INTERRUPT_T*) iucv_ext_int_buffer;
-  
-  netif_enter_interrupt(dev);        /* lock ! */
-  
-#ifdef DEBUG
-  printk(  "iucv: do_iucv_interrupt %x received; pathid: %02X\n",
-	   extern_int_buffer->iptype,extern_int_buffer->ippathid);
-  printk(   "iucv: extern_int_buffer:\n");
-  dumpit((char *)&extern_int_buffer[0],40);
-#endif
-  
-  switch (extern_int_buffer->iptype)
-    {
-    case 0x01: /* connection pending ext interrrupt */
-#ifdef DEBUG
-      printk(  "iucv: connection pending IRQ.\n");
-#endif
-      
-      rc = iucv_accept(glob_command_buffer,
-		       extern_int_buffer->ippathid);
-      if (rc != 0) {
-	printk(  "iucv: iucv_accept failed with rc: %X\n",rc);
-	iucv_retrieve_buffer(glob_command_buffer);
-	break;
-      }
-#ifdef DEBUG
-      dumpit(&((char *)extern_int_buffer)[8],8);
-#endif
-      dev = get_device_from_userid(&((char*)extern_int_buffer)[8]);
-      privptr = (struct iucv_priv *)(dev->priv);
-      privptr->pathid =  extern_int_buffer->ippathid;
-      
-#ifdef DEBUG
-      printk(  "iucv: iucv_accept ended with rc: %X\n",rc);
-      printk(  "iucv: device %s found.\n",dev->name);
-#endif
-      break;
-      
-    case 0x02: /* connection completed ext interrrupt */
-      /* set own global IP address */
-      /* & set global routing addr */
-#ifdef DEBUG
-      printk(  "connection completed.\n");
-#endif
-      
-      if( extern_int_buffer->ipmsgtag !=0)
-	{
-	  /* get ptr's to kernel struct with local & broadcast address */
-	  dev = get_device_from_pathid(extern_int_buffer->ippathid);
-	  privptr = (struct iucv_priv *)(dev->priv);
-	  indev = dev->ip_ptr;
-	  inaddr = (struct in_ifaddr*) indev->ifa_list;
+/**************************************************************/
+/* Name: iucv_send                                            */
+/* Purpose: sends messages                                    */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message returned to caller  */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        buffer - pointer to buffer                          */
+/*        buflen - ulong, length of buffer                    */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send (ushort pathid, ulong * msgid,
+	   ulong trgcls, ulong srccls,
+	   ulong msgtag, uchar priority_msg, void *buffer, ulong buflen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = buflen;	/* length of message */
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipflags1 |= one_way_msg;	/* one way message */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (send, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_send_array                                      */
+/* Purpose: sends messages in buffer array                    */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message returned to caller  */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        buffer - pointer to iucv_array_t                    */
+/*        buflen - ulong, length of buffer                    */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send_array (ushort pathid, ulong * msgid,
+		 ulong trgcls, ulong srccls,
+		 ulong msgtag, uchar priority_msg,
+		 iucv_array_t * buffer, ulong buflen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send_array\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = buflen;	/* length of message */
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipflags1 |= one_way_msg;	/* one way message */
+	parm.ipflags1 |= array;	/* one way w/ array */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (send, &parm);
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send_array\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_send_prmmsg                                     */
+/* Purpose: sends messages in parameter list                  */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message                     */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        prmmsg - uchar[8], message being sent               */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send_prmmsg (ushort pathid, ulong * msgid,
+		  ulong trgcls, ulong srccls,
+		  ulong msgtag, uchar priority_msg, uchar prmmsg[8])
+{
+	iparml_dpl parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send_prmmsg\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipflags1 |= parm_data;	/* message in prmlist */
+	parm.ipflags1 |= one_way_msg;	/* one way message */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	memcpy (parm.iprmmsg, prmmsg, 8);
+	b2f0_result = b2f0 (send, &parm);
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send_prmmsg\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_send2way                                        */
+/* Purpose: sends messages in both directions                 */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message                     */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        buffer - pointer to buffer                          */
+/*        buflen - ulong, length of buffer                    */
+/*        ansbuf - pointer to buffer on reply                 */
+/*        anslen - length of ansbuf buffer                    */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send2way (ushort pathid, ulong * msgid,
+	       ulong trgcls, ulong srccls,
+	       ulong msgtag, uchar priority_msg,
+	       void *buffer, ulong buflen, void *ansbuf, ulong anslen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send2way\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = buflen;	/* length of message */
+	parm.ipbfadr2 = (ulong) ansbuf;
+	parm.ipbfln2f = anslen;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (send, &parm);
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send2way\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_send2way_array                                  */
+/* Purpose: sends messages in both directions in arrays       */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message                     */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        buffer - pointer to iucv_array_t                    */
+/*        buflen - ulong, length of buffer                    */
+/*        ansbuf - pointer to iucv_array_t on reply           */
+/*        anslen - length of ansbuf buffer                    */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send2way_array (ushort pathid, ulong * msgid,
+		     ulong trgcls, ulong srccls,
+		     ulong msgtag, uchar priority_msg,
+		     iucv_array_t * buffer, ulong buflen,
+		     iucv_array_t * ansbuf, ulong anslen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send2way_array\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipbfadr1 = (ulong) buffer;
+	parm.ipbfln1f = buflen;	/* length of message */
+	parm.ipbfadr2 = (ulong) ansbuf;
+	parm.ipbfln2f = anslen;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipflags1 |= array;	/* send  w/ array  */
+	parm.ipflags1 |= reply_array;	/* reply w/ array  */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (send, &parm);
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send2way_array\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_send2way_prmmsg                                 */
+/* Purpose: sends messages in both directions w/parameter lst */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message                     */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        prmmsg - uchar[8], message being sent in parameter  */
+/*        ansbuf - pointer to buffer                          */
+/*        anslen - length of ansbuf buffer                    */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send2way_prmmsg (ushort pathid, ulong * msgid,
+		      ulong trgcls, ulong srccls,
+		      ulong msgtag, uchar priority_msg,
+		      uchar prmmsg[8], void *ansbuf, ulong anslen)
+{
+	iparml_dpl parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send2way_prmmsg\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipbfadr2 = (ulong) ansbuf;
+	parm.ipbfln2f = anslen;
+	parm.ipflags1 |= parm_data;	/* message in prmlist */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	memcpy (parm.iprmmsg, prmmsg, 8);
+	b2f0_result = b2f0 (send, &parm);
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send2way_prmmsg\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_reply                                           */
+/* Purpose: responds to the two-way messages that you receive */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong, id of message                       */
+/*        trgcls - ulong, target message class                */
+/*        priority_msg - uchar, flag                          */
+/*        buf    - pointer, address of buffer                 */
+/*        buflen - length of buffer                           */
+/* Output: iprcode - return code from b2f0 call               */
+/**************************************************************/
+int
+iucv_reply (ushort pathid, ulong msgid, ulong trgcls,
+	    uchar priority_msg, void *buf, ulong buflen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_reply\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
+	parm.iptrgcls = trgcls;
+	parm.ipbfadr2 = (ulong) buf;
+	parm.ipbfln2f = buflen;	/* length of message */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (reply, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_reply\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_reply_array                                     */
+/* Purpose: responds to the two-way messages that you receive */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong, id of message                       */
+/*        trgcls - ulong, target message class                */
+/*        priority_msg - uchar, flag                          */
+/*        buf    - pointer, address of array                  */
+/*        buflen - length of buffer                           */
+/* Output: iprcode - return code from b2f0 call               */
+/**************************************************************/
+int
+iucv_reply_array (ushort pathid, ulong msgid, ulong trgcls,
+		  uchar priority_msg, iucv_array_t * buffer, ulong buflen)
+{
+	iparml_db parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_reply_array\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
+	parm.iptrgcls = trgcls;
+	parm.ipbfadr2 = (ulong) buffer;
+	parm.ipbfln2f = buflen;	/* length of message */
+	parm.ipflags1 |= reply_array;	/* reply w/ array  */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (reply, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_reply_array\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_reply_prmmsg                                    */
+/* Purpose: responds to the two-way messages in parameter list */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong, id of message                       */
+/*        trgcls - ulong, target message class                */
+/*        priority_msg - uchar, flag                          */
+/*        prmmsg - uchar[8], message in parameter list        */
+/* Output: iprcode - return code from b2f0 call               */
+/**************************************************************/
+int
+iucv_reply_prmmsg (ushort pathid, ulong msgid, ulong trgcls,
+		   uchar priority_msg, uchar prmmsg[8])
+{
+	iparml_dpl parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_reply_prmmsg\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.ipmsgid = msgid;
+	parm.iptrgcls = trgcls;
+	memcpy (parm.iprmmsg, prmmsg, 8);
+	parm.ipflags1 |= parm_data;
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	b2f0_result = b2f0 (reply, &parm);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_reply_prmmsg\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_connect                                         */
+/* Purpose: establishes an IUCV path to another vm            */
+/* Input: pathid - ushort *, pathid returned to user          */
+/*        msglim - ushort, limit of outstanding messages      */
+/*        user_data - uchar[16], user data                    */
+/*        userid - uchar[8], user's id                        */
+/*        system_name - uchar[8], system identification       */
+/*        priority_requested - uchar- flag                    */
+/*        prmdata - uchar, flag prgrm can handler messages    */
+/*                  in parameter list                         */
+/*        quiesce - uchar, flag to quiesce a path being establ */
+/*        control - uchar, flag, option not used              */
+/*        local   - uchar, flag, establish connection only on */
+/*                  local system                              */
+/*        priority_permitted - uchar *, flag returned to user */
+/*        handle - address of handler                         */
+/*        pgm_data - ulong                                    */
+/* Output: iprcode - return code from b2f0 call               */
+/**************************************************************/
+int
+iucv_connect (ushort * pathid, ushort msglim, uchar user_data[16],
+	      uchar userid[8], uchar system_name[8],
+	      uchar priority_requested, uchar prmdata,
+	      uchar quiesce, uchar control,
+	      uchar local, uchar * priority_permitted,
+	      iucv_handle_t handle, ulong pgm_data)
+{
+	iparml_control parm;
+	ulong b2f0_result;
+	int add_pathid_result, rc;
+	handler *R;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_connect\n");
+#endif
+	memset (&parm, 0, sizeof (parm));
+	if (declare_flag == NULL) {
+		rc = iucv_declare_buffer (iucv_external_int_buffer);
+		if (rc) {
+			printk (KERN_DEBUG "IUCV: registration failed\n");
+#ifdef DEBUG
+			printk (KERN_DEBUG "rc from declare buffer is: %i\n",
+				rc);
+#endif
+			return rc;
+		} else
+			declare_flag = 1;
 	}
-      break;
-      
-      
-    case 0x03: /* connection severed ext interrrupt */
-      /* we do not handle this one at this time */
-#ifdef DEBUG
-      printk(  "connection severed.\n");
-#endif
-      break;
-      
-      
-    case 0x04: /* connection quiesced ext interrrupt */
-      /* we do not handle this one at this time */
-#ifdef DEBUG
-      printk(  "connection quiesced.\n");
-#endif
-      break;
-      
-      
-    case 0x05: /* connection resumed ext interrrupt */
-      /* we do not handle this one at this time */
-#ifdef DEBUG
-      printk(  "connection resumed.\n");
-#endif
-      break;
-      
-      
-    case 0x06: /* priority message complete ext interrupt */
-    case 0x07: /* non priority message complete ext interrupt */
-      /* send it to iucv_rx for handling */
+	/* Checking if handle is valid  */
+	spin_lock (&lock);
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		if (R == handle)
+			break;
+	if (R == NULL) {
+		spin_unlock (&lock);
 #ifdef DEBUG
-      printk(  "message completed.\n");
+		printk (KERN_DEBUG "iucv_connect: Invalid Handle\n");
 #endif
-      
-      if (extern_int_buffer->ipaudit ==0)  /* ok case */
-	{
+		return (-2);
+	}
+	if (pathid == NULL) {
+		spin_unlock (&lock);
 #ifdef DEBUG
-	  printk(  "iucv: msg complete interrupt successful, rc: %X\n",
-		   (unsigned int)extern_int_buffer->ipaudit);
+		printk (KERN_DEBUG "iucv_connect: invalid pathid pointer\n");
 #endif
-	  ;
+		return (-3);
 	}
-      else
-	{
-	  printk(  "iucv: msg complete interrupt error, rc: %X\n",
-		   (unsigned int)extern_int_buffer->ipaudit);
+	spin_unlock (&lock);
+	parm.ipmsglim = msglim;
+	memcpy (parm.ipuser, user_data, 16);
+	memcpy (parm.ipvmid, userid, 8);
+	memcpy (parm.iptarget, system_name, 8);
+	if (parm.iptarget)
+		ASCEBC (parm.iptarget, 8);
+	if (parm.ipvmid) {
+		ASCEBC (parm.ipvmid, 8);
+		EBC_TOUPPER(parm.ipvmid, 8);
 	}
-      /* a transmission is over: tell we are no more busy */
-      dev = get_device_from_pathid(extern_int_buffer->ippathid);
-      privptr = (struct iucv_priv *)(dev->priv);
-      privptr->stats.tx_packets++;
-      netif_wake_queue(dev);                /* transmission is no longer busy*/
-      break;
-      
-      
-    case 0x08: /* priority message pending */
-    case 0x09: /* non priority message pending */
-#ifdef DEBUG
-      printk(  "message pending.\n");
-#endif
-      dev = get_device_from_pathid(extern_int_buffer->ippathid);
-      privptr = (struct iucv_priv *)(dev->priv);
-      rcvptr = &privptr->receive_buffer[0];
-      
-      /* re-set receive buffer */
-      memset(privptr->receive_buffer,0,privptr->receive_buffer_len);
-      len = privptr->receive_buffer_len;
-      
-        /* get data now */
-        if (extern_int_buffer->ipflags1 & 0x80)
-	  {  /* data is in the message */
+	if (priority_requested)
+		parm.ipflags1 |= prior_msg;
+	if (prmdata)
+		parm.ipflags1 |= parm_data;	/*data in parameter list */
+	if (quiesce)
+		parm.ipflags1 |= quiesce_msg;
+	if (control) {
+		/* do nothing at the time being  */
+		/*control not provided yet */
+	}
+	if (local)
+		parm.ipflags1 |= local_conn;	/*connect on local system */
+	b2f0_result = b2f0 (connect, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+	add_pathid_result = add_pathid (parm.ippathid, handle, pgm_data);
+	if (add_pathid_result) {
 #ifdef DEBUG
-	    printk(  "iucv: iucv_receive data is in header!\n");
+		printk (KERN_DEBUG "iucv_connect: add_pathid failed \n");
 #endif
-	    memcpy(privptr->receive_buffer,
-		   (char *)extern_int_buffer->iprmmsg1,
-		   (unsigned long)(extern_int_buffer->iprmmsg2));
-	  }
-        else /* data is in buffer, do a receive */
-	  {
-	    rc = iucv_receive(privptr->command_buffer,rcvptr,len);
-	    if (rc != 0  || len == 0)
-	      {
-		printk(  "iucv: iucv_receive failed with rc: %X, length: %lX\n",rc,len);
-		iucv_retrieve_buffer(privptr->command_buffer);
-		break;
-	      }
-	  } /* end else */
-	
-      iucv_next = 0; 
-      /* get next packet offset */  
-      iucv_data_len= *((unsigned short*)rcvptr); 
-        do{ /* until receive buffer is empty, i.e. iucv_next == 0 ! */
+		return (add_pathid_result);
+	}
+	*pathid = parm.ippathid;
+	if (parm.ipflags1 & prior_msg)
+		if (priority_permitted)
+			*priority_permitted = 0x01;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_connect\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_accept                                          */
+/* Purpose: completes the iucv communication path             */
+/* Input: pathid - ushort , pathid                            */
+/*        msglim - ushort, limit of outstanding messages      */
+/*        user_data - uchar[16], user data                    */
+/*        priority_requested - uchar- flag                    */
+/*        prmdata - uchar, flag prgrm can handler messages    */
+/*                  in parameter list                         */
+/*        quiesce - uchar, flag to quiesce a path being establ*/
+/*        control - uchar, flag, option not used              */
+/*        priority_permitted -uchar *, flag returned to caller*/
+/*        handle - address of handler                         */
+/*        pgm_data - ulong                                    */
+/* Output: iprcode - return code from b2f0 call               */
+/**************************************************************/
+int
+iucv_accept (ushort pathid, ushort msglim, uchar user_data[16],
+	     uchar priority_requested,
+	     uchar prmdata, uchar quiesce, uchar control,
+	     uchar * priority_permitted, iucv_handle_t handle, ulong pgm_data)
+{
+	ulong index1, index2;
+	handler_table_entry *P = 0;
+	iparml_control parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_accept\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.ipmsglim = msglim;
+	memcpy (parm.ipuser, user_data, 16);
+	if (priority_requested)
+		parm.ipflags1 |= prior_msg;
+	if (prmdata)
+		parm.ipflags1 |= parm_data;	/*data in parameter list */
+	if (quiesce)
+		parm.ipflags1 |= quiesce_msg;
+	if (control) {
+		/* do nothing at the time being  */
+		/*control not provided yet */
+	}
+	b2f0_result = b2f0 (accept, &parm);
+	if (b2f0_result)
+		return b2f0_result;
+	index1 = ((ulong) pathid) / 512;
+	index2 = ((ulong) pathid) % 512;
+	spin_lock (&lock);
+	if (pgm_data) {
+		P = main_table[index1];
+		(P + index2)->pgm_data = pgm_data;
+	}
+	spin_unlock (&lock);
+	if (parm.ipflags1 & prior_msg)
+		if (priority_permitted)
+			*priority_permitted = 0x01;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_accept\n");
+#endif
+	return b2f0_result;
+}
+
+/**************************************************************/
+/* Name: iucv_send2way_prmmsg_array                           */
+/* Purpose: sends messages in both directions w/parameter lst */
+/* Input: pathid - ushort, pathid                             */
+/*        msgid  - ulong *, id of message returned to caller  */
+/*        trgcls - ulong, target message class                */
+/*        srccls - ulong, source message class                */
+/*        msgtag - ulong, message tag                         */
+/*        priority_msg - uchar, flag                          */
+/*        prmmsg - uchar[8], message being sent in parameter  */
+/*        ansbuf - pointer to array of buffers                */
+/*        anslen - length of ansbuf buffer                    */
+/* Output: iprcode - return code from b2f0 call               */
+/*         msgid - returns message id                         */
+/**************************************************************/
+int
+iucv_send2way_prmmsg_array (ushort pathid, ulong * msgid,
+			    ulong trgcls, ulong srccls,
+			    ulong msgtag, uchar priority_msg,
+			    uchar prmmsg[8],
+			    iucv_array_t * ansbuf, ulong anslen)
+{
+	iparml_dpl parm;
+	ulong b2f0_result;
+#ifdef DEBUG
+	printk (KERN_DEBUG "entering iucv_send2way_prmmsg\n");
+#endif
+	memset (&(parm), 0, sizeof (parm));
+	parm.ippathid = pathid;
+	parm.iptrgcls = trgcls;
+	parm.ipsrccls = srccls;
+	parm.ipmsgtag = msgtag;
+	parm.ipbfadr2 = (ulong) ansbuf;
+	parm.ipbfln2f = anslen;
+	parm.ipflags1 |= 0x88;	/* message in prmlist */
+	if (priority_msg)
+		parm.ipflags1 |= prior_msg;	/* priority message */
+	memcpy (parm.iprmmsg, prmmsg, 8);
+	b2f0_result = b2f0 (send, &parm);
+	if (msgid)
+		*msgid = parm.ipmsgid;
+#ifdef DEBUG
+	printk (KERN_DEBUG "exiting iucv_send2way_prmmsg\n");
+#endif
+	return b2f0_result;
+}
+
+/******************************************************************/
+/* Name: top_half_handler                                         */
+/* Purpose: handle minimum amount of interrupt in fastest time    */
+/*  possible and then pass interrupt to bottom half handler.      */
+/* Input: external interrupt buffer                               */
+/* Output: void                                                   */
+/******************************************************************/
+
+inline void
+top_half_interrupt (struct pt_regs *regs, __u16 code)
+{
+	iucv_packet *pkt;
+	pkt = (iucv_packet *) kmalloc
+	    (sizeof (iucv_packet), GFP_ATOMIC);
+	if (pkt == NULL) {
+		printk (KERN_DEBUG "out of memory\n");
+		return;
+	}
+	memcpy (pkt->data, iucv_external_int_buffer, 40);
+#ifdef DEBUG3
+printk (KERN_EMERG "TH: Got INT: %08x\n", *(int *)(pkt->data+4));
+#endif
+	/* put new packet on the list */
+	spin_lock (&iucv_packets_lock);
+	pkt->next = NULL;
+	if (iucv_packets_tail != NULL)
+		iucv_packets_tail->next = pkt;
+	else
+		iucv_packets_head = pkt;
+	iucv_packets_tail = pkt;
+	spin_unlock (&iucv_packets_lock);
+
+	if (atomic_compare_and_swap (0, 1, &bh_scheduled) == 0) {
+#ifdef DEBUG3
+printk (KERN_EMERG "TH: Queuing BH\n");
+#endif
+		INIT_LIST_HEAD(&short_task.list);
+		short_task.sync = 0;
+		short_task.routine = (void *) bottom_half_interrupt;
+		queue_task (&short_task, &tq_immediate);
+		mark_bh (IMMEDIATE_BH);
+	}
+	return;
+}
 
-        /* get data length:    */
-        iucv_data_len= iucv_data_len - iucv_next;
-	
-#ifdef DEBUG
-        printk(  "iucv: iucv_receive: len is %02X, last: %02X\n",
-		 iucv_data_len,iucv_next);
-#endif
-        /* transmit upstairs */
-        iucv_rx(dev,(iucv_data_len),rcvptr);
-	
-#ifdef DEBUG
-        printk(  "iucv: transaction complete now.\n");
-#endif
-        iucv_next = *((unsigned short*)rcvptr);
-        rcvptr = rcvptr + iucv_data_len;
-        /* get next packet offset */  
-        iucv_data_len= *((unsigned short*)rcvptr);
-	
-      } while (iucv_data_len != 0);
-      netif_start_queue(dev);                 /* transmission is no longer busy*/
-      break;
-      
-    default:
-      printk(  "unknown iucv interrupt \n");
-      break;
-      
-    } /* end switch */
-  netif_exit_interrupt(dev);              /* release lock*/
-  
-#ifdef DEBUG
-  printk(  "iucv: leaving do_iucv_interrupt.\n");
+/*******************************************************************/
+/* Name: bottom_half_interrupt                                     */
+/* Purpose: Handle interrupt at a more safer time                  */
+/* Input: void                                                     */
+/* Output: void                                                    */
+/*******************************************************************/
+void
+bottom_half_interrupt (void)
+{
+	iucv_packet *iucv_packet_list;
+	iucv_packet *tmp;
+	ulong flags;
+
+	atomic_set (&bh_scheduled, 0);
+	spin_lock_irqsave (&iucv_packets_lock, flags);
+	iucv_packet_list = iucv_packets_head;
+	iucv_packets_head = iucv_packets_tail = NULL;
+	spin_unlock_irqrestore (&iucv_packets_lock, flags);
+
+	/* now process all the request in the iucv_packet_list */
+#ifdef DEBUG3
+	printk (KERN_EMERG "BH: Process all packets\n");
+#endif
+	while (iucv_packet_list != NULL) {
+#ifdef DEBUG3
+		printk( KERN_EMERG "BH:>  %08x\n", 
+			*(int *)(iucv_packet_list->data+4));
+#endif
+		do_int ((iucv_ConnectionPending *) iucv_packet_list->data);
+#ifdef DEBUG3
+		printk( KERN_EMERG "BH:<  %08x\n",
+			*(int *)(iucv_packet_list->data+4));
+#endif
+		tmp = iucv_packet_list;
+		iucv_packet_list = iucv_packet_list->next;
+		kfree (tmp);
+	}
+#ifdef DEBUG3
+	printk (KERN_EMERG "BH: Done\n");
 #endif
-  
-}  /* end    do_iucv_interrupt()  */
-
-
-
-/*-------------------------------------------*/
-/*   Transmit a packet (low level interface) */
-/*-------------------------------------------*/
-int iucv_hw_tx(char *send_buf, int len,net_device *dev)
-{
-  /* This function deals with hw details.                         */
-  /* This interface strips off the ethernet header details.       */
-  /* In other words, this function implements the iucv behaviour,*/
-  /* while all other procedures are rather device-independent     */
-  struct iucv_priv *privptr;
-  int rc, recv_len=2000;
-  
-  privptr = (struct iucv_priv *)(dev->priv);
-  
-#ifdef DEBUG
-  printk(  "iucv: iucv_hw_tx, device %s\n",dev->name);
-  printk(  "iucv: hw_TX_data len: %X\n",len);
-  dumpit(send_buf,len);
+	return;
+}
+/*******************************************************************/
+/* Name: do_int                                                    */
+/* Purpose: Handle interrupt in a more safe environment            */
+/* Inuput: int_buf - pointer to copy of external interrupt buffer  */
+/* Output: void                                                    */
+/*******************************************************************/
+void
+do_int (iucv_ConnectionPending * int_buf)
+{
+	ulong index1 = 0, index2 = 0;
+	handler_table_entry *P = 0;	/* P is a pointer */
+	handler *Q = 0, *R;	/* Q and R are pointers */
+	iucv_interrupt_ops_t *interrupt = 0;	/* interrupt addresses */
+	uchar temp_buff1[24], temp_buff2[24];	/* masked handler id. */
+	int add_pathid_result = 0, j = 0;
+	uchar no_listener[16] = "NO LISTENER";
+#ifdef DEBUG
+	int i;
+	uchar *prt_parm;
+#endif
+#ifdef DEBUG3
+	printk (KERN_DEBUG "BH:-  Entered do_int "
+	                   "pathid %d, type %02X\n",
+		int_buf->ippathid, int_buf->iptype);
+#endif
+#ifdef DEBUG
+	prt_parm = (uchar *) (int_buf);
+	printk (KERN_DEBUG "External Interrupt Buffer\n");
+	for (i = 0; i < 40; i++)
+		printk (KERN_DEBUG "%02x ", prt_parm[i]);
+	printk (KERN_DEBUG "\n");
+#endif
+	ASCEBC (no_listener, 16);
+	if (int_buf->iptype != 01) {
+		index1 = ((ulong) (int_buf->ippathid)) / 512;
+		index2 = ((ulong) (int_buf->ippathid)) % 512;
+		spin_lock (&lock);
+
+		P = main_table[index1];
+		Q = (P + index2)->addrs;
+		interrupt = Q->interrupt_table;	/* interrupt functions */
+		spin_unlock (&lock);
+#ifdef DEBUG
+		printk (KERN_DEBUG "Handler is: \n");
+		prt_parm = (uchar *) Q;
+		for (i = 0; i < sizeof (handler); i++)
+			printk (KERN_DEBUG " %02x ", prt_parm[i]);
+		printk (KERN_DEBUG "\n");
+#endif
+	}			/* end of if statement */
+	switch (int_buf->iptype) {
+	case 0x01:		/* connection pending */
+		spin_lock (&lock);
+		for (R = handler_anchor; R != NULL; R = (handler *) R->next) {
+			memcpy (temp_buff1, &(int_buf->ipvmid), 24);
+			memcpy (temp_buff2, &(R->vmid), 24);
+			for (j = 0; j < 24; j++) {
+				temp_buff1[j] = (temp_buff1[j]) & (R->mask)[j];
+				temp_buff2[j] = (temp_buff2[j]) & (R->mask)[j];
+			}
+#ifdef DEBUG
+			for (i = 0; i < sizeof (temp_buff1); i++)
+				printk (KERN_DEBUG " %c ", temp_buff1[i]);
+			printk (KERN_DEBUG "\n");
+			for (i = 0; i < sizeof (temp_buff2); i++)
+				printk (KERN_DEBUG " %c ", temp_buff2[i]);
+			printk (KERN_DEBUG "\n");
+#endif
+			if (memcmp((void *) temp_buff1,
+				   (void *) temp_buff2, 24) == 0) {
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"found a matching handler\n");
+#endif
+				break;
+			}
+		}
+		spin_unlock (&lock);
+		if (R) {
+			/* ADD PATH TO PATHID TABLE */
+			add_pathid_result =
+			    add_pathid (int_buf->ippathid, R, R->pgm_data);
+			if (add_pathid_result == NULL) {
+				interrupt = R->interrupt_table;
+				if ((*interrupt).ConnectionPending) {
+					EBCASC (int_buf->ipvmid, 8);
+					
+					    ((*interrupt).
+					 ConnectionPending) (int_buf,
+							     R->pgm_data);
+				} else {
+					iucv_sever (int_buf->ippathid,
+						    no_listener);
+				}
+			} /* end if if(add_p...... */
+			else {
+				iucv_sever (int_buf->ippathid, no_listener);
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"add_pathid failed with rc = %d\n",
+					(int) add_pathid_result);
+#endif
+			}
+		} else
+			iucv_sever (int_buf->ippathid, no_listener);
+		break;
+	case 0x02:		/*connection complete */
+		if (Q) {
+			if ((*interrupt).ConnectionComplete)
+				((*interrupt).ConnectionComplete)
+				    
+				    ((iucv_ConnectionComplete *) int_buf,
+				     (P + index2)->pgm_data);
+			else {
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"ConnectionComplete not called\n");
+				printk (KERN_DEBUG "routine@ is %p\n",
+					(*interrupt).ConnectionComplete);
 #endif
-  
-  /* I am paranoid. Ain't I? */
-  if (len < sizeof(struct iphdr))
-    {
-      printk(  "iucv: Hmm... packet too short (%i octets)\n",len);
-      return -EINVAL;
-    }
-  
-  /*
-   * build IUCV header (preceeding halfword offset)   
-   * works as follows: Each packet is preceded by the 
-   * halfword offset to the next one. 
-   * The last packet is followed by an offset of zero.
-   * E.g., AL2(12),10-byte packet, AL2(34), 32-byte packet, AL2(0)
-   */
-  
-  memcpy(&privptr->send_buffer[2],send_buf,len+2);
-  privptr->send_buffer[len+2] = 0;
-  privptr->send_buffer[len+3] = 0;
-  *((unsigned short*) &privptr->send_buffer[0]) = len + 2;
-  
-#ifdef DEBUG
-  printk(  "iucv: iucv_hw_tx, device %s\n",dev->name);
-  printk(  "iucv: send len: %X\n",len+4);
-  dumpit(privptr->send_buffer,len+4);
+			}
+		}
+		break;
+	case 0x03:		/* connection severed */
+		if (Q) {
+			if ((*interrupt).ConnectionSevered)
+				((*interrupt).ConnectionSevered)
+				    
+				    ((iucv_ConnectionSevered *) int_buf,
+				     (P + index2)->pgm_data);
+			else
+				iucv_sever (int_buf->ippathid, no_listener);
+		} else
+			iucv_sever (int_buf->ippathid, no_listener);
+		break;
+	case 0x04:		/* connection quiesced */
+		if (Q) {
+			if ((*interrupt).ConnectionQuiesced)
+				((*interrupt).ConnectionQuiesced)
+				    
+				    ((iucv_ConnectionQuiesced *) int_buf,
+				     (P + index2)->pgm_data);
+			else {
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"ConnectionQuiesced not called\n");
+				printk (KERN_DEBUG "routine@ is %p\n",
+					(*interrupt).ConnectionQuiesced);
 #endif
-  *((unsigned short*) &privptr->send_buffer[0]) = len + 2;
-  
-  /* Ok, now the packet is ready for transmission: send it. */
-  if ((rc = iucv_send(privptr->command_buffer,
-		      privptr->pathid,
-		      &privptr->send_buffer[0],len+4,
-		      privptr->recv_buf,recv_len))!=0) {
-    printk(  "iucv: send_iucv failed, rc: %X\n",rc);
-    iucv_retrieve_buffer(privptr->command_buffer);
-  }
-#ifdef DEBUG
-  printk(  "iucv: send_iucv ended, rc: %X\n",rc);
+			}
+		}
+		break;
+	case 0x05:		/* connection resumed */
+		if (Q) {
+			if ((*interrupt).ConnectionResumed)
+				((*interrupt).ConnectionResumed)
+				    
+				    ((iucv_ConnectionResumed *) int_buf,
+				     (P + index2)->pgm_data);
+			else {
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"ConnectionResumed not called\n");
+				printk (KERN_DEBUG "routine@ is %p\n",
+					(*interrupt).ConnectionResumed);
 #endif
-  return rc;
-} /* end   iucv_hw_tx()  */
-
-
-
-
-
-
-/*------------------------------------------*/
-/* Transmit a packet (called by the kernel) */
-/*------------------------------------------*/
-int iucv_tx(struct sk_buff *skb, net_device *dev)
-{
-    int retval=0;
-
-    struct iucv_priv *privptr;
-
-    if (dev == NULL)
-    {
-      printk("iucv: NULL dev passed\n");
-      return 0;
-    }
-
-    privptr = (struct iucv_priv *) (dev->priv);
-
-    if (skb == NULL)
-    {
-      printk("iucv: %s: NULL buffer passed\n", dev->name);
-      privptr->stats.tx_errors++;
-      return 0;
-    }
-
-#ifdef DEBUG
-    printk(  "iucv: enter iucv_tx, using %s\n",dev->name);
+			}
+		}
+		break;
+	case 0x06:		/* priority message complete */
+	case 0x07:		/* nonpriority message complete */
+		if (Q) {
+			if ((*interrupt).MessageComplete)
+				((*interrupt).MessageComplete)
+				    
+				    ((iucv_MessageComplete *) int_buf,
+				     (P + index2)->pgm_data);
+			else {
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"MessageComplete not called\n");
+				printk (KERN_DEBUG "routine@ is %p\n",
+					(*interrupt).MessageComplete);
 #endif
-
-    if (netif_is_busy(dev))                        /* shouldn't happen */
-    {
-      privptr->stats.tx_errors++;
-      dev_kfree_skb(skb);
-      printk("iucv: %s: transmit access conflict ! leaving iucv_tx.\n", dev->name);
-    }
-
-    netif_stop_queue(dev);                                   /* transmission is busy*/
-    dev->trans_start = jiffies;                       /* save the timestamp*/
-
-    /* actual deliver of data is device-specific, and not shown here */
-    retval = iucv_hw_tx(skb->data, skb->len, dev);
-
-    dev_kfree_skb(skb);                               /* release it*/
-
-#ifdef DEBUG
-    printk(  "iucv:leaving iucv_tx, device %s\n",dev->name);
+			}
+		}
+		break;
+	case 0x08:		/* priority message pending  */
+	case 0x09:		/* nonpriority message pending  */
+		if (Q) {
+			if ((*interrupt).MessagePending)
+				((*interrupt).MessagePending)
+				    
+				    ((iucv_MessagePending *) int_buf,
+				     (P + index2)->pgm_data);
+			else {
+#ifdef DEBUG
+				printk (KERN_DEBUG
+					"MessagePending not called\n");
+				printk (KERN_DEBUG "routine@ is %p\n",
+					(*interrupt).MessagePending);
 #endif
-
-    return retval;              /* zero == done; nonzero == fail*/
-}   /* end  iucv_tx( struct sk_buff *skb, struct device *dev)  */
-
-
-
-
-
-
-/*---------------*/
-/* iucv_release */
-/*---------------*/
-int iucv_release(net_device *dev)
-{
-    int rc =0;
-    struct iucv_priv *privptr;
-    privptr = (struct iucv_priv *) (dev->priv);
-
-    netif_stop(dev);
-    netif_stop_queue(dev);           /* can't transmit any more*/
-    rc = iucv_sever(privptr->command_buffer);
-    if (rc!=0)
-    {
-       printk("iucv: %s: iucv_release pending...rc:%02x\n",dev->name,rc);
-    }
-
+			}
+		}
+		break;
+	default:		/* unknown iucv type */
+		printk (KERN_DEBUG "unknown iucv interrupt \n");
+		break;
+	}			/* end switch */
+#ifdef DEBUG3
+	printk (KERN_DEBUG "BH:-  Exiting do_int "
+	                   "pathid %d, type %02X\n",
+		int_buf->ippathid, int_buf->iptype);
+#endif
+	return;
+}				/* end of function call */
+
+/**************************************************************/
+/* Name: iucv_register_program                                */
+/* Purpose: registers a new handler                           */
+/* Input: pgmname- uchar[16], user id                         */
+/*        userid - uchar[8], machine id                       */
+/*        prmmask- mask                                       */
+/*        ops    - pointer to iucv_interrupt_ops buffer       */
+/* Output: new_handler - address of new handler               */
+/**************************************************************/
+iucv_handle_t
+iucv_register_program (uchar pgmname[16],
+		       uchar userid[8],
+		       uchar pgmmask[24],
+		       iucv_interrupt_ops_t * ops, ulong pgm_data)
+{
+	int rc;
+	handler *new_handler = 0;
+#ifdef DEBUG
+	int i;
+	uchar *prt_parm;
+	printk (KERN_DEBUG "enter iucv_register_program\n");
+#endif
+	my_ops = *ops;
+	/* Allocate handler table */
+	new_handler = (handler *) kmalloc (sizeof (handler), GFP_KERNEL);
+	if (new_handler == NULL) {
 #ifdef DEBUG
-      printk("iucv: iucv_sever ended with rc: %X\n",rc);
+		printk (KERN_DEBUG
+			"IUCV: returned NULL address for new handle \n");
 #endif
-
-    return rc;
-} /* end  iucv_release() */
-
-
-
-
-
-/*-----------------------------------------------*/
-/* Configuration changes (passed on by ifconfig) */
-/*-----------------------------------------------*/
-int iucv_config(net_device *dev, struct ifmap *map)
-{
-   if (dev->flags & IFF_UP)        /* can't act on a running interface*/
-        return -EBUSY;
-
-   /* ignore other fields */
-   return 0;
-}
-/*  end  iucv_config()  */
-
-
-
-
-
-/*----------------*/
-/* Ioctl commands */
-/*----------------*/
-int iucv_ioctl(net_device *dev, struct ifreq *rq, int cmd)
-{
-#ifdef DEBUG
-    printk(  "iucv: device %s; iucv_ioctl\n",dev->name);
+		return NULL;
+	}
+	/* fill in handler table */
+	memcpy (new_handler->user_data, pgmname, 16);
+	memcpy (new_handler->vmid, userid, 8);
+	memcpy (new_handler->mask, pgmmask, 24);
+	new_handler->pgm_data = pgm_data;
+	/* Convert from ASCII to EBCDIC */
+	if (new_handler->vmid) {
+		ASCEBC (new_handler->vmid, 8);
+		EBC_TOUPPER(new_handler->vmid, 8);
+	}
+	/* fill in handler table */
+	new_handler->interrupt_table = ops;
+	new_handler->size = ADDED_STOR;
+	/* Allocate storage for pathid table */
+	new_handler->start = kmalloc (ADDED_STOR * sizeof (ulong), GFP_KERNEL);
+	if (new_handler->start == NULL) {
+#ifdef DEBUG
+		printk (KERN_DEBUG
+			"IUCV: returned NULL address for pathid table,"
+			" exiting\n");
 #endif
-    return 0;
-}
-
-/*---------------------------------*/
-/* Return statistics to the caller */
-/*---------------------------------*/
-struct net_device_stats *iucv_stats(net_device *dev)
-{
-    struct iucv_priv *priv = (struct iucv_priv *)dev->priv;
-#ifdef DEBUG
-    printk(  "iucv: device %s; iucv_stats\n",dev->name);
+		kfree(new_handler);
+		return NULL;
+	}
+	memset (new_handler->start, 0, ADDED_STOR * sizeof (ulong));
+	new_handler->end = (*new_handler).start + ADDED_STOR;
+	new_handler->next = 0;
+	new_handler->prev = 0;
+	/* Place handler at beginning of chain */
+	spin_lock (&lock);
+	if (handler_anchor == NULL)
+		handler_anchor = new_handler;
+	else {
+		handler_anchor->prev = (ulong *) new_handler;
+		new_handler->next = (ulong *) handler_anchor;
+		handler_anchor = new_handler;
+#ifdef DEBUG
+		printk (KERN_DEBUG "adding a another handler to list\n");
+		printk (KERN_DEBUG "handler_anchor->prev is %p \n",
+			handler_anchor->prev);
+		printk (KERN_DEBUG "new_handler->next is %p \n",
+			new_handler->next);
+		printk (KERN_DEBUG "handler_anchor is %p \n", handler_anchor);
 #endif
-    return &priv->stats;
-}
-
-
-/*
- * iucv_change_mtu     
- * IUCV can handle MTU sizes from 576 to approx. 32000    
- */
-
-static int iucv_change_mtu(net_device *dev, int new_mtu)
-{
+	}
+	spin_unlock (&lock);
+	if (declare_flag == NULL) {
+		rc = iucv_declare_buffer (iucv_external_int_buffer);
+		if (rc == 0) {
+			declare_flag = 1;
+			/* request the 0x4000 external interrupt */
+			rc =
+			    register_external_interrupt (0x4000,
+							 top_half_interrupt);
+		} else {
+			panic ("Registration failed");
 #ifdef DEBUG
-    printk(  "iucv: device %s; iucv_change_mtu\n",dev->name);
+			printk (KERN_DEBUG "rc from declare buffer is: %i\n",
+				rc);
 #endif
-       if ((new_mtu < 64) || (new_mtu > 32000))
-	 return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-
-
-
-/*--------------------------------------------*/
-/* The init function (sometimes called probe).*/
-/* It is invoked by register_netdev()         */
-/*--------------------------------------------*/
-int iucv_init(net_device *dev)
-{
-    int rc;
-    struct iucv_priv *privptr;
-
+		}
+	}
 #ifdef DEBUG
-    printk(  "iucv: iucv_init, device: %s\n",dev->name);
-#endif
-
-    dev->open            = iucv_open;
-    dev->stop            = iucv_release;
-    dev->set_config      = iucv_config;
-    dev->hard_start_xmit = iucv_tx;
-    dev->do_ioctl        = iucv_ioctl;
-    dev->get_stats       = iucv_stats;
-    dev->change_mtu      = iucv_change_mtu;
-
-    /* keep the default flags, just add NOARP */
-
-    dev->hard_header_len = 0;
-    dev->addr_len        = 0;
-    dev->type            = ARPHRD_SLIP;
-    dev->tx_queue_len    = 100;
-    dev->flags           = IFF_NOARP|IFF_POINTOPOINT;
-    dev->mtu    = 4092;
-
-    dev_init_buffers(dev);
-
-    /* Then, allocate the priv field. This encloses the statistics */
-    /* and a few private fields.*/
-    dev->priv = kmalloc(sizeof(struct iucv_priv), GFP_KERNEL);
-    if (dev->priv == NULL){
-       printk(  "iucv: no memory for dev->priv.\n");
-       return -ENOMEM;
-    }
-    memset(dev->priv, 0, sizeof(struct iucv_priv));
-    privptr = (struct iucv_priv *)(dev->priv);
-
-
-    privptr->send_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8);
-    if (privptr->send_buffer == NULL) {
-      printk(KERN_INFO "%s: could not get pages for send buffer\n",
-	     dev->name);
-      return -ENOMEM;
-    }
-    memset(privptr->send_buffer, 0, 8*PAGE_SIZE);
-    privptr->send_buffer_len=8*PAGE_SIZE;
-    
-    privptr->receive_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8);
-    if (privptr->receive_buffer == NULL) {
-      printk(KERN_INFO "%s: could not get pages for receive buffer\n",
-	     dev->name);
-      return -ENOMEM;
-    }
-    memset(privptr->receive_buffer, 0, 8*PAGE_SIZE);
-    privptr->receive_buffer_len=8*PAGE_SIZE;
-
-    /* now use the private fields ... */
-    /* init pathid                    */
-    privptr->pathid = -1;
-
-    /* init private userid from global userid */
-    memcpy(privptr->userid,iucv_userid[dev-iucv_devs],8);
-
-
-    /* we can use only ONE buffer for external interrupt ! */
-    rc=iucv_declare_buffer(privptr->command_buffer,
-                           (DCLBFR_T *)iucv_ext_int_buffer);
-    if (rc!=0 && rc!=19)   /* ignore existing buffer */
-      {
-         printk(  "iucv:iucv_declare failed, rc: %X\n",rc);
-         return -ENODEV;
-      }
-
-    rc = iucv_enable(privptr->command_buffer);
-    if (rc!=0)
-    {
-            printk(  "iucv:iucv_enable failed, rc: %x\n",rc);
-            iucv_retrieve_buffer(privptr->command_buffer);
-            return -ENODEV;
-    }
+	printk (KERN_DEBUG "address of handle is %p ", new_handler);
+	printk (KERN_DEBUG "size of handle is %d ", (int) (sizeof (handler)));
+	printk (KERN_DEBUG "exit iucv_register_program\n");
+	printk (KERN_DEBUG "main_table is %p \n", main_table);
+	printk (KERN_DEBUG "handler_anchor is %p \n", handler_anchor);
+	printk (KERN_DEBUG "Handler is: \n");
+	prt_parm = (uchar *) new_handler;
+	for (i = 0; i < sizeof (handler); i++)
+		printk (KERN_DEBUG " %02x ", prt_parm[i]);
+	printk (KERN_DEBUG "\n");
+#endif
+	return new_handler;	/* send buffer address back */
+}				/* end of register function */
+
+/**************************************************************/
+/* Name: iucv_unregister                                      */
+/* Purpose: remove handler from chain and sever all paths     */
+/* Input: handle - address of handler to be severed           */
+/* Output: returns 0                                          */
+/**************************************************************/
+int
+iucv_unregister (iucv_handle_t handle)
+{
+	handler *temp_next = 0, *temp_prev = 0;
+	handler *Q = 0, *R;
+	handler_table_entry *H_T_E = 0;
+	ulong *S = 0;		/*points to the beginning of block of h_t_e's*/
+#ifdef DEBUG
+	printk (KERN_DEBUG "enter iucv_unregister\n");
+	printk (KERN_DEBUG "address of handle is %p ", handle);
+	printk (KERN_DEBUG "size of handle is %u ", (int) (sizeof (handle)));
+#endif
+	spin_lock (&lock);
+	Q = (handler *) handle;
+	/*
+	 * Checking if handle is still registered: if yes, continue
+	 *  if not registered, return.
+	 */
+	for (R = handler_anchor; R != NULL; R = (handler *) R->next)
+		if (Q == R) {
+#ifdef DEBUG
+			printk (KERN_DEBUG "found a matching handler\n");
+#endif
+			break;
+		}
+	if (!R) {
+		spin_unlock (&lock);
+		return (0);
+	}
+	S = Q->start;
 #ifdef DEBUG
-    printk(  "iucv: iucv_init endend OK for device %s.\n",dev->name);
+	printk (KERN_DEBUG "Q is handle? %p ", Q);
+	printk (KERN_DEBUG "Q->start is %p ", Q->start);
+	printk (KERN_DEBUG "&(Q->start) is %p ", &(Q->start));
+	printk (KERN_DEBUG "Q->end is %p ", Q->end);
+	printk (KERN_DEBUG "&(Q->end) is %p ", &(Q->end));
+#endif
+	while (S < (Q->end)) {	/* index thru table */
+		if (*S) {
+			H_T_E = (handler_table_entry *) (*S);
+#ifdef DEBUG
+			printk (KERN_DEBUG "Pointer to H_T_E is %p ", H_T_E);
+			printk (KERN_DEBUG "Address of handle in H_T_E is %p",
+				(H_T_E->addrs));
+#endif
+			if ((H_T_E->addrs) != handle) {
+				spin_unlock (&lock);
+				return (-2);	/*handler addresses don't match */
+			} else {
+				spin_unlock (&lock);
+				iucv_sever (H_T_E->pathid, Q->user_data);
+				spin_lock (&lock);
+			}
+		}
+		S++;		/* index by size of ulong */
+	}
+	kfree (Q->start);
+	temp_next = (handler *) Q->next;	/* address of next handler on list */
+	temp_prev = (handler *) Q->prev;	/* address of prev handler on list */
+	if ((temp_next != NULL) & (temp_prev != NULL)) {
+		(*temp_next).prev = (ulong *) temp_prev;
+		(*temp_prev).next = (ulong *) temp_next;
+	} else if ((temp_next != NULL) & (temp_prev == NULL)) {
+		(*temp_next).prev = NULL;
+		handler_anchor = temp_next;
+	} else if ((temp_next == NULL) & (temp_prev != NULL))
+		(*temp_prev).next = NULL;
+	else
+		handler_anchor = NULL;
+	if (handler_anchor == NULL)
+		iucv_retrieve_buffer ();
+	kfree (handle);
+	spin_unlock (&lock);
+#ifdef DEBUG
+	printk (KERN_DEBUG "exit iucv_unregister\n");
+#endif
+	return 0;
+}
+
+#ifdef CONFIG_MODULES
+EXPORT_SYMBOL (iucv_accept);
+EXPORT_SYMBOL (iucv_connect);
+EXPORT_SYMBOL (iucv_purge);
+EXPORT_SYMBOL (iucv_query);
+EXPORT_SYMBOL (iucv_quiesce);
+EXPORT_SYMBOL (iucv_receive);
+EXPORT_SYMBOL (iucv_receive_simple);
+EXPORT_SYMBOL (iucv_receive_array);
+EXPORT_SYMBOL (iucv_reject);
+EXPORT_SYMBOL (iucv_reply);
+EXPORT_SYMBOL (iucv_reply_array);
+EXPORT_SYMBOL (iucv_reply_prmmsg);
+EXPORT_SYMBOL (iucv_resume);
+EXPORT_SYMBOL (iucv_send);
+EXPORT_SYMBOL (iucv_send2way);
+EXPORT_SYMBOL (iucv_send2way_array);
+EXPORT_SYMBOL (iucv_send_array);
+EXPORT_SYMBOL (iucv_send2way_prmmsg);
+EXPORT_SYMBOL (iucv_send2way_prmmsg_array);
+EXPORT_SYMBOL (iucv_send_prmmsg);
+EXPORT_SYMBOL (iucv_setmask);
+EXPORT_SYMBOL (iucv_sever);
+EXPORT_SYMBOL (iucv_register_program);
+EXPORT_SYMBOL (iucv_unregister);
 #endif
-    return 0;
-}
-
-
-/*
- * setup iucv devices
- * 
- * string passed: iucv=userid1,...,useridn 
- */
-#if LINUX_VERSION_CODE>=0x020300
-static int  __init iucv_setup(char *str)
-#else
-__initfunc(void iucv_setup(char *str,int *ints))
-#endif
-{
-    int result=0, i=0,j=0, k=0, device_present=0;
-    char *s = str;
-    net_device * dev ={0};
-
-#ifdef DEBUG
-    printk(  "iucv: start registering device(s)... \n");
-#endif
-
-    /*
-     * scan device userids
-     */
-
-    while(*s != 0x20 && *s != '\0'){
-       if(*s == ','){
-          /* fill userid up to 8 chars */
-          for(k=i;k<8;k++){
-             iucv_userid[j][k] = 0x40;
-          } /* end for */
-          /* new device  */
-          j++;
-          s++; /* ignore current char */
-          i=0;
-          if (j>MAX_DEVICES) {
-             printk("iucv: setup devices: max devices %d reached.\n",
-		    MAX_DEVICES);
-             break;
-          } /* end if */
-          continue;
-       } /* end if */
-       iucv_ascii_userid[j][i] = (int)*s;
-       iucv_userid[j][i] = _ascebc[(int)*s++];
-       i++;
-    } /* end while */
-
-    /* 
-     * fill last userid up to 8 chars
-     */
-    for(k=i;k<8;k++) {
-      iucv_userid[j][k] = 0x40;
-    }
-
-    /*
-     * set device name and register
-     */
-
-    for (k=0;k<=j;k++) {
-      memcpy(iucv_devs[k].name, "iucv0", 4);
-      dev = &iucv_devs[k];
-      dev->name[4] = k + '0';
-
-#ifdef DEBUGX
-      printk("iucv: (ASCII- )Userid:%s\n",&iucv_ascii_userid[k][0]);
-      printk("iucv: (ASCII-)Userid: ");
-      for (i=0;i<8;i++) {
-        printk(  "%02X ",(int)iucv_ascii_userid[k][i]);
-      }
-      printk("\n");
-      printk("iucv: (EBCDIC-)Userid: ");
-      for (i=0;i<8;i++) {
-         printk(  "%02X ",(int)iucv_userid[k][i]);
-      }
-      printk("\n");
-      printk("iucv: device name :%s\n",iucv_devs[k].name);
-#endif
-
-      if ( (result = register_netdev(iucv_devs + k)) )
-          printk("iucv: error %i registering device \"%s\"\n",
-                 result, iucv_devs[k].name);
-      else
-      {
-              device_present++;
-      }
-    } /* end for */
-
-#ifdef DEBUG
-    printk(  "iucv: end register devices, %d devices present\n",device_present);
-#endif
-    /* return device_present ? 0 : -ENODEV; */
-#if LINUX_VERSION_CODE>=0x020300
-    return 1;
-#else
-    return;
-#endif
-}
-
-#if LINUX_VERSION_CODE>=0x020300
-__setup("iucv=", iucv_setup);
-#endif
-
-
-/*-------------*/
-/* The devices */
-/*-------------*/
-char iucv_names[MAX_DEVICES*8]; /* MAX_DEVICES eight-byte buffers */
-net_device iucv_devs[MAX_DEVICES] = {
-    {
-        iucv_names, /* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+8,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+16,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+24,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+32,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+40,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+48,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+56,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+64,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    },
-    {
-        iucv_names+72,/* name -- set at load time */
-        0, 0, 0, 0,  /* shmem addresses */
-        0x000,       /* ioport */
-        0,           /* irq line */
-        0, 0, 0,     /* various flags: init to 0 */
-        NULL,        /* next ptr */
-        iucv_init,  /* init function, fill other fields with NULL's */
-    }
-};
 
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/iucv.h linux/drivers/s390/net/iucv.h
--- v2.4.1/linux/drivers/s390/net/iucv.h	Fri May 12 11:41:44 2000
+++ linux/drivers/s390/net/iucv.h	Tue Feb 13 14:13:44 2001
@@ -1,146 +1,353 @@
 /*
- *  drivers/s390/net/iucv.h
- *    Network driver for VM using iucv
+ *  drivers/s390/net/netiucv.h
+ *    IUCV base support.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Stefan Hegewald <hegewald@de.ibm.com>
- *               Hartmut Penner <hpenner@de.ibm.com> 
+ *    Copyright (C) 2000 IBM Corporation
+ *    Author(s): Xenia Tkatschow (xenia@us.ibm.com)
+ *
+ *
+ * Functionality:
+ * To explore any of the IUCV functions, one must first register
+ * their program using iucv_register(). Once your program has
+ * successfully completed a register, it can use the other functions.
+ * For furthur reference on all IUCV functionality, refer to the
+ * CP Programming Services book, also available on the web
+ * thru www.ibm.com/s390/vm.
  */
-
 #ifndef _IUCV_H
 #define _IUCV_H
+#define uchar  unsigned char
+#define ushort unsigned short
+#define ulong  unsigned long
+#define iucv_handle_t void *
+/***********************FLAGS*************************************/
+#define  source_class   0x01
+#define  target_class   0x01
+#define  local_conn     0x01
+#define  specify_pathid 0x02
+#define  specify_msgid  0x04
+#define  reply_array    0x08
+#define  one_way_msg    0x10
+#define  prior_msg      0x20
+#define  array          0x40
+#define  quiesce_msg    0x40
+#define  parm_data      0x80
+#define  IPRMDATA	 0x80
+#define  IPBUFLST	 0x40
+#define  IPPRTY	 0x20
+#define  IPNORPY	 0x10
+#define  IPANSLST	 0x08
+#define  IPFGMID	 0x04
+#define  IPFGPID	 0x02
+#define  IPFGMCL	 0x01
+
+/*---------------------------------------------------------*/
+/* Mapping of external interrupt buffers                   */
+/* Names: iucv_ConnectionPending    ->  connection pending */
+/*        iucv_ConnectionComplete   ->  connection complete */
+/*        iucv_ConnectionSevered    ->  connection severed */
+/*        iucv_ConnectionQuiesced   ->  connection quiesced */
+/*        iucv_ConnectionResumed    ->  connection resumed */
+/*        iucv_MessagePending       ->  message pending    */
+/*        iucv_MessageComplete      ->  message complete   */
+/*---------------------------------------------------------*/
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iptype;
+	ushort ipmsglim;
+	ushort res1;
+	uchar ipvmid[8];
+	uchar ipuser[16];
+	ulong res3;
+	uchar ippollfg;
+	uchar res4[3];
+} iucv_ConnectionPending;
 
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iptype;
+	ushort ipmsglim;
+	ushort res1;
+	uchar res2[8];
+	uchar ipuser[16];
+	ulong res3;
+	uchar ippollfg;
+	uchar res4[3];
+} iucv_ConnectionComplete;
 
-#define UCHAR  unsigned char
-#define USHORT unsigned short
-#define ULONG  unsigned long
-
-#define DEFAULT_BUFFERSIZE  2048
-#define DEFAULT_FN_LENGTH   27
-#define TRANSFERLENGTH      10
-
-
-
-/* function ID's */
-#define RETRIEVE_BUFFER 2
-#define REPLY           3
-#define SEND            4
-#define RECEIVE         5
-#define ACCEPT          10
-#define CONNECT         11
-#define DECLARE_BUFFER  12
-#define SEVER           15
-#define SETMASK         16
-#define SETCMASK        17
-#define PURGE           9999
-
-/* structures */
-typedef struct {
-  USHORT res0;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  ULONG  res1;
-  ULONG  res2;
-  ULONG  ipbfadr1;
-  ULONG  res[6];
-} DCLBFR_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  USHORT ipmsglim;
-  USHORT res1;
-  UCHAR  ipvmid[8];
-  UCHAR  ipuser[16];
-  UCHAR  iptarget[8];
-} CONNECT_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  USHORT ipmsglim;
-  USHORT res1;
-  UCHAR  res2[8];
-  UCHAR  ipuser[16];
-  UCHAR  res3[8];
-} ACCEPT_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  ULONG  ipmsgid;
-  ULONG  iptrgcls;
-  ULONG  ipbfadr1;
-  ULONG  ipbfln1f;
-  ULONG  ipsrccls;
-  ULONG  ipmsgtag;
-  ULONG  ipbfadr2;
-  ULONG  ipbfln2f;
-  ULONG  res;
-} SEND_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  ULONG  ipmsgid;
-  ULONG  iptrgcls;
-  ULONG  iprmmsg1;
-  ULONG  iprmmsg2;
-  ULONG  res1[2];
-  ULONG  ipbfadr2;
-  ULONG  ipbfln2f;
-  ULONG  res2;
-} REPLY_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  ULONG  ipmsgid;
-  ULONG  iptrgcls;
-  ULONG  ipbfadr1;
-  ULONG  ipbfln1f;
-  ULONG  res1[3];
-  ULONG  ipbfln2f;
-  ULONG  res2;
-} RECEIVE_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iprcode;
-  ULONG  res1[3];
-  UCHAR  ipuser[16];
-  ULONG  res2[2];
-} SEVER_T;
-
-typedef struct {
-  UCHAR  ipmask;
-  UCHAR  res1[2];
-  UCHAR  iprcode;
-  ULONG  res2[9];
-} MASK_T;
-
-typedef struct {
-  USHORT ippathid;
-  UCHAR  ipflags1;
-  UCHAR  iptype;
-  ULONG  ipmsgid;
-  ULONG  ipaudit;
-  ULONG  iprmmsg1;
-  ULONG  iprmmsg2;
-  ULONG  ipsrccls;
-  ULONG  ipmsgtag;
-  ULONG  ipbfadr2;
-  ULONG  ipbfln2f;
-  UCHAR  ippollfg;
-  UCHAR  res2[3];
-} INTERRUPT_T;
+typedef struct {
+	ushort ippathid;
+	uchar res1;
+	uchar iptype;
+	ulong res2;
+	uchar res3[8];
+	uchar ipuser[16];
+	ulong res4;
+	uchar ippollfg;
+	uchar res5[3];
+} iucv_ConnectionSevered;
+
+typedef struct {
+	ushort ippathid;
+	uchar res1;
+	uchar iptype;
+	ulong res2;
+	uchar res3[8];
+	uchar ipuser[16];
+	ulong res4;
+	uchar ippollfg;
+	uchar res5[3];
+} iucv_ConnectionQuiesced;
 
+typedef struct {
+	ushort ippathid;
+	uchar res1;
+	uchar iptype;
+	ulong res2;
+	uchar res3[8];
+	uchar ipuser[16];
+	ulong res4;
+	uchar ippollfg;
+	uchar res5[3];
+} iucv_ConnectionResumed;
+
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iptype;
+	ulong ipmsgid;
+	ulong iptrgcls;
+	ulong iprmmsg1;
+	union u1 {
+		ulong ipbfln1f;
+		ulong iprmmsg2;
+	} ln1msg2;
+	ulong res1[3];
+	ulong ipbfln2f;
+	uchar ippollfg;
+	uchar res2[3];
+} iucv_MessagePending;
+
+typedef struct {
+	ushort ippathid;
+	uchar ipflags1;
+	uchar iptype;
+	ulong ipmsgid;
+	ulong ipaudit;
+	ulong iprmmsg1;
+	ulong iprmmsg2;
+	ulong ipsrccls;
+	ulong ipmsgtag;
+	ulong res;
+	ulong ipbfln2f;
+	uchar ippollfg;
+	uchar res2[3];
+} iucv_MessageComplete;
+
+/************************structures*************************/
+/*---------------------------------------------------------*/
+/*iucv_interrupt_ops_t: List of functions for interrupt    */
+/* handling.                                               */
+/*---------------------------------------------------------*/
+
+typedef struct {
+	void (*ConnectionPending) (iucv_ConnectionPending * eib,
+				   ulong pgm_data);
+	void (*ConnectionComplete) (iucv_ConnectionComplete * eib,
+				    ulong pgm_data);
+	void (*ConnectionSevered) (iucv_ConnectionSevered * eib,
+				   ulong pgm_data);
+	void (*ConnectionQuiesced) (iucv_ConnectionQuiesced * eib,
+				    ulong pgm_data);
+	void (*ConnectionResumed) (iucv_ConnectionResumed * eib,
+				   ulong pgm_data);
+	void (*MessagePending) (iucv_MessagePending * eib,
+				ulong pgm_data);
+	void (*MessageComplete) (iucv_MessageComplete * eib,
+				 ulong pgm_data);
+} iucv_interrupt_ops_t;
+
+/*---------------------------------------------------------*/
+/*iucv_array_t : Defines buffer array                      */
+/*---------------------------------------------------------*/
+
+typedef struct {
+	void *address;
+	int length;
+} iucv_array_t __attribute__ ((aligned (8)));
+
+/*************************-prototypes-******************************/
+
+iucv_handle_t iucv_register_program (uchar pgmname[16],
+				     uchar userid[8],
+				     uchar pgmmask[24],
+				     iucv_interrupt_ops_t * ops,
+				     ulong pgm_data);
+
+int iucv_unregister (iucv_handle_t handle);
+
+int iucv_purge (ulong msgid,
+		ushort pathid,
+		ulong srccls,
+		uchar audit[4]);
+
+void iucv_query (ulong * bufsize,
+		 ulong * conmax);
+
+int iucv_quiesce (ushort pathid,
+		  uchar user_data[16]);
+
+int iucv_resume (ushort pathid,
+		 uchar user_data[16]);
+
+int iucv_reject (ushort pathid,
+		 ulong msgid,
+		 ulong trgcls);
+
+int iucv_setmask (uchar non_priority_interrupts,
+		  uchar priority_interrupts,
+		  uchar non_priority_completion_interrupts,
+		  uchar priority_completion_interrupts);
+
+int iucv_connect (ushort * pathid,
+		  ushort msglim,
+		  uchar user_data[16],
+		  uchar userid[8],
+		  uchar system_name[8],
+		  uchar priority_requested,
+		  uchar prmdata,
+		  uchar quiesce,
+		  uchar control,
+		  uchar local,
+		  uchar * priority_permitted,
+		  iucv_handle_t handle,
+		  ulong pgm_data);
+
+int iucv_accept (ushort pathid,
+		 ushort msglim,
+		 uchar user_data[16],
+		 uchar priority_requested,
+		 uchar prmdata,
+		 uchar quiesce,
+		 uchar control,
+		 uchar * priority_permitted,
+		 iucv_handle_t handle,
+		 ulong pgm_data);
+
+int iucv_sever (ushort pathid,
+		uchar user_data[16]);
+
+int iucv_receive (ushort pathid,
+		  ulong * msgid,
+		  ulong * trgcls,
+		  void *buffer, ulong buflen,
+		  uchar * reply_required,
+		  uchar * priority_msg,
+		  ulong * adds_curr_buffer,
+		  ulong * adds_curr_length);
+
+int iucv_receive_simple (ushort pathid,
+			 ulong msgid,
+			 ulong trgcls,
+			 void *buffer, ulong buflen);
+
+int iucv_receive_array (ushort pathid,
+			ulong * msgid,
+			ulong * trgcls,
+			iucv_array_t * buffer,
+			ulong * buflen,
+			uchar * reply_required,
+			uchar * priority_msg,
+			ulong * adds_curr_buffer,
+			ulong * adds_curr_length);
+
+int iucv_send (ushort pathid,
+	       ulong * msgid,
+	       ulong trgcls,
+	       ulong srccls,
+	       ulong msgtag,
+	       uchar priority_msg,
+	       void *buffer,
+	       ulong buflen);
+
+int iucv_send_array (ushort pathid,
+		     ulong * msgid,
+		     ulong trgcls,
+		     ulong srccls,
+		     ulong msgtag,
+		     uchar priority_msg,
+		     iucv_array_t * buffer,
+		     ulong buflen);
+
+int iucv_send_prmmsg (ushort pathid,
+		      ulong * msgid,
+		      ulong trgcls,
+		      ulong srccls,
+		      ulong msgtag,
+		      uchar priority_msg,
+		      uchar prmmsg[8]);
+
+int iucv_send2way (ushort pathid,
+		   ulong * msgid,
+		   ulong trgcls,
+		   ulong srccls,
+		   ulong msgtag,
+		   uchar priority_msg,
+		   void *buffer,
+		   ulong buflen,
+		   void *ansbuf,
+		   ulong anslen);
+
+int iucv_send2way_array (ushort pathid,
+			 ulong * msgid,
+			 ulong trgcls,
+			 ulong srccls,
+			 ulong msgtag,
+			 uchar priority_msg,
+			 iucv_array_t * buffer,
+			 ulong buflen,
+			 iucv_array_t * ansbuf,
+			 ulong anslen);
+
+int iucv_send2way_prmmsg (ushort pathid,
+			  ulong * msgid,
+			  ulong trgcls,
+			  ulong srccls,
+			  ulong msgtag,
+			  uchar priority_msg,
+			  uchar prmmsg[8],
+			  void *ansbuf,
+			  ulong anslen);
+
+int iucv_send2way_prmmsg_array (ushort pathid,
+				ulong * msgid,
+				ulong trgcls, ulong srccls,
+				ulong msgtag,
+				uchar priority_msg,
+				uchar prmmsg[8],
+				iucv_array_t * ansbuf,
+				ulong anslen);
+int iucv_reply (ushort pathid,
+		ulong msgid,
+		ulong trgcls,
+		uchar priority_msg,
+		void *buf,
+		ulong buflen);
+
+int iucv_reply_array (ushort pathid,
+		      ulong msgid,
+		      ulong trgcls,
+		      uchar priority_msg,
+		      iucv_array_t * buffer,
+		      ulong buflen);
+
+int iucv_reply_prmmsg (ushort pathid,
+		       ulong msgid,
+		       ulong trgcls,
+		       uchar priority_msg,
+		       uchar prmmsg[8]);
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/net/netiucv.c linux/drivers/s390/net/netiucv.c
--- v2.4.1/linux/drivers/s390/net/netiucv.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/net/netiucv.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,901 @@
+/*
+ *  drivers/s390/net/netiucv.c
+ *    Network driver for VM using iucv
+ *
+ *  S/390 version
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Stefan Hegewald <hegewald@de.ibm.com>
+ *               Hartmut Penner <hpenner@de.ibm.com>
+ *
+ *
+ *    2.3 Updates Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *                Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *    Re-write:   Alan Altmark (Alan_Altmark@us.ibm.com)  Sept. 2000
+ *                Uses iucv.c kernel module for IUCV services. 
+ *
+ * -------------------------------------------------------------------------- 
+ *  An IUCV frame consists of one or more packets preceded by a 16-bit
+ *  header.   The header contains the offset to the next packet header,
+ *  measured from the beginning of the _frame_.  If zero, there are no more
+ *  packets in the frame.  Consider a frame which contains a 10-byte packet
+ *  followed by a 20-byte packet:
+ *        +-----+----------------+-----+----------------------------+-----+
+ *        |h'12'| 10-byte packet |h'34'|  20-byte packet            |h'00'|
+ *        +-----+----------------+-----+----------------------------+-----+
+ * Offset: 0     2                12    14                           34  
+ *
+ *  This means that each header will always have a larger value than the
+ *  previous one (except for the final zero header, of course).
+ *  
+ *  For outbound packets, we send ONE frame per packet.  So, our frame is:
+ *       AL2(packet length+2), packet, AL2(0)
+ *  The maximum packet size is the MTU, so the maximum IUCV frame we send
+ *  is MTU+4 bytes.
+ *
+ *  For inbound frames, we don't care how long the frame is.  We tear apart
+ *  the frame, processing packets up to MTU size in length, until no more
+ *  packets remain in the frame.
+ *
+ * --------------------------------------------------------------------------
+ *  The code uses the 2.3.43 network driver interfaces.  If compiled on an
+ *  an older level of the kernel, the module provides its own macros.
+ *  Doc is in Linux Weekly News (lwn.net) memo from David Miller, 9 Feb 2000.
+ *  There are a few other places with 2.3-specific enhancements.
+ *
+ * --------------------------------------------------------------------------
+*/
+//#define DEBUG 1
+
+/* If MAX_DEVICES increased, add initialization data to iucv_netdev[] array */
+/* (See bottom of program.)						    */
+#define MAX_DEVICES 10		/* Allows "iucv0" to "iucv9"    */
+#define MAX_VM_MTU 32764	/* 32K IUCV buffer, minus 4     */
+#define MAX_TX_Q 50		/* Maximum pending TX           */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+MODULE_AUTHOR
+    ("(C) 2000 IBM Corporation by Alan Altmark (Alan_Altmark@us.ibm.com)");
+MODULE_DESCRIPTION ("Linux for S/390 IUCV network driver");
+MODULE_PARM (iucv, "1-" __MODULE_STRING (MAX_DEVICES) "s");
+MODULE_PARM_DESC (iucv,
+		  "Specify the userids associated with iucv0-iucv9:\n"
+		  "iucv=userid1,userid2,...,userid10\n");
+#ifdef MODVERSIONS
+#include <linux/modversions.h>
+#endif
+#else
+#define MOD_INC_USE_COUNT
+#define MOD_DEC_USE_COUNT
+#endif
+
+#include <linux/sched.h>	/* task queues                  */
+#include <linux/malloc.h>	/* kmalloc()                    */
+#include <linux/errno.h>	/* error codes                  */
+#include <linux/types.h>	/* size_t                       */
+#include <linux/interrupt.h>	/* mark_bh                      */
+#include <linux/netdevice.h>	/* struct net_device, etc.      */
+#include <linux/if_arp.h>	/* ARPHRD_SLIP                  */
+#include <linux/skbuff.h>	/* skb                          */
+#include <linux/init.h>		/* __setup()                    */
+#include <asm/io.h>		/* virt_to_phys()               */
+#include <asm/string.h>		/* memset, memcpy, etc.         */
+#include "iucv.h"
+#define min(a,b) (a < b) ? a : b
+
+#ifdef DEBUG
+#undef KERN_INFO
+#undef KERN_DEBUG
+#define KERN_INFO    KERN_EMERG
+#define KERN_DEBUG   KERN_EMERG
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
+typedef struct net_device net_device;
+#else
+typedef struct device net_device;
+#endif
+
+static __inline__ int
+netif_is_busy (net_device * dev)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,45))
+	return (dev->tbusy);
+#else
+	return (test_bit (__LINK_STATE_XOFF, &dev->flags));
+#endif
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,45))
+	/* Provide our own 2.3.45 interfaces */
+#define netif_enter_interrupt(dev) dev->interrupt=1
+#define netif_exit_interrupt(dev) dev->interrupt=0
+#define netif_start(dev) dev->start=1
+#define netif_stop(dev) dev->start=0
+
+static __inline__ void
+netif_stop_queue (net_device * dev)
+{
+	dev->tbusy = 1;
+}
+
+static __inline__ void
+netif_start_queue (net_device * dev)
+{
+	dev->tbusy = 0;
+}
+
+static __inline__ void
+netif_wake_queue (net_device * dev)
+{
+	dev->tbusy = 0;
+	mark_bh (NET_BH);
+}
+
+#else
+	/* As of 2.3.45, we don't do these things anymore */
+#define netif_enter_interrupt(dev)
+#define netif_exit_interrupt(dev)
+#define netif_start(dev)
+#define netif_stop(dev)
+#endif
+
+static int iucv_start (net_device *);
+static int iucv_stop (net_device *);
+static int iucv_change_mtu (net_device *, int);
+static int iucv_init (net_device *);
+static void iucv_rx (net_device *, uchar *, int);
+static int iucv_tx (struct sk_buff *, net_device *);
+
+static void connection_severed (iucv_ConnectionSevered *, ulong);
+static void connection_pending (iucv_ConnectionPending *, ulong);
+static void connection_complete (iucv_ConnectionComplete *, ulong);
+static void message_pending (iucv_MessagePending *, ulong);
+static void send_complete (iucv_MessageComplete *, ulong);
+
+void register_iucv_dev (int, char *);
+
+static iucv_interrupt_ops_t netiucv_ops = {
+	&connection_pending,
+	&connection_complete,
+	&connection_severed,
+	NULL,			/* Quiesced             */
+	NULL,			/* Resumed              */
+	&message_pending,	/* Message pending      */
+	&send_complete		/* Message complete     */
+};
+
+static char iucv_userid[MAX_DEVICES][8];
+net_device iucv_netdev[MAX_DEVICES];
+static char eodata[2] = { '\0', '\0' };
+
+/* This structure is private to each device. It contains the    */
+/* information necessary to do IUCV operations.                 */
+struct iucv_priv {
+	struct net_device_stats stats;
+	net_device *dev;
+	iucv_handle_t handle;
+	uchar userid[9];	/* Printable userid */
+	uchar userid2[8];	/* Used for IUCV operations */
+
+	/* Note: atomic_compare_and_swap() return value is backwards */
+	/*       from what you might think: FALSE=0=OK, TRUE=1=FAIL  */
+	atomic_t state;
+#define FREE 0
+#define CONNECTING 1
+#define CONNECTED 2
+	u16 pathid;
+};
+
+struct iucvtag {
+	iucv_array_t iucvvec[3];
+	u16 framelen;
+	struct sk_buff *skb;
+};
+
+uchar iucv_host[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+uchar iucvMagic[16] = { 0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
+	0xF0, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40
+};
+
+/* This mask means the 16-byte IUCV "magic" and the origin userid must */
+/* match exactly as specified in order to give connection_pending()    */
+/* control. 							       */
+const char mask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+#ifdef DEBUG
+/*--------------------------*/
+/* Dump buffer formatted    */
+/*--------------------------*/
+static void
+dumpit (char *buf, int len)
+{
+	int i;
+	printk (KERN_DEBUG);
+	for (i = 0; i < len; i++) {
+		if (!(i % 32) && i != 0)
+			printk ("\n");
+		else if (!(i % 4) && i != 0)
+			printk (" ");
+		printk ("%02X", buf[i]);
+	}
+	if (len % 32)
+		printk ("\n");
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* Open a connection to another Linux or VM TCP/IP stack.          */
+/* Called by kernel.						   */
+/*                                                                 */
+/* 1. Register a handler. (Up to now, any attempt by another stack */
+/*    has been rejected by the IUCV handler.)  We give the handler */
+/*    the net_device* so that we can locate the dev associated     */
+/*    with the partner userid if he tries to connect to us or      */
+/*    if the connection is broken.                                 */
+/*                                                                 */
+/* 2. Connect to remote stack.  If we get a connection pending     */
+/*    interrupt while we're in the middle of connecting, don't     */
+/*    worry.  VM will sever its and use ours, because the DEVICE   */
+/*    is defined to be:                                            */
+/*           DEVICE devname IUCV 0 0 linuxvm A                     */
+/*        or DEVICE devname IUCV 0 0 linuxvm B                     */
+/*    In EBCDIC, "0" (0xF0) is greater than "A" (0xC1) or "B", so  */
+/*    win all races.  We will sever any connects that occur while  */
+/*    we are connecting.  The "0 0" is where we get iucvMagic from.*/
+/*								   */
+/*    FIXME: If two Linux machines get into this race condition,   */
+/*           both will sever.  Manual intervention required.       */
+/*           Need a better IUCV "hello"-like function that permits */
+/*           some negotiation.  But can't do that until VM TCP/IP  */
+/*           would support it.                                     */
+/*                                                                 */
+/* 3. Return 0 to indicate device ok.  Anything else is an error.  */
+/*-----------------------------------------------------------------*/
+static int
+iucv_start (net_device * dev)
+{
+	int rc, i;
+	uchar pri;
+	uchar unused = '\0';
+	struct iucv_priv *p = (struct iucv_priv *) dev->priv;
+
+	pr_debug ("iucv_start(%s)\n", dev->name);
+
+	if (p == NULL) {
+		/* Allocate priv data */
+		p = (struct iucv_priv *) kmalloc (sizeof (struct iucv_priv),
+						  GFP_KERNEL);
+		if (p == NULL) {
+			printk (KERN_CRIT "%s: no memory for dev->priv.\n",
+				dev->name);
+			return -ENOMEM;
+		}
+		memset (p, 0, sizeof (struct iucv_priv));
+		dev->priv = p;
+		p->dev = dev;
+
+		memcpy (p->userid, iucv_userid[dev - iucv_netdev], 8);	/* Save userid */
+		memcpy (p->userid2, p->userid, 8);	/* Again, with feeling.  */
+
+		for (i = 0; i < 8; i++) {	/* Change userid to printable form */
+			if (p->userid[i] == ' ') {
+				p->userid[i] = '\0';
+				break;
+			}
+		}
+		p->userid[8] = '\0';
+		atomic_set (&p->state, FREE);
+		p->handle =
+		    iucv_register_program (iucvMagic, p->userid2, (char *) mask,
+					   &netiucv_ops, (ulong) dev);
+		if (p->handle <= 0) {
+			printk (KERN_ERR
+				"%s: iucv_register_program error, rc=%i\n",
+				dev->name, (int) p->handle);
+			dev->priv = NULL;
+			kfree (p);
+			return -ENODEV;
+		}
+		pr_debug ("state@ = %p\n", &p->state);
+		MOD_INC_USE_COUNT;
+	}
+
+	if (atomic_compare_and_swap (FREE, CONNECTING, &p->state) != 0) {
+		pr_debug ("Other side connecting during start\n");
+		return 0;
+	}
+
+	rc =
+	    iucv_connect (&(p->pathid), MAX_TX_Q, iucvMagic, p->userid2,
+			  iucv_host, unused, unused, unused, unused, unused,
+			  &pri, p->handle, (ulong) p);
+
+	/* Some errors are not fatal.  In these cases we will report "OK". */
+	switch (rc) {
+	case 0:		/* Wait for connection to complete */
+		pr_debug ("...waiting for connection to complete...");
+		return 0;
+	case 11:		/* Wait for parter to connect */
+		printk (KERN_NOTICE "Device %s: "
+			"User %s is not available now.\n",
+			dev->name, p->userid);
+		atomic_set (&p->state, FREE);
+		return 0;
+	case 12:		/* Wait for partner to connect */
+		printk (KERN_NOTICE "Device %s: "
+			"User %s is not ready to talk now.\n",
+			dev->name, p->userid);
+		atomic_set (&p->state, FREE);
+		return 0;
+	case 13:		/* Fatal */
+		printk (KERN_ERR "Device %s: "
+			"You have too many IUCV connections."
+			"Check MAXCONN in CP directory.\n", dev->name);
+		break;
+	case 14:		/* Fatal */
+		printk (KERN_ERR "Device %s: "
+			"User %s has too many IUCV connections."
+			"Check MAXCONN in CP directory.\n",
+			dev->name, p->userid);
+		break;
+	case 15:		/* Fatal */
+		printk (KERN_ERR "Device %s: "
+			"No IUCV authorization found in CP directory.\n",
+			dev->name);
+		break;
+	default:		/* Really fatal! Should not occur!! */
+		printk (KERN_ERR "%s: "
+			"return code %i from iucv_connect()\n", dev->name, rc);
+	}
+
+	rc = iucv_unregister (p->handle);
+	dev->priv = NULL;
+	kfree (p);
+	MOD_DEC_USE_COUNT;
+	return -ENODEV;
+}				/* end iucv_start() */
+
+/*********************************************************************/
+/* Our connection TO another stack has been accepted.                */
+/*********************************************************************/
+static void
+connection_complete (iucv_ConnectionComplete * cci, ulong pgm_data)
+{
+	struct iucv_priv *p = (struct iucv_priv *) pgm_data;
+	pr_debug ("...%s connection complete... txq=%u\n",
+		  p->dev->name, cci->ipmsglim);
+	atomic_set (&p->state, CONNECTED);
+	p->pathid = cci->ippathid;
+	p->dev->tx_queue_len = cci->ipmsglim;
+	netif_start (p->dev);
+	netif_start_queue (p->dev);
+	printk (KERN_INFO "%s: Connection to user %s is up\n",
+		p->dev->name, p->userid);
+}				/* end connection_complete() */
+
+/*********************************************************************/
+/* A connection FROM another stack is pending.  If we are in the     */
+/* middle of connecting, sever the new connection.                   */
+/*								     */
+/* We only get here if we've done an iucv_register(), so we know     */
+/* the remote user is the correct user.                              */
+/*********************************************************************/
+static void
+connection_pending (iucv_ConnectionPending * cpi, ulong pgm_data)
+{
+	/* Only get this far if handler is set up, so we know userid is ok. */
+	/* and the device is started.                                       */
+	/* pgm_data is different for this one.  We get dev*, not priv*.     */
+	net_device *dev = (net_device *) pgm_data;
+	struct iucv_priv *p = (struct iucv_priv *) dev->priv;
+	int rc;
+	uchar udata[16];
+	uchar no = '\0';
+	uchar na;
+
+	/* If we're not waiting on a connect, reject the connection */
+	if (atomic_compare_and_swap (FREE, CONNECTING, &p->state) != 0) {
+		iucv_sever (cpi->ippathid, udata);
+		return;
+	}
+
+	rc = iucv_accept (cpi->ippathid,	/* Path id              */
+			  MAX_TX_Q,	/* msglimit                     */
+			  udata,	/* user_Data                    */
+			  no,	/* will we send priority msgs?  */
+			  no,	/* do we accept prmdata?        */
+			  no,	/* quiece immediately?          */
+			  no,	/* control path?                */
+			  &na,	/* other side accept prmdata?   */
+			  p->handle,	/* registration handle  */
+			  (ulong) p);	/* private data         */
+	if (rc != 0) {
+		atomic_set (&p->state, FREE);
+		printk (KERN_ERR "%s: iucv accept failed rc=%i\n",
+			p->dev->name, rc);
+	} else {
+		p->pathid = cpi->ippathid;
+		p->dev->tx_queue_len = cpi->ipmsglim;
+		netif_start (p->dev);
+		netif_start_queue (p->dev);
+		atomic_set (&p->state, CONNECTED);
+		printk (KERN_INFO "Device %s: Connection to user %s is up\n",
+			p->dev->name, p->userid);
+	}
+}				/* end connection_pending() */
+
+/*********************************************************************/
+/* Our connection to another stack has been severed.                 */
+/*********************************************************************/
+static void
+connection_severed (iucv_ConnectionSevered * eib, ulong pgm_data)
+{
+	struct iucv_priv *p = (struct iucv_priv *) pgm_data;
+
+	printk (KERN_INFO "%s: Connection to user %s is down\n",
+		p->dev->name, p->userid);
+
+	if (atomic_compare_and_swap (CONNECTED, FREE, &p->state) != 0)
+		return;		/* In case reconnect in progress already */
+
+	netif_stop_queue (p->dev);
+	netif_stop (p->dev);
+}				/* end connection_severed() */
+
+/*-----------------------------------------------------*/
+/* STOP device.                   Called by kernel.    */
+/*-----------------------------------------------------*/
+static int
+iucv_stop (net_device * dev)
+{
+	int rc = 0;
+	struct iucv_priv *p;
+	pr_debug ("%s: iucv_stop\n", dev->name);
+
+	netif_stop_queue (dev);
+	netif_stop (dev);
+
+	p = (struct iucv_priv *) (dev->priv);
+	if (p == NULL)
+		return 0;
+
+	rc = iucv_unregister (p->handle);	/* Will sever connections */
+	dev->priv = NULL;
+	kfree (p);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}				/* end  iucv_stop() */
+
+/*---------------------------------------------------------------------*/
+/* Inbound packets from other host are ready for receipt.  Receive     */
+/* them (they arrive as a single transmission), break them up into     */
+/* separate packets, and send them to the "generic" packet processor.  */
+/*---------------------------------------------------------------------*/
+static void
+message_pending (iucv_MessagePending * mpi, ulong pgm_data)
+{
+	struct iucv_priv *p = (struct iucv_priv *) pgm_data;
+	int rc;
+	u32 buffer_length;
+	u16 packet_offset, prev_offset = 0;
+	void *buffer;
+
+	buffer_length = mpi->ln1msg2.ipbfln1f;
+	pr_debug ("message_pending: ID=%p Length=%u\n", (void *) mpi->ipmsgid,
+		  buffer_length);
+
+	buffer = kmalloc (buffer_length, GFP_KERNEL | GFP_DMA);
+	if (buffer == NULL) {
+		p->stats.rx_dropped++;
+		return;
+	}
+
+	rc = iucv_receive_simple (p->pathid, mpi->ipmsgid, mpi->iptrgcls,
+				  buffer, buffer_length);
+
+	if (rc != 0 || buffer_length < 5) {
+		printk (KERN_INFO
+			"%s: iucv_receive error. rc=%X, length=%u\n",
+			p->dev->name, rc, buffer_length);
+		p->stats.rx_errors++;
+		kfree (buffer);
+		return;
+	}
+
+	packet_offset = *((u16 *) buffer);
+
+	while (packet_offset != 0) {
+		if (packet_offset <= prev_offset
+		    || packet_offset > buffer_length - 2) {
+			printk (KERN_INFO "%s: bad inbound packet offset %u, "
+				"prev %u, total %u\n", p->dev->name,
+				packet_offset, prev_offset, buffer_length);
+			p->stats.rx_errors++;
+			break;
+		} else {
+			/* Kick the packet upstairs */
+			iucv_rx (p->dev,
+				 buffer + prev_offset + 2,
+				 packet_offset - prev_offset - 2);
+			prev_offset = packet_offset;
+			packet_offset = *((u16 *) (buffer + packet_offset));
+		}
+	}
+
+	kfree (buffer);
+	return;
+}				/* end message_pending() */
+
+/*-------------------------------------------------------------*/
+/* Add meta-data to packet and send upstairs.                  */
+/*-------------------------------------------------------------*/
+static void
+iucv_rx (net_device * dev, uchar * buf, int len)
+{
+	struct iucv_priv *p = (struct iucv_priv *) dev->priv;
+	struct sk_buff *skb;
+
+	pr_debug ("%s: iucv_rx len=%u\n", p->dev->name, len);
+#ifdef DEBUG
+	dumpit (buf, 20);
+#endif
+
+	if (len > p->dev->mtu) {
+		printk (KERN_INFO
+			"%s: inbound packet length %u exceeds MTU %i\n",
+			p->dev->name, len, p->dev->mtu);
+		p->stats.rx_errors++;
+		return;
+	}
+
+	skb = dev_alloc_skb (len);
+	if (!skb) {
+		p->stats.rx_dropped++;
+		return;
+	}
+
+	/* If not enough room, skb_put will panic */
+	memcpy (skb_put (skb, len), buf, len);
+
+	/* Write metadata, and then pass to the receive level.  Since we */
+	/* are not an Ethernet device, we have special fields to set.    */
+	/* This is all boilerplace, not to be messed with.               */
+	skb->dev = p->dev;	/* Set device       */
+	skb->mac.raw = skb->data;	/* Point to packet  */
+	skb->pkt_type = PACKET_HOST;	/* ..for this host. */
+	skb->protocol = htons (ETH_P_IP);	/* IP packet        */
+	skb->ip_summed = CHECKSUM_UNNECESSARY;	/* No checksum      */
+	p->stats.rx_packets++;
+	p->stats.rx_bytes += len;
+	netif_rx (skb);
+
+	return;
+}				/* end  iucv_rx() */
+
+/*-------------------------------------------------------------*/
+/* TRANSMIT a packet.            	    Called by kernel.  */
+/* This function deals with hw details of packet transmission. */
+/*-------------------------------------------------------------*/
+static int
+iucv_tx (struct sk_buff *skb, net_device * dev)
+{
+	int rc, pktlen;
+	struct iucvtag *tag;
+	struct iucv_priv *p = (struct iucv_priv *) dev->priv;
+
+	if (skb == NULL)	/* Nothing to do */
+		return 0;
+
+	if (netif_is_busy (dev)) {
+		p->stats.tx_dropped++;
+		dev_kfree_skb (skb);
+		printk (KERN_ERR "%s: tx conflict! leave iucv_tx.\n",
+			dev->name);
+		return -EBUSY;
+	}
+
+	netif_stop_queue (dev);	/* transmission is busy */
+
+	dev->trans_start = jiffies;	/* save the timestamp */
+
+	/* Tag contains data that must survive exit from this */
+	/* routine.  MessageComplete exit will free the tag   */
+	/* and any structures it points to.                   */
+	tag =
+	    (struct iucvtag *) kmalloc (sizeof (struct iucvtag),
+					GFP_DMA | GFP_KERNEL);
+	if (!tag) {
+		p->stats.tx_dropped++;
+		dev_kfree_skb (skb);
+		return -ENOMEM;
+	}
+
+	pktlen = skb->len;
+	tag->framelen = (u16) pktlen + 2;
+	tag->skb = skb;
+	tag->iucvvec[0].address = &tag->framelen;
+	tag->iucvvec[0].length = 2;
+	tag->iucvvec[1].address = (void *) virt_to_phys (skb->data);
+	tag->iucvvec[1].length = pktlen;
+	tag->iucvvec[2].address = (void *) virt_to_phys (eodata);
+	tag->iucvvec[2].length = 2;
+	pr_debug ("iucv_tx: length=%i, skb=%p tag=%p\n", pktlen, tag->skb, tag);
+
+	/* Ok, now the packet is ready for transmission: send it. */
+	rc =
+	    iucv_send_array (p->pathid, NULL, 0, 0, (ulong) tag, 0,
+			     tag->iucvvec, pktlen + 4);
+	if (rc == 0)
+		p->stats.tx_packets++;
+	else {
+		if (rc == 3)	/* Exceeded MSGLIMIT */
+			p->stats.tx_dropped++;
+		else {
+			p->stats.tx_errors++;
+			printk (KERN_INFO "%s: iucv send failed, rc=%i\n",
+				p->dev->name, rc);
+		}
+		dev_kfree_skb (skb);
+		kfree (tag);
+	}
+
+	netif_wake_queue (p->dev);
+	return rc;		/* zero == done; nonzero == fail */
+}				/* end iucv_tx() */
+
+/*-----------------------------------------------------------*/
+/* SEND COMPLETE                    Called by IUCV handler.  */
+/* Free SKB associated with this transmission and free       */
+/* the IUCV buffer list and SKB pointer.                     */
+/*-----------------------------------------------------------*/
+static void
+send_complete (iucv_MessageComplete * mci, ulong pgm_data)
+{
+	struct iucvtag *tag = (struct iucvtag *) mci->ipmsgtag;
+	pr_debug ("TX COMPLETE: Tag=%p skb=%p\n", tag, tag->skb);
+	dev_kfree_skb (tag->skb);
+	kfree (tag);
+}				/* end send_complete() */
+
+/*-----------------------------------------------------------*/
+/* STATISTICS reporting.                  Called by kernel.  */
+/*-----------------------------------------------------------*/
+static struct net_device_stats *
+iucv_stats (net_device * dev)
+{
+	struct iucv_priv *p = (struct iucv_priv *) dev->priv;
+	return &p->stats;
+}				/* end iucv_stats() */
+
+/*-----------------------------------------------------------*/
+/* MTU change    .                        Called by kernel.  */
+/* IUCV can handle mtu sizes from 576 (the IP architectural  */
+/* minimum) up to maximum supported by VM.  I don't think IP */
+/* pays attention to new mtu until device is restarted.      */
+/*-----------------------------------------------------------*/
+static int
+iucv_change_mtu (net_device * dev, int new_mtu)
+{
+	if ((new_mtu < 576) || (new_mtu > MAX_VM_MTU))
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}				/* end iucv_change_mtu() */
+
+/*-----------------------------------------------------------*/
+/* INIT device.                           Called by kernel.  */
+/* Called by register_netdev() in kernel.                    */
+/*-----------------------------------------------------------*/
+static int
+iucv_init (net_device * dev)
+{
+	dev->open = iucv_start;
+	dev->stop = iucv_stop;
+	dev->hard_start_xmit = iucv_tx;
+	dev->get_stats = iucv_stats;
+	dev->change_mtu = iucv_change_mtu;
+	dev->hard_header_len = 0;
+	dev->addr_len = 0;
+	dev->type = ARPHRD_SLIP;
+	dev->tx_queue_len = MAX_TX_Q;	/* Default - updated based on IUCV */
+	/* keep the default flags, just add NOARP and POINTOPOINT */
+	dev->flags = IFF_NOARP | IFF_POINTOPOINT;
+	dev->mtu = 9216;
+
+	dev_init_buffers (dev);
+	pr_debug ("%s: iucv_init  dev@=%p\n", dev->name, dev);
+	return 0;
+}
+
+#ifndef MODULE
+/*-----------------------------------------------------------------*/
+/* Process iucv=userid1,...,useridn kernel parameter.              */
+/*                                                                 */
+/* Each user id provided will be associated with device 'iucvnn'.  */
+/* iucv_init will be called to initialize each device.             */
+/*-----------------------------------------------------------------*/
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
+#define init_return(a) return a
+static int __init
+iucv_setup (char *iucv)
+#else
+#define init_return(a) return
+__initfunc (void iucv_setup (char *iucv, int *ints))
+#endif
+{
+	int i, devnumber;
+	char *s;
+	char temp_userid[9];
+
+	i = devnumber = 0;
+	memset (temp_userid, ' ', 8);
+	temp_userid[8] = '\0';
+
+	if (!iucv)
+		init_return (0);
+
+	for (s = iucv; *s != '\0'; s++) {
+		if (*s == ' ')	/* Compress out blanks */
+			continue;
+
+		if (devnumber >= MAX_DEVICES) {
+			printk (KERN_ERR "More than %i IUCV hosts specified\n",
+				MAX_DEVICES);
+			init_return (-ENODEV);
+		}
+
+		if (*s != ',') {
+			temp_userid[i++] = *s;
+
+			if (i == 8 || *(s + 1) == ',' || *(s + 1) == '\0') {
+				register_iucv_dev (devnumber, temp_userid);
+				devnumber++;
+				i = 0;
+				memset (temp_userid, ' ', 8);
+				if (*(s + 1) != '\0')
+					*(s + 1) = ' ';
+			}
+		}
+	}			/* while */
+
+	init_return (1);
+}
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,0))
+__setup ("iucv=", iucv_setup);
+#endif
+#else				/* BUILT AS MODULE */
+/*-------------------------------------------------------------------*/
+/* Process iucv=userid1,...,useridn module paramter.                 */
+/*                                                                   */
+/* insmod passes the module an array of string pointers, each of     */
+/* which points to a userid.  The commas are stripped out by insmod. */
+/* MODULE_PARM defines the name of the array.  (See start of module.)*/
+/*                                                                   */
+/* Each user id provided will be associated with device 'iucvnn'.    */
+/* iucv_init will be called to initialize each device.               */
+/*-------------------------------------------------------------------*/
+char *iucv[MAX_DEVICES] = { NULL };
+int
+init_module (void)
+{
+	int i;
+	for (i = 0; i < MAX_DEVICES; i++) {
+		if (iucv[i] == NULL)
+			break;
+		register_iucv_dev (i, iucv[i]);
+	}
+	return 0;
+}
+
+void
+cleanup_module (void)
+{
+	int i;
+	for (i = 0; i < MAX_DEVICES; i++) {
+		if (iucv[i])
+			unregister_netdev (&iucv_netdev[i]);
+	}
+	return;
+}
+#endif				/* MODULE */
+
+void
+register_iucv_dev (int devnumber, char *userid)
+{
+	int rc;
+	net_device *dev;
+
+	memset (iucv_userid[devnumber], ' ', 8);
+	memcpy (iucv_userid[devnumber], userid, min (strlen (userid), 8));
+	dev = &iucv_netdev[devnumber];
+	sprintf (dev->name, "iucv%i", devnumber);
+
+	pr_debug ("netiucv: registering %s\n", dev->name);
+
+	if ((rc = register_netdev (dev))) {
+		printk (KERN_ERR
+			"netiucv: register_netdev(%s) error %i\n",
+			dev->name, rc);
+	}
+	return;
+}
+
+/* These structures are static because setup() can be called very */
+/* early in kernel init if this module is built into the kernel.  */
+/* Certainly no kmalloc() is available, probably no C runtime.    */
+/* If support changed to be module only, this can all be done     */
+/* dynamically.                                                   */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+static char iucv_names[MAX_DEVICES][8];	/* Allows "iucvXXX" plus null */
+#endif
+net_device iucv_netdev[MAX_DEVICES] = {
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[0][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[1][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[2][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[3][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[4][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[5][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[6][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[7][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[8][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+	{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+		name: &iucv_names[9][0],  /* Name filled in at load time  */
+#endif
+		init: iucv_init 	  /* probe function               */
+	},
+};
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/s390dyn.c linux/drivers/s390/s390dyn.c
--- v2.4.1/linux/drivers/s390/s390dyn.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/s390dyn.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,213 @@
+/*
+ *  arch/s390/kernel/s390dyn.c
+ *   S/390 dynamic device attachment
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+
+#include <asm/irq.h>
+#include <asm/s390io.h>
+#include <asm/s390dyn.h>
+
+static devreg_t   *devreg_anchor = NULL;
+static spinlock_t  dyn_lock      = SPIN_LOCK_UNLOCKED;
+
+
+int s390_device_register( devreg_t *drinfo )
+{
+	unsigned long  flags;
+	int            pdevflag,drflag;
+
+	int            ret     = 0;
+	devreg_t      *pdevreg = devreg_anchor;
+
+	if ( drinfo == NULL )
+		return( -EINVAL );
+
+	drflag = drinfo->flag;
+
+	if ( (drflag & DEVREG_TYPE_DEVNO) == (drflag & DEVREG_TYPE_DEVCHARS) )
+		return( -EINVAL ); 
+
+	spin_lock_irqsave( &dyn_lock, flags ); 	
+
+	while ( (pdevreg != NULL) && (ret ==0) )
+	{
+		if ( pdevreg == drinfo )
+		{
+			ret = -EINVAL;
+		}
+		else
+		{
+			pdevflag = pdevreg->flag;
+
+			/*
+			 * we don't allow multiple drivers to register 
+			 *  for the same device number 
+			 */
+			if (    (    (pdevflag & DEVREG_TYPE_DEVNO)
+			          && (pdevreg->ci.devno                ) )
+			     && (    (drflag & DEVREG_TYPE_DEVNO )
+			          && (drinfo->ci.devno                 ) ) )
+			{
+				ret = -EBUSY;
+			}           	
+			else if ( drflag == (   DEVREG_TYPE_DEVCHARS 
+			                      | DEVREG_EXACT_MATCH   )) 
+			{
+				if ( !memcmp(&drinfo->ci.hc,
+				             &pdevreg->ci.hc,
+				             sizeof(devreg_hc_t)))
+					ret=-EBUSY;
+			} /* endif */
+
+		} /* endif */
+
+		pdevreg = pdevreg->next;
+	
+	} /* endwhile */          	
+
+	/*
+	 * only enqueue if no collision was found ...	
+	 */
+	if(ret==0)	
+	{
+		drinfo->next = devreg_anchor;
+		drinfo->prev = NULL;
+
+		if ( devreg_anchor != NULL )
+		{
+			devreg_anchor->prev = drinfo;       	
+
+		} /* endif */
+		
+		devreg_anchor=drinfo;
+
+	} /* endif */
+
+	spin_unlock_irqrestore( &dyn_lock, flags ); 	
+ 	
+	return( ret);
+}
+
+
+int s390_device_unregister( devreg_t *dreg )
+{
+	unsigned long  flags;
+
+	int            ret     = -EINVAL;
+	devreg_t      *pdevreg = devreg_anchor;
+
+	if ( dreg == NULL )
+		return( -EINVAL );
+
+	spin_lock_irqsave( &dyn_lock, flags ); 	
+
+	while (    (pdevreg != NULL )
+	        && (    ret != 0    ) )
+	{
+		if ( pdevreg == dreg )
+		{
+			devreg_t *dprev = pdevreg->prev;
+			devreg_t *dnext = pdevreg->next;
+
+			if ( (dprev != NULL) && (dnext != NULL) )
+			{
+				dnext->prev = dprev;
+				dprev->next = dnext;
+			}
+			if ( (dprev != NULL) && (dnext == NULL) )
+			{
+				dprev->next = NULL;
+			}
+			if ( (dprev == NULL) && (dnext != NULL) )
+			{
+				dnext->prev = NULL;
+
+			} /* else */
+
+			ret = 0;
+		}
+		else
+		{
+			pdevreg = pdevreg->next;
+
+		} /* endif */
+
+	} /* endwhile */          	
+
+	spin_unlock_irqrestore( &dyn_lock, flags ); 	
+ 	
+	return( ret);
+}
+
+
+devreg_t * s390_search_devreg( ioinfo_t *ioinfo )
+{
+	unsigned long  flags;
+	devreg_hc_t    match;
+	devreg_t *pdevreg = devreg_anchor;
+
+	if ( ioinfo == NULL )
+		return( NULL );
+
+	spin_lock_irqsave( &dyn_lock, flags ); 	
+
+	while ( pdevreg != NULL )
+	{
+		int flag = pdevreg->flag;
+
+		if (    (flag & DEVREG_TYPE_DEVNO )
+		     && (ioinfo->ui.flags.dval == 1        )
+		     && (ioinfo->devno == pdevreg->ci.devno) )
+		{
+			break;
+		}           	
+		else if (flag & DEVREG_TYPE_DEVCHARS )
+		{
+			if ( flag & DEVREG_EXACT_MATCH ) 
+			{
+				if ( !memcmp( &pdevreg->ci.hc, 
+				              &ioinfo->senseid.cu_type,
+				              sizeof(devreg_hc_t)))
+					break; 
+			} 
+			else
+			{			
+				memcpy( &match, &ioinfo->senseid.cu_type, 
+				        sizeof(match));
+
+				if( flag & DEVREG_NO_CU_INFO )
+				{
+					match.ctype = pdevreg->ci.hc.ctype;
+					match.cmode = pdevreg->ci.hc.cmode;
+				}
+				if( flag & DEVREG_NO_DEV_INFO )
+				{
+					match.dtype = pdevreg->ci.hc.dtype;
+					match.dmode = pdevreg->ci.hc.dmode;
+				}
+				if ( flag & DEVREG_MATCH_CU_TYPE )
+					match.cmode = pdevreg->ci.hc.cmode;
+				if( flag & DEVREG_MATCH_DEV_TYPE)
+					match.dmode = pdevreg->ci.hc.dmode;
+				if ( !memcmp( &pdevreg->ci.hc,
+				              &match, sizeof(match)))
+					break;
+			} /* endif */
+		} /* endif */
+
+		pdevreg = pdevreg->next;
+
+	} /* endwhile */          	
+
+	spin_unlock_irqrestore( &dyn_lock, flags ); 	
+ 	
+	return( pdevreg);
+}
+
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/s390io.c linux/drivers/s390/s390io.c
--- v2.4.1/linux/drivers/s390/s390io.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/s390io.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,5668 @@
+/*
+ *  arch/s390/kernel/s390io.c
+ *   S/390 common I/O routines
+ *
+ *  S390 version
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+ *                             IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ *    ChangeLog: 01/04/2001 Holger Smolinski (smolinsk@de.ibm.com)
+ *                          Fixed lost interrupts and do_adapter_IO
+ */
+
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/malloc.h>
+#include <linux/string.h>
+#include <linux/smp.h>
+#include <linux/threads.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <linux/bootmem.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/processor.h>
+#include <asm/lowcore.h>
+#include <asm/idals.h>
+
+#include <asm/s390io.h>
+#include <asm/s390dyn.h>
+#include <asm/s390mach.h>
+
+#ifndef TRUE
+#define TRUE  1
+#define FALSE 0
+#endif
+
+#undef  CONFIG_DEBUG_IO
+#define CONFIG_DEBUG_CRW
+
+#define REIPL_DEVID_MAGIC 0x87654321
+
+struct s390_irqaction  init_IRQ_action;
+unsigned int           highest_subchannel;
+ioinfo_t              *ioinfo_head = NULL;
+ioinfo_t              *ioinfo_tail = NULL;
+ioinfo_t              *ioinfo[__MAX_SUBCHANNELS] = {
+	[0 ... (__MAX_SUBCHANNELS-1)] = INVALID_STORAGE_AREA
+};
+
+static atomic_t    sync_isc     = ATOMIC_INIT(-1);
+                                          // synchronous irq processing lock
+static spinlock_t  adapter_lock = SPIN_LOCK_UNLOCKED;
+                                          // adapter interrupt lock
+static psw_t      io_sync_wait;           // wait PSW for sync IO, prot. by sync_isc
+static int        cons_dev          = -1; // identify console device
+static int        init_IRQ_complete = 0;
+static int        cio_show_msg      = 0;
+static schib_t   *p_init_schib      = NULL;
+static irb_t     *p_init_irb        = NULL;
+static __u64      irq_IPL_TOD;
+static adapter_int_handler_t adapter_handler   = NULL;
+
+/*
+ * Dummy controller type for unused interrupts
+ */
+int  do_none(unsigned int irq, int cpu, struct pt_regs * regs) { return 0;}
+int  enable_none(unsigned int irq) { return(-ENODEV); }
+int  disable_none(unsigned int irq) { return(-ENODEV); }
+
+struct hw_interrupt_type no_irq_type = {
+	"none",
+	do_none,
+	enable_none,
+	disable_none
+};
+
+static void init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs);
+static int  s390_setup_irq(unsigned int irq, struct s390_irqaction * new);
+static void s390_process_subchannels( void);
+static void s390_device_recognition_all( void);
+static void s390_device_recognition_irq( int irq);
+static int  s390_validate_subchannel( int irq, int enable);
+static int  s390_SenseID( int irq, senseid_t *sid, __u8 lpm);
+static int  s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid);
+static int  s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid);
+static int  s390_process_IRQ( unsigned int irq );
+static int  disable_subchannel( unsigned int irq);
+
+static inline void do_adapter_IO( __u32 intparm );
+
+int  s390_DevicePathVerification( int irq, __u8 domask );
+int  s390_register_adapter_interrupt( adapter_int_handler_t handler );
+int  s390_unregister_adapter_interrupt( adapter_int_handler_t handler );
+
+extern int  do_none(unsigned int irq, int cpu, struct pt_regs * regs);
+extern int  enable_none(unsigned int irq);
+extern int  disable_none(unsigned int irq);
+
+asmlinkage void do_IRQ( struct pt_regs regs );
+
+void s390_displayhex(char *str,void *ptr,s32 cnt);
+
+void s390_displayhex(char *str,void *ptr,s32 cnt)
+{
+	s32	cnt1,cnt2,maxcnt2;
+	u32	*currptr=(__u32 *)ptr;
+
+	printk("\n%s\n",str);
+
+	for(cnt1=0;cnt1<cnt;cnt1+=16)
+	{
+		printk("%08lX ",(unsigned long)currptr);
+		maxcnt2=cnt-cnt1;
+		if(maxcnt2>16)
+			maxcnt2=16;
+		for(cnt2=0;cnt2<maxcnt2;cnt2+=4)
+			printk("%08X ",*currptr++);
+		printk("\n");
+	}
+}
+
+static int __init cio_setup( char *parm, int *ints)
+{
+	if ( !strcmp( parm, "yes") )
+	{
+		cio_show_msg = 1;
+	}
+	else if ( !strcmp( parm, "no") )
+	{
+		cio_show_msg = 0;
+	}
+	else
+	{
+		printk( "cio_setup : invalid cio_msg parameter '%s'", parm);
+
+	} /* endif */
+
+	return 1;
+}
+
+__setup("cio_msg=", cio_setup);
+
+
+/*
+ * register for adapter interrupts
+ *
+ * With HiperSockets the zSeries architecture provides for
+ *  means of adapter interrups, pseudo I/O interrupts that are
+ *  not tied to an I/O subchannel, but to an adapter. However,
+ *  it doesn't disclose the info how to enable/disable them, but
+ *  to recognize them only. Perhaps we should consider them
+ *  being shared interrupts, and thus build a linked list
+ *  of adapter handlers ... to be evaluated ...
+ */
+int  s390_register_adapter_interrupt( adapter_int_handler_t handler )
+{
+	int ret = 0;
+
+	spin_lock( &adapter_lock );
+
+	if ( handler == NULL )
+		ret = -EINVAL;
+	else if ( adapter_handler )
+		ret = -EBUSY;
+	else
+		adapter_handler = handler;
+  	
+	spin_unlock( &adapter_lock ); 	
+
+	return( ret);
+}
+
+
+int  s390_unregister_adapter_interrupt( adapter_int_handler_t handler )
+{
+	int ret = 0;
+
+	spin_lock( &adapter_lock ); 	
+
+	if ( handler == NULL )
+		ret = -EINVAL;
+	else if ( handler != adapter_handler )
+		ret = -EINVAL;
+	else
+		adapter_handler = NULL;
+  	
+	spin_unlock( &adapter_lock ); 	
+
+	return( ret);
+}
+
+static inline void do_adapter_IO( __u32 intparm )
+{
+	spin_lock( &adapter_lock ); 	
+
+	if ( adapter_handler )
+		(*adapter_handler)( intparm );
+
+	spin_unlock( &adapter_lock );
+
+	return;  	
+}
+
+
+int s390_request_irq_special( int                      irq,
+                              io_handler_func_t        io_handler,
+                              not_oper_handler_func_t  not_oper_handler,
+                              unsigned long            irqflags,
+                              const char              *devname,
+                              void                    *dev_id)
+{
+	int               retval;
+	struct s390_irqaction *action;
+
+	if (irq >= __MAX_SUBCHANNELS)
+		return -EINVAL;
+
+	if ( !io_handler || !dev_id )
+		return -EINVAL;
+
+	/*
+	 * during init_IRQ() processing we don't have memory
+	 *  management yet, thus need to use a statically
+	 *  allocated irqaction control block
+	 */
+	if ( init_IRQ_complete )
+	{
+		action = (struct s390_irqaction *)
+		            kmalloc( sizeof(struct s390_irqaction),
+		                     GFP_KERNEL);
+	}
+	else
+	{
+		action = &init_IRQ_action;
+
+	} /* endif */
+
+	if (!action)
+	{
+		return -ENOMEM;
+
+	} /* endif */
+
+	action->handler = io_handler;
+	action->flags   = irqflags;
+	action->name    = devname;
+	action->dev_id  = dev_id;
+
+	retval = s390_setup_irq( irq, action);
+
+	if ( init_IRQ_complete )
+	{
+		if ( !retval )
+		{
+			s390_DevicePathVerification( irq, 0 );
+		}
+		else
+		{
+			kfree(action);
+
+		} /* endif */
+
+	} /* endif */
+
+	if ( retval == 0 )
+	{
+		ioinfo[irq]->ui.flags.newreq = 1;
+		ioinfo[irq]->nopfunc         = not_oper_handler;  	
+	}
+
+	return retval;
+}
+
+
+int s390_request_irq( unsigned int   irq,
+                      void           (*handler)(int, void *, struct pt_regs *),
+                      unsigned long  irqflags,
+                      const char    *devname,
+                      void          *dev_id)
+{
+	int ret;
+
+	ret = s390_request_irq_special( irq,
+                                   (io_handler_func_t)handler,
+                                   NULL,
+                                   irqflags,
+                                   devname,
+                                   dev_id);
+
+	if ( ret == 0 )
+	{
+		ioinfo[irq]->ui.flags.newreq = 0;
+
+	} /* endif */
+
+	return( ret);
+}
+
+void s390_free_irq(unsigned int irq, void *dev_id)
+{
+	unsigned long flags;
+	int          ret;
+
+	unsigned int count = 0;
+
+	if ( irq >= __MAX_SUBCHANNELS || ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return;
+
+	} /* endif */
+
+	s390irq_spin_lock_irqsave( irq, flags);
+
+#ifdef  CONFIG_KERNEL_DEBUG
+	if ( irq != cons_dev )
+	{
+		printk("Trying to free IRQ%d\n",irq);
+
+	} /* endif */
+#endif
+
+	/*
+	 * disable the device and reset all IRQ info if
+	 *  the IRQ is actually owned by the handler ...
+	 */
+	if ( ioinfo[irq]->irq_desc.action )
+	{
+		if (    (dev_id == ioinfo[irq]->irq_desc.action->dev_id  )
+		     || (dev_id == (devstat_t *)REIPL_DEVID_MAGIC) )
+		{
+			/* start deregister */
+			ioinfo[irq]->ui.flags.unready = 1;
+
+			do
+			{
+				ret = disable_subchannel( irq);
+
+				count++;
+
+				if ( ret == -EBUSY )
+				{
+					int iret;
+
+					/*
+					 * kill it !
+					 * ... we first try sync and eventually
+					 *  try terminating the current I/O by
+					 *  an async request, twice halt, then
+					 *  clear.
+					 */
+					if ( count < 2 )
+					{              	
+						iret = halt_IO( irq,
+						                0xC8C1D3E3,
+						                DOIO_WAIT_FOR_INTERRUPT );
+   	
+						if ( iret == -EBUSY )
+						{
+							halt_IO( irq, 0xC8C1D3E3, 0);
+							s390irq_spin_unlock_irqrestore( irq, flags);
+							udelay( 200000 ); /* 200 ms */
+							s390irq_spin_lock_irqsave( irq, flags);
+
+						} /* endif */
+					}
+					else
+					{
+						iret = clear_IO( irq,
+						                 0x40C3D3D9,
+						                 DOIO_WAIT_FOR_INTERRUPT );
+   	
+						if ( iret == -EBUSY )
+						{
+							clear_IO( irq, 0xC8C1D3E3, 0);
+							s390irq_spin_unlock_irqrestore( irq, flags);
+							udelay( 1000000 ); /* 1000 ms */
+							s390irq_spin_lock_irqsave( irq, flags);
+
+						} /* endif */
+
+					} /* endif */
+
+					if ( count == 2 )
+               {
+						/* give it a very last try ... */
+						disable_subchannel( irq);
+
+						if ( ioinfo[irq]->ui.flags.busy )
+					   {
+							printk( KERN_CRIT"free_irq(%04X) "
+							       "- device %04X busy, retry "
+							       "count exceeded\n",
+						   	    irq,
+						      	 ioinfo[irq]->devstat.devno);
+
+                  } /* endif */
+						
+						break; /* sigh, let's give up ... */
+
+					} /* endif */
+
+				} /* endif */
+		
+			} while ( ret == -EBUSY );
+
+			if ( init_IRQ_complete )
+				kfree( ioinfo[irq]->irq_desc.action );
+
+			ioinfo[irq]->irq_desc.action           = NULL;
+			ioinfo[irq]->ui.flags.ready            = 0;
+			ioinfo[irq]->irq_desc.handler->enable  = enable_none;
+			ioinfo[irq]->irq_desc.handler->disable = disable_none;
+			ioinfo[irq]->ui.flags.unready          = 0; /* deregister ended */
+
+			ioinfo[irq]->nopfunc = NULL;
+
+			s390irq_spin_unlock_irqrestore( irq, flags);
+		}
+		else
+		{
+			s390irq_spin_unlock_irqrestore( irq, flags);
+
+			printk( "free_irq(%04X) : error, "
+			        "dev_id does not match !", irq);
+
+		} /* endif */
+
+	}
+	else
+	{
+		s390irq_spin_unlock_irqrestore( irq, flags);
+
+		printk( "free_irq(%04X) : error, "
+		        "no action block ... !\n", irq);
+
+	} /* endif */
+
+}
+
+/*
+ * Generic enable/disable code
+ */
+int disable_irq(unsigned int irq)
+{
+	unsigned long flags;
+	int           ret;
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
+	s390irq_spin_lock_irqsave(irq, flags);
+
+	/*
+	 * At this point we may actually have a pending interrupt being active
+	 * on another CPU. So don't touch the IRQ_INPROGRESS bit..
+	 */
+	ioinfo[irq]->irq_desc.status |= IRQ_DISABLED;
+	ret = ioinfo[irq]->irq_desc.handler->disable(irq);
+	s390irq_spin_unlock_irqrestore(irq, flags);
+
+	synchronize_irq();
+
+	return( ret);
+}
+
+int enable_irq(unsigned int irq)
+{
+	unsigned long flags;
+	int           ret;
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
+	s390irq_spin_lock_irqsave(irq, flags);
+
+	ioinfo[irq]->irq_desc.status = 0;
+	ret = ioinfo[irq]->irq_desc.handler->enable(irq);
+
+	s390irq_spin_unlock_irqrestore(irq, flags);
+
+	return(ret);
+}
+
+/*
+ * Enable IRQ by modifying the subchannel
+ */
+static int enable_subchannel( unsigned int irq)
+{
+	int   ret;
+	int   ccode;
+	int   retry = 5;
+
+	if ( irq > highest_subchannel || irq < 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+		return( -ENODEV);
+
+	/*
+	 * If a previous disable request is pending we reset it. However, this
+	 *  status implies that the device may (still) be not-operational.
+	 */
+	if (  ioinfo[irq]->ui.flags.d_disable )
+	{
+		ioinfo[irq]->ui.flags.d_disable = 0;
+		ret                             = 0;
+	}
+	else
+	{
+		ccode = stsch(irq, &(ioinfo[irq]->schib) );
+
+		if ( ccode )
+		{
+			ret = -ENODEV;
+		}
+		else
+		{
+			ioinfo[irq]->schib.pmcw.ena = 1;
+
+			if ( irq == cons_dev )
+			{
+				ioinfo[irq]->schib.pmcw.isc = 7;
+			}
+			else	
+			{
+				ioinfo[irq]->schib.pmcw.isc = 3;
+
+			} /* endif */
+
+			do
+			{
+				ccode = msch( irq, &(ioinfo[irq]->schib) );
+
+				switch (ccode) {
+				case 0:
+					ret = 0;
+					break;
+
+				case 1:
+					/*
+					 * very bad, requires interrupt alike
+					 *  processing, where "rbh" is a dummy
+					 *  parameter for interface compatibility
+					 *  only. Bottom-half handling cannot be
+					 *  required as this must be an
+					 *  unsolicited interrupt (!busy).
+					 */
+
+					ioinfo[irq]->ui.flags.s_pend = 1;
+					s390_process_IRQ( irq );
+					ioinfo[irq]->ui.flags.s_pend = 0;
+
+					ret = -EIO;    /* might be overwritten */
+					               /* ... on re-driving    */
+					               /* ... the msch() */
+					retry--;
+					break;
+
+				case 2:
+					udelay(100);	/* allow for recovery */
+					ret = -EBUSY;
+					retry--;
+					break;
+
+				case 3:
+					ioinfo[irq]->ui.flags.oper = 0;
+					ret = -ENODEV;
+					break;
+
+				default:
+					printk( KERN_CRIT"enable_subchannel(%04X) "
+					        " : ccode 2 on msch() for device "
+					        "%04X received !\n",
+					        irq,
+					        ioinfo[irq]->devstat.devno);
+
+					ret = -ENODEV; // never reached
+				}
+
+			} while ( (ccode == 1) && retry );
+
+		} /* endif */
+
+	}  /* endif */
+
+	return( ret );
+}
+
+
+/*
+ * Disable IRQ by modifying the subchannel
+ */
+static int disable_subchannel( unsigned int irq)
+{
+	int  cc;          /* condition code */
+	int  ret;         /* function return value */
+	int  retry = 5;
+
+	if ( irq > highest_subchannel )
+	{
+		ret = -ENODEV;
+	}
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+	}
+	else if ( ioinfo[irq]->ui.flags.busy )
+	{
+		/*
+		 * the disable function must not be called while there are
+		 *  requests pending for completion !
+		 */
+		ret = -EBUSY;
+	}
+	else
+	{
+		/*
+		 * If device isn't operational we have to perform delayed
+		 *  disabling when the next interrupt occurs - unless the
+		 *  irq is re-requested prior to the interrupt to occur.
+		 */
+		cc = stsch(irq, &(ioinfo[irq]->schib) );
+
+		if ( cc == 3 )
+		{
+			ioinfo[irq]->ui.flags.oper      = 0;
+			ioinfo[irq]->ui.flags.d_disable = 1;
+
+			ret = 0;
+		}
+		else // cc == 0
+		{
+			ioinfo[irq]->schib.pmcw.ena = 0;
+
+			do
+			{
+				cc = msch( irq, &(ioinfo[irq]->schib) );
+
+				switch (cc) {
+				case 0 :
+					ret = 0;   /* done */
+					break;
+
+				case 1 :
+					/*
+					 * very bad, requires interrupt alike
+  					 *  processing, where "rbh" is a dummy
+					 *  parm for interface compatibility
+					 *  only. Bottom-half handling cannot
+					 *  be required as this must be an
+					 *  unsolicited interrupt (!busy).
+					 */
+					ioinfo[irq]->ui.flags.s_pend = 1;
+					s390_process_IRQ( irq );
+					ioinfo[irq]->ui.flags.s_pend = 0;
+
+					ret = -EIO; /* might be overwritten  */
+					            /* ... on re-driving the */
+					            /* ... msch() call       */
+					retry--;
+					break;
+
+				case 2 :
+					/*
+					 * *** must not occur !              ***
+					 * ***                               ***
+					 * *** indicates our internal        ***
+					 * *** interrupt accounting is out   ***
+					 * ***  of sync ===> panic()         ***
+					 */
+					printk( KERN_CRIT"disable_subchannel(%04X) "
+					        "- unexpected busy condition for "
+							  "device %04X received !\n",
+					        irq,
+					        ioinfo[irq]->devstat.devno);
+					ret = -EBUSY;
+					break;
+
+				case 3 :
+					/*
+					 * should hardly occur ?!
+					 */
+					ioinfo[irq]->ui.flags.oper      = 0;
+					ioinfo[irq]->ui.flags.d_disable = 1;
+
+					ret = 0; /* if the device has gone we */
+					         /* ... don't need to disable */
+					         /* ... it anymore !    */
+					break;
+
+				default :
+					ret = -ENODEV;  // never reached ...
+					break;
+
+				} /* endswitch */
+
+			} while ( (cc == 1) && retry );
+
+		} /* endif */
+
+	} /* endif */
+
+	return( ret);
+}
+
+
+int s390_setup_irq( unsigned int irq, struct s390_irqaction * new)
+{
+	unsigned long      flags;
+	int                rc = 0;
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
+	/*
+	 * The following block of code has to be executed atomically
+	 */
+	s390irq_spin_lock_irqsave( irq, flags);
+
+	if ( ioinfo[irq]->irq_desc.action == NULL )
+	{
+		ioinfo[irq]->irq_desc.action           = new;
+		ioinfo[irq]->irq_desc.status           = 0;
+		ioinfo[irq]->irq_desc.handler->enable  = enable_subchannel;
+		ioinfo[irq]->irq_desc.handler->disable = disable_subchannel;
+		ioinfo[irq]->irq_desc.handler->handle  = handle_IRQ_event;
+
+		ioinfo[irq]->ui.flags.ready            = 1;
+
+		ioinfo[irq]->irq_desc.handler->enable(irq);
+	}
+	else
+	{
+		/*
+		 *  interrupt already owned, and shared interrupts
+		 *   aren't supported on S/390.
+		 */
+		rc = -EBUSY;
+
+	} /* endif */
+
+	s390irq_spin_unlock_irqrestore(irq,flags);
+
+	return( rc);
+}
+
+void s390_init_IRQ( void )
+{
+	unsigned long flags;     /* PSW flags */
+	long          cr6 __attribute__ ((aligned (8)));
+
+	// Hopefully bh_count's will get set when we copy the prefix lowcore
+	// structure to other CPI's ( DJB )
+	softirq_active(smp_processor_id()) = 0;
+	softirq_mask(smp_processor_id()) = 0;
+	local_bh_count(smp_processor_id()) = 0;
+	local_irq_count(smp_processor_id()) = 0;
+	syscall_count(smp_processor_id()) = 0;
+
+	asm volatile ("STCK %0" : "=m" (irq_IPL_TOD));
+
+	p_init_schib = alloc_bootmem_low( sizeof(schib_t));
+	p_init_irb   = alloc_bootmem_low( sizeof(irb_t));
+
+	/*
+	 * As we don't know about the calling environment
+	 *  we assure running disabled. Before leaving the
+	 *  function we resestablish the old environment.
+	 *
+	 * Note : as we don't need a system wide lock, therefore
+	 *        we shouldn't use cli(), but __cli() as this
+	 *        affects the current CPU only.
+	 */
+	__save_flags(flags);
+	__cli();
+
+	/*
+	 * disable all interrupts
+	 */
+	cr6 = 0;
+	__ctl_load( cr6, 6, 6);
+
+	s390_process_subchannels();
+
+	/*
+	 * enable default I/O-interrupt sublass 3
+	 */
+	cr6 = 0x10000000;
+	__ctl_load( cr6, 6, 6);
+
+	s390_device_recognition_all();
+
+	init_IRQ_complete = 1;
+
+	__restore_flags(flags);
+
+	return;
+}
+
+
+/*
+ * dummy handler, used during init_IRQ() processing for compatibility only
+ */
+void  init_IRQ_handler( int irq, void *dev_id, struct pt_regs *regs)
+{
+   /* this is a dummy handler only ... */
+}
+
+
+int s390_start_IO( int            irq,      /* IRQ */
+                   ccw1_t        *cpa,      /* logical channel prog addr */
+                   unsigned long  user_intparm,  /* interruption parameter */
+                   __u8           lpm,      /* logical path mask */
+                   unsigned long  flag)     /* flags */
+{
+	int            ccode;
+	int            ret = 0;
+
+	/*
+	 * The flag usage is mutal exclusive ...
+	 */
+	if (    (flag & DOIO_EARLY_NOTIFICATION)
+	     && (flag & DOIO_REPORT_ALL     ) )
+	{
+		return( -EINVAL );
+
+	} /* endif */
+
+	/*
+	 * setup ORB
+	 */
+  	ioinfo[irq]->orb.intparm = (__u32)(__u64)&ioinfo[irq]->u_intparm;
+	ioinfo[irq]->orb.fmt     = 1;
+
+	ioinfo[irq]->orb.pfch = !(flag & DOIO_DENY_PREFETCH);
+	ioinfo[irq]->orb.spnd =  (flag & DOIO_ALLOW_SUSPEND ? TRUE : FALSE);
+	ioinfo[irq]->orb.ssic =  (    (flag & DOIO_ALLOW_SUSPEND )
+	                           && (flag & DOIO_SUPPRESS_INTER) );
+
+	if ( flag & DOIO_VALID_LPM )
+	{
+		ioinfo[irq]->orb.lpm = lpm;
+	}
+	else
+	{
+		ioinfo[irq]->orb.lpm = ioinfo[irq]->opm;
+
+	} /* endif */
+
+#ifdef CONFIG_ARCH_S390X
+	/* 
+	 * for 64 bit we always support 64 bit IDAWs with 2k page
+	 *  size only
+	 * FIXTHEM: OSA microcode currently has problems with 4k
+         *          we would like to use 4k.
+	 */
+	ioinfo[irq]->orb.c64 = 1;
+	ioinfo[irq]->orb.i2k = 1;
+#endif
+
+	ioinfo[irq]->orb.cpa = (__u32)virt_to_phys( cpa);
+
+	/*
+	 * If sync processing was requested we lock the sync ISC, modify the
+	 *  device to present interrupts for this ISC only and switch the
+	 *  CPU to handle this ISC + the console ISC exclusively.
+	 */
+	if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+	{
+		ret = enable_cpu_sync_isc( irq);
+	
+		if ( ret )
+		{
+			return( ret);
+		}
+
+	} /* endif */
+
+	if ( flag & DOIO_DONT_CALL_INTHDLR )
+	{
+		ioinfo[irq]->ui.flags.repnone = 1;
+
+	} /* endif */
+
+	/*
+	 * Issue "Start subchannel" and process condition code
+	 */
+	ccode = ssch( irq, &(ioinfo[irq]->orb) );
+
+	switch ( ccode ) {
+	case 0:
+
+		if ( !ioinfo[irq]->ui.flags.w4sense )
+		{
+			/*
+			 * init the device driver specific devstat irb area
+			 *
+			 * Note : don´t clear saved irb info in case of sense !
+			 */
+			memset( &((devstat_t *)ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
+				'\0', sizeof( irb_t) );
+		} /* endif */
+
+		memset( &ioinfo[irq]->devstat.ii.irb,
+		        '\0',
+		        sizeof( irb_t) );
+
+		/*
+		 * initialize device status information
+		 */
+		ioinfo[irq]->ui.flags.busy   = 1;
+		ioinfo[irq]->ui.flags.doio   = 1;
+
+		ioinfo[irq]->u_intparm       = user_intparm;
+		ioinfo[irq]->devstat.cstat   = 0;
+		ioinfo[irq]->devstat.dstat   = 0;
+		ioinfo[irq]->devstat.lpum    = 0;
+		ioinfo[irq]->devstat.flag    = DEVSTAT_START_FUNCTION;
+		ioinfo[irq]->devstat.scnt    = 0;
+
+		ioinfo[irq]->ui.flags.fast   = 0;
+		ioinfo[irq]->ui.flags.repall = 0;
+
+		/*
+		 * Check for either early (FAST) notification requests
+		 *  or if we are to return all interrupt info.
+		 * Default is to call IRQ handler at secondary status only
+		 */
+		if ( flag & DOIO_EARLY_NOTIFICATION )
+		{
+			ioinfo[irq]->ui.flags.fast = 1;
+		}
+		else if ( flag & DOIO_REPORT_ALL )
+		{
+			ioinfo[irq]->ui.flags.repall = 1;
+
+		} /* endif */
+
+		ioinfo[irq]->ulpm = ioinfo[irq]->orb.lpm;
+
+		/*
+		 * If synchronous I/O processing is requested, we have
+		 *  to wait for the corresponding interrupt to occur by
+		 *  polling the interrupt condition. However, as multiple
+		 *  interrupts may be outstanding, we must not just wait
+		 *  for the first interrupt, but must poll until ours
+		 *  pops up.
+		 */
+		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+		{
+			psw_t            io_new_psw;
+			int              ccode;
+			uint64_t         time_start;    	
+			uint64_t         time_curr;    	
+
+			int              ready    = 0;
+			int              io_sub   = -1;
+			struct _lowcore *lc       = NULL;
+			int              do_retry = 1;
+
+			/*
+			 * We shouldn't perform a TPI loop, waiting for an
+			 *  interrupt to occur, but should load a WAIT PSW
+			 *  instead. Otherwise we may keep the channel subsystem
+			 *  busy, not able to present the interrupt. When our
+			 *  sync. interrupt arrived we reset the I/O old PSW to
+			 *  its original value.
+			 */
+			memcpy( &io_new_psw, &lc->io_new_psw, sizeof(psw_t));
+
+			ccode = iac();
+
+			switch (ccode) {
+			case 0:  		// primary-space
+				io_sync_wait.mask =   _IO_PSW_MASK
+				                    | _PSW_PRIM_SPACE_MODE
+				                    | _PSW_IO_WAIT;
+				break;
+			case 1:			// secondary-space
+				io_sync_wait.mask =   _IO_PSW_MASK
+				                    | _PSW_SEC_SPACE_MODE
+				                    | _PSW_IO_WAIT;
+				break;
+			case 2:			// access-register
+				io_sync_wait.mask =   _IO_PSW_MASK
+				                    | _PSW_ACC_REG_MODE
+				                    | _PSW_IO_WAIT;
+				break;
+			case 3:			// home-space	
+				io_sync_wait.mask =   _IO_PSW_MASK
+				                    | _PSW_HOME_SPACE_MODE
+				                    | _PSW_IO_WAIT;
+				break;
+			default:
+				panic( "start_IO() : unexpected "
+				       "address-space-control %d\n",
+				       ccode);
+				break;
+			} /* endswitch */
+
+			io_sync_wait.addr = FIX_PSW(&&io_wakeup);
+
+			/*
+			 * Martin didn't like modifying the new PSW, now we take
+			 *  a fast exit in do_IRQ() instead
+			 */
+			*(__u32 *)__LC_SYNC_IO_WORD  = 1;
+
+			asm volatile ("STCK %0" : "=m" (time_start));
+
+			time_start = time_start >> 32;
+
+			do
+			{
+				if ( flag & DOIO_TIMEOUT )
+				{
+					tpi_info_t tpi_info={0,};
+
+					do
+					{
+						if ( tpi(&tpi_info) == 1 )
+						{
+							io_sub = tpi_info.irq;
+							break;
+						}
+						else
+						{
+							udelay(100); /* usecs */
+							asm volatile ("STCK %0" : "=m" (time_curr));
+
+							if ( ((time_curr >> 32) - time_start ) >= 3 )
+								do_retry = 0;          							
+
+						} /* endif */
+				
+					} while ( do_retry );
+				}
+				else
+				{
+					__load_psw( io_sync_wait );
+
+io_wakeup:
+					io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
+
+				} /* endif */
+
+ 				if ( do_retry )
+					ready = s390_process_IRQ( io_sub );
+
+				/*
+				 * surrender when retry count's exceeded ...
+				 */
+			} while ( !(     ( io_sub == irq )
+			              && ( ready  == 1   ))
+			            && do_retry             );
+
+			*(__u32 *)__LC_SYNC_IO_WORD = 0;
+
+			if ( !do_retry )
+				ret = -ETIMEDOUT;
+
+		} /* endif */
+
+		break;
+
+	case 1 :            /* status pending */
+
+		ioinfo[irq]->devstat.flag =   DEVSTAT_START_FUNCTION
+		                            | DEVSTAT_STATUS_PENDING;
+
+		/*
+		 * initialize the device driver specific devstat irb area
+		 */
+		memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
+		        '\0', sizeof( irb_t) );
+
+		/*
+		 * Let the common interrupt handler process the pending status.
+		 *  However, we must avoid calling the user action handler, as
+		 *  it won't be prepared to handle a pending status during
+		 *  do_IO() processing inline. This also implies that process_IRQ
+		 *  must terminate synchronously - especially if device sensing
+		 *  is required.
+		 */
+		ioinfo[irq]->ui.flags.s_pend   = 1;
+		ioinfo[irq]->ui.flags.busy     = 1;
+		ioinfo[irq]->ui.flags.doio     = 1;
+
+		s390_process_IRQ( irq );
+
+		ioinfo[irq]->ui.flags.s_pend   = 0;
+		ioinfo[irq]->ui.flags.busy     = 0;
+		ioinfo[irq]->ui.flags.doio     = 0;
+
+		ioinfo[irq]->ui.flags.repall   = 0;
+		ioinfo[irq]->ui.flags.w4final  = 0;
+
+		ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
+
+		/*
+		 * In multipath mode a condition code 3 implies the last path
+		 *  has gone, except we have previously restricted the I/O to
+		 *  a particular path. A condition code 1 (0 won't occur)
+		 *  results in return code EIO as well as 3 with another path
+		 *  than the one used (i.e. path available mask is non-zero).
+		 */
+		if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
+		{
+			if ( flag & DOIO_VALID_LPM )
+			{
+				ioinfo[irq]->opm &= ~(ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum);
+			}
+			else
+			{
+				ioinfo[irq]->opm = 0;
+
+			} /* endif */
+	
+			if ( ioinfo[irq]->opm == 0 ) 	
+			{
+				ret                         = -ENODEV;
+				ioinfo[irq]->ui.flags.oper  = 0;
+         }
+			else
+			{
+				ret = -EIO;
+
+         } /* endif */
+
+			ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
+
+#ifdef CONFIG_DEBUG_IO
+			{
+			char buffer[80];
+
+			stsch(irq, &(ioinfo[irq]->schib) );
+
+			sprintf( buffer, "s390_start_IO(%04X) - irb for "
+			         "device %04X, after status pending\n",
+			         irq,
+			         ioinfo[irq]->devstat.devno );
+
+			s390_displayhex( buffer,
+			                 &(ioinfo[irq]->devstat.ii.irb) ,
+			                 sizeof(irb_t));
+
+			sprintf( buffer, "s390_start_IO(%04X) - schib for "
+			         "device %04X, after status pending\n",
+			         irq,
+			         ioinfo[irq]->devstat.devno );
+
+			s390_displayhex( buffer,
+			                 &(ioinfo[irq]->schib) ,
+			                 sizeof(schib_t));
+
+
+			if (ioinfo[irq]->devstat.flag & DEVSTAT_FLAG_SENSE_AVAIL)
+			{
+				sprintf( buffer, "s390_start_IO(%04X) - sense "
+				         "data for "
+				         "device %04X, after status pending\n",
+				         irq,
+				         ioinfo[irq]->devstat.devno );
+
+				s390_displayhex( buffer,
+		((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->ii.sense.data,
+		((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->rescnt);
+
+			} /* endif */
+			}
+#endif
+		}
+		else
+		{
+			ret                         = -EIO;
+			ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
+			ioinfo[irq]->ui.flags.oper  = 1;
+
+		} /* endif */
+
+		break;
+
+	case 2 :            /* busy */
+
+		ret = -EBUSY;
+		break;
+
+	default:            /* device/path not operational */
+		
+		if ( flag & DOIO_VALID_LPM )
+		{
+			ioinfo[irq]->opm &= ~lpm;
+		}
+		else
+		{
+			ioinfo[irq]->opm = 0;
+
+		} /* endif */
+	
+		if ( ioinfo[irq]->opm == 0 ) 	
+		{
+			ioinfo[irq]->ui.flags.oper  = 0;
+			ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
+
+		} /* endif */
+
+		ret = -ENODEV;
+
+		memcpy( ioinfo[irq]->irq_desc.action->dev_id,
+		        &(ioinfo[irq]->devstat),
+		        sizeof( devstat_t) );
+
+#ifdef CONFIG_DEBUG_IO
+		{
+			char buffer[80];
+
+   			stsch(irq, &(ioinfo[irq]->schib) );
+
+			sprintf( buffer, "s390_start_IO(%04X) - schib for "
+			         "device %04X, after 'not oper' status\n",
+			         irq,
+			         ioinfo[irq]->devstat.devno );
+
+			s390_displayhex( buffer,
+			                 &(ioinfo[irq]->schib),
+			                 sizeof(schib_t));
+      	}
+#endif
+		break;
+
+	} /* endswitch */
+
+	if ( flag & DOIO_WAIT_FOR_INTERRUPT)
+	{
+		disable_cpu_sync_isc( irq );
+
+	} /* endif */
+
+	if ( flag & DOIO_DONT_CALL_INTHDLR )
+	{
+		ioinfo[irq]->ui.flags.repnone = 0;
+
+   } /* endif */
+
+	return( ret);
+}
+
+int do_IO( int            irq,          /* IRQ */
+           ccw1_t        *cpa,          /* channel program address */
+           unsigned long  user_intparm, /* interruption parameter */
+           __u8           lpm,          /* logical path mask */
+           unsigned long  flag)         /* flags : see above */
+{
+	int ret = 0;
+
+	if ( irq > highest_subchannel || irq < 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
+	/* handler registered ? or free_irq() in process already ? */
+	if ( !ioinfo[irq]->ui.flags.ready || ioinfo[irq]->ui.flags.unready )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	/*
+	 * Note: We ignore the device operational status - if not operational,
+	 *        the SSCH will lead to an -ENODEV condition ...
+	 */
+	if ( !ioinfo[irq]->ui.flags.busy )         /* last I/O completed ? */
+	{
+		ret = s390_start_IO( irq, cpa, user_intparm, lpm, flag);
+	}
+	else if ( ioinfo[irq]->ui.flags.fast )
+	{
+		/*
+		 * If primary status was received and ending status is missing,
+		 *  the device driver won't be notified on the ending status
+		 *  if early (fast) interrupt notification was requested.
+		 *  Therefore we have to queue the next incoming request. If
+		 *  halt_IO() is issued while there is a request queued, a HSCH
+		 *  needs to be issued and the queued request must be deleted
+		 *  but its intparm must be returned (see halt_IO() processing)
+		 */
+		if (     ioinfo[irq]->ui.flags.w4final
+           && !ioinfo[irq]->ui.flags.doio_q )
+		{
+			ioinfo[irq]->qflag    = flag;
+			ioinfo[irq]->qcpa     = cpa;
+			ioinfo[irq]->qintparm = user_intparm;
+			ioinfo[irq]->qlpm     = lpm;
+		}
+		else
+		{
+			ret = -EBUSY;
+
+		} /* endif */
+	}
+	else
+	{
+		ret = -EBUSY;
+
+	} /* endif */
+
+	return( ret );
+
+}
+
+/*
+ * resume suspended I/O operation
+ */
+int resume_IO( int irq)
+{
+	int ret = 0;
+
+	if ( irq > highest_subchannel || irq < 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+	}
+
+	/*
+	 * We allow for 'resume' requests only for active I/O operations
+	 */
+	if ( ioinfo[irq]->ui.flags.busy )
+	{
+		int ccode;
+
+		ccode = rsch( irq);
+
+		switch (ccode) {
+		case 0 :
+			break;
+
+		case 1 :
+		  	s390_process_IRQ( irq );
+			ret = -EBUSY;
+			break;
+
+		case 2 :
+			ret = -EINVAL;
+			break;
+
+		case 3 :
+			/*
+			 * useless to wait for request completion
+			 *  as device is no longer operational !
+			 */
+			ioinfo[irq]->ui.flags.oper = 0;
+			ioinfo[irq]->ui.flags.busy = 0;
+			ret                        = -ENODEV;
+			break;
+
+		} /* endswitch */          	
+		
+	}
+	else
+	{
+		ret = -ENOTCONN;
+
+	} /* endif  */
+
+	return( ret);
+}
+
+/*
+ * Note: The "intparm" parameter is not used by the halt_IO() function
+ *       itself, as no ORB is built for the HSCH instruction. However,
+ *       it allows the device interrupt handler to associate the upcoming
+ *       interrupt with the halt_IO() request.
+ */
+int halt_IO( int           irq,
+             unsigned long user_intparm,
+             unsigned long flag)  /* possible DOIO_WAIT_FOR_INTERRUPT */
+{
+	int            ret;
+	int            ccode;
+
+	if ( irq > highest_subchannel || irq < 0 )
+	{
+		ret = -ENODEV;
+	}
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
+	/*
+	 * we only allow for halt_IO if the device has an I/O handler associated
+	 */
+	else if ( !ioinfo[irq]->ui.flags.ready )
+	{
+		ret = -ENODEV;
+	}
+	/*
+	 * we ignore the halt_io() request if ending_status was received but
+	 *  a SENSE operation is waiting for completion.
+	 */
+	else if ( ioinfo[irq]->ui.flags.w4sense )
+	{
+		ret = 0;
+	}
+	/*
+	 * We don't allow for halt_io with a sync do_IO() requests pending.
+	 */
+	else if (    ioinfo[irq]->ui.flags.syncio
+	          && (flag & DOIO_WAIT_FOR_INTERRUPT))
+	{
+		ret = -EBUSY;
+	}
+	else
+	{
+		/*
+		 * If sync processing was requested we lock the sync ISC,
+		 *  modify the device to present interrupts for this ISC only
+		 *  and switch the CPU to handle this ISC + the console ISC
+		 *  exclusively.
+		 */
+		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+		{
+			ret = enable_cpu_sync_isc( irq);
+
+			if ( ret )
+			{
+				return( ret);
+  	
+			} /* endif */
+
+		} /* endif */
+
+		/*
+		 * Issue "Halt subchannel" and process condition code
+		 */
+		ccode = hsch( irq );
+
+		switch ( ccode ) {
+		case 0:
+
+			ioinfo[irq]->ui.flags.haltio = 1;
+
+			if ( !ioinfo[irq]->ui.flags.doio )
+			{
+				ioinfo[irq]->ui.flags.busy   = 1;
+				ioinfo[irq]->u_intparm       = user_intparm;
+				ioinfo[irq]->devstat.cstat   = 0;
+				ioinfo[irq]->devstat.dstat   = 0;
+				ioinfo[irq]->devstat.lpum    = 0;
+				ioinfo[irq]->devstat.flag    = DEVSTAT_HALT_FUNCTION;
+				ioinfo[irq]->devstat.scnt    = 0;
+
+			}
+			else
+			{
+				ioinfo[irq]->devstat.flag   |= DEVSTAT_HALT_FUNCTION;
+
+			} /* endif */
+
+			/*
+			 * If synchronous I/O processing is requested, we have
+			 *  to wait for the corresponding interrupt to occur by
+			 *  polling the interrupt condition. However, as multiple
+			 *  interrupts may be outstanding, we must not just wait
+			 *  for the first interrupt, but must poll until ours
+			 *  pops up.
+			 */
+			if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+			{
+				int              io_sub;
+				__u32            io_parm;
+				psw_t            io_new_psw;
+				int              ccode;
+  	
+				int              ready = 0;
+				struct _lowcore *lc    = NULL;
+
+				/*
+				 * We shouldn't perform a TPI loop, waiting for
+				 *  an interrupt to occur, but should load a
+				 *  WAIT PSW instead. Otherwise we may keep the
+				 *  channel subsystem busy, not able to present
+				 *  the interrupt. When our sync. interrupt
+				 *  arrived we reset the I/O old PSW to its
+				 *  original value.
+				 */
+				memcpy( &io_new_psw,
+				        &lc->io_new_psw,
+				        sizeof(psw_t));
+
+				ccode = iac();
+
+				switch (ccode) {
+				case 0:  		// primary-space
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_PRIM_SPACE_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				case 1:			// secondary-space
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_SEC_SPACE_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				case 2:			// access-register
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_ACC_REG_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				case 3:			// home-space	
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_HOME_SPACE_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				default:
+					panic( "halt_IO() : unexpected "
+					       "address-space-control %d\n",
+					       ccode);
+					break;
+				} /* endswitch */
+
+				io_sync_wait.addr = FIX_PSW(&&hio_wakeup);
+
+				/*
+				 * Martin didn't like modifying the new PSW, now we take
+				 *  a fast exit in do_IRQ() instead
+				 */
+				*(__u32 *)__LC_SYNC_IO_WORD  = 1;
+
+				do
+				{
+
+					__load_psw( io_sync_wait );
+hio_wakeup:
+				   io_parm = *(__u32 *)__LC_IO_INT_PARM;
+				   io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
+
+				   ready = s390_process_IRQ( io_sub );
+
+				} while ( !((io_sub == irq) && (ready == 1)) );
+
+				*(__u32 *)__LC_SYNC_IO_WORD = 0;
+
+			} /* endif */
+
+			ret = 0;
+			break;
+
+		case 1 :            /* status pending */
+	
+			ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
+
+			/*
+			 * initialize the device driver specific devstat irb area
+			 */
+			memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
+			        '\0', sizeof( irb_t) );
+
+			/*
+			 * Let the common interrupt handler process the pending
+			 *  status. However, we must avoid calling the user
+			 *  action handler, as it won't be prepared to handle
+                        *  a pending status during do_IO() processing inline.
+			 *  This also implies that s390_process_IRQ must
+			 *  terminate synchronously - especially if device
+			 *  sensing is required.
+			 */
+			ioinfo[irq]->ui.flags.s_pend   = 1;
+			ioinfo[irq]->ui.flags.busy     = 1;
+			ioinfo[irq]->ui.flags.doio     = 1;
+
+			s390_process_IRQ( irq );
+			
+			ioinfo[irq]->ui.flags.s_pend   = 0;
+			ioinfo[irq]->ui.flags.busy     = 0;
+			ioinfo[irq]->ui.flags.doio     = 0;
+			ioinfo[irq]->ui.flags.repall   = 0;
+			ioinfo[irq]->ui.flags.w4final  = 0;
+
+			ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
+
+			/*
+			 * In multipath mode a condition code 3 implies the last
+			 *  path has gone, except we have previously restricted
+			 *  the I/O to a particular path. A condition code 1
+			 *  (0 won't occur) results in return code EIO as well
+			 *  as 3 with another path than the one used (i.e. path available mask is non-zero).
+			 */
+			if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
+			{
+				ret                         = -ENODEV;
+				ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
+				ioinfo[irq]->ui.flags.oper  = 0;
+			}
+			else
+			{
+				ret                         = -EIO;
+				ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
+				ioinfo[irq]->ui.flags.oper  = 1;
+
+			} /* endif */
+
+			break;
+
+		case 2 :            /* busy */
+
+			ret = -EBUSY;
+			break;
+
+		default:            /* device not operational */
+
+			ret = -ENODEV;
+			break;
+
+		} /* endswitch */
+
+		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+		{
+			disable_cpu_sync_isc( irq );
+
+		} /* endif */
+
+	} /* endif */
+
+	return( ret );
+}
+
+/*
+ * Note: The "intparm" parameter is not used by the clear_IO() function
+ *       itself, as no ORB is built for the CSCH instruction. However,
+ *       it allows the device interrupt handler to associate the upcoming
+ *       interrupt with the clear_IO() request.
+ */
+int clear_IO( int           irq,
+              unsigned long user_intparm,
+              unsigned long flag)  /* possible DOIO_WAIT_FOR_INTERRUPT */
+{
+	int            ret;
+	int            ccode;
+
+	if ( irq > highest_subchannel || irq < 0 )
+	{
+		ret = -ENODEV;
+	}
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
+	/*
+	 * we only allow for halt_IO if the device has an I/O handler associated
+	 */
+	else if ( !ioinfo[irq]->ui.flags.ready )
+	{
+		ret = -ENODEV;
+	}
+	/*
+	 * we ignore the halt_io() request if ending_status was received but
+	 *  a SENSE operation is waiting for completion.
+	 */
+	else if ( ioinfo[irq]->ui.flags.w4sense )
+	{
+		ret = 0;
+	}
+	/*
+	 * We don't allow for halt_io with a sync do_IO() requests pending.
+	 *  Concurrent I/O is possible in SMP environments only, but the
+	 *  sync. I/O request can be gated to one CPU at a time only.
+	 */
+	else if ( ioinfo[irq]->ui.flags.syncio )
+	{
+		ret = -EBUSY;
+	}
+	else
+	{
+		/*
+		 * If sync processing was requested we lock the sync ISC,
+		 *  modify the device to present interrupts for this ISC only
+		 *  and switch the CPU to handle this ISC + the console ISC
+		 *  exclusively.
+		 */
+		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+		{
+			ret = enable_cpu_sync_isc( irq);
+
+			if ( ret )
+			{
+				return( ret);
+  	
+			} /* endif */
+
+		} /* endif */
+
+		/*
+		 * Issue "Halt subchannel" and process condition code
+		 */
+		ccode = csch( irq );
+
+		switch ( ccode ) {
+		case 0:
+
+			ioinfo[irq]->ui.flags.haltio = 1;
+
+			if ( !ioinfo[irq]->ui.flags.doio )
+			{
+				ioinfo[irq]->ui.flags.busy   = 1;
+				ioinfo[irq]->u_intparm       = user_intparm;
+				ioinfo[irq]->devstat.cstat   = 0;
+				ioinfo[irq]->devstat.dstat   = 0;
+				ioinfo[irq]->devstat.lpum    = 0;
+				ioinfo[irq]->devstat.flag    = DEVSTAT_CLEAR_FUNCTION;
+				ioinfo[irq]->devstat.scnt    = 0;
+
+			}
+			else
+			{
+				ioinfo[irq]->devstat.flag   |= DEVSTAT_CLEAR_FUNCTION;
+
+			} /* endif */
+
+			/*
+			 * If synchronous I/O processing is requested, we have
+			 *  to wait for the corresponding interrupt to occur by
+			 *  polling the interrupt condition. However, as multiple
+			 *  interrupts may be outstanding, we must not just wait
+			 *  for the first interrupt, but must poll until ours
+			 *  pops up.
+			 */
+			if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+			{
+				int              io_sub;
+				__u32            io_parm;
+				psw_t            io_new_psw;
+				int              ccode;
+  	
+				int              ready = 0;
+				struct _lowcore *lc    = NULL;
+
+				/*
+				 * We shouldn't perform a TPI loop, waiting for
+				 *  an interrupt to occur, but should load a
+				 *  WAIT PSW instead. Otherwise we may keep the
+				 *  channel subsystem busy, not able to present
+				 *  the interrupt. When our sync. interrupt
+				 *  arrived we reset the I/O old PSW to its
+				 *  original value.
+				 */
+				memcpy( &io_new_psw,
+				        &lc->io_new_psw,
+				        sizeof(psw_t));
+
+				ccode = iac();
+
+				switch (ccode) {
+				case 0:  		// primary-space
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_PRIM_SPACE_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				case 1:			// secondary-space
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_SEC_SPACE_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				case 2:			// access-register
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_ACC_REG_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				case 3:			// home-space	
+					io_sync_wait.mask =   _IO_PSW_MASK
+					                    | _PSW_HOME_SPACE_MODE
+					                    | _PSW_IO_WAIT;
+					break;
+				default:
+					panic( "halt_IO() : unexpected "
+					       "address-space-control %d\n",
+					       ccode);
+					break;
+				} /* endswitch */
+
+				io_sync_wait.addr = FIX_PSW(&&cio_wakeup);
+
+				/*
+				 * Martin didn't like modifying the new PSW, now we take
+				 *  a fast exit in do_IRQ() instead
+				 */
+				*(__u32 *)__LC_SYNC_IO_WORD  = 1;
+
+				do
+				{
+
+					__load_psw( io_sync_wait );
+cio_wakeup:
+				   io_parm = *(__u32 *)__LC_IO_INT_PARM;
+				   io_sub  = (__u32)*(__u16 *)__LC_SUBCHANNEL_NR;
+
+				   ready = s390_process_IRQ( io_sub );
+
+				} while ( !((io_sub == irq) && (ready == 1)) );
+
+				*(__u32 *)__LC_SYNC_IO_WORD = 0;
+
+			} /* endif */
+
+			ret = 0;
+			break;
+
+		case 1 :            /* status pending */
+	
+			ioinfo[irq]->devstat.flag |= DEVSTAT_STATUS_PENDING;
+
+			/*
+			 * initialize the device driver specific devstat irb area
+			 */
+			memset( &((devstat_t *) ioinfo[irq]->irq_desc.action->dev_id)->ii.irb,
+			        '\0', sizeof( irb_t) );
+
+			/*
+			 * Let the common interrupt handler process the pending
+			 *  status. However, we must avoid calling the user
+			 *  action handler, as it won't be prepared to handle
+                        *  a pending status during do_IO() processing inline.
+			 *  This also implies that s390_process_IRQ must
+			 *  terminate synchronously - especially if device
+			 *  sensing is required.
+			 */
+			ioinfo[irq]->ui.flags.s_pend   = 1;
+			ioinfo[irq]->ui.flags.busy     = 1;
+			ioinfo[irq]->ui.flags.doio     = 1;
+
+			s390_process_IRQ( irq );
+			
+			ioinfo[irq]->ui.flags.s_pend   = 0;
+			ioinfo[irq]->ui.flags.busy     = 0;
+			ioinfo[irq]->ui.flags.doio     = 0;
+			ioinfo[irq]->ui.flags.repall   = 0;
+			ioinfo[irq]->ui.flags.w4final  = 0;
+
+			ioinfo[irq]->devstat.flag     |= DEVSTAT_FINAL_STATUS;
+
+			/*
+			 * In multipath mode a condition code 3 implies the last
+			 *  path has gone, except we have previously restricted
+			 *  the I/O to a particular path. A condition code 1
+			 *  (0 won't occur) results in return code EIO as well
+			 *  as 3 with another path than the one used (i.e. path available mask is non-zero).
+			 */
+			if ( ioinfo[irq]->devstat.ii.irb.scsw.cc == 3 )
+			{
+				ret                         = -ENODEV;
+				ioinfo[irq]->devstat.flag  |= DEVSTAT_NOT_OPER;
+				ioinfo[irq]->ui.flags.oper  = 0;
+			}
+			else
+			{
+				ret                         = -EIO;
+				ioinfo[irq]->devstat.flag  &= ~DEVSTAT_NOT_OPER;
+				ioinfo[irq]->ui.flags.oper  = 1;
+
+			} /* endif */
+
+			break;
+
+		case 2 :            /* busy */
+
+			ret = -EBUSY;
+			break;
+
+		default:            /* device not operational */
+
+			ret = -ENODEV;
+			break;
+
+		} /* endswitch */
+
+		if ( flag & DOIO_WAIT_FOR_INTERRUPT )
+		{
+			disable_cpu_sync_isc( irq );
+
+		} /* endif */
+
+	} /* endif */
+
+	return( ret );
+}
+
+
+/*
+ * do_IRQ() handles all normal I/O device IRQ's (the special
+ *          SMP cross-CPU interrupts have their own specific
+ *          handlers).
+ *
+ */
+asmlinkage void do_IRQ( struct pt_regs regs )
+{
+	/*
+	 * Get interrupt info from lowcore
+	 */
+	volatile tpi_info_t *tpi_info = (tpi_info_t*)(__LC_SUBCHANNEL_ID);
+
+	/*
+	 * take fast exit if CPU is in sync. I/O state
+	 *
+	 * Note: we have to turn off the WAIT bit and re-disable
+	 *       interrupts prior to return as this was the initial
+	 *       entry condition to synchronous I/O.
+	 */
+ 	if (    *(__u32 *)__LC_SYNC_IO_WORD )
+	{
+		regs.psw.mask &= ~(_PSW_WAIT_MASK_BIT | _PSW_IO_MASK_BIT);
+		return;
+	} /* endif */
+
+	
+#ifdef CONFIG_FAST_IRQ
+	do {
+#endif /*  CONFIG_FAST_IRQ */
+		
+		/*
+		 * Non I/O-subchannel thin interrupts are processed differently
+		 */
+		if ( tpi_info->adapter_IO == 1 &&
+		     tpi_info->int_type == IO_INTERRUPT_TYPE )
+		{
+			do_adapter_IO( tpi_info->intparm );
+		} 
+		else 
+		{
+			unsigned int irq = tpi_info->irq;
+	
+			/*
+			 * fix me !!!
+			 *
+			 * instead of boxing the device, we need to schedule device
+			 * recognition, the interrupt stays pending. We need to
+			 * dynamically allocate an ioinfo structure, etc..
+			 */
+			if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+			{
+				return;	/* this keeps the device boxed ... */
+			}
+	
+			s390irq_spin_lock( irq );
+			s390_process_IRQ( irq );
+			s390irq_spin_unlock( irq );
+		}
+
+#ifdef CONFIG_FAST_IRQ
+
+		/*
+		 * Are more interrupts pending?
+		 * If so, the tpi instruction will update the lowcore 
+		 * to hold the info for the next interrupt.
+		 */
+	} while ( tpi( NULL ) != 0 );
+
+#endif /*  CONFIG_FAST_IRQ */
+
+	return;
+}
+
+
+/*
+ * s390_process_IRQ() handles status pending situations and interrupts
+ *
+ * Called by : do_IRQ()             - for "real" interrupts
+ *             s390_start_IO, halt_IO()
+ *                                  - status pending cond. after SSCH, or HSCH
+ *             disable_subchannel() - status pending conditions (after MSCH)
+ *
+ * Returns: 0 - no ending status received, no further action taken
+ *          1 - interrupt handler was called with ending status
+ */
+int s390_process_IRQ( unsigned int irq )
+{
+	int                    ccode;      /* cond code from tsch() operation */
+	int                    irb_cc;     /* cond code from irb */
+	int                    sdevstat;   /* struct devstat size to copy */
+	unsigned int           fctl;       /* function control */
+	unsigned int           stctl;      /* status   control */
+	unsigned int           actl;       /* activity control */
+	struct s390_irqaction *action;
+	struct pt_regs         regs;       /* for interface compatibility only */
+
+	int               issense         = 0;
+	int               ending_status   = 0;
+	int               allow4handler   = 1;
+	int               chnchk          = 0;
+	devstat_t        *dp;
+#if 0
+	int               cpu             = smp_processor_id();
+
+	kstat.irqs[cpu][irq]++;
+#endif
+
+	if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		/* we can't properly process the interrupt ... */
+		tsch( irq, p_init_irb );
+		return( 1 );
+
+	} /* endif */
+
+	action = ioinfo[irq]->irq_desc.action;
+	dp     = &ioinfo[irq]->devstat;
+	
+
+#ifdef CONFIG_DEBUG_IO
+	/*
+	 * It might be possible that a device was not-oper. at the time
+	 *  of free_irq() processing. This means the handler is no longer
+	 *  available when the device possibly becomes ready again. In
+	 *  this case we perform delayed disable_subchannel() processing.
+	 */
+	if ( action == NULL )
+	{
+		if ( !ioinfo[irq]->ui.flags.d_disable )
+		{
+			printk( KERN_CRIT"s390_process_IRQ(%04X) "
+			        "- no interrupt handler registered "
+					  "for device %04X !\n",
+			        irq,
+			        ioinfo[irq]->devstat.devno);
+
+		} /* endif */
+
+	} /* endif */
+#endif
+
+	/*
+	 * retrieve the i/o interrupt information (irb),
+	 *  update the device specific status information
+	 *  and possibly call the interrupt handler.
+	 *
+	 * Note 1: At this time we don't process the resulting
+	 *         condition code (ccode) from tsch(), although
+	 *         we probably should.
+	 *
+	 * Note 2: Here we will have to check for channel
+	 *         check conditions and call a channel check
+	 *         handler.
+	 *
+	 * Note 3: If a start function was issued, the interruption
+	 *         parameter relates to it. If a halt function was
+	 *         issued for an idle device, the intparm must not
+	 *         be taken from lowcore, but from the devstat area.
+	 */
+	ccode = tsch( irq, &(dp->ii.irb) );
+
+	//
+	// We must only accumulate the status if the device is busy already
+	//
+	if ( ioinfo[irq]->ui.flags.busy )
+	{
+		dp->dstat   |= dp->ii.irb.scsw.dstat;
+		dp->cstat   |= dp->ii.irb.scsw.cstat;
+                dp->intparm  = ioinfo[irq]->u_intparm;
+
+	}
+	else
+	{
+		dp->dstat    = dp->ii.irb.scsw.dstat;
+		dp->cstat    = dp->ii.irb.scsw.cstat;
+
+		dp->flag     = 0;   // reset status flags
+		dp->intparm  = 0;
+
+	} /* endif */
+
+	dp->lpum = dp->ii.irb.esw.esw1.lpum;
+
+	/*
+	 * reset device-busy bit if no longer set in irb
+	 */
+	if (    (dp->dstat & DEV_STAT_BUSY                   ) 
+	     && ((dp->ii.irb.scsw.dstat & DEV_STAT_BUSY) == 0))
+	{
+		dp->dstat &= ~DEV_STAT_BUSY;
+
+	} /* endif */
+
+	/*
+	 * Save residual count and CCW information in case primary and
+	 *  secondary status are presented with different interrupts.
+	 */
+	if ( dp->ii.irb.scsw.stctl
+	           & (   SCSW_STCTL_PRIM_STATUS | SCSW_STCTL_INTER_STATUS ) )
+	{
+		dp->rescnt = dp->ii.irb.scsw.count;
+		dp->cpa    = dp->ii.irb.scsw.cpa;
+
+#ifdef CONFIG_DEBUG_IO
+		if ( irq != cons_dev )
+			printk( "s390_process_IRQ( %04X ) : "
+			        "residual count from irb after tsch() %d\n",
+			        irq, dp->rescnt );
+#endif
+
+	} /* endif */
+
+	irb_cc = dp->ii.irb.scsw.cc;
+
+	//
+	// check for any kind of channel or interface control check but don't
+	//  issue the message for the console device
+	//
+	if (    (dp->ii.irb.scsw.cstat
+	            & (  SCHN_STAT_CHN_DATA_CHK
+	               | SCHN_STAT_CHN_CTRL_CHK
+	               | SCHN_STAT_INTF_CTRL_CHK )       )
+	     && (irq != cons_dev                         ) )
+	{
+		printk( "Channel-Check or Interface-Control-Check "
+		        "received\n"
+		        " ... device %04X on subchannel %04X, dev_stat "
+		        ": %02X sch_stat : %02X\n",
+		        ioinfo[irq]->devstat.devno,
+		        irq,
+		        dp->dstat,
+		        dp->cstat);
+
+		chnchk = 1;
+
+	} /* endif */
+
+	if (    (dp->ii.irb.scsw.stctl == SCSW_STCTL_STATUS_PEND)
+	     &&	(dp->ii.irb.scsw.eswf  == 0                     ))
+	{
+		issense = 0;
+	}
+	else if (    (dp->ii.irb.scsw.stctl ==
+	                (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_INTER_STATUS)) 
+	          && ((dp->ii.irb.scsw.actl & SCSW_ACTL_SUSPENDED) == 0))
+	{
+		issense = 0;
+	}
+	else
+	{
+		issense = dp->ii.irb.esw.esw0.erw.cons;
+
+	} /* endif */
+
+	if ( issense )
+	{
+		dp->scnt  = dp->ii.irb.esw.esw0.erw.scnt;
+		dp->flag |= DEVSTAT_FLAG_SENSE_AVAIL;
+                  	
+		sdevstat = sizeof( devstat_t);
+
+#ifdef CONFIG_DEBUG_IO
+		if ( irq != cons_dev )
+			printk( "s390_process_IRQ( %04X ) : "
+			        "concurrent sense bytes avail %d\n",
+			        irq, dp->scnt );
+#endif
+	}
+	else
+	{
+		/* don't copy the sense data area ! */
+		sdevstat = sizeof( devstat_t) - SENSE_MAX_COUNT;
+
+	} /* endif */
+
+	switch ( irb_cc ) {
+	case 1:      /* status pending */
+
+		dp->flag |= DEVSTAT_STATUS_PENDING;
+
+	case 0:      /* normal i/o interruption */
+
+		fctl  = dp->ii.irb.scsw.fctl;
+		stctl = dp->ii.irb.scsw.stctl;
+		actl  = dp->ii.irb.scsw.actl;
+
+		if ( chnchk )
+		{
+			char buffer[80];
+   	
+			sprintf( buffer, "s390_process_IRQ(%04X) - irb for "
+			         "device %04X after channel check\n",
+			         irq,
+			         dp->devno );
+
+			s390_displayhex( buffer,
+			                 &(dp->ii.irb) ,
+			                 sizeof(irb_t));
+		} /* endif */
+			
+		ioinfo[irq]->stctl |= stctl;
+
+		ending_status =    ( stctl & SCSW_STCTL_SEC_STATUS                          )
+			|| ( stctl == (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)         )
+		   || ( (fctl == SCSW_FCTL_HALT_FUNC)  && (stctl == SCSW_STCTL_STATUS_PEND) )
+		   || ( (fctl == SCSW_FCTL_CLEAR_FUNC) && (stctl == SCSW_STCTL_STATUS_PEND) );
+
+		/*
+		 * Check for unsolicited interrupts - for debug purposes only
+		 *
+		 * We only consider an interrupt as unsolicited, if the device was not
+		 *  actively in use (busy) and an interrupt other than an ALERT status
+		 *  was received.
+		 *
+		 * Note: We must not issue a message to the console, if the
+		 *       unsolicited interrupt applies to the console device
+		 *       itself !
+		 */
+#ifdef CONFIG_DEBUG_IO
+		if (     ( irq != cons_dev                 )
+			 && !( stctl & SCSW_STCTL_ALERT_STATUS )
+			 &&  ( ioinfo[irq]->ui.flags.busy == 0  ) )
+		{
+			char buffer[80];
+
+			printk( "Unsolicited interrupt received for device %04X on subchannel %04X\n"
+				" ... device status : %02X subchannel status : %02X\n",
+				dp->devno,
+				irq,
+				dp->dstat,
+				dp->cstat);
+
+			sprintf( buffer, "s390_process_IRQ(%04X) - irb for "
+			         "device %04X, ending_status %d\n",
+			         irq,
+			         dp->devno,
+			         ending_status);
+
+			s390_displayhex( buffer,
+			                 &(dp->ii.irb) ,
+			                 sizeof(irb_t));
+
+		} /* endif */
+
+#endif
+		/*
+		 * take fast exit if no handler is available
+		 */
+		if ( !action )
+			return( ending_status );     		
+
+		/*
+		 * Check whether we must issue a SENSE CCW ourselves if there is no
+		 *  concurrent sense facility installed for the subchannel.
+		 *
+		 * Note: We should check for ioinfo[irq]->ui.flags.consns but VM
+		 *       violates the ESA/390 architecture and doesn't present an
+		 *       operand exception for virtual devices without concurrent
+		 *       sense facility available/supported when enabling the
+       *       concurrent sense facility.
+		 */
+		if (    (    (dp->ii.irb.scsw.dstat & DEV_STAT_UNIT_CHECK )
+		          && (!issense                                    ) )
+		     || (ioinfo[irq]->ui.flags.delsense && ending_status    ) )
+		{
+			int            ret_io;
+			ccw1_t        *s_ccw  = &ioinfo[irq]->senseccw;
+			unsigned long  s_flag = 0;
+
+			if ( ending_status )
+			{
+				/*
+				 * We copy the current status information into the device driver
+				 *  status area. Then we can use the local devstat area for device
+				 *  sensing. When finally calling the IRQ handler we must not overlay
+				 *  the original device status but copy the sense data only.
+				 */
+				memcpy( action->dev_id,
+				        dp,
+				        sizeof( devstat_t) );
+
+				s_ccw->cmd_code = CCW_CMD_BASIC_SENSE;
+				s_ccw->cda      = (__u32)virt_to_phys( ioinfo[irq]->sense_data );
+				s_ccw->count    = SENSE_MAX_COUNT;
+				s_ccw->flags    = CCW_FLAG_SLI;
+
+				/*
+				 * If free_irq() or a sync do_IO/s390_start_IO() is in
+				 *  process we have to sense synchronously
+				 */
+				if ( ioinfo[irq]->ui.flags.unready || ioinfo[irq]->ui.flags.syncio )
+				{
+					s_flag = DOIO_WAIT_FOR_INTERRUPT;
+
+				} /* endif */
+
+				/*
+				 * Reset status info
+				 *
+				 * It does not matter whether this is a sync. or async.
+				 *  SENSE request, but we have to assure we don't call
+				 *  the irq handler now, but keep the irq in busy state.
+				 *  In sync. mode s390_process_IRQ() is called recursively,
+				 *  while in async. mode we re-enter do_IRQ() with the
+				 *  next interrupt.
+				 *
+				 * Note : this may be a delayed sense request !
+				 */
+				allow4handler                  = 0;
+
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
+				ioinfo[irq]->ui.flags.w4final  = 0;
+				ioinfo[irq]->ui.flags.delsense = 0;
+
+				dp->cstat     = 0;
+				dp->dstat     = 0;
+				dp->rescnt    = SENSE_MAX_COUNT;
+
+				ioinfo[irq]->ui.flags.w4sense  = 1;
+			
+				ret_io = s390_start_IO( irq,
+				                        s_ccw,
+				                        0xE2C5D5E2,  // = SENSe
+				                        0,           // n/a
+				                        s_flag);
+			}
+			else
+			{
+				/*
+				 * we received an Unit Check but we have no final
+				 *  status yet, therefore we must delay the SENSE
+				 *  processing. However, we must not report this
+				 *  intermediate status to the device interrupt
+				 *  handler.
+				 */
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
+
+				ioinfo[irq]->ui.flags.delsense = 1;
+				allow4handler                  = 0;
+
+			} /* endif */
+
+		} /* endif */
+
+		/*
+		 * we allow for the device action handler if .
+		 *  - we received ending status
+		 *  - the action handler requested to see all interrupts
+		 *  - we received an intermediate status
+		 *  - fast notification was requested (primary status)
+		 *  - unsollicited interrupts
+		 *
+		 */
+		if ( allow4handler )
+		{
+			allow4handler =    ending_status
+			   || ( ioinfo[irq]->ui.flags.repall                                      )
+			   || ( stctl & SCSW_STCTL_INTER_STATUS                                   )
+				|| ( (ioinfo[irq]->ui.flags.fast ) && (stctl & SCSW_STCTL_PRIM_STATUS) )
+				|| ( ioinfo[irq]->ui.flags.oper == 0                                   );
+
+		} /* endif */
+
+		/*
+		 * We used to copy the device status information right before
+		 *  calling the device action handler. However, in status
+		 *  pending situations during do_IO() or halt_IO(), as well as
+		 *  enable_subchannel/disable_subchannel processing we must
+		 *  synchronously return the status information and must not
+		 *  call the device action handler.
+		 *
+		 */
+		if ( allow4handler )
+		{
+			/*
+			 * if we were waiting for sense data we copy the sense
+			 *  bytes only as the original status information was
+			 *  saved prior to sense already.
+			 */
+			if ( ioinfo[irq]->ui.flags.w4sense )
+			{
+				int sense_count = SENSE_MAX_COUNT-ioinfo[irq]->devstat.rescnt;
+
+#ifdef CONFIG_DEBUG_IO
+      if ( irq != cons_dev )
+         printk( "s390_process_IRQ( %04X ) : "
+                 "BASIC SENSE bytes avail %d\n",
+                 irq, sense_count );
+#endif
+				ioinfo[irq]->ui.flags.w4sense          = 0;
+				((devstat_t *)(action->dev_id))->flag |= DEVSTAT_FLAG_SENSE_AVAIL;
+				((devstat_t *)(action->dev_id))->scnt  = sense_count;
+
+				if ( sense_count >= 0 )
+				{
+					memcpy( ((devstat_t *)(action->dev_id))->ii.sense.data,
+					        &(ioinfo[irq]->sense_data),
+					        sense_count);
+				}
+				else
+				{
+#if 1
+					panic( "s390_process_IRQ(%04x) encountered "
+					       "negative sense count\n",
+					       irq);
+#else
+					printk( KERN_CRIT"s390_process_IRQ(%04x) encountered "
+					        "negative sense count\n",
+					        irq);
+#endif
+				} /* endif */
+			}
+			else
+			{
+				memcpy( action->dev_id, dp, sdevstat );
+
+			}  /* endif */
+
+      } /* endif */
+
+		/*
+		 * for status pending situations other than deferred interrupt
+		 *  conditions detected by s390_process_IRQ() itself we must not
+		 *  call the handler. This will synchronously be reported back
+		 *  to the caller instead, e.g. when detected during do_IO().
+		 */
+		if (    ioinfo[irq]->ui.flags.s_pend
+		     || ioinfo[irq]->ui.flags.unready
+		     || ioinfo[irq]->ui.flags.repnone )
+		{		
+			if ( ending_status )
+			{
+
+				ioinfo[irq]->ui.flags.busy     = 0;
+				ioinfo[irq]->ui.flags.doio     = 0;
+				ioinfo[irq]->ui.flags.haltio   = 0;
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
+				ioinfo[irq]->ui.flags.w4final  = 0;
+
+				dp->flag             |= DEVSTAT_FINAL_STATUS;
+				action->dev_id->flag |= DEVSTAT_FINAL_STATUS;
+
+			} /* endif */
+
+			allow4handler = 0;
+
+		} /* endif */
+
+		/*
+		 * Call device action handler if applicable
+		 */
+		if ( allow4handler )
+		{
+
+			/*
+			 *  We only reset the busy condition when we are sure that no further
+			 *   interrupt is pending for the current I/O request (ending_status).
+			 */
+			if ( ending_status || !ioinfo[irq]->ui.flags.oper )
+			{
+				ioinfo[irq]->ui.flags.oper     = 1;  /* dev IS oper */
+
+				ioinfo[irq]->ui.flags.busy     = 0;
+				ioinfo[irq]->ui.flags.doio     = 0;
+				ioinfo[irq]->ui.flags.haltio   = 0;
+				ioinfo[irq]->ui.flags.fast     = 0;
+				ioinfo[irq]->ui.flags.repall   = 0;
+				ioinfo[irq]->ui.flags.w4final  = 0;
+
+				dp->flag             |= DEVSTAT_FINAL_STATUS;
+				action->dev_id->flag |= DEVSTAT_FINAL_STATUS;
+
+				action->handler( irq, action->dev_id, &regs );
+
+				//
+				// reset intparm after final status or we will badly present unsolicited
+				//  interrupts with a intparm value possibly no longer valid.
+				//
+				dp->intparm   = 0;
+
+				//
+				// Was there anything queued ? Start the pending channel program
+				//  if there is one.
+				//
+				if ( ioinfo[irq]->ui.flags.doio_q )
+				{
+					int ret;
+
+					ret = s390_start_IO( irq,
+					                     ioinfo[irq]->qcpa,
+					                     ioinfo[irq]->qintparm,
+						             ioinfo[irq]->qlpm,
+					                     ioinfo[irq]->qflag);
+
+					ioinfo[irq]->ui.flags.doio_q = 0;
+
+					/*
+					 * If s390_start_IO() failed call the device's interrupt
+					 *  handler, the IRQ related devstat area was setup by
+					 *  s390_start_IO() accordingly already (status pending
+					 *  condition).
+					 */
+					if ( ret )
+					{
+						action->handler( irq, action->dev_id, &regs );
+
+					} /* endif */
+
+				} /* endif */
+
+			}
+			else
+			{
+				ioinfo[irq]->ui.flags.w4final = 1;
+
+				/*
+				 * Eventually reset subchannel PCI status and
+				 *  set the PCI or SUSPENDED flag in the user
+				 *  device status block if appropriate.
+				 */
+				if ( dp->cstat & SCHN_STAT_PCI )
+				{
+					action->dev_id->flag |= DEVSTAT_PCI;
+					dp->cstat            &= ~SCHN_STAT_PCI;
+				}
+
+				if ( actl & SCSW_ACTL_SUSPENDED )
+				{
+					action->dev_id->flag |= DEVSTAT_SUSPENDED;
+
+				} /* endif */
+
+				action->handler( irq, action->dev_id, &regs );
+
+			} /* endif */
+
+		} /* endif */
+
+		break;
+
+	case 3:      /* device/path not operational */
+
+		ioinfo[irq]->ui.flags.busy    = 0;
+		ioinfo[irq]->ui.flags.doio    = 0;
+		ioinfo[irq]->ui.flags.haltio  = 0;
+
+		dp->cstat    = 0;
+		dp->dstat    = 0;
+
+		if ( ioinfo[irq]->ulpm != ioinfo[irq]->opm )
+		{
+			/*
+			 * either it was the only path or it was restricted ...
+			 */
+			ioinfo[irq]->opm &= ~(ioinfo[irq]->devstat.ii.irb.esw.esw1.lpum);
+		}
+		else
+		{
+			ioinfo[irq]->opm = 0;
+
+		} /* endif */
+	
+		if ( ioinfo[irq]->opm == 0 ) 	
+		{
+			ioinfo[irq]->ui.flags.oper  = 0;
+
+		} /* endif */
+
+		ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
+		ioinfo[irq]->devstat.flag |= DEVSTAT_FINAL_STATUS;
+
+		/*
+		 * When we find a device "not oper" we save the status
+		 *  information into the device status area and call the
+		 *  device specific interrupt handler.
+		 *
+		 * Note: currently we don't have any way to reenable
+		 *       the device unless an unsolicited interrupt
+		 *       is presented. We don't check for spurious
+		 *       interrupts on "not oper" conditions.
+		 */
+
+		if (    ( ioinfo[irq]->ui.flags.fast    )
+		     && ( ioinfo[irq]->ui.flags.w4final ) )
+		{
+			/*
+			 * If a new request was queued already, we have
+			 *  to simulate the "not oper" status for the
+			 *  queued request by switching the "intparm" value
+			 *  and notify the interrupt handler.
+			 */
+			if ( ioinfo[irq]->ui.flags.doio_q )
+			{
+				ioinfo[irq]->devstat.intparm = ioinfo[irq]->qintparm;
+
+			} /* endif */
+
+		} /* endif */
+
+		ioinfo[irq]->ui.flags.fast    = 0;
+		ioinfo[irq]->ui.flags.repall  = 0;
+		ioinfo[irq]->ui.flags.w4final = 0;
+
+		/*
+		 * take fast exit if no handler is available
+		 */
+		if ( !action )
+			return( ending_status );     		
+
+		memcpy( action->dev_id, &(ioinfo[irq]->devstat), sdevstat );
+
+		ioinfo[irq]->devstat.intparm  = 0;
+
+		if ( !ioinfo[irq]->ui.flags.s_pend )
+		{
+			action->handler( irq, action->dev_id, &regs );
+
+		} /* endif */
+
+		ending_status    = 1;
+
+		break;
+
+	} /* endswitch */
+
+	return( ending_status );
+}
+
+/*
+ * Set the special i/o-interruption sublass 7 for the
+ *  device specified by parameter irq. There can only
+ *  be a single device been operated on this special
+ *  isc. This function is aimed being able to check
+ *  on special device interrupts in disabled state,
+ *  without having to delay I/O processing (by queueing)
+ *  for non-console devices.
+ *
+ * Setting of this isc is done by set_cons_dev(), while
+ *  reset_cons_dev() resets this isc and re-enables the
+ *  default isc3 for this device. wait_cons_dev() allows
+ *  to actively wait on an interrupt for this device in
+ *  disabed state. When the interrupt condition is
+ *  encountered, wait_cons_dev(9 calls do_IRQ() to have
+ *  the console device driver processing the interrupt.
+ */
+int set_cons_dev( int irq )
+{
+	int           ccode;
+	unsigned long cr6 __attribute__ ((aligned (8)));
+	int           rc = 0;
+
+	if ( cons_dev != -1  )
+	{
+		rc = -EBUSY;
+	}
+	else if ( (irq > highest_subchannel) || (irq < 0) )
+	{
+		rc = -ENODEV;
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+	else
+	{
+		/*
+		 * modify the indicated console device to operate
+		 *  on special console interrupt sublass 7
+		 */
+		ccode = stsch( irq, &(ioinfo[irq]->schib) );
+
+		if (ccode)
+		{
+			rc                         = -ENODEV;
+			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
+		}
+		else
+		{
+			ioinfo[irq]->schib.pmcw.isc = 7;
+
+			ccode = msch( irq, &(ioinfo[irq]->schib) );
+
+			if (ccode)
+			{
+				rc = -EIO;
+			}
+			else
+			{
+				cons_dev = irq;
+
+				/*
+				 * enable console I/O-interrupt sublass 7
+				 */
+				__ctl_store( cr6, 6, 6);
+				cr6 |= 0x01000000;
+				__ctl_load( cr6, 6, 6);
+
+			} /* endif */
+
+		} /* endif */
+
+	} /* endif */
+
+	return( rc);
+}
+
+int reset_cons_dev( int irq)
+{
+	int     rc = 0;
+	int     ccode;
+	long    cr6 __attribute__ ((aligned (8)));
+
+	if ( cons_dev != -1  )
+	{
+		rc = -EBUSY;
+	}
+	else if ( (irq > highest_subchannel) || (irq < 0) )
+	{
+		rc = -ENODEV;
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+	else
+	{
+		/*
+		 * reset the indicated console device to operate
+		 *  on default console interrupt sublass 3
+		 */
+		ccode = stsch( irq, &(ioinfo[irq]->schib) );
+
+		if (ccode)
+		{
+			rc                         = -ENODEV;
+			ioinfo[irq]->devstat.flag |= DEVSTAT_NOT_OPER;
+		}
+		else
+		{
+
+			ioinfo[irq]->schib.pmcw.isc = 3;
+
+			ccode = msch( irq, &(ioinfo[irq]->schib) );
+
+			if (ccode)
+			{
+				rc = -EIO;
+			}
+			else
+			{
+				cons_dev = -1;
+
+				/*
+				 * disable special console I/O-interrupt sublass 7
+				 */
+				__ctl_store( cr6, 6, 6);
+				cr6 &= 0xFEFFFFFF;
+				__ctl_load( cr6, 6, 6);
+
+			} /* endif */
+
+		} /* endif */
+
+	} /* endif */
+
+	return( rc);
+}
+
+int wait_cons_dev( int irq )
+{
+	int              rc = 0;
+	long             save_cr6;
+
+	if ( irq == cons_dev )
+	{
+
+		/*
+		 * before entering the spinlock we may already have
+		 *  processed the interrupt on a different CPU ...
+		 */
+		if ( ioinfo[irq]->ui.flags.busy == 1 )
+		{
+			long cr6 __attribute__ ((aligned (8)));
+
+			/*
+			 * disable all, but isc 7 (console device)
+			 */
+			__ctl_store( cr6, 6, 6);
+			save_cr6  = cr6;
+			cr6      &= 0x01FFFFFF;
+			__ctl_load( cr6, 6, 6);
+
+			do {
+				tpi_info_t tpi_info = {0,};
+				if (tpi(&tpi_info) == 1) {
+					s390_process_IRQ( tpi_info.irq );
+				} else {
+					s390irq_spin_unlock(irq);
+					udelay(100);
+					s390irq_spin_lock(irq);
+				}
+				eieio();
+			} while (ioinfo[irq]->ui.flags.busy == 1);
+
+			/*
+			 * restore previous isc value
+			 */
+			cr6 = save_cr6;
+			__ctl_load( cr6, 6, 6);
+
+		} /* endif */
+
+	}
+	else
+	{
+		rc = EINVAL;
+
+	} /* endif */
+
+
+	return(rc);
+}
+
+
+int enable_cpu_sync_isc( int irq )
+{
+	int             ccode;
+	long            cr6 __attribute__ ((aligned (8)));
+
+	int             count = 0;
+	int             rc    = 0;
+
+	/* This one spins until it can get the sync_isc lock for irq# irq */
+
+	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )
+	{
+		if ( atomic_read( &sync_isc ) != irq )
+			atomic_compare_and_swap_spin( -1, irq, &sync_isc );
+
+		ioinfo[irq]->syncnt++;
+		
+		if ( ioinfo[irq]->syncnt > 255 ) /* fixme : magic number */
+		{
+			panic("Too many recursive calls to enable_sync_isc");
+
+		}
+		/*
+		 * we only run the STSCH/MSCH path for the first enablement
+		 */
+		else if ( ioinfo[irq]->syncnt == 1)
+		{
+			ioinfo[irq]->ui.flags.syncio = 1;
+
+			ccode = stsch( irq, &(ioinfo[irq]->schib) );
+
+			if ( !ccode )
+			{
+				ioinfo[irq]->schib.pmcw.isc = 5;
+
+				do
+				{
+					ccode = msch( irq,
+					              &(ioinfo[irq]->schib) );
+
+					if (ccode == 0 )
+					{
+						/*
+						 * enable special isc
+						 */
+					__ctl_store( cr6, 6, 6);
+					cr6 |= 0x04000000;  // enable sync isc 5
+					cr6 &= 0xEFFFFFFF;  // disable standard isc 3
+					__ctl_load( cr6, 6, 6);
+					}
+					else if (ccode == 3)
+					{
+						rc = -ENODEV;  // very unlikely
+
+					}
+					else if (ccode == 2)
+					{
+						rc = -EBUSY; // device busy ...
+
+					}
+					else if (ccode == 1)
+					{
+						//
+						// process pending status
+						//
+						ioinfo[irq]->ui.flags.s_pend = 1;
+
+						s390_process_IRQ( irq );
+
+						ioinfo[irq]->ui.flags.s_pend = 0;
+
+						count++;
+
+					} /* endif */
+
+				} while ( ccode == 1 && count < 3 );
+
+				if ( count == 3)
+				{
+					rc = -EIO;
+                       	
+				} /* endif */
+			}
+			else
+			{
+				rc = -ENODEV;     // device is not-operational
+
+			} /* endif */
+
+		} /* endif */
+	}
+	else
+	{
+		rc = -EINVAL;
+
+	} /* endif */
+
+	return( rc);
+}
+
+int disable_cpu_sync_isc( int irq)
+{
+	int     rc         = 0;
+	int     retry1     = 5;
+	int     retry2     = 5;
+	int     clear_pend = 0;
+
+	int     ccode;
+	long    cr6 __attribute__ ((aligned (8)));
+
+	if ( irq <= highest_subchannel && ioinfo[irq] != INVALID_STORAGE_AREA )
+	{
+		/*
+		 * We disable if we're the top user only, as we may
+		 *  run recursively ...	
+		 * We must not decrease the count immediately; during
+		 *  msch() processing we may face another pending
+		 *  status we have to process recursively (sync).
+		 */
+		if ( (ioinfo[irq]->syncnt-1) == 0 )
+		{
+			ccode = stsch( irq, &(ioinfo[irq]->schib) );
+
+			ioinfo[irq]->schib.pmcw.isc = 3;
+
+			do
+			{
+				do
+				{
+					ccode = msch( irq, &(ioinfo[irq]->schib) );
+
+					switch ( ccode ) {
+					case 0:
+						/*
+						 * disable special interrupt subclass in CPU
+						 */
+				__ctl_store( cr6, 6, 6);
+				cr6 &= 0xFBFFFFFF; // disable sync isc 5
+				cr6 |= 0x10000000; // enable standard isc 3
+				__ctl_load( cr6, 6, 6);
+						break;
+					case 1:
+						ioinfo[irq]->ui.flags.s_pend = 1;
+						s390_process_IRQ( irq );
+						ioinfo[irq]->ui.flags.s_pend = 0;
+						retry2--;
+						break;
+					case 2:
+						break;
+					default:
+						retry2 = 0;
+						break;
+					} /* endswitch */
+
+				} while ( retry2 && (ccode != 0) );
+
+				retry1--;
+
+				/* try stopping it ... */
+				if ( (ccode) && !clear_pend )
+				{
+					clear_IO( irq, 0x00004711, 0 );
+					clear_pend = 1;
+               	
+				} /* endif */
+
+				udelay( 100);
+
+			} while ( retry1 && ccode );
+
+			ioinfo[irq]->syncnt          = 0;
+			ioinfo[irq]->ui.flags.syncio = 0;
+			
+			atomic_set( &sync_isc, -1);
+
+		}
+		else
+		{
+			ioinfo[irq]->syncnt--;
+
+   	} /* endif */
+	}
+	else
+	{
+		rc = -EINVAL;
+
+	} /* endif */
+
+	return( rc);
+}
+
+//
+// Input :
+//   devno - device number
+//   ps    - pointer to sense ID data area
+//
+// Output : none
+//
+void VM_virtual_device_info( __u16      devno,
+                             senseid_t *ps )
+{
+	diag210_t  *p_diag_data;
+	int        ccode;
+
+	int        error = 0;
+
+	if ( init_IRQ_complete )
+	{
+		p_diag_data = kmalloc( sizeof( diag210_t), GFP_DMA );
+	}
+	else
+	{
+		p_diag_data = alloc_bootmem_low( sizeof( diag210_t));
+
+	} /* endif */
+
+	p_diag_data->vrdcdvno = devno;
+	p_diag_data->vrdclen  = sizeof( diag210_t);
+	ccode                 = diag210( (diag210_t *)virt_to_phys( p_diag_data ) );
+	ps->reserved          = 0xff;
+
+	switch (p_diag_data->vrdcvcla) {
+	case 0x80:
+
+		switch (p_diag_data->vrdcvtyp) {
+		case 00:
+
+			ps->cu_type   = 0x3215;
+
+			break;
+
+		default:
+
+			error = 1;
+
+			break;
+
+		} /* endswitch */
+
+		break;
+
+	case 0x40:
+
+		switch (p_diag_data->vrdcvtyp) {
+		case 0xC0:
+
+			ps->cu_type   = 0x5080;
+
+			break;
+
+		case 0x80:
+
+			ps->cu_type   = 0x2250;
+
+			break;
+
+		case 0x04:
+
+			ps->cu_type   = 0x3277;
+
+			break;
+
+		case 0x01:
+
+			ps->cu_type   = 0x3278;
+
+			break;
+
+		default:
+
+			error = 1;
+
+			break;
+
+		} /* endswitch */
+
+		break;
+
+	case 0x20:
+
+		switch (p_diag_data->vrdcvtyp) {
+		case 0x84:
+
+			ps->cu_type   = 0x3505;
+
+			break;
+
+		case 0x82:
+
+			ps->cu_type   = 0x2540;
+
+			break;
+
+		case 0x81:
+
+			ps->cu_type   = 0x2501;
+
+			break;
+
+		default:
+
+			error = 1;
+
+			break;
+
+		} /* endswitch */
+
+		break;
+
+	case 0x10:
+
+		switch (p_diag_data->vrdcvtyp) {
+		case 0x84:
+
+			ps->cu_type   = 0x3525;
+
+			break;
+
+		case 0x82:
+
+			ps->cu_type   = 0x2540;
+
+			break;
+
+		case 0x4F:
+		case 0x4E:
+		case 0x48:
+
+			ps->cu_type   = 0x3820;
+
+			break;
+
+		case 0x4D:
+		case 0x49:
+		case 0x45:
+
+			ps->cu_type   = 0x3800;
+
+			break;
+
+		case 0x4B:
+
+			ps->cu_type   = 0x4248;
+
+			break;
+
+		case 0x4A:
+
+			ps->cu_type   = 0x4245;
+
+			break;
+
+		case 0x47:
+
+			ps->cu_type   = 0x3262;
+
+			break;
+
+		case 0x43:
+
+			ps->cu_type   = 0x3203;
+
+			break;
+
+		case 0x42:
+
+			ps->cu_type   = 0x3211;
+
+			break;
+
+		case 0x41:
+
+			ps->cu_type   = 0x1403;
+
+			break;
+
+		default:
+
+			error = 1;
+
+			break;
+
+		} /* endswitch */
+
+		break;
+
+	case 0x08:
+
+		switch (p_diag_data->vrdcvtyp) {
+		case 0x82:
+
+			ps->cu_type   = 0x3422;
+
+			break;
+
+		case 0x81:
+
+			ps->cu_type   = 0x3490;
+
+			break;
+
+		case 0x10:
+
+			ps->cu_type   = 0x3420;
+
+			break;
+
+		case 0x02:
+
+			ps->cu_type   = 0x3430;
+
+			break;
+
+		case 0x01:
+
+			ps->cu_type   = 0x3480;
+
+			break;
+
+		case 0x42:
+
+			ps->cu_type   = 0x3424;
+
+			break;
+
+		case 0x44:
+
+			ps->cu_type   = 0x9348;
+
+			break;
+
+		default:
+
+			error = 1;
+
+			break;
+
+		} /* endswitch */
+
+		break;
+
+	case 02: /* special device class ... */
+
+		switch (p_diag_data->vrdcvtyp) {
+		case 0x20: /* OSA */
+
+			ps->cu_type   = 0x3088;
+			ps->cu_model  = 0x60;
+
+			break;
+
+		default:
+
+			error = 1;
+      	break;
+
+		} /* endswitch */
+
+		break;
+
+	default:
+
+		error = 1;
+
+		break;
+
+	} /* endswitch */
+
+	if ( init_IRQ_complete )
+	{
+		kfree( p_diag_data );
+	}
+	else
+	{
+		free_bootmem( (unsigned long)p_diag_data, sizeof( diag210_t) );
+
+	} /* endif */
+
+	if ( error )
+	{
+		printk( "DIAG X'210' for "
+		        "device %04X returned "
+		        "(cc = %d): vdev class : %02X, "
+			"vdev type : %04X \n ...  rdev class : %02X, rdev type : %04X, rdev model: %02X\n",
+			devno,
+			ccode,
+			p_diag_data->vrdcvcla,
+			p_diag_data->vrdcvtyp,
+			p_diag_data->vrdcrccl,
+			p_diag_data->vrdccrty,
+			p_diag_data->vrdccrmd );
+
+	} /* endif */
+
+}
+
+/*
+ * This routine returns the characteristics for the device
+ *  specified. Some old devices might not provide the necessary
+ *  command code information during SenseID processing. In this
+ *  case the function returns -EINVAL. Otherwise the function
+ *  allocates a decice specific data buffer and provides the
+ *  device characteristics together with the buffer size. Its
+ *  the callers responability to release the kernel memory if
+ *  not longer needed. In case of persistent I/O problems -EBUSY
+ *  is returned.
+ *
+ *  The function may be called enabled or disabled. However, the
+ *   caller must have locked the irq it is requesting data for.
+ *
+ * Note : It would have been nice to collect this information
+ *         during init_IRQ() processing but this is not possible
+ *
+ *         a) without statically pre-allocation fixed size buffers
+ *            as virtual memory management isn't available yet.
+ *
+ *         b) without unnecessarily increase system startup by
+ *            evaluating devices eventually not used at all.
+ */
+int read_dev_chars( int irq, void **buffer, int length )
+{
+	unsigned int  flags;
+	ccw1_t       *rdc_ccw;
+	devstat_t     devstat;
+	char         *rdc_buf;
+	int           devflag;
+
+	int           ret      = 0;
+	int           emulated = 0;
+	int           retry    = 5;
+
+	if ( !buffer || !length )
+	{
+		return( -EINVAL );
+
+	} /* endif */
+
+	if ( (irq > highest_subchannel) || (irq < 0 ) )
+	{
+	return( -ENODEV );
+
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+   }
+
+	if ( ioinfo[irq]->ui.flags.oper == 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	/*
+	 * Before playing around with irq locks we should assure
+	 *   running disabled on (just) our CPU. Sync. I/O requests
+	 *   also require to run disabled.
+	 *
+	 * Note : as no global lock is required, we must not use
+	 *        cli(), but __cli() instead.  	
+	 */
+	__save_flags(flags);
+	__cli();
+
+	rdc_ccw = &ioinfo[irq]->senseccw;
+
+	if ( !ioinfo[irq]->ui.flags.ready )
+	{
+		ret = request_irq( irq,
+		                   init_IRQ_handler,
+		                   0, "RDC", &devstat );
+
+		if ( !ret )
+		{
+			emulated = 1;
+
+		} /* endif */
+
+	} /* endif */
+
+	if ( !ret )
+	{
+		if ( ! *buffer )
+		{
+			rdc_buf  = kmalloc( length, GFP_KERNEL);
+		}
+		else
+		{
+			rdc_buf = *buffer;
+
+		} /* endif */
+
+		if ( !rdc_buf )
+		{
+			ret = -ENOMEM;
+		}
+		else
+		{
+			do
+			{
+				rdc_ccw->cmd_code = CCW_CMD_RDC;
+				rdc_ccw->count    = length;
+				rdc_ccw->flags    = CCW_FLAG_SLI;
+				set_normalized_cda( rdc_ccw, (unsigned long)rdc_buf );
+
+				memset( (devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id),
+				        '\0',
+				        sizeof( devstat_t));
+
+				ret = s390_start_IO( irq,
+				                     rdc_ccw,
+				                     0x00524443, // RDC
+				                     0,          // n/a
+				                     DOIO_WAIT_FOR_INTERRUPT
+				                      | DOIO_DONT_CALL_INTHDLR );
+				retry--;
+				devflag = ((devstat_t *)(ioinfo[irq]->irq_desc.action->dev_id))->flag;   
+    
+				clear_normalized_cda( rdc_ccw);  
+
+			} while (    ( retry                                     )
+			          && ( ret || (devflag & DEVSTAT_STATUS_PENDING) ) );
+
+		} /* endif */
+
+		if ( !retry )
+		{
+			ret = -EBUSY;
+
+		} /* endif */
+
+		__restore_flags(flags);
+
+		/*
+		 * on success we update the user input parms
+		 */
+		if ( !ret )
+		{
+			*buffer = rdc_buf;
+
+		} /* endif */
+
+		if ( emulated )
+		{
+			free_irq( irq, &devstat);
+
+		} /* endif */
+
+	} /* endif */
+
+	return( ret );
+}
+
+/*
+ *  Read Configuration data
+ */
+int read_conf_data( int irq, void **buffer, int *length, __u8 lpm )
+{
+	unsigned long flags;
+	int           ciw_cnt;
+
+	int           found  = 0; // RCD CIW found
+	int           ret    = 0; // return code
+
+	if ( (irq > highest_subchannel) || (irq < 0 ) )
+	{
+		return( -ENODEV );
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+	}
+	else if ( !buffer || !length )
+	{
+		return( -EINVAL);
+	}
+	else if ( ioinfo[irq]->ui.flags.oper == 0 )
+	{
+		return( -ENODEV );
+	}
+	else if ( ioinfo[irq]->ui.flags.esid == 0 )
+	{
+		return( -EOPNOTSUPP );
+
+	} /* endif */
+
+	/*
+	 * scan for RCD command in extended SenseID data
+	 */
+	
+	for ( ciw_cnt = 0; (found == 0) && (ciw_cnt < 62); ciw_cnt++ )
+	{
+		if ( ioinfo[irq]->senseid.ciw[ciw_cnt].ct == CIW_TYPE_RCD )
+		{
+			/*
+			 * paranoia check ...
+			 */
+			if ( ioinfo[irq]->senseid.ciw[ciw_cnt].cmd != 0 )
+			{
+				found = 1;
+
+			} /* endif */
+
+      	break;
+
+      } /* endif */
+
+   } /* endfor */
+
+	if ( found )
+	{
+		devstat_t  devstat;  /* inline device status area */
+		devstat_t *pdevstat;
+		int        ioflags;
+
+		ccw1_t    *rcd_ccw  = &ioinfo[irq]->senseccw;
+		char      *rcd_buf  = NULL;
+		int        emulated = 0; /* no i/O handler installed */
+		int        retry    = 5; /* retry count */
+
+		__save_flags(flags);
+		__cli();
+
+		if ( !ioinfo[irq]->ui.flags.ready )
+		{
+			pdevstat = &devstat;
+			ret      = request_irq( irq,
+			                        init_IRQ_handler,
+			                        0, "RCD", pdevstat );
+
+			if ( !ret )
+			{
+				emulated = 1;
+
+			} /* endif */
+		}
+		else
+		{
+			pdevstat = ioinfo[irq]->irq_desc.action->dev_id;
+
+		} /* endif */
+
+		if ( !ret )
+		{
+			if ( init_IRQ_complete )
+			{
+				rcd_buf = kmalloc( ioinfo[irq]->senseid.ciw[ciw_cnt].count,
+				                   GFP_DMA);
+			}
+			else
+			{
+				rcd_buf = alloc_bootmem_low( ioinfo[irq]->senseid.ciw[ciw_cnt].count);
+
+   		} /* endif */
+
+			if ( rcd_buf == NULL )
+			{
+				ret = -ENOMEM;	
+
+			} /* endif */
+
+			if ( !ret )
+			{
+				memset( rcd_buf,
+				        '\0',
+				        ioinfo[irq]->senseid.ciw[ciw_cnt].count);
+       	
+				do
+				{
+					rcd_ccw->cmd_code = ioinfo[irq]->senseid.ciw[ciw_cnt].cmd;
+					rcd_ccw->cda      = (__u32)virt_to_phys( rcd_buf );
+					rcd_ccw->count    = ioinfo[irq]->senseid.ciw[ciw_cnt].count;
+					rcd_ccw->flags    = CCW_FLAG_SLI;
+
+					memset( pdevstat, '\0', sizeof( devstat_t));
+
+					if ( lpm )
+					{
+						ioflags = DOIO_WAIT_FOR_INTERRUPT
+						          | DOIO_VALID_LPM    					
+						          | DOIO_DONT_CALL_INTHDLR;
+					}
+					else
+					{
+						ioflags =   DOIO_WAIT_FOR_INTERRUPT
+						          | DOIO_DONT_CALL_INTHDLR;
+						             					
+					} /* endif */
+
+					ret = s390_start_IO( irq,
+					                     rcd_ccw,
+					                     0x00524344,  // == RCD
+					                     lpm,
+					                     ioflags );
+
+	            switch ( ret ) {
+   	         case 0    :
+      	      case -EIO :
+
+	               if ( !(pdevstat->flag & (   DEVSTAT_STATUS_PENDING
+   	                                      | DEVSTAT_NOT_OPER
+      	                                   | DEVSTAT_FLAG_SENSE_AVAIL ) ) )
+	               {
+   	               retry = 0;  // we got it ...
+      	         }
+         	      else
+            	   {
+               	   retry--;    // try again ...
+
+	               } /* endif */
+
+   	            break;
+
+	            default :   // -EBUSY, -ENODEV, ???
+   	            retry = 0;
+
+      	      } /* endswitch */
+
+				} while ( retry );
+
+			} /* endif */
+
+			__restore_flags( flags );
+
+		} /* endif */
+
+		/*
+		 * on success we update the user input parms
+		 */
+		if ( ret == 0 )
+		{
+			*length = ioinfo[irq]->senseid.ciw[ciw_cnt].count;
+			*buffer = rcd_buf;
+		}
+		else
+		{
+			if ( rcd_buf != NULL )
+			{
+				if ( init_IRQ_complete )
+				{
+					kfree( rcd_buf );
+				}
+				else
+				{
+					free_bootmem( (unsigned long)rcd_buf,
+					              ioinfo[irq]->senseid.ciw[ciw_cnt].count);
+
+   			} /* endif */
+
+			} /* endif */
+
+			*buffer = NULL;
+			*length = 0;
+    	
+		} /* endif */
+
+		if ( emulated )
+			free_irq( irq, pdevstat);
+	}
+	else
+	{
+		ret = -EOPNOTSUPP;
+
+	} /* endif */
+
+	return( ret );
+
+}
+
+int get_dev_info( int irq, s390_dev_info_t * pdi)
+{
+	return( get_dev_info_by_irq( irq, pdi));
+}
+
+static int __inline__ get_next_available_irq( ioinfo_t *pi)
+{
+	int ret_val;
+
+	while ( TRUE )
+	{
+		if ( pi->ui.flags.oper )
+		{
+			ret_val = pi->irq;
+			break;
+		}
+		else
+		{
+			pi = pi->next;
+
+			//
+			// leave at end of list unconditionally
+			//
+			if ( pi == NULL )
+			{
+				ret_val = -ENODEV;
+				break;
+			}
+
+		} /* endif */
+
+	} /* endwhile */
+
+	return ret_val;
+}
+
+
+int get_irq_first( void )
+{
+   int ret_irq;
+
+	if ( ioinfo_head )
+	{
+		if ( ioinfo_head->ui.flags.oper )
+		{
+			ret_irq = ioinfo_head->irq;
+		}
+		else if ( ioinfo_head->next )
+		{
+			ret_irq = get_next_available_irq( ioinfo_head->next );
+
+		}
+		else
+		{
+			ret_irq = -ENODEV;
+   	
+		} /* endif */
+	}
+	else
+	{
+		ret_irq = -ENODEV;
+
+	} /* endif */
+
+	return ret_irq;
+}
+
+int get_irq_next( int irq )
+{
+	int ret_irq;	
+
+	if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+	{
+		if ( ioinfo[irq]->next )
+		{
+			if ( ioinfo[irq]->next->ui.flags.oper )
+			{
+				ret_irq = ioinfo[irq]->next->irq;
+			}
+			else
+			{
+				ret_irq = get_next_available_irq( ioinfo[irq]->next );
+
+			} /* endif */
+		}
+		else
+		{
+			ret_irq = -ENODEV;     	
+
+		} /* endif */
+	}
+	else
+	{
+		ret_irq = -EINVAL;
+
+	} /* endif */
+
+	return ret_irq;
+}
+
+int get_dev_info_by_irq( int irq, s390_dev_info_t *pdi)
+{
+
+	if ( irq > highest_subchannel || irq < 0 )
+	{
+		return -ENODEV;
+	}
+	else if ( pdi == NULL )
+	{
+		return -EINVAL;
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+	}
+	else
+	{
+		pdi->devno = ioinfo[irq]->schib.pmcw.dev;
+		pdi->irq   = irq;
+
+		if (     ioinfo[irq]->ui.flags.oper
+           && !ioinfo[irq]->ui.flags.unknown )
+		{
+			pdi->status = 0;
+			memcpy( &(pdi->sid_data),
+			        &ioinfo[irq]->senseid,
+			        sizeof( senseid_t));
+		}
+		else if ( ioinfo[irq]->ui.flags.unknown )
+		{
+			pdi->status = DEVSTAT_UNKNOWN_DEV;
+			memset( &(pdi->sid_data),
+			        '\0',
+			        sizeof( senseid_t));
+			pdi->sid_data.cu_type = 0xFFFF;
+
+		}
+		else
+		{
+			pdi->status = DEVSTAT_NOT_OPER;
+			memset( &(pdi->sid_data),
+			        '\0',
+			        sizeof( senseid_t));
+			pdi->sid_data.cu_type = 0xFFFF;
+
+		} /* endif */
+
+		if ( ioinfo[irq]->ui.flags.ready )
+			pdi->status |= DEVSTAT_DEVICE_OWNED;
+
+	} /* endif */
+
+	return 0;
+}
+
+
+int get_dev_info_by_devno( __u16 devno, s390_dev_info_t *pdi)
+{
+	int i;
+	int rc = -ENODEV;
+
+	if ( devno > 0x0000ffff )
+	{
+		return -ENODEV;
+	}
+	else if ( pdi == NULL )
+	{
+		return -EINVAL;
+	}
+	else
+	{
+
+		for ( i=0; i <= highest_subchannel; i++ )
+		{
+
+			if (    ioinfo[i] != INVALID_STORAGE_AREA
+			     && ioinfo[i]->schib.pmcw.dev == devno )
+			{
+
+				pdi->irq   = i;
+				pdi->devno = devno;
+
+				if (    ioinfo[i]->ui.flags.oper
+                 && !ioinfo[i]->ui.flags.unknown )
+				{
+					pdi->status = 0;
+
+					memcpy( &(pdi->sid_data),
+					        &ioinfo[i]->senseid,
+					        sizeof( senseid_t));
+				}
+				else if ( ioinfo[i]->ui.flags.unknown )
+				{
+					pdi->status = DEVSTAT_UNKNOWN_DEV;
+
+					memset( &(pdi->sid_data),
+                       '\0',
+                       sizeof( senseid_t));
+
+					pdi->sid_data.cu_type = 0xFFFF;
+				}
+				else
+				{
+					pdi->status = DEVSTAT_NOT_OPER;
+	
+					memset( &(pdi->sid_data),
+                       '\0',
+                       sizeof( senseid_t));
+
+					pdi->sid_data.cu_type = 0xFFFF;
+
+				} /* endif */
+
+				if ( ioinfo[i]->ui.flags.ready )
+					pdi->status |= DEVSTAT_DEVICE_OWNED;
+
+				rc = 0; /* found */
+				break;
+
+			} /* endif */
+
+		} /* endfor */
+
+		return( rc);
+
+	} /* endif */
+
+}
+
+int get_irq_by_devno( __u16 devno )
+{
+	int i;
+	int rc = -1;
+
+	if ( devno <= 0x0000ffff )
+	{
+		for ( i=0; i <= highest_subchannel; i++ )
+		{
+			if (    (ioinfo[i] != INVALID_STORAGE_AREA )
+			     && (ioinfo[i]->schib.pmcw.dev == devno)
+			     && (ioinfo[i]->schib.pmcw.dnv == 1    ) )
+			{
+				rc = i;
+				break;
+
+			} /* endif */
+
+		} /* endfor */
+	
+	} /* endif */
+
+	return( rc);
+}
+
+unsigned int get_devno_by_irq( int irq )
+{
+
+	if (    ( irq > highest_subchannel            )
+	     || ( irq < 0                             )
+	     || ( ioinfo[irq] == INVALID_STORAGE_AREA ) )
+	{
+		return -1;
+	
+	} /* endif */
+
+	/*
+	 * we don't need to check for the device be operational
+	 *  as the initial STSCH will always present the device
+	 *  number defined by the IOCDS regardless of the device
+	 *  existing or not. However, there could be subchannels
+	 *  defined who's device number isn't valid ...
+	 */
+	if ( ioinfo[irq]->schib.pmcw.dnv )
+		return( ioinfo[irq]->schib.pmcw.dev );
+	else
+		return -1;
+}
+
+/*
+ * s390_device_recognition_irq
+ *
+ * Used for individual device recognition. Issues the device
+ *  independant SenseID command to obtain info the device type.
+ *
+ */
+void s390_device_recognition_irq( int irq )
+{
+	int           ret;
+	unsigned long psw_flags;
+
+	/*
+	 * We issue the SenseID command on I/O subchannels we think are
+	 *  operational only.
+	 */
+	if (    ( ioinfo[irq] != INVALID_STORAGE_AREA )	
+	     && ( ioinfo[irq]->schib.pmcw.st == 0     )
+	     && ( ioinfo[irq]->ui.flags.oper == 1     ) )
+	{
+		int       irq_ret;
+		devstat_t devstat;
+
+	   irq_ret = request_irq( irq,
+		                       init_IRQ_handler,
+		                       0,
+		                       "INIT",
+		                       &devstat);
+
+		if ( !irq_ret )
+		{
+			ret = enable_cpu_sync_isc( irq );
+
+			if ( ret )
+			{
+				free_irq( irq, &devstat );
+				return; // fixme ! fast exit ... grr
+			}
+			else
+			{
+				ioinfo[irq]->ui.flags.unknown = 0;
+
+				memset( &ioinfo[irq]->senseid, '\0', sizeof( senseid_t));
+
+				s390_SenseID( irq, &ioinfo[irq]->senseid, 0xff );
+#if 0	/* FIXME */
+				/*
+				 * We initially check the configuration data for
+				 *  those devices with more than a single path
+				 */
+				if ( ioinfo[irq]->schib.pmcw.pim != 0x80 )
+				{
+					char     *prcd;
+					int       lrcd;
+
+					ret = read_conf_data( irq, (void **)&prcd, &lrcd, 0 );
+
+					if ( !ret )	// on success only ...
+					{
+#ifdef CONFIG_DEBUG_IO
+						char buffer[80];
+
+						sprintf( buffer,
+						         "RCD for device(%04X)/"
+						         "subchannel(%04X) returns :\n",
+						         ioinfo[irq]->schib.pmcw.dev,
+						         irq );
+
+						s390_displayhex( buffer, prcd, lrcd );
+#endif      				
+						if ( init_IRQ_complete )
+						{
+							kfree( prcd );
+						}
+						else
+						{
+							free_bootmem( (unsigned long)prcd, lrcd );
+
+ 			  			} /* endif */
+
+	   			} /* endif */
+
+     	      } /* endif */
+#endif
+				s390_DevicePathVerification( irq, 0 );
+
+				disable_cpu_sync_isc( irq );
+
+			} /* endif */  	
+
+			free_irq( irq, &devstat );
+
+		} /* endif */
+		
+	} /* endif */
+
+}
+
+/*
+ * s390_device_recognition_all
+ *
+ * Used for system wide device recognition.
+ *
+ */
+void s390_device_recognition_all( void)
+{
+	int irq = 0; /* let's start with subchannel 0 ... */
+
+	do
+	{
+		s390_device_recognition_irq( irq );
+
+		irq ++;
+
+	} while ( irq <= highest_subchannel );
+
+}
+
+
+/*
+ * s390_search_devices
+ *
+ * Determines all subchannels available to the system.
+ *
+ */
+void s390_process_subchannels( void)
+{
+	int   ret;
+	int   irq = 0;   /* Evaluate all subchannels starting with 0 ... */
+
+	do
+	{
+		ret = s390_validate_subchannel( irq, 0);
+
+		if ( ret != -ENXIO)
+			irq++;
+	
+  	} while ( (ret != -ENXIO) && (irq < __MAX_SUBCHANNELS) );
+
+	highest_subchannel = (--irq);
+
+	printk( "Highest subchannel number detected (hex) : %04X\n",
+	        highest_subchannel);
+}
+
+/*
+ * s390_validate_subchannel()
+ *
+ * Process the subchannel for the requested irq. Returns 1 for valid
+ *  subchannels, otherwise 0.
+ */
+int s390_validate_subchannel( int irq, int enable )
+{
+
+	int      retry;     /* retry count for status pending conditions */
+	int      ccode;     /* condition code for stsch() only */
+	int      ccode2;    /* condition code for other I/O routines */
+	schib_t *p_schib;
+	int      ret;
+
+	/*
+	 * The first subchannel that is not-operational (ccode==3)
+	 *  indicates that there aren't any more devices available.
+	 */
+	if (    ( init_IRQ_complete                   )
+	     && ( ioinfo[irq] != INVALID_STORAGE_AREA ) )
+	{
+		p_schib = &ioinfo[irq]->schib;
+	}
+	else
+	{
+		p_schib = p_init_schib;
+
+	} /* endif */
+
+	/*
+	 * If we knew the device before we assume the worst case ... 	
+	 */
+	if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+	{
+		ioinfo[irq]->ui.flags.oper = 0;
+		ioinfo[irq]->ui.flags.dval = 0;
+
+	} /* endif */
+
+	ccode = stsch( irq, p_schib);
+
+	if ( !ccode )
+	{
+		/*
+		 * ... just being curious we check for non I/O subchannels
+		 */
+		if ( p_schib->pmcw.st )
+		{
+			printk( "Subchannel %04X reports "
+			        "non-I/O subchannel type %04X\n",
+			        irq,
+			        p_schib->pmcw.st);
+
+			if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+				ioinfo[irq]->ui.flags.oper = 0;
+
+		} /* endif */
+
+		if ( p_schib->pmcw.dnv )
+		{
+			if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+			{	
+				if ( !init_IRQ_complete )
+				{
+					ioinfo[irq] =
+					   (ioinfo_t *)alloc_bootmem_low( sizeof(ioinfo_t));
+				}
+				else
+				{
+					ioinfo[irq] =
+					   (ioinfo_t *)kmalloc( sizeof(ioinfo_t),
+				                           GFP_DMA );
+
+				} /* endif */
+
+				memset( ioinfo[irq], '\0', sizeof( ioinfo_t));
+				memcpy( &ioinfo[irq]->schib,
+			           p_init_schib,
+			           sizeof( schib_t));
+				ioinfo[irq]->irq_desc.status  = IRQ_DISABLED;
+				ioinfo[irq]->irq_desc.handler = &no_irq_type;
+			
+				/*
+				 * We have to insert the new ioinfo element
+				 *  into the linked list, either at its head,
+				 *  its tail or insert it.
+				 */
+				if ( ioinfo_head == NULL )  /* first element */
+				{
+					ioinfo_head = ioinfo[irq];
+					ioinfo_tail = ioinfo[irq];
+				}
+				else if ( irq < ioinfo_head->irq ) /* new head */
+				{
+					ioinfo[irq]->next = ioinfo_head;
+					ioinfo_head->prev = ioinfo[irq];
+					ioinfo_head       = ioinfo[irq];
+				}
+				else if ( irq > ioinfo_tail->irq ) /* new tail */
+				{
+					ioinfo_tail->next = ioinfo[irq];
+					ioinfo[irq]->prev = ioinfo_tail;
+					ioinfo_tail       = ioinfo[irq];
+				}
+				else /* insert element */
+				{
+					ioinfo_t *pi = ioinfo_head;
+
+					do
+					{
+						if ( irq < pi->next->irq )
+						{
+							ioinfo[irq]->next = pi->next;
+							ioinfo[irq]->prev = pi;
+							pi->next->prev    = ioinfo[irq];
+							pi->next          = ioinfo[irq];
+							break;
+						
+						} /* endif */
+
+						pi = pi->next;
+
+					} while ( 1 );
+      	
+				} /* endif */
+
+			} /* endif */
+
+			// initialize some values ...	
+			ioinfo[irq]->ui.flags.pgid_supp = 1;
+
+			ioinfo[irq]->opm =   ioinfo[irq]->schib.pmcw.pim
+			                   & ioinfo[irq]->schib.pmcw.pam
+			                   & ioinfo[irq]->schib.pmcw.pom;
+
+			if ( cio_show_msg )
+			{
+				printk( KERN_INFO"Detected device %04X "
+				        "on subchannel %04X"
+				        " - PIM = %02X, PAM = %02X, POM = %02X\n",
+				        ioinfo[irq]->schib.pmcw.dev,
+				        irq,
+			   	     ioinfo[irq]->schib.pmcw.pim,
+			      	  ioinfo[irq]->schib.pmcw.pam,
+			 	       ioinfo[irq]->schib.pmcw.pom);
+
+			} /* endif */
+
+			/*
+			 * initialize ioinfo structure
+			 */
+			ioinfo[irq]->irq             = irq;
+			if(!ioinfo[irq]->ui.flags.ready)
+			{
+				ioinfo[irq]->nopfunc         = NULL;
+				ioinfo[irq]->ui.flags.busy   = 0;
+				ioinfo[irq]->ui.flags.dval   = 1;
+				ioinfo[irq]->devstat.intparm = 0;
+				
+			}
+			ioinfo[irq]->devstat.devno   = ioinfo[irq]->schib.pmcw.dev;
+			ioinfo[irq]->devno           = ioinfo[irq]->schib.pmcw.dev;
+
+			/*
+			 * We should have at least one CHPID ...
+			 */
+			if ( ioinfo[irq]->opm )
+			{
+				/*
+				 * We now have to initially ...
+				 *  ... set "interruption sublass"
+				 *  ... enable "concurrent sense"
+				 *  ... enable "multipath mode" if more than one
+				 *        CHPID is available. This is done regardless
+				 *        whether multiple paths are available for us.
+				 *
+				 * Note : we don't enable the device here, this is temporarily
+				 *        done during device sensing below.
+				 */
+				ioinfo[irq]->schib.pmcw.isc     = 3; /* could be smth. else */
+				ioinfo[irq]->schib.pmcw.csense  = 1; /* concurrent sense */
+				ioinfo[irq]->schib.pmcw.ena     = enable;
+				ioinfo[irq]->schib.pmcw.intparm =
+				                     ioinfo[irq]->schib.pmcw.dev;
+
+				if (    ( ioinfo[irq]->opm != 0x80 )
+				     && ( ioinfo[irq]->opm != 0x40 )
+				     && ( ioinfo[irq]->opm != 0x20 )
+				     && ( ioinfo[irq]->opm != 0x10 )
+				     && ( ioinfo[irq]->opm != 0x08 )
+				     && ( ioinfo[irq]->opm != 0x04 )
+				     && ( ioinfo[irq]->opm != 0x02 )
+				     && ( ioinfo[irq]->opm != 0x01 ) )
+				{
+					ioinfo[irq]->schib.pmcw.mp = 1; /* multipath mode */
+
+				} /* endif */
+
+				retry = 5;
+
+				do
+				{
+					ccode2 = msch_err( irq, &ioinfo[irq]->schib);
+
+					switch (ccode2) {
+					case 0:  // successful completion
+						//
+						// concurrent sense facility available ...
+						//
+						ioinfo[irq]->ui.flags.oper   = 1;
+						ioinfo[irq]->ui.flags.consns = 1;
+						ret                          = 0;
+						break;
+      	
+					case 1:  // status pending
+						//
+						// How can we have a pending status as
+						//  device is disabled for interrupts ?
+						//  Anyway, process it ...
+						//
+						ioinfo[irq]->ui.flags.s_pend = 1;
+						s390_process_IRQ( irq);
+						ioinfo[irq]->ui.flags.s_pend = 0;
+						retry--;
+						ret = -EIO;
+						break;
+   	
+					case 2:  // busy
+						/*
+						 * we mark it not-oper as we can't
+						 *  properly operate it !
+						 */
+						ioinfo[irq]->ui.flags.oper = 0;
+						udelay( 100);	/* allow for recovery */
+						retry--;
+						ret = -EBUSY;
+						break;
+
+					case 3:  // not operational
+						ioinfo[irq]->ui.flags.oper = 0;
+						retry                      = 0;
+						ret = -ENODEV;
+						break;
+
+					default:
+#define PGMCHK_OPERAND_EXC      0x15
+
+						if ( (ccode2 & PGMCHK_OPERAND_EXC) == PGMCHK_OPERAND_EXC )
+						{
+							/*
+							 * re-issue the modify subchannel without trying to
+							 *  enable the concurrent sense facility
+							 */
+							ioinfo[irq]->schib.pmcw.csense = 0;
+   	
+							ccode2 = msch_err( irq, &ioinfo[irq]->schib);
+
+							if ( ccode2 != 0 )
+							{
+								printk( " ... msch() (2) failed with CC = %X\n",
+								        ccode2 );
+								ioinfo[irq]->ui.flags.oper = 0;
+								ret                        = -EIO;
+							}
+							else
+							{
+								ioinfo[irq]->ui.flags.oper   = 1;
+								ioinfo[irq]->ui.flags.consns = 0;
+								ret                          = 0;
+
+							} /* endif */
+						}
+						else
+						{
+							printk( " ... msch() (1) failed with CC = %X\n",
+							        ccode2);
+							ioinfo[irq]->ui.flags.oper = 0;
+							ret                        = -EIO;
+
+						} /* endif */
+   	
+						retry  = 0;
+						break;
+
+					} /* endswitch */
+
+				} while ( ccode2 && retry );
+
+				if ( (ccode2 != 0) && (ccode2 != 3) && (!retry) )
+				{
+					printk( " ... msch() retry count for "
+					        "subchannel %04X exceeded, CC = %d\n",
+					        irq,
+					        ccode2);
+
+				} /* endif */
+			}
+			else
+			{
+				/* no path available ... */
+				ioinfo[irq]->ui.flags.oper = 0;
+				ret                        = -ENODEV;    	
+
+			} /* endif */
+		}
+		else
+		{
+			ret = -ENODEV;
+
+		} /* endif */
+	}
+	else
+	{
+		ret = -ENXIO;
+
+	} /* endif */
+
+	return( ret );
+}
+
+/*
+ * s390_SenseID
+ *
+ * Try to obtain the 'control unit'/'device type' information
+ *  associated with the subchannel.
+ *
+ * The function is primarily meant to be called without irq
+ *  action handler in place. However, it also allows for
+ *  use with an action handler in place. If there is already
+ *  an action handler registered assure it can handle the
+ *  s390_SenseID() related device interrupts - interruption
+ *  parameter used is 0x00E2C9C4 ( SID ).
+ */
+int s390_SenseID( int irq, senseid_t *sid, __u8 lpm )
+{
+	ccw1_t    *sense_ccw;     /* ccw area for SenseID command */
+	senseid_t  isid;          /* internal sid */				
+	devstat_t  devstat;       /* required by request_irq() */
+	__u8       pathmask;      /* calulate path mask */
+	__u8       domask;        /* path mask to use */
+	int        inlreq;        /* inline request_irq() */
+	int        irq_ret;       /* return code */
+	devstat_t *pdevstat;      /* ptr to devstat in use */
+	int        retry;         /* retry count */
+	int        io_retry;      /* retry indicator */
+
+	senseid_t *psid     = sid;/* start with the external buffer */	
+	int        sbuffer  = 0; /* switch SID data buffer */
+
+	if ( (irq > highest_subchannel) || (irq < 0 ) )
+	{
+		return( -ENODEV );
+
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+
+	} /* endif */
+
+	if ( ioinfo[irq]->ui.flags.oper == 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	if ( !ioinfo[irq]->ui.flags.ready )
+	{
+
+		pdevstat = &devstat;
+
+		/*
+		 * Perform SENSE ID command processing. We have to request device
+		 *  ownership and provide a dummy I/O handler. We issue sync. I/O
+		 *  requests and evaluate the devstat area on return therefore
+		 *  we don't need a real I/O handler in place.
+		 */
+		irq_ret = request_irq( irq, init_IRQ_handler, 0, "SID", &devstat);
+
+		if ( irq_ret == 0 )
+			inlreq = 1;
+	}
+	else
+	{
+		inlreq   = 0;
+		irq_ret  = 0;
+		pdevstat = ioinfo[irq]->irq_desc.action->dev_id;
+
+  	} /* endif */
+
+	if ( irq_ret == 0 )
+   {
+      int i;
+
+		s390irq_spin_lock( irq);
+
+		if ( init_IRQ_complete )
+		{
+			sense_ccw = kmalloc( 2*sizeof( ccw1_t), GFP_DMA);
+		}
+		else	
+		{
+			sense_ccw = alloc_bootmem_low( 2*sizeof( ccw1_t));
+
+		} /* endif */
+
+		// more than one path installed ?
+		if ( ioinfo[irq]->schib.pmcw.pim != 0x80 )
+		{
+			sense_ccw[0].cmd_code = CCW_CMD_SUSPEND_RECONN;
+			sense_ccw[0].cda      = 0;
+			sense_ccw[0].count    = 0;
+			sense_ccw[0].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
+
+			sense_ccw[1].cmd_code = CCW_CMD_SENSE_ID;
+			sense_ccw[1].cda      = (__u32)virt_to_phys( sid );
+			sense_ccw[1].count    = sizeof( senseid_t);
+			sense_ccw[1].flags    = CCW_FLAG_SLI;
+		}
+		else
+		{
+			sense_ccw[0].cmd_code = CCW_CMD_SENSE_ID;
+			sense_ccw[0].cda      = (__u32)virt_to_phys( sid );
+			sense_ccw[0].count    = sizeof( senseid_t);
+			sense_ccw[0].flags    = CCW_FLAG_SLI;
+
+		} /* endif */
+
+		for ( i = 0 ; (i < 8) ; i++ )
+		{
+			pathmask = 0x80 >> i;						
+
+			domask = ioinfo[irq]->opm & pathmask;
+
+			if ( lpm )
+				domask &= lpm;
+
+			if ( domask )
+			{
+				psid->cu_type    = 0xFFFF;  /* initialize fields ... */
+				psid->cu_model   = 0;
+				psid->dev_type   = 0;
+				psid->dev_model  = 0;
+
+				retry            = 5;  /* retry count    */
+				io_retry         = 1;  /* enable retries */
+
+				/*
+				 * We now issue a SenseID request. In case of BUSY,
+				 *  STATUS PENDING or non-CMD_REJECT error conditions
+				 *  we run simple retries.
+				 */
+				do
+				{
+					memset( pdevstat, '\0', sizeof( devstat_t) );
+
+					irq_ret = s390_start_IO( irq,
+					                         sense_ccw,
+					                         0x00E2C9C4,  // == SID
+			   		                      domask,
+					                         DOIO_WAIT_FOR_INTERRUPT
+					                          | DOIO_TIMEOUT
+					                          | DOIO_VALID_LPM
+					                          | DOIO_DONT_CALL_INTHDLR );
+
+					//
+					// The OSA_E FE card possibly causes -ETIMEDOUT
+					//  conditions, as the SenseID may stay start
+					//  pending. This will cause start_IO() to finally
+					//  halt the operation we should retry. If the halt
+					//  fails this may cause -EBUSY we simply retry
+					//  and eventually clean up with free_irq().   	     		
+					//
+
+					if ( psid->cu_type  == 0xFFFF )
+					{
+						if ( pdevstat->flag & DEVSTAT_STATUS_PENDING )
+						{
+#ifdef CONFIG_DEBUG_IO
+							printk( "SenseID : device %04X on "
+							        "Subchannel %04X "
+							        "reports pending status, "
+							        "retry : %d\n",
+							        ioinfo[irq]->schib.pmcw.dev,
+					   		     irq,
+							        retry);
+#endif
+						} /* endif */
+
+						if ( pdevstat->flag & DEVSTAT_FLAG_SENSE_AVAIL )
+						{
+							/*
+							 * if the device doesn't support the SenseID
+							 *  command further retries wouldn't help ...
+							 */
+							if (  pdevstat->ii.sense.data[0]
+							    & (SNS0_CMD_REJECT | SNS0_INTERVENTION_REQ) )
+							{
+#ifdef CONFIG_DEBUG_IO
+								printk( "SenseID : device %04X on "
+								        "Subchannel %04X "
+								        "reports cmd reject or "
+								        "intervention required\n",
+								        ioinfo[irq]->schib.pmcw.dev,
+								        irq);
+#endif
+								io_retry = 1;
+							}
+#ifdef CONFIG_DEBUG_IO
+							else
+							{
+								printk( "SenseID : UC on "
+								        "dev %04X, "
+								        "retry %d, "
+								        "lpum %02X, "
+								        "cnt %02d, "
+								        "sns :"
+								        " %02X%02X%02X%02X "
+								        "%02X%02X%02X%02X ...\n",
+								        ioinfo[irq]->schib.pmcw.dev,
+								        retry,
+								        pdevstat->lpum,
+								        pdevstat->scnt,
+								        pdevstat->ii.sense.data[0],
+								        pdevstat->ii.sense.data[1],
+								        pdevstat->ii.sense.data[2],
+								        pdevstat->ii.sense.data[3],
+								        pdevstat->ii.sense.data[4],
+								        pdevstat->ii.sense.data[5],
+								        pdevstat->ii.sense.data[6],
+								        pdevstat->ii.sense.data[7]);
+
+							} /* endif */
+#endif
+						}
+						else if (    ( pdevstat->flag & DEVSTAT_NOT_OPER )
+					             || ( irq_ret        == -ENODEV         ) )
+						{
+#ifdef CONFIG_DEBUG_IO
+							printk( "SenseID : path %02X for "
+							        "device %04X on "
+							        "subchannel %04X "
+							        "is 'not operational'\n",
+							        domask,
+							        ioinfo[irq]->schib.pmcw.dev,
+							        irq);
+#endif
+
+							io_retry          = 0;
+							ioinfo[irq]->opm &= ~domask;
+      	
+						}
+#ifdef CONFIG_DEBUG_IO
+						else if (     (pdevstat->flag !=
+						                    (   DEVSTAT_START_FUNCTION
+						                      | DEVSTAT_FINAL_STATUS    ) )
+						           && !(pdevstat->flag &
+						                    DEVSTAT_STATUS_PENDING        ) )
+						{
+							printk( "SenseID : start_IO() for "
+							        "device %04X on "
+							        "subchannel %04X "
+							        "returns %d, retry %d, "
+							        "status %04X\n",
+							        ioinfo[irq]->schib.pmcw.dev,
+							        irq,
+							        irq_ret,
+							        retry,
+							        pdevstat->flag);
+
+						} /* endif */
+#endif
+					}
+					else   // we got it ...
+					{
+						if ( !sbuffer )	// switch buffers
+						{
+							/*
+							 * we report back the
+							 *  first hit only
+							 */
+							psid = &isid;
+
+							if ( ioinfo[irq]->schib.pmcw.pim != 0x80 )
+							{
+								sense_ccw[1].cda = (__u32)virt_to_phys( psid );
+							}
+							else
+							{
+								sense_ccw[0].cda = (__u32)virt_to_phys( psid );
+
+							} /* endif */
+
+							/*
+							 * if just the very first
+							 *  was requested to be
+							 *  sensed disable further
+							 *  scans.
+							 */	
+							if ( !lpm )
+								lpm = domask;
+
+							sbuffer = 1;
+
+						} /* endif */
+
+					   if ( pdevstat->rescnt < (sizeof( senseid_t) - 8) )
+						{
+							ioinfo[irq]->ui.flags.esid = 1;
+       							
+						} /* endif */
+
+						io_retry = 0;
+						
+					} /* endif */
+
+					if ( io_retry )
+					{
+						retry--;
+
+						if ( retry == 0 )
+						{
+							io_retry = 0;
+
+						} /* endif */
+      	
+					} /* endif */
+	
+				} while ( (io_retry) );
+
+ 			} /* endif - domask */
+
+		} /* endfor */
+
+		if ( init_IRQ_complete )
+		{
+			kfree( sense_ccw );
+		}
+		else	
+		{
+			free_bootmem( (unsigned long)sense_ccw, 2*sizeof(ccw1_t) );
+
+		} /* endif */
+
+		s390irq_spin_unlock( irq);
+
+		/*
+		 * If we installed the irq action handler we have to
+		 *  release it too.
+		 */
+		if ( inlreq )
+			free_irq( irq, pdevstat);
+
+		/*
+		 * if running under VM check there ... perhaps we should do
+		 *  only if we suffered a command reject, but it doesn't harm
+		 */
+		if (    ( sid->cu_type == 0xFFFF    )
+		     && ( MACHINE_IS_VM              ) )
+		{
+			VM_virtual_device_info( ioinfo[irq]->schib.pmcw.dev,
+			                        sid );
+		} /* endif */
+
+		if ( sid->cu_type == 0xFFFF )
+		{
+			/*
+			 * SenseID CU-type of 0xffff indicates that no device
+			 *  information could be retrieved (pre-init value).
+			 *
+			 * If we can't couldn't identify the device type we
+			 *  consider the device "not operational".
+			 */
+#ifdef CONFIG_DEBUG_IO
+			printk( "SenseID : unknown device %04X on subchannel %04X\n",
+			        ioinfo[irq]->schib.pmcw.dev,
+			        irq);
+#endif
+			ioinfo[irq]->ui.flags.unknown = 1;
+
+		} /* endif */
+
+		if ( cio_show_msg )
+		{
+			/*
+			 * Issue device info message if unit was operational .
+			 */
+			if ( !ioinfo[irq]->ui.flags.unknown )
+			{
+				if ( sid->dev_type != 0 )
+				{
+					printk( KERN_INFO"SenseID : device %04X reports: "
+					        "CU  Type/Mod = %04X/%02X,"
+				      	  " Dev Type/Mod = %04X/%02X\n",
+				   	     ioinfo[irq]->schib.pmcw.dev,
+					        sid->cu_type,
+					        sid->cu_model,
+					        sid->dev_type,
+					        sid->dev_model);
+				}
+				else
+				{
+					printk( KERN_INFO"SenseID : device %04X reports:"
+				   	     " Dev Type/Mod = %04X/%02X\n",
+					        ioinfo[irq]->schib.pmcw.dev,
+					        sid->cu_type,
+					        sid->cu_model);
+
+				} /* endif */
+
+			} /* endif */
+
+		} /* endif */
+
+		if ( !ioinfo[irq]->ui.flags.unknown )
+			irq_ret = 0;
+		else
+			irq_ret = -ENODEV;
+
+	} /* endif */
+
+   return( irq_ret );
+}
+
+static int __inline__ s390_SetMultiPath( int irq )
+{
+	int cc;
+
+	cc = stsch( irq, &ioinfo[irq]->schib );
+
+	if ( !cc )
+	{
+		ioinfo[irq]->schib.pmcw.mp = 1;     /* multipath mode */
+
+		cc = msch( irq, &ioinfo[irq]->schib );
+
+	} /* endif */
+
+	return( cc);
+}
+
+/*
+ * Device Path Verification
+ *
+ * Path verification is accomplished by checking which paths (CHPIDs) are
+ *  available. Further, a path group ID is set, if possible in multipath
+ *  mode, otherwise in single path mode.
+ *
+ */
+int s390_DevicePathVerification( int irq, __u8 usermask )
+{
+#if 1
+	int  ccode;
+	__u8 pathmask;
+	__u8 domask;
+
+	int ret = 0;
+
+	if ( ioinfo[irq]->ui.flags.pgid_supp == 0 )
+	{
+		return( 0);	// just exit ...
+
+	} /* endif */
+
+	ccode = stsch( irq, &(ioinfo[irq]->schib) );
+
+	if ( ccode )
+	{
+		ret = -ENODEV;
+	}
+	else if ( ioinfo[irq]->schib.pmcw.pim == 0x80 )
+	{
+		/*
+		 * no error, just not required for single path only devices
+		 */	
+		ioinfo[irq]->ui.flags.pgid_supp = 0;
+		ret = 0;
+	}
+	else
+	{
+		int    i;
+		pgid_t pgid;
+		__u8   dev_path;
+		int    first  = 1;
+
+		ioinfo[irq]->opm =   ioinfo[irq]->schib.pmcw.pim
+		                   & ioinfo[irq]->schib.pmcw.pam
+		                   & ioinfo[irq]->schib.pmcw.pom;
+
+		if ( usermask )
+		{
+			dev_path = usermask;
+		}
+		else
+		{
+			dev_path = ioinfo[irq]->opm;
+
+		} /* endif */
+
+		/*
+		 * let's build a path group ID if we don't have one yet
+		 */
+		if ( ioinfo[irq]->ui.flags.pgid == 0)
+		{
+			ioinfo[irq]->pgid.cpu_addr  = *(__u16 *)__LC_CPUADDR;
+			ioinfo[irq]->pgid.cpu_id    = ((cpuid_t *)__LC_CPUID)->ident;
+			ioinfo[irq]->pgid.cpu_model = ((cpuid_t *)__LC_CPUID)->machine;
+			ioinfo[irq]->pgid.tod_high  = *(__u32 *)&irq_IPL_TOD;
+
+			ioinfo[irq]->ui.flags.pgid  = 1;
+
+		} /* endif */     		
+
+		memcpy( &pgid, &ioinfo[irq]->pgid, sizeof(pgid_t));
+
+		for ( i = 0; i < 8 && !ret ; i++)
+		{
+			pathmask = 0x80 >> i;						
+
+			domask = dev_path & pathmask;
+
+			if ( domask )
+			{
+				ret = s390_SetPGID( irq, domask, &pgid );
+
+				/*
+				 * For the *first* path we are prepared
+				 *  for recovery
+				 *
+				 *  - If we fail setting the PGID we assume its
+				 *     using  a different PGID already (VM) we
+				 *     try to sense.
+				 */
+				if ( ret == -EOPNOTSUPP && first )
+				{
+					*(int *)&pgid = 0;
+					
+					ret   = s390_SensePGID( irq, domask, &pgid);
+					first = 0;
+
+					if ( ret == 0 )
+					{
+						/*
+						 * Check whether we retrieved
+						 *  a reasonable PGID ...
+						 */	
+						if ( pgid.inf.ps.state1 == SNID_STATE1_GROUPED )
+						{
+							memcpy( &(ioinfo[irq]->pgid),
+							        &pgid,
+							        sizeof(pgid_t) );
+						}
+						else // ungrouped or garbage ...
+						{
+							ret = -EOPNOTSUPP;
+
+						} /* endif */
+					}
+					else
+					{
+						ioinfo[irq]->ui.flags.pgid_supp = 0;
+
+#ifdef CONFIG_DEBUG_IO
+						printk( "PathVerification(%04X) "
+						        "- Device %04X doesn't "
+						        " support path grouping\n",
+						        irq,
+						        ioinfo[irq]->schib.pmcw.dev);
+#endif
+
+					} /* endif */
+				}
+				else if ( ret )
+				{
+
+#ifdef CONFIG_DEBUG_IO
+						printk( "PathVerification(%04X) "
+						        "- Device %04X doesn't "
+						        " support path grouping\n",
+						        irq,
+						        ioinfo[irq]->schib.pmcw.dev);
+
+#endif
+
+					ioinfo[irq]->ui.flags.pgid_supp = 0;
+
+				} /* endif */
+
+			} /* endif */
+
+		} /* endfor */
+
+	} /* endif */
+
+	return ret;
+#else
+	return 0;
+#endif
+}
+
+/*
+ * s390_SetPGID
+ *
+ * Set Path Group ID
+ *
+ */
+int s390_SetPGID( int irq, __u8 lpm, pgid_t *pgid )
+{
+	ccw1_t    *spid_ccw;    /* ccw area for SPID command */
+	devstat_t  devstat;     /* required by request_irq() */
+	devstat_t *pdevstat = &devstat;
+
+	int        irq_ret = 0; /* return code */
+	int        retry   = 5; /* retry count */
+	int        inlreq  = 0; /* inline request_irq() */
+	int        mpath   = 1; /* try multi-path first */
+
+	if ( (irq > highest_subchannel) || (irq < 0 ) )
+	{
+		return( -ENODEV );
+
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+
+	} /* endif */
+
+	if ( ioinfo[irq]->ui.flags.oper == 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	if ( !ioinfo[irq]->ui.flags.ready )
+	{
+		/*
+		 * Perform SENSE ID command processing. We have to request device
+		 *  ownership and provide a dummy I/O handler. We issue sync. I/O
+		 *  requests and evaluate the devstat area on return therefore
+		 *  we don't need a real I/O handler in place.
+		 */
+		irq_ret = request_irq( irq,
+		                       init_IRQ_handler,
+		                       0,
+		                       "SPID",
+		                       pdevstat);
+
+		if ( irq_ret == 0 )
+			inlreq = 1;
+   }
+	else
+	{
+		pdevstat = ioinfo[irq]->irq_desc.action->dev_id;
+
+	} /* endif */
+
+	if ( irq_ret == 0 )
+	{
+		s390irq_spin_lock( irq);
+
+		if ( init_IRQ_complete )
+		{
+			spid_ccw = kmalloc( 2*sizeof( ccw1_t), GFP_DMA);
+		}
+		else	
+		{
+			spid_ccw = alloc_bootmem_low( 2*sizeof( ccw1_t));
+
+		} /* endif */
+
+		spid_ccw[0].cmd_code = 0x5B;	/* suspend multipath reconnect */
+		spid_ccw[0].cda      = 0;
+		spid_ccw[0].count    = 0;
+		spid_ccw[0].flags    = CCW_FLAG_SLI | CCW_FLAG_CC;
+
+		spid_ccw[1].cmd_code = CCW_CMD_SET_PGID;
+		spid_ccw[1].cda      = (__u32)virt_to_phys( pgid );
+		spid_ccw[1].count    = sizeof( pgid_t);
+		spid_ccw[1].flags    = CCW_FLAG_SLI;
+
+		pgid->inf.fc = SPID_FUNC_MULTI_PATH | SPID_FUNC_ESTABLISH;
+
+		/*
+		 * We now issue a SenseID request. In case of BUSY
+		 *  or STATUS PENDING conditions we retry 5 times.
+		 */
+		do
+		{
+			memset( pdevstat, '\0', sizeof( devstat_t) );
+
+			irq_ret = s390_start_IO( irq,
+			                         spid_ccw,
+			                         0xE2D7C9C4,  // == SPID
+			                         lpm,         // n/a
+			                         DOIO_WAIT_FOR_INTERRUPT
+			                          | DOIO_VALID_LPM
+			                          | DOIO_DONT_CALL_INTHDLR );
+
+			if ( !irq_ret )
+			{
+				if ( pdevstat->flag & DEVSTAT_STATUS_PENDING )
+				{
+#ifdef CONFIG_DEBUG_IO
+					printk( "SPID - Device %04X "
+					        "on Subchannel %04X "
+					        "reports pending status, "
+					        "retry : %d\n",
+					        ioinfo[irq]->schib.pmcw.dev,
+					        irq,
+					        retry);
+#endif
+				} /* endif */
+
+				if ( pdevstat->flag == (   DEVSTAT_START_FUNCTION
+				                         | DEVSTAT_FINAL_STATUS   ) )
+				{
+					retry = 0;	// successfully set ...
+				}
+				else if ( pdevstat->flag & DEVSTAT_FLAG_SENSE_AVAIL )
+				{
+					/*
+					 * If the device doesn't support the
+					 *  Sense Path Group ID command
+					 *  further retries wouldn't help ...
+					 */
+					if ( pdevstat->ii.sense.data[0] & SNS0_CMD_REJECT )
+					{
+						if ( mpath )
+						{
+							pgid->inf.fc =   SPID_FUNC_SINGLE_PATH
+							               | SPID_FUNC_ESTABLISH;
+							mpath        = 0;
+							retry--;
+						}
+						else
+						{
+							irq_ret = -EOPNOTSUPP;
+							retry   = 0;			
+
+						} /* endif */
+					}
+#ifdef CONFIG_DEBUG_IO
+					else
+					{
+						printk( "SPID - device %04X,"
+						        " unit check,"
+						        " retry %d, cnt %02d,"
+						        " sns :"
+						        " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
+						        ioinfo[irq]->schib.pmcw.dev,
+						        retry,
+						        pdevstat->scnt,
+						        pdevstat->ii.sense.data[0],
+						        pdevstat->ii.sense.data[1],
+						        pdevstat->ii.sense.data[2],
+						        pdevstat->ii.sense.data[3],
+						        pdevstat->ii.sense.data[4],
+						        pdevstat->ii.sense.data[5],
+						        pdevstat->ii.sense.data[6],
+						        pdevstat->ii.sense.data[7]);
+
+					} /* endif */
+#endif
+				}
+				else if ( pdevstat->flag & DEVSTAT_NOT_OPER )
+				{
+					printk( "SPID - Device %04X "
+					        "on Subchannel %04X "
+					        "became 'not operational'\n",
+					        ioinfo[irq]->schib.pmcw.dev,
+					        irq);
+
+					retry = 0;
+
+				} /* endif */
+			}
+			else if ( irq_ret != -ENODEV )
+			{
+				retry--;
+			}
+			else
+			{
+				retry = 0;
+
+			} /* endif */
+
+		} while ( retry > 0 );
+
+		if ( init_IRQ_complete )
+		{
+			kfree( spid_ccw );
+		}
+		else	
+		{
+			free_bootmem( (unsigned long)spid_ccw, 2*sizeof(ccw1_t) );
+
+		} /* endif */
+
+		s390irq_spin_unlock( irq);
+
+		/*
+		 * If we installed the irq action handler we have to
+		 *  release it too.
+		 */
+		if ( inlreq )
+			free_irq( irq, pdevstat);
+
+	} /* endif */
+
+   return( irq_ret );
+}
+
+
+/*
+ * s390_SensePGID
+ *
+ * Sense Path Group ID
+ *
+ */
+int s390_SensePGID( int irq, __u8 lpm, pgid_t *pgid )
+{
+	ccw1_t    *snid_ccw;    /* ccw area for SNID command */
+	devstat_t  devstat;     /* required by request_irq() */
+	devstat_t *pdevstat = &devstat;
+
+	int        irq_ret = 0; /* return code */
+	int        retry   = 5; /* retry count */
+	int        inlreq  = 0; /* inline request_irq() */
+
+	if ( (irq > highest_subchannel) || (irq < 0 ) )
+	{
+		return( -ENODEV );
+
+	}
+	else if ( ioinfo[irq] == INVALID_STORAGE_AREA )
+	{
+		return( -ENODEV);
+
+	} /* endif */
+
+	if ( ioinfo[irq]->ui.flags.oper == 0 )
+	{
+		return( -ENODEV );
+
+	} /* endif */
+
+	if ( !ioinfo[irq]->ui.flags.ready )
+	{
+		/*
+		 * Perform SENSE ID command processing. We have to request device
+		 *  ownership and provide a dummy I/O handler. We issue sync. I/O
+		 *  requests and evaluate the devstat area on return therefore
+		 *  we don't need a real I/O handler in place.
+		 */
+		irq_ret = request_irq( irq,
+		                       init_IRQ_handler,
+		                       0,
+		                       "SNID",
+		                       pdevstat);
+
+		if ( irq_ret == 0 )
+			inlreq = 1;
+
+   }
+	else
+	{
+		pdevstat = ioinfo[irq]->irq_desc.action->dev_id;
+
+	} /* endif */
+
+	if ( irq_ret == 0 )
+	{
+		s390irq_spin_lock( irq);
+
+		if ( init_IRQ_complete )
+		{
+			snid_ccw = kmalloc( sizeof( ccw1_t), GFP_DMA);
+		}
+		else	
+		{
+			snid_ccw = alloc_bootmem_low( sizeof( ccw1_t));
+
+		} /* endif */
+
+		snid_ccw->cmd_code = CCW_CMD_SENSE_PGID;
+		snid_ccw->cda      = (__u32)virt_to_phys( pgid );
+		snid_ccw->count    = sizeof( pgid_t);
+		snid_ccw->flags    = CCW_FLAG_SLI;
+
+		/*
+		 * We now issue a SenseID request. In case of BUSY
+		 *  or STATUS PENDING conditions we retry 5 times.
+		 */
+		do
+		{
+			memset( pdevstat, '\0', sizeof( devstat_t) );
+
+			irq_ret = s390_start_IO( irq,
+			                         snid_ccw,
+			                         0xE2D5C9C4,  // == SNID
+			                         lpm,         // n/a
+			                         DOIO_WAIT_FOR_INTERRUPT
+			                          | DOIO_VALID_LPM
+			                          | DOIO_DONT_CALL_INTHDLR );
+
+			if ( irq_ret == 0 )
+			{
+				if ( pdevstat->flag & DEVSTAT_FLAG_SENSE_AVAIL )
+				{
+					/*
+					 * If the device doesn't support the
+					 *  Sense Path Group ID command
+					 *  further retries wouldn't help ...
+					 */
+					if ( pdevstat->ii.sense.data[0] & SNS0_CMD_REJECT )
+					{
+						retry   = 0;
+						irq_ret = -EOPNOTSUPP;
+					}
+					else
+					{
+#ifdef CONFIG_DEBUG_IO
+						printk( "SNID - device %04X,"
+						        " unit check,"
+						        " flag %04X, "
+						        " retry %d, cnt %02d,"
+						        " sns :"
+						        " %02X%02X%02X%02X %02X%02X%02X%02X ...\n",
+						        ioinfo[irq]->schib.pmcw.dev,
+						        pdevstat->flag,
+						        retry,
+						        pdevstat->scnt,
+						        pdevstat->ii.sense.data[0],
+						        pdevstat->ii.sense.data[1],
+						        pdevstat->ii.sense.data[2],
+						        pdevstat->ii.sense.data[3],
+						        pdevstat->ii.sense.data[4],
+						        pdevstat->ii.sense.data[5],
+						        pdevstat->ii.sense.data[6],
+						        pdevstat->ii.sense.data[7]);
+
+#endif
+						retry--;
+
+					} /* endif */
+				}
+				else if ( pdevstat->flag & DEVSTAT_NOT_OPER )
+				{
+					printk( "SNID - Device %04X "
+					        "on Subchannel %04X "
+					        "became 'not operational'\n",
+					        ioinfo[irq]->schib.pmcw.dev,
+					        irq);
+
+					retry = 0;
+
+				}
+				else
+				{
+					retry = 0; // success ...
+
+				} /* endif */
+			}
+			else if ( irq_ret != -ENODEV ) // -EIO, or -EBUSY
+			{
+#ifdef CONFIG_DEBUG_IO
+				if ( pdevstat->flag & DEVSTAT_STATUS_PENDING )
+				{
+					printk( "SNID - Device %04X "
+					        "on Subchannel %04X "
+					        "reports pending status, "
+					        "retry : %d\n",
+					        ioinfo[irq]->schib.pmcw.dev,
+					        irq,
+					        retry);
+				} /* endif */
+#endif
+
+				printk( "SNID - device %04X,"
+				        " start_io() reports rc : %d, retrying ...\n",
+				        ioinfo[irq]->schib.pmcw.dev,
+				        irq_ret);
+				retry--;
+			}
+			else	// -ENODEV ...
+			{
+				retry = 0;
+
+			} /* endif */
+
+		} while ( retry > 0 );
+
+		if ( init_IRQ_complete )
+		{
+			kfree( snid_ccw );
+		}
+		else	
+		{
+			free_bootmem( (unsigned long)snid_ccw, sizeof(ccw1_t) );
+
+		} /* endif */
+
+		s390irq_spin_unlock( irq);
+
+		/*
+		 * If we installed the irq action handler we have to
+		 *  release it too.
+		 */
+		if ( inlreq )
+			free_irq( irq, pdevstat);
+
+	} /* endif */
+
+   return( irq_ret );
+}
+
+/*
+ * s390_do_crw_pending
+ *
+ * Called by the machine check handler to process CRW pending
+ *  conditions. It may be a single CRW, or CRWs may be chained.
+ *
+ * Note : we currently process CRWs for subchannel source only
+ */
+void s390_do_crw_pending( crwe_t *pcrwe )
+{
+	int irq;
+	int chpid;
+	int dev_oper = 0;
+	int dev_no   = -1;	
+	int lock     = 0;
+
+#ifdef CONFIG_DEBUG_CRW
+	printk( "do_crw_pending : starting ...\n");
+#endif
+
+	while ( pcrwe != NULL )
+	{
+		int is_owned = 0;
+
+		switch ( pcrwe->crw.rsc ) {	
+		case CRW_RSC_SCH :
+
+			irq = pcrwe->crw.rsid;
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( KERN_INFO"do_crw_pending : source is "
+			        "subchannel %04X\n", irq);
+#endif
+
+			/*
+			 * If the device isn't known yet
+			 *   we can't lock it ...
+			 */
+			if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+			{
+				s390irq_spin_lock( irq );
+				lock = 1;
+
+				dev_oper = ioinfo[irq]->ui.flags.oper;
+
+				if ( ioinfo[irq]->ui.flags.dval )
+					dev_no = ioinfo[irq]->devno;
+
+				is_owned = ioinfo[irq]->ui.flags.ready;
+
+			} /* endif */
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : subchannel validation - start ...\n");
+#endif
+			s390_validate_subchannel( irq, is_owned );
+
+			if ( irq > highest_subchannel )
+				highest_subchannel = irq;
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : subchannel validation - done\n");
+#endif
+			/*
+			 * After the validate processing
+			 *   the ioinfo control block
+			 *   should be allocated ...
+			 */
+			if ( lock )
+			{
+				s390irq_spin_unlock( irq );
+
+			} /* endif */
+
+#ifdef CONFIG_DEBUG_CRW
+			if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+			{
+				printk( "do_crw_pending : ioinfo at %08X\n",
+				        (unsigned)ioinfo[irq]);
+
+			} /* endif */
+#endif
+
+			if ( ioinfo[irq] != INVALID_STORAGE_AREA )
+			{
+				if ( ioinfo[irq]->ui.flags.oper == 0 )
+				{
+					 not_oper_handler_func_t nopfunc=ioinfo[irq]->nopfunc;
+					/*
+					 * If the device has gone
+					 *  call not oper handler        	
+					 */       	
+					if (    (             dev_oper == 1    )
+					     && ( nopfunc != NULL ) )
+					{
+						
+						free_irq( irq,ioinfo[irq]->irq_desc.action->dev_id );
+						nopfunc( irq,DEVSTAT_DEVICE_GONE );			
+
+					} /* endif */
+				}
+				else
+				{
+#ifdef CONFIG_DEBUG_CRW
+					printk( "do_crw_pending : device "
+					        "recognition - start ...\n");
+#endif
+					s390_device_recognition_irq( irq );
+
+#ifdef CONFIG_DEBUG_CRW
+					printk( "do_crw_pending : device "
+					        "recognition - done\n");
+#endif
+		
+					/*
+					 * the device became operational
+					 */
+					if ( dev_oper == 0 )
+					{
+						devreg_t *pdevreg;
+
+						pdevreg = s390_search_devreg( ioinfo[irq] );
+
+						if ( pdevreg != NULL )
+						{
+							if ( pdevreg->oper_func != NULL )
+								pdevreg->oper_func( irq, pdevreg );
+
+						} /* endif */
+					}
+					/*
+					 * ... it is and was operational, but
+					 *      the devno may have changed
+					 */
+					else if ((ioinfo[irq]->devno != dev_no) && ( ioinfo[irq]->nopfunc != NULL ))   					
+					{
+						ioinfo[irq]->nopfunc( irq,
+						                      DEVSTAT_REVALIDATE );				
+
+					} /* endif */
+
+				} /* endif */
+
+			} /* endif */
+
+			break;
+
+		case CRW_RSC_MONITOR :
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : source is "
+			        "monitoring facility\n");
+#endif
+			break;
+
+		case CRW_RSC_CPATH :   	
+
+			chpid = pcrwe->crw.rsid;
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : source is "
+			        "channel path %02X\n", chpid);
+#endif
+			break;
+
+		case CRW_RSC_CONFIG : 	
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : source is "
+			        "configuration-alert facility\n");
+#endif
+			break;
+
+		case CRW_RSC_CSS :
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : source is "
+			        "channel subsystem\n");
+#endif
+			break;
+
+		default :
+
+#ifdef CONFIG_DEBUG_CRW
+			printk( "do_crw_pending : unknown source\n");
+#endif
+			break;		
+
+		} /* endswitch */
+
+		pcrwe = pcrwe->crwe_next;
+
+	} /* endwhile */
+
+#ifdef CONFIG_DEBUG_CRW
+	printk( "do_crw_pending : done\n");
+#endif
+
+   return;
+}
+
+
+/* added by Holger Smolinski for reipl support in reipl.S */
+extern void do_reipl (int);
+void
+reipl ( int sch )
+{
+	int i;
+
+	for ( i = 0; i < highest_subchannel; i ++ ) {
+	    free_irq ( i, (void*)REIPL_DEVID_MAGIC );
+	}
+	do_reipl( 0x10000 | sch );
+}
+
diff -u --recursive --new-file v2.4.1/linux/drivers/s390/s390mach.c linux/drivers/s390/s390mach.c
--- v2.4.1/linux/drivers/s390/s390mach.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/s390/s390mach.c	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,534 @@
+/*
+ *  arch/s390/kernel/s390mach.c
+ *   S/390 machine check handler,
+ *            currently only channel-reports are supported
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#include <linux/config.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#ifdef CONFIG_SMP
+#include <linux/smp.h>
+#endif
+
+#include <asm/irq.h>
+#include <asm/lowcore.h>
+#include <asm/semaphore.h>
+#include <asm/s390io.h>
+#include <asm/s390dyn.h>
+#include <asm/s390mach.h>
+
+#define S390_MACHCHK_DEBUG
+
+static int         s390_machine_check_handler( void * parm );
+static void        s390_enqueue_mchchk( mache_t *mchchk );
+static mache_t    *s390_dequeue_mchchk( void );
+static void        s390_enqueue_free_mchchk( mache_t *mchchk );
+static mache_t    *s390_dequeue_free_mchchk( void );
+static int         s390_collect_crw_info( void );
+
+static mache_t    *mchchk_queue_head = NULL;
+static mache_t    *mchchk_queue_tail = NULL;
+static mache_t    *mchchk_queue_free = NULL;
+static crwe_t     *crw_buffer_anchor = NULL;
+static spinlock_t  mchchk_queue_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t  crw_queue_lock    = SPIN_LOCK_UNLOCKED;
+
+static struct semaphore s_sem;
+
+
+/*
+ * s390_init_machine_check
+ *
+ * initialize machine check handling
+ */
+void s390_init_machine_check( void )
+{
+	crwe_t  *pcrwe;	 /* CRW buffer element pointer */
+	mache_t *pmache;   /* machine check element pointer */
+
+	init_MUTEX_LOCKED( &s_sem );
+
+	pcrwe = kmalloc( MAX_CRW_PENDING * sizeof( crwe_t), GFP_KERNEL);
+
+	if ( pcrwe )
+	{
+		int i;
+
+		crw_buffer_anchor = pcrwe;
+
+		for ( i=0; i < MAX_CRW_PENDING-1; i++)
+		{
+			pcrwe->crwe_next = (crwe_t *)((unsigned long)pcrwe + sizeof(crwe_t));
+   		pcrwe            = pcrwe->crwe_next;
+
+		} /* endfor */	
+
+		pcrwe->crwe_next = NULL;
+
+	}
+	else
+	{
+		panic( "s390_init_machine_check : unable to obtain memory\n");		
+
+	} /* endif */
+
+	pmache = kmalloc( MAX_MACH_PENDING * sizeof( mache_t), GFP_KERNEL);
+
+	if ( pmache )
+	{
+		int i;
+
+		for ( i=0; i < MAX_MACH_PENDING; i++)
+		{
+			s390_enqueue_free_mchchk( pmache );
+		   pmache = (mache_t *)((unsigned long)pmache + sizeof(mache_t));
+
+		} /* endfor */	
+	}
+	else
+	{
+		panic( "s390_init_machine_check : unable to obtain memory\n");		
+
+	} /* endif */
+
+#ifdef S390_MACHCHK_DEBUG
+	printk( "init_mach : starting machine check handler\n");
+#endif	
+
+	kernel_thread( s390_machine_check_handler, &s_sem, CLONE_FS | CLONE_FILES);
+
+	ctl_clear_bit( 14, 25 );  // disable damage MCH 	
+#if 1
+  	ctl_set_bit( 14, 28 );		// enable channel report MCH
+#endif
+
+#ifdef S390_MACHCHK_DEBUG
+	printk( "init_mach : machine check buffer : head = %08X\n",
+            (unsigned)&mchchk_queue_head);
+	printk( "init_mach : machine check buffer : tail = %08X\n",
+            (unsigned)&mchchk_queue_tail);
+	printk( "init_mach : machine check buffer : free = %08X\n",
+            (unsigned)&mchchk_queue_free);
+	printk( "init_mach : CRW entry buffer anchor = %08X\n",
+            (unsigned)&crw_buffer_anchor);
+	printk( "init_mach : machine check handler ready\n");
+#endif	
+
+	return;
+}
+
+/*
+ * s390_do_machine_check
+ *
+ * mchine check pre-processor, collecting the machine check info,
+ *  queueing it and posting the machine check handler for processing.
+ */
+void s390_do_machine_check( void )
+{
+	int      crw_count;
+	mcic_t   mcic;
+
+#ifdef S390_MACHCHK_DEBUG
+	printk( "s390_do_machine_check : starting ...\n");
+#endif
+
+	memcpy( &mcic,
+	        &S390_lowcore.mcck_interuption_code,
+	        sizeof(__u64));
+ 		
+	if ( mcic.mcc.mcd.cp )	// CRW pending ?
+	{
+		crw_count = s390_collect_crw_info();
+
+		if ( crw_count )
+		{
+			up( &s_sem );
+
+		} /* endif */
+
+	} /* endif */
+
+#ifdef S390_MACHCHK_DEBUG
+	printk( "s390_do_machine_check : done \n");
+#endif
+
+	return;
+}
+
+/*
+ * s390_machine_check_handler
+ *
+ * machine check handler, dequeueing machine check entries
+ *  and processing them
+ */
+static int s390_machine_check_handler( void *parm)
+{
+	struct semaphore *sem = parm;
+	int               flags;
+	mache_t          *pmache;
+
+	int               found = 0;
+
+        /* set name to something sensible */
+        strcpy (current->comm, "kmcheck");
+
+
+        /* block all signals */
+        sigfillset(&current->blocked);
+
+#ifdef S390_MACHCHK_DEBUG
+	printk( "mach_handler : ready\n");
+#endif	
+
+	do {
+
+#ifdef S390_MACHCHK_DEBUG
+		printk( "mach_handler : waiting for wakeup\n");
+#endif	
+
+		down_interruptible( sem );
+
+#ifdef S390_MACHCHK_DEBUG
+		printk( "\nmach_handler : wakeup ... \n");
+#endif	
+		found = 0; /* init ... */
+
+		__save_flags( flags );
+		__cli();
+
+		do {
+
+		pmache = s390_dequeue_mchchk();
+
+		if ( pmache )
+		{
+			found = 1;
+		
+			if ( pmache->mcic.mcc.mcd.cp )
+			{
+				crwe_t *pcrwe_n;
+				crwe_t *pcrwe_h;
+
+				s390_do_crw_pending( pmache->mc.crwe );
+
+				pcrwe_h = pmache->mc.crwe;
+				pcrwe_n = pmache->mc.crwe->crwe_next;
+
+				pmache->mcic.mcc.mcd.cp = 0;
+				pmache->mc.crwe         = NULL;
+
+				spin_lock( &crw_queue_lock);
+
+				while ( pcrwe_h )
+				{
+					pcrwe_h->crwe_next = crw_buffer_anchor;
+					crw_buffer_anchor  = pcrwe_h;
+					pcrwe_h            = pcrwe_n;
+
+					if ( pcrwe_h != NULL )
+						pcrwe_n = pcrwe_h->crwe_next;
+
+				} /* endwhile */
+
+				spin_unlock( &crw_queue_lock);
+
+			} /* endif */
+
+			s390_enqueue_free_mchchk( pmache );
+		}
+		else
+		{
+
+			// unconditional surrender ...
+#ifdef S390_MACHCHK_DEBUG
+			printk( "mach_handler : nothing to do, sleeping\n");
+#endif	
+
+		} /* endif */	
+
+		} while ( pmache );
+
+		__restore_flags( flags );
+
+	} while ( 1 );
+
+	return( 0);
+}
+
+/*
+ * s390_dequeue_mchchk
+ *
+ * Dequeue an entry from the machine check queue
+ *
+ * Note : The queue elements provide for a double linked list.
+ *  We dequeue entries from the tail, and enqueue entries to
+ *  the head.
+ *
+ */
+static mache_t *s390_dequeue_mchchk( void )
+{
+	mache_t *qe;
+
+	spin_lock( &mchchk_queue_lock );
+
+	qe = mchchk_queue_tail;
+
+   if ( qe != NULL )
+   {
+      mchchk_queue_tail = qe->prev;
+
+      if ( mchchk_queue_tail != NULL )
+      {
+			mchchk_queue_tail->next = NULL;
+		}
+		else
+      {
+			mchchk_queue_head = NULL;
+
+      } /* endif */
+
+	} /* endif */
+
+	spin_unlock( &mchchk_queue_lock );
+
+	return qe;
+}
+
+/*
+ * s390_enqueue_mchchk
+ *
+ * Enqueue an entry to the machine check queue.
+ *
+ * Note : The queue elements provide for a double linked list.
+ *  We enqueue entries to the head, and dequeue entries from
+ *  the tail.
+ *
+ */
+static void s390_enqueue_mchchk( mache_t *pmache )
+{
+	spin_lock( &mchchk_queue_lock );
+
+	if ( pmache != NULL )
+	{
+
+		if ( mchchk_queue_head == NULL )  /* first element */
+		{
+  			pmache->next      = NULL;
+  			pmache->prev      = NULL;
+
+			mchchk_queue_head = pmache;
+			mchchk_queue_tail = pmache;
+		}
+		else /* new head */
+		{
+  			pmache->prev            = NULL;
+			pmache->next            = mchchk_queue_head;
+
+			mchchk_queue_head->prev = pmache;
+			mchchk_queue_head       = pmache;
+
+		} /* endif */
+
+	} /* endif */
+
+	spin_unlock( &mchchk_queue_lock );
+
+	return;
+}
+
+
+/*
+ * s390_enqueue_free_mchchk
+ *
+ * Enqueue a free entry to the free queue.
+ *
+ * Note : While the queue elements provide for a double linked list,
+ *  the free queue entries are only concatenated by means of a
+ *  single linked list (forward concatenation).
+ *
+ */
+static void s390_enqueue_free_mchchk( mache_t *pmache )
+{
+	if ( pmache != NULL)
+	{
+		memset( pmache, '\0', sizeof( mache_t ));
+
+		spin_lock( &mchchk_queue_lock );
+		
+		pmache->next = mchchk_queue_free;
+
+		mchchk_queue_free = pmache;
+
+		spin_unlock( &mchchk_queue_lock );
+
+	} /* endif */
+
+	return;
+}
+
+/*
+ * s390_dequeue_free_mchchk
+ *
+ * Dequeue an entry from the free queue.
+ *
+ * Note : While the queue elements provide for a double linked list,
+ *  the free queue entries are only concatenated by means of a
+ *  single linked list (forward concatenation).
+ *
+ */
+static mache_t *s390_dequeue_free_mchchk( void )
+{
+	mache_t *qe;
+
+	spin_lock( &mchchk_queue_lock );
+
+	qe = mchchk_queue_free;
+
+	if ( qe != NULL )
+	{
+		mchchk_queue_free = qe->next;
+
+	} /* endif */
+
+	spin_unlock( &mchchk_queue_lock );
+
+	return qe;
+}
+
+/*
+ * s390_collect_crw_info
+ *
+ * Retrieve CRWs. If a CRW was found a machine check element
+ *  is dequeued from the free chain, filled and enqueued to
+ *  be processed.
+ *
+ * The function returns the number of CRWs found.
+ *
+ * Note : We must always be called disabled ...
+ */
+static int s390_collect_crw_info( void )
+{
+	crw_t    tcrw;     /* temporarily holds a CRW */
+	int      ccode;    /* condition code from stcrw() */
+	crwe_t  *pcrwe;    /* pointer to CRW buffer entry */
+
+	mache_t *pmache = NULL; /* ptr to mchchk entry */
+	int      chain  = 0;    /* indicate chaining */
+	crwe_t  *pccrw  = NULL; /* ptr to current CRW buffer entry */
+	int      count  = 0;    /* CRW count */
+
+#ifdef S390_MACHCHK_DEBUG
+	printk( "crw_info : looking for CRWs ...\n");
+#endif
+
+	do
+	{
+		ccode = stcrw( (__u32 *)&tcrw);
+
+		if ( ccode == 0 )
+		{
+			count++;
+			
+#ifdef S390_MACHCHK_DEBUG
+			printk( "crw_info : CRW reports "
+			        "slct=%d, oflw=%d, chn=%d, "
+			        "rsc=%X, anc=%d, erc=%X, "
+			        "rsid=%X\n",
+			        tcrw.slct,
+			        tcrw.oflw,
+			        tcrw.chn,
+			        tcrw.rsc,
+			        tcrw.anc,
+			        tcrw.erc,
+			        tcrw.rsid );
+#endif
+
+			/*
+			 * Dequeue a CRW entry from the free chain
+			 *  and process it ...
+			 */
+			spin_lock( &crw_queue_lock );
+
+			pcrwe = crw_buffer_anchor;
+
+			if ( pcrwe == NULL )
+			{
+				spin_unlock( &crw_queue_lock );
+				printk( KERN_CRIT"crw_info : "
+				        "no CRW buffer entries available\n");
+				break;
+
+			} /* endif */
+			
+			crw_buffer_anchor = pcrwe->crwe_next;
+			pcrwe->crwe_next  = NULL;
+
+			spin_unlock( &crw_queue_lock );
+
+			memcpy( &(pcrwe->crw), &tcrw, sizeof(crw_t));
+
+			/*
+			 * If it is the first CRW, chain it to the mchchk
+			 *  buffer entry, otherwise to the last CRW entry.
+			 */
+			if ( chain == 0 )
+			{
+				pmache = s390_dequeue_free_mchchk();
+
+				if ( pmache != NULL )
+				{
+					memset( pmache, '\0', sizeof(mache_t));
+
+					pmache->mcic.mcc.mcd.cp = 1;
+					pmache->mc.crwe         = pcrwe;
+					pccrw                   = pcrwe;
+
+				}
+				else
+				{
+					panic( "crw_info : "
+					       "unable to dequeue "
+					       "free mchchk buffer");				
+
+				} /* endif */
+			}
+			else
+			{
+				pccrw->crwe_next = pcrwe;
+				pccrw            = pcrwe;
+
+			} /* endif */	
+
+			if ( pccrw->crw.chn )
+			{
+#ifdef S390_MACHCHK_DEBUG
+				printk( "crw_info : "
+				        "chained CRWs pending ...\n\n");
+#endif
+				chain = 1;
+			}
+			else
+			{
+				chain = 0;
+
+				/*
+				 * We can enqueue the mchchk buffer if
+				 *  there aren't more CRWs chained.
+				 */
+				s390_enqueue_mchchk( pmache);
+
+			} /* endif */
+
+		} /* endif */
+
+	} while ( ccode == 0 );
+
+	return( count );
+}
+
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/audio/amd7930.c linux/drivers/sbus/audio/amd7930.c
--- v2.4.1/linux/drivers/sbus/audio/amd7930.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/sbus/audio/amd7930.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: amd7930.c,v 1.25 2001/01/08 04:19:16 davem Exp $
+/* $Id: amd7930.c,v 1.26 2001/02/13 01:16:59 davem Exp $
  * drivers/sbus/audio/amd7930.c
  *
  * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -88,7 +88,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/version.h>
 #include <linux/soundcard.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/audio/audio.c linux/drivers/sbus/audio/audio.c
--- v2.4.1/linux/drivers/sbus/audio/audio.c	Mon Oct 23 15:48:27 2000
+++ linux/drivers/sbus/audio/audio.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: audio.c,v 1.56 2000/10/19 00:50:02 davem Exp $
+/* $Id: audio.c,v 1.58 2001/02/13 01:16:59 davem Exp $
  * drivers/sbus/audio/audio.c
  *
  * Copyright 1996 Thomas K. Dyas (tdyas@noc.rutgers.edu)
@@ -28,13 +28,13 @@
 #include <linux/mm.h>
 #include <linux/tqueue.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/init.h>
 #include <linux/soundcard.h>
 #include <linux/version.h>
 #include <linux/devfs_fs_kernel.h>
-#include <asm/delay.h>
+#include <linux/delay.h>
 #include <asm/pgtable.h>
 
 #include <asm/audioio.h>
@@ -511,7 +511,7 @@
                         m = drv->ops->get_input_balance(drv);
                 i = OSS_TO_GAIN(k);
                 j = OSS_TO_BAL(k);
-                oprintk((" for stereo to to %d (bal %d):", i, j));
+                oprintk((" for stereo to do %d (bal %d):", i, j));
                 if (drv->ops->set_input_volume)
                         drv->ops->set_input_volume(drv, i);
                 if (drv->ops->set_input_balance)
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/audio/cs4231.c linux/drivers/sbus/audio/cs4231.c
--- v2.4.1/linux/drivers/sbus/audio/cs4231.c	Fri Feb 18 15:07:20 2000
+++ linux/drivers/sbus/audio/cs4231.c	Sun Feb 18 19:49:54 2001
@@ -1,4 +1,4 @@
-/* $Id: cs4231.c,v 1.43 2000/02/18 13:49:39 davem Exp $
+/* $Id: cs4231.c,v 1.44 2001/02/13 01:16:59 davem Exp $
  * drivers/sbus/audio/cs4231.c
  *
  * Copyright 1996, 1997, 1998, 1999 Derrick J Brashear (shadow@andrew.cmu.edu)
@@ -22,7 +22,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/soundcard.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/audio/dbri.c linux/drivers/sbus/audio/dbri.c
--- v2.4.1/linux/drivers/sbus/audio/dbri.c	Sat Feb  3 19:51:28 2001
+++ linux/drivers/sbus/audio/dbri.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: dbri.c,v 1.23 2001/01/08 04:19:16 davem Exp $
+/* $Id: dbri.c,v 1.25 2001/02/13 01:16:59 davem Exp $
  * drivers/sbus/audio/dbri.c
  *
  * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de)
@@ -47,14 +47,14 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
+#include <linux/delay.h>
 #include <asm/openprom.h>
 #include <asm/oplib.h>
 #include <asm/system.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 #include <asm/sbus.h>
 #include <asm/pgtable.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/audio/dmy.c linux/drivers/sbus/audio/dmy.c
--- v2.4.1/linux/drivers/sbus/audio/dmy.c	Fri Dec 29 14:07:22 2000
+++ linux/drivers/sbus/audio/dmy.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: dmy.c,v 1.6 2000/12/13 05:06:26 davem Exp $
+/* $Id: dmy.c,v 1.7 2001/02/13 01:16:59 davem Exp $
  * drivers/sbus/audio/dummy.c
  *
  * Copyright 1998 Derrick J Brashear (shadow@andrew.cmu.edu)
@@ -13,7 +13,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/soundcard.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/envctrl.c linux/drivers/sbus/char/envctrl.c
--- v2.4.1/linux/drivers/sbus/char/envctrl.c	Thu Nov  9 15:57:41 2000
+++ linux/drivers/sbus/char/envctrl.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: envctrl.c,v 1.19 2000/11/03 00:37:40 davem Exp $
+/* $Id: envctrl.c,v 1.21 2001/02/13 04:07:38 davem Exp $
  * envctrl.c: Temperature and Fan monitoring on Machines providing it.
  *
  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
@@ -25,7 +25,7 @@
 #include <linux/init.h>
 #include <linux/miscdevice.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/ebus.h>
 #include <asm/uaccess.h>
@@ -229,7 +229,7 @@
 		printk(KERN_INFO "envctrl: Busy bit will not clear.\n");
 }
 
-/* Function Description: Send the adress for a read access.
+/* Function Description: Send the address for a read access.
  * Return : 0 if not acknowledged, otherwise acknowledged.
  */
 static int envctrl_i2c_read_addr(unsigned char addr)
@@ -255,7 +255,7 @@
 	}
 }
 
-/* Function Description: Send the adress for write mode.  
+/* Function Description: Send the address for write mode.  
  * Return : None.
  */
 static void envctrl_i2c_write_addr(unsigned char addr)
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/flash.c linux/drivers/sbus/char/flash.c
--- v2.4.1/linux/drivers/sbus/char/flash.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sbus/char/flash.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: flash.c,v 1.21 2001/01/11 15:29:36 davem Exp $
+/* $Id: flash.c,v 1.22 2001/02/13 01:17:00 davem Exp $
  * flash.c: Allow mmap access to the OBP Flash, for OBP updates.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -9,7 +9,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/jsflash.c linux/drivers/sbus/char/jsflash.c
--- v2.4.1/linux/drivers/sbus/char/jsflash.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sbus/char/jsflash.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/openprom.c linux/drivers/sbus/char/openprom.c
--- v2.4.1/linux/drivers/sbus/char/openprom.c	Thu Nov  9 15:57:41 2000
+++ linux/drivers/sbus/char/openprom.c	Fri Feb  9 11:30:23 2001
@@ -36,7 +36,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/miscdevice.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/pcikbd.c linux/drivers/sbus/char/pcikbd.c
--- v2.4.1/linux/drivers/sbus/char/pcikbd.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sbus/char/pcikbd.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: pcikbd.c,v 1.50 2001/01/11 15:29:36 davem Exp $
+/* $Id: pcikbd.c,v 1.51 2001/02/13 01:17:00 davem Exp $
  * pcikbd.c: Ultra/AX PC keyboard support.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -16,7 +16,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/poll.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/random.h>
 #include <linux/miscdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/rtc.c linux/drivers/sbus/char/rtc.c
--- v2.4.1/linux/drivers/sbus/char/rtc.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sbus/char/rtc.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: rtc.c,v 1.24 2001/01/11 15:07:09 davem Exp $
+/* $Id: rtc.c,v 1.25 2001/02/13 01:17:00 davem Exp $
  *
  * Linux/SPARC Real Time Clock Driver
  * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu)
@@ -15,7 +15,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/poll.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/sab82532.c linux/drivers/sbus/char/sab82532.c
--- v2.4.1/linux/drivers/sbus/char/sab82532.c	Mon Dec 11 12:37:03 2000
+++ linux/drivers/sbus/char/sab82532.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: sab82532.c,v 1.54 2000/12/07 04:35:39 anton Exp $
+/* $Id: sab82532.c,v 1.55 2001/02/13 01:17:00 davem Exp $
  * sab82532.c: ASYNC Driver for the SIEMENS SAB82532 DUSCC.
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -24,7 +24,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 
@@ -2134,7 +2134,7 @@
 
 static inline void __init show_serial_version(void)
 {
-	char *revision = "$Revision: 1.54 $";
+	char *revision = "$Revision: 1.55 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/su.c linux/drivers/sbus/char/su.c
--- v2.4.1/linux/drivers/sbus/char/su.c	Tue Nov 14 23:36:01 2000
+++ linux/drivers/sbus/char/su.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: su.c,v 1.43 2000/11/15 07:28:09 davem Exp $
+/* $Id: su.c,v 1.44 2001/02/13 01:17:00 davem Exp $
  * su.c: Small serial driver for keyboard/mouse interface on sparc32/PCI
  *
  * Copyright (C) 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -61,7 +61,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/delay.h>
@@ -2220,7 +2220,7 @@
  */
 static __inline__ void __init show_su_version(void)
 {
-	char *revision = "$Revision: 1.43 $";
+	char *revision = "$Revision: 1.44 $";
 	char *version, *p;
 
 	version = strchr(revision, ' ');
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/uctrl.c linux/drivers/sbus/char/uctrl.c
--- v2.4.1/linux/drivers/sbus/char/uctrl.c	Thu Nov  9 15:57:41 2000
+++ linux/drivers/sbus/char/uctrl.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: uctrl.c,v 1.9 2000/11/08 05:04:06 davem Exp $
+/* $Id: uctrl.c,v 1.10 2001/02/13 01:17:00 davem Exp $
  * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3
  *
  * Copyright 1999 Derrick J Brashear (shadow@dementia.org)
@@ -9,7 +9,7 @@
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/miscdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/vfc_dev.c linux/drivers/sbus/char/vfc_dev.c
--- v2.4.1/linux/drivers/sbus/char/vfc_dev.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sbus/char/vfc_dev.c	Fri Feb  9 11:37:03 2001
@@ -17,11 +17,12 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
 #include <linux/smp_lock.h>
+#include <linux/delay.h>
 #include <linux/spinlock.h>
 
 #include <asm/openprom.h>
@@ -29,7 +30,6 @@
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/sbus.h>
-#include <asm/delay.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/char/vfc_i2c.c linux/drivers/sbus/char/vfc_i2c.c
--- v2.4.1/linux/drivers/sbus/char/vfc_i2c.c	Fri May  5 12:37:52 2000
+++ linux/drivers/sbus/char/vfc_i2c.c	Sun Feb 18 19:49:55 2001
@@ -20,7 +20,7 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
@@ -315,7 +315,7 @@
 		switch(ret) {
 		case XMIT_LAST_BYTE:
 			VFC_I2C_DEBUG_PRINTK(("vfc%d: "
-					      "Reciever ended transmission with "
+					      "Receiver ended transmission with "
 					      " %d bytes remaining\n",
 					      dev->instance, count));
 			ret = 0;
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/dvma.c linux/drivers/sbus/dvma.c
--- v2.4.1/linux/drivers/sbus/dvma.c	Thu Feb 17 09:26:31 2000
+++ linux/drivers/sbus/dvma.c	Fri Feb  9 11:37:03 2001
@@ -6,11 +6,11 @@
 #include <linux/config.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
+#include <linux/delay.h>
 
 #include <asm/oplib.h>
-#include <asm/delay.h>
 #include <asm/io.h>
 #include <asm/dma.h>
 #include <asm/sbus.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sbus/sbus.c linux/drivers/sbus/sbus.c
--- v2.4.1/linux/drivers/sbus/sbus.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sbus/sbus.c	Sun Feb 18 19:49:55 2001
@@ -1,11 +1,11 @@
-/* $Id: sbus.c,v 1.92 2001/01/25 17:15:59 davem Exp $
+/* $Id: sbus.c,v 1.94 2001/02/13 07:34:40 davem Exp $
  * sbus.c:  SBus support routines.
  *
  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/pci.h>
@@ -67,29 +67,12 @@
 	sdev->ranges_applied = 0;
 
 	base = (unsigned long) sdev->reg_addrs[0].phys_addr;
-	if (base >= SUN_SBUS_BVADDR ||
-	    (sparc_cpu_model != sun4c && sparc_cpu_model != sun4)) {
-		/* OK, we can compute the slot number in a
-		 * straightforward manner.
-		 */
-		if (sparc_cpu_model == sun4u ||
-		    sparc_cpu_model == sun4d)
-			sdev->slot = sdev->reg_addrs[0].which_io;
-		else
-			sdev->slot = sbus_dev_slot(base);
-	} else {
-		int rnum;
 
-		/* Fixups are needed to compute the slot number. */
+	/* Compute the slot number. */
+	if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
+		sdev->slot = sbus_dev_slot(base);
+	} else {
 		sdev->slot = sdev->reg_addrs[0].which_io;
-		sdev->reg_addrs[0].phys_addr =
-			sbus_devaddr(sdev->slot, base);
-		for (rnum = 1; rnum < sdev->num_registers; rnum++) {
-			base = (unsigned long)
-				sdev->reg_addrs[rnum].phys_addr;
-			sdev->reg_addrs[rnum].phys_addr =
-				sbus_devaddr(sdev->slot, base);
-		}
 	}
 
 no_regs:
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/53c7,8xx.c linux/drivers/scsi/53c7,8xx.c
--- v2.4.1/linux/drivers/scsi/53c7,8xx.c	Mon Sep 18 13:36:24 2000
+++ linux/drivers/scsi/53c7,8xx.c	Fri Feb  9 11:30:23 2001
@@ -229,7 +229,7 @@
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/53c7xx.c linux/drivers/scsi/53c7xx.c
--- v2.4.1/linux/drivers/scsi/53c7xx.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/53c7xx.c	Fri Feb  9 11:30:23 2001
@@ -246,7 +246,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/NCR5380.c linux/drivers/scsi/NCR5380.c
--- v2.4.1/linux/drivers/scsi/NCR5380.c	Fri Jul  7 15:55:24 2000
+++ linux/drivers/scsi/NCR5380.c	Fri Feb 16 16:02:36 2001
@@ -2264,8 +2264,8 @@
 		return -1;
 	}
 #if defined(REAL_DMA) || defined(REAL_DMA_POLL)
-#ifdef READ_OVERRUNS if (p & SR_IO) { c -= 2;
-}
+#ifdef READ_OVERRUNS 
+	if (p & SR_IO) { c -= 2; }
 #endif
 #if (NDEBUG & NDEBUG_DMA)
 printk("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n",
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/NCR5380.h linux/drivers/scsi/NCR5380.h
--- v2.4.1/linux/drivers/scsi/NCR5380.h	Sun Jun  7 10:37:41 1998
+++ linux/drivers/scsi/NCR5380.h	Tue Feb 13 13:15:04 2001
@@ -373,6 +373,6 @@
 }
 #endif /* defined(i386) || defined(__alpha__) */
 #endif /* defined(REAL_DMA)  */
-#endif __KERNEL_
+#endif /* __KERNEL__ */
 #endif /* ndef ASM */
 #endif /* NCR5380_H */
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/NCR53C9x.c linux/drivers/scsi/NCR53C9x.c
--- v2.4.1/linux/drivers/scsi/NCR53C9x.c	Mon Jun 19 17:59:41 2000
+++ linux/drivers/scsi/NCR53C9x.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/advansys.c linux/drivers/scsi/advansys.c
--- v2.4.1/linux/drivers/scsi/advansys.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/advansys.c	Fri Feb  9 11:30:23 2001
@@ -763,7 +763,7 @@
 #include <linux/types.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #if LINUX_VERSION_CODE >= ASC_LINUX_VERSION(1,3,0)
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.4.1/linux/drivers/scsi/aha152x.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/scsi/aha152x.c	Sun Feb  4 10:05:30 2001
@@ -1,6 +1,6 @@
 /* aha152x.c -- Adaptec AHA-152x driver
  * Author: Jürgen E. Fischer, fischer@norbit.de
- * Copyright 1993-1999 Jürgen E. Fischer
+ * Copyright 1993-2000 Jürgen E. Fischer
  *
  * 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
@@ -13,9 +13,13 @@
  * General Public License for more details.
  *
  *
- * $Id: aha152x.c,v 2.3 2000/11/04 16:40:26 fischer Exp $
+ * $Id: aha152x.c,v 2.4 2000/12/16 12:53:56 fischer Exp $
  *
  * $Log: aha152x.c,v $
+ * Revision 2.4  2000/12/16 12:53:56  fischer
+ * - allow REQUEST SENSE to be queued
+ * - handle shared PCI interrupts
+ *
  * Revision 2.3  2000/11/04 16:40:26  fischer
  * - handle data overruns
  * - extend timeout for data phases
@@ -299,7 +303,7 @@
                         (cmd) ? ((cmd)->target & 0x0f) : -1, \
 			(cmd) ? ((cmd)->lun & 0x07) : -1
 
-#define DELAY_DEFAULT 100
+#define DELAY_DEFAULT 1000
 
 /* possible irq range */
 #if defined(PCMCIA)
@@ -932,6 +936,8 @@
         	printk(KERN_ERR "aha152x%d: catched software interrupt for unknown controller.\n", HOSTNO);
 
 	HOSTDATA(shpnt)->swint++;
+
+	SETPORT(DMACNTRL0, INTEN);
 }
 
 
@@ -1231,18 +1237,12 @@
 		if (setup[i].reconnect)
 			shpnt->can_queue = AHA152X_MAXQUEUE;
 
-#if 0
-		if(!shpnt->hostt->use_new_eh_code) {
-#endif
-			/* RESET OUT */
-			printk("aha152x: resetting bus...\n");
-			SETPORT(SCSISEQ, SCSIRSTO);
-			mdelay(256);
-			SETPORT(SCSISEQ, 0);
-			mdelay(DELAY);
-#if 0
-		}
-#endif
+		/* RESET OUT */
+		printk("aha152x: resetting bus...\n");
+		SETPORT(SCSISEQ, SCSIRSTO);
+		mdelay(256);
+		SETPORT(SCSISEQ, 0);
+		mdelay(DELAY);
 
 		reset_ports(shpnt);
 
@@ -1274,7 +1274,7 @@
 		SETPORT(SIMODE0, 0);
 		SETPORT(SIMODE1, 0);
 
-		ok = request_irq(shpnt->irq, swintr, SA_INTERRUPT, "aha152x", shpnt);
+		ok = request_irq(shpnt->irq, swintr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt);
 		if (ok < 0) {
 			if (ok==-EINVAL)
 				printk(KERN_ERR "aha152x%d: bad IRQ %d.\n", HOSTNO, shpnt->irq);
@@ -1308,6 +1308,8 @@
 				printk("failed.\n");
 			}
 
+			SETPORT(DMACNTRL0, INTEN);
+
 			printk(KERN_ERR "aha152x%d: IRQ %d possibly wrong.  Please verify.\n", HOSTNO, shpnt->irq);
 
 			registered_count--;
@@ -1319,13 +1321,12 @@
 		}
 		printk("ok.\n");
 
-		SETPORT(DMACNTRL0, INTEN);
 
 		/* clear interrupts */
 		SETPORT(SSTAT0, 0x7f);
 		SETPORT(SSTAT1, 0xef);
 
-		if (request_irq(shpnt->irq, intr, SA_INTERRUPT, "aha152x", shpnt) < 0) {
+		if (request_irq(shpnt->irq, intr, SA_INTERRUPT|SA_SHIRQ, "aha152x", shpnt) < 0) {
 			printk(KERN_ERR "aha152x%d: failed to reassign interrupt.\n", HOSTNO);
 
 			scsi_unregister(shpnt);
@@ -1469,12 +1470,14 @@
 
 int aha152x_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *))
 {
+#if 0
 	if(*SCpnt->cmnd == REQUEST_SENSE) {
 		SCpnt->result = 0;
 		done(SCpnt);
 
-		return SUCCESS;
+		return 0;
 	}
+#endif
 
 	return aha152x_internal_queue(SCpnt, 0, 0, 0, done);
 }
@@ -1604,7 +1607,7 @@
 
 	init_timer(&timer);
 	timer.data     = (unsigned long) &sem;
-	timer.expires  = jiffies + 10 * HZ;   /* 10s */
+	timer.expires  = jiffies + 100*HZ;   /* 10s */
 	timer.function = (void (*)(unsigned long)) timer_expired;
 	add_timer(&timer);
 
@@ -1784,7 +1787,7 @@
 			if (info[0] == 255 && !EXT_TRANS) {
 				printk(KERN_NOTICE
 				       "aha152x: current partition table is using extended translation.\n"
-				       "         using it also, although it's not explictly enabled.\n");
+				       "         using it also, although it's not explicitly enabled.\n");
 			}
 		}
 	}
@@ -2579,7 +2582,7 @@
 		if(TESTHI(DMASTAT, DFIFOFULL)) {
 			fifodata = 128;
 		} else {
-			the_time=jiffies + HZ;
+			the_time=jiffies + 10*HZ;
 			while(TESTLO(SSTAT2, SEMPTY) && time_before(jiffies,the_time))
 				barrier();
 
@@ -2735,7 +2738,7 @@
 			CURRENT_SC->SCp.this_residual = CURRENT_SC->SCp.buffer->length;
 		}
 
-		the_time=jiffies+10*HZ;
+		the_time=jiffies + 10*HZ;
 		while(TESTLO(DMASTAT, DFIFOEMP|INTSTAT) && time_before(jiffies,the_time))
 			barrier();
 
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/aha152x.h linux/drivers/scsi/aha152x.h
--- v2.4.1/linux/drivers/scsi/aha152x.h	Mon Dec 11 13:19:02 2000
+++ linux/drivers/scsi/aha152x.h	Sun Feb  4 10:05:30 2001
@@ -2,7 +2,7 @@
 #define _AHA152X_H
 
 /*
- * $Id: aha152x.h,v 2.3 2000/11/04 16:41:37 fischer Exp $
+ * $Id: aha152x.h,v 2.4 2000/12/16 12:48:48 fischer Exp $
  */
 
 #if defined(__KERNEL__)
@@ -27,7 +27,7 @@
    (unless we support more than 1 cmd_per_lun this should do) */
 #define AHA152X_MAXQUEUE 7
 
-#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.3 $"
+#define AHA152X_REVID "Adaptec 152x SCSI driver; $Revision: 2.4 $"
 
 /* Initial value of Scsi_Host entry */
 #define AHA152X { proc_name:			"aha152x",		\
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/aha1542.c linux/drivers/scsi/aha1542.c
--- v2.4.1/linux/drivers/scsi/aha1542.c	Thu Nov 23 09:33:36 2000
+++ linux/drivers/scsi/aha1542.c	Tue Feb 13 14:13:44 2001
@@ -136,6 +136,18 @@
 int aha1542[] = {0x330, 11, 4, -1};
 MODULE_PARM(aha1542, "1-4i");
 MODULE_PARM(isapnp, "i");
+
+static struct isapnp_device_id id_table[] __devinitdata = {
+	{
+		ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('A', 'D', 'P'), ISAPNP_FUNCTION(0x1542),
+		0
+	},
+	{0}
+};
+
+MODULE_DEVICE_TABLE(isapnp, id_table);
+
 #else
 int isapnp=1;
 #endif
@@ -947,11 +959,12 @@
 	return 0;
 }
 
-/* called from init/main.c */
+#ifndef MODULE
+static int setup_idx = 0;
+
 void __init aha1542_setup(char *str, int *ints)
 {
 	const char *ahausage = "aha1542: usage: aha1542=<PORTBASE>[,<BUSON>,<BUSOFF>[,<DMASPEED>]]\n";
-	static int setup_idx = 0;
 	int setup_portbase;
 
 	if (setup_idx >= MAXBOARDS) {
@@ -1004,6 +1017,21 @@
 
 	++setup_idx;
 }
+
+static int __init do_setup(char *str)
+{
+	int ints[4];
+
+	int count=setup_idx;
+
+	get_options(str, sizeof(ints)/sizeof(int), ints);
+	aha1542_setup(str,ints);
+
+	return count<setup_idx;
+}
+
+__setup("aha1542=",do_setup);
+#endif
 
 /* return non-zero on detection */
 int aha1542_detect(Scsi_Host_Template * tpnt)
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/aic7xxx.c linux/drivers/scsi/aic7xxx.c
--- v2.4.1/linux/drivers/scsi/aic7xxx.c	Thu Oct 12 14:19:32 2000
+++ linux/drivers/scsi/aic7xxx.c	Fri Feb  9 11:30:23 2001
@@ -256,7 +256,7 @@
 #include <scsi/scsicam.h>
 
 #include <linux/stat.h>
-#include <linux/malloc.h>        /* for kmalloc() */
+#include <linux/slab.h>        /* for kmalloc() */
 
 #include <linux/config.h>        /* for CONFIG_PCI */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/blz1230.c linux/drivers/scsi/blz1230.c
--- v2.4.1/linux/drivers/scsi/blz1230.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/scsi/blz1230.c	Fri Feb  9 11:30:23 2001
@@ -21,7 +21,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/blz2060.c linux/drivers/scsi/blz2060.c
--- v2.4.1/linux/drivers/scsi/blz2060.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/scsi/blz2060.c	Fri Feb  9 11:30:23 2001
@@ -21,7 +21,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/cpqfcTScontrol.c linux/drivers/scsi/cpqfcTScontrol.c
--- v2.4.1/linux/drivers/scsi/cpqfcTScontrol.c	Tue Sep 19 08:01:34 2000
+++ linux/drivers/scsi/cpqfcTScontrol.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
 #include <linux/string.h>
 #include <linux/ioport.h>  // request_region() prototype
 #include <linux/sched.h>
-#include <linux/malloc.h>  // need "kfree" for ext. S/G pages
+#include <linux/slab.h>  // need "kfree" for ext. S/G pages
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/cpqfcTSinit.c linux/drivers/scsi/cpqfcTSinit.c
--- v2.4.1/linux/drivers/scsi/cpqfcTSinit.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/cpqfcTSinit.c	Fri Feb  9 11:30:23 2001
@@ -1686,7 +1686,7 @@
 
 
 
-#include "linux/malloc.h"
+#include "linux/slab.h"
 
 // Dynamic memory allocation alignment routines
 // HP's Tachyon Fibre Channel Controller chips require
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/cpqfcTSworker.c linux/drivers/scsi/cpqfcTSworker.c
--- v2.4.1/linux/drivers/scsi/cpqfcTSworker.c	Tue Sep 19 08:01:35 2000
+++ linux/drivers/scsi/cpqfcTSworker.c	Fri Feb  9 11:30:23 2001
@@ -22,7 +22,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/cyberstorm.c linux/drivers/scsi/cyberstorm.c
--- v2.4.1/linux/drivers/scsi/cyberstorm.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/scsi/cyberstorm.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/cyberstormII.c linux/drivers/scsi/cyberstormII.c
--- v2.4.1/linux/drivers/scsi/cyberstormII.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/scsi/cyberstormII.c	Fri Feb  9 11:30:23 2001
@@ -20,7 +20,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/dec_esp.c linux/drivers/scsi/dec_esp.c
--- v2.4.1/linux/drivers/scsi/dec_esp.c	Sun Jul  9 22:22:57 2000
+++ linux/drivers/scsi/dec_esp.c	Fri Feb  9 11:30:23 2001
@@ -15,7 +15,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/eata.c linux/drivers/scsi/eata.c
--- v2.4.1/linux/drivers/scsi/eata.c	Mon Nov 27 17:49:00 2000
+++ linux/drivers/scsi/eata.c	Fri Feb 16 16:02:36 2001
@@ -1,6 +1,12 @@
 /*
  *      eata.c - Low-level driver for EATA/DMA SCSI host adapters.
  *
+ *      30 Jan 2001 Rev. 6.04 for linux 2.4.1
+ *        + Call pci_resource_start after pci_enable_device.
+ *
+ *      25 Jan 2001 Rev. 6.03 for linux 2.4.0
+ *        + "check_region" call replaced by "request_region".
+ *
  *      22 Nov 2000 Rev. 6.02 for linux 2.4.0-test11
  *        + Return code checked when calling pci_enable_device.
  *        + Removed old scsi error handling support.
@@ -210,7 +216,7 @@
  *          This driver is based on the CAM (Common Access Method Committee)
  *          EATA (Enhanced AT Bus Attachment) rev. 2.0A, using DMA protocol.
  *
- *  Copyright (C) 1994-2000 Dario Ballabio (ballabio_dario@emc.com)
+ *  Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
  *
  *  Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
  *
@@ -835,10 +841,10 @@
 
       if (!(dev = pci_find_class(PCI_CLASS_STORAGE_SCSI << 8, dev))) break;
 
-      addr = pci_resource_start (dev, 0);
-
       if (pci_enable_device (dev)) continue;
 
+      addr = pci_resource_start (dev, 0);
+
 #if defined(DEBUG_PCI_DETECT)
       printk("%s: tune_pci_port, bus %d, devfn 0x%x, addr 0x%x.\n",
              driver_name, dev->bus->number, dev->devfn, addr);
@@ -901,25 +907,34 @@
 
    sprintf(name, "%s%d", driver_name, j);
 
-   if(check_region(port_base, REGION_SIZE)) {
+   if(!request_region(port_base, REGION_SIZE, driver_name)) {
 #if defined(DEBUG_DETECT)
       printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
 #endif
       return FALSE;
       }
 
-   if (do_dma(port_base, 0, READ_CONFIG_PIO)) return FALSE;
+   if (do_dma(port_base, 0, READ_CONFIG_PIO)) {
+      release_region(port_base, REGION_SIZE);
+      return FALSE;
+      }
 
    /* Read the info structure */
-   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0]))
+   if (read_pio(port_base, (ushort *)&info, (ushort *)&info.ipad[0])) {
+      release_region(port_base, REGION_SIZE);
       return FALSE;
+      }
 
    /* Check the controller "EATA" signature */
-   if (info.sign != EATA_SIGNATURE) return FALSE;
+   if (info.sign != EATA_SIGNATURE) {
+      release_region(port_base, REGION_SIZE);
+      return FALSE;
+      }
 
    if (DEV2H(info.data_len) < EATA_2_0A_SIZE) {
       printk("%s: config structure size (%d bytes) too short, detaching.\n",
              name, DEV2H(info.data_len));
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
    else if (DEV2H(info.data_len) == EATA_2_0A_SIZE)
@@ -957,6 +972,7 @@
    if (!info.haaval || info.ata) {
       printk("%s: address 0x%03lx, unusable %s board (%d%d), detaching.\n",
              name, port_base, bus_type, info.haaval, info.ata);
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -996,6 +1012,7 @@
              SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
              driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -1003,6 +1020,7 @@
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
              name, dma_channel);
       free_irq(irq, &sha[j]);
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -1017,6 +1035,7 @@
 
    if (do_dma(port_base, (unsigned long)&config, SET_CONFIG_DMA)) {
       printk("%s: busy timeout sending configuration, detaching.\n", name);
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
    }
@@ -1031,6 +1050,7 @@
 
       if (subversion == ISA) free_dma(dma_channel);
 
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -1129,7 +1149,7 @@
    else                                 tag_type = 'n';
 
    if (j == 0) {
-      printk("EATA/DMA 2.0x: Copyright (C) 1994-2000 Dario Ballabio.\n");
+      printk("EATA/DMA 2.0x: Copyright (C) 1994-2001 Dario Ballabio.\n");
       printk("%s config options -> tc:%c, lc:%c, mq:%d, rs:%c, et:%c.\n",
              driver_name, tag_type, YESNO(linked_comm), max_queue_depth,
              YESNO(rev_scan), YESNO(ext_tran));
@@ -1149,7 +1169,7 @@
 
 #if defined(DEBUG_DETECT)
    printk("%s: Vers. 0x%x, ocs %u, tar %u, trnxfr %u, more %u, SYNC 0x%x, "\
-          "sec. %u, infol %ld, cpl %ld spl %ld.\n", name, info.version,
+          "sec. %u, infol %d, cpl %d spl %d.\n", name, info.version,
           info.ocsena, info.tarsup, info.trnxfr, info.morsup, info.sync,
           info.second, DEV2H(info.data_len), DEV2H(info.cp_len),
           DEV2H(info.sp_len));
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/eata.h linux/drivers/scsi/eata.h
--- v2.4.1/linux/drivers/scsi/eata.h	Mon Nov 27 17:49:00 2000
+++ linux/drivers/scsi/eata.h	Fri Feb 16 16:02:36 2001
@@ -13,7 +13,7 @@
 int eata2x_reset(Scsi_Cmnd *);
 int eata2x_biosparam(Disk *, kdev_t, int *);
 
-#define EATA_VERSION "6.02.00"
+#define EATA_VERSION "6.04.00"
 
 #define EATA {                                                               \
                 name:              "EATA/DMA 2.0x rev. " EATA_VERSION " ",   \
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/eata_dma.c linux/drivers/scsi/eata_dma.c
--- v2.4.1/linux/drivers/scsi/eata_dma.c	Sun Dec 31 10:26:18 2000
+++ linux/drivers/scsi/eata_dma.c	Fri Feb  9 11:30:23 2001
@@ -68,7 +68,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/eata_pio.c linux/drivers/scsi/eata_pio.c
--- v2.4.1/linux/drivers/scsi/eata_pio.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/eata_pio.c	Fri Feb  9 11:30:23 2001
@@ -43,7 +43,7 @@
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/pci.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/esp.c linux/drivers/scsi/esp.c
--- v2.4.1/linux/drivers/scsi/esp.c	Thu Nov  9 15:57:41 2000
+++ linux/drivers/scsi/esp.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: esp.c,v 1.98 2000/11/02 22:34:16 davem Exp $
+/* $Id: esp.c,v 1.99 2001/02/13 01:17:01 davem Exp $
  * esp.c:  EnhancedScsiProcessor Sun SCSI driver code.
  *
  * Copyright (C) 1995, 1998 David S. Miller (davem@caip.rutgers.edu)
@@ -18,7 +18,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/fastlane.c linux/drivers/scsi/fastlane.c
--- v2.4.1/linux/drivers/scsi/fastlane.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/scsi/fastlane.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/fcal.c linux/drivers/scsi/fcal.c
--- v2.4.1/linux/drivers/scsi/fcal.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/fcal.c	Fri Feb  9 11:30:23 2001
@@ -8,7 +8,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/ide-scsi.c linux/drivers/scsi/ide-scsi.c
--- v2.4.1/linux/drivers/scsi/ide-scsi.c	Mon Nov 27 17:57:34 2000
+++ linux/drivers/scsi/ide-scsi.c	Fri Feb  9 11:30:23 2001
@@ -40,7 +40,7 @@
 #include <linux/blkdev.h>
 #include <linux/errno.h>
 #include <linux/hdreg.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ide.h>
 
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c
--- v2.4.1/linux/drivers/scsi/ini9100u.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/ini9100u.c	Fri Feb  9 11:30:23 2001
@@ -136,7 +136,7 @@
 #include "scsi.h"
 #include "sd.h"
 #include "hosts.h"
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include "ini9100u.h"
 
 #ifdef DEBUG_i91u
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/inia100.c linux/drivers/scsi/inia100.c
--- v2.4.1/linux/drivers/scsi/inia100.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/inia100.c	Fri Feb  9 11:30:23 2001
@@ -89,7 +89,7 @@
 #include "scsi.h"
 #include "sd.h"
 #include "hosts.h"
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include "inia100.h"
 
 static Scsi_Host_Template driver_template = INIA100;
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/ips.c linux/drivers/scsi/ips.c
--- v2.4.1/linux/drivers/scsi/ips.c	Wed Nov  8 17:09:50 2000
+++ linux/drivers/scsi/ips.c	Fri Feb  9 11:30:23 2001
@@ -123,7 +123,7 @@
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/ioport.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/jazz_esp.c linux/drivers/scsi/jazz_esp.c
--- v2.4.1/linux/drivers/scsi/jazz_esp.c	Thu Feb 24 22:51:47 2000
+++ linux/drivers/scsi/jazz_esp.c	Fri Feb  9 11:30:23 2001
@@ -10,7 +10,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/mac53c94.c linux/drivers/scsi/mac53c94.c
--- v2.4.1/linux/drivers/scsi/mac53c94.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/mac53c94.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/mac_esp.c linux/drivers/scsi/mac_esp.c
--- v2.4.1/linux/drivers/scsi/mac_esp.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/scsi/mac_esp.c	Fri Feb  9 11:30:23 2001
@@ -18,7 +18,7 @@
 #include <linux/types.h>
 #include <linux/ctype.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/mca_53c9x.c linux/drivers/scsi/mca_53c9x.c
--- v2.4.1/linux/drivers/scsi/mca_53c9x.c	Mon Sep 18 13:36:25 2000
+++ linux/drivers/scsi/mca_53c9x.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/mesh.c linux/drivers/scsi/mesh.c
--- v2.4.1/linux/drivers/scsi/mesh.c	Tue Sep 19 08:31:53 2000
+++ linux/drivers/scsi/mesh.c	Fri Feb  9 11:30:23 2001
@@ -12,7 +12,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/ncr53c8xx.c linux/drivers/scsi/ncr53c8xx.c
--- v2.4.1/linux/drivers/scsi/ncr53c8xx.c	Mon Sep 18 13:36:25 2000
+++ linux/drivers/scsi/ncr53c8xx.c	Fri Feb  9 11:30:23 2001
@@ -136,7 +136,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/time.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/oktagon_esp.c linux/drivers/scsi/oktagon_esp.c
--- v2.4.1/linux/drivers/scsi/oktagon_esp.c	Mon Oct 16 12:51:16 2000
+++ linux/drivers/scsi/oktagon_esp.c	Fri Feb  9 11:30:23 2001
@@ -19,7 +19,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/pci2220i.c linux/drivers/scsi/pci2220i.c
--- v2.4.1/linux/drivers/scsi/pci2220i.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/scsi/pci2220i.c	Fri Feb  9 11:30:23 2001
@@ -40,7 +40,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/pcmcia/aha152x_stub.c linux/drivers/scsi/pcmcia/aha152x_stub.c
--- v2.4.1/linux/drivers/scsi/pcmcia/aha152x_stub.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/scsi/pcmcia/aha152x_stub.c	Fri Feb  9 11:30:23 2001
@@ -38,7 +38,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/pcmcia/apa1480_stub.c linux/drivers/scsi/pcmcia/apa1480_stub.c
--- v2.4.1/linux/drivers/scsi/pcmcia/apa1480_stub.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/scsi/pcmcia/apa1480_stub.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/pcmcia/fdomain_stub.c linux/drivers/scsi/pcmcia/fdomain_stub.c
--- v2.4.1/linux/drivers/scsi/pcmcia/fdomain_stub.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/scsi/pcmcia/fdomain_stub.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/pcmcia/qlogic_stub.c linux/drivers/scsi/pcmcia/qlogic_stub.c
--- v2.4.1/linux/drivers/scsi/pcmcia/qlogic_stub.c	Sat Sep  2 00:15:37 2000
+++ linux/drivers/scsi/pcmcia/qlogic_stub.c	Fri Feb  9 11:30:23 2001
@@ -35,7 +35,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/pluto.c linux/drivers/scsi/pluto.c
--- v2.4.1/linux/drivers/scsi/pluto.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/pluto.c	Fri Feb  9 11:30:23 2001
@@ -8,7 +8,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/qla1280.c linux/drivers/scsi/qla1280.c
--- v2.4.1/linux/drivers/scsi/qla1280.c	Wed Dec  6 12:06:18 2000
+++ linux/drivers/scsi/qla1280.c	Fri Feb  9 11:30:23 2001
@@ -220,7 +220,7 @@
 #include "ql1280_fw.h"
 
 #include <linux/stat.h>
-#include <linux/malloc.h>        /* for kmalloc() */
+#include <linux/slab.h>        /* for kmalloc() */
 
 
 #ifndef KERNEL_VERSION
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/qlogicpti.c linux/drivers/scsi/qlogicpti.c
--- v2.4.1/linux/drivers/scsi/qlogicpti.c	Mon Sep 18 13:36:25 2000
+++ linux/drivers/scsi/qlogicpti.c	Fri Feb  9 11:30:23 2001
@@ -16,7 +16,7 @@
 #include <linux/delay.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi.c linux/drivers/scsi/scsi.c
--- v2.4.1/linux/drivers/scsi/scsi.c	Mon Oct 30 14:44:29 2000
+++ linux/drivers/scsi/scsi.c	Fri Feb  9 11:30:23 2001
@@ -45,7 +45,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_error.c linux/drivers/scsi/scsi_error.c
--- v2.4.1/linux/drivers/scsi/scsi_error.c	Wed Nov  8 17:09:50 2000
+++ linux/drivers/scsi/scsi_error.c	Fri Feb  9 11:30:23 2001
@@ -14,7 +14,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c
--- v2.4.1/linux/drivers/scsi/scsi_ioctl.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/scsi/scsi_ioctl.c	Sun Feb  4 10:05:30 2001
@@ -101,7 +101,10 @@
 
 
 	SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", cmd[0]));
-	SRpnt = scsi_allocate_request(dev);
+	if (NULL == (SRpnt = scsi_allocate_request(dev))) {
+		printk("SCSI internal ioctl failed, no memory\n");
+		return -ENOMEM;
+	}
 
 	SRpnt->sr_data_direction = SCSI_DATA_NONE;
         scsi_wait_req(SRpnt, cmd, NULL, 0, timeout, retries);
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_lib.c linux/drivers/scsi/scsi_lib.c
--- v2.4.1/linux/drivers/scsi/scsi_lib.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/scsi/scsi_lib.c	Fri Feb  9 11:30:23 2001
@@ -23,7 +23,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_merge.c linux/drivers/scsi/scsi_merge.c
--- v2.4.1/linux/drivers/scsi/scsi_merge.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/scsi/scsi_merge.c	Fri Feb  9 11:30:23 2001
@@ -39,7 +39,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_obsolete.c linux/drivers/scsi/scsi_obsolete.c
--- v2.4.1/linux/drivers/scsi/scsi_obsolete.c	Thu Nov  9 15:57:41 2000
+++ linux/drivers/scsi/scsi_obsolete.c	Fri Feb  9 11:30:23 2001
@@ -52,7 +52,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_proc.c linux/drivers/scsi/scsi_proc.c
--- v2.4.1/linux/drivers/scsi/scsi_proc.c	Mon Dec 20 22:05:10 1999
+++ linux/drivers/scsi/scsi_proc.c	Fri Feb  9 11:30:23 2001
@@ -22,7 +22,7 @@
 
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 #include <linux/errno.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_queue.c linux/drivers/scsi/scsi_queue.c
--- v2.4.1/linux/drivers/scsi/scsi_queue.c	Sun Sep 17 10:09:29 2000
+++ linux/drivers/scsi/scsi_queue.c	Fri Feb  9 11:30:23 2001
@@ -16,7 +16,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_scan.c linux/drivers/scsi/scsi_scan.c
--- v2.4.1/linux/drivers/scsi/scsi_scan.c	Tue Sep 19 08:01:34 2000
+++ linux/drivers/scsi/scsi_scan.c	Sun Feb  4 10:05:30 2001
@@ -492,7 +492,10 @@
 	SDpnt->expecting_cc_ua = 0;
 	SDpnt->starved = 0;
 
-	SRpnt = scsi_allocate_request(SDpnt);
+	if (NULL == (SRpnt = scsi_allocate_request(SDpnt))) {
+		printk("scan_scsis_single: no memory\n");
+		return 0;
+	}
 
 	/*
 	 * We used to do a TEST_UNIT_READY before the INQUIRY but that was 
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/scsi_syms.c linux/drivers/scsi/scsi_syms.c
--- v2.4.1/linux/drivers/scsi/scsi_syms.c	Wed Sep 20 13:11:53 2000
+++ linux/drivers/scsi/scsi_syms.c	Fri Feb  9 11:30:23 2001
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
 #include <linux/blk.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c
--- v2.4.1/linux/drivers/scsi/sd.c	Thu Oct 26 23:35:48 2000
+++ linux/drivers/scsi/sd.c	Sat Feb  3 11:45:55 2001
@@ -798,9 +798,9 @@
 				SRpnt->sr_data_direction = SCSI_DATA_READ;
 				scsi_wait_req(SRpnt, (void *) cmd, (void *) buffer,
 					    0/*512*/, SD_TIMEOUT, MAX_RETRIES);
+				spintime_value = jiffies;
 			}
 			spintime = 1;
-			spintime_value = jiffies;
 			time1 = HZ;
 			/* Wait 1 second for next try */
 			do {
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/sr.c linux/drivers/scsi/sr.c
--- v2.4.1/linux/drivers/scsi/sr.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/scsi/sr.c	Mon Feb 19 10:25:17 2001
@@ -88,7 +88,6 @@
 static int *sr_sizes;
 
 static int *sr_blocksizes;
-static int *sr_hardsizes;
 
 static int sr_open(struct cdrom_device_info *, int);
 void get_sectorsize(int);
@@ -349,7 +348,7 @@
 	devm = MINOR(SCpnt->request.rq_dev);
 	dev = DEVICE_NR(SCpnt->request.rq_dev);
 
-	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d, block = %d\n", devm, block));
+	SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %d\n", devm));
 
 	if (dev >= sr_template.nr_dev ||
 	    !scsi_CDs[dev].device ||
@@ -783,21 +782,16 @@
 	if (!sr_blocksizes)
 		goto cleanup_sizes;
 
-	sr_hardsizes = kmalloc(sr_template.dev_max * sizeof(int), GFP_ATOMIC);
-	if (!sr_hardsizes)
-		goto cleanup_blocksizes;
 	/*
 	 * These are good guesses for the time being.
+	 * Don't set sr_hardsizes here! That will prevent reading anything smaller.
 	 */
 	for (i = 0; i < sr_template.dev_max; i++) {
 		sr_blocksizes[i] = 2048;
-		sr_hardsizes[i] = 2048;
         }
 	blksize_size[MAJOR_NR] = sr_blocksizes;
-        hardsect_size[MAJOR_NR] = sr_hardsizes;
 	return 0;
-cleanup_blocksizes:
-	kfree(sr_blocksizes);
+
 cleanup_sizes:
 	kfree(sr_sizes);
 cleanup_cds:
@@ -921,11 +915,8 @@
 
 		kfree(sr_blocksizes);
 		sr_blocksizes = NULL;
-		kfree(sr_hardsizes);
-		sr_hardsizes = NULL;
 	}
 	blksize_size[MAJOR_NR] = NULL;
-        hardsect_size[MAJOR_NR] = NULL;
 	blk_size[MAJOR_NR] = NULL;
 	read_ahead[MAJOR_NR] = 0;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/sun3x_esp.c linux/drivers/scsi/sun3x_esp.c
--- v2.4.1/linux/drivers/scsi/sun3x_esp.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/scsi/sun3x_esp.c	Fri Feb  9 11:30:23 2001
@@ -8,7 +8,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blk.h>
 #include <linux/proc_fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/sym53c8xx.c linux/drivers/scsi/sym53c8xx.c
--- v2.4.1/linux/drivers/scsi/sym53c8xx.c	Mon Jan  1 10:23:21 2001
+++ linux/drivers/scsi/sym53c8xx.c	Fri Feb  9 11:30:23 2001
@@ -126,7 +126,7 @@
 #include <linux/errno.h>
 #include <linux/pci.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/time.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c
--- v2.4.1/linux/drivers/scsi/tmscsim.c	Thu Jan  4 15:25:55 2001
+++ linux/drivers/scsi/tmscsim.c	Fri Feb 16 16:06:17 2001
@@ -3054,7 +3054,4 @@
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99)
 static Scsi_Host_Template driver_template = DC390_T;
 #include "scsi_module.c"
-#elif defined(MODULE)
-Scsi_Host_Template driver_template = DC390_T;
-#include "scsi_module.c"
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/u14-34f.c linux/drivers/scsi/u14-34f.c
--- v2.4.1/linux/drivers/scsi/u14-34f.c	Mon Nov 27 17:49:00 2000
+++ linux/drivers/scsi/u14-34f.c	Sun Feb  4 10:05:30 2001
@@ -1,7 +1,10 @@
 /*
  *      u14-34f.c - Low-level driver for UltraStor 14F/34F SCSI host adapters.
  *
- *      01 Nov 2000 Rev. 6.02 for linux 2.4.0-test11
+ *      25 Jan 2001 Rev. 6.03 for linux 2.4.0
+ *        + "check_region" call replaced by "request_region".
+ *
+ *      22 Nov 2000 Rev. 6.02 for linux 2.4.0-test11
  *        + Removed old scsi error handling support.
  *        + The obsolete boot option flag eh:n is silently ignored.
  *        + Removed error messages while a disk drive is powered up at
@@ -177,7 +180,7 @@
  *
  *          Multiple U14F and/or U34F host adapters are supported.
  *
- *  Copyright (C) 1994-2000 Dario Ballabio (ballabio_dario@emc.com)
+ *  Copyright (C) 1994-2001 Dario Ballabio (ballabio_dario@emc.com)
  *
  *  Alternate email: dario.ballabio@inwind.it, dario.ballabio@tiscalinet.it
  *
@@ -729,18 +732,24 @@
 
    sprintf(name, "%s%d", driver_name, j);
 
-   if(check_region(port_base, REGION_SIZE)) {
+   if(!request_region(port_base, REGION_SIZE, driver_name)) {
 #if defined(DEBUG_DETECT)
       printk("%s: address 0x%03lx in use, skipping probe.\n", name, port_base);
 #endif
       return FALSE;
       }
 
-   if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) return FALSE;
+   if (inb(port_base + REG_PRODUCT_ID1) != PRODUCT_ID1) {
+      release_region(port_base, REGION_SIZE);
+      return FALSE;
+      }
 
    in_byte = inb(port_base + REG_PRODUCT_ID2);
 
-   if ((in_byte & 0xf0) != PRODUCT_ID2) return FALSE;
+   if ((in_byte & 0xf0) != PRODUCT_ID2) {
+      release_region(port_base, REGION_SIZE);
+      return FALSE;
+      }
 
    *(char *)&config_1 = inb(port_base + REG_CONFIG1);
    *(char *)&config_2 = inb(port_base + REG_CONFIG2);
@@ -754,6 +763,7 @@
              SA_INTERRUPT | ((subversion == ESA) ? SA_SHIRQ : 0),
              driver_name, (void *) &sha[j])) {
       printk("%s: unable to allocate IRQ %u, detaching.\n", name, irq);
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -761,6 +771,7 @@
       printk("%s: unable to allocate DMA channel %u, detaching.\n",
              name, dma_channel);
       free_irq(irq, &sha[j]);
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -775,6 +786,7 @@
 
       if (subversion == ISA) free_dma(dma_channel);
 
+      release_region(port_base, REGION_SIZE);
       return FALSE;
       }
 
@@ -805,9 +817,6 @@
    /* If BIOS is disabled, force enable interrupts */
    if (sh[j]->base == 0) outb(CMD_ENA_INTR, sh[j]->io_port + REG_SYS_MASK);
 
-   /* Register the I/O space that we use */
-   request_region(sh[j]->io_port, sh[j]->n_io_port, driver_name);
-
    memset(HD(j), 0, sizeof(struct hostdata));
    HD(j)->heads = mapping_table[config_2.mapping_mode].heads;
    HD(j)->sectors = mapping_table[config_2.mapping_mode].sectors;
@@ -873,7 +882,7 @@
    if (max_queue_depth < MAX_CMD_PER_LUN) max_queue_depth = MAX_CMD_PER_LUN;
 
    if (j == 0) {
-      printk("UltraStor 14F/34F: Copyright (C) 1994-2000 Dario Ballabio.\n");
+      printk("UltraStor 14F/34F: Copyright (C) 1994-2001 Dario Ballabio.\n");
       printk("%s config options -> of:%c, lc:%c, mq:%d, et:%c.\n",
              driver_name, YESNO(have_old_firmware), YESNO(linked_comm),
              max_queue_depth, YESNO(ext_tran));
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/u14-34f.h linux/drivers/scsi/u14-34f.h
--- v2.4.1/linux/drivers/scsi/u14-34f.h	Mon Nov 27 17:49:00 2000
+++ linux/drivers/scsi/u14-34f.h	Sun Feb  4 10:05:30 2001
@@ -13,7 +13,7 @@
 int u14_34f_reset(Scsi_Cmnd *);
 int u14_34f_biosparam(Disk *, kdev_t, int *);
 
-#define U14_34F_VERSION "6.02.00"
+#define U14_34F_VERSION "6.03.00"
 
 #define ULTRASTOR_14_34F {                                                   \
                 name:         "UltraStor 14F/34F rev. " U14_34F_VERSION " ", \
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/ultrastor.c linux/drivers/scsi/ultrastor.c
--- v2.4.1/linux/drivers/scsi/ultrastor.c	Mon Sep 18 13:36:25 2000
+++ linux/drivers/scsi/ultrastor.c	Sat Feb  3 11:32:54 2001
@@ -328,7 +328,7 @@
 {
   static char fmt[80] = "abort %d (%x); MSCP free pool: %x;";
   register int i;
-  int flags;
+  unsigned long flags;
   save_flags(flags);
   cli();
 
@@ -676,7 +676,7 @@
     int mscp_index;
 #endif
     unsigned int status;
-    int flags;
+    unsigned long flags;
 
     /* Next test is for debugging; "can't happen" */
     if ((config.mscp_free & ((1U << ULTRASTOR_MAX_CMDS) - 1)) == 0)
@@ -848,7 +848,7 @@
       {
 	int port0 = (config.slot << 12) | 0xc80;
 	int i;
-	int flags;
+	unsigned long flags;
 	save_flags(flags);
 	cli();
 	strcpy(out, "OGM %d:%x ICM %d:%x ports:  ");
@@ -874,7 +874,7 @@
     if (config.slot ? inb(config.icm_address - 1) == 2 :
 	(inb(SYS_DOORBELL_INTR(config.doorbell_address)) & 1))
       {
-	int flags;
+	unsigned long flags;
 	save_flags(flags);
 	printk("Ux4F: abort while completed command pending\n");
 	restore_flags(flags);
@@ -896,7 +896,7 @@
        and the interrupt handler will call done.  */
     if (config.slot && inb(config.ogm_address - 1) == 0)
       {
-	int flags;
+	unsigned long flags;
 
 	save_flags(flags);
 	cli();
@@ -948,7 +948,7 @@
 
 int ultrastor_reset(Scsi_Cmnd * SCpnt, unsigned int reset_flags)
 {
-    int flags;
+    unsigned long flags;
     register int i;
 #if (ULTRASTOR_DEBUG & UD_RESET)
     printk("US14F: reset: called\n");
diff -u --recursive --new-file v2.4.1/linux/drivers/scsi/wd7000.c linux/drivers/scsi/wd7000.c
--- v2.4.1/linux/drivers/scsi/wd7000.c	Sat Nov 11 19:01:11 2000
+++ linux/drivers/scsi/wd7000.c	Fri Feb  9 11:30:23 2001
@@ -151,7 +151,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <asm/system.h>
 #include <asm/dma.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sgi/char/ds1286.c linux/drivers/sgi/char/ds1286.c
--- v2.4.1/linux/drivers/sgi/char/ds1286.c	Wed Jul 12 21:58:43 2000
+++ linux/drivers/sgi/char/ds1286.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/miscdevice.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sgi/char/graphics.c linux/drivers/sgi/char/graphics.c
--- v2.4.1/linux/drivers/sgi/char/graphics.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/sgi/char/graphics.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/Config.in linux/drivers/sound/Config.in
--- v2.4.1/linux/drivers/sound/Config.in	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sound/Config.in	Fri Feb 16 16:02:36 2001
@@ -21,6 +21,8 @@
 dep_tristate '  Creative Ensoniq AudioPCI 97 (ES1371)' CONFIG_SOUND_ES1371 $CONFIG_SOUND
 dep_tristate '  ESS Technology Solo1' CONFIG_SOUND_ESSSOLO1 $CONFIG_SOUND
 dep_tristate '  ESS Maestro, Maestro2, Maestro2E driver' CONFIG_SOUND_MAESTRO $CONFIG_SOUND
+dep_tristate '  ESS Maestro3/Allegro driver (EXPERIMENTAL)' CONFIG_SOUND_MAESTRO3 $CONFIG_SOUND $CONFIG_PCI $CONFIG_EXPERIMENTAL
+dep_tristate '  Intel ICH (i8xx) audio support' CONFIG_SOUND_ICH $CONFIG_PCI
 dep_tristate '  S3 SonicVibes' CONFIG_SOUND_SONICVIBES $CONFIG_SOUND
 if [ "$CONFIG_VISWS" = "y" ]; then
     dep_tristate '  SGI Visual Workstation Sound' CONFIG_SOUND_VWSND $CONFIG_SOUND
@@ -99,7 +101,6 @@
       bool '      16 bit sampling option of GUS (_NOT_ GUS MAX)' CONFIG_SOUND_GUS16 
       bool '      GUS MAX support' CONFIG_SOUND_GUSMAX
    fi
-   dep_tristate '    Intel ICH audio support' CONFIG_SOUND_ICH $CONFIG_SOUND_OSS
    dep_tristate '    Loopback MIDI device support' CONFIG_SOUND_VMIDI $CONFIG_SOUND_OSS
    dep_tristate '    MediaTrix AudioTrix Pro support' CONFIG_SOUND_TRIX $CONFIG_SOUND_OSS
    if [ "$CONFIG_SOUND_TRIX" = "y" ]; then
@@ -141,11 +142,9 @@
 
    dep_tristate '    Yamaha FM synthesizer (YM3812/OPL-3) support' CONFIG_SOUND_YM3812 $CONFIG_SOUND_OSS
    dep_tristate '    Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
-   dep_tristate '    Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
+   dep_tristate '    Yamaha OPL3-SA2 and SA3 based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
    dep_tristate '    Yamaha YMF7xx PCI audio (native mode)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS $CONFIG_PCI
-   if [ "$CONFIG_SOUND_YMFPCI" != "n" ]; then
-      bool '      Yamaha PCI legacy ports support' CONFIG_SOUND_YMFPCI_LEGACY
-   fi
+   dep_mbool '      Yamaha PCI legacy ports support' CONFIG_SOUND_YMFPCI_LEGACY $CONFIG_SOUND_YMFPCI
    dep_tristate '    6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
   
    dep_tristate '    Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/Makefile linux/drivers/sound/Makefile
--- v2.4.1/linux/drivers/sound/Makefile	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sound/Makefile	Sun Feb  4 10:05:29 2001
@@ -62,14 +62,19 @@
 obj-$(CONFIG_SOUND_ES1371)	+= es1371.o ac97_codec.o
 obj-$(CONFIG_SOUND_ESSSOLO1)	+= esssolo1.o
 obj-$(CONFIG_SOUND_FUSION)	+= cs46xx.o ac97_codec.o
-obj-$(CONFIG_SOUND_CS4281)	+= cs4281.o
 obj-$(CONFIG_SOUND_MAESTRO)	+= maestro.o
+obj-$(CONFIG_SOUND_MAESTRO3)	+= maestro3.o ac97_codec.o
 obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o
 
 subdir-$(CONFIG_SOUND_EMU10K1) += emu10k1
+subdir-$(CONFIG_SOUND_CS4281) += cs4281
 
 ifeq ($(CONFIG_SOUND_EMU10K1),y)
   obj-y += emu10k1/emu10k1.o
+endif
+
+ifeq ($(CONFIG_SOUND_CS4281),y)
+  obj-y += cs4281/cs4281.o
 endif
 
 subdir-$(CONFIG_DMASOUND) += dmasound
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/aci.c linux/drivers/sound/aci.c
--- v2.4.1/linux/drivers/sound/aci.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/sound/aci.c	Fri Feb 16 16:02:36 2001
@@ -714,5 +714,9 @@
 		release_region(aci_port, 3);
 }
 
+EXPORT_SYMBOL(aci_write_cmd);
+EXPORT_SYMBOL(aci_indexed_cmd);
+EXPORT_SYMBOL(aci_write_cmd_d);
+
 module_init(attach_aci);
 module_exit(unload_aci);
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/ad1816.c linux/drivers/sound/ad1816.c
--- v2.4.1/linux/drivers/sound/ad1816.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/sound/ad1816.c	Sun Feb  4 10:05:29 2001
@@ -1314,30 +1314,44 @@
 	return(ad1816_dev);
 }
 
+static struct ad1816_data {
+	struct pci_dev * (*initfunc)(struct pci_bus*, struct pci_dev *, struct address_info *);
+	char *name;
+} ad1816_pnp_data[] __initdata = {
+	{ &ad1816_init_generic, "Analog Devices 1815" },
+	{ &ad1816_init_generic, "Analog Devices 1816A" }
+};
+
 static struct {
+	unsigned short card_vendor, card_device;
 	unsigned short vendor;
 	unsigned short function;
-	struct pci_dev * (*initfunc)(struct pci_bus*, struct pci_dev *, struct address_info *);
-	char *name;
+	struct ad1816_data *data;
 } isapnp_ad1816_list[] __initdata = {
-	{ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7150), &ad1816_init_generic, "Analog Devices 1815" },
-	{ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7180), &ad1816_init_generic, "Analog Devices 1816A" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7150), 
+		&ad1816_pnp_data[0] },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('A','D','S'), ISAPNP_FUNCTION(0x7180),
+		&ad1816_pnp_data[1] },
 	{0}
 };
 
+MODULE_DEVICE_TABLE(isapnp, isapnp_ad1816_list);
+
 static int __init ad1816_init_isapnp(struct address_info *hw_config,
 	struct pci_bus *bus, struct pci_dev *card, int slot)
 {
 	struct pci_dev *idev = NULL;
 	
 	/* You missed the init func? That's bad. */
-	if(isapnp_ad1816_list[slot].initfunc) {
-		char *busname = bus->name[0] ? bus->name : isapnp_ad1816_list[slot].name;
+	if(isapnp_ad1816_list[slot].data->initfunc) {
+		char *busname = bus->name[0] ? bus->name : isapnp_ad1816_list[slot].data->name;
 		
 		printk(KERN_INFO "ad1816: %s detected\n", busname);
 		
 		/* Initialize this baby. */
-		if((idev = isapnp_ad1816_list[slot].initfunc(bus, card, hw_config))) {
+		if((idev = isapnp_ad1816_list[slot].data->initfunc(bus, card, hw_config))) {
 			/* We got it. */
 
 			printk(KERN_NOTICE "ad1816: ISAPnP reports '%s' at i/o %#x, irq %d, dma %d, %d\n",
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.4.1/linux/drivers/sound/ad1848.c	Fri Aug 11 08:26:43 2000
+++ linux/drivers/sound/ad1848.c	Sun Feb  4 10:05:29 2001
@@ -28,6 +28,7 @@
  *		          of irqs. Use dev_id.
  * Christoph Hellwig	: adapted to module_init/module_exit
  * Aki Laukkanen	: added power management support
+ * Arnaldo C. de Melo	: added missing restore_flags in ad1848_resume
  *
  * Status:
  *		Tested. Believed fully functional.
@@ -1900,9 +1901,6 @@
 	if(portc==NULL)
 		return -1;
 
-	if (owner)
-		ad1848_audio_driver.owner = owner;
-	
 	if ((my_dev = sound_install_audiodrv(AUDIO_DRIVER_VERSION,
 					     dev_name,
 					     &ad1848_audio_driver,
@@ -1920,6 +1918,8 @@
 	
 	audio_devs[my_dev]->portc = portc;
 	audio_devs[my_dev]->mixer_dev = -1;
+	if (owner)
+		audio_devs[my_dev]->d->owner = owner;
 	memset((char *) portc, 0, sizeof(*portc));
 
 	nr_ad1848_devs++;
@@ -1986,6 +1986,7 @@
 			if (sound_alloc_dma(dma_capture, devc->name))
 				printk(KERN_WARNING "ad1848.c: Can't allocate DMA%d\n", dma_capture);
 	}
+
 	if ((e = sound_install_mixer(MIXER_DRIVER_VERSION,
 				     dev_name,
 				     &ad1848_mixer_operations,
@@ -1993,6 +1994,8 @@
 				     devc)) >= 0)
 	{
 		audio_devs[my_dev]->mixer_dev = e;
+		if (owner)
+			mixer_devs[e]->owner = owner;
 	}
 	return my_dev;
 }
@@ -2751,6 +2754,7 @@
 		bits = interrupt_bits[devc->irq];
 		if (bits == -1) {
 			printk(KERN_ERR "MSS: Bad IRQ %d\n", devc->irq);
+			restore_flags(flags);
 			return -1;
 		}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/audio.c linux/drivers/sound/audio.c
--- v2.4.1/linux/drivers/sound/audio.c	Fri Aug 11 08:26:43 2000
+++ linux/drivers/sound/audio.c	Sun Feb  4 10:05:29 2001
@@ -21,6 +21,9 @@
  * Daniel Rodriksson: reworked the use of the device specific copy_user
  *                    still generic
  * Horst von Brand:  Add missing #include <linux/string.h>
+ * Chris Rankin    : Update the module-usage counter for the coprocessor,
+ *                   and decrement the counters again if we cannot open
+ *                   the audio device.
  */
 
 #include <linux/stddef.h>
@@ -71,6 +74,8 @@
 	int bits;
 	int dev_type = dev & 0x0f;
 	int mode = translate_mode(file);
+	const struct audio_driver *driver;
+	const struct coproc_operations *coprocessor;
 
 	dev = dev >> 4;
 
@@ -82,18 +87,20 @@
 	if (dev < 0 || dev >= num_audiodevs)
 		return -ENXIO;
 
-	if (audio_devs[dev]->d->owner)
-		__MOD_INC_USE_COUNT (audio_devs[dev]->d->owner);
+	driver = audio_devs[dev]->d;
+	if (driver->owner)
+		__MOD_INC_USE_COUNT(driver->owner);
 
 	if ((ret = DMAbuf_open(dev, mode)) < 0)
-		return ret;
+		goto error_1;
 
-	if (audio_devs[dev]->coproc) {
-		if ((ret = audio_devs[dev]->coproc->
-			open(audio_devs[dev]->coproc->devc, COPR_PCM)) < 0) {
-			audio_release(dev, file);
+	if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
+		if (coprocessor->owner)
+			__MOD_INC_USE_COUNT(coprocessor->owner);
+
+		if ((ret = coprocessor->open(coprocessor->devc, COPR_PCM)) < 0) {
 			printk(KERN_WARNING "Sound: Can't access coprocessor device\n");
-			return ret;
+			goto error_2;
 		}
 	}
 	
@@ -106,6 +113,20 @@
 
 	audio_devs[dev]->audio_mode = AM_NONE;
 
+	return 0;
+
+	/*
+	 * Clean-up stack: this is what needs (un)doing if
+	 * we can't open the audio device ...
+	 */
+	error_2:
+	if (coprocessor->owner)
+		__MOD_DEC_USE_COUNT(coprocessor->owner);
+	DMAbuf_release(dev, mode);
+
+	error_1:
+	if (driver->owner)
+		__MOD_DEC_USE_COUNT(driver->owner);
 
 	return ret;
 }
@@ -156,7 +177,8 @@
 
 void audio_release(int dev, struct file *file)
 {
-	int             mode = translate_mode(file);
+	const struct coproc_operations *coprocessor;
+	int mode = translate_mode(file);
 
 	dev = dev >> 4;
 
@@ -176,8 +198,12 @@
 	if (mode & OPEN_WRITE)
 		sync_output(dev);
 
-	if (audio_devs[dev]->coproc)
-		audio_devs[dev]->coproc->close(audio_devs[dev]->coproc->devc, COPR_PCM);
+	if ( (coprocessor = audio_devs[dev]->coproc) != NULL ) {
+		coprocessor->close(coprocessor->devc, COPR_PCM);
+
+		if (coprocessor->owner)
+			__MOD_DEC_USE_COUNT(coprocessor->owner);
+	}
 	DMAbuf_release(dev, mode);
 
 	if (audio_devs[dev]->d->owner)
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/awe_wave.c linux/drivers/sound/awe_wave.c
--- v2.4.1/linux/drivers/sound/awe_wave.c	Thu Nov 16 12:51:28 2000
+++ linux/drivers/sound/awe_wave.c	Sun Feb  4 10:05:29 2001
@@ -4772,15 +4772,24 @@
 	
 #if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
 static struct {
+	unsigned short card_vendor, card_device;
 	unsigned short vendor;
 	unsigned short function;
 	char *name;
 } isapnp_awe_list[] __initdata = {
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0021), "AWE32 WaveTable"},
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0022), "AWE64 WaveTable"},
-	{ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0023), "AWE64 Gold WaveTable"},
-	{0,}
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0021),
+		"AWE32 WaveTable" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0022),
+		"AWE64 WaveTable" },
+	{	ISAPNP_ANY_ID, ISAPNP_ANY_ID,
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0023),
+		"AWE64 Gold WaveTable" },
+	{0}
 };
+
+MODULE_DEVICE_TABLE(isapnp, isapnp_awe_list);
 
 static struct pci_dev *idev = NULL;
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cmpci.c linux/drivers/sound/cmpci.c
--- v2.4.1/linux/drivers/sound/cmpci.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/cmpci.c	Fri Feb  9 11:30:23 2001
@@ -106,7 +106,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/wrapper.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281/Makefile linux/drivers/sound/cs4281/Makefile
--- v2.4.1/linux/drivers/sound/cs4281/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/Makefile	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,12 @@
+# Makefile for Cirrus Logic-Crystal CS4281 
+#
+
+O_TARGET := cs4281.o
+
+obj-y := cs4281m.o
+obj-m := $(O_TARGET)
+
+include $(TOPDIR)/Rules.make
+
+clean:
+	rm -f core *.o *.a *.s
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281/cs4281_hwdefs.h linux/drivers/sound/cs4281/cs4281_hwdefs.h
--- v2.4.1/linux/drivers/sound/cs4281/cs4281_hwdefs.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281_hwdefs.h	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,1234 @@
+//****************************************************************************
+//
+// HWDEFS.H - Definitions of the registers and data structures used by the
+//            CS4281
+//
+// Copyright (c) 1999,2000,2001 Crystal Semiconductor Corp.
+//
+//****************************************************************************
+
+#ifndef _H_HWDEFS
+#define _H_HWDEFS
+
+//****************************************************************************
+//
+// The following define the offsets of the registers located in the PCI
+// configuration space of the CS4281 part.
+//
+//****************************************************************************
+#define PCICONFIG_DEVID_VENID                   0x00000000L
+#define PCICONFIG_STATUS_COMMAND                0x00000004L
+#define PCICONFIG_CLASS_REVISION                0x00000008L
+#define PCICONFIG_LATENCY_TIMER                 0x0000000CL
+#define PCICONFIG_BA0                           0x00000010L
+#define PCICONFIG_BA1                           0x00000014L
+#define PCICONFIG_SUBSYSID_SUBSYSVENID          0x0000002CL
+#define PCICONFIG_INTERRUPT                     0x0000003CL
+
+//****************************************************************************
+//
+// The following define the offsets of the registers accessed via base address
+// register zero on the CS4281 part.
+//
+//****************************************************************************
+#define BA0_HISR                                0x00000000L
+#define BA0_HICR                                0x00000008L
+#define BA0_HIMR                                0x0000000CL
+#define BA0_IIER                                0x00000010L
+#define BA0_HDSR0                               0x000000F0L
+#define BA0_HDSR1                               0x000000F4L
+#define BA0_HDSR2                               0x000000F8L
+#define BA0_HDSR3                               0x000000FCL
+#define BA0_DCA0                                0x00000110L
+#define BA0_DCC0                                0x00000114L
+#define BA0_DBA0                                0x00000118L
+#define BA0_DBC0                                0x0000011CL
+#define BA0_DCA1                                0x00000120L
+#define BA0_DCC1                                0x00000124L
+#define BA0_DBA1                                0x00000128L
+#define BA0_DBC1                                0x0000012CL
+#define BA0_DCA2                                0x00000130L
+#define BA0_DCC2                                0x00000134L
+#define BA0_DBA2                                0x00000138L
+#define BA0_DBC2                                0x0000013CL
+#define BA0_DCA3                                0x00000140L
+#define BA0_DCC3                                0x00000144L
+#define BA0_DBA3                                0x00000148L
+#define BA0_DBC3                                0x0000014CL
+#define BA0_DMR0                                0x00000150L
+#define BA0_DCR0                                0x00000154L
+#define BA0_DMR1                                0x00000158L
+#define BA0_DCR1                                0x0000015CL
+#define BA0_DMR2                                0x00000160L
+#define BA0_DCR2                                0x00000164L
+#define BA0_DMR3                                0x00000168L
+#define BA0_DCR3                                0x0000016CL
+#define BA0_DLMR                                0x00000170L
+#define BA0_DLSR                                0x00000174L
+#define BA0_FCR0                                0x00000180L
+#define BA0_FCR1                                0x00000184L
+#define BA0_FCR2                                0x00000188L
+#define BA0_FCR3                                0x0000018CL
+#define BA0_FPDR0                               0x00000190L
+#define BA0_FPDR1                               0x00000194L
+#define BA0_FPDR2                               0x00000198L
+#define BA0_FPDR3                               0x0000019CL
+#define BA0_FCHS                                0x0000020CL
+#define BA0_FSIC0                               0x00000210L
+#define BA0_FSIC1                               0x00000214L
+#define BA0_FSIC2                               0x00000218L
+#define BA0_FSIC3                               0x0000021CL
+#define BA0_PCICFG00                            0x00000300L
+#define BA0_PCICFG04                            0x00000304L
+#define BA0_PCICFG08                            0x00000308L
+#define BA0_PCICFG0C                            0x0000030CL
+#define BA0_PCICFG10                            0x00000310L
+#define BA0_PCICFG14                            0x00000314L
+#define BA0_PCICFG18                            0x00000318L
+#define BA0_PCICFG1C                            0x0000031CL
+#define BA0_PCICFG20                            0x00000320L
+#define BA0_PCICFG24                            0x00000324L
+#define BA0_PCICFG28                            0x00000328L
+#define BA0_PCICFG2C                            0x0000032CL
+#define BA0_PCICFG30                            0x00000330L
+#define BA0_PCICFG34                            0x00000334L
+#define BA0_PCICFG38                            0x00000338L
+#define BA0_PCICFG3C                            0x0000033CL
+#define BA0_PCICFG40                            0x00000340L
+#define BA0_PMCS                                0x00000344L
+#define BA0_CWPR                                0x000003E0L
+#define BA0_EPPMC                               0x000003E4L
+#define BA0_GPIOR                               0x000003E8L
+#define BA0_SPMC                                0x000003ECL
+#define BA0_CFLR                                0x000003F0L
+#define BA0_IISR                                0x000003F4L
+#define BA0_TMS                                 0x000003F8L
+#define BA0_SSVID                               0x000003FCL
+#define BA0_CLKCR1                              0x00000400L
+#define BA0_FRR                                 0x00000410L
+#define BA0_SLT12O                              0x0000041CL
+#define BA0_SERMC                               0x00000420L
+#define BA0_SERC1                               0x00000428L
+#define BA0_SERC2                               0x0000042CL
+#define BA0_SLT12M                              0x0000045CL
+#define BA0_ACCTL                               0x00000460L
+#define BA0_ACSTS                               0x00000464L
+#define BA0_ACOSV                               0x00000468L
+#define BA0_ACCAD                               0x0000046CL
+#define BA0_ACCDA                               0x00000470L
+#define BA0_ACISV                               0x00000474L
+#define BA0_ACSAD                               0x00000478L
+#define BA0_ACSDA                               0x0000047CL
+#define BA0_JSPT                                0x00000480L
+#define BA0_JSCTL                               0x00000484L
+#define BA0_MIDCR                               0x00000490L
+#define BA0_MIDCMD                              0x00000494L
+#define BA0_MIDSR                               0x00000494L
+#define BA0_MIDWP                               0x00000498L
+#define BA0_MIDRP                               0x0000049CL
+#define BA0_AODSD1                              0x000004A8L
+#define BA0_AODSD2                              0x000004ACL
+#define BA0_CFGI                                0x000004B0L
+#define BA0_SLT12M2                             0x000004DCL
+#define BA0_ACSTS2                              0x000004E4L
+#define BA0_ACISV2                              0x000004F4L
+#define BA0_ACSAD2                              0x000004F8L
+#define BA0_ACSDA2                              0x000004FCL
+#define BA0_IOTGP                               0x00000500L
+#define BA0_IOTSB                               0x00000504L
+#define BA0_IOTFM                               0x00000508L
+#define BA0_IOTDMA                              0x0000050CL
+#define BA0_IOTAC0                              0x00000500L
+#define BA0_IOTAC1                              0x00000504L
+#define BA0_IOTAC2                              0x00000508L
+#define BA0_IOTAC3                              0x0000050CL
+#define BA0_IOTPCP                              0x0000052CL
+#define BA0_IOTCC                               0x00000530L
+#define BA0_IOTCR                               0x0000058CL
+#define BA0_PCPRR                               0x00000600L
+#define BA0_PCPGR                               0x00000604L
+#define BA0_PCPCR                               0x00000608L
+#define BA0_PCPCIEN                             0x00000608L
+#define BA0_SBMAR                               0x00000700L
+#define BA0_SBMDR                               0x00000704L
+#define BA0_SBRR                                0x00000708L
+#define BA0_SBRDP                               0x0000070CL
+#define BA0_SBWDP                               0x00000710L
+#define BA0_SBWBS                               0x00000710L
+#define BA0_SBRBS                               0x00000714L
+#define BA0_FMSR                                0x00000730L
+#define BA0_B0AP                                0x00000730L
+#define BA0_FMDP                                0x00000734L
+#define BA0_B1AP                                0x00000738L
+#define BA0_B1DP                                0x0000073CL
+#define BA0_SSPM                                0x00000740L
+#define BA0_DACSR                               0x00000744L
+#define BA0_ADCSR                               0x00000748L
+#define BA0_SSCR                                0x0000074CL
+#define BA0_FMLVC                               0x00000754L
+#define BA0_FMRVC                               0x00000758L
+#define BA0_SRCSA                               0x0000075CL
+#define BA0_PPLVC                               0x00000760L
+#define BA0_PPRVC                               0x00000764L
+#define BA0_PASR                                0x00000768L
+#define BA0_CASR                                0x0000076CL
+
+//****************************************************************************
+//
+// The following define the offsets of the AC97 shadow registers, which appear
+// as a virtual extension to the base address register zero memory range.
+//
+//****************************************************************************
+#define AC97_REG_OFFSET_MASK                    0x0000007EL
+#define AC97_CODEC_NUMBER_MASK                  0x00003000L
+
+#define BA0_AC97_RESET                          0x00001000L
+#define BA0_AC97_MASTER_VOLUME                  0x00001002L
+#define BA0_AC97_HEADPHONE_VOLUME               0x00001004L
+#define BA0_AC97_MASTER_VOLUME_MONO             0x00001006L
+#define BA0_AC97_MASTER_TONE                    0x00001008L
+#define BA0_AC97_PC_BEEP_VOLUME                 0x0000100AL
+#define BA0_AC97_PHONE_VOLUME                   0x0000100CL
+#define BA0_AC97_MIC_VOLUME                     0x0000100EL
+#define BA0_AC97_LINE_IN_VOLUME                 0x00001010L
+#define BA0_AC97_CD_VOLUME                      0x00001012L
+#define BA0_AC97_VIDEO_VOLUME                   0x00001014L
+#define BA0_AC97_AUX_VOLUME                     0x00001016L
+#define BA0_AC97_PCM_OUT_VOLUME                 0x00001018L
+#define BA0_AC97_RECORD_SELECT                  0x0000101AL
+#define BA0_AC97_RECORD_GAIN                    0x0000101CL
+#define BA0_AC97_RECORD_GAIN_MIC                0x0000101EL
+#define BA0_AC97_GENERAL_PURPOSE                0x00001020L
+#define BA0_AC97_3D_CONTROL                     0x00001022L
+#define BA0_AC97_MODEM_RATE                     0x00001024L
+#define BA0_AC97_POWERDOWN                      0x00001026L
+#define BA0_AC97_EXT_AUDIO_ID                   0x00001028L
+#define BA0_AC97_EXT_AUDIO_POWER                0x0000102AL
+#define BA0_AC97_PCM_FRONT_DAC_RATE             0x0000102CL
+#define BA0_AC97_PCM_SURR_DAC_RATE              0x0000102EL
+#define BA0_AC97_PCM_LFE_DAC_RATE               0x00001030L
+#define BA0_AC97_PCM_LR_ADC_RATE                0x00001032L
+#define BA0_AC97_MIC_ADC_RATE                   0x00001034L
+#define BA0_AC97_6CH_VOL_C_LFE                  0x00001036L
+#define BA0_AC97_6CH_VOL_SURROUND               0x00001038L
+#define BA0_AC97_RESERVED_3A                    0x0000103AL
+#define BA0_AC97_EXT_MODEM_ID                   0x0000103CL
+#define BA0_AC97_EXT_MODEM_POWER                0x0000103EL
+#define BA0_AC97_LINE1_CODEC_RATE               0x00001040L
+#define BA0_AC97_LINE2_CODEC_RATE               0x00001042L
+#define BA0_AC97_HANDSET_CODEC_RATE             0x00001044L
+#define BA0_AC97_LINE1_CODEC_LEVEL              0x00001046L
+#define BA0_AC97_LINE2_CODEC_LEVEL              0x00001048L
+#define BA0_AC97_HANDSET_CODEC_LEVEL            0x0000104AL
+#define BA0_AC97_GPIO_PIN_CONFIG                0x0000104CL
+#define BA0_AC97_GPIO_PIN_TYPE                  0x0000104EL
+#define BA0_AC97_GPIO_PIN_STICKY                0x00001050L
+#define BA0_AC97_GPIO_PIN_WAKEUP                0x00001052L
+#define BA0_AC97_GPIO_PIN_STATUS                0x00001054L
+#define BA0_AC97_MISC_MODEM_AFE_STAT            0x00001056L
+#define BA0_AC97_RESERVED_58                    0x00001058L
+#define BA0_AC97_CRYSTAL_REV_N_FAB_ID           0x0000105AL
+#define BA0_AC97_TEST_AND_MISC_CTRL             0x0000105CL
+#define BA0_AC97_AC_MODE                        0x0000105EL
+#define BA0_AC97_MISC_CRYSTAL_CONTROL           0x00001060L
+#define BA0_AC97_LINE1_HYPRID_CTRL              0x00001062L
+#define BA0_AC97_VENDOR_RESERVED_64             0x00001064L
+#define BA0_AC97_VENDOR_RESERVED_66             0x00001066L
+#define BA0_AC97_SPDIF_CONTROL                  0x00001068L
+#define BA0_AC97_VENDOR_RESERVED_6A             0x0000106AL
+#define BA0_AC97_VENDOR_RESERVED_6C             0x0000106CL
+#define BA0_AC97_VENDOR_RESERVED_6E             0x0000106EL
+#define BA0_AC97_VENDOR_RESERVED_70             0x00001070L
+#define BA0_AC97_VENDOR_RESERVED_72             0x00001072L
+#define BA0_AC97_VENDOR_RESERVED_74             0x00001074L
+#define BA0_AC97_CAL_ADDRESS                    0x00001076L
+#define BA0_AC97_CAL_DATA                       0x00001078L
+#define BA0_AC97_VENDOR_RESERVED_7A             0x0000107AL
+#define BA0_AC97_VENDOR_ID1                     0x0000107CL
+#define BA0_AC97_VENDOR_ID2                     0x0000107EL
+
+//****************************************************************************
+//
+// The following define the offsets of the registers and memories accessed via
+// base address register one on the CS4281 part.
+//
+//****************************************************************************
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI device ID/vendor ID
+// register.
+//
+//****************************************************************************
+#define PDV_VENID_MASK                          0x0000FFFFL
+#define PDV_DEVID_MASK                          0xFFFF0000L
+#define PDV_VENID_SHIFT                         0L
+#define PDV_DEVID_SHIFT                         16L
+#define VENID_CIRRUS_LOGIC                      0x1013L
+#define DEVID_CS4281                            0x6005L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI status and command
+// register.
+//
+//****************************************************************************
+#define PSC_IO_SPACE_ENABLE                     0x00000001L
+#define PSC_MEMORY_SPACE_ENABLE                 0x00000002L
+#define PSC_BUS_MASTER_ENABLE                   0x00000004L
+#define PSC_SPECIAL_CYCLES                      0x00000008L
+#define PSC_MWI_ENABLE                          0x00000010L
+#define PSC_VGA_PALETTE_SNOOP                   0x00000020L
+#define PSC_PARITY_RESPONSE                     0x00000040L
+#define PSC_WAIT_CONTROL                        0x00000080L
+#define PSC_SERR_ENABLE                         0x00000100L
+#define PSC_FAST_B2B_ENABLE                     0x00000200L
+#define PSC_UDF_MASK                            0x007F0000L
+#define PSC_FAST_B2B_CAPABLE                    0x00800000L
+#define PSC_PARITY_ERROR_DETECTED               0x01000000L
+#define PSC_DEVSEL_TIMING_MASK                  0x06000000L
+#define PSC_TARGET_ABORT_SIGNALLED              0x08000000L
+#define PSC_RECEIVED_TARGET_ABORT               0x10000000L
+#define PSC_RECEIVED_MASTER_ABORT               0x20000000L
+#define PSC_SIGNALLED_SERR                      0x40000000L
+#define PSC_DETECTED_PARITY_ERROR               0x80000000L
+#define PSC_UDF_SHIFT                           16L
+#define PSC_DEVSEL_TIMING_SHIFT                 25L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI class/revision ID
+// register.
+//
+//****************************************************************************
+#define PCR_REVID_MASK                          0x000000FFL
+#define PCR_INTERFACE_MASK                      0x0000FF00L
+#define PCR_SUBCLASS_MASK                       0x00FF0000L
+#define PCR_CLASS_MASK                          0xFF000000L
+#define PCR_REVID_SHIFT                         0L
+#define PCR_INTERFACE_SHIFT                     8L
+#define PCR_SUBCLASS_SHIFT                      16L
+#define PCR_CLASS_SHIFT                         24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI latency timer register.
+//
+//****************************************************************************
+#define PLT_CACHE_LINE_SIZE_MASK                0x000000FFL
+#define PLT_LATENCY_TIMER_MASK                  0x0000FF00L
+#define PLT_HEADER_TYPE_MASK                    0x00FF0000L
+#define PLT_BIST_MASK                           0xFF000000L
+#define PLT_CACHE_LINE_SIZE_SHIFT               0L
+#define PLT_LATENCY_TIMER_SHIFT                 8L
+#define PLT_HEADER_TYPE_SHIFT                   16L
+#define PLT_BIST_SHIFT                          24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI base address registers.
+//
+//****************************************************************************
+#define PBAR_MEMORY_SPACE_INDICATOR             0x00000001L
+#define PBAR_LOCATION_TYPE_MASK                 0x00000006L
+#define PBAR_NOT_PREFETCHABLE                   0x00000008L
+#define PBAR_ADDRESS_MASK                       0xFFFFFFF0L
+#define PBAR_LOCATION_TYPE_SHIFT                1L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI subsystem ID/subsystem
+// vendor ID register.
+//
+//****************************************************************************
+#define PSS_SUBSYSTEM_VENDOR_ID_MASK            0x0000FFFFL
+#define PSS_SUBSYSTEM_ID_MASK                   0xFFFF0000L
+#define PSS_SUBSYSTEM_VENDOR_ID_SHIFT           0L
+#define PSS_SUBSYSTEM_ID_SHIFT                  16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PCI interrupt register.
+//
+//****************************************************************************
+#define PI_LINE_MASK                            0x000000FFL
+#define PI_PIN_MASK                             0x0000FF00L
+#define PI_MIN_GRANT_MASK                       0x00FF0000L
+#define PI_MAX_LATENCY_MASK                     0xFF000000L
+#define PI_LINE_SHIFT                           0L
+#define PI_PIN_SHIFT                            8L
+#define PI_MIN_GRANT_SHIFT                      16L
+#define PI_MAX_LATENCY_SHIFT                    24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the host interrupt status
+// register.
+//
+//****************************************************************************
+#define HISR_HVOLMASK                            0x00000003L
+#define HISR_VDNI                                0x00000001L
+#define HISR_VUPI                                0x00000002L
+#define HISR_GP1I                                0x00000004L
+#define HISR_GP3I                                0x00000008L
+#define HISR_GPSI                                0x00000010L
+#define HISR_GPPI                                0x00000020L
+#define HISR_DMAI                                0x00040000L
+#define HISR_FIFOI                               0x00100000L
+#define HISR_HVOL                                0x00200000L
+#define HISR_MIDI                                0x00400000L
+#define HISR_SBINT                               0x00800000L
+#define HISR_INTENA                              0x80000000L
+#define HISR_DMA_MASK                            0x00000F00L
+#define HISR_FIFO_MASK                           0x0000F000L
+#define HISR_DMA_SHIFT                           8L
+#define HISR_FIFO_SHIFT                          12L
+#define HISR_FIFO0                               0x00001000L
+#define HISR_FIFO1                               0x00002000L
+#define HISR_FIFO2                               0x00004000L
+#define HISR_FIFO3                               0x00008000L
+#define HISR_DMA0                                0x00000100L
+#define HISR_DMA1                                0x00000200L
+#define HISR_DMA2                                0x00000400L
+#define HISR_DMA3                                0x00000800L
+#define HISR_RESERVED                            0x40000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the host interrupt control
+// register.
+//
+//****************************************************************************
+#define HICR_IEV                                 0x00000001L
+#define HICR_CHGM                                0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the DMA Mode Register n
+// (DMRn)
+//
+//****************************************************************************
+#define DMRn_TR_MASK                             0x0000000CL
+#define DMRn_TR_SHIFT                            2L
+#define DMRn_AUTO                                0x00000010L
+#define DMRn_TR_READ                             0x00000008L
+#define DMRn_TR_WRITE                            0x00000004L
+#define DMRn_TYPE_MASK                           0x000000C0L
+#define DMRn_TYPE_SHIFT                          6L
+#define DMRn_SIZE8                               0x00010000L
+#define DMRn_MONO                                0x00020000L
+#define DMRn_BEND                                0x00040000L
+#define DMRn_USIGN                               0x00080000L
+#define DMRn_SIZE20                              0x00100000L
+#define DMRn_SWAPC                               0x00400000L
+#define DMRn_CBC                                 0x01000000L
+#define DMRn_TBC                                 0x02000000L
+#define DMRn_POLL                                0x10000000L
+#define DMRn_DMA                                 0x20000000L
+#define DMRn_FSEL_MASK                           0xC0000000L
+#define DMRn_FSEL_SHIFT                          30L
+#define DMRn_FSEL0                               0x00000000L
+#define DMRn_FSEL1                               0x40000000L
+#define DMRn_FSEL2                               0x80000000L
+#define DMRn_FSEL3                               0xC0000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the DMA Command Register n
+// (DCRn)
+//
+//****************************************************************************
+#define DCRn_HTCIE                               0x00020000L
+#define DCRn_TCIE                                0x00010000L
+#define DCRn_MSK                                 0x00000001L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the FIFO Control 
+// register n.(FCRn)
+//
+//****************************************************************************
+#define FCRn_OF_MASK                            0x0000007FL
+#define FCRn_OF_SHIFT                           0L
+#define FCRn_SZ_MASK                            0x00007F00L
+#define FCRn_SZ_SHIFT                           8L
+#define FCRn_LS_MASK                            0x001F0000L
+#define FCRn_LS_SHIFT                           16L
+#define FCRn_RS_MASK                            0x1F000000L
+#define FCRn_RS_SHIFT                           24L
+#define FCRn_FEN                                0x80000000L
+#define FCRn_PSH                                0x20000000L
+#define FCRn_DACZ                               0x40000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port Power Management
+// control register.(SPMC)
+//
+//****************************************************************************
+#define SPMC_RSTN                               0x00000001L
+#define SPMC_ASYN                               0x00000002L
+#define SPMC_WUP1                               0x00000004L
+#define SPMC_WUP2                               0x00000008L
+#define SPMC_ASDI2E                             0x00000100L
+#define SPMC_ESSPD                              0x00000200L
+#define SPMC_GISPEN                             0x00004000L
+#define SPMC_GIPPEN                             0x00008000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Configuration Load register.
+// (CFLR)
+//
+//****************************************************************************
+#define CFLR_CLOCK_SOURCE_MASK                  0x00000003L
+#define CFLR_CLOCK_SOURCE_AC97                  0x00000001L
+
+#define CFLR_CB0_MASK                            0x000000FFL
+#define CFLR_CB1_MASK                            0x0000FF00L
+#define CFLR_CB2_MASK                            0x00FF0000L
+#define CFLR_CB3_MASK                            0xFF000000L
+#define CFLR_CB0_SHIFT                           0L
+#define CFLR_CB1_SHIFT                           8L
+#define CFLR_CB2_SHIFT                           16L
+#define CFLR_CB3_SHIFT                           24L
+
+#define IOTCR_DMA0                              0x00000000L
+#define IOTCR_DMA1                              0x00000400L
+#define IOTCR_DMA2                              0x00000800L
+#define IOTCR_DMA3                              0x00000C00L
+#define IOTCR_CCLS                              0x00000100L
+#define IOTCR_PCPCI                             0x00000200L
+#define IOTCR_DDMA                              0x00000300L
+
+#define SBWBS_WBB                               0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the SRC Slot Assignment Register
+// (SRCSA)
+//
+//****************************************************************************
+#define SRCSA_PLSS_MASK                         0x0000001FL
+#define SRCSA_PLSS_SHIFT                        0L
+#define SRCSA_PRSS_MASK                         0x00001F00L
+#define SRCSA_PRSS_SHIFT                        8L
+#define SRCSA_CLSS_MASK                         0x001F0000L
+#define SRCSA_CLSS_SHIFT                        16L
+#define SRCSA_CRSS_MASK                         0x1F000000L
+#define SRCSA_CRSS_SHIFT                        24L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Sound System Power Management
+// register.(SSPM)
+//
+//****************************************************************************
+#define SSPM_FPDN                               0x00000080L
+#define SSPM_MIXEN                              0x00000040L
+#define SSPM_CSRCEN                             0x00000020L
+#define SSPM_PSRCEN                             0x00000010L
+#define SSPM_JSEN                               0x00000008L
+#define SSPM_ACLEN                              0x00000004L
+#define SSPM_FMEN                               0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Sound System Control
+// Register. (SSCR)
+//
+//****************************************************************************
+#define SSCR_SB                                 0x00000004L
+#define SSCR_HVC                                0x00000008L
+#define SSCR_LPFIFO                             0x00000040L
+#define SSCR_LPSRC                              0x00000080L
+#define SSCR_XLPSRC                             0x00000100L
+#define SSCR_MVMD                               0x00010000L
+#define SSCR_MVAD                               0x00020000L
+#define SSCR_MVLD                               0x00040000L
+#define SSCR_MVCS                               0x00080000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Clock Control Register 1. 
+// (CLKCR1)
+//
+//****************************************************************************
+#define CLKCR1_DLLSS_MASK                       0x0000000CL
+#define CLKCR1_DLLSS_SHIFT                      2L
+#define CLKCR1_DLLP                             0x00000010L
+#define CLKCR1_SWCE                             0x00000020L
+#define CLKCR1_DLLOS                            0x00000040L
+#define CLKCR1_CKRA                             0x00010000L
+#define CLKCR1_CKRN                             0x00020000L
+#define CLKCR1_DLLRDY                           0x01000000L
+#define CLKCR1_CLKON                            0x02000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the Sound Blaster Read Buffer
+// Status.(SBRBS)
+//
+//****************************************************************************
+#define SBRBS_RD_MASK                           0x0000007FL
+#define SBRBS_RD_SHIFT                          0L
+#define SBRBS_RBF                               0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port master control
+// register.(SERMC)
+//
+//****************************************************************************
+#define SERMC_MSPE                              0x00000001L
+#define SERMC_PTC_MASK                          0x0000000EL
+#define SERMC_PTC_SHIFT                         1L
+#define SERMC_PTC_AC97                          0x00000002L
+#define SERMC_PLB                               0x00000010L
+#define SERMC_PXLB                              0x00000020L
+#define SERMC_LOFV                              0x00080000L
+#define SERMC_SLB                               0x00100000L
+#define SERMC_SXLB                              0x00200000L
+#define SERMC_ODSEN1                            0x01000000L
+#define SERMC_ODSEN2                            0x02000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the General Purpose I/O Register. 
+// (GPIOR)
+//
+//****************************************************************************
+#define GPIOR_VDNS                              0x00000001L
+#define GPIOR_VUPS                              0x00000002L
+#define GPIOR_GP1S                              0x00000004L
+#define GPIOR_GP3S                              0x00000008L
+#define GPIOR_GPSS                              0x00000010L
+#define GPIOR_GPPS                              0x00000020L
+#define GPIOR_GP1D                              0x00000400L
+#define GPIOR_GP3D                              0x00000800L
+#define GPIOR_VDNLT                             0x00010000L
+#define GPIOR_VDNPO                             0x00020000L
+#define GPIOR_VDNST                             0x00040000L
+#define GPIOR_VDNW                              0x00080000L
+#define GPIOR_VUPLT                             0x00100000L
+#define GPIOR_VUPPO                             0x00200000L
+#define GPIOR_VUPST                             0x00400000L
+#define GPIOR_VUPW                              0x00800000L
+#define GPIOR_GP1OE                             0x01000000L
+#define GPIOR_GP1PT                             0x02000000L
+#define GPIOR_GP1ST                             0x04000000L
+#define GPIOR_GP1W                              0x08000000L
+#define GPIOR_GP3OE                             0x10000000L
+#define GPIOR_GP3PT                             0x20000000L
+#define GPIOR_GP3ST                             0x40000000L
+#define GPIOR_GP3W                              0x80000000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the clock control register 1.
+//
+//****************************************************************************
+#define CLKCR1_PLLSS_MASK                       0x0000000CL
+#define CLKCR1_PLLSS_SERIAL                     0x00000000L
+#define CLKCR1_PLLSS_CRYSTAL                    0x00000004L
+#define CLKCR1_PLLSS_PCI                        0x00000008L
+#define CLKCR1_PLLSS_RESERVED                   0x0000000CL
+#define CLKCR1_PLLP                             0x00000010L
+#define CLKCR1_SWCE                             0x00000020L
+#define CLKCR1_PLLOS                            0x00000040L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the feature reporting register.
+//
+//****************************************************************************
+#define FRR_FAB_MASK                            0x00000003L
+#define FRR_MASK_MASK                           0x0000001CL
+#define FRR_ID_MASK                             0x00003000L
+#define FRR_FAB_SHIFT                           0L
+#define FRR_MASK_SHIFT                          2L
+#define FRR_ID_SHIFT                            12L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port 1 configuration
+// register.
+//
+//****************************************************************************
+#define SERC1_VALUE                             0x00000003L
+#define SERC1_SO1EN                             0x00000001L
+#define SERC1_SO1F_MASK                         0x0000000EL
+#define SERC1_SO1F_CS423X                       0x00000000L
+#define SERC1_SO1F_AC97                         0x00000002L
+#define SERC1_SO1F_DAC                          0x00000004L
+#define SERC1_SO1F_SPDIF                        0x00000006L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the serial port 2 configuration
+// register.
+//
+//****************************************************************************
+#define SERC2_VALUE                             0x00000003L
+#define SERC2_SI1EN                             0x00000001L
+#define SERC2_SI1F_MASK                         0x0000000EL
+#define SERC2_SI1F_CS423X                       0x00000000L
+#define SERC2_SI1F_AC97                         0x00000002L
+#define SERC2_SI1F_ADC                          0x00000004L
+#define SERC2_SI1F_SPDIF                        0x00000006L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 control register.
+//
+//****************************************************************************
+#define ACCTL_ESYN                              0x00000002L
+#define ACCTL_VFRM                              0x00000004L
+#define ACCTL_DCV                               0x00000008L
+#define ACCTL_CRW                               0x00000010L
+#define ACCTL_TC                                0x00000040L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status register.
+//
+//****************************************************************************
+#define ACSTS_CRDY                              0x00000001L
+#define ACSTS_VSTS                              0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 output slot valid
+// register.
+//
+//****************************************************************************
+#define ACOSV_SLV3                              0x00000001L
+#define ACOSV_SLV4                              0x00000002L
+#define ACOSV_SLV5                              0x00000004L
+#define ACOSV_SLV6                              0x00000008L
+#define ACOSV_SLV7                              0x00000010L
+#define ACOSV_SLV8                              0x00000020L
+#define ACOSV_SLV9                              0x00000040L
+#define ACOSV_SLV10                             0x00000080L
+#define ACOSV_SLV11                             0x00000100L
+#define ACOSV_SLV12                             0x00000200L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 command address
+// register.
+//
+//****************************************************************************
+#define ACCAD_CI_MASK                           0x0000007FL
+#define ACCAD_CI_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 command data register.
+//
+//****************************************************************************
+#define ACCDA_CD_MASK                           0x0000FFFFL
+#define ACCDA_CD_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 input slot valid
+// register.
+//
+//****************************************************************************
+#define ACISV_ISV3                              0x00000001L
+#define ACISV_ISV4                              0x00000002L
+#define ACISV_ISV5                              0x00000004L
+#define ACISV_ISV6                              0x00000008L
+#define ACISV_ISV7                              0x00000010L
+#define ACISV_ISV8                              0x00000020L
+#define ACISV_ISV9                              0x00000040L
+#define ACISV_ISV10                             0x00000080L
+#define ACISV_ISV11                             0x00000100L
+#define ACISV_ISV12                             0x00000200L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status address
+// register.
+//
+//****************************************************************************
+#define ACSAD_SI_MASK                           0x0000007FL
+#define ACSAD_SI_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status data register.
+//
+//****************************************************************************
+#define ACSDA_SD_MASK                           0x0000FFFFL
+#define ACSDA_SD_SHIFT                          0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers (all 12).
+//
+//****************************************************************************
+#define IOTAC_SA_MASK                           0x0000FFFFL
+#define IOTAC_MSK_MASK                          0x000F0000L
+#define IOTAC_IODC_MASK                         0x06000000L
+#define IOTAC_IODC_16_BIT                       0x00000000L
+#define IOTAC_IODC_10_BIT                       0x02000000L
+#define IOTAC_IODC_12_BIT                       0x04000000L
+#define IOTAC_WSPI                              0x08000000L
+#define IOTAC_RSPI                              0x10000000L
+#define IOTAC_WSE                               0x20000000L
+#define IOTAC_WE                                0x40000000L
+#define IOTAC_RE                                0x80000000L
+#define IOTAC_SA_SHIFT                          0L
+#define IOTAC_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI master enable
+// register.
+//
+//****************************************************************************
+#define PCPCIEN_EN                              0x00000001L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the joystick poll/trigger
+// register.
+//
+//****************************************************************************
+#define JSPT_CAX                                0x00000001L
+#define JSPT_CAY                                0x00000002L
+#define JSPT_CBX                                0x00000004L
+#define JSPT_CBY                                0x00000008L
+#define JSPT_BA1                                0x00000010L
+#define JSPT_BA2                                0x00000020L
+#define JSPT_BB1                                0x00000040L
+#define JSPT_BB2                                0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the joystick control register.
+// The TBF bit has been moved from MIDSR register to JSCTL register bit 8.
+//
+//****************************************************************************
+#define JSCTL_SP_MASK                           0x00000003L
+#define JSCTL_SP_SLOW                           0x00000000L
+#define JSCTL_SP_MEDIUM_SLOW                    0x00000001L
+#define JSCTL_SP_MEDIUM_FAST                    0x00000002L
+#define JSCTL_SP_FAST                           0x00000003L
+#define JSCTL_ARE                               0x00000004L
+#define JSCTL_TBF                               0x00000100L
+
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI control register.
+//
+//****************************************************************************
+#define MIDCR_TXE                               0x00000001L
+#define MIDCR_RXE                               0x00000002L
+#define MIDCR_RIE                               0x00000004L
+#define MIDCR_TIE                               0x00000008L
+#define MIDCR_MLB                               0x00000010L
+#define MIDCR_MRST                              0x00000020L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI status register.
+//
+//****************************************************************************
+#define MIDSR_RBE                               0x00000080L
+#define MIDSR_RDA                               0x00008000L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI write port register.
+//
+//****************************************************************************
+#define MIDWP_MWD_MASK                          0x000000FFL
+#define MIDWP_MWD_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the MIDI read port register.
+//
+//****************************************************************************
+#define MIDRP_MRD_MASK                          0x000000FFL
+#define MIDRP_MRD_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the configuration interface
+// register.
+//
+//****************************************************************************
+#define CFGI_CLK                                0x00000001L
+#define CFGI_DOUT                               0x00000002L
+#define CFGI_DIN_EEN                            0x00000004L
+#define CFGI_EELD                               0x00000008L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the subsystem ID and vendor ID
+// register.
+//
+//****************************************************************************
+#define SSVID_VID_MASK                          0x0000FFFFL
+#define SSVID_SID_MASK                          0xFFFF0000L
+#define SSVID_VID_SHIFT                         0L
+#define SSVID_SID_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the GPIO pin interface register.
+//
+//****************************************************************************
+#define GPIOR_VOLDN                             0x00000001L
+#define GPIOR_VOLUP                             0x00000002L
+#define GPIOR_SI2D                              0x00000004L
+#define GPIOR_SI2OE                             0x00000008L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status register 2.
+//
+//****************************************************************************
+#define ACSTS2_CRDY                             0x00000001L
+#define ACSTS2_VSTS                             0x00000002L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 input slot valid
+// register 2.
+//
+//****************************************************************************
+#define ACISV2_ISV3                             0x00000001L
+#define ACISV2_ISV4                             0x00000002L
+#define ACISV2_ISV5                             0x00000004L
+#define ACISV2_ISV6                             0x00000008L
+#define ACISV2_ISV7                             0x00000010L
+#define ACISV2_ISV8                             0x00000020L
+#define ACISV2_ISV9                             0x00000040L
+#define ACISV2_ISV10                            0x00000080L
+#define ACISV2_ISV11                            0x00000100L
+#define ACISV2_ISV12                            0x00000200L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status address
+// register 2.
+//
+//****************************************************************************
+#define ACSAD2_SI_MASK                          0x0000007FL
+#define ACSAD2_SI_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 status data register 2.
+//
+//****************************************************************************
+#define ACSDA2_SD_MASK                          0x0000FFFFL
+#define ACSDA2_SD_SHIFT                         0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap control register.
+//
+//****************************************************************************
+#define IOTCR_ITD                               0x00000001L
+#define IOTCR_HRV                               0x00000002L
+#define IOTCR_SRV                               0x00000004L
+#define IOTCR_DTI                               0x00000008L
+#define IOTCR_DFI                               0x00000010L
+#define IOTCR_DDP                               0x00000020L
+#define IOTCR_JTE                               0x00000040L
+#define IOTCR_PPE                               0x00000080L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers for Hardware Master Volume.  
+//
+//****************************************************************************
+#define IOTGP_SA_MASK                           0x0000FFFFL
+#define IOTGP_MSK_MASK                          0x000F0000L
+#define IOTGP_IODC_MASK                         0x06000000L
+#define IOTGP_IODC_16_BIT                       0x00000000L
+#define IOTGP_IODC_10_BIT                       0x02000000L
+#define IOTGP_IODC_12_BIT                       0x04000000L
+#define IOTGP_WSPI                              0x08000000L
+#define IOTGP_RSPI                              0x10000000L
+#define IOTGP_WSE                               0x20000000L
+#define IOTGP_WE                                0x40000000L
+#define IOTGP_RE                                0x80000000L
+#define IOTGP_SA_SHIFT                          0L
+#define IOTGP_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers for Sound Blaster
+//
+//****************************************************************************
+#define IOTSB_SA_MASK                           0x0000FFFFL
+#define IOTSB_MSK_MASK                          0x000F0000L
+#define IOTSB_IODC_MASK                         0x06000000L
+#define IOTSB_IODC_16_BIT                       0x00000000L
+#define IOTSB_IODC_10_BIT                       0x02000000L
+#define IOTSB_IODC_12_BIT                       0x04000000L
+#define IOTSB_WSPI                              0x08000000L
+#define IOTSB_RSPI                              0x10000000L
+#define IOTSB_WSE                               0x20000000L
+#define IOTSB_WE                                0x40000000L
+#define IOTSB_RE                                0x80000000L
+#define IOTSB_SA_SHIFT                          0L
+#define IOTSB_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the I/O trap address and control
+// registers for FM.
+//
+//****************************************************************************
+#define IOTFM_SA_MASK                           0x0000FFFFL
+#define IOTFM_MSK_MASK                          0x000F0000L
+#define IOTFM_IODC_MASK                         0x06000000L
+#define IOTFM_IODC_16_BIT                       0x00000000L
+#define IOTFM_IODC_10_BIT                       0x02000000L
+#define IOTFM_IODC_12_BIT                       0x04000000L
+#define IOTFM_WSPI                              0x08000000L
+#define IOTFM_RSPI                              0x10000000L
+#define IOTFM_WSE                               0x20000000L
+#define IOTFM_WE                                0x40000000L
+#define IOTFM_RE                                0x80000000L
+#define IOTFM_SA_SHIFT                          0L
+#define IOTFM_MSK_SHIFT                         16L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI request register.
+//
+//****************************************************************************
+#define PCPRR_RDC_MASK                         0x00000007L
+#define PCPRR_REQ                              0x00008000L
+#define PCPRR_RDC_SHIFT                        0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI grant register.
+//
+//****************************************************************************
+#define PCPGR_GDC_MASK                         0x00000007L
+#define PCPGR_VL                               0x00008000L
+#define PCPGR_GDC_SHIFT                        0L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the PC/PCI Control Register.
+//
+//****************************************************************************
+#define PCPCR_EN                               0x00000001L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the debug index register.
+//
+//****************************************************************************
+#define DREG_REGID_MASK                         0x0000007FL
+#define DREG_DEBUG                              0x00000080L
+#define DREG_RGBK_MASK                          0x00000700L
+#define DREG_TRAP                               0x00000800L
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_TRAPX                              0x00001000L
+#endif
+#endif
+#define DREG_REGID_SHIFT                        0L
+#define DREG_RGBK_SHIFT                         8L
+#define DREG_RGBK_REGID_MASK                    0x0000077FL
+#define DREG_REGID_R0                           0x00000010L
+#define DREG_REGID_R1                           0x00000011L
+#define DREG_REGID_R2                           0x00000012L
+#define DREG_REGID_R3                           0x00000013L
+#define DREG_REGID_R4                           0x00000014L
+#define DREG_REGID_R5                           0x00000015L
+#define DREG_REGID_R6                           0x00000016L
+#define DREG_REGID_R7                           0x00000017L
+#define DREG_REGID_R8                           0x00000018L
+#define DREG_REGID_R9                           0x00000019L
+#define DREG_REGID_RA                           0x0000001AL
+#define DREG_REGID_RB                           0x0000001BL
+#define DREG_REGID_RC                           0x0000001CL
+#define DREG_REGID_RD                           0x0000001DL
+#define DREG_REGID_RE                           0x0000001EL
+#define DREG_REGID_RF                           0x0000001FL
+#define DREG_REGID_RA_BUS_LOW                   0x00000020L
+#define DREG_REGID_RA_BUS_HIGH                  0x00000038L
+#define DREG_REGID_YBUS_LOW                     0x00000050L
+#define DREG_REGID_YBUS_HIGH                    0x00000058L
+#define DREG_REGID_TRAP_0                       0x00000100L
+#define DREG_REGID_TRAP_1                       0x00000101L
+#define DREG_REGID_TRAP_2                       0x00000102L
+#define DREG_REGID_TRAP_3                       0x00000103L
+#define DREG_REGID_TRAP_4                       0x00000104L
+#define DREG_REGID_TRAP_5                       0x00000105L
+#define DREG_REGID_TRAP_6                       0x00000106L
+#define DREG_REGID_TRAP_7                       0x00000107L
+#define DREG_REGID_INDIRECT_ADDRESS             0x0000010EL
+#define DREG_REGID_TOP_OF_STACK                 0x0000010FL
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_REGID_TRAP_8                       0x00000110L
+#define DREG_REGID_TRAP_9                       0x00000111L
+#define DREG_REGID_TRAP_10                      0x00000112L
+#define DREG_REGID_TRAP_11                      0x00000113L
+#define DREG_REGID_TRAP_12                      0x00000114L
+#define DREG_REGID_TRAP_13                      0x00000115L
+#define DREG_REGID_TRAP_14                      0x00000116L
+#define DREG_REGID_TRAP_15                      0x00000117L
+#define DREG_REGID_TRAP_16                      0x00000118L
+#define DREG_REGID_TRAP_17                      0x00000119L
+#define DREG_REGID_TRAP_18                      0x0000011AL
+#define DREG_REGID_TRAP_19                      0x0000011BL
+#define DREG_REGID_TRAP_20                      0x0000011CL
+#define DREG_REGID_TRAP_21                      0x0000011DL
+#define DREG_REGID_TRAP_22                      0x0000011EL
+#define DREG_REGID_TRAP_23                      0x0000011FL
+#endif
+#endif
+#define DREG_REGID_RSA0_LOW                     0x00000200L
+#define DREG_REGID_RSA0_HIGH                    0x00000201L
+#define DREG_REGID_RSA1_LOW                     0x00000202L
+#define DREG_REGID_RSA1_HIGH                    0x00000203L
+#define DREG_REGID_RSA2                         0x00000204L
+#define DREG_REGID_RSA3                         0x00000205L
+#define DREG_REGID_RSI0_LOW                     0x00000206L
+#define DREG_REGID_RSI0_HIGH                    0x00000207L
+#define DREG_REGID_RSI1                         0x00000208L
+#define DREG_REGID_RSI2                         0x00000209L
+#define DREG_REGID_SAGUSTATUS                   0x0000020AL
+#define DREG_REGID_RSCONFIG01_LOW               0x0000020BL
+#define DREG_REGID_RSCONFIG01_HIGH              0x0000020CL
+#define DREG_REGID_RSCONFIG23_LOW               0x0000020DL
+#define DREG_REGID_RSCONFIG23_HIGH              0x0000020EL
+#define DREG_REGID_RSDMA01E                     0x0000020FL
+#define DREG_REGID_RSDMA23E                     0x00000210L
+#define DREG_REGID_RSD0_LOW                     0x00000211L
+#define DREG_REGID_RSD0_HIGH                    0x00000212L
+#define DREG_REGID_RSD1_LOW                     0x00000213L
+#define DREG_REGID_RSD1_HIGH                    0x00000214L
+#define DREG_REGID_RSD2_LOW                     0x00000215L
+#define DREG_REGID_RSD2_HIGH                    0x00000216L
+#define DREG_REGID_RSD3_LOW                     0x00000217L
+#define DREG_REGID_RSD3_HIGH                    0x00000218L
+#define DREG_REGID_SRAR_HIGH                    0x0000021AL
+#define DREG_REGID_SRAR_LOW                     0x0000021BL
+#define DREG_REGID_DMA_STATE                    0x0000021CL
+#define DREG_REGID_CURRENT_DMA_STREAM           0x0000021DL
+#define DREG_REGID_NEXT_DMA_STREAM              0x0000021EL
+#define DREG_REGID_CPU_STATUS                   0x00000300L
+#define DREG_REGID_MAC_MODE                     0x00000301L
+#define DREG_REGID_STACK_AND_REPEAT             0x00000302L
+#define DREG_REGID_INDEX0                       0x00000304L
+#define DREG_REGID_INDEX1                       0x00000305L
+#define DREG_REGID_DMA_STATE_0_3                0x00000400L
+#define DREG_REGID_DMA_STATE_4_7                0x00000404L
+#define DREG_REGID_DMA_STATE_8_11               0x00000408L
+#define DREG_REGID_DMA_STATE_12_15              0x0000040CL
+#define DREG_REGID_DMA_STATE_16_19              0x00000410L
+#define DREG_REGID_DMA_STATE_20_23              0x00000414L
+#define DREG_REGID_DMA_STATE_24_27              0x00000418L
+#define DREG_REGID_DMA_STATE_28_31              0x0000041CL
+#define DREG_REGID_DMA_STATE_32_35              0x00000420L
+#define DREG_REGID_DMA_STATE_36_39              0x00000424L
+#define DREG_REGID_DMA_STATE_40_43              0x00000428L
+#define DREG_REGID_DMA_STATE_44_47              0x0000042CL
+#define DREG_REGID_DMA_STATE_48_51              0x00000430L
+#define DREG_REGID_DMA_STATE_52_55              0x00000434L
+#define DREG_REGID_DMA_STATE_56_59              0x00000438L
+#define DREG_REGID_DMA_STATE_60_63              0x0000043CL
+#define DREG_REGID_DMA_STATE_64_67              0x00000440L
+#define DREG_REGID_DMA_STATE_68_71              0x00000444L
+#define DREG_REGID_DMA_STATE_72_75              0x00000448L
+#define DREG_REGID_DMA_STATE_76_79              0x0000044CL
+#define DREG_REGID_DMA_STATE_80_83              0x00000450L
+#define DREG_REGID_DMA_STATE_84_87              0x00000454L
+#define DREG_REGID_DMA_STATE_88_91              0x00000458L
+#define DREG_REGID_DMA_STATE_92_95              0x0000045CL
+#define DREG_REGID_TRAP_SELECT                  0x00000500L
+#define DREG_REGID_TRAP_WRITE_0                 0x00000500L
+#define DREG_REGID_TRAP_WRITE_1                 0x00000501L
+#define DREG_REGID_TRAP_WRITE_2                 0x00000502L
+#define DREG_REGID_TRAP_WRITE_3                 0x00000503L
+#define DREG_REGID_TRAP_WRITE_4                 0x00000504L
+#define DREG_REGID_TRAP_WRITE_5                 0x00000505L
+#define DREG_REGID_TRAP_WRITE_6                 0x00000506L
+#define DREG_REGID_TRAP_WRITE_7                 0x00000507L
+#if !defined(NO_CS4612)
+#if !defined(NO_CS4615)
+#define DREG_REGID_TRAP_WRITE_8                 0x00000510L
+#define DREG_REGID_TRAP_WRITE_9                 0x00000511L
+#define DREG_REGID_TRAP_WRITE_10                0x00000512L
+#define DREG_REGID_TRAP_WRITE_11                0x00000513L
+#define DREG_REGID_TRAP_WRITE_12                0x00000514L
+#define DREG_REGID_TRAP_WRITE_13                0x00000515L
+#define DREG_REGID_TRAP_WRITE_14                0x00000516L
+#define DREG_REGID_TRAP_WRITE_15                0x00000517L
+#define DREG_REGID_TRAP_WRITE_16                0x00000518L
+#define DREG_REGID_TRAP_WRITE_17                0x00000519L
+#define DREG_REGID_TRAP_WRITE_18                0x0000051AL
+#define DREG_REGID_TRAP_WRITE_19                0x0000051BL
+#define DREG_REGID_TRAP_WRITE_20                0x0000051CL
+#define DREG_REGID_TRAP_WRITE_21                0x0000051DL
+#define DREG_REGID_TRAP_WRITE_22                0x0000051EL
+#define DREG_REGID_TRAP_WRITE_23                0x0000051FL
+#endif
+#endif
+#define DREG_REGID_MAC0_ACC0_LOW                0x00000600L
+#define DREG_REGID_MAC0_ACC1_LOW                0x00000601L
+#define DREG_REGID_MAC0_ACC2_LOW                0x00000602L
+#define DREG_REGID_MAC0_ACC3_LOW                0x00000603L
+#define DREG_REGID_MAC1_ACC0_LOW                0x00000604L
+#define DREG_REGID_MAC1_ACC1_LOW                0x00000605L
+#define DREG_REGID_MAC1_ACC2_LOW                0x00000606L
+#define DREG_REGID_MAC1_ACC3_LOW                0x00000607L
+#define DREG_REGID_MAC0_ACC0_MID                0x00000608L
+#define DREG_REGID_MAC0_ACC1_MID                0x00000609L
+#define DREG_REGID_MAC0_ACC2_MID                0x0000060AL
+#define DREG_REGID_MAC0_ACC3_MID                0x0000060BL
+#define DREG_REGID_MAC1_ACC0_MID                0x0000060CL
+#define DREG_REGID_MAC1_ACC1_MID                0x0000060DL
+#define DREG_REGID_MAC1_ACC2_MID                0x0000060EL
+#define DREG_REGID_MAC1_ACC3_MID                0x0000060FL
+#define DREG_REGID_MAC0_ACC0_HIGH               0x00000610L
+#define DREG_REGID_MAC0_ACC1_HIGH               0x00000611L
+#define DREG_REGID_MAC0_ACC2_HIGH               0x00000612L
+#define DREG_REGID_MAC0_ACC3_HIGH               0x00000613L
+#define DREG_REGID_MAC1_ACC0_HIGH               0x00000614L
+#define DREG_REGID_MAC1_ACC1_HIGH               0x00000615L
+#define DREG_REGID_MAC1_ACC2_HIGH               0x00000616L
+#define DREG_REGID_MAC1_ACC3_HIGH               0x00000617L
+#define DREG_REGID_RSHOUT_LOW                   0x00000620L
+#define DREG_REGID_RSHOUT_MID                   0x00000628L
+#define DREG_REGID_RSHOUT_HIGH                  0x00000630L
+
+//****************************************************************************
+//
+// The following defines are for the flags in the AC97 S/PDIF Control register.
+//
+//****************************************************************************
+#define SPDIF_CONTROL_SPDIF_EN                 0x00008000L
+#define SPDIF_CONTROL_VAL                      0x00004000L
+#define SPDIF_CONTROL_COPY                     0x00000004L
+#define SPDIF_CONTROL_CC0                      0x00000010L
+#define SPDIF_CONTROL_CC1                      0x00000020L
+#define SPDIF_CONTROL_CC2                      0x00000040L
+#define SPDIF_CONTROL_CC3                      0x00000080L
+#define SPDIF_CONTROL_CC4                      0x00000100L
+#define SPDIF_CONTROL_CC5                      0x00000200L
+#define SPDIF_CONTROL_CC6                      0x00000400L
+#define SPDIF_CONTROL_L                        0x00000800L
+
+#endif // _H_HWDEFS
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281/cs4281_wrapper-24.c linux/drivers/sound/cs4281/cs4281_wrapper-24.c
--- v2.4.1/linux/drivers/sound/cs4281/cs4281_wrapper-24.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281_wrapper-24.c	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,51 @@
+/*******************************************************************************
+*
+*      "cs4281_wrapper.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*
+*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
+*            -- tom woller (twoller@crystal.cirrus.com) or
+*               (audio@crystal.cirrus.com).
+*
+*      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.
+*
+* 12/20/00 trw - new file. 
+*
+*******************************************************************************/
+
+#include <linux/spinlock.h>
+
+void cs4281_null(struct pci_dev *pcidev) { return; }
+#define cs4x_mem_map_reserve(page) mem_map_reserve(page)
+#define cs4x_mem_map_unreserve(page) mem_map_unreserve(page)
+
+#define free_dmabuf(state, dmabuf) \
+	pci_free_consistent(state->pcidev, \
+			    PAGE_SIZE << (dmabuf)->buforder, \
+			    (dmabuf)->rawbuf, (dmabuf)->dmaaddr);
+#define free_dmabuf2(state, dmabuf) \
+	pci_free_consistent((state)->pcidev, \
+				    PAGE_SIZE << (state)->buforder_tmpbuff, \
+				    (state)->tmpbuff, (state)->dmaaddr_tmpbuff);
+#define cs4x_pgoff(vma) ((vma)->vm_pgoff)
+
+#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
+#define RSRCISMEMORYREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
+	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
+#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
+#define PCI_GET_DRIVER_DATA pci_get_drvdata
+#define PCI_SET_DRIVER_DATA pci_set_drvdata
+#define PCI_SET_DMA_MASK(pcidev,mask) pcidev->dma_mask = mask
+
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281/cs4281m.c linux/drivers/sound/cs4281/cs4281m.c
--- v2.4.1/linux/drivers/sound/cs4281/cs4281m.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281m.c	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,4537 @@
+/*******************************************************************************
+*
+*      "cs4281.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*
+*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
+*            -- adapted from drivers by Thomas Sailer, 
+*            -- but don't bug him; Problems should go to:
+*            -- tom woller (twoller@crystal.cirrus.com) or
+*               (audio@crystal.cirrus.com).
+*
+*      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.
+*
+* Module command line parameters:
+*   none
+*
+*  Supported devices:
+*  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible
+*  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
+*  /dev/midi   simple MIDI UART interface, no ioctl
+*
+* Modification History
+* 08/20/00 trw - silence and no stopping DAC until release
+* 08/23/00 trw - added CS_DBG statements, fix interrupt hang issue on DAC stop.
+* 09/18/00 trw - added 16bit only record with conversion 
+* 09/24/00 trw - added Enhanced Full duplex (separate simultaneous 
+*                capture/playback rates)
+* 10/03/00 trw - fixed mmap (fixed GRECORD and the XMMS mmap test plugin  
+*                libOSSm.so)
+* 10/11/00 trw - modified for 2.4.0-test9 kernel enhancements (NR_MAP removal)
+* 11/03/00 trw - fixed interrupt loss/stutter, added debug.
+* 11/10/00 bkz - added __devinit to cs4281_hw_init()
+* 11/10/00 trw - fixed SMP and capture spinlock hang.
+* 12/04/00 trw - cleaned up CSDEBUG flags and added "defaultorder" moduleparm.
+* 12/05/00 trw - fixed polling (myth2), and added underrun swptr fix.
+* 12/08/00 trw - added PM support. 
+* 12/14/00 trw - added wrapper code, builds under 2.4.0, 2.2.17-20, 2.2.17-8 
+*		 (RH/Dell base), 2.2.18, 2.2.12.  cleaned up code mods by ident.
+* 12/19/00 trw - added PM support for 2.2 base (apm_callback). other PM cleanup.
+* 12/21/00 trw - added fractional "defaultorder" inputs. if >100 then use 
+*		 defaultorder-100 as power of 2 for the buffer size. example:
+*		 106 = 2^(106-100) = 2^6 = 64 bytes for the buffer size.
+*
+*******************************************************************************/
+
+/* uncomment the following line to disable building PM support into the driver */
+//#define NOT_CS4281_PM 1 
+
+#include <linux/list.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/malloc.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/smp_lock.h>
+#include <linux/wrapper.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+//#include "cs_dm.h"
+#include "cs4281_hwdefs.h"
+#include "cs4281pm.h"
+
+struct cs4281_state;
+EXPORT_NO_SYMBOLS;
+
+static void stop_dac(struct cs4281_state *s);
+static void stop_adc(struct cs4281_state *s);
+static void start_dac(struct cs4281_state *s);
+static void start_adc(struct cs4281_state *s);
+#undef OSS_DOCUMENTED_MIXER_SEMANTICS
+
+// --------------------------------------------------------------------- 
+
+#ifndef PCI_VENDOR_ID_CIRRUS
+#define PCI_VENDOR_ID_CIRRUS          0x1013
+#endif
+#ifndef PCI_DEVICE_ID_CRYSTAL_CS4281
+#define PCI_DEVICE_ID_CRYSTAL_CS4281  0x6005
+#endif
+
+#define CS4281_MAGIC  ((PCI_DEVICE_ID_CRYSTAL_CS4281<<16) | PCI_VENDOR_ID_CIRRUS)
+#define	CS4281_CFLR_DEFAULT	0x00000001  /* CFLR must be in AC97 link mode */
+
+// buffer order determines the size of the dma buffer for the driver.
+// under Linux, a smaller buffer allows more responsiveness from many of the 
+// applications (e.g. games).  A larger buffer allows some of the apps (esound) 
+// to not underrun the dma buffer as easily.  As default, use 32k (order=3)
+// rather than 64k as some of the games work more responsively.
+// log base 2( buff sz = 32k).
+static unsigned long defaultorder = 3;
+MODULE_PARM(defaultorder, "i");
+
+//
+// Turn on/off debugging compilation by commenting out "#define CSDEBUG"
+//
+#define CSDEBUG 1
+#if CSDEBUG
+#define CSDEBUG_INTERFACE 1
+#else
+#undef CSDEBUG_INTERFACE
+#endif
+//
+// cs_debugmask areas
+//
+#define CS_INIT	 	0x00000001	// initialization and probe functions
+#define CS_ERROR 	0x00000002	// tmp debugging bit placeholder
+#define CS_INTERRUPT	0x00000004	// interrupt handler (separate from all other)
+#define CS_FUNCTION 	0x00000008	// enter/leave functions
+#define CS_WAVE_WRITE 	0x00000010	// write information for wave
+#define CS_WAVE_READ 	0x00000020	// read information for wave
+#define CS_MIDI_WRITE 	0x00000040	// write information for midi
+#define CS_MIDI_READ 	0x00000080	// read information for midi
+#define CS_MPU401_WRITE 0x00000100	// write information for mpu401
+#define CS_MPU401_READ 	0x00000200	// read information for mpu401
+#define CS_OPEN		0x00000400	// all open functions in the driver
+#define CS_RELEASE	0x00000800	// all release functions in the driver
+#define CS_PARMS	0x00001000	// functional and operational parameters
+#define CS_IOCTL	0x00002000	// ioctl (non-mixer)
+#define CS_PM		0x00004000	// power management 
+#define CS_TMP		0x10000000	// tmp debug mask bit
+
+#define CS_IOCTL_CMD_SUSPEND	0x1	// suspend
+#define CS_IOCTL_CMD_RESUME	0x2	// resume
+//
+// CSDEBUG is usual mode is set to 1, then use the
+// cs_debuglevel and cs_debugmask to turn on or off debugging.
+// Debug level of 1 has been defined to be kernel errors and info
+// that should be printed on any released driver.
+//
+#if CSDEBUG
+#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask) ) {x;}
+#else
+#define CS_DBGOUT(mask,level,x)
+#endif
+
+#if CSDEBUG
+static unsigned long cs_debuglevel = 1;	// levels range from 1-9
+static unsigned long cs_debugmask = CS_INIT | CS_ERROR;	// use CS_DBGOUT with various mask values
+MODULE_PARM(cs_debuglevel, "i");
+MODULE_PARM(cs_debugmask, "i");
+#endif
+#define CS_TRUE 	1
+#define CS_FALSE 	0
+
+// MIDI buffer sizes 
+#define MIDIINBUF  500
+#define MIDIOUTBUF 500
+
+#define FMODE_MIDI_SHIFT 3
+#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
+#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
+
+#define CS4281_MAJOR_VERSION 	1
+#define CS4281_MINOR_VERSION 	13
+#ifdef __ia64__
+#define CS4281_ARCH	     	64	//architecture key
+#else
+#define CS4281_ARCH	     	32	//architecture key
+#endif
+
+#define CS_TYPE_ADC 0
+#define CS_TYPE_DAC 1
+
+
+static const char invalid_magic[] =
+    KERN_CRIT "cs4281: invalid magic value\n";
+
+#define VALIDATE_STATE(s)                         \
+({                                                \
+        if (!(s) || (s)->magic != CS4281_MAGIC) { \
+                printk(invalid_magic);            \
+                return -ENXIO;                    \
+        }                                         \
+})
+
+#define list_for_each(pos, head) \
+        for (pos = (head)->next; pos != (head); pos = pos->next)
+
+//LIST_HEAD(cs4281_devs);
+struct list_head cs4281_devs = { &cs4281_devs, &cs4281_devs };
+
+struct cs4281_state; 
+
+#include "cs4281_wrapper-24.c"
+
+struct cs4281_state {
+	// magic 
+	unsigned int magic;
+
+	// we keep the cards in a linked list 
+	struct cs4281_state *next;
+
+	// pcidev is needed to turn off the DDMA controller at driver shutdown 
+	struct pci_dev *pcidev;
+	struct list_head list;
+
+	// soundcore stuff 
+	int dev_audio;
+	int dev_mixer;
+	int dev_midi;
+
+	// hardware resources 
+	unsigned int pBA0phys, pBA1phys;
+	char *pBA0, *pBA1;
+	unsigned int irq;
+
+	// mixer registers 
+	struct {
+		unsigned short vol[10];
+		unsigned int recsrc;
+		unsigned int modcnt;
+		unsigned short micpreamp;
+	} mix;
+
+	// wave stuff   
+	struct properties {
+		unsigned fmt;
+		unsigned fmt_original;	// original requested format
+		unsigned channels;
+		unsigned rate;
+		unsigned char clkdiv;
+	} prop_dac, prop_adc;
+	unsigned conversion:1;	// conversion from 16 to 8 bit in progress
+	void *tmpbuff;		// tmp buffer for sample conversions
+	unsigned ena;
+	spinlock_t lock;
+	struct semaphore open_sem;
+	struct semaphore open_sem_adc;
+	struct semaphore open_sem_dac;
+	mode_t open_mode;
+	wait_queue_head_t open_wait;
+	wait_queue_head_t open_wait_adc;
+	wait_queue_head_t open_wait_dac;
+
+	dma_addr_t dmaaddr_tmpbuff;
+	unsigned buforder_tmpbuff;	// Log base 2 of 'rawbuf' size in bytes..
+	struct dmabuf {
+		void *rawbuf;	// Physical address of  
+		dma_addr_t dmaaddr;
+		unsigned buforder;	// Log base 2 of 'rawbuf' size in bytes..
+		unsigned numfrag;	// # of 'fragments' in the buffer.
+		unsigned fragshift;	// Log base 2 of fragment size.
+		unsigned hwptr, swptr;
+		unsigned total_bytes;	// # bytes process since open.
+		unsigned blocks;	// last returned blocks value GETOPTR
+		unsigned wakeup;	// interrupt occurred on block 
+		int count;
+		unsigned underrun;	// underrun flag
+		unsigned error;	// over/underrun 
+		wait_queue_head_t wait;
+		// redundant, but makes calculations easier 
+		unsigned fragsize;	// 2**fragshift..
+		unsigned dmasize;	// 2**buforder.
+		unsigned fragsamples;
+		// OSS stuff 
+		unsigned mapped:1;	// Buffer mapped in cs4281_mmap()?
+		unsigned ready:1;	// prog_dmabuf_dac()/adc() successful?
+		unsigned endcleared:1;
+		unsigned type:1;	// adc or dac buffer (CS_TYPE_XXX)
+		unsigned ossfragshift;
+		int ossmaxfrags;
+		unsigned subdivision;
+	} dma_dac, dma_adc;
+
+	// midi stuff 
+	struct {
+		unsigned ird, iwr, icnt;
+		unsigned ord, owr, ocnt;
+		wait_queue_head_t iwait;
+		wait_queue_head_t owait;
+		struct timer_list timer;
+		unsigned char ibuf[MIDIINBUF];
+		unsigned char obuf[MIDIOUTBUF];
+	} midi;
+
+	struct cs4281_pm pm;
+	struct cs4281_pipeline pl[CS4281_NUMBER_OF_PIPELINES];
+};
+
+#include "cs4281pm-24.c"
+
+#if CSDEBUG
+
+// DEBUG ROUTINES
+
+#define SOUND_MIXER_CS_GETDBGLEVEL 	_SIOWR('M',120, int)
+#define SOUND_MIXER_CS_SETDBGLEVEL 	_SIOWR('M',121, int)
+#define SOUND_MIXER_CS_GETDBGMASK 	_SIOWR('M',122, int)
+#define SOUND_MIXER_CS_SETDBGMASK 	_SIOWR('M',123, int)
+
+#define SOUND_MIXER_CS_APM	 	_SIOWR('M',124, int)
+
+
+static void cs_printioctl(unsigned int x)
+{
+	unsigned int i;
+	unsigned char vidx;
+	// Index of mixtable1[] member is Device ID 
+	// and must be <= SOUND_MIXER_NRDEVICES.
+	// Value of array member is index into s->mix.vol[]
+	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
+		[SOUND_MIXER_PCM] = 1,	// voice 
+		[SOUND_MIXER_LINE1] = 2,	// AUX
+		[SOUND_MIXER_CD] = 3,	// CD 
+		[SOUND_MIXER_LINE] = 4,	// Line 
+		[SOUND_MIXER_SYNTH] = 5,	// FM
+		[SOUND_MIXER_MIC] = 6,	// Mic 
+		[SOUND_MIXER_SPEAKER] = 7,	// Speaker 
+		[SOUND_MIXER_RECLEV] = 8,	// Recording level 
+		[SOUND_MIXER_VOLUME] = 9	// Master Volume 
+	};
+
+	switch (x) {
+	case SOUND_MIXER_CS_GETDBGMASK:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SOUND_MIXER_CS_GETDBGMASK:\n"));
+		break;
+	case SOUND_MIXER_CS_GETDBGLEVEL:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SOUND_MIXER_CS_GETDBGLEVEL:\n"));
+		break;
+	case SOUND_MIXER_CS_SETDBGMASK:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SOUND_MIXER_CS_SETDBGMASK:\n"));
+		break;
+	case SOUND_MIXER_CS_SETDBGLEVEL:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SOUND_MIXER_CS_SETDBGLEVEL:\n"));
+		break;
+	case OSS_GETVERSION:
+		CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION:\n"));
+		break;
+	case SNDCTL_DSP_SYNC:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC:\n"));
+		break;
+	case SNDCTL_DSP_SETDUPLEX:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX:\n"));
+		break;
+	case SNDCTL_DSP_GETCAPS:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS:\n"));
+		break;
+	case SNDCTL_DSP_RESET:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET:\n"));
+		break;
+	case SNDCTL_DSP_SPEED:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED:\n"));
+		break;
+	case SNDCTL_DSP_STEREO:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO:\n"));
+		break;
+	case SNDCTL_DSP_CHANNELS:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS:\n"));
+		break;
+	case SNDCTL_DSP_GETFMTS:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS:\n"));
+		break;
+	case SNDCTL_DSP_SETFMT:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT:\n"));
+		break;
+	case SNDCTL_DSP_POST:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST:\n"));
+		break;
+	case SNDCTL_DSP_GETTRIGGER:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER:\n"));
+		break;
+	case SNDCTL_DSP_SETTRIGGER:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER:\n"));
+		break;
+	case SNDCTL_DSP_GETOSPACE:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE:\n"));
+		break;
+	case SNDCTL_DSP_GETISPACE:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE:\n"));
+		break;
+	case SNDCTL_DSP_NONBLOCK:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK:\n"));
+		break;
+	case SNDCTL_DSP_GETODELAY:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY:\n"));
+		break;
+	case SNDCTL_DSP_GETIPTR:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR:\n"));
+		break;
+	case SNDCTL_DSP_GETOPTR:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR:\n"));
+		break;
+	case SNDCTL_DSP_GETBLKSIZE:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE:\n"));
+		break;
+	case SNDCTL_DSP_SETFRAGMENT:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SNDCTL_DSP_SETFRAGMENT:\n"));
+		break;
+	case SNDCTL_DSP_SUBDIVIDE:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE:\n"));
+		break;
+	case SOUND_PCM_READ_RATE:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE:\n"));
+		break;
+	case SOUND_PCM_READ_CHANNELS:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SOUND_PCM_READ_CHANNELS:\n"));
+		break;
+	case SOUND_PCM_READ_BITS:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n"));
+		break;
+	case SOUND_PCM_WRITE_FILTER:
+		CS_DBGOUT(CS_IOCTL, 4,
+			  printk("SOUND_PCM_WRITE_FILTER:\n"));
+		break;
+	case SNDCTL_DSP_SETSYNCRO:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n"));
+		break;
+	case SOUND_PCM_READ_FILTER:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n"));
+		break;
+	case SOUND_MIXER_PRIVATE1:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n"));
+		break;
+	case SOUND_MIXER_PRIVATE2:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n"));
+		break;
+	case SOUND_MIXER_PRIVATE3:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n"));
+		break;
+	case SOUND_MIXER_PRIVATE4:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n"));
+		break;
+	case SOUND_MIXER_PRIVATE5:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n"));
+		break;
+	case SOUND_MIXER_INFO:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n"));
+		break;
+	case SOUND_OLD_MIXER_INFO:
+		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n"));
+		break;
+
+	default:
+		switch (_IOC_NR(x)) {
+		case SOUND_MIXER_VOLUME:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_VOLUME:\n"));
+			break;
+		case SOUND_MIXER_SPEAKER:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_SPEAKER:\n"));
+			break;
+		case SOUND_MIXER_RECLEV:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_RECLEV:\n"));
+			break;
+		case SOUND_MIXER_MIC:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_MIC:\n"));
+			break;
+		case SOUND_MIXER_SYNTH:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_SYNTH:\n"));
+			break;
+		case SOUND_MIXER_RECSRC:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_RECSRC:\n"));
+			break;
+		case SOUND_MIXER_DEVMASK:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_DEVMASK:\n"));
+			break;
+		case SOUND_MIXER_RECMASK:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_RECMASK:\n"));
+			break;
+		case SOUND_MIXER_STEREODEVS:
+			CS_DBGOUT(CS_IOCTL, 4,
+				  printk("SOUND_MIXER_STEREODEVS:\n"));
+			break;
+		case SOUND_MIXER_CAPS:
+			CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_CAPS:\n"));
+			break;
+		default:
+			i = _IOC_NR(x);
+			if (i >= SOUND_MIXER_NRDEVICES
+			    || !(vidx = mixtable1[i])) {
+				CS_DBGOUT(CS_IOCTL, 4, printk
+					("UNKNOWN IOCTL: 0x%.8x NR=%d\n",
+						x, i));
+			} else {
+				CS_DBGOUT(CS_IOCTL, 4, printk
+					("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n",
+						x, i));
+			}
+			break;
+		}
+	}
+}
+#endif
+static int prog_dmabuf_adc(struct cs4281_state *s);
+static void prog_codec(struct cs4281_state *s, unsigned type);
+
+// --------------------------------------------------------------------- 
+//
+//              Hardware Interfaces For the CS4281
+//
+
+
+//******************************************************************************
+// "delayus()-- Delay for the specified # of microseconds.
+//******************************************************************************
+static void delayus(struct cs4281_state *s, u32 delay)
+{
+	u32 j;
+	if ((delay > 9999) && (s->pm.flags & CS4281_PM_IDLE)) {
+		j = (delay * HZ) / 1000000;	/* calculate delay in jiffies  */
+		if (j < 1)
+			j = 1;	/* minimum one jiffy. */
+		current->state = TASK_UNINTERRUPTIBLE;
+		schedule_timeout(j);
+	} else
+		udelay(delay);
+	return;
+}
+
+
+//******************************************************************************
+// "cs4281_read_ac97" -- Reads a word from the specified location in the
+//               CS4281's address space(based on the BA0 register).
+//
+// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
+// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 register,
+//                                            0h for reads.
+// 3. Write ACCTL = Control Register = 460h for initiating the write
+// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
+// 5. if DCV not cleared, break and return error
+// 6. Read ACSTS = Status Register = 464h, check VSTS bit
+//****************************************************************************
+static int cs4281_read_ac97(struct cs4281_state *card, u32 offset,
+			    u32 * value)
+{
+	u32 count, status;
+
+	// Make sure that there is not data sitting
+	// around from a previous uncompleted access.
+	// ACSDA = Status Data Register = 47Ch
+	status = readl(card->pBA0 + BA0_ACSDA);
+
+	// Setup the AC97 control registers on the CS4281 to send the
+	// appropriate command to the AC97 to perform the read.
+	// ACCAD = Command Address Register = 46Ch
+	// ACCDA = Command Data Register = 470h
+	// ACCTL = Control Register = 460h
+	// bit DCV - will clear when process completed
+	// bit CRW - Read command
+	// bit VFRM - valid frame enabled
+	// bit ESYN - ASYNC generation enabled
+
+	// Get the actual AC97 register from the offset
+	writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD);
+	writel(0, card->pBA0 + BA0_ACCDA);
+	writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN,
+	       card->pBA0 + BA0_ACCTL);
+
+	// Wait for the read to occur.
+	for (count = 0; count < 10; count++) {
+		// First, we want to wait for a short time.
+		udelay(25);
+
+		// Now, check to see if the read has completed.
+		// ACCTL = 460h, DCV should be reset by now and 460h = 17h
+		if (!(readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV))
+			break;
+	}
+
+	// Make sure the read completed.
+	if (readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV)
+		return 1;
+
+	// Wait for the valid status bit to go active.
+	for (count = 0; count < 10; count++) {
+		// Read the AC97 status register.
+		// ACSTS = Status Register = 464h
+		status = readl(card->pBA0 + BA0_ACSTS);
+
+		// See if we have valid status.
+		// VSTS - Valid Status
+		if (status & ACSTS_VSTS)
+			break;
+		// Wait for a short while.
+		udelay(25);
+	}
+
+	// Make sure we got valid status.
+	if (!(status & ACSTS_VSTS))
+		return 1;
+
+	// Read the data returned from the AC97 register.
+	// ACSDA = Status Data Register = 474h
+	*value = readl(card->pBA0 + BA0_ACSDA);
+
+	// Success.
+	return (0);
+}
+
+
+//****************************************************************************
+//
+// "cs4281_write_ac97()"-- writes a word to the specified location in the
+// CS461x's address space (based on the part's base address zero register).
+//
+// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
+// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 reg.
+// 3. Write ACCTL = Control Register = 460h for initiating the write
+// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
+// 5. if DCV not cleared, break and return error
+//
+//****************************************************************************
+static int cs4281_write_ac97(struct cs4281_state *card, u32 offset,
+			     u32 value)
+{
+	u32 count, status=0;
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n"));
+
+	// Setup the AC97 control registers on the CS4281 to send the
+	// appropriate command to the AC97 to perform the read.
+	// ACCAD = Command Address Register = 46Ch
+	// ACCDA = Command Data Register = 470h
+	// ACCTL = Control Register = 460h
+	// set DCV - will clear when process completed
+	// reset CRW - Write command
+	// set VFRM - valid frame enabled
+	// set ESYN - ASYNC generation enabled
+	// set RSTN - ARST# inactive, AC97 codec not reset
+
+	// Get the actual AC97 register from the offset
+
+	writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD);
+	writel(value, card->pBA0 + BA0_ACCDA);
+	writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN,
+	       card->pBA0 + BA0_ACCTL);
+
+	// Wait for the write to occur.
+	for (count = 0; count < 10; count++) {
+		// First, we want to wait for a short time.
+		udelay(25);
+		// Now, check to see if the write has completed.
+		// ACCTL = 460h, DCV should be reset by now and 460h = 07h
+		status = readl(card->pBA0 + BA0_ACCTL);
+		if (!(status & ACCTL_DCV))
+			break;
+	}
+
+	// Make sure the write completed.
+	if (status & ACCTL_DCV) {
+		CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
+	      		"cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n"));
+		return 1;
+	}
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n"));
+	// Success.
+	return 0;
+}
+
+
+//******************************************************************************
+// "Init4281()" -- Bring up the part.
+//******************************************************************************
+static __devinit int cs4281_hw_init(struct cs4281_state *card)
+{
+	u32 ac97_slotid;
+	u32 temp1, temp2;
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n"));
+#ifndef NOT_CS4281_PM
+	if(!card)
+		return 1;
+#endif
+	temp2 = readl(card->pBA0 + BA0_CFLR);
+	CS_DBGOUT(CS_INIT | CS_ERROR | CS_PARMS, 4, printk(KERN_INFO 
+		"cs4281: cs4281_hw_init() CFLR 0x%x\n", temp2));
+	if(temp2 != CS4281_CFLR_DEFAULT)
+	{
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 
+			"cs4281: cs4281_hw_init() CFLR invalid - resetting from 0x%x to 0x%x\n",
+				temp2,CS4281_CFLR_DEFAULT));
+		writel(CS4281_CFLR_DEFAULT, card->pBA0 + BA0_CFLR);
+		temp2 = readl(card->pBA0 + BA0_CFLR);
+		if(temp2 != CS4281_CFLR_DEFAULT)
+		{
+			CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO 
+				"cs4281: cs4281_hw_init() Invalid hardware - unable to configure CFLR\n"));
+			return 1;
+		}
+	}
+
+	//***************************************7
+	//  Set up the Sound System Configuration
+	//***************************************
+
+	// Set the 'Configuration Write Protect' register
+	// to 4281h.  Allows vendor-defined configuration
+	// space between 0e4h and 0ffh to be written.
+
+	writel(0x4281, card->pBA0 + BA0_CWPR);	// (3e0h)
+
+	// (0), Blast the clock control register to zero so that the
+	// PLL starts out in a known state, and blast the master serial
+	// port control register to zero so that the serial ports also
+	// start out in a known state.
+
+	writel(0, card->pBA0 + BA0_CLKCR1);	// (400h)
+	writel(0, card->pBA0 + BA0_SERMC);	// (420h)
+
+
+	// (1), Make ESYN go to zero to turn off
+	// the Sync pulse on the AC97 link.
+
+	writel(0, card->pBA0 + BA0_ACCTL);
+	udelay(50);
+
+
+	// (2) Drive the ARST# pin low for a minimum of 1uS (as defined in
+	// the AC97 spec) and then drive it high.  This is done for non
+	// AC97 modes since there might be logic external to the CS461x
+	// that uses the ARST# line for a reset.
+
+	writel(0, card->pBA0 + BA0_SPMC);	// (3ech)
+	udelay(100);
+	writel(SPMC_RSTN, card->pBA0 + BA0_SPMC);
+	delayus(card,50000);		// Wait 50 ms for ABITCLK to become stable.
+
+	// (3) Turn on the Sound System Clocks.
+	writel(CLKCR1_PLLP, card->pBA0 + BA0_CLKCR1);	// (400h)
+	delayus(card,50000);		// Wait for the PLL to stabilize.
+	// Turn on clocking of the core (CLKCR1(400h) = 0x00000030)
+	writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0 + BA0_CLKCR1);
+
+	// (4) Power on everything for now..
+	writel(0x7E, card->pBA0 + BA0_SSPM);	// (740h)
+
+	// (5) Wait for clock stabilization.
+	for (temp1 = 0; temp1 < 1000; temp1++) {
+		udelay(1000);
+		if (readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)
+			break;
+	}
+	if (!(readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)) {
+		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR 
+			"cs4281: DLLRDY failed!\n"));
+		return -EIO;
+	}
+	// (6) Enable ASYNC generation.
+	writel(ACCTL_ESYN, card->pBA0 + BA0_ACCTL);	// (460h)
+
+	// Now wait 'for a short while' to allow the  AC97
+	// part to start generating bit clock. (so we don't
+	// Try to start the PLL without an input clock.)
+	delayus(card,50000);
+
+	// Set the serial port timing configuration, so that the
+	// clock control circuit gets its clock from the right place.
+	writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC);	// (420h)=2.
+
+	// (7) Wait for the codec ready signal from the AC97 codec.
+
+	for (temp1 = 0; temp1 < 1000; temp1++) {
+		// Delay a mil to let things settle out and
+		// to prevent retrying the read too quickly.
+		udelay(1000);
+		if (readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY)	// If ready,  (464h)
+			break;	//   exit the 'for' loop.
+	}
+	if (!(readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY))	// If never came ready,
+	{
+		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR
+			 "cs4281: ACSTS never came ready!\n"));
+		return -EIO;	//   exit initialization.
+	}
+	// (8) Assert the 'valid frame' signal so we can
+	// begin sending commands to the AC97 codec.
+	writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0 + BA0_ACCTL);	// (460h)
+
+	// (9), Wait until CODEC calibration is finished.
+	// Print an error message if it doesn't.
+	for (temp1 = 0; temp1 < 1000; temp1++) {
+		delayus(card,10000);
+		// Read the AC97 Powerdown Control/Status Register.
+		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp2);
+		if ((temp2 & 0x0000000F) == 0x0000000F)
+			break;
+	}
+	if ((temp2 & 0x0000000F) != 0x0000000F) {
+		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR
+			"cs4281: Codec failed to calibrate.  Status = %.8x.\n",
+				temp2));
+		return -EIO;
+	}
+	// (10), Set the serial port timing configuration, so that the
+	// clock control circuit gets its clock from the right place.
+	writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC);	// (420h)=2.
+
+
+	// (11) Wait until we've sampled input slots 3 & 4 as valid, meaning
+	// that the codec is pumping ADC data across the AC link.
+	for (temp1 = 0; temp1 < 1000; temp1++) {
+		// Delay a mil to let things settle out and
+		// to prevent retrying the read too quickly.
+		delayus(card,1000);	//(test)
+
+		// Read the input slot valid register;  See
+		// if input slots 3 and 4 are valid yet.
+		if (
+		    (readl(card->pBA0 + BA0_ACISV) &
+		     (ACISV_ISV3 | ACISV_ISV4)) ==
+		    (ACISV_ISV3 | ACISV_ISV4)) break;	// Exit the 'for' if slots are valid.
+	}
+	// If we never got valid data, exit initialization.
+	if ((readl(card->pBA0 + BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4))
+	    != (ACISV_ISV3 | ACISV_ISV4)) {
+		CS_DBGOUT(CS_FUNCTION, 2,
+			  printk(KERN_ERR
+				 "cs4281: Never got valid data!\n"));
+		return -EIO;	// If no valid data, exit initialization.
+	}
+	// (12), Start digital data transfer of audio data to the codec.
+	writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0 + BA0_ACOSV);	// (468h)
+
+
+	//**************************************
+	// Unmute the Master and Alternate
+	// (headphone) volumes.  Set to max.
+	//**************************************
+	cs4281_write_ac97(card, BA0_AC97_HEADPHONE_VOLUME, 0);
+	cs4281_write_ac97(card, BA0_AC97_MASTER_VOLUME, 0);
+
+	//******************************************
+	// Power on the DAC(AddDACUser()from main())
+	//******************************************
+	cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+	cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfdff);
+
+	// Wait until we sample a DAC ready state.
+	for (temp2 = 0; temp2 < 32; temp2++) {
+		// Let's wait a mil to let things settle.
+		delayus(card,1000);
+		// Read the current state of the power control reg.
+		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+		// If the DAC ready state bit is set, stop waiting.
+		if (temp1 & 0x2)
+			break;
+	}
+
+	//******************************************
+	// Power on the ADC(AddADCUser()from main())
+	//******************************************
+	cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+	cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfeff);
+
+	// Wait until we sample ADC ready state.
+	for (temp2 = 0; temp2 < 32; temp2++) {
+		// Let's wait a mil to let things settle.
+		delayus(card,1000);
+		// Read the current state of the power control reg.
+		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
+		// If the ADC ready state bit is set, stop waiting.
+		if (temp1 & 0x1)
+			break;
+	}
+	// Set up 4281 Register contents that
+	// don't change for boot duration.
+
+	// For playback, we map AC97 slot 3 and 4(Left
+	// & Right PCM playback) to DMA Channel 0.
+	// Set the fifo to be 15 bytes at offset zero.
+
+	ac97_slotid = 0x01000f00;	// FCR0.RS[4:0]=1(=>slot4, right PCM playback).
+	// FCR0.LS[4:0]=0(=>slot3, left PCM playback).
+	// FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0.
+	writel(ac97_slotid, card->pBA0 + BA0_FCR0);	// (180h)
+	writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0);	// Turn on FIFO Enable.
+
+	// For capture, we map AC97 slot 10 and 11(Left
+	// and Right PCM Record) to DMA Channel 1.
+	// Set the fifo to be 15 bytes at offset sixteen.
+	ac97_slotid = 0x0B0A0f10;	// FCR1.RS[4:0]=11(=>slot11, right PCM record).
+	// FCR1.LS[4:0]=10(=>slot10, left PCM record).
+	// FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16.
+	writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1);	// (184h)
+	writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1);	// Turn on FIFO Enable.
+
+	// Map the Playback SRC to the same AC97 slots(3 & 4--
+	// --Playback left & right)as DMA channel 0.
+	// Map the record SRC to the same AC97 slots(10 & 11--
+	// -- Record left & right) as DMA channel 1.
+
+	ac97_slotid = 0x0b0a0100;	// SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback).
+	// SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback).
+	// SCRSA.CRSS[4:0]=11(=>slot11, right PCM record)
+	// SCRSA.CLSS[4:0]=10(=>slot10, left PCM record).
+	writel(ac97_slotid, card->pBA0 + BA0_SRCSA);	// (75ch)
+
+	// Set 'Half Terminal Count Interrupt Enable' and 'Terminal
+	// Count Interrupt Enable' in DMA Control Registers 0 & 1.
+	// Set 'MSK' flag to 1 to keep the DMA engines paused.
+	temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK);	// (00030001h)
+	writel(temp1, card->pBA0 + BA0_DCR0);	// (154h
+	writel(temp1, card->pBA0 + BA0_DCR1);	// (15ch)
+
+	// Set 'Auto-Initialize Control' to 'enabled'; For playback,
+	// set 'Transfer Type Control'(TR[1:0]) to 'read transfer',
+	// for record, set Transfer Type Control to 'write transfer'.
+	// All other bits set to zero;  Some will be changed @ transfer start.
+	temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);	// (20000018h)
+	writel(temp1, card->pBA0 + BA0_DMR0);	// (150h)
+	temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);	// (20000014h)
+	writel(temp1, card->pBA0 + BA0_DMR1);	// (158h)
+
+	// Enable DMA interrupts generally, and
+	// DMA0 & DMA1 interrupts specifically.
+	temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff;
+	writel(temp1, card->pBA0 + BA0_HIMR);
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n"));
+	return 0;
+}
+
+#ifndef NOT_CS4281_PM
+void printpm(struct cs4281_state *s)
+{
+	CS_DBGOUT(CS_PM, 9, printk("pm struct:\n"));
+	CS_DBGOUT(CS_PM, 9, printk("flags:0x%x u32CLKCR1_SAVE: 0%x u32SSPMValue: 0x%x\n",
+		(unsigned)s->pm.flags,s->pm.u32CLKCR1_SAVE,s->pm.u32SSPMValue));
+	CS_DBGOUT(CS_PM, 9, printk("u32PPLVCvalue: 0x%x u32PPRVCvalue: 0x%x\n",
+		s->pm.u32PPLVCvalue,s->pm.u32PPRVCvalue));
+	CS_DBGOUT(CS_PM, 9, printk("u32FMLVCvalue: 0x%x u32FMRVCvalue: 0x%x\n",
+		s->pm.u32FMLVCvalue,s->pm.u32FMRVCvalue));
+	CS_DBGOUT(CS_PM, 9, printk("u32GPIORvalue: 0x%x u32JSCTLvalue: 0x%x\n",
+		s->pm.u32GPIORvalue,s->pm.u32JSCTLvalue));
+	CS_DBGOUT(CS_PM, 9, printk("u32SSCR: 0x%x u32SRCSA: 0x%x\n",
+		s->pm.u32SSCR,s->pm.u32SRCSA));
+	CS_DBGOUT(CS_PM, 9, printk("u32DacASR: 0x%x u32AdcASR: 0x%x\n",
+		s->pm.u32DacASR,s->pm.u32AdcASR));
+	CS_DBGOUT(CS_PM, 9, printk("u32DacSR: 0x%x u32AdcSR: 0x%x\n",
+		s->pm.u32DacSR,s->pm.u32AdcSR));
+	CS_DBGOUT(CS_PM, 9, printk("u32MIDCR_Save: 0x%x\n",
+		s->pm.u32MIDCR_Save));
+
+}
+void printpipe(struct cs4281_pipeline *pl)
+{
+
+	CS_DBGOUT(CS_PM, 9, printk("pm struct:\n"));
+	CS_DBGOUT(CS_PM, 9, printk("flags:0x%x number: 0%x\n",
+		(unsigned)pl->flags,pl->number));
+	CS_DBGOUT(CS_PM, 9, printk("u32DBAnValue: 0%x u32DBCnValue: 0x%x\n",
+		pl->u32DBAnValue,pl->u32DBCnValue));
+	CS_DBGOUT(CS_PM, 9, printk("u32DMRnValue: 0x%x u32DCRnValue: 0x%x\n",
+		pl->u32DMRnValue,pl->u32DCRnValue));
+	CS_DBGOUT(CS_PM, 9, printk("u32DBAnAddress: 0x%x u32DBCnAddress: 0x%x\n",
+		pl->u32DBAnAddress,pl->u32DBCnAddress));
+	CS_DBGOUT(CS_PM, 9, printk("u32DCAnAddress: 0x%x u32DCCnAddress: 0x%x\n",
+		pl->u32DCCnAddress,pl->u32DCCnAddress));
+	CS_DBGOUT(CS_PM, 9, printk("u32DMRnAddress: 0x%x u32DCRnAddress: 0x%x\n",
+		pl->u32DMRnAddress,pl->u32DCRnAddress));
+	CS_DBGOUT(CS_PM, 9, printk("u32HDSRnAddress: 0x%x u32DBAn_Save: 0x%x\n",
+		pl->u32HDSRnAddress,pl->u32DBAn_Save));
+	CS_DBGOUT(CS_PM, 9, printk("u32DBCn_Save: 0x%x u32DMRn_Save: 0x%x\n",
+		pl->u32DBCn_Save,pl->u32DMRn_Save));
+	CS_DBGOUT(CS_PM, 9, printk("u32DCRn_Save: 0x%x u32DCCn_Save: 0x%x\n",
+		pl->u32DCRn_Save,pl->u32DCCn_Save));
+	CS_DBGOUT(CS_PM, 9, printk("u32DCAn_Save: 0x%x\n",
+		pl->u32DCAn_Save));
+	CS_DBGOUT(CS_PM, 9, printk("u32FCRn_Save: 0x%x u32FSICn_Save: 0x%x\n",
+		pl->u32FCRn_Save,pl->u32FSICn_Save));
+	CS_DBGOUT(CS_PM, 9, printk("u32FCRnValue: 0x%x u32FSICnValue: 0x%x\n",
+		pl->u32FCRnValue,pl->u32FSICnValue));
+	CS_DBGOUT(CS_PM, 9, printk("u32FCRnAddress: 0x%x u32FSICnAddress: 0x%x\n",
+		pl->u32FCRnAddress,pl->u32FSICnAddress));
+	CS_DBGOUT(CS_PM, 9, printk("u32FPDRnValue: 0x%x u32FPDRnAddress: 0x%x\n",
+		pl->u32FPDRnValue,pl->u32FPDRnAddress));
+}
+void printpipelines(struct cs4281_state *s)
+{
+	int i;
+	for(i=0;i<CS4281_NUMBER_OF_PIPELINES;i++)
+	{
+		if(s->pl[i].flags & CS4281_PIPELINE_VALID)
+		{
+			printpipe(&s->pl[i]);
+		}
+	}
+}
+/****************************************************************************
+*
+*  Suspend - save the ac97 regs, mute the outputs and power down the part.  
+*
+****************************************************************************/
+void cs4281_ac97_suspend(struct cs4281_state *s)
+{
+	int Count,i;
+
+	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_suspend()+\n"));
+/*
+* change the state, save the current hwptr, then stop the dac/adc
+*/
+	s->pm.flags &= ~CS4281_PM_IDLE;
+	s->pm.flags |= CS4281_PM_SUSPENDING;
+	s->pm.u32hwptr_playback = readl(s->pBA0 + BA0_DCA0);
+	s->pm.u32hwptr_capture = readl(s->pBA0 + BA0_DCA1);
+	stop_dac(s);
+	stop_adc(s);
+
+	for(Count = 0x2, i=0; (Count <= CS4281_AC97_HIGHESTREGTORESTORE)
+			&& (i < CS4281_AC97_NUMBER_RESTORE_REGS); 
+		Count += 2, i++)
+	{
+		cs4281_read_ac97(s, BA0_AC97_RESET + Count, &s->pm.ac97[i]);
+	}
+/*
+* Save the ac97 volume registers as well as the current powerdown state.
+* Now, mute the all the outputs (master, headphone, and mono), as well
+* as the PCM volume, in preparation for powering down the entire part.
+*/ 
+	cs4281_read_ac97(s, BA0_AC97_MASTER_VOLUME, &s->pm.u32AC97_master_volume);
+	cs4281_read_ac97(s, BA0_AC97_HEADPHONE_VOLUME, &s->pm.u32AC97_headphone_volume);
+	cs4281_read_ac97(s, BA0_AC97_MASTER_VOLUME_MONO, &s->pm.u32AC97_master_volume_mono);
+	cs4281_read_ac97(s, BA0_AC97_PCM_OUT_VOLUME, &s->pm.u32AC97_pcm_out_volume);
+		
+	cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, 0x8000);
+	cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, 0x8000);
+	cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME_MONO, 0x8000);
+	cs4281_write_ac97(s, BA0_AC97_PCM_OUT_VOLUME, 0x8000);
+
+	cs4281_read_ac97(s, BA0_AC97_POWERDOWN, &s->pm.u32AC97_powerdown);
+	cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE, &s->pm.u32AC97_general_purpose);
+
+/*
+* And power down everything on the AC97 codec.
+*/
+	cs4281_write_ac97(s, BA0_AC97_POWERDOWN, 0xff00);
+	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_suspend()-\n"));
+}
+
+/****************************************************************************
+*
+*  Resume - power up the part and restore its registers..  
+*
+****************************************************************************/
+void cs4281_ac97_resume(struct cs4281_state *s)
+{
+	int Count,i;
+
+	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_resume()+\n"));
+
+/* do not save the power state registers at this time
+    //
+    // If we saved away the power control registers, write them into the
+    // shadows so those saved values get restored instead of the current
+    // shadowed value.
+    //
+    if( bPowerStateSaved )
+    {
+        PokeShadow( 0x26, ulSaveReg0x26 );
+        bPowerStateSaved = FALSE;
+    }
+*/
+
+//
+// First, we restore the state of the general purpose register.  This
+// contains the mic select (mic1 or mic2) and if we restore this after
+// we restore the mic volume/boost state and mic2 was selected at
+// suspend time, we will end up with a brief period of time where mic1
+// is selected with the volume/boost settings for mic2, causing
+// acoustic feedback.  So we restore the general purpose register
+// first, thereby getting the correct mic selected before we restore
+// the mic volume/boost.
+//
+	cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE, s->pm.u32AC97_general_purpose);
+
+//
+// Now, while the outputs are still muted, restore the state of power
+// on the AC97 part.
+//
+	cs4281_write_ac97(s, BA0_AC97_POWERDOWN, s->pm.u32AC97_powerdown);
+
+/*
+* Restore just the first set of registers, from register number
+* 0x02 to the register number that ulHighestRegToRestore specifies.
+*/
+	for(	Count = 0x2, i=0; 
+		(Count <= CS4281_AC97_HIGHESTREGTORESTORE)
+			&& (i < CS4281_AC97_NUMBER_RESTORE_REGS); 
+		Count += 2, i++)
+	{
+		cs4281_write_ac97(s, BA0_AC97_RESET + Count, s->pm.ac97[i]);
+	}
+	CS_DBGOUT(CS_PM, 9, printk("cs4281: cs4281_ac97_resume()-\n"));
+}
+
+/* do not save the power state registers at this time
+****************************************************************************
+*
+*  SavePowerState - Save the power registers away. 
+*
+****************************************************************************
+void 
+HWAC97codec::SavePowerState(void)
+{
+    ENTRY(TM_OBJECTCALLS, "HWAC97codec::SavePowerState()\r\n");
+
+    ulSaveReg0x26 = PeekShadow(0x26);
+
+    //
+    // Note that we have saved registers that need to be restored during a
+    // resume instead of ulAC97Regs[].
+    //
+    bPowerStateSaved = TRUE;
+
+} // SavePowerState
+*/
+
+void cs4281_SuspendFIFO(struct cs4281_state *s, struct cs4281_pipeline *pl)
+{
+ /*
+ * We need to save the contents of the BASIC FIFO Registers.
+ */
+	pl->u32FCRn_Save = readl(s->pBA0 + pl->u32FCRnAddress);
+	pl->u32FSICn_Save = readl(s->pBA0 + pl->u32FSICnAddress);
+}
+void cs4281_ResumeFIFO(struct cs4281_state *s, struct cs4281_pipeline *pl)
+{
+ /*
+ * We need to restore the contents of the BASIC FIFO Registers.
+ */
+	writel(pl->u32FCRn_Save,s->pBA0 + pl->u32FCRnAddress);
+	writel(pl->u32FSICn_Save,s->pBA0 + pl->u32FSICnAddress);
+}
+void cs4281_SuspendDMAengine(struct cs4281_state *s, struct cs4281_pipeline *pl)
+{
+	//
+	// We need to save the contents of the BASIC DMA Registers.
+	//
+	pl->u32DBAn_Save = readl(s->pBA0 + pl->u32DBAnAddress);
+	pl->u32DBCn_Save = readl(s->pBA0 + pl->u32DBCnAddress);
+	pl->u32DMRn_Save = readl(s->pBA0 + pl->u32DMRnAddress);
+	pl->u32DCRn_Save = readl(s->pBA0 + pl->u32DCRnAddress);
+	pl->u32DCCn_Save = readl(s->pBA0 + pl->u32DCCnAddress);
+	pl->u32DCAn_Save = readl(s->pBA0 + pl->u32DCAnAddress);
+}
+void cs4281_ResumeDMAengine(struct cs4281_state *s, struct cs4281_pipeline *pl)
+{
+	//
+	// We need to save the contents of the BASIC DMA Registers.
+	//
+	writel( pl->u32DBAn_Save, s->pBA0 + pl->u32DBAnAddress);
+	writel( pl->u32DBCn_Save, s->pBA0 + pl->u32DBCnAddress);
+	writel( pl->u32DMRn_Save, s->pBA0 + pl->u32DMRnAddress);
+	writel( pl->u32DCRn_Save, s->pBA0 + pl->u32DCRnAddress);
+	writel( pl->u32DCCn_Save, s->pBA0 + pl->u32DCCnAddress);
+	writel( pl->u32DCAn_Save, s->pBA0 + pl->u32DCAnAddress);
+}
+
+int cs4281_suspend(struct cs4281_state *s)
+{
+	int i;
+	u32 u32CLKCR1;
+	struct cs4281_pm *pm = &s->pm;
+	CS_DBGOUT(CS_PM | CS_FUNCTION, 9, 
+		printk("cs4281: cs4281_suspend()+ flags=%d\n",
+			(unsigned)s->pm.flags));
+/*
+* check the current state, only suspend if IDLE
+*/
+	if(!(s->pm.flags & CS4281_PM_IDLE))
+	{
+		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
+			printk("cs4281: cs4281_suspend() unable to suspend, not IDLE\n"));
+		return 1;
+	}
+	s->pm.flags &= ~CS4281_PM_IDLE;
+	s->pm.flags |= CS4281_PM_SUSPENDING;
+
+//
+// Gershwin CLKRUN - Set CKRA
+//
+	u32CLKCR1 = readl(s->pBA0 + BA0_CLKCR1);
+
+	pm->u32CLKCR1_SAVE = u32CLKCR1;
+	if(!(u32CLKCR1 & 0x00010000 ) )
+		writel(u32CLKCR1 | 0x00010000, s->pBA0 + BA0_CLKCR1);
+
+//
+// First, turn on the clocks (yikes) to the devices, so that they will
+// respond when we try to save their state.
+//
+	if(!(u32CLKCR1 & CLKCR1_SWCE))
+	{
+		writel(u32CLKCR1 | CLKCR1_SWCE , s->pBA0 + BA0_CLKCR1);
+	}
+    
+	//
+	// Save the power state
+	//
+	pm->u32SSPMValue = readl(s->pBA0 + BA0_SSPM);
+
+	//
+	// Disable interrupts.
+	//
+	writel(HICR_CHGM, s->pBA0 + BA0_HICR);
+
+	//
+	// Save the PCM Playback Left and Right Volume Control.
+	//
+	pm->u32PPLVCvalue = readl(s->pBA0 + BA0_PPLVC);
+	pm->u32PPRVCvalue = readl(s->pBA0 + BA0_PPRVC);
+
+	//
+	// Save the FM Synthesis Left and Right Volume Control.
+	//
+	pm->u32FMLVCvalue = readl(s->pBA0 + BA0_FMLVC);
+	pm->u32FMRVCvalue = readl(s->pBA0 + BA0_FMRVC);
+
+	//
+	// Save the GPIOR value.
+	//
+	pm->u32GPIORvalue = readl(s->pBA0 + BA0_GPIOR);
+
+	//
+	// Save the JSCTL value.
+	//
+	pm->u32JSCTLvalue = readl(s->pBA0 + BA0_GPIOR);
+
+	//
+	// Save Sound System Control Register
+	//
+	pm->u32SSCR = readl(s->pBA0 + BA0_SSCR);
+
+	//
+	// Save SRC Slot Assinment register
+	//
+	pm->u32SRCSA = readl(s->pBA0 + BA0_SRCSA);
+
+	//
+	// Save sample rate
+	//
+	pm->u32DacASR = readl(s->pBA0 + BA0_PASR);
+	pm->u32AdcASR = readl(s->pBA0 + BA0_CASR);
+	pm->u32DacSR = readl(s->pBA0 + BA0_DACSR);
+	pm->u32AdcSR = readl(s->pBA0 + BA0_ADCSR);
+
+	//
+	// Loop through all of the PipeLines 
+	//
+	for(i = 0; i < CS4281_NUMBER_OF_PIPELINES; i++)
+        {
+		if(s->pl[i].flags & CS4281_PIPELINE_VALID)
+		{
+		//
+		// Ask the DMAengines and FIFOs to Suspend.
+		//
+			cs4281_SuspendDMAengine(s,&s->pl[i]);
+			cs4281_SuspendFIFO(s,&s->pl[i]);
+		}
+	}
+	//
+	// We need to save the contents of the Midi Control Register.
+	//
+	pm->u32MIDCR_Save = readl(s->pBA0 + BA0_MIDCR);
+/*
+* save off the AC97 part information
+*/
+	cs4281_ac97_suspend(s);
+    
+	//
+	// Turn off the serial ports.
+	//
+	writel(0, s->pBA0 + BA0_SERMC);
+
+	//
+	// Power off FM, Joystick, AC link, 
+	//
+	writel(0, s->pBA0 + BA0_SSPM);
+
+	//
+	// DLL off.
+	//
+	writel(0, s->pBA0 + BA0_CLKCR1);
+
+	//
+	// AC link off.
+	//
+	writel(0, s->pBA0 + BA0_SPMC);
+
+	//
+	// Put the chip into D3(hot) state.
+	//
+	// PokeBA0(BA0_PMCS, 0x00000003);
+
+	//
+	// Gershwin CLKRUN - Clear CKRA
+	//
+	u32CLKCR1 = readl(s->pBA0 + BA0_CLKCR1);
+	writel(u32CLKCR1 & 0xFFFEFFFF, s->pBA0 + BA0_CLKCR1);
+
+#ifdef CSDEBUG
+	printpm(s);
+	printpipelines(s);
+#endif
+
+	s->pm.flags &= ~CS4281_PM_SUSPENDING;
+	s->pm.flags |= CS4281_PM_SUSPENDED;
+
+	CS_DBGOUT(CS_PM | CS_FUNCTION, 9, 
+		printk("cs4281: cs4281_suspend()- flags=%d\n",
+			(unsigned)s->pm.flags));
+	return 0;
+}
+
+int cs4281_resume(struct cs4281_state *s)
+{
+	int i;
+	unsigned temp1;
+	u32 u32CLKCR1;
+	struct cs4281_pm *pm = &s->pm;
+	CS_DBGOUT(CS_PM | CS_FUNCTION, 4, 
+		printk( "cs4281: cs4281_resume()+ flags=%d\n",
+			(unsigned)s->pm.flags));
+	if(!(s->pm.flags & CS4281_PM_SUSPENDED))
+	{
+		CS_DBGOUT(CS_PM | CS_ERROR, 2, 
+			printk("cs4281: cs4281_resume() unable to resume, not SUSPENDED\n"));
+		return 1;
+	}
+	s->pm.flags &= ~CS4281_PM_SUSPENDED;
+	s->pm.flags |= CS4281_PM_RESUMING;
+
+//
+// Gershwin CLKRUN - Set CKRA
+//
+	u32CLKCR1 = readl(s->pBA0 + BA0_CLKCR1);
+	writel(u32CLKCR1 | 0x00010000, s->pBA0 + BA0_CLKCR1);
+
+	//
+	// set the power state.
+	//
+	//old PokeBA0(BA0_PMCS, 0);
+
+	//
+	// Program the clock circuit and serial ports.
+	//
+	temp1 = cs4281_hw_init(s);
+	if (temp1) {
+		CS_DBGOUT(CS_ERROR | CS_INIT, 1,
+		    printk(KERN_ERR
+			"cs4281: resume cs4281_hw_init() error.\n"));
+		return -1;
+	}
+
+	//
+	// restore the Power state
+	//
+	writel(pm->u32SSPMValue, s->pBA0 + BA0_SSPM);
+
+	//
+	// Set post SRC mix setting (FM or ALT48K)
+	//
+	writel(pm->u32SSPM_BITS, s->pBA0 + BA0_SSPM);
+
+	//
+	// Loop through all of the PipeLines 
+	//
+	for(i = 0; i < CS4281_NUMBER_OF_PIPELINES; i++)
+        {
+		if(s->pl[i].flags & CS4281_PIPELINE_VALID)
+		{
+		//
+		// Ask the DMAengines and FIFOs to Resume.
+		//
+			cs4281_ResumeDMAengine(s,&s->pl[i]);
+			cs4281_ResumeFIFO(s,&s->pl[i]);
+		}
+	}
+	//
+	// We need to restore the contents of the Midi Control Register.
+	//
+	writel(pm->u32MIDCR_Save, s->pBA0 + BA0_MIDCR);
+
+	cs4281_ac97_resume(s);
+	//
+	// Restore the PCM Playback Left and Right Volume Control.
+	//
+	writel(pm->u32PPLVCvalue, s->pBA0 + BA0_PPLVC);
+	writel(pm->u32PPRVCvalue, s->pBA0 + BA0_PPRVC);
+
+	//
+	// Restore the FM Synthesis Left and Right Volume Control.
+	//
+	writel(pm->u32FMLVCvalue, s->pBA0 + BA0_FMLVC);
+	writel(pm->u32FMRVCvalue, s->pBA0 + BA0_FMRVC);
+
+	//
+	// Restore the JSCTL value.
+	//
+	writel(pm->u32JSCTLvalue, s->pBA0 + BA0_JSCTL);
+
+	//
+	// Restore the GPIOR register value.
+	//
+	writel(pm->u32GPIORvalue, s->pBA0 + BA0_GPIOR);
+
+	//
+	// Restore Sound System Control Register
+	//
+	writel(pm->u32SSCR, s->pBA0 + BA0_SSCR);
+
+	//
+	// Restore SRC Slot Assignment register
+	//
+	writel(pm->u32SRCSA, s->pBA0 + BA0_SRCSA);
+
+	//
+	// Restore sample rate
+	//
+	writel(pm->u32DacASR, s->pBA0 + BA0_PASR);
+	writel(pm->u32AdcASR, s->pBA0 + BA0_CASR);
+	writel(pm->u32DacSR, s->pBA0 + BA0_DACSR);
+	writel(pm->u32AdcSR, s->pBA0 + BA0_ADCSR);
+
+	// 
+	// Restore CFL1/2 registers we saved to compensate for OEM bugs.
+	//
+	//	PokeBA0(BA0_CFLR, ulConfig);
+
+	//
+	// Gershwin CLKRUN - Clear CKRA
+	//
+	writel(pm->u32CLKCR1_SAVE, s->pBA0 + BA0_CLKCR1);
+
+	//
+	// Enable interrupts on the part.
+	//
+	writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);
+
+#ifdef CSDEBUG
+	printpm(s);
+	printpipelines(s);
+#endif
+/*
+* change the state, restore the current hwptrs, then stop the dac/adc
+*/
+	s->pm.flags |= CS4281_PM_IDLE;
+	s->pm.flags &= ~(CS4281_PM_SUSPENDING | CS4281_PM_SUSPENDED 
+			| CS4281_PM_RESUMING | CS4281_PM_RESUMED);
+
+	writel(s->pm.u32hwptr_playback, s->pBA0 + BA0_DCA0);
+	writel(s->pm.u32hwptr_capture, s->pBA0 + BA0_DCA1);
+	start_dac(s);
+	start_adc(s);
+
+	CS_DBGOUT(CS_PM | CS_FUNCTION, 9, printk("cs4281: cs4281_resume()- flags=%d\n",
+		(unsigned)s->pm.flags));
+	return 0;
+}
+
+#endif
+
+//******************************************************************************
+// "cs4281_play_rate()" --
+//******************************************************************************
+static void cs4281_play_rate(struct cs4281_state *card, u32 playrate)
+{
+	u32 DACSRvalue = 1;
+
+	// Based on the sample rate, program the DACSR register.
+	if (playrate == 8000)
+		DACSRvalue = 5;
+	if (playrate == 11025)
+		DACSRvalue = 4;
+	else if (playrate == 22050)
+		DACSRvalue = 2;
+	else if (playrate == 44100)
+		DACSRvalue = 1;
+	else if ((playrate <= 48000) && (playrate >= 6023))
+		DACSRvalue = 24576000 / (playrate * 16);
+	else if (playrate < 6023)
+		// Not allowed by open.
+		return;
+	else if (playrate > 48000)
+		// Not allowed by open.
+		return;
+	CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO
+		"cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n",
+			DACSRvalue, playrate));
+	//  Write the 'sample rate select code'
+	//  to the 'DAC Sample Rate' register.
+	writel(DACSRvalue, card->pBA0 + BA0_DACSR);	// (744h)
+}
+
+//******************************************************************************
+// "cs4281_record_rate()" -- Initialize the record sample rate converter.
+//******************************************************************************
+static void cs4281_record_rate(struct cs4281_state *card, u32 outrate)
+{
+	u32 ADCSRvalue = 1;
+
+	//
+	// Based on the sample rate, program the ADCSR register
+	//
+	if (outrate == 8000)
+		ADCSRvalue = 5;
+	if (outrate == 11025)
+		ADCSRvalue = 4;
+	else if (outrate == 22050)
+		ADCSRvalue = 2;
+	else if (outrate == 44100)
+		ADCSRvalue = 1;
+	else if ((outrate <= 48000) && (outrate >= 6023))
+		ADCSRvalue = 24576000 / (outrate * 16);
+	else if (outrate < 6023) {
+		// Not allowed by open.
+		return;
+	} else if (outrate > 48000) {
+		// Not allowed by open.
+		return;
+	}
+	CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO
+		"cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n",
+			ADCSRvalue, outrate));
+	//  Write the 'sample rate select code
+	//  to the 'ADC Sample Rate' register.
+	writel(ADCSRvalue, card->pBA0 + BA0_ADCSR);	// (748h)
+}
+
+
+
+static void stop_dac(struct cs4281_state *s)
+{
+	unsigned long flags;
+	unsigned temp1;
+
+	CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO "cs4281: stop_dac():\n"));
+	spin_lock_irqsave(&s->lock, flags);
+	s->ena &= ~FMODE_WRITE;
+	temp1 = readl(s->pBA0 + BA0_DCR0) | DCRn_MSK;
+	writel(temp1, s->pBA0 + BA0_DCR0);
+
+	spin_unlock_irqrestore(&s->lock, flags);
+}
+
+
+static void start_dac(struct cs4281_state *s)
+{
+	unsigned long flags;
+	unsigned temp1;
+
+	CS_DBGOUT(CS_FUNCTION, 3, printk(KERN_INFO "cs4281: start_dac()+\n"));
+	spin_lock_irqsave(&s->lock, flags);
+	if (!(s->ena & FMODE_WRITE) && (s->dma_dac.mapped ||
+					(s->dma_dac.count > 0
+	    				&& s->dma_dac.ready))
+#ifndef NOT_CS4281_PM
+	&& (s->pm.flags & CS4281_PM_IDLE))
+#else
+)
+#endif
+ {
+		s->ena |= FMODE_WRITE;
+		temp1 = readl(s->pBA0 + BA0_DCR0) & ~DCRn_MSK;	// Clear DMA0 channel mask.
+		writel(temp1, s->pBA0 + BA0_DCR0);	// Start DMA'ing.
+		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts.              
+
+		writel(7, s->pBA0 + BA0_PPRVC);
+		writel(7, s->pBA0 + BA0_PPLVC);
+		CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 8, printk(KERN_INFO
+			"cs4281: start_dac(): writel 0x%x start dma\n", temp1));
+
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	CS_DBGOUT(CS_FUNCTION, 3,
+		  printk(KERN_INFO "cs4281: start_dac()-\n"));
+}
+
+
+static void stop_adc(struct cs4281_state *s)
+{
+	unsigned long flags;
+	unsigned temp1;
+
+	CS_DBGOUT(CS_FUNCTION, 3,
+		  printk(KERN_INFO "cs4281: stop_adc()+\n"));
+
+	spin_lock_irqsave(&s->lock, flags);
+	s->ena &= ~FMODE_READ;
+
+	if (s->conversion == 1) {
+		s->conversion = 0;
+		s->prop_adc.fmt = s->prop_adc.fmt_original;
+	}
+	temp1 = readl(s->pBA0 + BA0_DCR1) | DCRn_MSK;
+	writel(temp1, s->pBA0 + BA0_DCR1);
+	spin_unlock_irqrestore(&s->lock, flags);
+	CS_DBGOUT(CS_FUNCTION, 3,
+		  printk(KERN_INFO "cs4281: stop_adc()-\n"));
+}
+
+
+static void start_adc(struct cs4281_state *s)
+{
+	unsigned long flags;
+	unsigned temp1;
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: start_adc()+\n"));
+
+	if (!(s->ena & FMODE_READ) &&
+	    (s->dma_adc.mapped || s->dma_adc.count <=
+	     (signed) (s->dma_adc.dmasize - 2 * s->dma_adc.fragsize))
+	    && s->dma_adc.ready
+#ifndef NOT_CS4281_PM
+	&& (s->pm.flags & CS4281_PM_IDLE))
+#else
+) 
+#endif
+	{
+		if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) {
+			// 
+			// now only use 16 bit capture, due to truncation issue
+			// in the chip, noticable distortion occurs.
+			// allocate buffer and then convert from 16 bit to 
+			// 8 bit for the user buffer.
+			//
+			s->prop_adc.fmt_original = s->prop_adc.fmt;
+			if (s->prop_adc.fmt & AFMT_S8) {
+				s->prop_adc.fmt &= ~AFMT_S8;
+				s->prop_adc.fmt |= AFMT_S16_LE;
+			}
+			if (s->prop_adc.fmt & AFMT_U8) {
+				s->prop_adc.fmt &= ~AFMT_U8;
+				s->prop_adc.fmt |= AFMT_U16_LE;
+			}
+			//
+			// prog_dmabuf_adc performs a stop_adc() but that is
+			// ok since we really haven't started the DMA yet.
+			//
+			prog_codec(s, CS_TYPE_ADC);
+
+			if (prog_dmabuf_adc(s) != 0) {
+				CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
+					 "cs4281: start_adc(): error in prog_dmabuf_adc\n"));
+			}
+			s->conversion = 1;
+		}
+		spin_lock_irqsave(&s->lock, flags);
+		s->ena |= FMODE_READ;
+		temp1 = readl(s->pBA0 + BA0_DCR1) & ~DCRn_MSK;	// Clear DMA1 channel mask bit.
+		writel(temp1, s->pBA0 + BA0_DCR1);	// Start recording
+		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts.
+		spin_unlock_irqrestore(&s->lock, flags);
+
+		CS_DBGOUT(CS_PARMS, 6, printk(KERN_INFO
+			 "cs4281: start_adc(): writel 0x%x \n", temp1));
+	}
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: start_adc()-\n"));
+
+}
+
+
+// --------------------------------------------------------------------- 
+
+#define DMABUF_MINORDER 1	// ==> min buffer size = 8K.
+
+
+extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db)
+{
+	struct page *map, *mapend;
+
+	if (db->rawbuf) {
+		// Undo prog_dmabuf()'s marking the pages as reserved 
+		mapend =
+		    virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) -
+				 1);
+		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
+			cs4x_mem_map_unreserve(map);
+		free_dmabuf(s, db);
+	}
+	if (s->tmpbuff && (db->type == CS_TYPE_ADC)) {
+		// Undo prog_dmabuf()'s marking the pages as reserved 
+		mapend =
+		    virt_to_page(s->tmpbuff +
+				 (PAGE_SIZE << s->buforder_tmpbuff) - 1);
+		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)
+			cs4x_mem_map_unreserve(map);
+		free_dmabuf2(s, db);
+	}
+	s->tmpbuff = NULL;
+	db->rawbuf = NULL;
+	db->mapped = db->ready = 0;
+}
+
+static int prog_dmabuf(struct cs4281_state *s, struct dmabuf *db)
+{
+	int order;
+	unsigned bytespersec, temp1;
+	unsigned bufs, sample_shift = 0;
+	struct page *map, *mapend;
+	unsigned long df;
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: prog_dmabuf()+\n"));
+	db->hwptr = db->swptr = db->total_bytes = db->count = db->error =
+	    db->endcleared = db->blocks = db->wakeup = db->underrun = 0;
+/*
+* check for order within limits, but do not overwrite value, check
+* later for a fractional defaultorder (i.e. 100+).
+*/
+	if((defaultorder > 0) && (defaultorder < 12))
+		df = defaultorder;
+	else
+		df = 1;	
+
+	if (!db->rawbuf) {
+		db->ready = db->mapped = 0;
+		for (order = df; order >= DMABUF_MINORDER; order--)
+			if ( (db->rawbuf = (void *) pci_alloc_consistent(
+				s->pcidev, PAGE_SIZE << order, &db-> dmaaddr)))
+				    break;
+		if (!db->rawbuf) {
+			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+				"cs4281: prog_dmabuf(): unable to allocate rawbuf\n"));
+			return -ENOMEM;
+		}
+		db->buforder = order;
+		// Now mark the pages as reserved; otherwise the 
+		// remap_page_range() in cs4281_mmap doesn't work.
+		// 1. get index to last page in mem_map array for rawbuf.
+		mapend = virt_to_page(db->rawbuf + 
+			(PAGE_SIZE << db->buforder) - 1);
+
+		// 2. mark each physical page in range as 'reserved'.
+		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
+			cs4x_mem_map_reserve(map);
+	}
+	if (!s->tmpbuff && (db->type == CS_TYPE_ADC)) {
+		for (order = df; order >= DMABUF_MINORDER;
+		     order--)
+			if ( (s->tmpbuff = (void *) pci_alloc_consistent(
+					s->pcidev, PAGE_SIZE << order, 
+					&s->dmaaddr_tmpbuff)))
+				    break;
+		if (!s->tmpbuff) {
+			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+				"cs4281: prog_dmabuf(): unable to allocate tmpbuff\n"));
+			return -ENOMEM;
+		}
+		s->buforder_tmpbuff = order;
+		// Now mark the pages as reserved; otherwise the 
+		// remap_page_range() in cs4281_mmap doesn't work.
+		// 1. get index to last page in mem_map array for rawbuf.
+		mapend = virt_to_page(s->tmpbuff + 
+				(PAGE_SIZE << s->buforder_tmpbuff) - 1);
+
+		// 2. mark each physical page in range as 'reserved'.
+		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)
+			cs4x_mem_map_reserve(map);
+	}
+	if (db->type == CS_TYPE_DAC) {
+		if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE))
+			sample_shift++;
+		if (s->prop_dac.channels > 1)
+			sample_shift++;
+		bytespersec = s->prop_dac.rate << sample_shift;
+	} else			// CS_TYPE_ADC
+	{
+		if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE))
+			sample_shift++;
+		if (s->prop_adc.channels > 1)
+			sample_shift++;
+		bytespersec = s->prop_adc.rate << sample_shift;
+	}
+	bufs = PAGE_SIZE << db->buforder;
+
+/*
+* added fractional "defaultorder" inputs. if >100 then use 
+* defaultorder-100 as power of 2 for the buffer size. example:
+* 106 = 2^(106-100) = 2^6 = 64 bytes for the buffer size.
+*/
+	if(defaultorder >= 100)
+	{
+		bufs = 1 << (defaultorder-100);
+	}
+
+#define INTERRUPT_RATE_MS       100	// Interrupt rate in milliseconds.
+	db->numfrag = 2;
+/* 
+* Nominal frag size(bytes/interrupt)
+*/
+	temp1 = bytespersec / (1000 / INTERRUPT_RATE_MS);
+	db->fragshift = 8;	// Min 256 bytes.
+	while (1 << db->fragshift < temp1)	// Calc power of 2 frag size.
+		db->fragshift += 1;
+	db->fragsize = 1 << db->fragshift;
+	db->dmasize = db->fragsize * 2;
+	db->fragsamples = db->fragsize >> sample_shift;	// # samples/fragment.
+
+// If the calculated size is larger than the allocated
+//  buffer, divide the allocated buffer into 2 fragments.
+	if (db->dmasize > bufs) {
+
+		db->numfrag = 2;	// Two fragments.
+		db->fragsize = bufs >> 1;	// Each 1/2 the alloc'ed buffer.
+		db->fragsamples = db->fragsize >> sample_shift;	// # samples/fragment.
+		db->dmasize = bufs;	// Use all the alloc'ed buffer.
+
+		db->fragshift = 0;	// Calculate 'fragshift'.
+		temp1 = db->fragsize;	// update_ptr() uses it 
+		while ((temp1 >>= 1) > 1)	// to calc 'total-bytes'
+			db->fragshift += 1;	// returned in DSP_GETI/OPTR. 
+	}
+	CS_DBGOUT(CS_PARMS, 3, printk(KERN_INFO
+		"cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d bufs=%d fmt=0x%x ch=%d\n",
+			db->numfrag, db->fragsize, db->fragsamples, 
+			db->fragshift, bufs, 
+			(db->type == CS_TYPE_DAC) ? s->prop_dac.fmt : 
+				s->prop_adc.fmt, 
+			(db->type == CS_TYPE_DAC) ? s->prop_dac.channels : 
+				s->prop_adc.channels));
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: prog_dmabuf()-\n"));
+	return 0;
+}
+
+
+static int prog_dmabuf_adc(struct cs4281_state *s)
+{
+	unsigned long va;
+	unsigned count;
+	int c;
+	stop_adc(s);
+	s->dma_adc.type = CS_TYPE_ADC;
+	if ((c = prog_dmabuf(s, &s->dma_adc)))
+		return c;
+
+	if (s->dma_adc.rawbuf) {
+		memset(s->dma_adc.rawbuf,
+		       (s->prop_adc.
+			fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
+		       s->dma_adc.dmasize);
+	}
+	if (s->tmpbuff) {
+		memset(s->tmpbuff,
+		       (s->prop_adc.
+			fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
+		       PAGE_SIZE << s->buforder_tmpbuff);
+	}
+
+	va = virt_to_bus(s->dma_adc.rawbuf);
+
+	count = s->dma_adc.dmasize;
+
+	if (s->prop_adc.
+	    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))
+		    count /= 2;	// 16-bit.
+
+	if (s->prop_adc.channels > 1)
+		count /= 2;	// Assume stereo.
+
+	CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO
+		"cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n",
+			count, (unsigned) va));
+
+	writel(va, s->pBA0 + BA0_DBA1);	// Set buffer start address.
+	writel(count - 1, s->pBA0 + BA0_DBC1);	// Set count. 
+	s->dma_adc.ready = 1;
+	return 0;
+}
+
+
+static int prog_dmabuf_dac(struct cs4281_state *s)
+{
+	unsigned long va;
+	unsigned count;
+	int c;
+	stop_dac(s);
+	s->dma_dac.type = CS_TYPE_DAC;
+	if ((c = prog_dmabuf(s, &s->dma_dac)))
+		return c;
+	memset(s->dma_dac.rawbuf,
+	       (s->prop_dac.fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
+	       s->dma_dac.dmasize);
+
+	va = virt_to_bus(s->dma_dac.rawbuf);
+
+	count = s->dma_dac.dmasize;
+	if (s->prop_dac.
+	    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))
+		    count /= 2;	// 16-bit.
+
+	if (s->prop_dac.channels > 1)
+		count /= 2;	// Assume stereo.
+
+	writel(va, s->pBA0 + BA0_DBA0);	// Set buffer start address.
+	writel(count - 1, s->pBA0 + BA0_DBC0);	// Set count.             
+
+	CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO
+		"cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n",
+			count, (unsigned) va));
+
+	s->dma_dac.ready = 1;
+	return 0;
+}
+
+
+static void clear_advance(void *buf, unsigned bsize, unsigned bptr,
+			  unsigned len, unsigned char c)
+{
+	if (bptr + len > bsize) {
+		unsigned x = bsize - bptr;
+		memset(((char *) buf) + bptr, c, x);
+		bptr = 0;
+		len -= x;
+	}
+	CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO
+		"cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n",
+			(unsigned)c, (unsigned)((char *) buf) + bptr, len));
+	memset(((char *) buf) + bptr, c, len);
+}
+
+
+
+// call with spinlock held! 
+static void cs4281_update_ptr(struct cs4281_state *s, int intflag)
+{
+	int diff;
+	unsigned hwptr, va;
+
+	// update ADC pointer 
+	if (s->ena & FMODE_READ) {
+		hwptr = readl(s->pBA0 + BA0_DCA1);	// Read capture DMA address.
+		va = virt_to_bus(s->dma_adc.rawbuf);
+		hwptr -= (unsigned) va;
+		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;
+		if (s->dma_adc.count > s->dma_adc.dmasize)
+			s->dma_adc.count = s->dma_adc.dmasize;
+		if (s->dma_adc.mapped) {
+			if (s->dma_adc.count >=
+			    (signed) s->dma_adc.fragsize) wake_up(&s->
+								  dma_adc.
+								  wait);
+		} else {
+			if (s->dma_adc.count > 0)
+				wake_up(&s->dma_adc.wait);
+		}
+		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
+			"cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
+				(unsigned)s, s->dma_adc.hwptr, 
+				s->dma_adc.total_bytes, s->dma_adc.count));
+	}
+	// update DAC pointer 
+	//
+	// check for end of buffer, means that we are going to wait for another interrupt
+	// to allow silence to fill the fifos on the part, to keep pops down to a minimum.
+	//
+	if (s->ena & FMODE_WRITE) {
+		hwptr = readl(s->pBA0 + BA0_DCA0);	// Read play DMA address.
+		va = virt_to_bus(s->dma_dac.rawbuf);
+		hwptr -= (unsigned) va;
+		diff = (s->dma_dac.dmasize + hwptr -
+		     s->dma_dac.hwptr) % s->dma_dac.dmasize;
+		s->dma_dac.hwptr = hwptr;
+		s->dma_dac.total_bytes += diff;
+		if (s->dma_dac.mapped) {
+			s->dma_dac.count += diff;
+			if (s->dma_dac.count >= s->dma_dac.fragsize) {
+				s->dma_dac.wakeup = 1;
+				wake_up(&s->dma_dac.wait);
+				if (s->dma_dac.count > s->dma_dac.dmasize)
+					s->dma_dac.count &=
+					    s->dma_dac.dmasize - 1;
+			}
+		} else {
+			s->dma_dac.count -= diff;
+			if (s->dma_dac.count <= 0) {
+				//
+				// fill with silence, and do not shut down the DAC.
+				// Continue to play silence until the _release.
+				//
+				CS_DBGOUT(CS_WAVE_WRITE, 6, printk(KERN_INFO
+					"cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n",
+						(unsigned)(s->prop_dac.fmt & 
+						(AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0, 
+						(unsigned)s->dma_dac.rawbuf, 
+						s->dma_dac.dmasize));
+				memset(s->dma_dac.rawbuf,
+				       (s->prop_dac.
+					fmt & (AFMT_U8 | AFMT_U16_LE)) ?
+				       0x80 : 0, s->dma_dac.dmasize);
+				if (s->dma_dac.count < 0) {
+					s->dma_dac.underrun = 1;
+					s->dma_dac.count = 0;
+					CS_DBGOUT(CS_ERROR, 9, printk(KERN_INFO
+					 "cs4281: cs4281_update_ptr(): underrun\n"));
+				}
+			} else if (s->dma_dac.count <=
+				   (signed) s->dma_dac.fragsize
+				   && !s->dma_dac.endcleared) {
+				clear_advance(s->dma_dac.rawbuf,
+					      s->dma_dac.dmasize,
+					      s->dma_dac.swptr,
+					      s->dma_dac.fragsize,
+					      (s->prop_dac.
+					       fmt & (AFMT_U8 |
+						      AFMT_U16_LE)) ? 0x80
+					      : 0);
+				s->dma_dac.endcleared = 1;
+			}
+			if ( (s->dma_dac.count <= (signed) s->dma_dac.dmasize/2) ||
+				intflag)
+			{
+				wake_up(&s->dma_dac.wait);
+			}
+		}
+		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
+			"cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
+				(unsigned) s, s->dma_dac.hwptr, 
+				s->dma_dac.total_bytes, s->dma_dac.count));
+	}
+}
+
+
+// --------------------------------------------------------------------- 
+
+static void prog_codec(struct cs4281_state *s, unsigned type)
+{
+	unsigned long flags;
+	unsigned temp1, format;
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: prog_codec()+ \n"));
+
+	spin_lock_irqsave(&s->lock, flags);
+	if (type == CS_TYPE_ADC) {
+		temp1 = readl(s->pBA0 + BA0_DCR1);
+		writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR1);	// Stop capture DMA, if active.
+
+		// program sampling rates  
+		// Note, for CS4281, capture & play rates can be set independently.
+		cs4281_record_rate(s, s->prop_adc.rate);
+
+		// program ADC parameters 
+		format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE;
+		if (s->prop_adc.
+		    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) {	// 16-bit
+			if (s->prop_adc.fmt & (AFMT_S16_BE | AFMT_U16_BE))	// Big-endian?
+				format |= DMRn_BEND;
+			if (s->prop_adc.fmt & (AFMT_U16_LE | AFMT_U16_BE))
+				format |= DMRn_USIGN;	// Unsigned.      
+		} else
+			format |= DMRn_SIZE8 | DMRn_USIGN;	// 8-bit, unsigned
+		if (s->prop_adc.channels < 2)
+			format |= DMRn_MONO;
+
+		writel(format, s->pBA0 + BA0_DMR1);
+
+		CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO
+			"cs4281: prog_codec(): adc %s %s %s rate=%d DMR0 format=0x%.8x\n",
+				(format & DMRn_SIZE8) ? "8" : "16",
+				(format & DMRn_USIGN) ?  "Unsigned" : "Signed", 
+				(format & DMRn_MONO) ? "Mono" : "Stereo", 
+				s->prop_adc.rate, format));
+
+		s->ena &= ~FMODE_READ;	// not capturing data yet
+	}
+
+
+	if (type == CS_TYPE_DAC) {
+		temp1 = readl(s->pBA0 + BA0_DCR0);
+		writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR0);	// Stop play DMA, if active.
+
+		// program sampling rates  
+		// Note, for CS4281, capture & play rates can be set independently.
+		cs4281_play_rate(s, s->prop_dac.rate);
+
+		// program DAC parameters 
+		format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ;
+		if (s->prop_dac.
+		    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) {	// 16-bit
+			if (s->prop_dac.fmt & (AFMT_S16_BE | AFMT_U16_BE))
+				format |= DMRn_BEND;	// Big Endian.
+			if (s->prop_dac.fmt & (AFMT_U16_LE | AFMT_U16_BE))
+				format |= DMRn_USIGN;	// Unsigned.      
+		} else
+			format |= DMRn_SIZE8 | DMRn_USIGN;	// 8-bit, unsigned
+
+		if (s->prop_dac.channels < 2)
+			format |= DMRn_MONO;
+
+		writel(format, s->pBA0 + BA0_DMR0);
+
+
+		CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO
+			"cs4281: prog_codec(): dac %s %s %s rate=%d DMR0 format=0x%.8x\n",
+				(format & DMRn_SIZE8) ? "8" : "16",
+				(format & DMRn_USIGN) ?  "Unsigned" : "Signed",
+				(format & DMRn_MONO) ? "Mono" : "Stereo", 
+				s->prop_dac.rate, format));
+
+		s->ena &= ~FMODE_WRITE;	// not capturing data yet
+
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: prog_codec()- \n"));
+}
+
+
+static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd,
+		       unsigned long arg)
+{
+	// Index to mixer_src[] is value of AC97 Input Mux Select Reg.
+	// Value of array member is recording source Device ID Mask.
+	static const unsigned int mixer_src[8] = {
+		SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1,
+		SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0
+	};
+
+	// Index of mixtable1[] member is Device ID 
+	// and must be <= SOUND_MIXER_NRDEVICES.
+	// Value of array member is index into s->mix.vol[]
+	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
+		[SOUND_MIXER_PCM] = 1,	// voice 
+		[SOUND_MIXER_LINE1] = 2,	// AUX
+		[SOUND_MIXER_CD] = 3,	// CD 
+		[SOUND_MIXER_LINE] = 4,	// Line 
+		[SOUND_MIXER_SYNTH] = 5,	// FM
+		[SOUND_MIXER_MIC] = 6,	// Mic 
+		[SOUND_MIXER_SPEAKER] = 7,	// Speaker 
+		[SOUND_MIXER_RECLEV] = 8,	// Recording level 
+		[SOUND_MIXER_VOLUME] = 9	// Master Volume 
+	};
+
+
+	static const unsigned mixreg[] = {
+		BA0_AC97_PCM_OUT_VOLUME,
+		BA0_AC97_AUX_VOLUME,
+		BA0_AC97_CD_VOLUME,
+		BA0_AC97_LINE_IN_VOLUME
+	};
+	unsigned char l, r, rl, rr, vidx;
+	unsigned char attentbl[11] =
+	    { 63, 42, 26, 17, 14, 11, 8, 6, 4, 2, 0 };
+	unsigned temp1;
+	int i, val;
+
+	VALIDATE_STATE(s);
+	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
+		 "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n",
+			 (unsigned) s, cmd));
+#if CSDEBUG
+	cs_printioctl(cmd);
+#endif
+#if CSDEBUG_INTERFACE
+
+	if ((cmd == SOUND_MIXER_CS_GETDBGMASK) ||
+	    (cmd == SOUND_MIXER_CS_SETDBGMASK) ||
+	    (cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
+	    (cmd == SOUND_MIXER_CS_SETDBGLEVEL) ||
+	    (cmd == SOUND_MIXER_CS_APM))
+	{
+		switch (cmd) {
+
+		case SOUND_MIXER_CS_GETDBGMASK:
+			return put_user(cs_debugmask,
+					(unsigned long *) arg);
+
+		case SOUND_MIXER_CS_GETDBGLEVEL:
+			return put_user(cs_debuglevel,
+					(unsigned long *) arg);
+
+		case SOUND_MIXER_CS_SETDBGMASK:
+			if (get_user(val, (unsigned long *) arg))
+				return -EFAULT;
+			cs_debugmask = val;
+			return 0;
+
+		case SOUND_MIXER_CS_SETDBGLEVEL:
+			if (get_user(val, (unsigned long *) arg))
+				return -EFAULT;
+			cs_debuglevel = val;
+			return 0;
+#ifndef NOT_CS4281_PM
+		case SOUND_MIXER_CS_APM:
+			if (get_user(val, (unsigned long *) arg))
+				return -EFAULT;
+			if(val == CS_IOCTL_CMD_SUSPEND)
+				cs4281_suspend(s);
+			else if(val == CS_IOCTL_CMD_RESUME)
+				cs4281_resume(s);
+			else
+			{
+				CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
+				    "cs4281: mixer_ioctl(): invalid APM cmd (%d)\n",
+					val));
+			}
+			return 0;
+#endif
+		default:
+			CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
+				"cs4281: mixer_ioctl(): ERROR unknown debug cmd\n"));
+			return 0;
+		}
+	}
+#endif
+
+	if (cmd == SOUND_MIXER_PRIVATE1) {
+		// enable/disable/query mixer preamp 
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		if (val != -1) {
+			cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
+			temp1 = val ? (temp1 | 0x40) : (temp1 & 0xffbf);
+			cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1);
+		}
+		cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
+		val = (temp1 & 0x40) ? 1 : 0;
+		return put_user(val, (int *) arg);
+	}
+	if (cmd == SOUND_MIXER_PRIVATE2) {
+		// enable/disable/query spatializer 
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		if (val != -1) {
+			temp1 = (val & 0x3f) >> 2;
+			cs4281_write_ac97(s, BA0_AC97_3D_CONTROL, temp1);
+			cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE,
+					 &temp1);
+			cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE,
+					  temp1 | 0x2000);
+		}
+		cs4281_read_ac97(s, BA0_AC97_3D_CONTROL, &temp1);
+		return put_user((temp1 << 2) | 3, (int *) arg);
+	}
+	if (cmd == SOUND_MIXER_INFO) {
+		mixer_info info;
+		strncpy(info.id, "CS4281", sizeof(info.id));
+		strncpy(info.name, "Crystal CS4281", sizeof(info.name));
+		info.modify_counter = s->mix.modcnt;
+		if (copy_to_user((void *) arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == SOUND_OLD_MIXER_INFO) {
+		_old_mixer_info info;
+		strncpy(info.id, "CS4281", sizeof(info.id));
+		strncpy(info.name, "Crystal CS4281", sizeof(info.name));
+		if (copy_to_user((void *) arg, &info, sizeof(info)))
+			return -EFAULT;
+		return 0;
+	}
+	if (cmd == OSS_GETVERSION)
+		return put_user(SOUND_VERSION, (int *) arg);
+
+	if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))
+		return -EINVAL;
+
+	// If ioctl has only the SIOC_READ bit(bit 31)
+	// on, process the only-read commands. 
+	if (_SIOC_DIR(cmd) == _SIOC_READ) {
+		switch (_IOC_NR(cmd)) {
+		case SOUND_MIXER_RECSRC:	// Arg contains a bit for each recording source 
+			cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT,
+					 &temp1);
+			return put_user(mixer_src[temp1 & 7], (int *) arg);
+
+		case SOUND_MIXER_DEVMASK:	// Arg contains a bit for each supported device 
+			return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH |
+					SOUND_MASK_CD | SOUND_MASK_LINE |
+					SOUND_MASK_LINE1 | SOUND_MASK_MIC |
+					SOUND_MASK_VOLUME |
+					SOUND_MASK_RECLEV |
+					SOUND_MASK_SPEAKER, (int *) arg);
+
+		case SOUND_MIXER_RECMASK:	// Arg contains a bit for each supported recording source 
+			return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC |
+					SOUND_MASK_CD | SOUND_MASK_VOLUME |
+					SOUND_MASK_LINE1, (int *) arg);
+
+		case SOUND_MIXER_STEREODEVS:	// Mixer channels supporting stereo 
+			return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH |
+					SOUND_MASK_CD | SOUND_MASK_LINE |
+					SOUND_MASK_LINE1 | SOUND_MASK_MIC |
+					SOUND_MASK_VOLUME |
+					SOUND_MASK_RECLEV, (int *) arg);
+
+		case SOUND_MIXER_CAPS:
+			return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
+
+		default:
+			i = _IOC_NR(cmd);
+			if (i >= SOUND_MIXER_NRDEVICES
+			    || !(vidx = mixtable1[i]))
+				return -EINVAL;
+			return put_user(s->mix.vol[vidx - 1], (int *) arg);
+		}
+	}
+	// If ioctl doesn't have both the SIOC_READ and 
+	// the SIOC_WRITE bit set, return invalid.
+	if (_SIOC_DIR(cmd) != (_SIOC_READ | _SIOC_WRITE))
+		return -EINVAL;
+
+	// Increment the count of volume writes.
+	s->mix.modcnt++;
+
+	// Isolate the command; it must be a write.
+	switch (_IOC_NR(cmd)) {
+
+	case SOUND_MIXER_RECSRC:	// Arg contains a bit for each recording source 
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		i = hweight32(val);	// i = # bits on in val.
+		if (i != 1)	// One & only 1 bit must be on.
+			return 0;
+		for (i = 0; i < sizeof(mixer_src) / sizeof(int); i++) {
+			if (val == mixer_src[i]) {
+				temp1 = (i << 8) | i;
+				cs4281_write_ac97(s,
+						  BA0_AC97_RECORD_SELECT,
+						  temp1);
+				return 0;
+			}
+		}
+		return 0;
+
+	case SOUND_MIXER_VOLUME:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		l = val & 0xff;
+		if (l > 100)
+			l = 100;	// Max soundcard.h vol is 100.
+		if (l < 6) {
+			rl = 63;
+			l = 0;
+		} else
+			rl = attentbl[(10 * l) / 100];	// Convert 0-100 vol to 63-0 atten.
+
+		r = (val >> 8) & 0xff;
+		if (r > 100)
+			r = 100;	// Max right volume is 100, too
+		if (r < 6) {
+			rr = 63;
+			r = 0;
+		} else
+			rr = attentbl[(10 * r) / 100];	// Convert volume to attenuation.
+
+		if ((rl > 60) && (rr > 60))	// If both l & r are 'low',          
+			temp1 = 0x8000;	//  turn on the mute bit.
+		else
+			temp1 = 0;
+
+		temp1 |= (rl << 8) | rr;
+
+		cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, temp1);
+		cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, temp1);
+
+#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);
+
+	case SOUND_MIXER_SPEAKER:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		l = val & 0xff;
+		if (l > 100)
+			l = 100;
+		if (l < 3) {
+			rl = 0;
+			l = 0;
+		} else {
+			rl = (l * 2 - 5) / 13;	// Convert 0-100 range to 0-15.
+			l = (rl * 13 + 5) / 2;
+		}
+
+		if (rl < 3) {
+			temp1 = 0x8000;
+			rl = 0;
+		} else
+			temp1 = 0;
+		rl = 15 - rl;	// Convert volume to attenuation.
+		temp1 |= rl << 1;
+		cs4281_write_ac97(s, BA0_AC97_PC_BEEP_VOLUME, temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+		s->mix.vol[6] = l << 8;
+#else
+		s->mix.vol[6] = val;
+#endif
+		return put_user(s->mix.vol[6], (int *) arg);
+
+	case SOUND_MIXER_RECLEV:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		l = val & 0xff;
+		if (l > 100)
+			l = 100;
+		r = (val >> 8) & 0xff;
+		if (r > 100)
+			r = 100;
+		rl = (l * 2 - 5) / 13;	// Convert 0-100 scale to 0-15.
+		rr = (r * 2 - 5) / 13;
+		if (rl < 3 && rr < 3)
+			temp1 = 0x8000;
+		else
+			temp1 = 0;
+
+		temp1 = temp1 | (rl << 8) | rr;
+		cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+		s->mix.vol[7] = ((unsigned int) r << 8) | l;
+#else
+		s->mix.vol[7] = val;
+#endif
+		return put_user(s->mix.vol[7], (int *) arg);
+
+	case SOUND_MIXER_MIC:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		l = val & 0xff;
+		if (l > 100)
+			l = 100;
+		if (l < 1) {
+			l = 0;
+			rl = 0;
+		} else {
+			rl = ((unsigned) l * 5 - 4) / 16;	// Convert 0-100 range to 0-31.
+			l = (rl * 16 + 4) / 5;
+		}
+		cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
+		temp1 &= 0x40;	// Isolate 20db gain bit.
+		if (rl < 3) {
+			temp1 |= 0x8000;
+			rl = 0;
+		}
+		rl = 31 - rl;	// Convert volume to attenuation.
+		temp1 |= rl;
+		cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+		s->mix.vol[5] = val << 8;
+#else
+		s->mix.vol[5] = val;
+#endif
+		return put_user(s->mix.vol[5], (int *) arg);
+
+
+	case SOUND_MIXER_SYNTH:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		l = val & 0xff;
+		if (l > 100)
+			l = 100;
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		r = (val >> 8) & 0xff;
+		if (r > 100)
+			r = 100;
+		rl = (l * 2 - 11) / 3;	// Convert 0-100 range to 0-63.
+		rr = (r * 2 - 11) / 3;
+		if (rl < 3)	// If l is low, turn on
+			temp1 = 0x0080;	//  the mute bit.
+		else
+			temp1 = 0;
+
+		rl = 63 - rl;	// Convert vol to attenuation.
+		writel(temp1 | rl, s->pBA0 + BA0_FMLVC);
+		if (rr < 3)	//  If rr is low, turn on
+			temp1 = 0x0080;	//   the mute bit.
+		else
+			temp1 = 0;
+		rr = 63 - rr;	// Convert vol to attenuation.
+		writel(temp1 | rr, s->pBA0 + BA0_FMRVC);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+		s->mix.vol[4] = (r << 8) | l;
+#else
+		s->mix.vol[4] = val;
+#endif
+		return put_user(s->mix.vol[4], (int *) arg);
+
+
+	default:
+		CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO
+			"cs4281: mixer_ioctl(): default\n"));
+
+		i = _IOC_NR(cmd);
+		if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
+			return -EINVAL;
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		l = val & 0xff;
+		if (l > 100)
+			l = 100;
+		if (l < 1) {
+			l = 0;
+			rl = 31;
+		} else
+			rl = (attentbl[(l * 10) / 100]) >> 1;
+
+		r = (val >> 8) & 0xff;
+		if (r > 100)
+			r = 100;
+		if (r < 1) {
+			r = 0;
+			rr = 31;
+		} else
+			rr = (attentbl[(r * 10) / 100]) >> 1;
+		if ((rl > 30) && (rr > 30))
+			temp1 = 0x8000;
+		else
+			temp1 = 0;
+		temp1 = temp1 | (rl << 8) | rr;
+		cs4281_write_ac97(s, mixreg[vidx - 1], temp1);
+
+#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
+		s->mix.vol[vidx - 1] = ((unsigned int) r << 8) | l;
+#else
+		s->mix.vol[vidx - 1] = val;
+#endif
+#ifndef NOT_CS4281_PM
+		CS_DBGOUT(CS_PM, 9, printk(KERN_INFO 
+			"write ac97 mixreg[%d]=0x%x mix.vol[]=0x%x\n", 
+				vidx-1,temp1,s->mix.vol[vidx-1]));
+#endif
+		return put_user(s->mix.vol[vidx - 1], (int *) arg);
+	}
+}
+
+
+// --------------------------------------------------------------------- 
+
+static loff_t cs4281_llseek(struct file *file, loff_t offset, int origin)
+{
+	return -ESPIPE;
+}
+
+
+// --------------------------------------------------------------------- 
+
+static int cs4281_open_mixdev(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct cs4281_state *s=NULL;
+	struct list_head *entry;
+
+	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
+		  printk(KERN_INFO "cs4281: cs4281_open_mixdev()+\n"));
+
+	list_for_each(entry, &cs4281_devs)
+	{
+		s = list_entry(entry, struct cs4281_state, list);
+		if(s->dev_mixer == minor)
+			break;
+	}
+	if (!s)
+	{
+		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
+			printk(KERN_INFO "cs4281: cs4281_open_mixdev()- -ENODEV\n"));
+		return -ENODEV;
+	}
+	VALIDATE_STATE(s);
+	file->private_data = s;
+	MOD_INC_USE_COUNT;
+
+	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 4,
+		  printk(KERN_INFO "cs4281: cs4281_open_mixdev()- 0\n"));
+
+	return 0;
+}
+
+
+static int cs4281_release_mixdev(struct inode *inode, struct file *file)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+
+	VALIDATE_STATE(s);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+
+static int cs4281_ioctl_mixdev(struct inode *inode, struct file *file,
+			       unsigned int cmd, unsigned long arg)
+{
+	return mixer_ioctl((struct cs4281_state *) file->private_data, cmd,
+			   arg);
+}
+
+
+// ******************************************************************************************
+//   Mixer file operations struct.
+// ******************************************************************************************
+static /*const */ struct file_operations cs4281_mixer_fops = {
+	llseek:cs4281_llseek,
+	ioctl:cs4281_ioctl_mixdev,
+	open:cs4281_open_mixdev,
+	release:cs4281_release_mixdev,
+};
+
+// --------------------------------------------------------------------- 
+
+
+static int drain_adc(struct cs4281_state *s, int nonblock)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int count;
+	unsigned tmo;
+
+	if (s->dma_adc.mapped)
+		return 0;
+	add_wait_queue(&s->dma_adc.wait, &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_adc.count;
+		CS_DBGOUT(CS_FUNCTION, 2,
+			  printk(KERN_INFO "cs4281: drain_adc() %d\n", count));
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (count <= 0) {
+			CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO
+				 "cs4281: drain_adc() count<0\n"));
+			break;
+		}
+		if (signal_pending(current))
+			break;
+		if (nonblock) {
+			remove_wait_queue(&s->dma_adc.wait, &wait);
+			current->state = TASK_RUNNING;
+			return -EBUSY;
+		}
+		tmo =
+		    3 * HZ * (count +
+			      s->dma_adc.fragsize) / 2 / s->prop_adc.rate;
+		if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE))
+			tmo >>= 1;
+		if (s->prop_adc.channels > 1)
+			tmo >>= 1;
+		if (!schedule_timeout(tmo + 1))
+			printk(KERN_DEBUG "cs4281: dma timed out??\n");
+	}
+	remove_wait_queue(&s->dma_adc.wait, &wait);
+	current->state = TASK_RUNNING;
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+static int drain_dac(struct cs4281_state *s, int nonblock)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	int count;
+	unsigned tmo;
+
+	if (s->dma_dac.mapped)
+		return 0;
+	add_wait_queue(&s->dma_dac.wait, &wait);
+	for (;;) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		spin_lock_irqsave(&s->lock, flags);
+		count = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (count <= 0)
+			break;
+		if (signal_pending(current))
+			break;
+		if (nonblock) {
+			remove_wait_queue(&s->dma_dac.wait, &wait);
+			current->state = TASK_RUNNING;
+			return -EBUSY;
+		}
+		tmo =
+		    3 * HZ * (count +
+			      s->dma_dac.fragsize) / 2 / s->prop_dac.rate;
+		if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE))
+			tmo >>= 1;
+		if (s->prop_dac.channels > 1)
+			tmo >>= 1;
+		if (!schedule_timeout(tmo + 1))
+			printk(KERN_DEBUG "cs4281: dma timed out??\n");
+	}
+	remove_wait_queue(&s->dma_dac.wait, &wait);
+	current->state = TASK_RUNNING;
+	if (signal_pending(current))
+		return -ERESTARTSYS;
+	return 0;
+}
+
+//****************************************************************************
+//
+// CopySamples copies 16-bit stereo samples from the source to the
+// destination, possibly converting down to either 8-bit or mono or both.
+// count specifies the number of output bytes to write.
+//
+//  Arguments:
+//
+//  dst             - Pointer to a destination buffer.
+//  src             - Pointer to a source buffer
+//  count           - The number of bytes to copy into the destination buffer.
+//  iChannels       - Stereo - 2
+//                    Mono   - 1
+//  fmt             - AFMT_xxx (soundcard.h formats)
+//
+// NOTES: only call this routine for conversion to 8bit from 16bit
+//
+//****************************************************************************
+static void CopySamples(char *dst, char *src, int count, int iChannels,
+			unsigned fmt)
+{
+
+	unsigned short *psSrc;
+	long lAudioSample;
+
+	CS_DBGOUT(CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: CopySamples()+ "));
+	CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
+		 " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n",
+			 (unsigned) dst, (unsigned) src, (unsigned) count,
+			 (unsigned) iChannels, (unsigned) fmt));
+
+	// Gershwin does format conversion in hardware so normally
+	// we don't do any host based coversion. The data formatter
+	// truncates 16 bit data to 8 bit and that causes some hiss.
+	// We have already forced the HW to do 16 bit sampling and 
+	// 2 channel so that we can use software to round instead 
+	// of truncate
+
+	//
+	// See if the data should be output as 8-bit unsigned stereo.
+	// or if the data should be output at 8-bit unsigned mono.
+	//
+	if ( ((iChannels == 2) && (fmt & AFMT_U8)) ||
+		((iChannels == 1) && (fmt & AFMT_U8)) ) {
+		//
+		// Convert each 16-bit unsigned stereo sample to 8-bit unsigned 
+		// stereo using rounding.
+		//
+		psSrc = (unsigned short *) src;
+		count = count / 2;
+		while (count--) {
+			lAudioSample = (long) psSrc[count] + (long) 0x80;
+			if (lAudioSample > 0xffff) {
+				lAudioSample = 0xffff;
+			}
+			dst[count] = (char) (lAudioSample >> 8);
+		}
+	}
+	//
+	// check for 8-bit signed stereo.
+	//
+	else if ((iChannels == 2) && (fmt & AFMT_S8)) {
+		//
+		// Convert each 16-bit stereo sample to 8-bit stereo using rounding.
+		//
+		psSrc = (short *) src;
+		while (count--) {
+			lAudioSample =
+			    (((long) psSrc[0] + (long) psSrc[1]) / 2);
+			psSrc += 2;
+			*dst++ = (char) ((short) lAudioSample >> 8);
+		}
+	}
+	//
+	// Otherwise, the data should be output as 8-bit signed mono.
+	//
+	else if ((iChannels == 1) && (fmt & AFMT_S8)) {
+		//
+		// Convert each 16-bit signed mono sample to 8-bit signed mono 
+		// using rounding.
+		//
+		psSrc = (short *) src;
+		count = count / 2;
+		while (count--) {
+			lAudioSample =
+			    (((long) psSrc[0] + (long) psSrc[1]) / 2);
+			if (lAudioSample > 0x7fff) {
+				lAudioSample = 0x7fff;
+			}
+			psSrc += 2;
+			*dst++ = (char) ((short) lAudioSample >> 8);
+		}
+	}
+}
+
+//
+// cs_copy_to_user()
+// replacement for the standard copy_to_user, to allow for a conversion from
+// 16 bit to 8 bit if the record conversion is active.  the cs4281 has some
+// issues with 8 bit capture, so the driver always captures data in 16 bit
+// and then if the user requested 8 bit, converts from 16 to 8 bit.
+//
+static unsigned cs_copy_to_user(struct cs4281_state *s, void *dest,
+				unsigned *hwsrc, unsigned cnt,
+				unsigned *copied)
+{
+	void *src = hwsrc;	//default to the standard destination buffer addr
+
+	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO
+		"cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=0x%.8x\n",
+			s->prop_adc.fmt, s->prop_adc.fmt_original,
+			(unsigned) cnt, (unsigned) dest));
+
+	if (cnt > s->dma_adc.dmasize) {
+		cnt = s->dma_adc.dmasize;
+	}
+	if (!cnt) {
+		*copied = 0;
+		return 0;
+	}
+	if (s->conversion) {
+		if (!s->tmpbuff) {
+			*copied = cnt / 2;
+			return 0;
+		}
+		CopySamples(s->tmpbuff, (void *) hwsrc, cnt,
+			    (unsigned) s->prop_adc.channels,
+			    s->prop_adc.fmt_original);
+		src = s->tmpbuff;
+		cnt = cnt / 2;
+	}
+
+	if (copy_to_user(dest, src, cnt)) {
+		*copied = 0;
+		return -EFAULT;
+	}
+	*copied = cnt;
+	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO
+		"cs4281: cs_copy_to_user()- copied bytes is %d \n", cnt));
+	return 0;
+}
+
+// --------------------------------------------------------------------- 
+
+static ssize_t cs4281_read(struct file *file, char *buffer, size_t count,
+			   loff_t * ppos)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned swptr;
+	int cnt;
+	unsigned copied = 0;
+
+	CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
+		  printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count));
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->dma_adc.mapped)
+		return -ENXIO;
+	if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
+		return ret;
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+	ret = 0;
+//
+// "count" is the amount of bytes to read (from app), is decremented each loop
+//      by the amount of bytes that have been returned to the user buffer.
+// "cnt" is the running total of each read from the buffer (changes each loop)
+// "buffer" points to the app's buffer
+// "ret" keeps a running total of the amount of bytes that have been copied
+//      to the user buffer.
+// "copied" is the total bytes copied into the user buffer for each loop.
+//
+	while (count > 0) {
+		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
+			"_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n",
+				count, s->dma_adc.count,
+				s->dma_adc.swptr, s->dma_adc.hwptr));
+		spin_lock_irqsave(&s->lock, flags);
+
+		// get the current copy point of the sw buffer
+		swptr = s->dma_adc.swptr;
+
+		// cnt is the amount of unread bytes from the end of the 
+		// hw buffer to the current sw pointer
+		cnt = s->dma_adc.dmasize - swptr;
+
+		// dma_adc.count is the current total bytes that have not been read.
+		// if the amount of unread bytes from the current sw pointer to the
+		// end of the buffer is greater than the current total bytes that
+		// have not been read, then set the "cnt" (unread bytes) to the
+		// amount of unread bytes.  
+
+		if (s->dma_adc.count < cnt)
+			cnt = s->dma_adc.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		//
+		// if we are converting from 8/16 then we need to copy
+		// twice the number of 16 bit bytes then 8 bit bytes.
+		// 
+		if (s->conversion) {
+			if (cnt > (count * 2))
+				cnt = (count * 2);
+		} else {
+			if (cnt > count)
+				cnt = count;
+		}
+		//
+		// "cnt" NOW is the smaller of the amount that will be read,
+		// and the amount that is requested in this read (or partial).
+		// if there are no bytes in the buffer to read, then start the
+		// ADC and wait for the interrupt handler to wake us up.
+		//
+		if (cnt <= 0) {
+
+			// start up the dma engine and then continue back to the top of
+			// the loop when wake up occurs.
+			start_adc(s);
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+			interruptible_sleep_on(&s->dma_adc.wait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		// there are bytes in the buffer to read.
+		// copy from the hw buffer over to the user buffer.
+		// user buffer is designated by "buffer"
+		// virtual address to copy from is rawbuf+swptr
+		// the "cnt" is the number of bytes to read.
+
+		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO
+			"_read() copy_to cnt=%d count=%d ", cnt, count));
+		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
+			 " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n",
+				 s->dma_adc.dmasize, s->dma_adc.count,
+				 (unsigned) buffer, ret));
+
+		if (cs_copy_to_user
+		    (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied))
+			return ret ? ret : -EFAULT;
+		swptr = (swptr + cnt) % s->dma_adc.dmasize;
+		spin_lock_irqsave(&s->lock, flags);
+		s->dma_adc.swptr = swptr;
+		s->dma_adc.count -= cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= copied;
+		buffer += copied;
+		ret += copied;
+		start_adc(s);
+	}
+	CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
+		  printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret));
+	return ret;
+}
+
+
+static ssize_t cs4281_write(struct file *file, const char *buffer,
+			    size_t count, loff_t * ppos)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned swptr, hwptr, busaddr;
+	int cnt;
+
+	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
+		  printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n",
+			 count));
+	VALIDATE_STATE(s);
+
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (s->dma_dac.mapped)
+		return -ENXIO;
+	if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
+		return ret;
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	ret = 0;
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		if (s->dma_dac.count < 0) {
+			s->dma_dac.count = 0;
+			s->dma_dac.swptr = s->dma_dac.hwptr;
+		}
+		if (s->dma_dac.underrun) {
+			s->dma_dac.underrun = 0;
+			hwptr = readl(s->pBA0 + BA0_DCA0);
+			busaddr = virt_to_bus(s->dma_dac.rawbuf);
+			hwptr -= (unsigned) busaddr;
+			s->dma_dac.swptr = s->dma_dac.hwptr = hwptr;
+		}
+		swptr = s->dma_dac.swptr;
+		cnt = s->dma_dac.dmasize - swptr;
+		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
+			cnt = s->dma_dac.dmasize - s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			start_dac(s);
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+			interruptible_sleep_on(&s->dma_dac.wait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
+			return ret ? ret : -EFAULT;
+		swptr = (swptr + cnt) % s->dma_dac.dmasize;
+		spin_lock_irqsave(&s->lock, flags);
+		s->dma_dac.swptr = swptr;
+		s->dma_dac.count += cnt;
+		s->dma_dac.endcleared = 0;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		start_dac(s);
+	}
+	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
+		  printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret));
+	return ret;
+}
+
+
+static unsigned int cs4281_poll(struct file *file,
+				struct poll_table_struct *wait)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
+		  printk(KERN_INFO "cs4281: cs4281_poll()+\n"));
+	VALIDATE_STATE(s);
+	if (file->f_mode & FMODE_WRITE) {
+		CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
+			  printk(KERN_INFO
+				 "cs4281: cs4281_poll() wait on FMODE_WRITE\n"));
+		if(!s->dma_dac.ready && prog_dmabuf_dac(s))
+			return 0;
+		poll_wait(file, &s->dma_dac.wait, wait);
+	}
+	if (file->f_mode & FMODE_READ) {
+		CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
+			  printk(KERN_INFO
+				 "cs4281: cs4281_poll() wait on FMODE_READ\n"));
+		if(!s->dma_dac.ready && prog_dmabuf_adc(s))
+			return 0;
+		poll_wait(file, &s->dma_adc.wait, wait);
+	}
+	spin_lock_irqsave(&s->lock, flags);
+	cs4281_update_ptr(s,CS_FALSE);
+	if (file->f_mode & FMODE_WRITE) {
+		if (s->dma_dac.mapped) {
+			if (s->dma_dac.count >=
+			    (signed) s->dma_dac.fragsize) {
+				if (s->dma_dac.wakeup)
+					mask |= POLLOUT | POLLWRNORM;
+				else
+					mask = 0;
+				s->dma_dac.wakeup = 0;
+			}
+		} else {
+			if ((signed) (s->dma_dac.dmasize/2) >= s->dma_dac.count)
+				mask |= POLLOUT | POLLWRNORM;
+		}
+	} else if (file->f_mode & FMODE_READ) {
+		if (s->dma_adc.mapped) {
+			if (s->dma_adc.count >= (signed) s->dma_adc.fragsize) 
+				mask |= POLLIN | POLLRDNORM;
+		} else {
+			if (s->dma_adc.count > 0)
+				mask |= POLLIN | POLLRDNORM;
+		}
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
+		  printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n",
+			 mask));
+	return mask;
+}
+
+
+static int cs4281_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	struct dmabuf *db;
+	int ret;
+	unsigned long size;
+
+	CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4,
+		  printk(KERN_INFO "cs4281: cs4281_mmap()+\n"));
+
+	VALIDATE_STATE(s);
+	if (vma->vm_flags & VM_WRITE) {
+		if ((ret = prog_dmabuf_dac(s)) != 0)
+			return ret;
+		db = &s->dma_dac;
+	} else if (vma->vm_flags & VM_READ) {
+		if ((ret = prog_dmabuf_adc(s)) != 0)
+			return ret;
+		db = &s->dma_adc;
+	} else
+		return -EINVAL;
+//
+// only support PLAYBACK for now
+//
+	db = &s->dma_dac;
+
+	if (cs4x_pgoff(vma) != 0)
+		return -EINVAL;
+	size = vma->vm_end - vma->vm_start;
+	if (size > (PAGE_SIZE << db->buforder))
+		return -EINVAL;
+	if (remap_page_range
+	    (vma->vm_start, virt_to_phys(db->rawbuf), size,
+	     vma->vm_page_prot)) return -EAGAIN;
+	db->mapped = 1;
+
+	CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4,
+		  printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n",
+			 (unsigned) size));
+
+	return 0;
+}
+
+
+static int cs4281_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	unsigned long flags;
+	audio_buf_info abinfo;
+	count_info cinfo;
+	int val, mapped, ret;
+
+	CS_DBGOUT(CS_FUNCTION, 4, printk(KERN_INFO
+		 "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n",
+			 (unsigned) file, cmd));
+#if CSDEBUG
+	cs_printioctl(cmd);
+#endif
+	VALIDATE_STATE(s);
+	mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
+	    ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+	switch (cmd) {
+	case OSS_GETVERSION:
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+			"cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n",
+				 SOUND_VERSION));
+		return put_user(SOUND_VERSION, (int *) arg);
+
+	case SNDCTL_DSP_SYNC:
+		CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_SYNC\n"));
+		if (file->f_mode & FMODE_WRITE)
+			return drain_dac(s,
+					 0 /*file->f_flags & O_NONBLOCK */
+					 );
+		return 0;
+
+	case SNDCTL_DSP_SETDUPLEX:
+		return 0;
+
+	case SNDCTL_DSP_GETCAPS:
+		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
+				DSP_CAP_TRIGGER | DSP_CAP_MMAP,
+				(int *) arg);
+
+	case SNDCTL_DSP_RESET:
+		CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_RESET\n"));
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			synchronize_irq();
+			s->dma_dac.swptr = s->dma_dac.hwptr =
+			    s->dma_dac.count = s->dma_dac.total_bytes =
+			    s->dma_dac.blocks = s->dma_dac.wakeup = 0;
+			prog_codec(s, CS_TYPE_DAC);
+		}
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			synchronize_irq();
+			s->dma_adc.swptr = s->dma_adc.hwptr =
+			    s->dma_adc.count = s->dma_adc.total_bytes =
+			    s->dma_adc.blocks = s->dma_dac.wakeup = 0;
+			prog_codec(s, CS_TYPE_ADC);
+		}
+		return 0;
+
+	case SNDCTL_DSP_SPEED:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_SPEED val=%d\n", val));
+		//
+		// support independent capture and playback channels
+		// assume that the file mode bit determines the 
+		// direction of the data flow.
+		//
+		if (file->f_mode & FMODE_READ) {
+			if (val >= 0) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				// program sampling rates 
+				if (val > 48000)
+					val = 48000;
+				if (val < 6300)
+					val = 6300;
+				s->prop_adc.rate = val;
+				prog_codec(s, CS_TYPE_ADC);
+			}
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			if (val >= 0) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				// program sampling rates 
+				if (val > 48000)
+					val = 48000;
+				if (val < 6300)
+					val = 6300;
+				s->prop_dac.rate = val;
+				prog_codec(s, CS_TYPE_DAC);
+			}
+		}
+
+		if (file->f_mode & FMODE_WRITE)
+			val = s->prop_dac.rate;
+		else if (file->f_mode & FMODE_READ)
+			val = s->prop_adc.rate;
+
+		return put_user(val, (int *) arg);
+
+	case SNDCTL_DSP_STEREO:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_STEREO val=%d\n", val));
+		if (file->f_mode & FMODE_READ) {
+			stop_adc(s);
+			s->dma_adc.ready = 0;
+			s->prop_adc.channels = val ? 2 : 1;
+			prog_codec(s, CS_TYPE_ADC);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			stop_dac(s);
+			s->dma_dac.ready = 0;
+			s->prop_dac.channels = val ? 2 : 1;
+			prog_codec(s, CS_TYPE_DAC);
+		}
+		return 0;
+
+	case SNDCTL_DSP_CHANNELS:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_CHANNELS val=%d\n",
+				 val));
+		if (val != 0) {
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				if (val >= 2)
+					s->prop_adc.channels = 2;
+				else
+					s->prop_adc.channels = 1;
+				prog_codec(s, CS_TYPE_ADC);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				if (val >= 2)
+					s->prop_dac.channels = 2;
+				else
+					s->prop_dac.channels = 1;
+				prog_codec(s, CS_TYPE_DAC);
+			}
+		}
+
+		if (file->f_mode & FMODE_WRITE)
+			val = s->prop_dac.channels;
+		else if (file->f_mode & FMODE_READ)
+			val = s->prop_adc.channels;
+
+		return put_user(val, (int *) arg);
+
+	case SNDCTL_DSP_GETFMTS:	// Returns a mask 
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+			"cs4281: cs4281_ioctl(): DSP_GETFMT val=0x%.8x\n",
+				 AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
+				 AFMT_U8));
+		return put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
+				AFMT_U8, (int *) arg);
+
+	case SNDCTL_DSP_SETFMT:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_SETFMT val=0x%.8x\n",
+				 val));
+		if (val != AFMT_QUERY) {
+			if (file->f_mode & FMODE_READ) {
+				stop_adc(s);
+				s->dma_adc.ready = 0;
+				if (val != AFMT_S16_LE
+				    && val != AFMT_U16_LE && val != AFMT_S8
+				    && val != AFMT_U8)
+					val = AFMT_U8;
+				s->prop_adc.fmt = val;
+				s->prop_adc.fmt_original = s->prop_adc.fmt;
+				prog_codec(s, CS_TYPE_ADC);
+			}
+			if (file->f_mode & FMODE_WRITE) {
+				stop_dac(s);
+				s->dma_dac.ready = 0;
+				if (val != AFMT_S16_LE
+				    && val != AFMT_U16_LE && val != AFMT_S8
+				    && val != AFMT_U8)
+					val = AFMT_U8;
+				s->prop_dac.fmt = val;
+				s->prop_dac.fmt_original = s->prop_dac.fmt;
+				prog_codec(s, CS_TYPE_DAC);
+			}
+		} else {
+			if (file->f_mode & FMODE_WRITE)
+				val = s->prop_dac.fmt_original;
+			else if (file->f_mode & FMODE_READ)
+				val = s->prop_adc.fmt_original;
+		}
+		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
+		  "cs4281: cs4281_ioctl(): DSP_SETFMT return val=0x%.8x\n", 
+			val));
+		return put_user(val, (int *) arg);
+
+	case SNDCTL_DSP_POST:
+		CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO
+			 "cs4281: cs4281_ioctl(): DSP_POST\n"));
+		return 0;
+
+	case SNDCTL_DSP_GETTRIGGER:
+		val = 0;
+		if (file->f_mode & s->ena & FMODE_READ)
+			val |= PCM_ENABLE_INPUT;
+		if (file->f_mode & s->ena & FMODE_WRITE)
+			val |= PCM_ENABLE_OUTPUT;
+		return put_user(val, (int *) arg);
+
+	case SNDCTL_DSP_SETTRIGGER:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		if (file->f_mode & FMODE_READ) {
+			if (val & PCM_ENABLE_INPUT) {
+				if (!s->dma_adc.ready
+				    && (ret = prog_dmabuf_adc(s)))
+					return ret;
+				start_adc(s);
+			} else
+				stop_adc(s);
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			if (val & PCM_ENABLE_OUTPUT) {
+				if (!s->dma_dac.ready
+				    && (ret = prog_dmabuf_dac(s)))
+					return ret;
+				start_dac(s);
+			} else
+				stop_dac(s);
+		}
+		return 0;
+
+	case SNDCTL_DSP_GETOSPACE:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)))
+			return val;
+		spin_lock_irqsave(&s->lock, flags);
+		cs4281_update_ptr(s,CS_FALSE);
+		abinfo.fragsize = s->dma_dac.fragsize;
+		if (s->dma_dac.mapped)
+			abinfo.bytes = s->dma_dac.dmasize;
+		else
+			abinfo.bytes =
+			    s->dma_dac.dmasize - s->dma_dac.count;
+		abinfo.fragstotal = s->dma_dac.numfrag;
+		abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
+		CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO
+			"cs4281: cs4281_ioctl(): GETOSPACE .fragsize=%d .bytes=%d .fragstotal=%d .fragments=%d\n",
+				abinfo.fragsize,abinfo.bytes,abinfo.fragstotal,
+				abinfo.fragments));
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *) arg, &abinfo,
+				    sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_GETISPACE:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
+			return val;
+		spin_lock_irqsave(&s->lock, flags);
+		cs4281_update_ptr(s,CS_FALSE);
+		if (s->conversion) {
+			abinfo.fragsize = s->dma_adc.fragsize / 2;
+			abinfo.bytes = s->dma_adc.count / 2;
+			abinfo.fragstotal = s->dma_adc.numfrag;
+			abinfo.fragments =
+			    abinfo.bytes >> (s->dma_adc.fragshift - 1);
+		} else {
+			abinfo.fragsize = s->dma_adc.fragsize;
+			abinfo.bytes = s->dma_adc.count;
+			abinfo.fragstotal = s->dma_adc.numfrag;
+			abinfo.fragments =
+			    abinfo.bytes >> s->dma_adc.fragshift;
+		}
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *) arg, &abinfo,
+				    sizeof(abinfo)) ? -EFAULT : 0;
+
+	case SNDCTL_DSP_NONBLOCK:
+		file->f_flags |= O_NONBLOCK;
+		return 0;
+
+	case SNDCTL_DSP_GETODELAY:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		if(!s->dma_dac.ready && prog_dmabuf_dac(s))
+			return 0;
+		spin_lock_irqsave(&s->lock, flags);
+		cs4281_update_ptr(s,CS_FALSE);
+		val = s->dma_dac.count;
+		spin_unlock_irqrestore(&s->lock, flags);
+		return put_user(val, (int *) arg);
+
+	case SNDCTL_DSP_GETIPTR:
+		if (!(file->f_mode & FMODE_READ))
+			return -EINVAL;
+		if(!s->dma_adc.ready && prog_dmabuf_adc(s))
+			return 0;
+		spin_lock_irqsave(&s->lock, flags);
+		cs4281_update_ptr(s,CS_FALSE);
+		cinfo.bytes = s->dma_adc.total_bytes;
+		if (s->dma_adc.mapped) {
+			cinfo.blocks =
+			    (cinfo.bytes >> s->dma_adc.fragshift) -
+			    s->dma_adc.blocks;
+			s->dma_adc.blocks =
+			    cinfo.bytes >> s->dma_adc.fragshift;
+		} else {
+			if (s->conversion) {
+				cinfo.blocks =
+				    s->dma_adc.count /
+				    2 >> (s->dma_adc.fragshift - 1);
+			} else
+				cinfo.blocks =
+				    s->dma_adc.count >> s->dma_adc.
+				    fragshift;
+		}
+		if (s->conversion)
+			cinfo.ptr = s->dma_adc.hwptr / 2;
+		else
+			cinfo.ptr = s->dma_adc.hwptr;
+		if (s->dma_adc.mapped)
+			s->dma_adc.count &= s->dma_adc.fragsize - 1;
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
+
+	case SNDCTL_DSP_GETOPTR:
+		if (!(file->f_mode & FMODE_WRITE))
+			return -EINVAL;
+		if(!s->dma_dac.ready && prog_dmabuf_dac(s))
+			return 0;
+		spin_lock_irqsave(&s->lock, flags);
+		cs4281_update_ptr(s,CS_FALSE);
+		cinfo.bytes = s->dma_dac.total_bytes;
+		if (s->dma_dac.mapped) {
+			cinfo.blocks =
+			    (cinfo.bytes >> s->dma_dac.fragshift) -
+			    s->dma_dac.blocks;
+			s->dma_dac.blocks =
+			    cinfo.bytes >> s->dma_dac.fragshift;
+		} else {
+			cinfo.blocks =
+			    s->dma_dac.count >> s->dma_dac.fragshift;
+		}
+		cinfo.ptr = s->dma_dac.hwptr;
+		if (s->dma_dac.mapped)
+			s->dma_dac.count &= s->dma_dac.fragsize - 1;
+		spin_unlock_irqrestore(&s->lock, flags);
+		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
+
+	case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE) {
+			if ((val = prog_dmabuf_dac(s)))
+				return val;
+			return put_user(s->dma_dac.fragsize, (int *) arg);
+		}
+		if ((val = prog_dmabuf_adc(s)))
+			return val;
+		if (s->conversion)
+			return put_user(s->dma_adc.fragsize / 2,
+					(int *) arg);
+		else
+			return put_user(s->dma_adc.fragsize, (int *) arg);
+
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		return 0;	// Say OK, but do nothing.
+
+	case SNDCTL_DSP_SUBDIVIDE:
+		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision)
+		    || (file->f_mode & FMODE_WRITE
+			&& s->dma_dac.subdivision)) return -EINVAL;
+		if (get_user(val, (int *) arg))
+			return -EFAULT;
+		if (val != 1 && val != 2 && val != 4)
+			return -EINVAL;
+		if (file->f_mode & FMODE_READ)
+			s->dma_adc.subdivision = val;
+		else if (file->f_mode & FMODE_WRITE)
+			s->dma_dac.subdivision = val;
+		return 0;
+
+	case SOUND_PCM_READ_RATE:
+		if (file->f_mode & FMODE_READ)
+			return put_user(s->prop_adc.rate, (int *) arg);
+		else if (file->f_mode & FMODE_WRITE)
+			return put_user(s->prop_dac.rate, (int *) arg);
+
+	case SOUND_PCM_READ_CHANNELS:
+		if (file->f_mode & FMODE_READ)
+			return put_user(s->prop_adc.channels, (int *) arg);
+		else if (file->f_mode & FMODE_WRITE)
+			return put_user(s->prop_dac.channels, (int *) arg);
+
+	case SOUND_PCM_READ_BITS:
+		if (file->f_mode & FMODE_READ)
+			return
+			    put_user(
+				     (s->prop_adc.
+				      fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16,
+				     (int *) arg);
+		else if (file->f_mode & FMODE_WRITE)
+			return
+			    put_user(
+				     (s->prop_dac.
+				      fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16,
+				     (int *) arg);
+
+	case SOUND_PCM_WRITE_FILTER:
+	case SNDCTL_DSP_SETSYNCRO:
+	case SOUND_PCM_READ_FILTER:
+		return -EINVAL;
+	}
+	return mixer_ioctl(s, cmd, arg);
+}
+
+
+static int cs4281_release(struct inode *inode, struct file *file)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+
+	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2, printk(KERN_INFO
+		 "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n",
+			 (unsigned) inode, (unsigned) file, file->f_mode));
+
+	VALIDATE_STATE(s);
+
+	if (file->f_mode & FMODE_WRITE) {
+		drain_dac(s, file->f_flags & O_NONBLOCK);
+		down(&s->open_sem_dac);
+		stop_dac(s);
+		dealloc_dmabuf(s, &s->dma_dac);
+		s->open_mode &= ~FMODE_WRITE;
+		up(&s->open_sem_dac);
+		wake_up(&s->open_wait_dac);
+		MOD_DEC_USE_COUNT;
+	}
+	if (file->f_mode & FMODE_READ) {
+		drain_adc(s, file->f_flags & O_NONBLOCK);
+		down(&s->open_sem_adc);
+		stop_adc(s);
+		dealloc_dmabuf(s, &s->dma_adc);
+		s->open_mode &= ~FMODE_READ;
+		up(&s->open_sem_adc);
+		wake_up(&s->open_wait_adc);
+		MOD_DEC_USE_COUNT;
+	}
+	return 0;
+}
+
+static int cs4281_open(struct inode *inode, struct file *file)
+{
+	int minor = MINOR(inode->i_rdev);
+	struct cs4281_state *s=NULL;
+	struct list_head *entry;
+
+	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
+		"cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n",
+			(unsigned) inode, (unsigned) file, file->f_mode));
+
+	list_for_each(entry, &cs4281_devs)
+	{
+		s = list_entry(entry, struct cs4281_state, list);
+
+		if (!((s->dev_audio ^ minor) & ~0xf))
+			break;
+	}
+	if (entry == &cs4281_devs)
+		return -ENODEV;
+	if (!s) {
+		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
+			"cs4281: cs4281_open(): Error - unable to find audio state struct\n"));
+		return -ENODEV;
+	}
+	VALIDATE_STATE(s);
+	file->private_data = s;
+
+	// wait for device to become free 
+	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) {
+		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2, printk(KERN_INFO
+			 "cs4281: cs4281_open(): Error - must open READ and/or WRITE\n"));
+		return -ENODEV;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		down(&s->open_sem_dac);
+		while (s->open_mode & FMODE_WRITE) {
+			if (file->f_flags & O_NONBLOCK) {
+				up(&s->open_sem_dac);
+				return -EBUSY;
+			}
+			up(&s->open_sem_dac);
+			interruptible_sleep_on(&s->open_wait_dac);
+
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			down(&s->open_sem_dac);
+		}
+	}
+	if (file->f_mode & FMODE_READ) {
+		down(&s->open_sem_adc);
+		while (s->open_mode & FMODE_READ) {
+			if (file->f_flags & O_NONBLOCK) {
+				up(&s->open_sem_adc);
+				return -EBUSY;
+			}
+			up(&s->open_sem_adc);
+			interruptible_sleep_on(&s->open_wait_adc);
+
+			if (signal_pending(current))
+				return -ERESTARTSYS;
+			down(&s->open_sem_adc);
+		}
+	}
+	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+	if (file->f_mode & FMODE_READ) {
+		s->prop_adc.fmt = AFMT_U8;
+		s->prop_adc.fmt_original = s->prop_adc.fmt;
+		s->prop_adc.channels = 1;
+		s->prop_adc.rate = 8000;
+		s->prop_adc.clkdiv = 96 | 0x80;
+		s->conversion = 0;
+		s->ena &= ~FMODE_READ;
+		s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags =
+		    s->dma_adc.subdivision = 0;
+		up(&s->open_sem_adc);
+		MOD_INC_USE_COUNT;
+
+		if (prog_dmabuf_adc(s)) {
+			CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR
+				"cs4281: adc Program dmabufs failed.\n"));
+			cs4281_release(inode, file);
+			return -ENOMEM;
+		}
+		prog_codec(s, CS_TYPE_ADC);
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		s->prop_dac.fmt = AFMT_U8;
+		s->prop_dac.fmt_original = s->prop_dac.fmt;
+		s->prop_dac.channels = 1;
+		s->prop_dac.rate = 8000;
+		s->prop_dac.clkdiv = 96 | 0x80;
+		s->conversion = 0;
+		s->ena &= ~FMODE_WRITE;
+		s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags =
+		    s->dma_dac.subdivision = 0;
+		up(&s->open_sem_dac);
+		MOD_INC_USE_COUNT;
+
+		if (prog_dmabuf_dac(s)) {
+			CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR
+				"cs4281: dac Program dmabufs failed.\n"));
+			cs4281_release(inode, file);
+			return -ENOMEM;
+		}
+		prog_codec(s, CS_TYPE_DAC);
+	}
+	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2,
+		  printk(KERN_INFO "cs4281: cs4281_open()- 0\n"));
+	return 0;
+}
+
+
+// ******************************************************************************************
+//   Wave (audio) file operations struct.
+// ******************************************************************************************
+static /*const */ struct file_operations cs4281_audio_fops = {
+	llseek:cs4281_llseek,
+	read:cs4281_read,
+	write:cs4281_write,
+	poll:cs4281_poll,
+	ioctl:cs4281_ioctl,
+	mmap:cs4281_mmap,
+	open:cs4281_open,
+	release:cs4281_release,
+};
+
+// --------------------------------------------------------------------- 
+
+// hold spinlock for the following! 
+static void cs4281_handle_midi(struct cs4281_state *s)
+{
+	unsigned char ch;
+	int wake;
+	unsigned temp1;
+
+	wake = 0;
+	while (!(readl(s->pBA0 + BA0_MIDSR) & 0x80)) {
+		ch = readl(s->pBA0 + BA0_MIDRP);
+		if (s->midi.icnt < MIDIINBUF) {
+			s->midi.ibuf[s->midi.iwr] = ch;
+			s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
+			s->midi.icnt++;
+		}
+		wake = 1;
+	}
+	if (wake)
+		wake_up(&s->midi.iwait);
+	wake = 0;
+	while (!(readl(s->pBA0 + BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) {
+		temp1 = (s->midi.obuf[s->midi.ord]) & 0x000000ff;
+		writel(temp1, s->pBA0 + BA0_MIDWP);
+		s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
+		s->midi.ocnt--;
+		if (s->midi.ocnt < MIDIOUTBUF - 16)
+			wake = 1;
+	}
+	if (wake)
+		wake_up(&s->midi.owait);
+}
+
+
+
+static void cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	struct cs4281_state *s = (struct cs4281_state *) dev_id;
+	unsigned int temp1;
+
+	// fastpath out, to ease interrupt sharing 
+	temp1 = readl(s->pBA0 + BA0_HISR);	// Get Int Status reg.
+
+	CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO
+		  "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n", temp1));
+/*
+* If not DMA or MIDI interrupt, then just return.
+*/
+	if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {
+		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);
+		CS_DBGOUT(CS_INTERRUPT, 9, printk(KERN_INFO
+			"cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n"));
+		return;
+	}
+
+	if (temp1 & HISR_DMA0)	// If play interrupt,
+		readl(s->pBA0 + BA0_HDSR0);	//   clear the source.
+
+	if (temp1 & HISR_DMA1)	// Same for play.
+		readl(s->pBA0 + BA0_HDSR1);
+	writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Local EOI
+
+	spin_lock(&s->lock);
+	cs4281_update_ptr(s,CS_TRUE);
+	cs4281_handle_midi(s);
+	spin_unlock(&s->lock);
+}
+
+// **************************************************************************
+
+static void cs4281_midi_timer(unsigned long data)
+{
+	struct cs4281_state *s = (struct cs4281_state *) data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&s->lock, flags);
+	cs4281_handle_midi(s);
+	spin_unlock_irqrestore(&s->lock, flags);
+	s->midi.timer.expires = jiffies + 1;
+	add_timer(&s->midi.timer);
+}
+
+
+// --------------------------------------------------------------------- 
+
+static ssize_t cs4281_midi_read(struct file *file, char *buffer,
+				size_t count, loff_t * ppos)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned ptr;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (!access_ok(VERIFY_WRITE, buffer, count))
+		return -EFAULT;
+	ret = 0;
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		ptr = s->midi.ird;
+		cnt = MIDIINBUF - ptr;
+		if (s->midi.icnt < cnt)
+			cnt = s->midi.icnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+			interruptible_sleep_on(&s->midi.iwait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
+			return ret ? ret : -EFAULT;
+		ptr = (ptr + cnt) % MIDIINBUF;
+		spin_lock_irqsave(&s->lock, flags);
+		s->midi.ird = ptr;
+		s->midi.icnt -= cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+	}
+	return ret;
+}
+
+
+static ssize_t cs4281_midi_write(struct file *file, const char *buffer,
+				 size_t count, loff_t * ppos)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	ssize_t ret;
+	unsigned long flags;
+	unsigned ptr;
+	int cnt;
+
+	VALIDATE_STATE(s);
+	if (ppos != &file->f_pos)
+		return -ESPIPE;
+	if (!access_ok(VERIFY_READ, buffer, count))
+		return -EFAULT;
+	ret = 0;
+	while (count > 0) {
+		spin_lock_irqsave(&s->lock, flags);
+		ptr = s->midi.owr;
+		cnt = MIDIOUTBUF - ptr;
+		if (s->midi.ocnt + cnt > MIDIOUTBUF)
+			cnt = MIDIOUTBUF - s->midi.ocnt;
+		if (cnt <= 0)
+			cs4281_handle_midi(s);
+		spin_unlock_irqrestore(&s->lock, flags);
+		if (cnt > count)
+			cnt = count;
+		if (cnt <= 0) {
+			if (file->f_flags & O_NONBLOCK)
+				return ret ? ret : -EAGAIN;
+			interruptible_sleep_on(&s->midi.owait);
+			if (signal_pending(current))
+				return ret ? ret : -ERESTARTSYS;
+			continue;
+		}
+		if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
+			return ret ? ret : -EFAULT;
+		ptr = (ptr + cnt) % MIDIOUTBUF;
+		spin_lock_irqsave(&s->lock, flags);
+		s->midi.owr = ptr;
+		s->midi.ocnt += cnt;
+		spin_unlock_irqrestore(&s->lock, flags);
+		count -= cnt;
+		buffer += cnt;
+		ret += cnt;
+		spin_lock_irqsave(&s->lock, flags);
+		cs4281_handle_midi(s);
+		spin_unlock_irqrestore(&s->lock, flags);
+	}
+	return ret;
+}
+
+
+static unsigned int cs4281_midi_poll(struct file *file,
+				     struct poll_table_struct *wait)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	unsigned long flags;
+	unsigned int mask = 0;
+
+	VALIDATE_STATE(s);
+	if (file->f_flags & FMODE_WRITE)
+		poll_wait(file, &s->midi.owait, wait);
+	if (file->f_flags & FMODE_READ)
+		poll_wait(file, &s->midi.iwait, wait);
+	spin_lock_irqsave(&s->lock, flags);
+	if (file->f_flags & FMODE_READ) {
+		if (s->midi.icnt > 0)
+			mask |= POLLIN | POLLRDNORM;
+	}
+	if (file->f_flags & FMODE_WRITE) {
+		if (s->midi.ocnt < MIDIOUTBUF)
+			mask |= POLLOUT | POLLWRNORM;
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	return mask;
+}
+
+
+static int cs4281_midi_open(struct inode *inode, struct file *file)
+{
+	unsigned long flags, temp1;
+	int minor = MINOR(inode->i_rdev);
+	struct cs4281_state *s=NULL;
+	struct list_head *entry;
+	list_for_each(entry, &cs4281_devs)
+	{
+		s = list_entry(entry, struct cs4281_state, list);
+
+		if (s->dev_midi == minor)
+			break;
+	}
+
+	if (entry == &cs4281_devs)
+		return -ENODEV;
+	if (!s)
+	{
+		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
+			"cs4281: cs4281_open(): Error - unable to find audio state struct\n"));
+		return -ENODEV;
+	}
+	VALIDATE_STATE(s);
+	file->private_data = s;
+	// wait for device to become free 
+	down(&s->open_sem);
+	while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
+		if (file->f_flags & O_NONBLOCK) {
+			up(&s->open_sem);
+			return -EBUSY;
+		}
+		up(&s->open_sem);
+		interruptible_sleep_on(&s->open_wait);
+		if (signal_pending(current))
+			return -ERESTARTSYS;
+		down(&s->open_sem);
+	}
+	spin_lock_irqsave(&s->lock, flags);
+	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+		writel(1, s->pBA0 + BA0_MIDCR);	// Reset the interface.
+		writel(0, s->pBA0 + BA0_MIDCR);	// Return to normal mode.
+		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+		writel(0x0000000f, s->pBA0 + BA0_MIDCR);	// Enable transmit, record, ints.
+		temp1 = readl(s->pBA0 + BA0_HIMR);
+		writel(temp1 & 0xffbfffff, s->pBA0 + BA0_HIMR);	// Enable midi int. recognition.
+		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts
+		init_timer(&s->midi.timer);
+		s->midi.timer.expires = jiffies + 1;
+		s->midi.timer.data = (unsigned long) s;
+		s->midi.timer.function = cs4281_midi_timer;
+		add_timer(&s->midi.timer);
+	}
+	if (file->f_mode & FMODE_READ) {
+		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
+	}
+	if (file->f_mode & FMODE_WRITE) {
+		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	s->open_mode |=
+	    (file->
+	     f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ |
+					    FMODE_MIDI_WRITE);
+	up(&s->open_sem);
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+
+static int cs4281_midi_release(struct inode *inode, struct file *file)
+{
+	struct cs4281_state *s =
+	    (struct cs4281_state *) file->private_data;
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long flags;
+	unsigned count, tmo;
+
+	VALIDATE_STATE(s);
+
+	if (file->f_mode & FMODE_WRITE) {
+		add_wait_queue(&s->midi.owait, &wait);
+		for (;;) {
+			set_current_state(TASK_INTERRUPTIBLE);
+			spin_lock_irqsave(&s->lock, flags);
+			count = s->midi.ocnt;
+			spin_unlock_irqrestore(&s->lock, flags);
+			if (count <= 0)
+				break;
+			if (signal_pending(current))
+				break;
+			if (file->f_flags & O_NONBLOCK) {
+				remove_wait_queue(&s->midi.owait, &wait);
+				current->state = TASK_RUNNING;
+				return -EBUSY;
+			}
+			tmo = (count * HZ) / 3100;
+			if (!schedule_timeout(tmo ? : 1) && tmo)
+				printk(KERN_DEBUG
+				       "cs4281: midi timed out??\n");
+		}
+		remove_wait_queue(&s->midi.owait, &wait);
+		current->state = TASK_RUNNING;
+	}
+	down(&s->open_sem);
+	s->open_mode &=
+	    (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ |
+						     FMODE_MIDI_WRITE);
+	spin_lock_irqsave(&s->lock, flags);
+	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
+		writel(0, s->pBA0 + BA0_MIDCR);	// Disable Midi interrupts.  
+		del_timer(&s->midi.timer);
+	}
+	spin_unlock_irqrestore(&s->lock, flags);
+	up(&s->open_sem);
+	wake_up(&s->open_wait);
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+// ******************************************************************************************
+//   Midi file operations struct.
+// ******************************************************************************************
+static /*const */ struct file_operations cs4281_midi_fops = {
+	llseek:cs4281_llseek,
+	read:cs4281_midi_read,
+	write:cs4281_midi_write,
+	poll:cs4281_midi_poll,
+	open:cs4281_midi_open,
+	release:cs4281_midi_release,
+};
+
+
+// --------------------------------------------------------------------- 
+
+// maximum number of devices 
+#define NR_DEVICE 8		// Only eight devices supported currently.
+
+// --------------------------------------------------------------------- 
+
+static struct initvol {
+	int mixch;
+	int vol;
+} initvol[] __initdata = {
+
+	{
+	SOUND_MIXER_WRITE_VOLUME, 0x4040}, {
+	SOUND_MIXER_WRITE_PCM, 0x4040}, {
+	SOUND_MIXER_WRITE_SYNTH, 0x4040}, {
+	SOUND_MIXER_WRITE_CD, 0x4040}, {
+	SOUND_MIXER_WRITE_LINE, 0x4040}, {
+	SOUND_MIXER_WRITE_LINE1, 0x4040}, {
+	SOUND_MIXER_WRITE_RECLEV, 0x0000}, {
+	SOUND_MIXER_WRITE_SPEAKER, 0x4040}, {
+	SOUND_MIXER_WRITE_MIC, 0x0000}
+};
+
+
+#ifndef NOT_CS4281_PM
+void __devinit cs4281_BuildFIFO(
+	struct cs4281_pipeline *p, 
+	struct cs4281_state *s)
+{
+	switch(p->number)
+	{
+		case 0:  /* playback */
+		{
+			p->u32FCRnAddress  =  BA0_FCR0;
+			p->u32FSICnAddress = BA0_FSIC0;
+			p->u32FPDRnAddress = BA0_FPDR0;
+			break;
+		}
+		case 1:  /* capture */
+		{
+			p->u32FCRnAddress  =  BA0_FCR1;
+			p->u32FSICnAddress = BA0_FSIC1;
+			p->u32FPDRnAddress = BA0_FPDR1;
+			break;
+		}
+
+		case 2: 
+		{
+			p->u32FCRnAddress  =  BA0_FCR2;
+			p->u32FSICnAddress = BA0_FSIC2;
+			p->u32FPDRnAddress = BA0_FPDR2;
+			break;
+		}
+		case 3: 
+		{
+			p->u32FCRnAddress  =  BA0_FCR3;
+			p->u32FSICnAddress = BA0_FSIC3;
+			p->u32FPDRnAddress = BA0_FPDR3;
+			break;
+		}
+		default:
+			break;
+	}
+	//
+	// first read the hardware to initialize the member variables
+	//
+	p->u32FCRnValue = readl(s->pBA0 + p->u32FCRnAddress);
+	p->u32FSICnValue = readl(s->pBA0 + p->u32FSICnAddress);
+	p->u32FPDRnValue = readl(s->pBA0 + p->u32FPDRnAddress);
+
+}
+
+void __devinit cs4281_BuildDMAengine(
+	struct cs4281_pipeline *p, 
+	struct cs4281_state *s)
+{
+/*
+* initialize all the addresses of this pipeline dma info.
+*/
+	switch(p->number)
+	{
+		case 0:  /* playback */
+		{
+			p->u32DBAnAddress = BA0_DBA0;
+			p->u32DCAnAddress = BA0_DCA0;
+			p->u32DBCnAddress = BA0_DBC0;
+			p->u32DCCnAddress = BA0_DCC0;
+			p->u32DMRnAddress = BA0_DMR0;
+			p->u32DCRnAddress = BA0_DCR0;
+			p->u32HDSRnAddress = BA0_HDSR0;
+			break;
+		}
+
+		case 1: /* capture */
+		{
+			p->u32DBAnAddress = BA0_DBA1;
+			p->u32DCAnAddress = BA0_DCA1;
+			p->u32DBCnAddress = BA0_DBC1;
+			p->u32DCCnAddress = BA0_DCC1;
+			p->u32DMRnAddress = BA0_DMR1;
+			p->u32DCRnAddress = BA0_DCR1;
+			p->u32HDSRnAddress = BA0_HDSR1;
+			break;
+		}
+
+		case 2:
+		{
+			p->u32DBAnAddress = BA0_DBA2;
+			p->u32DCAnAddress = BA0_DCA2;
+			p->u32DBCnAddress = BA0_DBC2;
+			p->u32DCCnAddress = BA0_DCC2;
+			p->u32DMRnAddress = BA0_DMR2;
+			p->u32DCRnAddress = BA0_DCR2;
+			p->u32HDSRnAddress = BA0_HDSR2;
+			break;
+		}
+
+		case 3:
+		{
+			p->u32DBAnAddress = BA0_DBA3;
+			p->u32DCAnAddress = BA0_DCA3;
+			p->u32DBCnAddress = BA0_DBC3;
+			p->u32DCCnAddress = BA0_DCC3;
+			p->u32DMRnAddress = BA0_DMR3;
+			p->u32DCRnAddress = BA0_DCR3;
+			p->u32HDSRnAddress = BA0_HDSR3;
+			break;
+		}
+		default:
+			break;
+	}
+
+//
+// Initialize the dma values for this pipeline
+//
+	p->u32DBAnValue = readl(s->pBA0 + p->u32DBAnAddress);
+	p->u32DBCnValue = readl(s->pBA0 + p->u32DBCnAddress);
+	p->u32DMRnValue = readl(s->pBA0 + p->u32DMRnAddress);
+	p->u32DCRnValue = readl(s->pBA0 + p->u32DCRnAddress);
+
+}
+
+void __devinit cs4281_InitPM(struct cs4281_state *s)
+{
+	int i;
+	struct cs4281_pipeline *p;
+
+	for(i=0;i<CS4281_NUMBER_OF_PIPELINES;i++)
+	{
+		p = &s->pl[i];
+		p->number = i;
+		cs4281_BuildDMAengine(p,s);
+		cs4281_BuildFIFO(p,s);
+	/*
+	* currently only  2 pipelines are used
+	* so, only set the valid bit on the playback and capture.
+	*/
+		if( (i == CS4281_PLAYBACK_PIPELINE_NUMBER) || 
+			(i == CS4281_CAPTURE_PIPELINE_NUMBER))
+			p->flags |= CS4281_PIPELINE_VALID;
+	}
+	s->pm.u32SSPM_BITS = 0x7e;  /* rev c, use 0x7c for rev a or b */
+}
+#endif
+
+static int __devinit cs4281_probe(struct pci_dev *pcidev,
+				  const struct pci_device_id *pciid)
+{
+#ifndef NOT_CS4281_PM
+	struct pm_dev *pmdev;
+#endif
+	struct cs4281_state *s;
+	dma_addr_t dma_mask;
+	mm_segment_t fs;
+	int i, val;
+	unsigned int temp1, temp2;
+
+	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
+		  printk(KERN_INFO "cs4281: probe()+\n"));
+
+	if (!RSRCISMEMORYREGION(pcidev, 0) ||
+	    !RSRCISMEMORYREGION(pcidev, 1)) {
+		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+			 "cs4281: probe()- Memory region not assigned\n"));
+		return -1;
+	}
+	if (pcidev->irq == 0) {
+		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+			 "cs4281: probe() IRQ not assigned\n"));
+		return -1;
+	}
+	if (!pci_dma_supported(pcidev, 0xffffffff)) {
+		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+		      "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n"));
+		return -1;
+	}
+	dma_mask = 0xffffffff;	/* this enables playback and recording */
+	if (!(s = kmalloc(sizeof(struct cs4281_state), GFP_KERNEL))) {
+		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
+		      "cs4281: probe() no memory for state struct.\n"));
+		return -1;
+	}
+	memset(s, 0, sizeof(struct cs4281_state));
+	init_waitqueue_head(&s->dma_adc.wait);
+	init_waitqueue_head(&s->dma_dac.wait);
+	init_waitqueue_head(&s->open_wait);
+	init_waitqueue_head(&s->open_wait_adc);
+	init_waitqueue_head(&s->open_wait_dac);
+	init_waitqueue_head(&s->midi.iwait);
+	init_waitqueue_head(&s->midi.owait);
+	init_MUTEX(&s->open_sem);
+	init_MUTEX(&s->open_sem_adc);
+	init_MUTEX(&s->open_sem_dac);
+	spin_lock_init(&s->lock);
+	s->pBA0phys = RSRCADDRESS(pcidev, 0);
+	s->pBA1phys = RSRCADDRESS(pcidev, 1);
+
+	/* Convert phys to linear. */
+	s->pBA0 = ioremap_nocache(s->pBA0phys, 4096);
+	if (!s->pBA0) {
+		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_ERR
+			 "cs4281: BA0 I/O mapping failed. Skipping part.\n"));
+		goto err_free;
+	}
+	s->pBA1 = ioremap_nocache(s->pBA1phys, 65536);
+	if (!s->pBA1) {
+		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_ERR
+			 "cs4281: BA1 I/O mapping failed. Skipping part.\n"));
+		goto err_unmap;
+	}
+
+	temp1 = readl(s->pBA0 + BA0_PCICFG00);
+	temp2 = readl(s->pBA0 + BA0_PCICFG04);
+
+	CS_DBGOUT(CS_INIT, 2,
+		  printk(KERN_INFO
+			 "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n",
+			 (unsigned) temp1, (unsigned) temp2,
+			 (unsigned) s->pBA0, (unsigned) s->pBA1));
+
+	CS_DBGOUT(CS_INIT, 2,
+		  printk(KERN_INFO
+			 "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n",
+			 (unsigned) s->pBA0phys, (unsigned) s->pBA1phys));
+
+#ifndef NOT_CS4281_PM
+	s->pm.flags = CS4281_PM_IDLE;
+#endif
+	temp1 = cs4281_hw_init(s);
+	if (temp1) {
+		CS_DBGOUT(CS_ERROR | CS_INIT, 1, printk(KERN_ERR
+			 "cs4281: cs4281_hw_init() failed. Skipping part.\n"));
+		goto err_irq;
+	}
+	s->magic = CS4281_MAGIC;
+	s->pcidev = pcidev;
+	s->irq = pcidev->irq;
+	if (pci_enable_device(pcidev)) {
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
+			 "cs4281: pci_enable_device() failed\n"));
+		goto err_irq;
+	}
+	if (request_irq
+	    (s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)) {
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
+			  printk(KERN_ERR "cs4281: irq %u in use\n", s->irq));
+		goto err_irq;
+	}
+	if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) <
+	    0) {
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
+			 "cs4281: probe() register_sound_dsp() failed.\n"));
+		goto err_dev1;
+	}
+	if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) <
+	    0) {
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
+			 "cs4281: probe() register_sound_mixer() failed.\n"));
+		goto err_dev2;
+	}
+	if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0) {
+		CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_ERR
+			 "cs4281: probe() register_sound_midi() failed.\n"));
+		goto err_dev3;
+	}
+#ifndef NOT_CS4281_PM
+	cs4281_InitPM(s);
+	pmdev = cs_pm_register(PM_PCI_DEV, PM_PCI_ID(pcidev), cs4281_pm_callback);
+	if (pmdev)
+	{
+		CS_DBGOUT(CS_INIT | CS_PM, 4, printk(KERN_INFO
+			 "cs4281: probe() pm_register() succeeded (0x%x).\n",
+				(unsigned)pmdev));
+		pmdev->data = s;
+	}
+	else
+	{
+		CS_DBGOUT(CS_INIT | CS_PM | CS_ERROR, 0, printk(KERN_INFO
+			 "cs4281: probe() pm_register() failed (0x%x).\n",
+				(unsigned)pmdev));
+		s->pm.flags |= CS4281_PM_NOT_REGISTERED;
+	}
+#endif
+
+	pci_set_master(pcidev);	// enable bus mastering 
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	val = SOUND_MASK_LINE;
+	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
+	for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) {
+		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);
+
+	PCI_SET_DRIVER_DATA(pcidev, s);
+	PCI_SET_DMA_MASK(pcidev, dma_mask);
+	list_add(&s->list, &cs4281_devs);
+	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
+		"cs4281: probe()- device allocated successfully\n"));
+	return 0;
+
+      err_dev3:
+	unregister_sound_mixer(s->dev_mixer);
+      err_dev2:
+	unregister_sound_dsp(s->dev_audio);
+      err_dev1:
+	free_irq(s->irq, s);
+      err_irq:
+	iounmap(s->pBA1);
+      err_unmap:
+	iounmap(s->pBA0);
+      err_free:
+	kfree(s);
+
+	CS_DBGOUT(CS_INIT | CS_ERROR, 1, printk(KERN_INFO
+		"cs4281: probe()- no device allocated\n"));
+	return -ENODEV;
+} // probe_cs4281
+
+
+// --------------------------------------------------------------------- 
+
+static void __devinit cs4281_remove(struct pci_dev *pci_dev)
+{
+	struct cs4281_state *s = PCI_GET_DRIVER_DATA(pci_dev);
+	// stop DMA controller 
+	synchronize_irq();
+	free_irq(s->irq, s);
+	unregister_sound_dsp(s->dev_audio);
+	unregister_sound_mixer(s->dev_mixer);
+	unregister_sound_midi(s->dev_midi);
+	iounmap(s->pBA1);
+	iounmap(s->pBA0);
+	kfree(s);
+	PCI_SET_DRIVER_DATA(pci_dev,NULL);
+	list_del(&s->list);
+	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
+		 "cs4281: cs4281_remove()-: remove successful\n"));
+}
+
+static struct pci_device_id cs4281_pci_tbl[] __devinitdata = {
+	{PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281,
+	 PCI_ANY_ID, PCI_ANY_ID, 0, 0},
+	{0,}
+};
+
+MODULE_DEVICE_TABLE(pci, cs4281_pci_tbl);
+
+struct pci_driver cs4281_pci_driver = {
+	name:"cs4281",
+	id_table:cs4281_pci_tbl,
+	probe:cs4281_probe,
+	remove:cs4281_remove,
+	suspend:CS4281_SUSPEND_TBL,
+	resume:CS4281_RESUME_TBL,
+};
+
+int __init cs4281_init_module(void)
+{
+	int rtn = 0;
+	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO 
+		"cs4281: cs4281_init_module()+ \n"));
+	if (!pci_present()) {	/* No PCI bus in this machine! */
+		CS_DBGOUT(CS_INIT | CS_FUNCTION, 2, printk(KERN_INFO
+			"cs4281: cs4281_init_module()- no pci bus found\n"));
+		return -ENODEV;
+	}
+	printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " "
+	       __DATE__ "\n", CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION,
+	       CS4281_ARCH);
+	rtn = pci_module_init(&cs4281_pci_driver);
+
+	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: cs4281_init_module()- (%d)\n",rtn));
+	return rtn;
+}
+
+void __exit cs4281_cleanup_module(void)
+{
+	pci_unregister_driver(&cs4281_pci_driver);
+#ifndef NOT_CS4281_PM
+	cs_pm_unregister_all(cs4281_pm_callback);
+#endif
+	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
+		  printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n"));
+}
+// --------------------------------------------------------------------- 
+
+MODULE_AUTHOR("gw boynton, audio@crystal.cirrus.com");
+MODULE_DESCRIPTION("Cirrus Logic CS4281 Driver");
+
+// --------------------------------------------------------------------- 
+
+module_init(cs4281_init_module);
+module_exit(cs4281_cleanup_module);
+
+#ifndef MODULE
+int __init init_cs4281(void)
+{
+	return cs4281_init_module();
+}
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281/cs4281pm-24.c linux/drivers/sound/cs4281/cs4281pm-24.c
--- v2.4.1/linux/drivers/sound/cs4281/cs4281pm-24.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281pm-24.c	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,84 @@
+/*******************************************************************************
+*
+*      "cs4281pm.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*
+*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
+*            -- tom woller (twoller@crystal.cirrus.com) or
+*               (audio@crystal.cirrus.com).
+*
+*      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.
+*
+* 12/22/00 trw - new file. 
+*
+*******************************************************************************/
+
+#ifndef NOT_CS4281_PM
+#include <linux/pm.h>
+
+#define cs_pm_register(a, b, c) pm_register((a), (b), (c));
+#define cs_pm_unregister_all(a) pm_unregister_all((a));
+
+int cs4281_suspend(struct cs4281_state *s);
+int cs4281_resume(struct cs4281_state *s);
+/* 
+* for now (12/22/00) only enable the pm_register PM support.
+* allow these table entries to be null.
+#define CS4281_SUSPEND_TBL cs4281_suspend_tbl
+#define CS4281_RESUME_TBL cs4281_resume_tbl
+*/
+#define CS4281_SUSPEND_TBL cs4281_null
+#define CS4281_RESUME_TBL cs4281_null
+
+int cs4281_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *data)
+{
+	struct cs4281_state *state;
+
+	CS_DBGOUT(CS_PM, 2, printk(KERN_INFO 
+		"cs4281: cs4281_pm_callback dev=0x%x rqst=0x%x state=%d\n",
+			(unsigned)dev,(unsigned)rqst,(unsigned)data));
+	state = (struct cs4281_state *) dev->data;
+	if (state) {
+		switch(rqst) {
+			case PM_SUSPEND:
+				CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
+					"cs4281: PM suspend request\n"));
+				if(cs4281_suspend(state))
+				{
+				    CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
+					"cs4281: PM suspend request refused\n"));
+					return 1; 
+				}
+				break;
+			case PM_RESUME:
+				CS_DBGOUT(CS_PM, 2, printk(KERN_INFO
+					"cs4281: PM resume request\n"));
+				if(cs4281_resume(state))
+				{
+				    CS_DBGOUT(CS_ERROR, 2, printk(KERN_INFO
+					"cs4281: PM resume request refused\n"));
+					return 1;
+				}
+				break;
+		}
+	}
+
+	return 0;
+}
+
+#else /* CS4281_PM */
+#define CS4281_SUSPEND_TBL cs4281_null
+#define CS4281_RESUME_TBL cs4281_null
+#endif /* CS4281_PM */
+
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281/cs4281pm.h linux/drivers/sound/cs4281/cs4281pm.h
--- v2.4.1/linux/drivers/sound/cs4281/cs4281pm.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/cs4281/cs4281pm.h	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,74 @@
+#ifndef NOT_CS4281_PM
+/*******************************************************************************
+*
+*      "cs4281pm.h" --  Cirrus Logic-Crystal CS4281 linux audio driver.
+*
+*      Copyright (C) 2000,2001  Cirrus Logic Corp.  
+*            -- tom woller (twoller@crystal.cirrus.com) or
+*               (audio@crystal.cirrus.com).
+*
+*      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.
+*
+* 12/22/00 trw - new file. 
+*
+*******************************************************************************/
+/* general pm definitions */
+#define CS4281_AC97_HIGHESTREGTORESTORE 0x26
+#define CS4281_AC97_NUMBER_RESTORE_REGS (CS4281_AC97_HIGHESTREGTORESTORE/2-1)
+
+/* pipeline definitions */
+#define CS4281_NUMBER_OF_PIPELINES 	4
+#define CS4281_PIPELINE_VALID 		0x0001
+#define CS4281_PLAYBACK_PIPELINE_NUMBER	0x0000
+#define CS4281_CAPTURE_PIPELINE_NUMBER 	0x0001
+
+/* PM state defintions */
+#define CS4281_PM_NOT_REGISTERED	0x1000
+#define CS4281_PM_IDLE			0x0001
+#define CS4281_PM_SUSPENDING		0x0002
+#define CS4281_PM_SUSPENDED		0x0004
+#define CS4281_PM_RESUMING		0x0008
+#define CS4281_PM_RESUMED		0x0010
+
+struct cs4281_pm {
+	unsigned long flags;
+	u32 u32CLKCR1_SAVE,u32SSPMValue,u32PPLVCvalue,u32PPRVCvalue;
+	u32 u32FMLVCvalue,u32FMRVCvalue,u32GPIORvalue,u32JSCTLvalue,u32SSCR;
+	u32 u32SRCSA,u32DacASR,u32AdcASR,u32DacSR,u32AdcSR,u32MIDCR_Save;
+	u32 u32SSPM_BITS;
+	u32 ac97[CS4281_AC97_NUMBER_RESTORE_REGS];
+	u32 u32AC97_master_volume, u32AC97_headphone_volume, u32AC97_master_volume_mono;
+	u32 u32AC97_pcm_out_volume, u32AC97_powerdown, u32AC97_general_purpose;
+	u32 u32hwptr_playback,u32hwptr_capture;
+};
+
+struct cs4281_pipeline {
+	unsigned flags;
+	unsigned number;
+	u32 u32DBAnValue,u32DBCnValue,u32DMRnValue,u32DCRnValue;
+	u32 u32DBAnAddress,u32DCAnAddress,u32DBCnAddress,u32DCCnAddress;
+	u32 u32DMRnAddress,u32DCRnAddress,u32HDSRnAddress;
+	u32 u32DBAn_Save,u32DBCn_Save,u32DMRn_Save,u32DCRn_Save;
+	u32 u32DCCn_Save,u32DCAn_Save;
+/* 
+* technically, these are fifo variables, but just map the 
+* first fifo with the first pipeline and then use the fifo
+* variables inside of the pipeline struct.
+*/
+	u32 u32FCRn_Save,u32FSICn_Save;
+	u32 u32FCRnValue,u32FCRnAddress,u32FSICnValue,u32FSICnAddress;
+	u32 u32FPDRnValue,u32FPDRnAddress;
+};
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281.c linux/drivers/sound/cs4281.c
--- v2.4.1/linux/drivers/sound/cs4281.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/cs4281.c	Wed Dec 31 16:00:00 1969
@@ -1,3799 +0,0 @@
-//*****************************************************************************
-//
-//      "cs4281.c" --  Cirrus Logic-Crystal CS4281 linux audio driver.
-//
-//      Copyright (C) 2000  Cirrus Logic Corp.  
-//            -- adapted from drivers by Thomas Sailer, 
-//            -- but don't bug him; Problems should go to:
-//            -- gw boynton (wesb@crystal.cirrus.com) or
-//            -- tom woller (twoller@crystal.cirrus.com).
-//
-//      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.
-//
-// Module command line parameters:
-//   none
-//
-//  Supported devices:
-//  /dev/dsp    standard /dev/dsp device, (mostly) OSS compatible
-//  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible
-//  /dev/midi   simple MIDI UART interface, no ioctl
-//
-// Modification History
-// 08/20/00 trw - silence and no stopping DAC until release
-// 08/23/00 trw - added CS_DBG statements, fix interrupt hang issue on DAC stop.
-// 09/18/00 trw - added 16bit only record with conversion 
-// 09/24/00 trw - added Enhanced Full duplex (separate simultaneous 
-//                capture/playback rates)
-// 10/03/00 trw - fixed mmap (fixed GRECORD and the XMMS mmap test plugin  
-//                libOSSm.so)
-// 10/11/00 trw - modified for 2.4.0-test9 kernel enhancements (NR_MAP removal)
-// 11/03/00 trw - fixed interrupt loss/stutter, added debug.
-// 11/10/00 bkz - added __devinit to cs4281_hw_init()
-//
-// *****************************************************************************
-
-#include <linux/config.h>
-#include <linux/version.h>
-#include <linux/module.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/sound.h>
-#include <linux/malloc.h>
-#include <linux/soundcard.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-#include <asm/dma.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/smp_lock.h>
-#include <linux/wrapper.h>
-#include <asm/uaccess.h>
-#include <asm/hardirq.h>
-//#include <linux/vmalloc.h>
-#include "dm.h"
-#include "cs4281_hwdefs.h"
-
-EXPORT_NO_SYMBOLS;
-
-#undef OSS_DOCUMENTED_MIXER_SEMANTICS
-
-// --------------------------------------------------------------------- 
-
-#ifndef PCI_VENDOR_ID_CIRRUS
-#define PCI_VENDOR_ID_CIRRUS          0x1013
-#endif
-#ifndef PCI_DEVICE_ID_CRYSTAL_CS4281
-#define PCI_DEVICE_ID_CRYSTAL_CS4281  0x6005
-#endif
-
-#define CS4281_MAGIC  ((PCI_DEVICE_ID_CRYSTAL_CS4281<<16) | PCI_VENDOR_ID_CIRRUS)
-
-// Turn on/off debugging compilation by using 1/0 respectively for CSDEBUG
-//
-#define CSDEBUG_INTERFACE 1
-#define CSDEBUG 1
-//
-// CSDEBUG is usual mode is set to 1, then use the
-// cs_debuglevel and cs_debugmask to turn on or off debugging.
-// Debug level of 1 has been defined to be kernel errors and info
-// that should be printed on any released driver.
-//
-#if CSDEBUG
-extern unsigned long cs_debugmask;
-extern unsigned long cs_debuglevel;
-#define CS_DBGOUT(mask,level,x) if((cs_debuglevel >= (level)) && ((mask) & cs_debugmask) ) {x;}
-#else
-#define CS_DBGOUT(mask,level,x)
-#endif
-//
-// cs_debugmask areas
-//
-#define CS_INIT	 	0x00000001	// initialization and probe functions
-#define CS_ERROR 	0x00000002	// tmp debugging bit placeholder
-#define CS_INTERRUPT	0x00000004	// interrupt handler (separate from all other)
-#define CS_FUNCTION 	0x00000008	// enter/leave functions
-#define CS_WAVE_WRITE 	0x00000010	// write information for wave
-#define CS_WAVE_READ 	0x00000020	// read information for wave
-#define CS_MIDI_WRITE 	0x00000040	// write information for midi
-#define CS_MIDI_READ 	0x00000080	// read information for midi
-#define CS_MPU401_WRITE 0x00000100	// write information for mpu401
-#define CS_MPU401_READ 	0x00000200	// read information for mpu401
-#define CS_OPEN		0x00000400	// all open functions in the driver
-#define CS_RELEASE	0x00000800	// all release functions in the driver
-#define CS_PARMS	0x00001000	// functional and operational parameters
-#define CS_IOCTL	0x00002000	// ioctl (non-mixer)
-#define CS_TMP		0x10000000	// tmp debug mask bit
-
-#if CSDEBUG
-static unsigned long cs_debuglevel = 1;	// levels range from 1-9
-static unsigned long cs_debugmask = CS_INIT | CS_ERROR;	// use CS_DBGOUT with various mask values
-#if MODULE
-MODULE_PARM(cs_debuglevel, "i");
-MODULE_PARM(cs_debugmask, "i");
-#endif
-#endif
-
-// MIDI buffer sizes 
-#define MIDIINBUF  500
-#define MIDIOUTBUF 500
-
-#define FMODE_MIDI_SHIFT 3
-#define FMODE_MIDI_READ  (FMODE_READ << FMODE_MIDI_SHIFT)
-#define FMODE_MIDI_WRITE (FMODE_WRITE << FMODE_MIDI_SHIFT)
-
-#define RSRCISIOREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
-	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
-#define RSRCISMEMORYREGION(dev,num) ((dev)->resource[(num)].start != 0 && \
-	 ((dev)->resource[(num)].flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY)
-#define RSRCADDRESS(dev,num) ((dev)->resource[(num)].start)
-
-#define CS4281_MAJOR_VERSION 	1
-#define CS4281_MINOR_VERSION 	1
-#ifdef __ia64__
-#define CS4281_ARCH	     	64	//architecture key
-#else
-#define CS4281_ARCH	     	32	//architecture key
-#endif
-
-#define CS_TYPE_ADC 0
-#define CS_TYPE_DAC 1
-
-struct cs4281_state {
-	// magic 
-	unsigned int magic;
-
-	// we keep the cards in a linked list 
-	struct cs4281_state *next;
-
-	// pcidev is needed to turn off the DDMA controller at driver shutdown 
-	struct pci_dev *pcidev;
-
-	// soundcore stuff 
-	int dev_audio;
-	int dev_mixer;
-	int dev_midi;
-
-	// hardware resources 
-	unsigned int pBA0phys, pBA1phys;
-	char *pBA0, *pBA1;
-	unsigned int irq;
-
-	// mixer registers 
-	struct {
-		unsigned short vol[10];
-		unsigned int recsrc;
-		unsigned int modcnt;
-		unsigned short micpreamp;
-	} mix;
-
-	// wave stuff   
-	struct properties {
-		unsigned fmt;
-		unsigned fmt_original;	// original requested format
-		unsigned channels;
-		unsigned rate;
-		unsigned char clkdiv;
-	} prop_dac, prop_adc;
-	unsigned conversion:1;	// conversion from 16 to 8 bit in progress
-	void *tmpbuff;		// tmp buffer for sample conversions
-	unsigned ena;
-	spinlock_t lock;
-	struct semaphore open_sem;
-	struct semaphore open_sem_adc;
-	struct semaphore open_sem_dac;
-	mode_t open_mode;
-	wait_queue_head_t open_wait;
-	wait_queue_head_t open_wait_adc;
-	wait_queue_head_t open_wait_dac;
-
-	dma_addr_t dmaaddr_tmpbuff;
-	unsigned buforder_tmpbuff;	// Log base 2 of 'rawbuf' size in bytes..
-	struct dmabuf {
-		void *rawbuf;	// Physical address of  
-		dma_addr_t dmaaddr;
-		unsigned buforder;	// Log base 2 of 'rawbuf' size in bytes..
-		unsigned numfrag;	// # of 'fragments' in the buffer.
-		unsigned fragshift;	// Log base 2 of fragment size.
-		unsigned hwptr, swptr;
-		unsigned total_bytes;	// # bytes process since open.
-		unsigned blocks;	// last returned blocks value GETOPTR
-		unsigned wakeup;	// interrupt occurred on block 
-		int count;
-		unsigned error;	// over/underrun 
-		wait_queue_head_t wait;
-		// redundant, but makes calculations easier 
-		unsigned fragsize;	// 2**fragshift..
-		unsigned dmasize;	// 2**buforder.
-		unsigned fragsamples;
-		// OSS stuff 
-		unsigned mapped:1;	// Buffer mapped in cs4281_mmap()?
-		unsigned ready:1;	// prog_dmabuf_dac()/adc() successful?
-		unsigned endcleared:1;
-		unsigned type:1;	// adc or dac buffer (CS_TYPE_XXX)
-		unsigned ossfragshift;
-		int ossmaxfrags;
-		unsigned subdivision;
-	} dma_dac, dma_adc;
-
-	// midi stuff 
-	struct {
-		unsigned ird, iwr, icnt;
-		unsigned ord, owr, ocnt;
-		wait_queue_head_t iwait;
-		wait_queue_head_t owait;
-		struct timer_list timer;
-		unsigned char ibuf[MIDIINBUF];
-		unsigned char obuf[MIDIOUTBUF];
-	} midi;
-
-};
-
-#if CSDEBUG
-
-// DEBUG ROUTINES
-
-#define SOUND_MIXER_CS_GETDBGLEVEL 	_SIOWR('M',120, int)
-#define SOUND_MIXER_CS_SETDBGLEVEL 	_SIOWR('M',121, int)
-#define SOUND_MIXER_CS_GETDBGMASK 	_SIOWR('M',122, int)
-#define SOUND_MIXER_CS_SETDBGMASK 	_SIOWR('M',123, int)
-
-#define SNDCTL_DSP_CS_GETDBGLEVEL 	_SIOWR('P', 50, int)
-#define SNDCTL_DSP_CS_SETDBGLEVEL 	_SIOWR('P', 51, int)
-#define SNDCTL_DSP_CS_GETDBGMASK 	_SIOWR('P', 52, int)
-#define SNDCTL_DSP_CS_SETDBGMASK 	_SIOWR('P', 53, int)
-
-static void printioctl(unsigned int x)
-{
-	unsigned int i;
-	unsigned char vidx;
-	// Index of mixtable1[] member is Device ID 
-	// and must be <= SOUND_MIXER_NRDEVICES.
-	// Value of array member is index into s->mix.vol[]
-	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
-		[SOUND_MIXER_PCM] = 1,	// voice 
-		[SOUND_MIXER_LINE1] = 2,	// AUX
-		[SOUND_MIXER_CD] = 3,	// CD 
-		[SOUND_MIXER_LINE] = 4,	// Line 
-		[SOUND_MIXER_SYNTH] = 5,	// FM
-		[SOUND_MIXER_MIC] = 6,	// Mic 
-		[SOUND_MIXER_SPEAKER] = 7,	// Speaker 
-		[SOUND_MIXER_RECLEV] = 8,	// Recording level 
-		[SOUND_MIXER_VOLUME] = 9	// Master Volume 
-	};
-
-	switch (x) {
-	case SOUND_MIXER_CS_GETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SOUND_MIXER_CS_GETDBGMASK:\n"));
-		break;
-	case SOUND_MIXER_CS_GETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SOUND_MIXER_CS_GETDBGLEVEL:\n"));
-		break;
-	case SOUND_MIXER_CS_SETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SOUND_MIXER_CS_SETDBGMASK:\n"));
-		break;
-	case SOUND_MIXER_CS_SETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SOUND_MIXER_CS_SETDBGLEVEL:\n"));
-		break;
-	case OSS_GETVERSION:
-		CS_DBGOUT(CS_IOCTL, 4, printk("OSS_GETVERSION:\n"));
-		break;
-	case SNDCTL_DSP_SYNC:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SYNC:\n"));
-		break;
-	case SNDCTL_DSP_SETDUPLEX:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETDUPLEX:\n"));
-		break;
-	case SNDCTL_DSP_GETCAPS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETCAPS:\n"));
-		break;
-	case SNDCTL_DSP_RESET:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_RESET:\n"));
-		break;
-	case SNDCTL_DSP_SPEED:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SPEED:\n"));
-		break;
-	case SNDCTL_DSP_STEREO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_STEREO:\n"));
-		break;
-	case SNDCTL_DSP_CHANNELS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_CHANNELS:\n"));
-		break;
-	case SNDCTL_DSP_GETFMTS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETFMTS:\n"));
-		break;
-	case SNDCTL_DSP_SETFMT:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETFMT:\n"));
-		break;
-	case SNDCTL_DSP_POST:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_POST:\n"));
-		break;
-	case SNDCTL_DSP_GETTRIGGER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETTRIGGER:\n"));
-		break;
-	case SNDCTL_DSP_SETTRIGGER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETTRIGGER:\n"));
-		break;
-	case SNDCTL_DSP_GETOSPACE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOSPACE:\n"));
-		break;
-	case SNDCTL_DSP_GETISPACE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETISPACE:\n"));
-		break;
-	case SNDCTL_DSP_NONBLOCK:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_NONBLOCK:\n"));
-		break;
-	case SNDCTL_DSP_GETODELAY:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETODELAY:\n"));
-		break;
-	case SNDCTL_DSP_GETIPTR:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETIPTR:\n"));
-		break;
-	case SNDCTL_DSP_GETOPTR:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETOPTR:\n"));
-		break;
-	case SNDCTL_DSP_GETBLKSIZE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_GETBLKSIZE:\n"));
-		break;
-	case SNDCTL_DSP_SETFRAGMENT:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SNDCTL_DSP_SETFRAGMENT:\n"));
-		break;
-	case SNDCTL_DSP_SUBDIVIDE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SUBDIVIDE:\n"));
-		break;
-	case SOUND_PCM_READ_RATE:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_RATE:\n"));
-		break;
-	case SOUND_PCM_READ_CHANNELS:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SOUND_PCM_READ_CHANNELS:\n"));
-		break;
-	case SOUND_PCM_READ_BITS:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_BITS:\n"));
-		break;
-	case SOUND_PCM_WRITE_FILTER:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SOUND_PCM_WRITE_FILTER:\n"));
-		break;
-	case SNDCTL_DSP_SETSYNCRO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SNDCTL_DSP_SETSYNCRO:\n"));
-		break;
-	case SOUND_PCM_READ_FILTER:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_PCM_READ_FILTER:\n"));
-		break;
-	case SNDCTL_DSP_CS_GETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SNDCTL_DSP_CS_GETDBGMASK:\n"));
-		break;
-	case SNDCTL_DSP_CS_GETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SNDCTL_DSP_CS_GETDBGLEVEL:\n"));
-		break;
-	case SNDCTL_DSP_CS_SETDBGMASK:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SNDCTL_DSP_CS_SETDBGMASK:\n"));
-		break;
-	case SNDCTL_DSP_CS_SETDBGLEVEL:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk("SNDCTL_DSP_CS_SETDBGLEVEL:\n"));
-		break;
-
-	case SOUND_MIXER_PRIVATE1:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE1:\n"));
-		break;
-	case SOUND_MIXER_PRIVATE2:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE2:\n"));
-		break;
-	case SOUND_MIXER_PRIVATE3:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE3:\n"));
-		break;
-	case SOUND_MIXER_PRIVATE4:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE4:\n"));
-		break;
-	case SOUND_MIXER_PRIVATE5:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_PRIVATE5:\n"));
-		break;
-	case SOUND_MIXER_INFO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_MIXER_INFO:\n"));
-		break;
-	case SOUND_OLD_MIXER_INFO:
-		CS_DBGOUT(CS_IOCTL, 4, printk("SOUND_OLD_MIXER_INFO:\n"));
-		break;
-
-	default:
-		switch (_IOC_NR(x)) {
-		case SOUND_MIXER_VOLUME:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_VOLUME:\n"));
-			break;
-		case SOUND_MIXER_SPEAKER:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_SPEAKER:\n"));
-			break;
-		case SOUND_MIXER_RECLEV:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_RECLEV:\n"));
-			break;
-		case SOUND_MIXER_MIC:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_MIC:\n"));
-			break;
-		case SOUND_MIXER_SYNTH:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_SYNTH:\n"));
-			break;
-		case SOUND_MIXER_RECSRC:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_RECSRC:\n"));
-			break;
-		case SOUND_MIXER_DEVMASK:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_DEVMASK:\n"));
-			break;
-		case SOUND_MIXER_RECMASK:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_RECMASK:\n"));
-			break;
-		case SOUND_MIXER_STEREODEVS:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_STEREODEVS:\n"));
-			break;
-		case SOUND_MIXER_CAPS:
-			CS_DBGOUT(CS_IOCTL, 4,
-				  printk("SOUND_MIXER_CAPS:\n"));
-			break;
-		default:
-			i = _IOC_NR(x);
-			if (i >= SOUND_MIXER_NRDEVICES
-			    || !(vidx = mixtable1[i])) {
-				CS_DBGOUT(CS_IOCTL, 4,
-					  printk
-					  ("UNKNOWN IOCTL: 0x%.8x NR=%d\n",
-					   x, i));
-			} else {
-				CS_DBGOUT(CS_IOCTL, 4,
-					  printk
-					  ("SOUND_MIXER_IOCTL AC9x: 0x%.8x NR=%d\n",
-					   x, i));
-			}
-			break;
-		}
-	}
-}
-#endif
-static int prog_dmabuf_adc(struct cs4281_state *s);
-static void prog_codec(struct cs4281_state *s, unsigned type);
-
-static struct cs4281_state *devs = NULL;
-// --------------------------------------------------------------------- 
-//
-//              Hardware Interfaces For the CS4281
-//
-
-
-//******************************************************************************
-// "delayus()-- Delay for the specified # of microseconds.
-//******************************************************************************
-static void delayus(u32 delay)
-{
-	u32 j;
-	if (delay > 9999) {
-		j = (delay * HZ) / 1000000;	/* calculate delay in jiffies  */
-		if (j < 1)
-			j = 1;	/* minimum one jiffy. */
-		current->state = TASK_UNINTERRUPTIBLE;
-		schedule_timeout(j);
-	} else
-		udelay(delay);
-	return;
-}
-
-
-//******************************************************************************
-// "cs4281_read_ac97" -- Reads a word from the specified location in the
-//               CS4281's address space(based on the BA0 register).
-//
-// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
-// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 register,
-//                                            0h for reads.
-// 3. Write ACCTL = Control Register = 460h for initiating the write
-// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
-// 5. if DCV not cleared, break and return error
-// 6. Read ACSTS = Status Register = 464h, check VSTS bit
-//****************************************************************************
-static int cs4281_read_ac97(struct cs4281_state *card, u32 offset,
-			    u32 * value)
-{
-	u32 count, status;
-
-	// Make sure that there is not data sitting
-	// around from a previous uncompleted access.
-	// ACSDA = Status Data Register = 47Ch
-	status = readl(card->pBA0 + BA0_ACSDA);
-
-	// Setup the AC97 control registers on the CS4281 to send the
-	// appropriate command to the AC97 to perform the read.
-	// ACCAD = Command Address Register = 46Ch
-	// ACCDA = Command Data Register = 470h
-	// ACCTL = Control Register = 460h
-	// bit DCV - will clear when process completed
-	// bit CRW - Read command
-	// bit VFRM - valid frame enabled
-	// bit ESYN - ASYNC generation enabled
-
-	// Get the actual AC97 register from the offset
-	writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD);
-	writel(0, card->pBA0 + BA0_ACCDA);
-	writel(ACCTL_DCV | ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN,
-	       card->pBA0 + BA0_ACCTL);
-
-	// Wait for the read to occur.
-	for (count = 0; count < 10; count++) {
-		// First, we want to wait for a short time.
-		udelay(25);
-
-		// Now, check to see if the read has completed.
-		// ACCTL = 460h, DCV should be reset by now and 460h = 17h
-		if (!(readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV))
-			break;
-	}
-
-	// Make sure the read completed.
-	if (readl(card->pBA0 + BA0_ACCTL) & ACCTL_DCV)
-		return 1;
-
-	// Wait for the valid status bit to go active.
-	for (count = 0; count < 10; count++) {
-		// Read the AC97 status register.
-		// ACSTS = Status Register = 464h
-		status = readl(card->pBA0 + BA0_ACSTS);
-
-		// See if we have valid status.
-		// VSTS - Valid Status
-		if (status & ACSTS_VSTS)
-			break;
-		// Wait for a short while.
-		udelay(25);
-	}
-
-	// Make sure we got valid status.
-	if (!(status & ACSTS_VSTS))
-		return 1;
-
-	// Read the data returned from the AC97 register.
-	// ACSDA = Status Data Register = 474h
-	*value = readl(card->pBA0 + BA0_ACSDA);
-
-	// Success.
-	return (0);
-}
-
-
-//****************************************************************************
-//
-// "cs4281_write_ac97()"-- writes a word to the specified location in the
-// CS461x's address space (based on the part's base address zero register).
-//
-// 1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
-// 2. Write ACCDA = Command Data Register = 470h for data to write to AC97 reg.
-// 3. Write ACCTL = Control Register = 460h for initiating the write
-// 4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
-// 5. if DCV not cleared, break and return error
-//
-//****************************************************************************
-static int cs4281_write_ac97(struct cs4281_state *card, u32 offset,
-			     u32 value)
-{
-	u32 count, status;
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: cs_4281_write_ac97()+ \n"));
-
-	// Setup the AC97 control registers on the CS4281 to send the
-	// appropriate command to the AC97 to perform the read.
-	// ACCAD = Command Address Register = 46Ch
-	// ACCDA = Command Data Register = 470h
-	// ACCTL = Control Register = 460h
-	// set DCV - will clear when process completed
-	// reset CRW - Write command
-	// set VFRM - valid frame enabled
-	// set ESYN - ASYNC generation enabled
-	// set RSTN - ARST# inactive, AC97 codec not reset
-
-	// Get the actual AC97 register from the offset
-
-	writel(offset - BA0_AC97_RESET, card->pBA0 + BA0_ACCAD);
-	writel(value, card->pBA0 + BA0_ACCDA);
-	writel(ACCTL_DCV | ACCTL_VFRM | ACCTL_ESYN,
-	       card->pBA0 + BA0_ACCTL);
-
-	// Wait for the write to occur.
-	for (count = 0; count < 10; count++) {
-		// First, we want to wait for a short time.
-		udelay(25);
-		// Now, check to see if the write has completed.
-		// ACCTL = 460h, DCV should be reset by now and 460h = 07h
-		status = readl(card->pBA0 + BA0_ACCTL);
-		if (!(status & ACCTL_DCV))
-			break;
-	}
-
-	// Make sure the write completed.
-	if (status & ACCTL_DCV) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
-					      "cs4281: cs_4281_write_ac97()- unable to write. ACCTL_DCV active\n"));
-		return 1;
-	}
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: cs_4281_write_ac97()- 0\n"));
-	// Success.
-	return 0;
-}
-
-
-//******************************************************************************
-// "Init4281()" -- Bring up the part.
-//******************************************************************************
-static int __devinit cs4281_hw_init(struct cs4281_state *card)
-{
-	u32 ac97_slotid;
-	u32 temp1, temp2;
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: cs4281_hw_init()+ \n"));
-	//***************************************7
-	//  Set up the Sound System Configuration
-	//***************************************
-
-	// Set the 'Configuration Write Protect' register
-	// to 4281h.  Allows vendor-defined configuration
-	// space between 0e4h and 0ffh to be written.
-
-	writel(0x4281, card->pBA0 + BA0_CWPR);	// (3e0h)
-
-	// (0), Blast the clock control register to zero so that the
-	// PLL starts out in a known state, and blast the master serial
-	// port control register to zero so that the serial ports also
-	// start out in a known state.
-
-	writel(0, card->pBA0 + BA0_CLKCR1);	// (400h)
-	writel(0, card->pBA0 + BA0_SERMC);	// (420h)
-
-
-	// (1), Make ESYN go to zero to turn off
-	// the Sync pulse on the AC97 link.
-
-	writel(0, card->pBA0 + BA0_ACCTL);
-	udelay(50);
-
-
-	// (2) Drive the ARST# pin low for a minimum of 1uS (as defined in
-	// the AC97 spec) and then drive it high.  This is done for non
-	// AC97 modes since there might be logic external to the CS461x
-	// that uses the ARST# line for a reset.
-
-	writel(0, card->pBA0 + BA0_SPMC);	// (3ech)
-	udelay(100);
-	writel(SPMC_RSTN, card->pBA0 + BA0_SPMC);
-	delayus(50000);		// Wait 50 ms for ABITCLK to become stable.
-
-	// (3) Turn on the Sound System Clocks.
-	writel(CLKCR1_PLLP, card->pBA0 + BA0_CLKCR1);	// (400h)
-	delayus(50000);		// Wait for the PLL to stabilize.
-	// Turn on clocking of the core (CLKCR1(400h) = 0x00000030)
-	writel(CLKCR1_PLLP | CLKCR1_SWCE, card->pBA0 + BA0_CLKCR1);
-
-	// (4) Power on everything for now..
-	writel(0x7E, card->pBA0 + BA0_SSPM);	// (740h)
-
-	// (5) Wait for clock stabilization.
-	for (temp1 = 0; temp1 < 1000; temp1++) {
-		udelay(1000);
-		if (readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)
-			break;
-	}
-	if (!(readl(card->pBA0 + BA0_CLKCR1) & CLKCR1_DLLRDY)) {
-		CS_DBGOUT(CS_ERROR, 1,
-			  printk(KERN_ERR "cs4281: DLLRDY failed!\n"));
-		return -EIO;
-	}
-	// (6) Enable ASYNC generation.
-	writel(ACCTL_ESYN, card->pBA0 + BA0_ACCTL);	// (460h)
-
-	// Now wait 'for a short while' to allow the  AC97
-	// part to start generating bit clock. (so we don't
-	// Try to start the PLL without an input clock.)
-	delayus(50000);
-
-	// Set the serial port timing configuration, so that the
-	// clock control circuit gets its clock from the right place.
-	writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC);	// (420h)=2.
-
-	// (7) Wait for the codec ready signal from the AC97 codec.
-
-	for (temp1 = 0; temp1 < 1000; temp1++) {
-		// Delay a mil to let things settle out and
-		// to prevent retrying the read too quickly.
-		udelay(1000);
-		if (readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY)	// If ready,  (464h)
-			break;	//   exit the 'for' loop.
-	}
-	if (!(readl(card->pBA0 + BA0_ACSTS) & ACSTS_CRDY))	// If never came ready,
-	{
-		CS_DBGOUT(CS_FUNCTION, 2,
-			  printk(KERN_ERR
-				 "cs4281: ACSTS never came ready!\n"));
-		return -EIO;	//   exit initialization.
-	}
-	// (8) Assert the 'valid frame' signal so we can
-	// begin sending commands to the AC97 codec.
-	writel(ACCTL_VFRM | ACCTL_ESYN, card->pBA0 + BA0_ACCTL);	// (460h)
-
-	// (9), Wait until CODEC calibration is finished.
-	// Print an error message if it doesn't.
-	for (temp1 = 0; temp1 < 1000; temp1++) {
-		delayus(10000);
-		// Read the AC97 Powerdown Control/Status Register.
-		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp2);
-		if ((temp2 & 0x0000000F) == 0x0000000F)
-			break;
-	}
-	if ((temp2 & 0x0000000F) != 0x0000000F) {
-		CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_ERR
-						 "cs4281: Codec failed to calibrate.  Status = %.8x.\n",
-						 temp2));
-		return -EIO;
-	}
-	// (10), Set the serial port timing configuration, so that the
-	// clock control circuit gets its clock from the right place.
-	writel(SERMC_PTC_AC97, card->pBA0 + BA0_SERMC);	// (420h)=2.
-
-
-	// (11) Wait until we've sampled input slots 3 & 4 as valid, meaning
-	// that the codec is pumping ADC data across the AC link.
-	for (temp1 = 0; temp1 < 1000; temp1++) {
-		// Delay a mil to let things settle out and
-		// to prevent retrying the read too quickly.
-		delayus(1000);	//(test)
-
-		// Read the input slot valid register;  See
-		// if input slots 3 and 4 are valid yet.
-		if (
-		    (readl(card->pBA0 + BA0_ACISV) &
-		     (ACISV_ISV3 | ACISV_ISV4)) ==
-		    (ACISV_ISV3 | ACISV_ISV4)) break;	// Exit the 'for' if slots are valid.
-	}
-	// If we never got valid data, exit initialization.
-	if ((readl(card->pBA0 + BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4))
-	    != (ACISV_ISV3 | ACISV_ISV4)) {
-		CS_DBGOUT(CS_FUNCTION, 2,
-			  printk(KERN_ERR
-				 "cs4281: Never got valid data!\n"));
-		return -EIO;	// If no valid data, exit initialization.
-	}
-	// (12), Start digital data transfer of audio data to the codec.
-	writel(ACOSV_SLV3 | ACOSV_SLV4, card->pBA0 + BA0_ACOSV);	// (468h)
-
-
-	//**************************************
-	// Unmute the Master and Alternate
-	// (headphone) volumes.  Set to max.
-	//**************************************
-	cs4281_write_ac97(card, BA0_AC97_HEADPHONE_VOLUME, 0);
-	cs4281_write_ac97(card, BA0_AC97_MASTER_VOLUME, 0);
-
-	//******************************************
-	// Power on the DAC(AddDACUser()from main())
-	//******************************************
-	cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
-	cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfdff);
-
-	// Wait until we sample a DAC ready state.
-	for (temp2 = 0; temp2 < 32; temp2++) {
-		// Let's wait a mil to let things settle.
-		delayus(1000);
-		// Read the current state of the power control reg.
-		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
-		// If the DAC ready state bit is set, stop waiting.
-		if (temp1 & 0x2)
-			break;
-	}
-
-	//******************************************
-	// Power on the ADC(AddADCUser()from main())
-	//******************************************
-	cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
-	cs4281_write_ac97(card, BA0_AC97_POWERDOWN, temp1 &= 0xfeff);
-
-	// Wait until we sample ADC ready state.
-	for (temp2 = 0; temp2 < 32; temp2++) {
-		// Let's wait a mil to let things settle.
-		delayus(1000);
-		// Read the current state of the power control reg.
-		cs4281_read_ac97(card, BA0_AC97_POWERDOWN, &temp1);
-		// If the ADC ready state bit is set, stop waiting.
-		if (temp1 & 0x1)
-			break;
-	}
-	// Set up 4281 Register contents that
-	// don't change for boot duration.
-
-	// For playback, we map AC97 slot 3 and 4(Left
-	// & Right PCM playback) to DMA Channel 0.
-	// Set the fifo to be 15 bytes at offset zero.
-
-	ac97_slotid = 0x01000f00;	// FCR0.RS[4:0]=1(=>slot4, right PCM playback).
-	// FCR0.LS[4:0]=0(=>slot3, left PCM playback).
-	// FCR0.SZ[6-0]=15; FCR0.OF[6-0]=0.
-	writel(ac97_slotid, card->pBA0 + BA0_FCR0);	// (180h)
-	writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR0);	// Turn on FIFO Enable.
-
-	// For capture, we map AC97 slot 10 and 11(Left
-	// and Right PCM Record) to DMA Channel 1.
-	// Set the fifo to be 15 bytes at offset sixteen.
-	ac97_slotid = 0x0B0A0f10;	// FCR1.RS[4:0]=11(=>slot11, right PCM record).
-	// FCR1.LS[4:0]=10(=>slot10, left PCM record).
-	// FCR1.SZ[6-0]=15; FCR1.OF[6-0]=16.
-	writel(ac97_slotid | FCRn_PSH, card->pBA0 + BA0_FCR1);	// (184h)
-	writel(ac97_slotid | FCRn_FEN, card->pBA0 + BA0_FCR1);	// Turn on FIFO Enable.
-
-	// Map the Playback SRC to the same AC97 slots(3 & 4--
-	// --Playback left & right)as DMA channel 0.
-	// Map the record SRC to the same AC97 slots(10 & 11--
-	// -- Record left & right) as DMA channel 1.
-
-	ac97_slotid = 0x0b0a0100;	// SCRSA.PRSS[4:0]=1(=>slot4, right PCM playback).
-	// SCRSA.PLSS[4:0]=0(=>slot3, left PCM playback).
-	// SCRSA.CRSS[4:0]=11(=>slot11, right PCM record)
-	// SCRSA.CLSS[4:0]=10(=>slot10, left PCM record).
-	writel(ac97_slotid, card->pBA0 + BA0_SRCSA);	// (75ch)
-
-	// Set 'Half Terminal Count Interrupt Enable' and 'Terminal
-	// Count Interrupt Enable' in DMA Control Registers 0 & 1.
-	// Set 'MSK' flag to 1 to keep the DMA engines paused.
-	temp1 = (DCRn_HTCIE | DCRn_TCIE | DCRn_MSK);	// (00030001h)
-	writel(temp1, card->pBA0 + BA0_DCR0);	// (154h
-	writel(temp1, card->pBA0 + BA0_DCR1);	// (15ch)
-
-	// Set 'Auto-Initialize Control' to 'enabled'; For playback,
-	// set 'Transfer Type Control'(TR[1:0]) to 'read transfer',
-	// for record, set Transfer Type Control to 'write transfer'.
-	// All other bits set to zero;  Some will be changed @ transfer start.
-	temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_READ);	// (20000018h)
-	writel(temp1, card->pBA0 + BA0_DMR0);	// (150h)
-	temp1 = (DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE);	// (20000014h)
-	writel(temp1, card->pBA0 + BA0_DMR1);	// (158h)
-
-	// Enable DMA interrupts generally, and
-	// DMA0 & DMA1 interrupts specifically.
-	temp1 = readl(card->pBA0 + BA0_HIMR) & 0xfffbfcff;
-	writel(temp1, card->pBA0 + BA0_HIMR);
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: cs4281_hw_init()- 0\n"));
-	return 0;
-}
-
-
-//******************************************************************************
-// "cs4281_play_rate()" --
-//******************************************************************************
-static void cs4281_play_rate(struct cs4281_state *card, u32 playrate)
-{
-	u32 DACSRvalue = 1;
-
-	// Based on the sample rate, program the DACSR register.
-	if (playrate == 8000)
-		DACSRvalue = 5;
-	if (playrate == 11025)
-		DACSRvalue = 4;
-	else if (playrate == 22050)
-		DACSRvalue = 2;
-	else if (playrate == 44100)
-		DACSRvalue = 1;
-	else if ((playrate <= 48000) && (playrate >= 6023))
-		DACSRvalue = 24576000 / (playrate * 16);
-	else if (playrate < 6023)
-		// Not allowed by open.
-		return;
-	else if (playrate > 48000)
-		// Not allowed by open.
-		return;
-	CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 2, printk(KERN_INFO
-						      "cs4281: cs4281_play_rate(): DACSRvalue=0x%.8x playrate=%d\n",
-						      DACSRvalue,
-						      playrate));
-	//  Write the 'sample rate select code'
-	//  to the 'DAC Sample Rate' register.
-	writel(DACSRvalue, card->pBA0 + BA0_DACSR);	// (744h)
-}
-
-//******************************************************************************
-// "cs4281_record_rate()" -- Initialize the record sample rate converter.
-//******************************************************************************
-static void cs4281_record_rate(struct cs4281_state *card, u32 outrate)
-{
-	u32 ADCSRvalue = 1;
-
-	//
-	// Based on the sample rate, program the ADCSR register
-	//
-	if (outrate == 8000)
-		ADCSRvalue = 5;
-	if (outrate == 11025)
-		ADCSRvalue = 4;
-	else if (outrate == 22050)
-		ADCSRvalue = 2;
-	else if (outrate == 44100)
-		ADCSRvalue = 1;
-	else if ((outrate <= 48000) && (outrate >= 6023))
-		ADCSRvalue = 24576000 / (outrate * 16);
-	else if (outrate < 6023) {
-		// Not allowed by open.
-		return;
-	} else if (outrate > 48000) {
-		// Not allowed by open.
-		return;
-	}
-	CS_DBGOUT(CS_WAVE_READ | CS_PARMS, 2, printk(KERN_INFO
-						     "cs4281: cs4281_record_rate(): ADCSRvalue=0x%.8x outrate=%d\n",
-						     ADCSRvalue, outrate));
-	//  Write the 'sample rate select code
-	//  to the 'ADC Sample Rate' register.
-	writel(ADCSRvalue, card->pBA0 + BA0_ADCSR);	// (748h)
-}
-
-
-
-static void stop_dac(struct cs4281_state *s)
-{
-	unsigned long flags;
-	unsigned temp1;
-
-	CS_DBGOUT(CS_WAVE_WRITE, 3,
-		  printk(KERN_INFO "cs4281: stop_dac():\n"));
-	spin_lock_irqsave(&s->lock, flags);
-	s->ena &= ~FMODE_WRITE;
-	temp1 = readl(s->pBA0 + BA0_DCR0) | DCRn_MSK;
-	writel(temp1, s->pBA0 + BA0_DCR0);
-
-	spin_unlock_irqrestore(&s->lock, flags);
-}
-
-
-static void start_dac(struct cs4281_state *s)
-{
-	unsigned long flags;
-	unsigned temp1;
-
-	CS_DBGOUT(CS_FUNCTION, 3,
-		  printk(KERN_INFO "cs4281: start_dac()+\n"));
-	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;
-		temp1 = readl(s->pBA0 + BA0_DCR0) & ~DCRn_MSK;	// Clear DMA0 channel mask.
-		writel(temp1, s->pBA0 + BA0_DCR0);	// Start DMA'ing.
-		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts.              
-
-		writel(7, s->pBA0 + BA0_PPRVC);
-		writel(7, s->pBA0 + BA0_PPLVC);
-		CS_DBGOUT(CS_WAVE_WRITE | CS_PARMS, 8, printk(KERN_INFO
-							      "cs4281: start_dac(): writel 0x%x start dma\n",
-							      temp1));
-
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 3,
-		  printk(KERN_INFO "cs4281: start_dac()-\n"));
-}
-
-
-static void stop_adc(struct cs4281_state *s)
-{
-	unsigned long flags;
-	unsigned temp1;
-
-	CS_DBGOUT(CS_FUNCTION, 3,
-		  printk(KERN_INFO "cs4281: stop_adc()+\n"));
-
-	spin_lock_irqsave(&s->lock, flags);
-	s->ena &= ~FMODE_READ;
-
-	if (s->conversion == 1) {
-		s->conversion = 0;
-		s->prop_adc.fmt = s->prop_adc.fmt_original;
-	}
-	temp1 = readl(s->pBA0 + BA0_DCR1) | DCRn_MSK;
-	writel(temp1, s->pBA0 + BA0_DCR1);
-	spin_unlock_irqrestore(&s->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 3,
-		  printk(KERN_INFO "cs4281: stop_adc()-\n"));
-}
-
-
-static void start_adc(struct cs4281_state *s)
-{
-	unsigned long flags;
-	unsigned temp1;
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: start_adc()+\n"));
-
-	spin_lock_irqsave(&s->lock, flags);
-	if (!(s->ena & FMODE_READ) &&
-	    (s->dma_adc.mapped || s->dma_adc.count <=
-	     (signed) (s->dma_adc.dmasize - 2 * s->dma_adc.fragsize))
-	    && s->dma_adc.ready) {
-		if (s->prop_adc.fmt & AFMT_S8 || s->prop_adc.fmt & AFMT_U8) {
-			// 
-			// now only use 16 bit capture, due to truncation issue
-			// in the chip, noticable distortion occurs.
-			// allocate buffer and then convert from 16 bit to 
-			// 8 bit for the user buffer.
-			//
-			s->prop_adc.fmt_original = s->prop_adc.fmt;
-			if (s->prop_adc.fmt & AFMT_S8) {
-				s->prop_adc.fmt &= ~AFMT_S8;
-				s->prop_adc.fmt |= AFMT_S16_LE;
-			}
-			if (s->prop_adc.fmt & AFMT_U8) {
-				s->prop_adc.fmt &= ~AFMT_U8;
-				s->prop_adc.fmt |= AFMT_U16_LE;
-			}
-			//
-			// prog_dmabuf_adc performs a stop_adc() but that is
-			// ok since we really haven't started the DMA yet.
-			//
-			prog_codec(s, CS_TYPE_ADC);
-
-			if (prog_dmabuf_adc(s) != 0) {
-				CS_DBGOUT(CS_ERROR, 3,
-					  printk(KERN_INFO
-						 "cs4281: start_adc(): error in prog_dmabuf_adc\n"));
-			}
-			s->conversion = 1;
-		}
-		s->ena |= FMODE_READ;
-		temp1 = readl(s->pBA0 + BA0_DCR1) & ~DCRn_MSK;	// Clear DMA1 channel mask bit.
-		writel(temp1, s->pBA0 + BA0_DCR1);	// Start recording
-		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts.
-		CS_DBGOUT(CS_PARMS, 6,
-			  printk(KERN_INFO
-				 "cs4281: start_adc(): writel 0x%x \n",
-				 temp1));
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: start_adc()-\n"));
-
-}
-
-
-// --------------------------------------------------------------------- 
-// use 64k (+1) rather than 32k as some of the higher frequencies need a larger buffer.
-// comments reflect 32k.
-#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT+1)	// == 3(for PC), = log base 2( buff sz = 32k).
-#define DMABUF_MINORDER 1	// ==> min buffer size = 8K.
-
-
-extern void dealloc_dmabuf(struct cs4281_state *s, struct dmabuf *db)
-{
-	struct page *map, *mapend;
-
-	if (db->rawbuf) {
-		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend =
-		    virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) -
-				 1);
-		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
-			mem_map_unreserve(map);
-		pci_free_consistent(s->pcidev, PAGE_SIZE << db->buforder,
-				    db->rawbuf, db->dmaaddr);
-	}
-	if (s->tmpbuff && (db->type == CS_TYPE_ADC)) {
-		// Undo prog_dmabuf()'s marking the pages as reserved 
-		mapend =
-		    virt_to_page(s->tmpbuff +
-				 (PAGE_SIZE << s->buforder_tmpbuff) - 1);
-		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)
-			mem_map_unreserve(map);
-		pci_free_consistent(s->pcidev,
-				    PAGE_SIZE << s->buforder_tmpbuff,
-				    s->tmpbuff, s->dmaaddr_tmpbuff);
-	}
-	s->tmpbuff = NULL;
-	db->rawbuf = NULL;
-	db->mapped = db->ready = 0;
-}
-
-static int prog_dmabuf(struct cs4281_state *s, struct dmabuf *db)
-{
-	int order;
-	unsigned bytespersec, temp1;
-	unsigned bufs, sample_shift = 0;
-	struct page *map, *mapend;
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: prog_dmabuf()+\n"));
-	db->hwptr = db->swptr = db->total_bytes = db->count = db->error =
-	    db->endcleared = db->blocks = db->wakeup = 0;
-
-	if (!db->rawbuf) {
-		db->ready = db->mapped = 0;
-		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER;
-		     order--)
-			if (
-			    (db->rawbuf =
-			     (void *) pci_alloc_consistent(s->pcidev,
-							   PAGE_SIZE <<
-							   order,
-							   &db->
-							   dmaaddr)))
-				    break;
-		if (!db->rawbuf) {
-			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-						      "cs4281: prog_dmabuf(): unable to allocate rawbuf\n"));
-			return -ENOMEM;
-		}
-		db->buforder = order;
-		// Now mark the pages as reserved; otherwise the 
-		// remap_page_range() in cs4281_mmap doesn't work.
-		// 1. get index to last page in mem_map array for rawbuf.
-		mapend =
-		    virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) -
-				 1);
-
-		// 2. mark each physical page in range as 'reserved'.
-		for (map = virt_to_page(db->rawbuf); map <= mapend; map++)
-			mem_map_reserve(map);
-	}
-	if (!s->tmpbuff && (db->type == CS_TYPE_ADC)) {
-		for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER;
-		     order--)
-			if (
-			    (s->tmpbuff =
-			     (void *) pci_alloc_consistent(s->pcidev,
-							   PAGE_SIZE <<
-							   order,
-							   &s->
-							   dmaaddr_tmpbuff)))
-				    break;
-		if (!s->tmpbuff) {
-			CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-						      "cs4281: prog_dmabuf(): unable to allocate tmpbuff\n"));
-			return -ENOMEM;
-		}
-		s->buforder_tmpbuff = order;
-		// Now mark the pages as reserved; otherwise the 
-		// remap_page_range() in cs4281_mmap doesn't work.
-		// 1. get index to last page in mem_map array for rawbuf.
-		mapend =
-		    virt_to_page(s->tmpbuff +
-				 (PAGE_SIZE << s->buforder_tmpbuff) - 1);
-
-		// 2. mark each physical page in range as 'reserved'.
-		for (map = virt_to_page(s->tmpbuff); map <= mapend; map++)
-			mem_map_reserve(map);
-	}
-	if (db->type == CS_TYPE_DAC) {
-		if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE))
-			sample_shift++;
-		if (s->prop_dac.channels > 1)
-			sample_shift++;
-		bytespersec = s->prop_dac.rate << sample_shift;
-	} else			// CS_TYPE_ADC
-	{
-		if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE))
-			sample_shift++;
-		if (s->prop_adc.channels > 1)
-			sample_shift++;
-		bytespersec = s->prop_adc.rate << sample_shift;
-	}
-	bufs = PAGE_SIZE << db->buforder;
-
-
-#define INTERRUPT_RATE_MS       100	// Interrupt rate in milliseconds.
-	db->numfrag = 2;
-	temp1 = bytespersec / (1000 / INTERRUPT_RATE_MS);	// Nominal frag size(bytes/interrupt)
-	db->fragshift = 8;	// Min 256 bytes.
-	while (1 << db->fragshift < temp1)	// Calc power of 2 frag size.
-		db->fragshift += 1;
-	db->fragsize = 1 << db->fragshift;
-	db->dmasize = db->fragsize * 2;
-	db->fragsamples = db->fragsize >> sample_shift;	// # samples/fragment.
-
-// If the calculated size is larger than the allocated
-//  buffer, divide the allocated buffer into 2 fragments.
-	if (db->dmasize > bufs) {
-
-		db->numfrag = 2;	// Two fragments.
-		db->fragsize = bufs >> 1;	// Each 1/2 the alloc'ed buffer.
-		db->fragsamples = db->fragsize >> sample_shift;	// # samples/fragment.
-		db->dmasize = bufs;	// Use all the alloc'ed buffer.
-
-		db->fragshift = 0;	// Calculate 'fragshift'.
-		temp1 = db->fragsize;	// update_ptr() uses it 
-		while ((temp1 >>= 1) > 1)	// to calc 'total-bytes'
-			db->fragshift += 1;	// returned in DSP_GETI/OPTR. 
-	}
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: prog_dmabuf()-\n"));
-	CS_DBGOUT(CS_PARMS, 8,
-		  printk(KERN_INFO
-			 "cs4281: prog_dmabuf(): numfrag=%d fragsize=%d fragsamples=%d fragshift=%d bufs=%d fmt=0x%x ch=%d\n",
-			 db->numfrag, db->fragsize, db->fragsamples,
-			 db->fragshift, bufs,
-			 (db->type ==
-			  CS_TYPE_DAC) ? s->prop_dac.fmt : s->prop_adc.fmt,
-			 (db->type ==
-			  CS_TYPE_DAC) ? s->prop_dac.channels : s->
-			 prop_adc.channels));
-	return 0;
-}
-
-
-static int prog_dmabuf_adc(struct cs4281_state *s)
-{
-	unsigned long va;
-	unsigned count;
-	int c;
-	stop_adc(s);
-	s->dma_adc.type = CS_TYPE_ADC;
-	if ((c = prog_dmabuf(s, &s->dma_adc)))
-		return c;
-
-	if (s->dma_adc.rawbuf) {
-		memset(s->dma_adc.rawbuf,
-		       (s->prop_adc.
-			fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
-		       s->dma_adc.dmasize);
-	}
-	if (s->tmpbuff) {
-		memset(s->tmpbuff,
-		       (s->prop_adc.
-			fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
-		       PAGE_SIZE << s->buforder_tmpbuff);
-	}
-
-	va = virt_to_bus(s->dma_adc.rawbuf);
-
-	count = s->dma_adc.dmasize;
-
-	if (s->prop_adc.
-	    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))
-		    count /= 2;	// 16-bit.
-
-	if (s->prop_adc.channels > 1)
-		count /= 2;	// Assume stereo.
-
-	CS_DBGOUT(CS_WAVE_READ, 3, printk(KERN_INFO
-					  "cs4281: prog_dmabuf_adc(): count=%d va=0x%.8x\n",
-					  count, (unsigned) va));
-
-	writel(va, s->pBA0 + BA0_DBA1);	// Set buffer start address.
-	writel(count - 1, s->pBA0 + BA0_DBC1);	// Set count. 
-	s->dma_adc.ready = 1;
-	return 0;
-}
-
-
-static int prog_dmabuf_dac(struct cs4281_state *s)
-{
-	unsigned long va;
-	unsigned count;
-	int c;
-	stop_dac(s);
-	s->dma_dac.type = CS_TYPE_DAC;
-	if ((c = prog_dmabuf(s, &s->dma_dac)))
-		return c;
-	memset(s->dma_dac.rawbuf,
-	       (s->prop_dac.fmt & (AFMT_U8 | AFMT_U16_LE)) ? 0x80 : 0,
-	       s->dma_dac.dmasize);
-
-	va = virt_to_bus(s->dma_dac.rawbuf);
-
-	count = s->dma_dac.dmasize;
-	if (s->prop_dac.
-	    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE))
-		    count /= 2;	// 16-bit.
-
-	if (s->prop_dac.channels > 1)
-		count /= 2;	// Assume stereo.
-
-	writel(va, s->pBA0 + BA0_DBA0);	// Set buffer start address.
-	writel(count - 1, s->pBA0 + BA0_DBC0);	// Set count.             
-
-	CS_DBGOUT(CS_WAVE_WRITE, 3, printk(KERN_INFO
-					   "cs4281: prog_dmabuf_dac(): count=%d va=0x%.8x\n",
-					   count, (unsigned) va));
-
-	s->dma_dac.ready = 1;
-	return 0;
-}
-
-
-static void clear_advance(void *buf, unsigned bsize, unsigned bptr,
-			  unsigned len, unsigned char c)
-{
-	if (bptr + len > bsize) {
-		unsigned x = bsize - bptr;
-		memset(((char *) buf) + bptr, c, x);
-		bptr = 0;
-		len -= x;
-	}
-	CS_DBGOUT(CS_WAVE_WRITE, 4, printk(KERN_INFO
-					   "cs4281: clear_advance(): memset %d at 0x%.8x for %d size \n",
-					   (unsigned) c,
-					   (unsigned) ((char *) buf) +
-					   bptr, len));
-	memset(((char *) buf) + bptr, c, len);
-}
-
-
-
-// call with spinlock held! 
-static void cs4281_update_ptr(struct cs4281_state *s)
-{
-	int diff;
-	unsigned hwptr, va;
-
-	// update ADC pointer 
-	if (s->ena & FMODE_READ) {
-		hwptr = readl(s->pBA0 + BA0_DCA1);	// Read capture DMA address.
-		va = virt_to_bus(s->dma_adc.rawbuf);
-		hwptr -= (unsigned) va;
-		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;
-		if (s->dma_adc.count > s->dma_adc.dmasize)
-			s->dma_adc.count = s->dma_adc.dmasize;
-		if (s->dma_adc.mapped) {
-			if (s->dma_adc.count >=
-			    (signed) s->dma_adc.fragsize) wake_up(&s->
-								  dma_adc.
-								  wait);
-		} else {
-			if (s->dma_adc.count > 0)
-				wake_up(&s->dma_adc.wait);
-		}
-		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
-					      "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
-					      (unsigned) s,
-					      s->dma_adc.hwptr,
-					      s->dma_adc.total_bytes,
-					      s->dma_adc.count));
-	}
-	// update DAC pointer 
-	//
-	// check for end of buffer, means that we are going to wait for another interrupt
-	// to allow silence to fill the fifos on the part, to keep pops down to a minimum.
-	//
-	if (s->ena & FMODE_WRITE) {
-		hwptr = readl(s->pBA0 + BA0_DCA0);	// Read play DMA address.
-		va = virt_to_bus(s->dma_dac.rawbuf);
-		hwptr -= (unsigned) va;
-		diff =
-		    (s->dma_dac.dmasize + hwptr -
-		     s->dma_dac.hwptr) % s->dma_dac.dmasize;
-		s->dma_dac.hwptr = hwptr;
-		s->dma_dac.total_bytes += diff;
-		if (s->dma_dac.mapped) {
-			s->dma_dac.count += diff;
-			if (s->dma_dac.count >= s->dma_dac.fragsize) {
-				s->dma_dac.wakeup = 1;
-				wake_up(&s->dma_dac.wait);
-				if (s->dma_dac.count > s->dma_dac.dmasize)
-					s->dma_dac.count &=
-					    s->dma_dac.dmasize - 1;
-			}
-		} else {
-
-			s->dma_dac.count -= diff;
-			if (s->dma_dac.count <= 0) {
-				//
-				// fill with silence, and do not shut down the DAC.
-				// Continue to play silence until the _release.
-				//
-				CS_DBGOUT(CS_WAVE_WRITE, 6,
-					  printk(KERN_INFO
-						 "cs4281: cs4281_update_ptr(): memset %d at 0x%.8x for %d size \n",
-						 (unsigned) (s->prop_dac.
-							     fmt & (AFMT_U8
-								    |
-								    AFMT_U16_LE))
-						 ? 0x80 : 0,
-						 (unsigned) s->dma_dac.
-						 rawbuf,
-						 s->dma_dac.dmasize));
-				memset(s->dma_dac.rawbuf,
-				       (s->prop_dac.
-					fmt & (AFMT_U8 | AFMT_U16_LE)) ?
-				       0x80 : 0, s->dma_dac.dmasize);
-			} else if (s->dma_dac.count <=
-				   (signed) s->dma_dac.fragsize
-				   && !s->dma_dac.endcleared) {
-				clear_advance(s->dma_dac.rawbuf,
-					      s->dma_dac.dmasize,
-					      s->dma_dac.swptr,
-					      s->dma_dac.fragsize,
-					      (s->prop_dac.
-					       fmt & (AFMT_U8 |
-						      AFMT_U16_LE)) ? 0x80
-					      : 0);
-				s->dma_dac.endcleared = 1;
-			}
-			if (s->dma_dac.count < (signed) s->dma_dac.dmasize)
-				wake_up(&s->dma_dac.wait);
-		}
-		CS_DBGOUT(CS_PARMS, 8, printk(KERN_INFO
-					      "cs4281: cs4281_update_ptr(): s=0x%.8x hwptr=%d total_bytes=%d count=%d \n",
-					      (unsigned) s,
-					      s->dma_dac.hwptr,
-					      s->dma_dac.total_bytes,
-					      s->dma_dac.count));
-	}
-}
-
-
-// --------------------------------------------------------------------- 
-
-static void prog_codec(struct cs4281_state *s, unsigned type)
-{
-	unsigned long flags;
-	unsigned temp1, format;
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: prog_codec()+ \n"));
-
-	spin_lock_irqsave(&s->lock, flags);
-	if (type == CS_TYPE_ADC) {
-		temp1 = readl(s->pBA0 + BA0_DCR1);
-		writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR1);	// Stop capture DMA, if active.
-
-		// program sampling rates  
-		// Note, for CS4281, capture & play rates can be set independently.
-		cs4281_record_rate(s, s->prop_adc.rate);
-
-		// program ADC parameters 
-		format = DMRn_DMA | DMRn_AUTO | DMRn_TR_WRITE;
-		if (s->prop_adc.
-		    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) {	// 16-bit
-			if (s->prop_adc.fmt & (AFMT_S16_BE | AFMT_U16_BE))	// Big-endian?
-				format |= DMRn_BEND;
-			if (s->prop_adc.fmt & (AFMT_U16_LE | AFMT_U16_BE))
-				format |= DMRn_USIGN;	// Unsigned.      
-		} else
-			format |= DMRn_SIZE8 | DMRn_USIGN;	// 8-bit, unsigned
-		if (s->prop_adc.channels < 2)
-			format |= DMRn_MONO;
-
-		writel(format, s->pBA0 + BA0_DMR1);
-
-		CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO
-					      "cs4281: prog_codec(): adc %s %s %s rate=%d DMR0 format=0x%.8x\n",
-					      (format & DMRn_SIZE8) ? "8" :
-					      "16",
-					      (format & DMRn_USIGN) ?
-					      "Unsigned" : "Signed",
-					      (format & DMRn_MONO) ? "Mono"
-					      : "Stereo", s->prop_adc.rate,
-					      format));
-
-		s->ena &= ~FMODE_READ;	// not capturing data yet
-	}
-
-
-	if (type == CS_TYPE_DAC) {
-		temp1 = readl(s->pBA0 + BA0_DCR0);
-		writel(temp1 | DCRn_MSK, s->pBA0 + BA0_DCR0);	// Stop play DMA, if active.
-
-		// program sampling rates  
-		// Note, for CS4281, capture & play rates can be set independently.
-		cs4281_play_rate(s, s->prop_dac.rate);
-
-		// program DAC parameters 
-		format = DMRn_DMA | DMRn_AUTO | DMRn_TR_READ;
-		if (s->prop_dac.
-		    fmt & (AFMT_S16_LE | AFMT_U16_LE | AFMT_S16_BE | AFMT_U16_BE)) {	// 16-bit
-			if (s->prop_dac.fmt & (AFMT_S16_BE | AFMT_U16_BE))
-				format |= DMRn_BEND;	// Big Endian.
-			if (s->prop_dac.fmt & (AFMT_U16_LE | AFMT_U16_BE))
-				format |= DMRn_USIGN;	// Unsigned.      
-		} else
-			format |= DMRn_SIZE8 | DMRn_USIGN;	// 8-bit, unsigned
-
-		if (s->prop_dac.channels < 2)
-			format |= DMRn_MONO;
-
-		writel(format, s->pBA0 + BA0_DMR0);
-
-
-		CS_DBGOUT(CS_PARMS, 2, printk(KERN_INFO
-					      "cs4281: prog_codec(): dac %s %s %s rate=%d DMR0 format=0x%.8x\n",
-					      (format & DMRn_SIZE8) ? "8" :
-					      "16",
-					      (format & DMRn_USIGN) ?
-					      "Unsigned" : "Signed",
-					      (format & DMRn_MONO) ? "Mono"
-					      : "Stereo", s->prop_dac.rate,
-					      format));
-
-		s->ena &= ~FMODE_WRITE;	// not capturing data yet
-
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: prog_codec()- \n"));
-}
-
-
-// --------------------------------------------------------------------- 
-
-static const char invalid_magic[] =
-    KERN_CRIT "cs4281: invalid magic value\n";
-
-#define VALIDATE_STATE(s)                         \
-({                                                \
-        if (!(s) || (s)->magic != CS4281_MAGIC) { \
-                printk(invalid_magic);            \
-                return -ENXIO;                    \
-        }                                         \
-})
-
-// --------------------------------------------------------------------- 
-
-
-static int mixer_ioctl(struct cs4281_state *s, unsigned int cmd,
-		       unsigned long arg)
-{
-	// Index to mixer_src[] is value of AC97 Input Mux Select Reg.
-	// Value of array member is recording source Device ID Mask.
-	static const unsigned int mixer_src[8] = {
-		SOUND_MASK_MIC, SOUND_MASK_CD, 0, SOUND_MASK_LINE1,
-		SOUND_MASK_LINE, SOUND_MASK_VOLUME, 0, 0
-	};
-
-	// Index of mixtable1[] member is Device ID 
-	// and must be <= SOUND_MIXER_NRDEVICES.
-	// Value of array member is index into s->mix.vol[]
-	static const unsigned char mixtable1[SOUND_MIXER_NRDEVICES] = {
-		[SOUND_MIXER_PCM] = 1,	// voice 
-		[SOUND_MIXER_LINE1] = 2,	// AUX
-		[SOUND_MIXER_CD] = 3,	// CD 
-		[SOUND_MIXER_LINE] = 4,	// Line 
-		[SOUND_MIXER_SYNTH] = 5,	// FM
-		[SOUND_MIXER_MIC] = 6,	// Mic 
-		[SOUND_MIXER_SPEAKER] = 7,	// Speaker 
-		[SOUND_MIXER_RECLEV] = 8,	// Recording level 
-		[SOUND_MIXER_VOLUME] = 9	// Master Volume 
-	};
-
-
-	static const unsigned mixreg[] = {
-		BA0_AC97_PCM_OUT_VOLUME,
-		BA0_AC97_AUX_VOLUME,
-		BA0_AC97_CD_VOLUME,
-		BA0_AC97_LINE_IN_VOLUME
-	};
-	unsigned char l, r, rl, rr, vidx;
-	unsigned char attentbl[11] =
-	    { 63, 42, 26, 17, 14, 11, 8, 6, 4, 2, 0 };
-	unsigned temp1;
-	int i, val;
-
-	VALIDATE_STATE(s);
-	CS_DBGOUT(CS_FUNCTION, 4,
-		  printk(KERN_INFO
-			 "cs4281: mixer_ioctl(): s=0x%.8x cmd=0x%.8x\n",
-			 (unsigned) s, cmd));
-#if CSDEBUG
-	printioctl(cmd);
-#endif
-#if CSDEBUG_INTERFACE
-
-	if ((cmd == SOUND_MIXER_CS_GETDBGMASK) ||
-	    (cmd == SOUND_MIXER_CS_SETDBGMASK) ||
-	    (cmd == SOUND_MIXER_CS_GETDBGLEVEL) ||
-	    (cmd == SOUND_MIXER_CS_SETDBGLEVEL)) {
-		switch (cmd) {
-
-		case SOUND_MIXER_CS_GETDBGMASK:
-			return put_user(cs_debugmask,
-					(unsigned long *) arg);
-
-		case SOUND_MIXER_CS_GETDBGLEVEL:
-			return put_user(cs_debuglevel,
-					(unsigned long *) arg);
-
-		case SOUND_MIXER_CS_SETDBGMASK:
-			if (get_user(val, (unsigned long *) arg))
-				return -EFAULT;
-			cs_debugmask = val;
-			return 0;
-
-		case SOUND_MIXER_CS_SETDBGLEVEL:
-			if (get_user(val, (unsigned long *) arg))
-				return -EFAULT;
-			cs_debuglevel = val;
-			return 0;
-		default:
-			CS_DBGOUT(CS_ERROR, 1, printk(KERN_INFO
-						      "cs4281: mixer_ioctl(): ERROR unknown debug cmd\n"));
-			return 0;
-		}
-	}
-#endif
-
-	if (cmd == SOUND_MIXER_PRIVATE1) {
-		// enable/disable/query mixer preamp 
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		if (val != -1) {
-			cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
-			temp1 = val ? (temp1 | 0x40) : (temp1 & 0xffbf);
-			cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1);
-		}
-		cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
-		val = (temp1 & 0x40) ? 1 : 0;
-		return put_user(val, (int *) arg);
-	}
-	if (cmd == SOUND_MIXER_PRIVATE2) {
-		// enable/disable/query spatializer 
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		if (val != -1) {
-			temp1 = (val & 0x3f) >> 2;
-			cs4281_write_ac97(s, BA0_AC97_3D_CONTROL, temp1);
-			cs4281_read_ac97(s, BA0_AC97_GENERAL_PURPOSE,
-					 &temp1);
-			cs4281_write_ac97(s, BA0_AC97_GENERAL_PURPOSE,
-					  temp1 | 0x2000);
-		}
-		cs4281_read_ac97(s, BA0_AC97_3D_CONTROL, &temp1);
-		return put_user((temp1 << 2) | 3, (int *) arg);
-	}
-	if (cmd == SOUND_MIXER_INFO) {
-		mixer_info info;
-		strncpy(info.id, "CS4281", sizeof(info.id));
-		strncpy(info.name, "Crystal CS4281", sizeof(info.name));
-		info.modify_counter = s->mix.modcnt;
-		if (copy_to_user((void *) arg, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == SOUND_OLD_MIXER_INFO) {
-		_old_mixer_info info;
-		strncpy(info.id, "CS4281", sizeof(info.id));
-		strncpy(info.name, "Crystal CS4281", sizeof(info.name));
-		if (copy_to_user((void *) arg, &info, sizeof(info)))
-			return -EFAULT;
-		return 0;
-	}
-	if (cmd == OSS_GETVERSION)
-		return put_user(SOUND_VERSION, (int *) arg);
-
-	if (_IOC_TYPE(cmd) != 'M' || _SIOC_SIZE(cmd) != sizeof(int))
-		return -EINVAL;
-
-	// If ioctl has only the SIOC_READ bit(bit 31)
-	// on, process the only-read commands. 
-	if (_SIOC_DIR(cmd) == _SIOC_READ) {
-		switch (_IOC_NR(cmd)) {
-		case SOUND_MIXER_RECSRC:	// Arg contains a bit for each recording source 
-			cs4281_read_ac97(s, BA0_AC97_RECORD_SELECT,
-					 &temp1);
-			return put_user(mixer_src[temp1 & 7], (int *) arg);
-
-		case SOUND_MIXER_DEVMASK:	// Arg contains a bit for each supported device 
-			return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH |
-					SOUND_MASK_CD | SOUND_MASK_LINE |
-					SOUND_MASK_LINE1 | SOUND_MASK_MIC |
-					SOUND_MASK_VOLUME |
-					SOUND_MASK_RECLEV |
-					SOUND_MASK_SPEAKER, (int *) arg);
-
-		case SOUND_MIXER_RECMASK:	// Arg contains a bit for each supported recording source 
-			return put_user(SOUND_MASK_LINE | SOUND_MASK_MIC |
-					SOUND_MASK_CD | SOUND_MASK_VOLUME |
-					SOUND_MASK_LINE1, (int *) arg);
-
-		case SOUND_MIXER_STEREODEVS:	// Mixer channels supporting stereo 
-			return put_user(SOUND_MASK_PCM | SOUND_MASK_SYNTH |
-					SOUND_MASK_CD | SOUND_MASK_LINE |
-					SOUND_MASK_LINE1 | SOUND_MASK_MIC |
-					SOUND_MASK_VOLUME |
-					SOUND_MASK_RECLEV, (int *) arg);
-
-		case SOUND_MIXER_CAPS:
-			return put_user(SOUND_CAP_EXCL_INPUT, (int *) arg);
-
-		default:
-			i = _IOC_NR(cmd);
-			if (i >= SOUND_MIXER_NRDEVICES
-			    || !(vidx = mixtable1[i]))
-				return -EINVAL;
-			return put_user(s->mix.vol[vidx - 1], (int *) arg);
-		}
-	}
-	// If ioctl doesn't have both the SIOC_READ and 
-	// the SIOC_WRITE bit set, return invalid.
-	if (_SIOC_DIR(cmd) != (_SIOC_READ | _SIOC_WRITE))
-		return -EINVAL;
-
-	// Increment the count of volume writes.
-	s->mix.modcnt++;
-
-	// Isolate the command; it must be a write.
-	switch (_IOC_NR(cmd)) {
-
-	case SOUND_MIXER_RECSRC:	// Arg contains a bit for each recording source 
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		i = hweight32(val);	// i = # bits on in val.
-		if (i != 1)	// One & only 1 bit must be on.
-			return 0;
-		for (i = 0; i < sizeof(mixer_src) / sizeof(int); i++) {
-			if (val == mixer_src[i]) {
-				temp1 = (i << 8) | i;
-				cs4281_write_ac97(s,
-						  BA0_AC97_RECORD_SELECT,
-						  temp1);
-				return 0;
-			}
-		}
-		return 0;
-
-	case SOUND_MIXER_VOLUME:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		l = val & 0xff;
-		if (l > 100)
-			l = 100;	// Max soundcard.h vol is 100.
-		if (l < 6) {
-			rl = 63;
-			l = 0;
-		} else
-			rl = attentbl[(10 * l) / 100];	// Convert 0-100 vol to 63-0 atten.
-
-		r = (val >> 8) & 0xff;
-		if (r > 100)
-			r = 100;	// Max right volume is 100, too
-		if (r < 6) {
-			rr = 63;
-			r = 0;
-		} else
-			rr = attentbl[(10 * r) / 100];	// Convert volume to attenuation.
-
-		if ((rl > 60) && (rr > 60))	// If both l & r are 'low',          
-			temp1 = 0x8000;	//  turn on the mute bit.
-		else
-			temp1 = 0;
-
-		temp1 |= (rl << 8) | rr;
-
-		cs4281_write_ac97(s, BA0_AC97_MASTER_VOLUME, temp1);
-		cs4281_write_ac97(s, BA0_AC97_HEADPHONE_VOLUME, temp1);
-
-#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);
-
-	case SOUND_MIXER_SPEAKER:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		l = val & 0xff;
-		if (l > 100)
-			l = 100;
-		if (l < 3) {
-			rl = 0;
-			l = 0;
-		} else {
-			rl = (l * 2 - 5) / 13;	// Convert 0-100 range to 0-15.
-			l = (rl * 13 + 5) / 2;
-		}
-
-		if (rl < 3) {
-			temp1 = 0x8000;
-			rl = 0;
-		} else
-			temp1 = 0;
-		rl = 15 - rl;	// Convert volume to attenuation.
-		temp1 |= rl << 1;
-		cs4281_write_ac97(s, BA0_AC97_PC_BEEP_VOLUME, temp1);
-
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-		s->mix.vol[6] = l << 8;
-#else
-		s->mix.vol[6] = val;
-#endif
-		return put_user(s->mix.vol[6], (int *) arg);
-
-	case SOUND_MIXER_RECLEV:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		l = val & 0xff;
-		if (l > 100)
-			l = 100;
-		r = (val >> 8) & 0xff;
-		if (r > 100)
-			r = 100;
-		rl = (l * 2 - 5) / 13;	// Convert 0-100 scale to 0-15.
-		rr = (r * 2 - 5) / 13;
-		if (rl < 3 && rr < 3)
-			temp1 = 0x8000;
-		else
-			temp1 = 0;
-
-		temp1 = temp1 | (rl << 8) | rr;
-		cs4281_write_ac97(s, BA0_AC97_RECORD_GAIN, temp1);
-
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-		s->mix.vol[7] = ((unsigned int) r << 8) | l;
-#else
-		s->mix.vol[7] = val;
-#endif
-		return put_user(s->mix.vol[7], (int *) arg);
-
-	case SOUND_MIXER_MIC:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		l = val & 0xff;
-		if (l > 100)
-			l = 100;
-		if (l < 1) {
-			l = 0;
-			rl = 0;
-		} else {
-			rl = ((unsigned) l * 5 - 4) / 16;	// Convert 0-100 range to 0-31.
-			l = (rl * 16 + 4) / 5;
-		}
-		cs4281_read_ac97(s, BA0_AC97_MIC_VOLUME, &temp1);
-		temp1 &= 0x40;	// Isolate 20db gain bit.
-		if (rl < 3) {
-			temp1 |= 0x8000;
-			rl = 0;
-		}
-		rl = 31 - rl;	// Convert volume to attenuation.
-		temp1 |= rl;
-		cs4281_write_ac97(s, BA0_AC97_MIC_VOLUME, temp1);
-
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-		s->mix.vol[5] = val << 8;
-#else
-		s->mix.vol[5] = val;
-#endif
-		return put_user(s->mix.vol[5], (int *) arg);
-
-
-	case SOUND_MIXER_SYNTH:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		l = val & 0xff;
-		if (l > 100)
-			l = 100;
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		r = (val >> 8) & 0xff;
-		if (r > 100)
-			r = 100;
-		rl = (l * 2 - 11) / 3;	// Convert 0-100 range to 0-63.
-		rr = (r * 2 - 11) / 3;
-		if (rl < 3)	// If l is low, turn on
-			temp1 = 0x0080;	//  the mute bit.
-		else
-			temp1 = 0;
-
-		rl = 63 - rl;	// Convert vol to attenuation.
-		writel(temp1 | rl, s->pBA0 + BA0_FMLVC);
-		if (rr < 3)	//  If rr is low, turn on
-			temp1 = 0x0080;	//   the mute bit.
-		else
-			temp1 = 0;
-		rr = 63 - rr;	// Convert vol to attenuation.
-		writel(temp1 | rr, s->pBA0 + BA0_FMRVC);
-
-#ifdef OSS_DOCUMENTED_MIXER_SEMANTICS
-		s->mix.vol[4] = (r << 8) | l;
-#else
-		s->mix.vol[4] = val;
-#endif
-		return put_user(s->mix.vol[4], (int *) arg);
-
-
-	default:
-		CS_DBGOUT(CS_IOCTL, 4, printk(KERN_INFO
-					      "cs4281: mixer_ioctl(): default\n"));
-
-		i = _IOC_NR(cmd);
-		if (i >= SOUND_MIXER_NRDEVICES || !(vidx = mixtable1[i]))
-			return -EINVAL;
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		l = val & 0xff;
-		if (l > 100)
-			l = 100;
-		if (l < 1) {
-			l = 0;
-			rl = 31;
-		} else
-			rl = (attentbl[(l * 10) / 100]) >> 1;
-
-		r = (val >> 8) & 0xff;
-		if (r > 100)
-			r = 100;
-		if (r < 1) {
-			r = 0;
-			rr = 31;
-		} else
-			rr = (attentbl[(r * 10) / 100]) >> 1;
-		if ((rl > 30) && (rr > 30))
-			temp1 = 0x8000;
-		else
-			temp1 = 0;
-		temp1 = temp1 | (rl << 8) | rr;
-		cs4281_write_ac97(s, mixreg[vidx - 1], temp1);
-
-#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);
-	}
-}
-
-
-// --------------------------------------------------------------------- 
-
-static loff_t cs4281_llseek(struct file *file, loff_t offset, int origin)
-{
-	return -ESPIPE;
-}
-
-
-// --------------------------------------------------------------------- 
-
-static int cs4281_open_mixdev(struct inode *inode, struct file *file)
-{
-	int minor = MINOR(inode->i_rdev);
-	struct cs4281_state *s = devs;
-
-	while (s && s->dev_mixer != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
-	VALIDATE_STATE(s);
-	file->private_data = s;
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-
-static int cs4281_release_mixdev(struct inode *inode, struct file *file)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-
-	VALIDATE_STATE(s);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-
-static int cs4281_ioctl_mixdev(struct inode *inode, struct file *file,
-			       unsigned int cmd, unsigned long arg)
-{
-	return mixer_ioctl((struct cs4281_state *) file->private_data, cmd,
-			   arg);
-}
-
-
-// ******************************************************************************************
-//   Mixer file operations struct.
-// ******************************************************************************************
-static /*const */ struct file_operations cs4281_mixer_fops = {
-	llseek:cs4281_llseek,
-	ioctl:cs4281_ioctl_mixdev,
-	open:cs4281_open_mixdev,
-	release:cs4281_release_mixdev,
-};
-
-// --------------------------------------------------------------------- 
-
-
-static int drain_adc(struct cs4281_state *s, int nonblock)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int count;
-	unsigned tmo;
-
-	if (s->dma_adc.mapped)
-		return 0;
-	add_wait_queue(&s->dma_adc.wait, &wait);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&s->lock, flags);
-		count = s->dma_adc.count;
-		CS_DBGOUT(CS_FUNCTION, 2,
-			  printk(KERN_INFO "cs4281: drain_adc() %d\n",
-				 count));
-		spin_unlock_irqrestore(&s->lock, flags);
-		if (count <= 0) {
-			CS_DBGOUT(CS_FUNCTION, 2,
-				  printk(KERN_INFO
-					 "cs4281: drain_adc() count<0\n"));
-			break;
-		}
-		if (signal_pending(current))
-			break;
-		if (nonblock) {
-			remove_wait_queue(&s->dma_adc.wait, &wait);
-			current->state = TASK_RUNNING;
-			return -EBUSY;
-		}
-		tmo =
-		    3 * HZ * (count +
-			      s->dma_adc.fragsize) / 2 / s->prop_adc.rate;
-		if (s->prop_adc.fmt & (AFMT_S16_LE | AFMT_U16_LE))
-			tmo >>= 1;
-		if (s->prop_adc.channels > 1)
-			tmo >>= 1;
-		if (!schedule_timeout(tmo + 1))
-			printk(KERN_DEBUG "cs4281: dma timed out??\n");
-	}
-	remove_wait_queue(&s->dma_adc.wait, &wait);
-	current->state = TASK_RUNNING;
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-static int drain_dac(struct cs4281_state *s, int nonblock)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int count;
-	unsigned tmo;
-
-	if (s->dma_dac.mapped)
-		return 0;
-	add_wait_queue(&s->dma_dac.wait, &wait);
-	for (;;) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_lock_irqsave(&s->lock, flags);
-		count = s->dma_dac.count;
-		spin_unlock_irqrestore(&s->lock, flags);
-		if (count <= 0)
-			break;
-		if (signal_pending(current))
-			break;
-		if (nonblock) {
-			remove_wait_queue(&s->dma_dac.wait, &wait);
-			current->state = TASK_RUNNING;
-			return -EBUSY;
-		}
-		tmo =
-		    3 * HZ * (count +
-			      s->dma_dac.fragsize) / 2 / s->prop_dac.rate;
-		if (s->prop_dac.fmt & (AFMT_S16_LE | AFMT_U16_LE))
-			tmo >>= 1;
-		if (s->prop_dac.channels > 1)
-			tmo >>= 1;
-		if (!schedule_timeout(tmo + 1))
-			printk(KERN_DEBUG "cs4281: dma timed out??\n");
-	}
-	remove_wait_queue(&s->dma_dac.wait, &wait);
-	current->state = TASK_RUNNING;
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-	return 0;
-}
-
-//****************************************************************************
-//
-// CopySamples copies 16-bit stereo samples from the source to the
-// destination, possibly converting down to either 8-bit or mono or both.
-// count specifies the number of output bytes to write.
-//
-//  Arguments:
-//
-//  dst             - Pointer to a destination buffer.
-//  src             - Pointer to a source buffer
-//  count           - The number of bytes to copy into the destination buffer.
-//  iChannels       - Stereo - 2
-//                    Mono   - 1
-//  fmt             - AFMT_xxx (soundcard.h formats)
-//
-// NOTES: only call this routine for conversion to 8bit from 16bit
-//
-//****************************************************************************
-static void CopySamples(char *dst, char *src, int count, int iChannels,
-			unsigned fmt)
-{
-
-	unsigned short *psSrc;
-	long lAudioSample;
-
-	CS_DBGOUT(CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: CopySamples()+ "));
-	CS_DBGOUT(CS_WAVE_READ, 8,
-		  printk(KERN_INFO
-			 " dst=0x%x src=0x%x count=%d iChannels=%d fmt=0x%x\n",
-			 (unsigned) dst, (unsigned) src, (unsigned) count,
-			 (unsigned) iChannels, (unsigned) fmt));
-
-	// Gershwin does format conversion in hardware so normally
-	// we don't do any host based coversion. The data formatter
-	// truncates 16 bit data to 8 bit and that causes some hiss.
-	// We have already forced the HW to do 16 bit sampling and 
-	// 2 channel so that we can use software to round instead 
-	// of truncate
-
-	//
-	// See if the data should be output as 8-bit unsigned stereo.
-	//
-	if ((iChannels == 2) && (fmt & AFMT_U8)) {
-		//
-		// Convert each 16-bit unsigned stereo sample to 8-bit unsigned 
-		// stereo using rounding.
-		//
-		psSrc = (unsigned short *) src;
-		count = count / 2;
-		while (count--) {
-			lAudioSample = (long) psSrc[count] + (long) 0x80;
-			if (lAudioSample > 0xffff) {
-				lAudioSample = 0xffff;
-			}
-			dst[count] = (char) (lAudioSample >> 8);
-		}
-	}
-	//
-	// check for 8-bit signed stereo.
-	//
-	else if ((iChannels == 2) && (fmt & AFMT_S8)) {
-		//
-		// Convert each 16-bit stereo sample to 8-bit stereo using rounding.
-		//
-		psSrc = (short *) src;
-		while (count--) {
-			lAudioSample =
-			    (((long) psSrc[0] + (long) psSrc[1]) / 2);
-			psSrc += 2;
-			*dst++ = (char) ((short) lAudioSample >> 8);
-		}
-	}
-	//
-	// See if the data should be output at 8-bit unsigned mono.
-	//
-	else if ((iChannels == 1) && (fmt & AFMT_U8)) {
-		//
-		// Convert each 16-bit unsigned mono sample to 8-bit unsigned
-		// mono using rounding.
-		//
-
-		psSrc = (short *) src;
-		while (count--) {
-			lAudioSample = (long) *psSrc++ + (long) 0x80;
-			if (lAudioSample > 0x7fff) {
-				lAudioSample = 0x7fff;
-			}
-			//
-			// Convert Signed to Unsigned.
-			//
-
-			*dst++ =
-			    (unsigned
-			     char) (((short) lAudioSample +
-				     (short) 0x8000) >> 8);
-		}
-	}
-	//
-	// Otherwise, the data should be output as 8-bit signed mono.
-	//
-	else if ((iChannels == 1) && (fmt & AFMT_S8)) {
-		//
-		// Convert each 16-bit signed mono sample to 8-bit signed mono 
-		// using rounding.
-		//
-		psSrc = (short *) src;
-		while (count--) {
-			lAudioSample =
-			    (((long) psSrc[0] + (long) psSrc[1]) / 2);
-			if (lAudioSample > 0x7fff) {
-				lAudioSample = 0x7fff;
-			}
-			psSrc += 2;
-			*dst++ = (char) ((short) lAudioSample >> 8);
-		}
-	}
-}
-
-//
-// cs_copy_to_user()
-// replacement for the standard copy_to_user, to allow for a conversion from
-// 16 bit to 8 bit if the record conversion is active.  the cs4281 has some
-// issues with 8 bit capture, so the driver always captures data in 16 bit
-// and then if the user requested 8 bit, converts from 16 to 8 bit.
-//
-static unsigned cs_copy_to_user(struct cs4281_state *s, void *dest,
-				unsigned *hwsrc, unsigned cnt,
-				unsigned *copied)
-{
-	void *src = hwsrc;	//default to the standard destination buffer addr
-
-	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO
-					 "cs_copy_to_user()+ fmt=0x%x fmt_o=0x%x cnt=%d dest=0x%.8x\n",
-					 s->prop_adc.fmt,
-					 s->prop_adc.fmt_original,
-					 (unsigned) cnt, (unsigned) dest));
-
-	if (cnt > s->dma_adc.dmasize) {
-		cnt = s->dma_adc.dmasize;
-	}
-	if (!cnt) {
-		*copied = 0;
-		return 0;
-	}
-	if (s->conversion) {
-		if (!s->tmpbuff) {
-			*copied = cnt / 2;
-			return 0;
-		}
-		CopySamples(s->tmpbuff, (void *) hwsrc, cnt,
-			    (unsigned) s->prop_adc.channels,
-			    s->prop_adc.fmt_original);
-		src = s->tmpbuff;
-		cnt = cnt / 2;
-	}
-
-	if (copy_to_user(dest, src, cnt)) {
-		*copied = 0;
-		return -EFAULT;
-	}
-	*copied = cnt;
-	CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO
-					 "cs4281: cs_copy_to_user()- copied bytes is %d \n",
-					 cnt));
-	return 0;
-}
-
-// --------------------------------------------------------------------- 
-
-static ssize_t cs4281_read(struct file *file, char *buffer, size_t count,
-			   loff_t * ppos)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned swptr;
-	int cnt;
-	unsigned copied = 0;
-
-	CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
-		  printk(KERN_INFO "cs4281: cs4281_read()+ %d \n", count));
-
-	VALIDATE_STATE(s);
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	if (s->dma_adc.mapped)
-		return -ENXIO;
-	if (!s->dma_adc.ready && (ret = prog_dmabuf_adc(s)))
-		return ret;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	ret = 0;
-//
-// "count" is the amount of bytes to read (from app), is decremented each loop
-//      by the amount of bytes that have been returned to the user buffer.
-// "cnt" is the running total of each read from the buffer (changes each loop)
-// "buffer" points to the app's buffer
-// "ret" keeps a running total of the amount of bytes that have been copied
-//      to the user buffer.
-// "copied" is the total bytes copied into the user buffer for each loop.
-//
-	while (count > 0) {
-		CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO
-						  "_read() count>0 count=%d .count=%d .swptr=%d .hwptr=%d \n",
-						  count, s->dma_adc.count,
-						  s->dma_adc.swptr,
-						  s->dma_adc.hwptr));
-		spin_lock_irqsave(&s->lock, flags);
-
-		// get the current copy point of the sw buffer
-		swptr = s->dma_adc.swptr;
-
-		// cnt is the amount of unread bytes from the end of the 
-		// hw buffer to the current sw pointer
-		cnt = s->dma_adc.dmasize - swptr;
-
-		// dma_adc.count is the current total bytes that have not been read.
-		// if the amount of unread bytes from the current sw pointer to the
-		// end of the buffer is greater than the current total bytes that
-		// have not been read, then set the "cnt" (unread bytes) to the
-		// amount of unread bytes.  
-
-		if (s->dma_adc.count < cnt)
-			cnt = s->dma_adc.count;
-		spin_unlock_irqrestore(&s->lock, flags);
-		//
-		// if we are converting from 8/16 then we need to copy
-		// twice the number of 16 bit bytes then 8 bit bytes.
-		// 
-		if (s->conversion) {
-			if (cnt > (count * 2))
-				cnt = (count * 2);
-		} else {
-			if (cnt > count)
-				cnt = count;
-		}
-		//
-		// "cnt" NOW is the smaller of the amount that will be read,
-		// and the amount that is requested in this read (or partial).
-		// if there are no bytes in the buffer to read, then start the
-		// ADC and wait for the interrupt handler to wake us up.
-		//
-		if (cnt <= 0) {
-
-			// start up the dma engine and then continue back to the top of
-			// the loop when wake up occurs.
-			start_adc(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_adc.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
-			continue;
-		}
-		// there are bytes in the buffer to read.
-		// copy from the hw buffer over to the user buffer.
-		// user buffer is designated by "buffer"
-		// virtual address to copy from is rawbuf+swptr
-		// the "cnt" is the number of bytes to read.
-
-		CS_DBGOUT(CS_WAVE_READ, 2, printk(KERN_INFO
-						  "_read() copy_to cnt=%d count=%d ",
-						  cnt, count));
-		CS_DBGOUT(CS_WAVE_READ, 8,
-			  printk(KERN_INFO
-				 " .dmasize=%d .count=%d buffer=0x%.8x ret=%d\n",
-				 s->dma_adc.dmasize, s->dma_adc.count,
-				 (unsigned) buffer, ret));
-
-		if (cs_copy_to_user
-		    (s, buffer, s->dma_adc.rawbuf + swptr, cnt, &copied))
-			return ret ? ret : -EFAULT;
-		swptr = (swptr + cnt) % s->dma_adc.dmasize;
-		spin_lock_irqsave(&s->lock, flags);
-		s->dma_adc.swptr = swptr;
-		s->dma_adc.count -= cnt;
-		spin_unlock_irqrestore(&s->lock, flags);
-		count -= copied;
-		buffer += copied;
-		ret += copied;
-		start_adc(s);
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_WAVE_READ, 2,
-		  printk(KERN_INFO "cs4281: cs4281_read()- %d\n", ret));
-	return ret;
-}
-
-
-static ssize_t cs4281_write(struct file *file, const char *buffer,
-			    size_t count, loff_t * ppos)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned swptr;
-	int cnt;
-
-	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
-		  printk(KERN_INFO "cs4281: cs4281_write()+ count=%d\n",
-			 count));
-	VALIDATE_STATE(s);
-
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	if (s->dma_dac.mapped)
-		return -ENXIO;
-	if (!s->dma_dac.ready && (ret = prog_dmabuf_dac(s)))
-		return ret;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	ret = 0;
-	while (count > 0) {
-		spin_lock_irqsave(&s->lock, flags);
-		if (s->dma_dac.count < 0) {
-			s->dma_dac.count = 0;
-			s->dma_dac.swptr = s->dma_dac.hwptr;
-		}
-		swptr = s->dma_dac.swptr;
-		cnt = s->dma_dac.dmasize - swptr;
-		if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
-			cnt = s->dma_dac.dmasize - s->dma_dac.count;
-		spin_unlock_irqrestore(&s->lock, flags);
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-
-			start_dac(s);
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->dma_dac.wait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
-			continue;
-		}
-		if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
-		swptr = (swptr + cnt) % s->dma_dac.dmasize;
-		spin_lock_irqsave(&s->lock, flags);
-		s->dma_dac.swptr = swptr;
-		s->dma_dac.count += cnt;
-		s->dma_dac.endcleared = 0;
-		spin_unlock_irqrestore(&s->lock, flags);
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		start_dac(s);
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE, 2,
-		  printk(KERN_INFO "cs4281: cs4281_write()- %d\n", ret));
-	return ret;
-}
-
-
-static unsigned int cs4281_poll(struct file *file,
-				struct poll_table_struct *wait)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
-		  printk(KERN_INFO "cs4281: cs4281_poll()+\n"));
-	VALIDATE_STATE(s);
-	if (file->f_mode & FMODE_WRITE) {
-		CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_poll() wait on FMODE_WRITE\n"));
-		if (!s->dma_dac.ready && prog_dmabuf_dac(s))
-			return 0;
-		poll_wait(file, &s->dma_dac.wait, wait);
-	}
-	if (file->f_mode & FMODE_READ) {
-		CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_poll() wait on FMODE_READ\n"));
-		if (!s->dma_adc.ready && prog_dmabuf_adc(s))
-			return 0;
-		poll_wait(file, &s->dma_adc.wait, wait);
-	}
-
-	spin_lock_irqsave(&s->lock, flags);
-	cs4281_update_ptr(s);
-	if (file->f_mode & FMODE_WRITE) {
-		if (s->dma_dac.mapped) {
-			if (s->dma_dac.count >=
-			    (signed) s->dma_dac.fragsize) {
-				if (s->dma_dac.wakeup)
-					mask |= POLLOUT | POLLWRNORM;
-				else
-					mask = 0;
-				s->dma_dac.wakeup = 0;
-			}
-		} else {
-			if ((signed) s->dma_dac.dmasize > s->dma_dac.count)
-				mask |= POLLOUT | POLLWRNORM;
-		}
-	} else if (file->f_mode & FMODE_READ) {
-		if (s->dma_adc.mapped) {
-			if (s->dma_adc.count >=
-			    (signed) s->dma_adc.fragsize)
-				mask |= POLLIN | POLLRDNORM;
-		} else {
-			if (s->dma_adc.count > 0)
-				mask |= POLLIN | POLLRDNORM;
-		}
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	CS_DBGOUT(CS_FUNCTION | CS_WAVE_WRITE | CS_WAVE_READ, 4,
-		  printk(KERN_INFO "cs4281: cs4281_poll()- 0x%.8x\n",
-			 mask));
-	return mask;
-}
-
-
-static int cs4281_mmap(struct file *file, struct vm_area_struct *vma)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	struct dmabuf *db;
-	int ret;
-	unsigned long size;
-
-	CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4,
-		  printk(KERN_INFO "cs4281: cs4281_mmap()+\n"));
-
-	VALIDATE_STATE(s);
-	if (vma->vm_flags & VM_WRITE) {
-		if ((ret = prog_dmabuf_dac(s)) != 0)
-			return ret;
-		db = &s->dma_dac;
-	} else if (vma->vm_flags & VM_READ) {
-		if ((ret = prog_dmabuf_adc(s)) != 0)
-			return ret;
-		db = &s->dma_adc;
-	} else
-		return -EINVAL;
-//
-// only support PLAYBACK for now
-//
-	db = &s->dma_dac;
-
-	if (vma->vm_pgoff != 0)
-		return -EINVAL;
-	size = vma->vm_end - vma->vm_start;
-	if (size > (PAGE_SIZE << db->buforder))
-		return -EINVAL;
-	if (remap_page_range
-	    (vma->vm_start, virt_to_phys(db->rawbuf), size,
-	     vma->vm_page_prot)) return -EAGAIN;
-	db->mapped = 1;
-
-	CS_DBGOUT(CS_FUNCTION | CS_PARMS | CS_OPEN, 4,
-		  printk(KERN_INFO "cs4281: cs4281_mmap()- 0 size=%d\n",
-			 (unsigned) size));
-
-	return 0;
-}
-
-
-static int cs4281_ioctl(struct inode *inode, struct file *file,
-			unsigned int cmd, unsigned long arg)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	unsigned long flags;
-	audio_buf_info abinfo;
-	count_info cinfo;
-	int val, mapped, ret;
-
-	CS_DBGOUT(CS_FUNCTION, 4,
-		  printk(KERN_INFO
-			 "cs4281: cs4281_ioctl(): file=0x%.8x cmd=0x%.8x\n",
-			 (unsigned) file, cmd));
-#if CSDEBUG
-	printioctl(cmd);
-#endif
-	VALIDATE_STATE(s);
-	mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
-	    ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
-	switch (cmd) {
-	case OSS_GETVERSION:
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4, printk(KERN_INFO
-							 "cs4281: cs4281_ioctl(): SOUND_VERSION=0x%.8x\n",
-							 SOUND_VERSION));
-		return put_user(SOUND_VERSION, (int *) arg);
-
-	case SNDCTL_DSP_SYNC:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_SYNC\n"));
-		if (file->f_mode & FMODE_WRITE)
-			return drain_dac(s,
-					 0 /*file->f_flags & O_NONBLOCK */
-					 );
-		return 0;
-
-	case SNDCTL_DSP_SETDUPLEX:
-		return 0;
-
-	case SNDCTL_DSP_GETCAPS:
-		return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |
-				DSP_CAP_TRIGGER | DSP_CAP_MMAP,
-				(int *) arg);
-
-	case SNDCTL_DSP_RESET:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_RESET\n"));
-		if (file->f_mode & FMODE_WRITE) {
-			stop_dac(s);
-			synchronize_irq();
-			s->dma_dac.swptr = s->dma_dac.hwptr =
-			    s->dma_dac.count = s->dma_dac.total_bytes =
-			    s->dma_dac.blocks = s->dma_dac.wakeup = 0;
-			prog_codec(s, CS_TYPE_DAC);
-		}
-		if (file->f_mode & FMODE_READ) {
-			stop_adc(s);
-			synchronize_irq();
-			s->dma_adc.swptr = s->dma_adc.hwptr =
-			    s->dma_adc.count = s->dma_adc.total_bytes =
-			    s->dma_adc.blocks = s->dma_dac.wakeup = 0;
-			prog_codec(s, CS_TYPE_ADC);
-		}
-		return 0;
-
-	case SNDCTL_DSP_SPEED:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_SPEED val=%d\n",
-				 val));
-		//
-		// support independent capture and playback channels
-		// assume that the file mode bit determines the 
-		// direction of the data flow.
-		//
-		if (file->f_mode & FMODE_READ) {
-			if (val >= 0) {
-				stop_adc(s);
-				s->dma_adc.ready = 0;
-				// program sampling rates 
-				if (val > 48000)
-					val = 48000;
-				if (val < 6300)
-					val = 6300;
-				s->prop_adc.rate = val;
-				prog_codec(s, CS_TYPE_ADC);
-			}
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			if (val >= 0) {
-				stop_dac(s);
-				s->dma_dac.ready = 0;
-				// program sampling rates 
-				if (val > 48000)
-					val = 48000;
-				if (val < 6300)
-					val = 6300;
-				s->prop_dac.rate = val;
-				prog_codec(s, CS_TYPE_DAC);
-			}
-		}
-
-		if (file->f_mode & FMODE_WRITE)
-			val = s->prop_dac.rate;
-		else if (file->f_mode & FMODE_READ)
-			val = s->prop_adc.rate;
-
-		return put_user(val, (int *) arg);
-
-	case SNDCTL_DSP_STEREO:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_STEREO val=%d\n",
-				 val));
-		if (file->f_mode & FMODE_READ) {
-			stop_adc(s);
-			s->dma_adc.ready = 0;
-			s->prop_adc.channels = val ? 2 : 1;
-			prog_codec(s, CS_TYPE_ADC);
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			stop_dac(s);
-			s->dma_dac.ready = 0;
-			s->prop_dac.channels = val ? 2 : 1;
-			prog_codec(s, CS_TYPE_DAC);
-		}
-		return 0;
-
-	case SNDCTL_DSP_CHANNELS:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_CHANNELS val=%d\n",
-				 val));
-		if (val != 0) {
-			if (file->f_mode & FMODE_READ) {
-				stop_adc(s);
-				s->dma_adc.ready = 0;
-				if (val >= 2)
-					s->prop_adc.channels = 2;
-				else
-					s->prop_adc.channels = 1;
-				prog_codec(s, CS_TYPE_ADC);
-			}
-			if (file->f_mode & FMODE_WRITE) {
-				stop_dac(s);
-				s->dma_dac.ready = 0;
-				if (val >= 2)
-					s->prop_dac.channels = 2;
-				else
-					s->prop_dac.channels = 1;
-				prog_codec(s, CS_TYPE_DAC);
-			}
-		}
-
-		if (file->f_mode & FMODE_WRITE)
-			val = s->prop_dac.channels;
-		else if (file->f_mode & FMODE_READ)
-			val = s->prop_adc.channels;
-
-		return put_user(val, (int *) arg);
-
-	case SNDCTL_DSP_GETFMTS:	// Returns a mask 
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_GETFMT val=0x%.8x\n",
-				 AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
-				 AFMT_U8));
-		return put_user(AFMT_S16_LE | AFMT_U16_LE | AFMT_S8 |
-				AFMT_U8, (int *) arg);
-
-	case SNDCTL_DSP_SETFMT:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_SETFMT val=0x%.8x\n",
-				 val));
-		if (val != AFMT_QUERY) {
-			if (file->f_mode & FMODE_READ) {
-				stop_adc(s);
-				s->dma_adc.ready = 0;
-				if (val != AFMT_S16_LE
-				    && val != AFMT_U16_LE && val != AFMT_S8
-				    && val != AFMT_U8)
-					val = AFMT_U8;
-				s->prop_adc.fmt = val;
-				s->prop_adc.fmt_original = s->prop_adc.fmt;
-				prog_codec(s, CS_TYPE_ADC);
-			}
-			if (file->f_mode & FMODE_WRITE) {
-				stop_dac(s);
-				s->dma_dac.ready = 0;
-				if (val != AFMT_S16_LE
-				    && val != AFMT_U16_LE && val != AFMT_S8
-				    && val != AFMT_U8)
-					val = AFMT_U8;
-				s->prop_dac.fmt = val;
-				s->prop_dac.fmt_original = s->prop_dac.fmt;
-				prog_codec(s, CS_TYPE_DAC);
-			}
-		} else {
-			if (file->f_mode & FMODE_WRITE)
-				val = s->prop_dac.fmt_original;
-			else if (file->f_mode & FMODE_READ)
-				val = s->prop_adc.fmt_original;
-		}
-		CS_DBGOUT(CS_IOCTL | CS_PARMS, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_SETFMT return val=0x%.8x\n",
-				 val));
-		return put_user(val, (int *) arg);
-
-	case SNDCTL_DSP_POST:
-		CS_DBGOUT(CS_IOCTL, 4,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_ioctl(): DSP_POST\n"));
-		return 0;
-
-	case SNDCTL_DSP_GETTRIGGER:
-		val = 0;
-		if (file->f_mode & s->ena & FMODE_READ)
-			val |= PCM_ENABLE_INPUT;
-		if (file->f_mode & s->ena & FMODE_WRITE)
-			val |= PCM_ENABLE_OUTPUT;
-		return put_user(val, (int *) arg);
-
-	case SNDCTL_DSP_SETTRIGGER:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		if (file->f_mode & FMODE_READ) {
-			if (val & PCM_ENABLE_INPUT) {
-				if (!s->dma_adc.ready
-				    && (ret = prog_dmabuf_adc(s)))
-					return ret;
-				start_adc(s);
-			} else
-				stop_adc(s);
-		}
-		if (file->f_mode & FMODE_WRITE) {
-			if (val & PCM_ENABLE_OUTPUT) {
-				if (!s->dma_dac.ready
-				    && (ret = prog_dmabuf_dac(s)))
-					return ret;
-				start_dac(s);
-			} else
-				stop_dac(s);
-		}
-		return 0;
-
-	case SNDCTL_DSP_GETOSPACE:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
-			return val;
-		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s);
-		abinfo.fragsize = s->dma_dac.fragsize;
-		if (s->dma_dac.mapped)
-			abinfo.bytes = s->dma_dac.dmasize;
-		else
-			abinfo.bytes =
-			    s->dma_dac.dmasize - s->dma_dac.count;
-		abinfo.fragstotal = s->dma_dac.numfrag;
-		abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;
-		CS_DBGOUT(CS_FUNCTION | CS_PARMS, 4, printk(KERN_INFO
-							    "cs4281: cs4281_ioctl(): GETOSPACE .fragsize=%d .bytes=%d .fragstotal=%d .fragments=%d\n",
-							    abinfo.
-							    fragsize,
-							    abinfo.bytes,
-							    abinfo.
-							    fragstotal,
-							    abinfo.
-							    fragments));
-		spin_unlock_irqrestore(&s->lock, flags);
-		return copy_to_user((void *) arg, &abinfo,
-				    sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_GETISPACE:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)))
-			return val;
-		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s);
-		if (s->conversion) {
-			abinfo.fragsize = s->dma_adc.fragsize / 2;
-			abinfo.bytes = s->dma_adc.count / 2;
-			abinfo.fragstotal = s->dma_adc.numfrag;
-			abinfo.fragments =
-			    abinfo.bytes >> (s->dma_adc.fragshift - 1);
-		} else {
-			abinfo.fragsize = s->dma_adc.fragsize;
-			abinfo.bytes = s->dma_adc.count;
-			abinfo.fragstotal = s->dma_adc.numfrag;
-			abinfo.fragments =
-			    abinfo.bytes >> s->dma_adc.fragshift;
-		}
-		spin_unlock_irqrestore(&s->lock, flags);
-		return copy_to_user((void *) arg, &abinfo,
-				    sizeof(abinfo)) ? -EFAULT : 0;
-
-	case SNDCTL_DSP_NONBLOCK:
-		file->f_flags |= O_NONBLOCK;
-		return 0;
-
-	case SNDCTL_DSP_GETODELAY:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
-			return val;
-		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s);
-		val = s->dma_dac.count;
-		spin_unlock_irqrestore(&s->lock, flags);
-		return put_user(val, (int *) arg);
-
-	case SNDCTL_DSP_GETIPTR:
-		if (!(file->f_mode & FMODE_READ))
-			return -EINVAL;
-		if (!s->dma_dac.ready && (val = prog_dmabuf_dac(s)))
-			return val;
-		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s);
-		cinfo.bytes = s->dma_adc.total_bytes;
-		if (s->dma_adc.mapped) {
-			cinfo.blocks =
-			    (cinfo.bytes >> s->dma_adc.fragshift) -
-			    s->dma_adc.blocks;
-			s->dma_adc.blocks =
-			    cinfo.bytes >> s->dma_adc.fragshift;
-		} else {
-			if (s->conversion) {
-				cinfo.blocks =
-				    s->dma_adc.count /
-				    2 >> (s->dma_adc.fragshift - 1);
-			} else
-				cinfo.blocks =
-				    s->dma_adc.count >> s->dma_adc.
-				    fragshift;
-		}
-		if (s->conversion)
-			cinfo.ptr = s->dma_adc.hwptr / 2;
-		else
-			cinfo.ptr = s->dma_adc.hwptr;
-		if (s->dma_adc.mapped)
-			s->dma_adc.count &= s->dma_adc.fragsize - 1;
-		spin_unlock_irqrestore(&s->lock, flags);
-		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
-
-	case SNDCTL_DSP_GETOPTR:
-		if (!(file->f_mode & FMODE_WRITE))
-			return -EINVAL;
-		if (!s->dma_adc.ready && (val = prog_dmabuf_adc(s)))
-			return val;
-		spin_lock_irqsave(&s->lock, flags);
-		cs4281_update_ptr(s);
-		cinfo.bytes = s->dma_dac.total_bytes;
-		if (s->dma_dac.mapped) {
-			cinfo.blocks =
-			    (cinfo.bytes >> s->dma_dac.fragshift) -
-			    s->dma_dac.blocks;
-			s->dma_dac.blocks =
-			    cinfo.bytes >> s->dma_dac.fragshift;
-		} else {
-			cinfo.blocks =
-			    s->dma_dac.count >> s->dma_dac.fragshift;
-		}
-		cinfo.ptr = s->dma_dac.hwptr;
-		if (s->dma_dac.mapped)
-			s->dma_dac.count &= s->dma_dac.fragsize - 1;
-		spin_unlock_irqrestore(&s->lock, flags);
-		return copy_to_user((void *) arg, &cinfo, sizeof(cinfo));
-
-	case SNDCTL_DSP_GETBLKSIZE:
-		if (file->f_mode & FMODE_WRITE) {
-			if ((val = prog_dmabuf_dac(s)))
-				return val;
-			return put_user(s->dma_dac.fragsize, (int *) arg);
-		}
-		if ((val = prog_dmabuf_adc(s)))
-			return val;
-		if (s->conversion)
-			return put_user(s->dma_adc.fragsize / 2,
-					(int *) arg);
-		else
-			return put_user(s->dma_adc.fragsize, (int *) arg);
-
-	case SNDCTL_DSP_SETFRAGMENT:
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		return 0;	// Say OK, but do nothing.
-
-	case SNDCTL_DSP_SUBDIVIDE:
-		if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision)
-		    || (file->f_mode & FMODE_WRITE
-			&& s->dma_dac.subdivision)) return -EINVAL;
-		if (get_user(val, (int *) arg))
-			return -EFAULT;
-		if (val != 1 && val != 2 && val != 4)
-			return -EINVAL;
-		if (file->f_mode & FMODE_READ)
-			s->dma_adc.subdivision = val;
-		else if (file->f_mode & FMODE_WRITE)
-			s->dma_dac.subdivision = val;
-		return 0;
-
-	case SOUND_PCM_READ_RATE:
-		if (file->f_mode & FMODE_READ)
-			return put_user(s->prop_adc.rate, (int *) arg);
-		else if (file->f_mode & FMODE_WRITE)
-			return put_user(s->prop_dac.rate, (int *) arg);
-
-	case SOUND_PCM_READ_CHANNELS:
-		if (file->f_mode & FMODE_READ)
-			return put_user(s->prop_adc.channels, (int *) arg);
-		else if (file->f_mode & FMODE_WRITE)
-			return put_user(s->prop_dac.channels, (int *) arg);
-
-	case SOUND_PCM_READ_BITS:
-		if (file->f_mode & FMODE_READ)
-			return
-			    put_user(
-				     (s->prop_adc.
-				      fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16,
-				     (int *) arg);
-		else if (file->f_mode & FMODE_WRITE)
-			return
-			    put_user(
-				     (s->prop_dac.
-				      fmt & (AFMT_S8 | AFMT_U8)) ? 8 : 16,
-				     (int *) arg);
-
-	case SOUND_PCM_WRITE_FILTER:
-	case SNDCTL_DSP_SETSYNCRO:
-	case SOUND_PCM_READ_FILTER:
-		return -EINVAL;
-
-#if CSDEBUG_INTERFACE
-
-	case SNDCTL_DSP_CS_GETDBGMASK:
-		return put_user(cs_debugmask, (unsigned long *) arg);
-
-	case SNDCTL_DSP_CS_GETDBGLEVEL:
-		return put_user(cs_debuglevel, (unsigned long *) arg);
-
-	case SNDCTL_DSP_CS_SETDBGMASK:
-		if (get_user(val, (unsigned long *) arg))
-			return -EFAULT;
-		cs_debugmask = val;
-		return 0;
-
-	case SNDCTL_DSP_CS_SETDBGLEVEL:
-		if (get_user(val, (unsigned long *) arg))
-			return -EFAULT;
-		cs_debuglevel = val;
-		return 0;
-#endif
-
-	}
-	return mixer_ioctl(s, cmd, arg);
-}
-
-
-static int cs4281_release(struct inode *inode, struct file *file)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-
-	CS_DBGOUT(CS_FUNCTION | CS_RELEASE, 2,
-		  printk(KERN_INFO
-			 "cs4281: cs4281_release(): inode=0x%.8x file=0x%.8x f_mode=%d\n",
-			 (unsigned) inode, (unsigned) file, file->f_mode));
-
-	VALIDATE_STATE(s);
-
-	if (file->f_mode & FMODE_WRITE) {
-		drain_dac(s, file->f_flags & O_NONBLOCK);
-		down(&s->open_sem_dac);
-		stop_dac(s);
-		dealloc_dmabuf(s, &s->dma_dac);
-		s->open_mode &= ~FMODE_WRITE;
-		up(&s->open_sem_dac);
-		wake_up(&s->open_wait_dac);
-		MOD_DEC_USE_COUNT;
-	}
-	if (file->f_mode & FMODE_READ) {
-		drain_adc(s, file->f_flags & O_NONBLOCK);
-		down(&s->open_sem_adc);
-		stop_adc(s);
-		dealloc_dmabuf(s, &s->dma_adc);
-		s->open_mode &= ~FMODE_READ;
-		up(&s->open_sem_adc);
-		wake_up(&s->open_wait_adc);
-		MOD_DEC_USE_COUNT;
-	}
-	return 0;
-}
-
-static int cs4281_open(struct inode *inode, struct file *file)
-{
-	int minor = MINOR(inode->i_rdev);
-	struct cs4281_state *s = devs;
-
-	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2,
-		  printk(KERN_INFO
-			 "cs4281: cs4281_open(): inode=0x%.8x file=0x%.8x f_mode=0x%x\n",
-			 (unsigned) inode, (unsigned) file, file->f_mode));
-	while (s && ((s->dev_audio ^ minor) & ~0xf))
-		s = s->next;
-	if (!s) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO
-							   "cs4281: cs4281_open(): Error - unable to find audio state struct\n"));
-		return -ENODEV;
-	}
-	VALIDATE_STATE(s);
-	file->private_data = s;
-
-	// wait for device to become free 
-	if (!(file->f_mode & (FMODE_WRITE | FMODE_READ))) {
-		CS_DBGOUT(CS_FUNCTION | CS_OPEN | CS_ERROR, 2,
-			  printk(KERN_INFO
-				 "cs4281: cs4281_open(): Error - must open READ and/or WRITE\n"));
-		return -ENODEV;
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		down(&s->open_sem_dac);
-		while (s->open_mode & FMODE_WRITE) {
-			if (file->f_flags & O_NONBLOCK) {
-				up(&s->open_sem_dac);
-				return -EBUSY;
-			}
-			up(&s->open_sem_dac);
-			interruptible_sleep_on(&s->open_wait_dac);
-
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-			down(&s->open_sem_dac);
-		}
-	}
-	if (file->f_mode & FMODE_READ) {
-		down(&s->open_sem_adc);
-		while (s->open_mode & FMODE_READ) {
-			if (file->f_flags & O_NONBLOCK) {
-				up(&s->open_sem_adc);
-				return -EBUSY;
-			}
-			up(&s->open_sem_adc);
-			interruptible_sleep_on(&s->open_wait_adc);
-
-			if (signal_pending(current))
-				return -ERESTARTSYS;
-			down(&s->open_sem_adc);
-		}
-	}
-	s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
-	if (file->f_mode & FMODE_READ) {
-		s->prop_adc.fmt = AFMT_U8;
-		s->prop_adc.fmt_original = s->prop_adc.fmt;
-		s->prop_adc.channels = 1;
-		s->prop_adc.rate = 8000;
-		s->prop_adc.clkdiv = 96 | 0x80;
-		s->conversion = 0;
-		s->ena &= ~FMODE_READ;
-		s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags =
-		    s->dma_adc.subdivision = 0;
-		up(&s->open_sem_adc);
-		MOD_INC_USE_COUNT;
-
-		if (prog_dmabuf_adc(s)) {
-			CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR
-								"cs4281: adc Program dmabufs failed.\n"));
-			cs4281_release(inode, file);
-			return -ENOMEM;
-		}
-		prog_codec(s, CS_TYPE_ADC);
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		s->prop_dac.fmt = AFMT_U8;
-		s->prop_dac.fmt_original = s->prop_dac.fmt;
-		s->prop_dac.channels = 1;
-		s->prop_dac.rate = 8000;
-		s->prop_dac.clkdiv = 96 | 0x80;
-		s->conversion = 0;
-		s->ena &= ~FMODE_WRITE;
-		s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags =
-		    s->dma_dac.subdivision = 0;
-		up(&s->open_sem_dac);
-		MOD_INC_USE_COUNT;
-
-		if (prog_dmabuf_dac(s)) {
-			CS_DBGOUT(CS_OPEN | CS_ERROR, 2, printk(KERN_ERR
-								"cs4281: dac Program dmabufs failed.\n"));
-			cs4281_release(inode, file);
-			return -ENOMEM;
-		}
-		prog_codec(s, CS_TYPE_DAC);
-	}
-	CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2,
-		  printk(KERN_INFO "cs4281: cs4281_open()- 0\n"));
-	return 0;
-}
-
-
-// ******************************************************************************************
-//   Wave (audio) file operations struct.
-// ******************************************************************************************
-static /*const */ struct file_operations cs4281_audio_fops = {
-	llseek:cs4281_llseek,
-	read:cs4281_read,
-	write:cs4281_write,
-	poll:cs4281_poll,
-	ioctl:cs4281_ioctl,
-	mmap:cs4281_mmap,
-	open:cs4281_open,
-	release:cs4281_release,
-};
-
-// --------------------------------------------------------------------- 
-
-// hold spinlock for the following! 
-static void cs4281_handle_midi(struct cs4281_state *s)
-{
-	unsigned char ch;
-	int wake;
-	unsigned temp1;
-
-	wake = 0;
-	while (!(readl(s->pBA0 + BA0_MIDSR) & 0x80)) {
-		ch = readl(s->pBA0 + BA0_MIDRP);
-		if (s->midi.icnt < MIDIINBUF) {
-			s->midi.ibuf[s->midi.iwr] = ch;
-			s->midi.iwr = (s->midi.iwr + 1) % MIDIINBUF;
-			s->midi.icnt++;
-		}
-		wake = 1;
-	}
-	if (wake)
-		wake_up(&s->midi.iwait);
-	wake = 0;
-	while (!(readl(s->pBA0 + BA0_MIDSR) & 0x40) && s->midi.ocnt > 0) {
-		temp1 = (s->midi.obuf[s->midi.ord]) & 0x000000ff;
-		writel(temp1, s->pBA0 + BA0_MIDWP);
-		s->midi.ord = (s->midi.ord + 1) % MIDIOUTBUF;
-		s->midi.ocnt--;
-		if (s->midi.ocnt < MIDIOUTBUF - 16)
-			wake = 1;
-	}
-	if (wake)
-		wake_up(&s->midi.owait);
-}
-
-
-
-static void cs4281_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-	struct cs4281_state *s = (struct cs4281_state *) dev_id;
-	unsigned int temp1;
-
-	// fastpath out, to ease interrupt sharing 
-	temp1 = readl(s->pBA0 + BA0_HISR);	// Get Int Status reg.
-
-	CS_DBGOUT(CS_INTERRUPT, 6, printk(KERN_INFO
-					  "cs4281: cs4281_interrupt() BA0_HISR=0x%.8x\n",
-					  temp1));
-
-	if (!(temp1 & (HISR_DMA0 | HISR_DMA1 | HISR_MIDI))) {	// If not DMA or MIDI int,
-		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	//  reenable interrupts
-		CS_DBGOUT(CS_INTERRUPT, 4, printk(KERN_INFO
-						  "cs4281: cs4281_interrupt(): returning not cs4281 interrupt.\n"));
-		return;		//   and return.
-	}
-
-	if (temp1 & HISR_DMA0)	// If play interrupt,
-		readl(s->pBA0 + BA0_HDSR0);	//   clear the source.
-
-	if (temp1 & HISR_DMA1)	// Same for play.
-		readl(s->pBA0 + BA0_HDSR1);
-	writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Local EOI
-
-	spin_lock(&s->lock);
-	cs4281_update_ptr(s);
-	cs4281_handle_midi(s);
-	spin_unlock(&s->lock);
-}
-
-// **************************************************************************
-
-static void cs4281_midi_timer(unsigned long data)
-{
-	struct cs4281_state *s = (struct cs4281_state *) data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&s->lock, flags);
-	cs4281_handle_midi(s);
-	spin_unlock_irqrestore(&s->lock, flags);
-	s->midi.timer.expires = jiffies + 1;
-	add_timer(&s->midi.timer);
-}
-
-
-// --------------------------------------------------------------------- 
-
-static ssize_t cs4281_midi_read(struct file *file, char *buffer,
-				size_t count, loff_t * ppos)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned ptr;
-	int cnt;
-
-	VALIDATE_STATE(s);
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	if (!access_ok(VERIFY_WRITE, buffer, count))
-		return -EFAULT;
-	ret = 0;
-	while (count > 0) {
-		spin_lock_irqsave(&s->lock, flags);
-		ptr = s->midi.ird;
-		cnt = MIDIINBUF - ptr;
-		if (s->midi.icnt < cnt)
-			cnt = s->midi.icnt;
-		spin_unlock_irqrestore(&s->lock, flags);
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->midi.iwait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
-			continue;
-		}
-		if (copy_to_user(buffer, s->midi.ibuf + ptr, cnt))
-			return ret ? ret : -EFAULT;
-		ptr = (ptr + cnt) % MIDIINBUF;
-		spin_lock_irqsave(&s->lock, flags);
-		s->midi.ird = ptr;
-		s->midi.icnt -= cnt;
-		spin_unlock_irqrestore(&s->lock, flags);
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-	}
-	return ret;
-}
-
-
-static ssize_t cs4281_midi_write(struct file *file, const char *buffer,
-				 size_t count, loff_t * ppos)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	ssize_t ret;
-	unsigned long flags;
-	unsigned ptr;
-	int cnt;
-
-	VALIDATE_STATE(s);
-	if (ppos != &file->f_pos)
-		return -ESPIPE;
-	if (!access_ok(VERIFY_READ, buffer, count))
-		return -EFAULT;
-	ret = 0;
-	while (count > 0) {
-		spin_lock_irqsave(&s->lock, flags);
-		ptr = s->midi.owr;
-		cnt = MIDIOUTBUF - ptr;
-		if (s->midi.ocnt + cnt > MIDIOUTBUF)
-			cnt = MIDIOUTBUF - s->midi.ocnt;
-		if (cnt <= 0)
-			cs4281_handle_midi(s);
-		spin_unlock_irqrestore(&s->lock, flags);
-		if (cnt > count)
-			cnt = count;
-		if (cnt <= 0) {
-			if (file->f_flags & O_NONBLOCK)
-				return ret ? ret : -EAGAIN;
-			interruptible_sleep_on(&s->midi.owait);
-			if (signal_pending(current))
-				return ret ? ret : -ERESTARTSYS;
-			continue;
-		}
-		if (copy_from_user(s->midi.obuf + ptr, buffer, cnt))
-			return ret ? ret : -EFAULT;
-		ptr = (ptr + cnt) % MIDIOUTBUF;
-		spin_lock_irqsave(&s->lock, flags);
-		s->midi.owr = ptr;
-		s->midi.ocnt += cnt;
-		spin_unlock_irqrestore(&s->lock, flags);
-		count -= cnt;
-		buffer += cnt;
-		ret += cnt;
-		spin_lock_irqsave(&s->lock, flags);
-		cs4281_handle_midi(s);
-		spin_unlock_irqrestore(&s->lock, flags);
-	}
-	return ret;
-}
-
-
-static unsigned int cs4281_midi_poll(struct file *file,
-				     struct poll_table_struct *wait)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	unsigned long flags;
-	unsigned int mask = 0;
-
-	VALIDATE_STATE(s);
-	if (file->f_flags & FMODE_WRITE)
-		poll_wait(file, &s->midi.owait, wait);
-	if (file->f_flags & FMODE_READ)
-		poll_wait(file, &s->midi.iwait, wait);
-	spin_lock_irqsave(&s->lock, flags);
-	if (file->f_flags & FMODE_READ) {
-		if (s->midi.icnt > 0)
-			mask |= POLLIN | POLLRDNORM;
-	}
-	if (file->f_flags & FMODE_WRITE) {
-		if (s->midi.ocnt < MIDIOUTBUF)
-			mask |= POLLOUT | POLLWRNORM;
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	return mask;
-}
-
-
-static int cs4281_midi_open(struct inode *inode, struct file *file)
-{
-	int minor = MINOR(inode->i_rdev);
-	struct cs4281_state *s = devs;
-	unsigned long flags, temp1;
-	while (s && s->dev_midi != minor)
-		s = s->next;
-	if (!s)
-		return -ENODEV;
-	VALIDATE_STATE(s);
-	file->private_data = s;
-	// wait for device to become free 
-	down(&s->open_sem);
-	while (s->open_mode & (file->f_mode << FMODE_MIDI_SHIFT)) {
-		if (file->f_flags & O_NONBLOCK) {
-			up(&s->open_sem);
-			return -EBUSY;
-		}
-		up(&s->open_sem);
-		interruptible_sleep_on(&s->open_wait);
-		if (signal_pending(current))
-			return -ERESTARTSYS;
-		down(&s->open_sem);
-	}
-	spin_lock_irqsave(&s->lock, flags);
-	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
-		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
-		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
-		writel(1, s->pBA0 + BA0_MIDCR);	// Reset the interface.
-		writel(0, s->pBA0 + BA0_MIDCR);	// Return to normal mode.
-		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
-		writel(0x0000000f, s->pBA0 + BA0_MIDCR);	// Enable transmit, record, ints.
-		temp1 = readl(s->pBA0 + BA0_HIMR);
-		writel(temp1 & 0xffbfffff, s->pBA0 + BA0_HIMR);	// Enable midi int. recognition.
-		writel(HICR_IEV | HICR_CHGM, s->pBA0 + BA0_HICR);	// Enable interrupts
-		init_timer(&s->midi.timer);
-		s->midi.timer.expires = jiffies + 1;
-		s->midi.timer.data = (unsigned long) s;
-		s->midi.timer.function = cs4281_midi_timer;
-		add_timer(&s->midi.timer);
-	}
-	if (file->f_mode & FMODE_READ) {
-		s->midi.ird = s->midi.iwr = s->midi.icnt = 0;
-	}
-	if (file->f_mode & FMODE_WRITE) {
-		s->midi.ord = s->midi.owr = s->midi.ocnt = 0;
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	s->open_mode |=
-	    (file->
-	     f_mode << FMODE_MIDI_SHIFT) & (FMODE_MIDI_READ |
-					    FMODE_MIDI_WRITE);
-	up(&s->open_sem);
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-
-static int cs4281_midi_release(struct inode *inode, struct file *file)
-{
-	struct cs4281_state *s =
-	    (struct cs4281_state *) file->private_data;
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	unsigned count, tmo;
-
-	VALIDATE_STATE(s);
-
-	if (file->f_mode & FMODE_WRITE) {
-		add_wait_queue(&s->midi.owait, &wait);
-		for (;;) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			spin_lock_irqsave(&s->lock, flags);
-			count = s->midi.ocnt;
-			spin_unlock_irqrestore(&s->lock, flags);
-			if (count <= 0)
-				break;
-			if (signal_pending(current))
-				break;
-			if (file->f_flags & O_NONBLOCK) {
-				remove_wait_queue(&s->midi.owait, &wait);
-				current->state = TASK_RUNNING;
-				return -EBUSY;
-			}
-			tmo = (count * HZ) / 3100;
-			if (!schedule_timeout(tmo ? : 1) && tmo)
-				printk(KERN_DEBUG
-				       "cs4281: midi timed out??\n");
-		}
-		remove_wait_queue(&s->midi.owait, &wait);
-		current->state = TASK_RUNNING;
-	}
-	down(&s->open_sem);
-	s->open_mode &=
-	    (~(file->f_mode << FMODE_MIDI_SHIFT)) & (FMODE_MIDI_READ |
-						     FMODE_MIDI_WRITE);
-	spin_lock_irqsave(&s->lock, flags);
-	if (!(s->open_mode & (FMODE_MIDI_READ | FMODE_MIDI_WRITE))) {
-		writel(0, s->pBA0 + BA0_MIDCR);	// Disable Midi interrupts.  
-		del_timer(&s->midi.timer);
-	}
-	spin_unlock_irqrestore(&s->lock, flags);
-	up(&s->open_sem);
-	wake_up(&s->open_wait);
-	MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-// ******************************************************************************************
-//   Midi file operations struct.
-// ******************************************************************************************
-static /*const */ struct file_operations cs4281_midi_fops = {
-	llseek:cs4281_llseek,
-	read:cs4281_midi_read,
-	write:cs4281_midi_write,
-	poll:cs4281_midi_poll,
-	open:cs4281_midi_open,
-	release:cs4281_midi_release,
-};
-
-
-// --------------------------------------------------------------------- 
-
-// maximum number of devices 
-#define NR_DEVICE 8		// Only eight devices supported currently.
-
-// --------------------------------------------------------------------- 
-
-static struct initvol {
-	int mixch;
-	int vol;
-} initvol[] __initdata = {
-
-	{
-	SOUND_MIXER_WRITE_VOLUME, 0x4040}, {
-	SOUND_MIXER_WRITE_PCM, 0x4040}, {
-	SOUND_MIXER_WRITE_SYNTH, 0x4040}, {
-	SOUND_MIXER_WRITE_CD, 0x4040}, {
-	SOUND_MIXER_WRITE_LINE, 0x4040}, {
-	SOUND_MIXER_WRITE_LINE1, 0x4040}, {
-	SOUND_MIXER_WRITE_RECLEV, 0x0000}, {
-	SOUND_MIXER_WRITE_SPEAKER, 0x4040}, {
-	SOUND_MIXER_WRITE_MIC, 0x0000}
-};
-
-
-static int __devinit cs4281_probe(struct pci_dev *pcidev,
-				  const struct pci_device_id *pciid)
-{
-	struct cs4281_state *s;
-	dma_addr_t dma_mask;
-	mm_segment_t fs;
-	int i, val, index = 0;
-	unsigned int temp1, temp2;
-
-	CS_DBGOUT(CS_FUNCTION | CS_INIT, 2,
-		  printk(KERN_INFO "cs4281: probe()+\n"));
-
-	if (!RSRCISMEMORYREGION(pcidev, 0) ||
-	    !RSRCISMEMORYREGION(pcidev, 1)) {
-		CS_DBGOUT(CS_ERROR, 1,
-			  printk(KERN_ERR
-				 "cs4281: probe()- Memory region not assigned\n"));
-		return -1;
-	}
-	if (pcidev->irq == 0) {
-		CS_DBGOUT(CS_ERROR, 1,
-			  printk(KERN_ERR
-				 "cs4281: probe() IRQ not assigned\n"));
-		return -1;
-	}
-	if (!pci_dma_supported(pcidev, 0xffffffff)) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-					      "cs4281: probe() architecture does not support 32bit PCI busmaster DMA\n"));
-		return -1;
-	}
-	dma_mask = 0xffffffff;	/* this enables playback and recording */
-	if (!(s = kmalloc(sizeof(struct cs4281_state), GFP_KERNEL))) {
-		CS_DBGOUT(CS_ERROR, 1, printk(KERN_ERR
-					      "cs4281: probe() no memory for state struct.\n"));
-		return -1;
-	}
-	memset(s, 0, sizeof(struct cs4281_state));
-	init_waitqueue_head(&s->dma_adc.wait);
-	init_waitqueue_head(&s->dma_dac.wait);
-	init_waitqueue_head(&s->open_wait);
-	init_waitqueue_head(&s->open_wait_adc);
-	init_waitqueue_head(&s->open_wait_dac);
-	init_waitqueue_head(&s->midi.iwait);
-	init_waitqueue_head(&s->midi.owait);
-	init_MUTEX(&s->open_sem);
-	init_MUTEX(&s->open_sem_adc);
-	init_MUTEX(&s->open_sem_dac);
-	spin_lock_init(&s->lock);
-	s->pBA0phys = RSRCADDRESS(pcidev, 0);
-	s->pBA1phys = RSRCADDRESS(pcidev, 1);
-	s->pBA0 = ioremap_nocache(s->pBA0phys, 4096);	// Convert phys 
-	s->pBA1 = ioremap_nocache(s->pBA1phys, 65536);	//  to linear. 
-	temp1 = readl(s->pBA0 + BA0_PCICFG00);
-	temp2 = readl(s->pBA0 + BA0_PCICFG04);
-
-	CS_DBGOUT(CS_INIT, 2,
-		  printk(KERN_INFO
-			 "cs4281: probe() BA0=0x%.8x BA1=0x%.8x pBA0=0x%.8x pBA1=0x%.8x \n",
-			 (unsigned) temp1, (unsigned) temp2,
-			 (unsigned) s->pBA0, (unsigned) s->pBA1));
-
-	CS_DBGOUT(CS_INIT, 2,
-		  printk(KERN_INFO
-			 "cs4281: probe() pBA0phys=0x%.8x pBA1phys=0x%.8x\n",
-			 (unsigned) s->pBA0phys, (unsigned) s->pBA1phys));
-
-	temp1 = cs4281_hw_init(s);
-	if (temp1) {
-		CS_DBGOUT(CS_ERROR | CS_INIT, 1,
-			  printk(KERN_ERR
-				 "cs4281: cs4281_hw_init() failed. Skipping part.\n"));
-		return -1;
-	}
-	s->magic = CS4281_MAGIC;
-	s->pcidev = pcidev;
-	s->irq = pcidev->irq;
-	if (pci_enable_device(pcidev)) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
-			  printk(KERN_ERR
-				 "cs4281: pci_enable_device() failed\n"));
-		goto err_irq;
-	}
-	if (request_irq
-	    (s->irq, cs4281_interrupt, SA_SHIRQ, "Crystal CS4281", s)) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
-			  printk(KERN_ERR "cs4281: irq %u in use\n",
-				 s->irq));
-		goto err_irq;
-	}
-	if ((s->dev_audio = register_sound_dsp(&cs4281_audio_fops, -1)) <
-	    0) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
-			  printk(KERN_ERR
-				 "cs4281: probe() register_sound_dsp() failed.\n"));
-		goto err_dev1;
-	}
-	if ((s->dev_mixer = register_sound_mixer(&cs4281_mixer_fops, -1)) <
-	    0) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
-			  printk(KERN_ERR
-				 "cs4281: probe() register_sound_mixer() failed.\n"));
-		goto err_dev2;
-	}
-	if ((s->dev_midi = register_sound_midi(&cs4281_midi_fops, -1)) < 0) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
-			  printk(KERN_ERR
-				 "cs4281: probe() register_sound_midi() failed.\n"));
-		goto err_dev3;
-	}
-
-	pci_set_master(pcidev);	// enable bus mastering 
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-	val = SOUND_MASK_LINE;
-	mixer_ioctl(s, SOUND_MIXER_WRITE_RECSRC, (unsigned long) &val);
-	for (i = 0; i < sizeof(initvol) / sizeof(initvol[0]); i++) {
-		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;
-	pcidev->driver_data = s;
-	pcidev->dma_mask = dma_mask;
-	devs = s;
-	index++;
-	return 0;
-
-      err_dev3:
-	unregister_sound_mixer(s->dev_mixer);
-      err_dev2:
-	unregister_sound_dsp(s->dev_audio);
-      err_dev1:
-	free_irq(s->irq, s);
-      err_irq:
-	kfree(s);
-
-	if (!devs) {
-		CS_DBGOUT(CS_INIT | CS_ERROR, 1,
-			  printk(KERN_INFO
-				 "cs4281: probe()- no device allocated\n"));
-		return -ENODEV;
-	}
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO
-			 "cs4281: probe()- device allocated successfully\n"));
-	return 0;
-}				// probe_cs4281
-
-
-// --------------------------------------------------------------------- 
-
-static void __devinit cs4281_remove(struct pci_dev *dev)
-{
-	struct cs4281_state *s = (struct cs4281_state *) dev->driver_data;
-	// stop DMA controller 
-	synchronize_irq();
-	free_irq(s->irq, s);
-	unregister_sound_dsp(s->dev_audio);
-	unregister_sound_mixer(s->dev_mixer);
-	unregister_sound_midi(s->dev_midi);
-	kfree(s);
-	dev->driver_data = NULL;
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO
-			 "cs4281: cs4281_remove(): remove successful\n"));
-}
-
-static struct pci_device_id id_table[] __devinitdata = {
-	
-	    {PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CRYSTAL_CS4281,
-	 PCI_ANY_ID, PCI_ANY_ID, 0, 0},
-	{0,}
-};
-
-MODULE_DEVICE_TABLE(pci, id_table);
-
-static struct pci_driver cs4281_driver = {
-	name:"cs4281",
-	id_table:id_table,
-	probe:cs4281_probe,
-	remove:cs4281_remove
-};
-
-static int __init init_cs4281(void)
-{
-
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: init_cs4281()+ \n"));
-	if (!pci_present()) {	/* No PCI bus in this machine! */
-		CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-			  printk(KERN_INFO
-				 "cs4281: init_cs4281()- no pci bus found\n"));
-		return -ENODEV;
-	}
-	printk(KERN_INFO "cs4281: version v%d.%02d.%d time " __TIME__ " "
-	       __DATE__ "\n", CS4281_MAJOR_VERSION, CS4281_MINOR_VERSION,
-	       CS4281_ARCH);
-	if (!pci_register_driver(&cs4281_driver)) {
-		pci_unregister_driver(&cs4281_driver);
-		CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-			  printk(KERN_INFO
-				 "cs4281: init_cs4281()- unable to register pci device \n"));
-		return -ENODEV;
-	}
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: init_cs4281()- 0\n"));
-	return 0;
-}
-
-
-// --------------------------------------------------------------------- 
-
-
-MODULE_AUTHOR("gw boynton, wesb@crystal.cirrus.com");
-MODULE_DESCRIPTION("Cirrus Logic CS4281 Driver");
-
-static void __exit cleanup_cs4281(void)
-{
-	pci_unregister_driver(&cs4281_driver);
-	CS_DBGOUT(CS_INIT | CS_FUNCTION, 2,
-		  printk(KERN_INFO "cs4281: cleanup_cs4281() finished\n"));
-}
-
-// --------------------------------------------------------------------- 
-
-module_init(init_cs4281);
-module_exit(cleanup_cs4281);
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs4281_hwdefs.h linux/drivers/sound/cs4281_hwdefs.h
--- v2.4.1/linux/drivers/sound/cs4281_hwdefs.h	Sat Sep 23 20:23:09 2000
+++ linux/drivers/sound/cs4281_hwdefs.h	Wed Dec 31 16:00:00 1969
@@ -1,1234 +0,0 @@
-//****************************************************************************
-//
-// HWDEFS.H - Definitions of the registers and data structures used by the
-//            CS4281
-//
-// Copyright (c) 1999 Crystal Semiconductor Corp.
-//
-//****************************************************************************
-
-#ifndef _H_HWDEFS
-#define _H_HWDEFS
-
-//****************************************************************************
-//
-// The following define the offsets of the registers located in the PCI
-// configuration space of the CS4281 part.
-//
-//****************************************************************************
-#define PCICONFIG_DEVID_VENID                   0x00000000L
-#define PCICONFIG_STATUS_COMMAND                0x00000004L
-#define PCICONFIG_CLASS_REVISION                0x00000008L
-#define PCICONFIG_LATENCY_TIMER                 0x0000000CL
-#define PCICONFIG_BA0                           0x00000010L
-#define PCICONFIG_BA1                           0x00000014L
-#define PCICONFIG_SUBSYSID_SUBSYSVENID          0x0000002CL
-#define PCICONFIG_INTERRUPT                     0x0000003CL
-
-//****************************************************************************
-//
-// The following define the offsets of the registers accessed via base address
-// register zero on the CS4281 part.
-//
-//****************************************************************************
-#define BA0_HISR                                0x00000000L
-#define BA0_HICR                                0x00000008L
-#define BA0_HIMR                                0x0000000CL
-#define BA0_IIER                                0x00000010L
-#define BA0_HDSR0                               0x000000F0L
-#define BA0_HDSR1                               0x000000F4L
-#define BA0_HDSR2                               0x000000F8L
-#define BA0_HDSR3                               0x000000FCL
-#define BA0_DCA0                                0x00000110L
-#define BA0_DCC0                                0x00000114L
-#define BA0_DBA0                                0x00000118L
-#define BA0_DBC0                                0x0000011CL
-#define BA0_DCA1                                0x00000120L
-#define BA0_DCC1                                0x00000124L
-#define BA0_DBA1                                0x00000128L
-#define BA0_DBC1                                0x0000012CL
-#define BA0_DCA2                                0x00000130L
-#define BA0_DCC2                                0x00000134L
-#define BA0_DBA2                                0x00000138L
-#define BA0_DBC2                                0x0000013CL
-#define BA0_DCA3                                0x00000140L
-#define BA0_DCC3                                0x00000144L
-#define BA0_DBA3                                0x00000148L
-#define BA0_DBC3                                0x0000014CL
-#define BA0_DMR0                                0x00000150L
-#define BA0_DCR0                                0x00000154L
-#define BA0_DMR1                                0x00000158L
-#define BA0_DCR1                                0x0000015CL
-#define BA0_DMR2                                0x00000160L
-#define BA0_DCR2                                0x00000164L
-#define BA0_DMR3                                0x00000168L
-#define BA0_DCR3                                0x0000016CL
-#define BA0_DLMR                                0x00000170L
-#define BA0_DLSR                                0x00000174L
-#define BA0_FCR0                                0x00000180L
-#define BA0_FCR1                                0x00000184L
-#define BA0_FCR2                                0x00000188L
-#define BA0_FCR3                                0x0000018CL
-#define BA0_FPDR0                               0x00000190L
-#define BA0_FPDR1                               0x00000194L
-#define BA0_FPDR2                               0x00000198L
-#define BA0_FPDR3                               0x0000019CL
-#define BA0_FCHS                                0x0000020CL
-#define BA0_FSIC0                               0x00000210L
-#define BA0_FSIC1                               0x00000214L
-#define BA0_FSIC2                               0x00000218L
-#define BA0_FSIC3                               0x0000021CL
-#define BA0_PCICFG00                            0x00000300L
-#define BA0_PCICFG04                            0x00000304L
-#define BA0_PCICFG08                            0x00000308L
-#define BA0_PCICFG0C                            0x0000030CL
-#define BA0_PCICFG10                            0x00000310L
-#define BA0_PCICFG14                            0x00000314L
-#define BA0_PCICFG18                            0x00000318L
-#define BA0_PCICFG1C                            0x0000031CL
-#define BA0_PCICFG20                            0x00000320L
-#define BA0_PCICFG24                            0x00000324L
-#define BA0_PCICFG28                            0x00000328L
-#define BA0_PCICFG2C                            0x0000032CL
-#define BA0_PCICFG30                            0x00000330L
-#define BA0_PCICFG34                            0x00000334L
-#define BA0_PCICFG38                            0x00000338L
-#define BA0_PCICFG3C                            0x0000033CL
-#define BA0_PCICFG40                            0x00000340L
-#define BA0_PMCS                                0x00000344L
-#define BA0_CWPR                                0x000003E0L
-#define BA0_EPPMC                               0x000003E4L
-#define BA0_GPIOR                               0x000003E8L
-#define BA0_SPMC                                0x000003ECL
-#define BA0_CFLR                                0x000003F0L
-#define BA0_IISR                                0x000003F4L
-#define BA0_TMS                                 0x000003F8L
-#define BA0_SSVID                               0x000003FCL
-#define BA0_CLKCR1                              0x00000400L
-#define BA0_FRR                                 0x00000410L
-#define BA0_SLT12O                              0x0000041CL
-#define BA0_SERMC                               0x00000420L
-#define BA0_SERC1                               0x00000428L
-#define BA0_SERC2                               0x0000042CL
-#define BA0_SLT12M                              0x0000045CL
-#define BA0_ACCTL                               0x00000460L
-#define BA0_ACSTS                               0x00000464L
-#define BA0_ACOSV                               0x00000468L
-#define BA0_ACCAD                               0x0000046CL
-#define BA0_ACCDA                               0x00000470L
-#define BA0_ACISV                               0x00000474L
-#define BA0_ACSAD                               0x00000478L
-#define BA0_ACSDA                               0x0000047CL
-#define BA0_JSPT                                0x00000480L
-#define BA0_JSCTL                               0x00000484L
-#define BA0_MIDCR                               0x00000490L
-#define BA0_MIDCMD                              0x00000494L
-#define BA0_MIDSR                               0x00000494L
-#define BA0_MIDWP                               0x00000498L
-#define BA0_MIDRP                               0x0000049CL
-#define BA0_AODSD1                              0x000004A8L
-#define BA0_AODSD2                              0x000004ACL
-#define BA0_CFGI                                0x000004B0L
-#define BA0_SLT12M2                             0x000004DCL
-#define BA0_ACSTS2                              0x000004E4L
-#define BA0_ACISV2                              0x000004F4L
-#define BA0_ACSAD2                              0x000004F8L
-#define BA0_ACSDA2                              0x000004FCL
-#define BA0_IOTGP                               0x00000500L
-#define BA0_IOTSB                               0x00000504L
-#define BA0_IOTFM                               0x00000508L
-#define BA0_IOTDMA                              0x0000050CL
-#define BA0_IOTAC0                              0x00000500L
-#define BA0_IOTAC1                              0x00000504L
-#define BA0_IOTAC2                              0x00000508L
-#define BA0_IOTAC3                              0x0000050CL
-#define BA0_IOTPCP                              0x0000052CL
-#define BA0_IOTCC                               0x00000530L
-#define BA0_IOTCR                               0x0000058CL
-#define BA0_PCPRR                               0x00000600L
-#define BA0_PCPGR                               0x00000604L
-#define BA0_PCPCR                               0x00000608L
-#define BA0_PCPCIEN                             0x00000608L
-#define BA0_SBMAR                               0x00000700L
-#define BA0_SBMDR                               0x00000704L
-#define BA0_SBRR                                0x00000708L
-#define BA0_SBRDP                               0x0000070CL
-#define BA0_SBWDP                               0x00000710L
-#define BA0_SBWBS                               0x00000710L
-#define BA0_SBRBS                               0x00000714L
-#define BA0_FMSR                                0x00000730L
-#define BA0_B0AP                                0x00000730L
-#define BA0_FMDP                                0x00000734L
-#define BA0_B1AP                                0x00000738L
-#define BA0_B1DP                                0x0000073CL
-#define BA0_SSPM                                0x00000740L
-#define BA0_DACSR                               0x00000744L
-#define BA0_ADCSR                               0x00000748L
-#define BA0_SSCR                                0x0000074CL
-#define BA0_FMLVC                               0x00000754L
-#define BA0_FMRVC                               0x00000758L
-#define BA0_SRCSA                               0x0000075CL
-#define BA0_PPLVC                               0x00000760L
-#define BA0_PPRVC                               0x00000764L
-#define BA0_PASR                                0x00000768L
-#define BA0_CASR                                0x0000076CL
-
-//****************************************************************************
-//
-// The following define the offsets of the AC97 shadow registers, which appear
-// as a virtual extension to the base address register zero memory range.
-//
-//****************************************************************************
-#define AC97_REG_OFFSET_MASK                    0x0000007EL
-#define AC97_CODEC_NUMBER_MASK                  0x00003000L
-
-#define BA0_AC97_RESET                          0x00001000L
-#define BA0_AC97_MASTER_VOLUME                  0x00001002L
-#define BA0_AC97_HEADPHONE_VOLUME               0x00001004L
-#define BA0_AC97_MASTER_VOLUME_MONO             0x00001006L
-#define BA0_AC97_MASTER_TONE                    0x00001008L
-#define BA0_AC97_PC_BEEP_VOLUME                 0x0000100AL
-#define BA0_AC97_PHONE_VOLUME                   0x0000100CL
-#define BA0_AC97_MIC_VOLUME                     0x0000100EL
-#define BA0_AC97_LINE_IN_VOLUME                 0x00001010L
-#define BA0_AC97_CD_VOLUME                      0x00001012L
-#define BA0_AC97_VIDEO_VOLUME                   0x00001014L
-#define BA0_AC97_AUX_VOLUME                     0x00001016L
-#define BA0_AC97_PCM_OUT_VOLUME                 0x00001018L
-#define BA0_AC97_RECORD_SELECT                  0x0000101AL
-#define BA0_AC97_RECORD_GAIN                    0x0000101CL
-#define BA0_AC97_RECORD_GAIN_MIC                0x0000101EL
-#define BA0_AC97_GENERAL_PURPOSE                0x00001020L
-#define BA0_AC97_3D_CONTROL                     0x00001022L
-#define BA0_AC97_MODEM_RATE                     0x00001024L
-#define BA0_AC97_POWERDOWN                      0x00001026L
-#define BA0_AC97_EXT_AUDIO_ID                   0x00001028L
-#define BA0_AC97_EXT_AUDIO_POWER                0x0000102AL
-#define BA0_AC97_PCM_FRONT_DAC_RATE             0x0000102CL
-#define BA0_AC97_PCM_SURR_DAC_RATE              0x0000102EL
-#define BA0_AC97_PCM_LFE_DAC_RATE               0x00001030L
-#define BA0_AC97_PCM_LR_ADC_RATE                0x00001032L
-#define BA0_AC97_MIC_ADC_RATE                   0x00001034L
-#define BA0_AC97_6CH_VOL_C_LFE                  0x00001036L
-#define BA0_AC97_6CH_VOL_SURROUND               0x00001038L
-#define BA0_AC97_RESERVED_3A                    0x0000103AL
-#define BA0_AC97_EXT_MODEM_ID                   0x0000103CL
-#define BA0_AC97_EXT_MODEM_POWER                0x0000103EL
-#define BA0_AC97_LINE1_CODEC_RATE               0x00001040L
-#define BA0_AC97_LINE2_CODEC_RATE               0x00001042L
-#define BA0_AC97_HANDSET_CODEC_RATE             0x00001044L
-#define BA0_AC97_LINE1_CODEC_LEVEL              0x00001046L
-#define BA0_AC97_LINE2_CODEC_LEVEL              0x00001048L
-#define BA0_AC97_HANDSET_CODEC_LEVEL            0x0000104AL
-#define BA0_AC97_GPIO_PIN_CONFIG                0x0000104CL
-#define BA0_AC97_GPIO_PIN_TYPE                  0x0000104EL
-#define BA0_AC97_GPIO_PIN_STICKY                0x00001050L
-#define BA0_AC97_GPIO_PIN_WAKEUP                0x00001052L
-#define BA0_AC97_GPIO_PIN_STATUS                0x00001054L
-#define BA0_AC97_MISC_MODEM_AFE_STAT            0x00001056L
-#define BA0_AC97_RESERVED_58                    0x00001058L
-#define BA0_AC97_CRYSTAL_REV_N_FAB_ID           0x0000105AL
-#define BA0_AC97_TEST_AND_MISC_CTRL             0x0000105CL
-#define BA0_AC97_AC_MODE                        0x0000105EL
-#define BA0_AC97_MISC_CRYSTAL_CONTROL           0x00001060L
-#define BA0_AC97_LINE1_HYPRID_CTRL              0x00001062L
-#define BA0_AC97_VENDOR_RESERVED_64             0x00001064L
-#define BA0_AC97_VENDOR_RESERVED_66             0x00001066L
-#define BA0_AC97_SPDIF_CONTROL                  0x00001068L
-#define BA0_AC97_VENDOR_RESERVED_6A             0x0000106AL
-#define BA0_AC97_VENDOR_RESERVED_6C             0x0000106CL
-#define BA0_AC97_VENDOR_RESERVED_6E             0x0000106EL
-#define BA0_AC97_VENDOR_RESERVED_70             0x00001070L
-#define BA0_AC97_VENDOR_RESERVED_72             0x00001072L
-#define BA0_AC97_VENDOR_RESERVED_74             0x00001074L
-#define BA0_AC97_CAL_ADDRESS                    0x00001076L
-#define BA0_AC97_CAL_DATA                       0x00001078L
-#define BA0_AC97_VENDOR_RESERVED_7A             0x0000107AL
-#define BA0_AC97_VENDOR_ID1                     0x0000107CL
-#define BA0_AC97_VENDOR_ID2                     0x0000107EL
-
-//****************************************************************************
-//
-// The following define the offsets of the registers and memories accessed via
-// base address register one on the CS4281 part.
-//
-//****************************************************************************
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI device ID/vendor ID
-// register.
-//
-//****************************************************************************
-#define PDV_VENID_MASK                          0x0000FFFFL
-#define PDV_DEVID_MASK                          0xFFFF0000L
-#define PDV_VENID_SHIFT                         0L
-#define PDV_DEVID_SHIFT                         16L
-#define VENID_CIRRUS_LOGIC                      0x1013L
-#define DEVID_CS4281                            0x6005L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI status and command
-// register.
-//
-//****************************************************************************
-#define PSC_IO_SPACE_ENABLE                     0x00000001L
-#define PSC_MEMORY_SPACE_ENABLE                 0x00000002L
-#define PSC_BUS_MASTER_ENABLE                   0x00000004L
-#define PSC_SPECIAL_CYCLES                      0x00000008L
-#define PSC_MWI_ENABLE                          0x00000010L
-#define PSC_VGA_PALETTE_SNOOP                   0x00000020L
-#define PSC_PARITY_RESPONSE                     0x00000040L
-#define PSC_WAIT_CONTROL                        0x00000080L
-#define PSC_SERR_ENABLE                         0x00000100L
-#define PSC_FAST_B2B_ENABLE                     0x00000200L
-#define PSC_UDF_MASK                            0x007F0000L
-#define PSC_FAST_B2B_CAPABLE                    0x00800000L
-#define PSC_PARITY_ERROR_DETECTED               0x01000000L
-#define PSC_DEVSEL_TIMING_MASK                  0x06000000L
-#define PSC_TARGET_ABORT_SIGNALLED              0x08000000L
-#define PSC_RECEIVED_TARGET_ABORT               0x10000000L
-#define PSC_RECEIVED_MASTER_ABORT               0x20000000L
-#define PSC_SIGNALLED_SERR                      0x40000000L
-#define PSC_DETECTED_PARITY_ERROR               0x80000000L
-#define PSC_UDF_SHIFT                           16L
-#define PSC_DEVSEL_TIMING_SHIFT                 25L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI class/revision ID
-// register.
-//
-//****************************************************************************
-#define PCR_REVID_MASK                          0x000000FFL
-#define PCR_INTERFACE_MASK                      0x0000FF00L
-#define PCR_SUBCLASS_MASK                       0x00FF0000L
-#define PCR_CLASS_MASK                          0xFF000000L
-#define PCR_REVID_SHIFT                         0L
-#define PCR_INTERFACE_SHIFT                     8L
-#define PCR_SUBCLASS_SHIFT                      16L
-#define PCR_CLASS_SHIFT                         24L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI latency timer register.
-//
-//****************************************************************************
-#define PLT_CACHE_LINE_SIZE_MASK                0x000000FFL
-#define PLT_LATENCY_TIMER_MASK                  0x0000FF00L
-#define PLT_HEADER_TYPE_MASK                    0x00FF0000L
-#define PLT_BIST_MASK                           0xFF000000L
-#define PLT_CACHE_LINE_SIZE_SHIFT               0L
-#define PLT_LATENCY_TIMER_SHIFT                 8L
-#define PLT_HEADER_TYPE_SHIFT                   16L
-#define PLT_BIST_SHIFT                          24L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI base address registers.
-//
-//****************************************************************************
-#define PBAR_MEMORY_SPACE_INDICATOR             0x00000001L
-#define PBAR_LOCATION_TYPE_MASK                 0x00000006L
-#define PBAR_NOT_PREFETCHABLE                   0x00000008L
-#define PBAR_ADDRESS_MASK                       0xFFFFFFF0L
-#define PBAR_LOCATION_TYPE_SHIFT                1L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI subsystem ID/subsystem
-// vendor ID register.
-//
-//****************************************************************************
-#define PSS_SUBSYSTEM_VENDOR_ID_MASK            0x0000FFFFL
-#define PSS_SUBSYSTEM_ID_MASK                   0xFFFF0000L
-#define PSS_SUBSYSTEM_VENDOR_ID_SHIFT           0L
-#define PSS_SUBSYSTEM_ID_SHIFT                  16L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PCI interrupt register.
-//
-//****************************************************************************
-#define PI_LINE_MASK                            0x000000FFL
-#define PI_PIN_MASK                             0x0000FF00L
-#define PI_MIN_GRANT_MASK                       0x00FF0000L
-#define PI_MAX_LATENCY_MASK                     0xFF000000L
-#define PI_LINE_SHIFT                           0L
-#define PI_PIN_SHIFT                            8L
-#define PI_MIN_GRANT_SHIFT                      16L
-#define PI_MAX_LATENCY_SHIFT                    24L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the host interrupt status
-// register.
-//
-//****************************************************************************
-#define HISR_HVOLMASK                            0x00000003L
-#define HISR_VDNI                                0x00000001L
-#define HISR_VUPI                                0x00000002L
-#define HISR_GP1I                                0x00000004L
-#define HISR_GP3I                                0x00000008L
-#define HISR_GPSI                                0x00000010L
-#define HISR_GPPI                                0x00000020L
-#define HISR_DMAI                                0x00040000L
-#define HISR_FIFOI                               0x00100000L
-#define HISR_HVOL                                0x00200000L
-#define HISR_MIDI                                0x00400000L
-#define HISR_SBINT                               0x00800000L
-#define HISR_INTENA                              0x80000000L
-#define HISR_DMA_MASK                            0x00000F00L
-#define HISR_FIFO_MASK                           0x0000F000L
-#define HISR_DMA_SHIFT                           8L
-#define HISR_FIFO_SHIFT                          12L
-#define HISR_FIFO0                               0x00001000L
-#define HISR_FIFO1                               0x00002000L
-#define HISR_FIFO2                               0x00004000L
-#define HISR_FIFO3                               0x00008000L
-#define HISR_DMA0                                0x00000100L
-#define HISR_DMA1                                0x00000200L
-#define HISR_DMA2                                0x00000400L
-#define HISR_DMA3                                0x00000800L
-#define HISR_RESERVED                            0x40000000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the host interrupt control
-// register.
-//
-//****************************************************************************
-#define HICR_IEV                                 0x00000001L
-#define HICR_CHGM                                0x00000002L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the DMA Mode Register n
-// (DMRn)
-//
-//****************************************************************************
-#define DMRn_TR_MASK                             0x0000000CL
-#define DMRn_TR_SHIFT                            2L
-#define DMRn_AUTO                                0x00000010L
-#define DMRn_TR_READ                             0x00000008L
-#define DMRn_TR_WRITE                            0x00000004L
-#define DMRn_TYPE_MASK                           0x000000C0L
-#define DMRn_TYPE_SHIFT                          6L
-#define DMRn_SIZE8                               0x00010000L
-#define DMRn_MONO                                0x00020000L
-#define DMRn_BEND                                0x00040000L
-#define DMRn_USIGN                               0x00080000L
-#define DMRn_SIZE20                              0x00100000L
-#define DMRn_SWAPC                               0x00400000L
-#define DMRn_CBC                                 0x01000000L
-#define DMRn_TBC                                 0x02000000L
-#define DMRn_POLL                                0x10000000L
-#define DMRn_DMA                                 0x20000000L
-#define DMRn_FSEL_MASK                           0xC0000000L
-#define DMRn_FSEL_SHIFT                          30L
-#define DMRn_FSEL0                               0x00000000L
-#define DMRn_FSEL1                               0x40000000L
-#define DMRn_FSEL2                               0x80000000L
-#define DMRn_FSEL3                               0xC0000000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the DMA Command Register n
-// (DCRn)
-//
-//****************************************************************************
-#define DCRn_HTCIE                               0x00020000L
-#define DCRn_TCIE                                0x00010000L
-#define DCRn_MSK                                 0x00000001L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the FIFO Control 
-// register n.(FCRn)
-//
-//****************************************************************************
-#define FCRn_OF_MASK                            0x0000007FL
-#define FCRn_OF_SHIFT                           0L
-#define FCRn_SZ_MASK                            0x00007F00L
-#define FCRn_SZ_SHIFT                           8L
-#define FCRn_LS_MASK                            0x001F0000L
-#define FCRn_LS_SHIFT                           16L
-#define FCRn_RS_MASK                            0x1F000000L
-#define FCRn_RS_SHIFT                           24L
-#define FCRn_FEN                                0x80000000L
-#define FCRn_PSH                                0x20000000L
-#define FCRn_DACZ                               0x40000000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the serial port Power Management
-// control register.(SPMC)
-//
-//****************************************************************************
-#define SPMC_RSTN                               0x00000001L
-#define SPMC_ASYN                               0x00000002L
-#define SPMC_WUP1                               0x00000004L
-#define SPMC_WUP2                               0x00000008L
-#define SPMC_ASDI2E                             0x00000100L
-#define SPMC_ESSPD                              0x00000200L
-#define SPMC_GISPEN                             0x00004000L
-#define SPMC_GIPPEN                             0x00008000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the Configuration Load register.
-// (CFLR)
-//
-//****************************************************************************
-#define CFLR_CLOCK_SOURCE_MASK                  0x00000003L
-#define CFLR_CLOCK_SOURCE_AC97                  0x00000001L
-
-#define CFLR_CB0_MASK                            0x000000FFL
-#define CFLR_CB1_MASK                            0x0000FF00L
-#define CFLR_CB2_MASK                            0x00FF0000L
-#define CFLR_CB3_MASK                            0xFF000000L
-#define CFLR_CB0_SHIFT                           0L
-#define CFLR_CB1_SHIFT                           8L
-#define CFLR_CB2_SHIFT                           16L
-#define CFLR_CB3_SHIFT                           24L
-
-#define IOTCR_DMA0                              0x00000000L
-#define IOTCR_DMA1                              0x00000400L
-#define IOTCR_DMA2                              0x00000800L
-#define IOTCR_DMA3                              0x00000C00L
-#define IOTCR_CCLS                              0x00000100L
-#define IOTCR_PCPCI                             0x00000200L
-#define IOTCR_DDMA                              0x00000300L
-
-#define SBWBS_WBB                               0x00000080L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the SRC Slot Assignment Register
-// (SRCSA)
-//
-//****************************************************************************
-#define SRCSA_PLSS_MASK                         0x0000001FL
-#define SRCSA_PLSS_SHIFT                        0L
-#define SRCSA_PRSS_MASK                         0x00001F00L
-#define SRCSA_PRSS_SHIFT                        8L
-#define SRCSA_CLSS_MASK                         0x001F0000L
-#define SRCSA_CLSS_SHIFT                        16L
-#define SRCSA_CRSS_MASK                         0x1F000000L
-#define SRCSA_CRSS_SHIFT                        24L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the Sound System Power Management
-// register.(SSPM)
-//
-//****************************************************************************
-#define SSPM_FPDN                               0x00000080L
-#define SSPM_MIXEN                              0x00000040L
-#define SSPM_CSRCEN                             0x00000020L
-#define SSPM_PSRCEN                             0x00000010L
-#define SSPM_JSEN                               0x00000008L
-#define SSPM_ACLEN                              0x00000004L
-#define SSPM_FMEN                               0x00000002L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the Sound System Control
-// Register. (SSCR)
-//
-//****************************************************************************
-#define SSCR_SB                                 0x00000004L
-#define SSCR_HVC                                0x00000008L
-#define SSCR_LPFIFO                             0x00000040L
-#define SSCR_LPSRC                              0x00000080L
-#define SSCR_XLPSRC                             0x00000100L
-#define SSCR_MVMD                               0x00010000L
-#define SSCR_MVAD                               0x00020000L
-#define SSCR_MVLD                               0x00040000L
-#define SSCR_MVCS                               0x00080000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the Clock Control Register 1. 
-// (CLKCR1)
-//
-//****************************************************************************
-#define CLKCR1_DLLSS_MASK                       0x0000000CL
-#define CLKCR1_DLLSS_SHIFT                      2L
-#define CLKCR1_DLLP                             0x00000010L
-#define CLKCR1_SWCE                             0x00000020L
-#define CLKCR1_DLLOS                            0x00000040L
-#define CLKCR1_CKRA                             0x00010000L
-#define CLKCR1_CKRN                             0x00020000L
-#define CLKCR1_DLLRDY                           0x01000000L
-#define CLKCR1_CLKON                            0x02000000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the Sound Blaster Read Buffer
-// Status.(SBRBS)
-//
-//****************************************************************************
-#define SBRBS_RD_MASK                           0x0000007FL
-#define SBRBS_RD_SHIFT                          0L
-#define SBRBS_RBF                               0x00000080L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the serial port master control
-// register.(SERMC)
-//
-//****************************************************************************
-#define SERMC_MSPE                              0x00000001L
-#define SERMC_PTC_MASK                          0x0000000EL
-#define SERMC_PTC_SHIFT                         1L
-#define SERMC_PTC_AC97                          0x00000002L
-#define SERMC_PLB                               0x00000010L
-#define SERMC_PXLB                              0x00000020L
-#define SERMC_LOFV                              0x00080000L
-#define SERMC_SLB                               0x00100000L
-#define SERMC_SXLB                              0x00200000L
-#define SERMC_ODSEN1                            0x01000000L
-#define SERMC_ODSEN2                            0x02000000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the General Purpose I/O Register. 
-// (GPIOR)
-//
-//****************************************************************************
-#define GPIOR_VDNS                              0x00000001L
-#define GPIOR_VUPS                              0x00000002L
-#define GPIOR_GP1S                              0x00000004L
-#define GPIOR_GP3S                              0x00000008L
-#define GPIOR_GPSS                              0x00000010L
-#define GPIOR_GPPS                              0x00000020L
-#define GPIOR_GP1D                              0x00000400L
-#define GPIOR_GP3D                              0x00000800L
-#define GPIOR_VDNLT                             0x00010000L
-#define GPIOR_VDNPO                             0x00020000L
-#define GPIOR_VDNST                             0x00040000L
-#define GPIOR_VDNW                              0x00080000L
-#define GPIOR_VUPLT                             0x00100000L
-#define GPIOR_VUPPO                             0x00200000L
-#define GPIOR_VUPST                             0x00400000L
-#define GPIOR_VUPW                              0x00800000L
-#define GPIOR_GP1OE                             0x01000000L
-#define GPIOR_GP1PT                             0x02000000L
-#define GPIOR_GP1ST                             0x04000000L
-#define GPIOR_GP1W                              0x08000000L
-#define GPIOR_GP3OE                             0x10000000L
-#define GPIOR_GP3PT                             0x20000000L
-#define GPIOR_GP3ST                             0x40000000L
-#define GPIOR_GP3W                              0x80000000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the clock control register 1.
-//
-//****************************************************************************
-#define CLKCR1_PLLSS_MASK                       0x0000000CL
-#define CLKCR1_PLLSS_SERIAL                     0x00000000L
-#define CLKCR1_PLLSS_CRYSTAL                    0x00000004L
-#define CLKCR1_PLLSS_PCI                        0x00000008L
-#define CLKCR1_PLLSS_RESERVED                   0x0000000CL
-#define CLKCR1_PLLP                             0x00000010L
-#define CLKCR1_SWCE                             0x00000020L
-#define CLKCR1_PLLOS                            0x00000040L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the feature reporting register.
-//
-//****************************************************************************
-#define FRR_FAB_MASK                            0x00000003L
-#define FRR_MASK_MASK                           0x0000001CL
-#define FRR_ID_MASK                             0x00003000L
-#define FRR_FAB_SHIFT                           0L
-#define FRR_MASK_SHIFT                          2L
-#define FRR_ID_SHIFT                            12L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the serial port 1 configuration
-// register.
-//
-//****************************************************************************
-#define SERC1_VALUE                             0x00000003L
-#define SERC1_SO1EN                             0x00000001L
-#define SERC1_SO1F_MASK                         0x0000000EL
-#define SERC1_SO1F_CS423X                       0x00000000L
-#define SERC1_SO1F_AC97                         0x00000002L
-#define SERC1_SO1F_DAC                          0x00000004L
-#define SERC1_SO1F_SPDIF                        0x00000006L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the serial port 2 configuration
-// register.
-//
-//****************************************************************************
-#define SERC2_VALUE                             0x00000003L
-#define SERC2_SI1EN                             0x00000001L
-#define SERC2_SI1F_MASK                         0x0000000EL
-#define SERC2_SI1F_CS423X                       0x00000000L
-#define SERC2_SI1F_AC97                         0x00000002L
-#define SERC2_SI1F_ADC                          0x00000004L
-#define SERC2_SI1F_SPDIF                        0x00000006L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 control register.
-//
-//****************************************************************************
-#define ACCTL_ESYN                              0x00000002L
-#define ACCTL_VFRM                              0x00000004L
-#define ACCTL_DCV                               0x00000008L
-#define ACCTL_CRW                               0x00000010L
-#define ACCTL_TC                                0x00000040L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 status register.
-//
-//****************************************************************************
-#define ACSTS_CRDY                              0x00000001L
-#define ACSTS_VSTS                              0x00000002L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 output slot valid
-// register.
-//
-//****************************************************************************
-#define ACOSV_SLV3                              0x00000001L
-#define ACOSV_SLV4                              0x00000002L
-#define ACOSV_SLV5                              0x00000004L
-#define ACOSV_SLV6                              0x00000008L
-#define ACOSV_SLV7                              0x00000010L
-#define ACOSV_SLV8                              0x00000020L
-#define ACOSV_SLV9                              0x00000040L
-#define ACOSV_SLV10                             0x00000080L
-#define ACOSV_SLV11                             0x00000100L
-#define ACOSV_SLV12                             0x00000200L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 command address
-// register.
-//
-//****************************************************************************
-#define ACCAD_CI_MASK                           0x0000007FL
-#define ACCAD_CI_SHIFT                          0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 command data register.
-//
-//****************************************************************************
-#define ACCDA_CD_MASK                           0x0000FFFFL
-#define ACCDA_CD_SHIFT                          0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 input slot valid
-// register.
-//
-//****************************************************************************
-#define ACISV_ISV3                              0x00000001L
-#define ACISV_ISV4                              0x00000002L
-#define ACISV_ISV5                              0x00000004L
-#define ACISV_ISV6                              0x00000008L
-#define ACISV_ISV7                              0x00000010L
-#define ACISV_ISV8                              0x00000020L
-#define ACISV_ISV9                              0x00000040L
-#define ACISV_ISV10                             0x00000080L
-#define ACISV_ISV11                             0x00000100L
-#define ACISV_ISV12                             0x00000200L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 status address
-// register.
-//
-//****************************************************************************
-#define ACSAD_SI_MASK                           0x0000007FL
-#define ACSAD_SI_SHIFT                          0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 status data register.
-//
-//****************************************************************************
-#define ACSDA_SD_MASK                           0x0000FFFFL
-#define ACSDA_SD_SHIFT                          0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the I/O trap address and control
-// registers (all 12).
-//
-//****************************************************************************
-#define IOTAC_SA_MASK                           0x0000FFFFL
-#define IOTAC_MSK_MASK                          0x000F0000L
-#define IOTAC_IODC_MASK                         0x06000000L
-#define IOTAC_IODC_16_BIT                       0x00000000L
-#define IOTAC_IODC_10_BIT                       0x02000000L
-#define IOTAC_IODC_12_BIT                       0x04000000L
-#define IOTAC_WSPI                              0x08000000L
-#define IOTAC_RSPI                              0x10000000L
-#define IOTAC_WSE                               0x20000000L
-#define IOTAC_WE                                0x40000000L
-#define IOTAC_RE                                0x80000000L
-#define IOTAC_SA_SHIFT                          0L
-#define IOTAC_MSK_SHIFT                         16L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PC/PCI master enable
-// register.
-//
-//****************************************************************************
-#define PCPCIEN_EN                              0x00000001L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the joystick poll/trigger
-// register.
-//
-//****************************************************************************
-#define JSPT_CAX                                0x00000001L
-#define JSPT_CAY                                0x00000002L
-#define JSPT_CBX                                0x00000004L
-#define JSPT_CBY                                0x00000008L
-#define JSPT_BA1                                0x00000010L
-#define JSPT_BA2                                0x00000020L
-#define JSPT_BB1                                0x00000040L
-#define JSPT_BB2                                0x00000080L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the joystick control register.
-// The TBF bit has been moved from MIDSR register to JSCTL register bit 8.
-//
-//****************************************************************************
-#define JSCTL_SP_MASK                           0x00000003L
-#define JSCTL_SP_SLOW                           0x00000000L
-#define JSCTL_SP_MEDIUM_SLOW                    0x00000001L
-#define JSCTL_SP_MEDIUM_FAST                    0x00000002L
-#define JSCTL_SP_FAST                           0x00000003L
-#define JSCTL_ARE                               0x00000004L
-#define JSCTL_TBF                               0x00000100L
-
-
-//****************************************************************************
-//
-// The following defines are for the flags in the MIDI control register.
-//
-//****************************************************************************
-#define MIDCR_TXE                               0x00000001L
-#define MIDCR_RXE                               0x00000002L
-#define MIDCR_RIE                               0x00000004L
-#define MIDCR_TIE                               0x00000008L
-#define MIDCR_MLB                               0x00000010L
-#define MIDCR_MRST                              0x00000020L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the MIDI status register.
-//
-//****************************************************************************
-#define MIDSR_RBE                               0x00000080L
-#define MIDSR_RDA                               0x00008000L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the MIDI write port register.
-//
-//****************************************************************************
-#define MIDWP_MWD_MASK                          0x000000FFL
-#define MIDWP_MWD_SHIFT                         0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the MIDI read port register.
-//
-//****************************************************************************
-#define MIDRP_MRD_MASK                          0x000000FFL
-#define MIDRP_MRD_SHIFT                         0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the configuration interface
-// register.
-//
-//****************************************************************************
-#define CFGI_CLK                                0x00000001L
-#define CFGI_DOUT                               0x00000002L
-#define CFGI_DIN_EEN                            0x00000004L
-#define CFGI_EELD                               0x00000008L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the subsystem ID and vendor ID
-// register.
-//
-//****************************************************************************
-#define SSVID_VID_MASK                          0x0000FFFFL
-#define SSVID_SID_MASK                          0xFFFF0000L
-#define SSVID_VID_SHIFT                         0L
-#define SSVID_SID_SHIFT                         16L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the GPIO pin interface register.
-//
-//****************************************************************************
-#define GPIOR_VOLDN                             0x00000001L
-#define GPIOR_VOLUP                             0x00000002L
-#define GPIOR_SI2D                              0x00000004L
-#define GPIOR_SI2OE                             0x00000008L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 status register 2.
-//
-//****************************************************************************
-#define ACSTS2_CRDY                             0x00000001L
-#define ACSTS2_VSTS                             0x00000002L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 input slot valid
-// register 2.
-//
-//****************************************************************************
-#define ACISV2_ISV3                             0x00000001L
-#define ACISV2_ISV4                             0x00000002L
-#define ACISV2_ISV5                             0x00000004L
-#define ACISV2_ISV6                             0x00000008L
-#define ACISV2_ISV7                             0x00000010L
-#define ACISV2_ISV8                             0x00000020L
-#define ACISV2_ISV9                             0x00000040L
-#define ACISV2_ISV10                            0x00000080L
-#define ACISV2_ISV11                            0x00000100L
-#define ACISV2_ISV12                            0x00000200L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 status address
-// register 2.
-//
-//****************************************************************************
-#define ACSAD2_SI_MASK                          0x0000007FL
-#define ACSAD2_SI_SHIFT                         0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 status data register 2.
-//
-//****************************************************************************
-#define ACSDA2_SD_MASK                          0x0000FFFFL
-#define ACSDA2_SD_SHIFT                         0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the I/O trap control register.
-//
-//****************************************************************************
-#define IOTCR_ITD                               0x00000001L
-#define IOTCR_HRV                               0x00000002L
-#define IOTCR_SRV                               0x00000004L
-#define IOTCR_DTI                               0x00000008L
-#define IOTCR_DFI                               0x00000010L
-#define IOTCR_DDP                               0x00000020L
-#define IOTCR_JTE                               0x00000040L
-#define IOTCR_PPE                               0x00000080L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the I/O trap address and control
-// registers for Hardware Master Volume.  
-//
-//****************************************************************************
-#define IOTGP_SA_MASK                           0x0000FFFFL
-#define IOTGP_MSK_MASK                          0x000F0000L
-#define IOTGP_IODC_MASK                         0x06000000L
-#define IOTGP_IODC_16_BIT                       0x00000000L
-#define IOTGP_IODC_10_BIT                       0x02000000L
-#define IOTGP_IODC_12_BIT                       0x04000000L
-#define IOTGP_WSPI                              0x08000000L
-#define IOTGP_RSPI                              0x10000000L
-#define IOTGP_WSE                               0x20000000L
-#define IOTGP_WE                                0x40000000L
-#define IOTGP_RE                                0x80000000L
-#define IOTGP_SA_SHIFT                          0L
-#define IOTGP_MSK_SHIFT                         16L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the I/O trap address and control
-// registers for Sound Blaster
-//
-//****************************************************************************
-#define IOTSB_SA_MASK                           0x0000FFFFL
-#define IOTSB_MSK_MASK                          0x000F0000L
-#define IOTSB_IODC_MASK                         0x06000000L
-#define IOTSB_IODC_16_BIT                       0x00000000L
-#define IOTSB_IODC_10_BIT                       0x02000000L
-#define IOTSB_IODC_12_BIT                       0x04000000L
-#define IOTSB_WSPI                              0x08000000L
-#define IOTSB_RSPI                              0x10000000L
-#define IOTSB_WSE                               0x20000000L
-#define IOTSB_WE                                0x40000000L
-#define IOTSB_RE                                0x80000000L
-#define IOTSB_SA_SHIFT                          0L
-#define IOTSB_MSK_SHIFT                         16L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the I/O trap address and control
-// registers for FM.
-//
-//****************************************************************************
-#define IOTFM_SA_MASK                           0x0000FFFFL
-#define IOTFM_MSK_MASK                          0x000F0000L
-#define IOTFM_IODC_MASK                         0x06000000L
-#define IOTFM_IODC_16_BIT                       0x00000000L
-#define IOTFM_IODC_10_BIT                       0x02000000L
-#define IOTFM_IODC_12_BIT                       0x04000000L
-#define IOTFM_WSPI                              0x08000000L
-#define IOTFM_RSPI                              0x10000000L
-#define IOTFM_WSE                               0x20000000L
-#define IOTFM_WE                                0x40000000L
-#define IOTFM_RE                                0x80000000L
-#define IOTFM_SA_SHIFT                          0L
-#define IOTFM_MSK_SHIFT                         16L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PC/PCI request register.
-//
-//****************************************************************************
-#define PCPRR_RDC_MASK                         0x00000007L
-#define PCPRR_REQ                              0x00008000L
-#define PCPRR_RDC_SHIFT                        0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PC/PCI grant register.
-//
-//****************************************************************************
-#define PCPGR_GDC_MASK                         0x00000007L
-#define PCPGR_VL                               0x00008000L
-#define PCPGR_GDC_SHIFT                        0L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the PC/PCI Control Register.
-//
-//****************************************************************************
-#define PCPCR_EN                               0x00000001L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the debug index register.
-//
-//****************************************************************************
-#define DREG_REGID_MASK                         0x0000007FL
-#define DREG_DEBUG                              0x00000080L
-#define DREG_RGBK_MASK                          0x00000700L
-#define DREG_TRAP                               0x00000800L
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_TRAPX                              0x00001000L
-#endif
-#endif
-#define DREG_REGID_SHIFT                        0L
-#define DREG_RGBK_SHIFT                         8L
-#define DREG_RGBK_REGID_MASK                    0x0000077FL
-#define DREG_REGID_R0                           0x00000010L
-#define DREG_REGID_R1                           0x00000011L
-#define DREG_REGID_R2                           0x00000012L
-#define DREG_REGID_R3                           0x00000013L
-#define DREG_REGID_R4                           0x00000014L
-#define DREG_REGID_R5                           0x00000015L
-#define DREG_REGID_R6                           0x00000016L
-#define DREG_REGID_R7                           0x00000017L
-#define DREG_REGID_R8                           0x00000018L
-#define DREG_REGID_R9                           0x00000019L
-#define DREG_REGID_RA                           0x0000001AL
-#define DREG_REGID_RB                           0x0000001BL
-#define DREG_REGID_RC                           0x0000001CL
-#define DREG_REGID_RD                           0x0000001DL
-#define DREG_REGID_RE                           0x0000001EL
-#define DREG_REGID_RF                           0x0000001FL
-#define DREG_REGID_RA_BUS_LOW                   0x00000020L
-#define DREG_REGID_RA_BUS_HIGH                  0x00000038L
-#define DREG_REGID_YBUS_LOW                     0x00000050L
-#define DREG_REGID_YBUS_HIGH                    0x00000058L
-#define DREG_REGID_TRAP_0                       0x00000100L
-#define DREG_REGID_TRAP_1                       0x00000101L
-#define DREG_REGID_TRAP_2                       0x00000102L
-#define DREG_REGID_TRAP_3                       0x00000103L
-#define DREG_REGID_TRAP_4                       0x00000104L
-#define DREG_REGID_TRAP_5                       0x00000105L
-#define DREG_REGID_TRAP_6                       0x00000106L
-#define DREG_REGID_TRAP_7                       0x00000107L
-#define DREG_REGID_INDIRECT_ADDRESS             0x0000010EL
-#define DREG_REGID_TOP_OF_STACK                 0x0000010FL
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_8                       0x00000110L
-#define DREG_REGID_TRAP_9                       0x00000111L
-#define DREG_REGID_TRAP_10                      0x00000112L
-#define DREG_REGID_TRAP_11                      0x00000113L
-#define DREG_REGID_TRAP_12                      0x00000114L
-#define DREG_REGID_TRAP_13                      0x00000115L
-#define DREG_REGID_TRAP_14                      0x00000116L
-#define DREG_REGID_TRAP_15                      0x00000117L
-#define DREG_REGID_TRAP_16                      0x00000118L
-#define DREG_REGID_TRAP_17                      0x00000119L
-#define DREG_REGID_TRAP_18                      0x0000011AL
-#define DREG_REGID_TRAP_19                      0x0000011BL
-#define DREG_REGID_TRAP_20                      0x0000011CL
-#define DREG_REGID_TRAP_21                      0x0000011DL
-#define DREG_REGID_TRAP_22                      0x0000011EL
-#define DREG_REGID_TRAP_23                      0x0000011FL
-#endif
-#endif
-#define DREG_REGID_RSA0_LOW                     0x00000200L
-#define DREG_REGID_RSA0_HIGH                    0x00000201L
-#define DREG_REGID_RSA1_LOW                     0x00000202L
-#define DREG_REGID_RSA1_HIGH                    0x00000203L
-#define DREG_REGID_RSA2                         0x00000204L
-#define DREG_REGID_RSA3                         0x00000205L
-#define DREG_REGID_RSI0_LOW                     0x00000206L
-#define DREG_REGID_RSI0_HIGH                    0x00000207L
-#define DREG_REGID_RSI1                         0x00000208L
-#define DREG_REGID_RSI2                         0x00000209L
-#define DREG_REGID_SAGUSTATUS                   0x0000020AL
-#define DREG_REGID_RSCONFIG01_LOW               0x0000020BL
-#define DREG_REGID_RSCONFIG01_HIGH              0x0000020CL
-#define DREG_REGID_RSCONFIG23_LOW               0x0000020DL
-#define DREG_REGID_RSCONFIG23_HIGH              0x0000020EL
-#define DREG_REGID_RSDMA01E                     0x0000020FL
-#define DREG_REGID_RSDMA23E                     0x00000210L
-#define DREG_REGID_RSD0_LOW                     0x00000211L
-#define DREG_REGID_RSD0_HIGH                    0x00000212L
-#define DREG_REGID_RSD1_LOW                     0x00000213L
-#define DREG_REGID_RSD1_HIGH                    0x00000214L
-#define DREG_REGID_RSD2_LOW                     0x00000215L
-#define DREG_REGID_RSD2_HIGH                    0x00000216L
-#define DREG_REGID_RSD3_LOW                     0x00000217L
-#define DREG_REGID_RSD3_HIGH                    0x00000218L
-#define DREG_REGID_SRAR_HIGH                    0x0000021AL
-#define DREG_REGID_SRAR_LOW                     0x0000021BL
-#define DREG_REGID_DMA_STATE                    0x0000021CL
-#define DREG_REGID_CURRENT_DMA_STREAM           0x0000021DL
-#define DREG_REGID_NEXT_DMA_STREAM              0x0000021EL
-#define DREG_REGID_CPU_STATUS                   0x00000300L
-#define DREG_REGID_MAC_MODE                     0x00000301L
-#define DREG_REGID_STACK_AND_REPEAT             0x00000302L
-#define DREG_REGID_INDEX0                       0x00000304L
-#define DREG_REGID_INDEX1                       0x00000305L
-#define DREG_REGID_DMA_STATE_0_3                0x00000400L
-#define DREG_REGID_DMA_STATE_4_7                0x00000404L
-#define DREG_REGID_DMA_STATE_8_11               0x00000408L
-#define DREG_REGID_DMA_STATE_12_15              0x0000040CL
-#define DREG_REGID_DMA_STATE_16_19              0x00000410L
-#define DREG_REGID_DMA_STATE_20_23              0x00000414L
-#define DREG_REGID_DMA_STATE_24_27              0x00000418L
-#define DREG_REGID_DMA_STATE_28_31              0x0000041CL
-#define DREG_REGID_DMA_STATE_32_35              0x00000420L
-#define DREG_REGID_DMA_STATE_36_39              0x00000424L
-#define DREG_REGID_DMA_STATE_40_43              0x00000428L
-#define DREG_REGID_DMA_STATE_44_47              0x0000042CL
-#define DREG_REGID_DMA_STATE_48_51              0x00000430L
-#define DREG_REGID_DMA_STATE_52_55              0x00000434L
-#define DREG_REGID_DMA_STATE_56_59              0x00000438L
-#define DREG_REGID_DMA_STATE_60_63              0x0000043CL
-#define DREG_REGID_DMA_STATE_64_67              0x00000440L
-#define DREG_REGID_DMA_STATE_68_71              0x00000444L
-#define DREG_REGID_DMA_STATE_72_75              0x00000448L
-#define DREG_REGID_DMA_STATE_76_79              0x0000044CL
-#define DREG_REGID_DMA_STATE_80_83              0x00000450L
-#define DREG_REGID_DMA_STATE_84_87              0x00000454L
-#define DREG_REGID_DMA_STATE_88_91              0x00000458L
-#define DREG_REGID_DMA_STATE_92_95              0x0000045CL
-#define DREG_REGID_TRAP_SELECT                  0x00000500L
-#define DREG_REGID_TRAP_WRITE_0                 0x00000500L
-#define DREG_REGID_TRAP_WRITE_1                 0x00000501L
-#define DREG_REGID_TRAP_WRITE_2                 0x00000502L
-#define DREG_REGID_TRAP_WRITE_3                 0x00000503L
-#define DREG_REGID_TRAP_WRITE_4                 0x00000504L
-#define DREG_REGID_TRAP_WRITE_5                 0x00000505L
-#define DREG_REGID_TRAP_WRITE_6                 0x00000506L
-#define DREG_REGID_TRAP_WRITE_7                 0x00000507L
-#if !defined(NO_CS4612)
-#if !defined(NO_CS4615)
-#define DREG_REGID_TRAP_WRITE_8                 0x00000510L
-#define DREG_REGID_TRAP_WRITE_9                 0x00000511L
-#define DREG_REGID_TRAP_WRITE_10                0x00000512L
-#define DREG_REGID_TRAP_WRITE_11                0x00000513L
-#define DREG_REGID_TRAP_WRITE_12                0x00000514L
-#define DREG_REGID_TRAP_WRITE_13                0x00000515L
-#define DREG_REGID_TRAP_WRITE_14                0x00000516L
-#define DREG_REGID_TRAP_WRITE_15                0x00000517L
-#define DREG_REGID_TRAP_WRITE_16                0x00000518L
-#define DREG_REGID_TRAP_WRITE_17                0x00000519L
-#define DREG_REGID_TRAP_WRITE_18                0x0000051AL
-#define DREG_REGID_TRAP_WRITE_19                0x0000051BL
-#define DREG_REGID_TRAP_WRITE_20                0x0000051CL
-#define DREG_REGID_TRAP_WRITE_21                0x0000051DL
-#define DREG_REGID_TRAP_WRITE_22                0x0000051EL
-#define DREG_REGID_TRAP_WRITE_23                0x0000051FL
-#endif
-#endif
-#define DREG_REGID_MAC0_ACC0_LOW                0x00000600L
-#define DREG_REGID_MAC0_ACC1_LOW                0x00000601L
-#define DREG_REGID_MAC0_ACC2_LOW                0x00000602L
-#define DREG_REGID_MAC0_ACC3_LOW                0x00000603L
-#define DREG_REGID_MAC1_ACC0_LOW                0x00000604L
-#define DREG_REGID_MAC1_ACC1_LOW                0x00000605L
-#define DREG_REGID_MAC1_ACC2_LOW                0x00000606L
-#define DREG_REGID_MAC1_ACC3_LOW                0x00000607L
-#define DREG_REGID_MAC0_ACC0_MID                0x00000608L
-#define DREG_REGID_MAC0_ACC1_MID                0x00000609L
-#define DREG_REGID_MAC0_ACC2_MID                0x0000060AL
-#define DREG_REGID_MAC0_ACC3_MID                0x0000060BL
-#define DREG_REGID_MAC1_ACC0_MID                0x0000060CL
-#define DREG_REGID_MAC1_ACC1_MID                0x0000060DL
-#define DREG_REGID_MAC1_ACC2_MID                0x0000060EL
-#define DREG_REGID_MAC1_ACC3_MID                0x0000060FL
-#define DREG_REGID_MAC0_ACC0_HIGH               0x00000610L
-#define DREG_REGID_MAC0_ACC1_HIGH               0x00000611L
-#define DREG_REGID_MAC0_ACC2_HIGH               0x00000612L
-#define DREG_REGID_MAC0_ACC3_HIGH               0x00000613L
-#define DREG_REGID_MAC1_ACC0_HIGH               0x00000614L
-#define DREG_REGID_MAC1_ACC1_HIGH               0x00000615L
-#define DREG_REGID_MAC1_ACC2_HIGH               0x00000616L
-#define DREG_REGID_MAC1_ACC3_HIGH               0x00000617L
-#define DREG_REGID_RSHOUT_LOW                   0x00000620L
-#define DREG_REGID_RSHOUT_MID                   0x00000628L
-#define DREG_REGID_RSHOUT_HIGH                  0x00000630L
-
-//****************************************************************************
-//
-// The following defines are for the flags in the AC97 S/PDIF Control register.
-//
-//****************************************************************************
-#define SPDIF_CONTROL_SPDIF_EN                 0x00008000L
-#define SPDIF_CONTROL_VAL                      0x00004000L
-#define SPDIF_CONTROL_COPY                     0x00000004L
-#define SPDIF_CONTROL_CC0                      0x00000010L
-#define SPDIF_CONTROL_CC1                      0x00000020L
-#define SPDIF_CONTROL_CC2                      0x00000040L
-#define SPDIF_CONTROL_CC3                      0x00000080L
-#define SPDIF_CONTROL_CC4                      0x00000100L
-#define SPDIF_CONTROL_CC5                      0x00000200L
-#define SPDIF_CONTROL_CC6                      0x00000400L
-#define SPDIF_CONTROL_L                        0x00000800L
-
-#endif // _H_HWDEFS
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/cs46xx.c linux/drivers/sound/cs46xx.c
--- v2.4.1/linux/drivers/sound/cs46xx.c	Mon Jan  1 11:24:54 2001
+++ linux/drivers/sound/cs46xx.c	Fri Feb  9 11:30:23 2001
@@ -58,7 +58,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #ifdef CS46XX_PM
@@ -139,19 +139,18 @@
 
 #if CSDEBUG
 static unsigned long cs_debuglevel=1;			/* levels range from 1-9 */
+MODULE_PARM(cs_debuglevel, "i");
 static unsigned long cs_debugmask=CS_INIT | CS_ERROR;	/* use CS_DBGOUT with various mask values */
+MODULE_PARM(cs_debugmask, "i");
 #endif
 #define DMABUF_DEFAULTORDER 3
 static unsigned long defaultorder=DMABUF_DEFAULTORDER;
-#if MODULE
 MODULE_PARM(defaultorder, "i");
-MODULE_PARM(cs_debuglevel, "i");
-MODULE_PARM(cs_debugmask, "i");
-#endif
-
-static int external_amp = 0;
-static int thinkpad = 0;
 
+static int external_amp;
+MODULE_PARM(external_amp, "i");
+static int thinkpad;
+MODULE_PARM(thinkpad, "i");
 
 /* An instance of the 4610 channel */
 
@@ -312,7 +311,7 @@
 	} midi;
 };
 
-static struct cs_card *devs = NULL;
+static struct cs_card *devs;
 
 static int cs_open_mixdev(struct inode *inode, struct file *file);
 static int cs_release_mixdev(struct inode *inode, struct file *file);
@@ -320,7 +319,7 @@
 				unsigned long arg);
 static loff_t cs_llseek(struct file *file, loff_t offset, int origin);
 
-extern __inline__ unsigned ld2(unsigned int x)
+static inline unsigned ld2(unsigned int x)
 {
 	unsigned r = 0;
 	
@@ -905,7 +904,7 @@
 /* get current playback/recording dma buffer pointer (byte offset from LBA),
    called with spinlock held! */
    
-extern __inline__ unsigned cs_get_dma_addr(struct cs_state *state)
+static inline unsigned cs_get_dma_addr(struct cs_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
 	u32 offset;
@@ -950,7 +949,7 @@
 }
 	
 /* Stop recording (lock held) */
-extern __inline__ void __stop_adc(struct cs_state *state)
+static inline void __stop_adc(struct cs_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
 	struct cs_card *card = state->card;
@@ -999,7 +998,7 @@
 }
 
 /* stop playback (lock held) */
-extern __inline__ void __stop_dac(struct cs_state *state)
+static inline void __stop_dac(struct cs_state *state)
 {
 	struct dmabuf *dmabuf = &state->dmabuf;
 	struct cs_card *card = state->card;
@@ -1766,6 +1765,7 @@
  *   Midi file operations struct.
  */
 static /*const*/ struct file_operations cs_midi_fops = {
+	owner:		THIS_MODULE,
         llseek:		cs_llseek,
         read:		cs_midi_read,
         write:		cs_midi_write,
@@ -3144,6 +3144,7 @@
 }
 
 static /*const*/ struct file_operations cs461x_fops = {
+	owner:		THIS_MODULE,
 	llseek:		cs_llseek,
 	read:		cs_read,
 	write:		cs_write,
@@ -3352,7 +3353,7 @@
 
 static int cs_open_mixdev(struct inode *inode, struct file *file)
 {
-	int i;
+	int i=0;
 	int minor = MINOR(inode->i_rdev);
 	struct cs_card *card = devs;
 
@@ -3437,6 +3438,7 @@
 }
 
 static /*const*/ struct file_operations cs_mixer_fops = {
+	owner:		THIS_MODULE,
 	llseek:		cs_llseek,
 	ioctl:		cs_ioctl_mixdev,
 	open:		cs_open_mixdev,
@@ -4233,16 +4235,18 @@
 MODULE_AUTHOR("Alan Cox <alan@redhat.com>, Jaroslav Kysela, <audio@crystal.cirrus.com>");
 MODULE_DESCRIPTION("Crystal SoundFusion Audio Support");
 
-int __init cs_probe(void)
+static char banner[] __initdata = KERN_INFO "Crystal 4280/461x + AC97 Audio, version " DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n";
+static char fndmsg[] __initdata = KERN_INFO "cs461x: Found %d audio device(s).\n";
+
+static int __init cs_init_driver(void)
 {
 	struct pci_dev *pcidev = NULL;
 	int foundone=0;
-	
+
 	if (!pci_present())   /* No PCI bus in this machine! */
 		return -ENODEV;
-		
-	printk(KERN_INFO "Crystal 4280/461x + AC97 Audio, version "
-	       DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
+
+	printk(banner);
 
 	while( (pcidev = pci_find_device(PCI_VENDOR_ID_CIRRUS, 0x6001 , pcidev))!=NULL ) {
 		if (cs_install(pcidev)==0)
@@ -4257,19 +4261,11 @@
 			foundone++;
 	}
 
-	printk(KERN_INFO "cs461x: Found %d audio device(s).\n",
-		foundone);
-	return foundone;
-}
-
-int __init init_module(void)
-{
-	if(cs_probe()==0)
-		printk(KERN_ERR "cs461x: No devices found.\n");
-	return 0;
+	printk(fndmsg, foundone);
+	return foundone ? 0 : -ENODEV;
 }
 
-void __exit cleanup_module (void)
+static void __exit cs_exit_driver(void)
 {
 	struct cs_card *next;
 #ifdef CS46XX_PM
@@ -4283,5 +4279,5 @@
 	}
 }
 
-MODULE_PARM(external_amp, "i");
-MODULE_PARM(thinkpad, "i");
+module_init(cs_init_driver);
+module_exit(cs_exit_driver);
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/dev_table.h linux/drivers/sound/dev_table.h
--- v2.4.1/linux/drivers/sound/dev_table.h	Fri Aug 11 08:26:43 2000
+++ linux/drivers/sound/dev_table.h	Sun Feb  4 10:05:29 2001
@@ -150,6 +150,7 @@
 typedef struct coproc_operations 
 {
 	char name[64];
+	struct module *owner;
 	int (*open) (void *devc, int sub_device);
 	void (*close) (void *devc, int sub_device);
 	int (*ioctl) (void *devc, unsigned int cmd, caddr_t arg, int local);
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/dmasound/dmasound_awacs.c linux/drivers/sound/dmasound/dmasound_awacs.c
--- v2.4.1/linux/drivers/sound/dmasound/dmasound_awacs.c	Sun Sep 17 09:48:05 2000
+++ linux/drivers/sound/dmasound/dmasound_awacs.c	Fri Feb  9 11:30:23 2001
@@ -10,12 +10,13 @@
 
 #include <linux/module.h>
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/soundcard.h>
 #include <linux/adb.h>
 #include <linux/nvram.h>
+#include <linux/tty.h>
 #include <linux/vt_kern.h>
 #ifdef CONFIG_ADB_CUDA
 #include <linux/cuda.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/dmasound/dmasound_core.c linux/drivers/sound/dmasound/dmasound_core.c
--- v2.4.1/linux/drivers/sound/dmasound/dmasound_core.c	Sat Nov 11 18:19:56 2000
+++ linux/drivers/sound/dmasound/dmasound_core.c	Fri Feb  9 11:30:23 2001
@@ -107,7 +107,7 @@
 
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sound.h>
 #include <linux/init.h>
 #include <linux/soundcard.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/dmasound/dmasound_q40.c linux/drivers/sound/dmasound/dmasound_q40.c
--- v2.4.1/linux/drivers/sound/dmasound/dmasound_q40.c	Tue Apr 25 17:58:46 2000
+++ linux/drivers/sound/dmasound/dmasound_q40.c	Fri Feb  9 11:30:23 2001
@@ -10,7 +10,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/emu10k1/audio.c linux/drivers/sound/emu10k1/audio.c
--- v2.4.1/linux/drivers/sound/emu10k1/audio.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sound/emu10k1/audio.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #define __NO_VERSION__
 #include <linux/module.h>
 #include <linux/poll.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/bitops.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/emu10k1/cardmi.c linux/drivers/sound/emu10k1/cardmi.c
--- v2.4.1/linux/drivers/sound/emu10k1/cardmi.c	Mon Aug 14 08:32:48 2000
+++ linux/drivers/sound/emu10k1/cardmi.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
  **********************************************************************
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 
 #include "hwaccess.h"
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/emu10k1/cardmo.c linux/drivers/sound/emu10k1/cardmo.c
--- v2.4.1/linux/drivers/sound/emu10k1/cardmo.c	Mon Aug 14 08:32:48 2000
+++ linux/drivers/sound/emu10k1/cardmo.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
  ********************************************************************** 
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include "hwaccess.h"
 #include "8010.h"
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/emu10k1/ecard.h linux/drivers/sound/emu10k1/ecard.h
--- v2.4.1/linux/drivers/sound/emu10k1/ecard.h	Mon Dec 11 13:02:22 2000
+++ linux/drivers/sound/emu10k1/ecard.h	Sun Feb  4 10:05:29 2001
@@ -99,7 +99,7 @@
 #define HC_EA 0x01L
 
 /* ECARD state structure.  This structure maintains the state
- * for various portions of the the ECARD's onboard hardware.
+ * for various portions of the ECARD's onboard hardware.
  */
 struct ecard_state {
 	u32 control_bits;
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/emu10k1/main.c linux/drivers/sound/emu10k1/main.c
--- v2.4.1/linux/drivers/sound/emu10k1/main.c	Thu Sep 21 13:25:09 2000
+++ linux/drivers/sound/emu10k1/main.c	Fri Feb  9 11:30:23 2001
@@ -52,7 +52,7 @@
 /* These are only included once per module */
 #include <linux/version.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/emu10k1/midi.c linux/drivers/sound/emu10k1/midi.c
--- v2.4.1/linux/drivers/sound/emu10k1/midi.c	Thu Sep 21 13:25:09 2000
+++ linux/drivers/sound/emu10k1/midi.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 
 #define __NO_VERSION__
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/version.h>
 #include <linux/sched.h>
 #include <linux/smp_lock.h>
@@ -85,7 +85,7 @@
 static int emu10k1_midi_open(struct inode *inode, struct file *file)
 {
 	int minor = MINOR(inode->i_rdev);
-	struct emu10k1_card *card;
+	struct emu10k1_card *card=NULL;
 	struct emu10k1_mididevice *midi_dev;
 	struct list_head *entry;
 
@@ -423,6 +423,7 @@
 		break;
 
 	default:		/* Unknown message */
+		spin_unlock_irqrestore(&midi_spinlock, flags);
 		return -1;
 	}
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/es1370.c linux/drivers/sound/es1370.c
--- v2.4.1/linux/drivers/sound/es1370.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/es1370.c	Fri Feb  9 11:30:23 2001
@@ -146,7 +146,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/es1371.c linux/drivers/sound/es1371.c
--- v2.4.1/linux/drivers/sound/es1371.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/es1371.c	Fri Feb  9 11:30:23 2001
@@ -113,7 +113,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/esssolo1.c linux/drivers/sound/esssolo1.c
--- v2.4.1/linux/drivers/sound/esssolo1.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/esssolo1.c	Fri Feb  9 11:30:23 2001
@@ -81,7 +81,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/i810_audio.c linux/drivers/sound/i810_audio.c
--- v2.4.1/linux/drivers/sound/i810_audio.c	Thu Jan  4 12:50:17 2001
+++ linux/drivers/sound/i810_audio.c	Fri Feb 16 16:02:37 2001
@@ -73,7 +73,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <asm/io.h>
@@ -879,7 +879,9 @@
 					dmabuf->endcleared = 1;
 				}
 			}			
-			wake_up(&dmabuf->wait);
+			if (dmabuf->count < (signed)dmabuf->dmasize/2) {
+				wake_up(&dmabuf->wait);
+			}
 		}
 	}
 	/* error handling and process wake up for DAC */
@@ -896,10 +898,12 @@
 				   it here, just stop the machine and let the process force hwptr
 				   and swptr to sync */
 				__stop_dac(state);
-				printk("DMA overrun on send\n");
+				printk(KERN_WARNING "i810_audio: DMA overrun on send\n");
 				dmabuf->error++;
 			}
-			wake_up(&dmabuf->wait);
+			if (dmabuf->count < (signed)dmabuf->dmasize/2) {
+				wake_up(&dmabuf->wait);
+			}
 		}
 	}
 }
@@ -1047,7 +1051,7 @@
 				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
 				       dmabuf->hwptr, dmabuf->swptr);
 #endif
-				/* a buffer overrun, we delay the recovery untill next time the
+				/* a buffer overrun, we delay the recovery until next time the
 				   while loop begin and we REALLY have space to record */
 			}
 			if (signal_pending(current)) {
@@ -1144,7 +1148,7 @@
 				       dmabuf->dmasize, dmabuf->fragsize, dmabuf->count,
 				       dmabuf->hwptr, dmabuf->swptr);
 #endif
-				/* a buffer underrun, we delay the recovery untill next time the
+				/* a buffer underrun, we delay the recovery until next time the
 				   while loop begin and we REALLY have data to play */
 			}
 			if (signal_pending(current)) {
@@ -1823,7 +1827,7 @@
 }
 
 /* install the driver, we do not allocate hardware channel nor DMA buffer now, they are defered 
-   untill "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
+   until "ACCESS" time (in prog_dmabuf called by open/read/write/ioctl/mmap) */
    
 static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
 {
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/maestro.c linux/drivers/sound/maestro.c
--- v2.4.1/linux/drivers/sound/maestro.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/maestro.c	Fri Feb  9 11:30:23 2001
@@ -231,7 +231,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/maestro3.c linux/drivers/sound/maestro3.c
--- v2.4.1/linux/drivers/sound/maestro3.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/maestro3.c	Fri Feb 16 16:02:37 2001
@@ -0,0 +1,2952 @@
+/*****************************************************************************
+ *
+ *      ESS Maestro3/Allegro driver for Linux 2.4.x
+ *
+ *      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.
+ *
+ *    (c) Copyright 2000 Zach Brown <zab@zabbo.net>
+ *
+ * I need to thank many people for helping make this driver happen.  
+ * As always, Eric Brombaugh was a hacking machine and killed many bugs
+ * that I was too dumb to notice.  Howard Kim at ESS provided reference boards 
+ * and as much docs as he could.  Todd and Mick at Dell tested snapshots on 
+ * an army of laptops.  msw and deviant at Red Hat also humoured me by hanging
+ * their laptops every few hours in the name of science.
+ * 
+ * Shouts go out to Mike "DJ XPCom" Ang.
+ *
+ * History
+ *  v1.21 - Feb 04 2001 - Zach Brown <zab@zabbo.net>
+ *   fix up really dumb notifier -> suspend oops
+ *  v1.20 - Jan 30 2001 - Zach Brown <zab@zabbo.net>
+ *   get rid of pm callback and use pci_dev suspend/resume instead
+ *   m3_probe cleanups, including pm oops think-o
+ *  v1.10 - Jan 6 2001 - Zach Brown <zab@zabbo.net>
+ *   revert to lame remap_page_range mmap() just to make it work
+ *   record mmap fixed.
+ *   fix up incredibly broken open/release resource management
+ *   duh.  fix record format setting.
+ *   add SMP locking and cleanup formatting here and there
+ *  v1.00 - Dec 16 2000 - Zach Brown <zab@zabbo.net>
+ *   port to sexy 2.4 interfaces
+ *   properly align instance allocations so recording works
+ *   clean up function namespace a little :/
+ *   update PCI IDs based on mail from ESS
+ *   arbitrarily bump version number to show its 2.4 now, 
+ *      2.2 will stay 0., oss_audio port gets 2.
+ *  v0.03 - Nov 05 2000 - Zach Brown <zab@zabbo.net>
+ *   disable recording but allow dsp to be opened read 
+ *   pull out most silly compat defines
+ *  v0.02 - Nov 04 2000 - Zach Brown <zab@zabbo.net>
+ *   changed clocking setup for m3, slowdown fixed.
+ *   codec reset is hopefully reliable now
+ *   rudimentary apm/power management makes suspend/resume work
+ *  v0.01 - Oct 31 2000 - Zach Brown <zab@zabbo.net>
+ *   first release
+ *  v0.00 - Sep 09 2000 - Zach Brown <zab@zabbo.net>
+ *   first pass derivation from maestro.c
+ *
+ * TODO
+ *  in/out allocated contiguously so fullduplex mmap will work?
+ *  no beep on init (mute)
+ *  resetup msrc data memory if freq changes?
+ *
+ *  --
+ *
+ *  Allow me to ramble a bit about the m3 architecture.  The core of the
+ *  chip is the 'assp', the custom ESS dsp that runs the show.  It has
+ *  a small amount of code and data ram.  ESS drops binary dsp code images
+ *  on our heads, but we don't get to see specs on the dsp.  
+ *
+ *  The constant piece of code on the dsp is the 'kernel'.  It also has a 
+ *  chunk of the dsp memory that is statically set aside for its control
+ *  info.  This is the KDATA defines in maestro3.h.  Part of its core
+ *  data is a list of code addresses that point to the pieces of DSP code
+ *  that it should walk through in its loop.  These other pieces of code
+ *  do the real work.  The kernel presumably jumps into each of them in turn.
+ *  These code images tend to have their own data area, and one can have
+ *  multiple data areas representing different states for each of the 'client
+ *  instance' code portions.  There is generaly a list in the kernel data
+ *  that points to the data instances for a given piece of code.
+ *
+ *  We've only been given the binary image for the 'minisrc', mini sample 
+ *  rate converter.  This is rather annoying because it limits the work
+ *  we can do on the dsp, but it also greatly simplifies the job of managing
+ *  dsp data memory for the code and data for our playing streams :).  We
+ *  statically allocate the minisrc code into a region we 'know' to be free
+ *  based on the map of the binary kernel image we're loading.  We also 
+ *  statically allocate the data areas for the maximum number of pcm streams
+ *  we can be dealing with.  This max is set by the length of the static list
+ *  in the kernel data that records the number of minisrc data regions we
+ *  can have.  Thats right, all software dsp mixing with static code list
+ *  limits.  Rock.
+ *
+ *  How sound goes in and out is still a relative mystery.  It appears
+ *  that the dsp has the ability to get input and output through various
+ *  'connections'.  To do IO from or to a connection, you put the address
+ *  of the minisrc client area in the static kernel data lists for that 
+ *  input or output.  so for pcm -> dsp -> mixer, we put the minisrc data
+ *  instance in the DMA list and also in the list for the mixer.  I guess
+ *  it Just Knows which is in/out, and we give some dma control info that
+ *  helps.  There are all sorts of cool inputs/outputs that it seems we can't
+ *  use without dsp code images that know how to use them.
+ *
+ *  So at init time we preload all the memory allocation stuff and set some
+ *  system wide parameters.  When we really get a sound to play we build
+ *  up its minisrc header (stream parameters, buffer addresses, input/output
+ *  settings).  Then we throw its header on the various lists.  We also
+ *  tickle some KDATA settings that ask the assp to raise clock interrupts
+ *  and do some amount of software mixing before handing data to the ac97.
+ *
+ *  Sorry for the vague details.  Feel free to ask Eric or myself if you
+ *  happen to be trying to use this driver elsewhere.  Please accept my
+ *  apologies for the quality of the OSS support code, its passed through
+ *  too many hands now and desperately wants to be rethought.
+ */
+
+/*****************************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/sound.h>
+#include <linux/malloc.h>
+#include <linux/soundcard.h>
+#include <linux/pci.h>
+#include <linux/vmalloc.h>
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/reboot.h>
+#include <asm/uaccess.h>
+#include <asm/hardirq.h>
+#include <linux/spinlock.h>
+#include <linux/ac97_codec.h>
+
+ /*
+  * for crizappy mmap()
+  */
+#include <linux/wrapper.h>
+
+#include "maestro3.h"
+
+#define M_DEBUG 1
+
+#define DRIVER_VERSION      "1.21"
+#define M3_MODULE_NAME      "maestro3"
+#define PFX                 M3_MODULE_NAME ": "
+
+#define M3_STATE_MAGIC      0x734d724d
+#define M3_CARD_MAGIC       0x646e6f50
+
+#define ESS_FMT_STEREO      0x01
+#define ESS_FMT_16BIT       0x02
+#define ESS_FMT_MASK        0x03
+#define ESS_DAC_SHIFT       0   
+#define ESS_ADC_SHIFT       4
+
+#define DAC_RUNNING         1
+#define ADC_RUNNING         2
+
+#define SND_DEV_DSP16       5 
+   
+#ifdef M_DEBUG
+static int debug=0;
+#define DPMOD   1   /* per module load */
+#define DPSTR   2   /* per 'stream' */
+#define DPSYS   3   /* per syscall */
+#define DPCRAP  4   /* stuff the user shouldn't see unless they're really debuggin */
+#define DPINT   5   /* per interrupt, LOTS */
+#define DPRINTK(DP, args...) {if (debug >= (DP)) printk(KERN_DEBUG PFX args);}
+#else
+#define DPRINTK(x)
+#endif
+
+struct m3_list {
+    int curlen;
+    u16 mem_addr;
+    int max;
+};
+
+int external_amp = 1;
+
+struct m3_state {
+    unsigned int magic;
+    struct m3_card *card;
+    unsigned char fmt, enable;
+
+    int index;
+
+    /* this locks around the oss state in the driver */
+    spinlock_t lock;
+
+    struct semaphore open_sem;
+    wait_queue_head_t open_wait;
+    mode_t open_mode;
+
+    int dev_audio;
+
+    struct assp_instance {
+        u16 code, data;
+    } dac_inst, adc_inst;
+
+    /* should be in dmabuf */
+    unsigned int rateadc, ratedac;
+
+    struct dmabuf {
+        void *rawbuf;
+        unsigned buforder;
+        unsigned numfrag;
+        unsigned fragshift;
+        unsigned hwptr, swptr;
+        unsigned total_bytes;
+        int count;
+        unsigned error; /* over/underrun */
+        wait_queue_head_t wait;
+        /* redundant, but makes calculations easier */
+        unsigned fragsize;
+        unsigned dmasize;
+        unsigned fragsamples;
+        /* OSS stuff */
+        unsigned mapped:1;
+        unsigned ready:1;    
+        unsigned endcleared:1;
+        unsigned ossfragshift;
+        int ossmaxfrags;
+        unsigned subdivision;
+        /* new in m3 */
+        int mixer_index, dma_index, msrc_index, adc1_index;
+        int in_lists;
+        /* 2.4.. */
+        dma_addr_t handle;
+
+    } dma_dac, dma_adc;
+};
+    
+struct m3_card {
+    unsigned int magic;
+
+    struct m3_card *next;
+
+    struct ac97_codec *ac97;
+    spinlock_t ac97_lock;
+
+    int card_type;
+
+#define NR_DSPS 1
+#define MAX_DSPS NR_DSPS
+    struct m3_state channels[MAX_DSPS];
+
+    /* this locks around the physical registers on the card */
+    spinlock_t lock;
+
+    /* hardware resources */
+    struct pci_dev *pcidev;
+    u32 iobase;
+    u32 irq;
+
+    int dacs_active;
+
+    int timer_users;
+
+    struct m3_list  msrc_list,
+                    mixer_list,
+                    adc1_list,
+                    dma_list;
+
+    /* for storing reset state..*/
+    u8 reset_state;
+
+    u16 *suspend_mem;
+    int in_suspend;
+    wait_queue_head_t suspend_queue;
+};
+
+/*
+ * an arbitrary volume we set the internal
+ * volume settings to so that the ac97 volume
+ * range is a little less insane.  0x7fff is 
+ * max.
+ */
+#define ARB_VOLUME ( 0x6800 )
+
+static const unsigned sample_shift[] = { 0, 1, 1, 2 };
+
+enum {
+    ESS_ALLEGRO,
+    ESS_MAESTRO3,
+    /*
+     * a maestro3 with 'hardware strapping', only
+     * found inside ESS?
+     */
+    ESS_MAESTRO3HW,
+};
+
+static char *card_names[] = {
+    [ESS_ALLEGRO] = "Allegro",
+    [ESS_MAESTRO3] = "Maestro3(i)",
+    [ESS_MAESTRO3HW] = "Maestro3(i)hw"
+};
+
+#ifndef PCI_VENDOR_ESS
+#define PCI_VENDOR_ESS      0x125D
+#endif
+
+#define M3_DEVICE(DEV, TYPE)                \
+{                                           \
+vendor: PCI_VENDOR_ESS,                     \
+device: DEV,                                \
+subvendor: PCI_ANY_ID,                      \
+subdevice: PCI_ANY_ID,                      \
+class:  PCI_CLASS_MULTIMEDIA_AUDIO << 8,    \
+class_mask: 0xffff << 8,                    \
+driver_data: TYPE,                          \
+}
+
+static struct pci_device_id m3_id_table[] __initdata = {
+    M3_DEVICE(0x1988, ESS_ALLEGRO),
+    M3_DEVICE(0x1998, ESS_MAESTRO3),
+    M3_DEVICE(0x199a, ESS_MAESTRO3HW),
+    {0,}
+};
+
+MODULE_DEVICE_TABLE (pci, m3_id_table);
+
+static unsigned 
+ld2(unsigned int x)
+{
+    unsigned r = 0;
+    
+    if (x >= 0x10000) {
+        x >>= 16;
+        r += 16;
+    }
+    if (x >= 0x100) {
+        x >>= 8;
+        r += 8;
+    }
+    if (x >= 0x10) {
+        x >>= 4;
+        r += 4;
+    }
+    if (x >= 4) {
+        x >>= 2;
+        r += 2;
+    }
+    if (x >= 2)
+        r++;
+    return r;
+}
+
+static struct m3_card *devs = NULL;
+
+/*
+ * I'm not very good at laying out functions in a file :)
+ */
+static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf);
+static void m3_suspend(struct pci_dev *pci_dev);
+static void check_suspend(struct m3_card *card);
+
+struct notifier_block m3_reboot_nb = {m3_notifier, NULL, 0};
+
+static void m3_outw(struct m3_card *card,
+        u16 value, unsigned long reg)
+{
+    check_suspend(card);
+    outw(value, card->iobase + reg);
+}
+
+static u16 m3_inw(struct m3_card *card, unsigned long reg)
+{
+    check_suspend(card);
+    return inw(card->iobase + reg);
+}
+static void m3_outb(struct m3_card *card, 
+        u8 value, unsigned long reg)
+{
+    check_suspend(card);
+    outb(value, card->iobase + reg);
+}
+static u8 m3_inb(struct m3_card *card, unsigned long reg)
+{
+    check_suspend(card);
+    return inb(card->iobase + reg);
+}
+
+/*
+ * access 16bit words to the code or data regions of the dsp's memory.
+ * index addresses 16bit words.
+ */
+static u16 __m3_assp_read(struct m3_card *card, u16 region, u16 index)
+{
+    m3_outw(card, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE);
+    m3_outw(card, index, DSP_PORT_MEMORY_INDEX);
+    return m3_inw(card, DSP_PORT_MEMORY_DATA);
+}
+static u16 m3_assp_read(struct m3_card *card, u16 region, u16 index)
+{
+    unsigned long flags;
+    u16 ret;
+
+    spin_lock_irqsave(&(card->lock), flags);
+    ret = __m3_assp_read(card, region, index);
+    spin_unlock_irqrestore(&(card->lock), flags);
+
+    return ret;
+}
+
+static void __m3_assp_write(struct m3_card *card, 
+        u16 region, u16 index, u16 data)
+{
+    m3_outw(card, region & MEMTYPE_MASK, DSP_PORT_MEMORY_TYPE);
+    m3_outw(card, index, DSP_PORT_MEMORY_INDEX);
+    m3_outw(card, data, DSP_PORT_MEMORY_DATA);
+}
+static void m3_assp_write(struct m3_card *card, 
+        u16 region, u16 index, u16 data)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&(card->lock), flags);
+    __m3_assp_write(card, region, index, data);
+    spin_unlock_irqrestore(&(card->lock), flags);
+}
+
+static void m3_assp_halt(struct m3_card *card)
+{
+    card->reset_state = m3_inb(card, DSP_PORT_CONTROL_REG_B) & ~REGB_STOP_CLOCK;
+    mdelay(10);
+    m3_outb(card, card->reset_state & ~REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);
+}
+
+static void m3_assp_continue(struct m3_card *card)
+{
+    m3_outb(card, card->reset_state | REGB_ENABLE_RESET, DSP_PORT_CONTROL_REG_B);
+}
+
+/*
+ * This makes me sad. the maestro3 has lists
+ * internally that must be packed.. 0 terminates,
+ * apparently, or maybe all unused entries have
+ * to be 0, the lists have static lengths set
+ * by the binary code images.
+ */
+
+static int m3_add_list(struct m3_card *card,
+        struct m3_list *list, u16 val)
+{
+    DPRINTK(DPSTR, "adding val 0x%x to list 0x%p at pos %d\n",
+            val, list, list->curlen);
+
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+            list->mem_addr + list->curlen,
+            val);
+
+    return list->curlen++;
+
+}
+
+static void m3_remove_list(struct m3_card *card,
+        struct m3_list *list, int index)
+{
+    u16  val;
+    int lastindex = list->curlen - 1;
+
+    DPRINTK(DPSTR, "removing ind %d from list 0x%p\n",
+            index, list);
+
+    if(index != lastindex) {
+        val = m3_assp_read(card, MEMTYPE_INTERNAL_DATA,
+                list->mem_addr + lastindex);
+        m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+                list->mem_addr + index,
+                val);
+    }
+
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+            list->mem_addr + lastindex,
+            0);
+
+    list->curlen--;
+}
+
+static void set_fmt(struct m3_state *s, unsigned char mask, unsigned char data)
+{
+    int tmp;
+
+    s->fmt = (s->fmt & mask) | data;
+
+    tmp = (s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK;
+
+    /* write to 'mono' word */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->dac_inst.data + SRC3_DIRECTION_OFFSET + 1, 
+            (tmp & ESS_FMT_STEREO) ? 0 : 1);
+    /* write to '8bit' word */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->dac_inst.data + SRC3_DIRECTION_OFFSET + 2, 
+            (tmp & ESS_FMT_16BIT) ? 0 : 1);
+
+    tmp = (s->fmt >> ESS_ADC_SHIFT) & ESS_FMT_MASK;
+
+    /* write to 'mono' word */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->adc_inst.data + SRC3_DIRECTION_OFFSET + 1, 
+            (tmp & ESS_FMT_STEREO) ? 0 : 1);
+    /* write to '8bit' word */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->adc_inst.data + SRC3_DIRECTION_OFFSET + 2, 
+            (tmp & ESS_FMT_16BIT) ? 0 : 1);
+}
+
+static void set_dac_rate(struct m3_state *s, unsigned int rate)
+{
+    u32 freq;
+
+    if (rate > 48000)
+        rate = 48000;
+    if (rate < 8000)
+        rate = 8000;
+
+    s->ratedac = rate;
+
+    freq = ((rate << 15) + 24000 ) / 48000;
+    if(freq) 
+        freq--;
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->dac_inst.data + CDATA_FREQUENCY,
+            freq);
+}
+
+static void set_adc_rate(struct m3_state *s, unsigned int rate)
+{
+    u32 freq;
+
+    if (rate > 48000)
+        rate = 48000;
+    if (rate < 8000)
+        rate = 8000;
+
+    s->rateadc = rate;
+
+    freq = ((rate << 15) + 24000 ) / 48000;
+    if(freq) 
+        freq--;
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->adc_inst.data + CDATA_FREQUENCY,
+            freq);
+}
+
+static void inc_timer_users(struct m3_card *card)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&card->lock, flags);
+    
+    card->timer_users++;
+    DPRINTK(DPSYS, "inc timer users now %d\n",
+            card->timer_users);
+    if(card->timer_users != 1) 
+        goto out;
+
+    __m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+        KDATA_TIMER_COUNT_RELOAD,
+         240 ) ;
+
+    __m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+        KDATA_TIMER_COUNT_CURRENT,
+         240 ) ;
+
+    m3_outw(card,  
+            m3_inw(card, HOST_INT_CTRL) | CLKRUN_GEN_ENABLE,
+            HOST_INT_CTRL);
+out:
+    spin_unlock_irqrestore(&card->lock, flags);
+}
+
+static void dec_timer_users(struct m3_card *card)
+{
+    unsigned long flags;
+
+    spin_lock_irqsave(&card->lock, flags);
+
+    card->timer_users--;
+    DPRINTK(DPSYS, "dec timer users now %d\n",
+            card->timer_users);
+    if(card->timer_users > 0 ) 
+        goto out;
+
+    __m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+        KDATA_TIMER_COUNT_RELOAD,
+         0 ) ;
+
+    __m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+        KDATA_TIMER_COUNT_CURRENT,
+         0 ) ;
+
+    m3_outw(card,  m3_inw(card, HOST_INT_CTRL) & ~CLKRUN_GEN_ENABLE,
+            HOST_INT_CTRL);
+out:
+    spin_unlock_irqrestore(&card->lock, flags);
+}
+
+/*
+ * {start,stop}_{adc,dac} should be called
+ * while holding the 'state' lock and they
+ * will try to grab the 'card' lock..
+ */
+static void stop_adc(struct m3_state *s)
+{
+    if (! (s->enable & ADC_RUNNING)) 
+        return;
+
+    s->enable &= ~ADC_RUNNING;
+    dec_timer_users(s->card);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->adc_inst.data + CDATA_INSTANCE_READY, 0);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            KDATA_ADC1_REQUEST, 0);
+}    
+
+static void stop_dac(struct m3_state *s)
+{
+    if (! (s->enable & DAC_RUNNING)) 
+        return;
+
+    DPRINTK(DPSYS, "stop_dac()\n");
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->dac_inst.data + CDATA_INSTANCE_READY, 0);
+
+    s->enable &= ~DAC_RUNNING;
+    s->card->dacs_active--;
+    dec_timer_users(s->card);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            KDATA_MIXER_TASK_NUMBER, 
+            s->card->dacs_active ) ;
+}    
+
+static void start_dac(struct m3_state *s)
+{
+    if( (!s->dma_dac.mapped && s->dma_dac.count < 1) ||
+            !s->dma_dac.ready ||
+            (s->enable & DAC_RUNNING)) 
+        return;
+
+    DPRINTK(DPSYS, "start_dac()\n");
+
+    s->enable |= DAC_RUNNING;
+    s->card->dacs_active++;
+    inc_timer_users(s->card);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->dac_inst.data + CDATA_INSTANCE_READY, 1);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            KDATA_MIXER_TASK_NUMBER, 
+            s->card->dacs_active ) ;
+}    
+
+static void start_adc(struct m3_state *s)
+{
+    if ((! s->dma_adc.mapped &&
+                s->dma_adc.count >= (signed)(s->dma_adc.dmasize - 2*s->dma_adc.fragsize)) 
+        || !s->dma_adc.ready 
+        || (s->enable & ADC_RUNNING) ) 
+            return;
+
+    DPRINTK(DPSYS, "start_adc()\n");
+
+    s->enable |= ADC_RUNNING;
+    inc_timer_users(s->card);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            KDATA_ADC1_REQUEST, 1);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->adc_inst.data + CDATA_INSTANCE_READY, 1);
+}    
+
+static struct play_vals {
+    u16 addr, val;
+} pv[] = {
+    {CDATA_LEFT_VOLUME, ARB_VOLUME},
+    {CDATA_RIGHT_VOLUME, ARB_VOLUME},
+    {SRC3_DIRECTION_OFFSET, 0} ,
+    /* +1, +2 are stereo/16 bit */
+    {SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */
+    {SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */
+    {SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */
+    {SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */
+    {SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */
+    {SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */
+    {SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */
+    {SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */
+    {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */
+    {SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */
+    {SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */
+    {SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */
+    {SRC3_DIRECTION_OFFSET + 16, 8}, /* numin */
+    {SRC3_DIRECTION_OFFSET + 17, 50*2}, /* numout */
+    {SRC3_DIRECTION_OFFSET + 18, MINISRC_BIQUAD_STAGE - 1}, /* numstage */
+    {SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */
+    {SRC3_DIRECTION_OFFSET + 21, 0} /* booster */
+};
+
+
+/* the mode passed should be already shifted and masked */
+static void m3_play_setup(struct m3_state *s, int mode, u32 rate, void *buffer, int size)
+{
+    int dsp_in_size = MINISRC_IN_BUFFER_SIZE - (0x20 * 2);
+    int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x20 * 2);
+    int dsp_in_buffer = s->dac_inst.data + (MINISRC_TMP_BUFFER_SIZE / 2);
+    int dsp_out_buffer = dsp_in_buffer + (dsp_in_size / 2) + 1;
+    struct dmabuf *db = &s->dma_dac;
+    int i;
+
+    DPRINTK(DPSTR, "mode=%d rate=%d buf=%p len=%d.\n",
+        mode, rate, buffer, size);
+
+#define LO(x) ((x) & 0xffff)
+#define HI(x) LO((x) >> 16)
+
+    /* host dma buffer pointers */
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_HOST_SRC_ADDRL,
+        LO(virt_to_bus(buffer)));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_HOST_SRC_ADDRH,
+        HI(virt_to_bus(buffer)));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_HOST_SRC_END_PLUS_1L,
+        LO(virt_to_bus(buffer) + size));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_HOST_SRC_END_PLUS_1H,
+        HI(virt_to_bus(buffer) + size));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_HOST_SRC_CURRENTL,
+        LO(virt_to_bus(buffer)));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_HOST_SRC_CURRENTH,
+        HI(virt_to_bus(buffer)));
+#undef LO
+#undef HI
+
+    /* dsp buffers */
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_IN_BUF_BEGIN,
+        dsp_in_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_IN_BUF_END_PLUS_1,
+        dsp_in_buffer + (dsp_in_size / 2));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_IN_BUF_HEAD,
+        dsp_in_buffer);
+    
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_IN_BUF_TAIL,
+        dsp_in_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_OUT_BUF_BEGIN,
+        dsp_out_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_OUT_BUF_END_PLUS_1,
+        dsp_out_buffer + (dsp_out_size / 2));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_OUT_BUF_HEAD,
+        dsp_out_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_OUT_BUF_TAIL,
+        dsp_out_buffer);
+
+    /*
+     * some per client initializers
+     */
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + SRC3_DIRECTION_OFFSET + 12,
+        s->dac_inst.data + 40 + 8);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + SRC3_DIRECTION_OFFSET + 19,
+        s->dac_inst.code + MINISRC_COEF_LOC);
+
+    /* enable or disable low pass filter? */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + SRC3_DIRECTION_OFFSET + 22,
+        s->ratedac > 45000 ? 0xff : 0 );
+    
+    /* tell it which way dma is going? */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->dac_inst.data + CDATA_DMA_CONTROL,
+        DMACONTROL_AUTOREPEAT + DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);
+
+    /*
+     * set an armload of static initializers
+     */
+    for(i = 0 ; i < (sizeof(pv) / sizeof(pv[0])) ; i++) 
+        m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->dac_inst.data + pv[i].addr, pv[i].val);
+
+    /* 
+     * put us in the lists if we're not already there
+     */
+
+    if(db->in_lists == 0) {
+
+        db->msrc_index = m3_add_list(s->card, &s->card->msrc_list, 
+                s->dac_inst.data >> DP_SHIFT_COUNT);
+
+        db->dma_index = m3_add_list(s->card, &s->card->dma_list, 
+                s->dac_inst.data >> DP_SHIFT_COUNT);
+
+        db->mixer_index = m3_add_list(s->card, &s->card->mixer_list, 
+                s->dac_inst.data >> DP_SHIFT_COUNT);
+
+        db->in_lists = 1;
+    }
+
+    set_dac_rate(s,rate);
+    start_dac(s);
+}
+
+/*
+ *    Native record driver 
+ */
+static struct rec_vals {
+    u16 addr, val;
+} rv[] = {
+    {CDATA_LEFT_VOLUME, ARB_VOLUME},
+    {CDATA_RIGHT_VOLUME, ARB_VOLUME},
+    {SRC3_DIRECTION_OFFSET, 1} ,
+    /* +1, +2 are stereo/16 bit */
+    {SRC3_DIRECTION_OFFSET + 3, 0x0000}, /* fraction? */
+    {SRC3_DIRECTION_OFFSET + 4, 0}, /* first l */
+    {SRC3_DIRECTION_OFFSET + 5, 0}, /* first r */
+    {SRC3_DIRECTION_OFFSET + 6, 0}, /* second l */
+    {SRC3_DIRECTION_OFFSET + 7, 0}, /* second r */
+    {SRC3_DIRECTION_OFFSET + 8, 0}, /* delta l */
+    {SRC3_DIRECTION_OFFSET + 9, 0}, /* delta r */
+    {SRC3_DIRECTION_OFFSET + 10, 0x8000}, /* round */
+    {SRC3_DIRECTION_OFFSET + 11, 0xFF00}, /* higher bute mark */
+    {SRC3_DIRECTION_OFFSET + 13, 0}, /* temp0 */
+    {SRC3_DIRECTION_OFFSET + 14, 0}, /* c fraction */
+    {SRC3_DIRECTION_OFFSET + 15, 0}, /* counter */
+    {SRC3_DIRECTION_OFFSET + 16, 50},/* numin */
+    {SRC3_DIRECTION_OFFSET + 17, 8}, /* numout */
+    {SRC3_DIRECTION_OFFSET + 18, 0}, /* numstage */
+    {SRC3_DIRECTION_OFFSET + 19, 0}, /* coef */
+    {SRC3_DIRECTION_OFFSET + 20, 0}, /* filtertap */
+    {SRC3_DIRECTION_OFFSET + 21, 0}, /* booster */
+    {SRC3_DIRECTION_OFFSET + 22, 0xff} /* skip lpf */
+};
+
+/* again, passed mode is alrady shifted/masked */
+static void m3_rec_setup(struct m3_state *s, int mode, u32 rate, void *buffer, int size)
+{
+    int dsp_in_size = MINISRC_IN_BUFFER_SIZE + (0x10 * 2);
+    int dsp_out_size = MINISRC_OUT_BUFFER_SIZE - (0x10 * 2);
+    int dsp_in_buffer = s->adc_inst.data + (MINISRC_TMP_BUFFER_SIZE / 2);
+    int dsp_out_buffer = dsp_in_buffer + (dsp_in_size / 2) + 1;
+    struct dmabuf *db = &s->dma_adc;
+    int i;
+
+    DPRINTK(DPSTR, "rec_setup mode=%d rate=%d buf=%p len=%d.\n",
+        mode, rate, buffer, size);
+
+#define LO(x) ((x) & 0xffff)
+#define HI(x) LO((x) >> 16)
+
+    /* host dma buffer pointers */
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_HOST_SRC_ADDRL,
+        LO(virt_to_bus(buffer)));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_HOST_SRC_ADDRH,
+        HI(virt_to_bus(buffer)));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_HOST_SRC_END_PLUS_1L,
+        LO(virt_to_bus(buffer) + size));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_HOST_SRC_END_PLUS_1H,
+        HI(virt_to_bus(buffer) + size));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_HOST_SRC_CURRENTL,
+        LO(virt_to_bus(buffer)));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_HOST_SRC_CURRENTH,
+        HI(virt_to_bus(buffer)));
+#undef LO
+#undef HI
+
+    /* dsp buffers */
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_IN_BUF_BEGIN,
+        dsp_in_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_IN_BUF_END_PLUS_1,
+        dsp_in_buffer + (dsp_in_size / 2));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_IN_BUF_HEAD,
+        dsp_in_buffer);
+    
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_IN_BUF_TAIL,
+        dsp_in_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_OUT_BUF_BEGIN,
+        dsp_out_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_OUT_BUF_END_PLUS_1,
+        dsp_out_buffer + (dsp_out_size / 2));
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_OUT_BUF_HEAD,
+        dsp_out_buffer);
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_OUT_BUF_TAIL,
+        dsp_out_buffer);
+
+    /*
+     * some per client initializers
+     */
+
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + SRC3_DIRECTION_OFFSET + 12,
+        s->adc_inst.data + 40 + 8);
+
+    /* tell it which way dma is going? */
+    m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+        s->adc_inst.data + CDATA_DMA_CONTROL,
+        DMACONTROL_DIRECTION + DMACONTROL_AUTOREPEAT + 
+        DMAC_PAGE3_SELECTOR + DMAC_BLOCKF_SELECTOR);
+
+    /*
+     * set an armload of static initializers
+     */
+    for(i = 0 ; i < (sizeof(rv) / sizeof(rv[0])) ; i++) 
+        m3_assp_write(s->card, MEMTYPE_INTERNAL_DATA,
+            s->adc_inst.data + rv[i].addr, rv[i].val);
+
+    /* 
+     * put us in the lists if we're not already there
+     */
+
+    if(db->in_lists == 0) {
+
+        db->adc1_index = m3_add_list(s->card, &s->card->adc1_list, 
+                s->adc_inst.data >> DP_SHIFT_COUNT);
+
+        db->dma_index = m3_add_list(s->card, &s->card->dma_list, 
+                s->adc_inst.data >> DP_SHIFT_COUNT);
+
+        db->msrc_index = m3_add_list(s->card, &s->card->msrc_list, 
+                s->adc_inst.data >> DP_SHIFT_COUNT);
+
+        db->in_lists = 1;
+    }
+
+    set_adc_rate(s,rate);
+    start_adc(s);
+}
+/* --------------------------------------------------------------------- */
+
+static void set_dmaa(struct m3_state *s, unsigned int addr, unsigned int count)
+{
+    DPRINTK(DPINT,"set_dmaa??\n");
+}
+
+static void set_dmac(struct m3_state *s, unsigned int addr, unsigned int count)
+{
+    DPRINTK(DPINT,"set_dmac??\n");
+}
+
+u32 get_dma_pos(struct m3_card *card,
+        int instance_addr)
+{
+    u16 hi = 0, lo = 0;
+    int retry = 10;
+
+    /*
+     * try and get a valid answer
+     */
+    while(retry--) {
+        hi =  m3_assp_read(card, MEMTYPE_INTERNAL_DATA,
+                instance_addr + CDATA_HOST_SRC_CURRENTH);
+
+        lo = m3_assp_read(card, MEMTYPE_INTERNAL_DATA,
+                instance_addr + CDATA_HOST_SRC_CURRENTL);
+
+        if(hi == m3_assp_read(card, MEMTYPE_INTERNAL_DATA,
+                instance_addr + CDATA_HOST_SRC_CURRENTH))
+            break;
+    }
+    return lo | (hi<<16);
+}
+
+u32 get_dmaa(struct m3_state *s)
+{
+    u32 offset;
+
+    offset = get_dma_pos(s->card, s->dac_inst.data) - 
+        virt_to_bus(s->dma_dac.rawbuf);
+
+    DPRINTK(DPINT,"get_dmaa: 0x%08x\n",offset);
+
+    return offset;
+}
+
+u32 get_dmac(struct m3_state *s)
+{
+    u32 offset;
+
+    offset = get_dma_pos(s->card, s->adc_inst.data) -
+        virt_to_bus(s->dma_adc.rawbuf);
+
+    DPRINTK(DPINT,"get_dmac: 0x%08x\n",offset);
+
+    return offset;
+
+}
+
+static void m3_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+
+static int 
+prog_dmabuf(struct m3_state *s, unsigned rec)
+{
+    struct dmabuf *db = rec ? &s->dma_adc : &s->dma_dac;
+    unsigned rate = rec ? s->rateadc : s->ratedac;
+    unsigned bytepersec;
+    unsigned bufs;
+    unsigned char fmt;
+    unsigned long flags;
+
+    spin_lock_irqsave(&s->lock, flags);
+
+    fmt = s->fmt;
+    if (rec) {
+        stop_adc(s);
+        fmt >>= ESS_ADC_SHIFT;
+    } else {
+        stop_dac(s);
+        fmt >>= ESS_DAC_SHIFT;
+    }
+    fmt &= ESS_FMT_MASK;
+
+    db->hwptr = db->swptr = db->total_bytes = db->count = db->error = db->endcleared = 0;
+
+    bytepersec = rate << sample_shift[fmt];
+    bufs = PAGE_SIZE << db->buforder;
+    if (db->ossfragshift) {
+        if ((1000 << db->ossfragshift) < bytepersec)
+            db->fragshift = ld2(bytepersec/1000);
+        else
+            db->fragshift = db->ossfragshift;
+    } else {
+        db->fragshift = ld2(bytepersec/100/(db->subdivision ? db->subdivision : 1));
+        if (db->fragshift < 3)
+            db->fragshift = 3; 
+    }
+    db->numfrag = bufs >> db->fragshift;
+    while (db->numfrag < 4 && db->fragshift > 3) {
+        db->fragshift--;
+        db->numfrag = bufs >> db->fragshift;
+    }
+    db->fragsize = 1 << db->fragshift;
+    if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)
+        db->numfrag = db->ossmaxfrags;
+    db->fragsamples = db->fragsize >> sample_shift[fmt];
+    db->dmasize = db->numfrag << db->fragshift;
+
+    DPRINTK(DPSTR,"prog_dmabuf: numfrag: %d fragsize: %d dmasize: %d\n",db->numfrag,db->fragsize,db->dmasize);
+
+    memset(db->rawbuf, (fmt & ESS_FMT_16BIT) ? 0 : 0x80, db->dmasize);
+
+    if (rec) 
+        m3_rec_setup(s, fmt, s->rateadc, db->rawbuf, db->dmasize);
+    else 
+        m3_play_setup(s, fmt, s->ratedac, db->rawbuf, db->dmasize);
+
+    db->ready = 1;
+
+    spin_unlock_irqrestore(&s->lock, flags);
+
+    return 0;
+}
+
+static void clear_advance(struct m3_state *s)
+{
+    unsigned char c = ((s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_16BIT) ? 0 : 0x80;
+    
+    unsigned char *buf = s->dma_dac.rawbuf;
+    unsigned bsize = s->dma_dac.dmasize;
+    unsigned bptr = s->dma_dac.swptr;
+    unsigned len = s->dma_dac.fragsize;
+    
+    if (bptr + len > bsize) {
+        unsigned x = bsize - bptr;
+        memset(buf + bptr, c, x);
+        /* account for wrapping? */
+        bptr = 0;
+        len -= x;
+    }
+    memset(buf + bptr, c, len);
+}
+
+/* call with spinlock held! */
+static void m3_update_ptr(struct m3_state *s)
+{
+    unsigned hwptr;
+    int diff;
+
+    /* update ADC pointer */
+    if (s->dma_adc.ready) {
+        hwptr = get_dmac(s) % 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;
+        if (s->dma_adc.count >= (signed)s->dma_adc.fragsize) 
+            wake_up(&s->dma_adc.wait);
+        if (!s->dma_adc.mapped) {
+            if (s->dma_adc.count > (signed)(s->dma_adc.dmasize - ((3 * s->dma_adc.fragsize) >> 1))) {
+                stop_adc(s); 
+                /* brute force everyone back in sync, sigh */
+                s->dma_adc.count = 0;
+                s->dma_adc.swptr = 0;
+                s->dma_adc.hwptr = 0;
+                s->dma_adc.error++;
+            }
+        }
+    }
+    /* update DAC pointer */
+    if (s->dma_dac.ready) {
+        hwptr = get_dmaa(s) % s->dma_dac.dmasize; 
+        diff = (s->dma_dac.dmasize + hwptr - s->dma_dac.hwptr) % s->dma_dac.dmasize;
+
+        DPRINTK(DPINT,"updating dac: hwptr: %6d diff: %6d count: %6d\n",
+                hwptr,diff,s->dma_dac.count);
+
+        s->dma_dac.hwptr = hwptr;
+        s->dma_dac.total_bytes += diff;
+
+        if (s->dma_dac.mapped) {
+            
+            s->dma_dac.count += diff;
+            if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) {
+                wake_up(&s->dma_dac.wait);
+            }
+        } else {
+
+            s->dma_dac.count -= diff;
+            
+            if (s->dma_dac.count <= 0) {
+                DPRINTK(DPCRAP,"underflow! diff: %d (0x%x) count: %d (0x%x) hw: %d (0x%x) sw: %d (0x%x)\n", 
+                        diff, diff, 
+                        s->dma_dac.count, 
+                        s->dma_dac.count, 
+                    hwptr, hwptr,
+                    s->dma_dac.swptr,
+                    s->dma_dac.swptr);
+                stop_dac(s);
+                /* brute force everyone back in sync, sigh */
+                s->dma_dac.count = 0; 
+                s->dma_dac.swptr = hwptr; 
+                s->dma_dac.error++;
+            } else if (s->dma_dac.count <= (signed)s->dma_dac.fragsize && !s->dma_dac.endcleared) {
+                clear_advance(s);
+                s->dma_dac.endcleared = 1;
+            }
+            if (s->dma_dac.count + (signed)s->dma_dac.fragsize <= (signed)s->dma_dac.dmasize) {
+                wake_up(&s->dma_dac.wait);
+                DPRINTK(DPINT,"waking up DAC count: %d sw: %d hw: %d\n",
+                        s->dma_dac.count, s->dma_dac.swptr, hwptr);
+            }
+        }
+    }
+}
+
+static void m3_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+    struct m3_card *c = (struct m3_card *)dev_id;
+    struct m3_state *s = &c->channels[0];
+    u8 status;
+
+    status = inb(c->iobase+0x1A);
+
+    if(status == 0xff) return;
+   
+    /* presumably acking the ints? */
+    outw(status, c->iobase+0x1A); 
+
+    if(c->in_suspend)
+        return;
+
+    /*
+     * ack an assp int if its running
+     * and has an int pending
+     */
+    if( status & ASSP_INT_PENDING) {
+        u8 ctl = inb(c->iobase + ASSP_CONTROL_B);
+        if( !(ctl & STOP_ASSP_CLOCK)) {
+            ctl = inb(c->iobase + ASSP_HOST_INT_STATUS );
+            if(ctl & DSP2HOST_REQ_TIMER) {
+                outb( DSP2HOST_REQ_TIMER, c->iobase + ASSP_HOST_INT_STATUS);
+                /* update adc/dac info if it was a timer int */
+                spin_lock(&s->lock);
+                m3_update_ptr(s);
+                spin_unlock(&s->lock);
+            }
+        }
+    }
+
+    /* XXX is this needed? */
+    if(status & 0x40) 
+        outb(0x40, c->iobase+0x1A);
+}
+
+
+/* --------------------------------------------------------------------- */
+
+static const char invalid_magic[] = KERN_CRIT PFX "invalid magic value in %s\n";
+
+#define VALIDATE_MAGIC(FOO,MAG)                         \
+({                                                \
+    if (!(FOO) || (FOO)->magic != MAG) { \
+        printk(invalid_magic,__FUNCTION__);            \
+        return -ENXIO;                    \
+    }                                         \
+})
+
+#define VALIDATE_STATE(a) VALIDATE_MAGIC(a,M3_STATE_MAGIC)
+#define VALIDATE_CARD(a) VALIDATE_MAGIC(a,M3_CARD_MAGIC)
+
+/* --------------------------------------------------------------------- */
+
+static loff_t m3_llseek(struct file *file, loff_t offset, int origin)
+{
+    return -ESPIPE;
+}
+
+/* --------------------------------------------------------------------- */
+
+static int drain_dac(struct m3_state *s, int nonblock)
+{
+    DECLARE_WAITQUEUE(wait,current);
+    unsigned long flags;
+    int count;
+    signed long tmo;
+
+    if (s->dma_dac.mapped || !s->dma_dac.ready)
+        return 0;
+    current->state = TASK_INTERRUPTIBLE;
+    add_wait_queue(&s->dma_dac.wait, &wait);
+    for (;;) {
+        spin_lock_irqsave(&s->lock, flags);
+        count = s->dma_dac.count;
+        spin_unlock_irqrestore(&s->lock, flags);
+        if (count <= 0)
+            break;
+        if (signal_pending(current))
+            break;
+        if (nonblock) {
+            remove_wait_queue(&s->dma_dac.wait, &wait);
+            current->state = TASK_RUNNING;
+            return -EBUSY;
+        }
+        tmo = (count * HZ) / s->ratedac;
+        tmo >>= sample_shift[(s->fmt >> ESS_DAC_SHIFT) & ESS_FMT_MASK];
+        /* XXX this is just broken.  someone is waking us up alot, or schedule_timeout is broken.
+            or something.  who cares. - zach */
+        if (!schedule_timeout(tmo ? tmo : 1) && tmo)
+            DPRINTK(DPCRAP,"dma timed out?? %ld\n",jiffies);
+    }
+    remove_wait_queue(&s->dma_dac.wait, &wait);
+    current->state = TASK_RUNNING;
+    if (signal_pending(current))
+            return -ERESTARTSYS;
+    return 0;
+}
+
+static ssize_t m3_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+    struct m3_state *s = (struct m3_state *)file->private_data;
+    ssize_t ret;
+    unsigned long flags;
+    unsigned swptr;
+    int cnt;
+    
+    VALIDATE_STATE(s);
+    if (ppos != &file->f_pos)
+        return -ESPIPE;
+    if (s->dma_adc.mapped)
+        return -ENXIO;
+    if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1)))
+        return ret;
+    if (!access_ok(VERIFY_WRITE, buffer, count))
+        return -EFAULT;
+    ret = 0;
+
+    spin_lock_irqsave(&s->lock, flags);
+
+    while (count > 0) {
+        int timed_out;
+
+        swptr = s->dma_adc.swptr;
+        cnt = s->dma_adc.dmasize-swptr;
+        if (s->dma_adc.count < cnt)
+            cnt = s->dma_adc.count;
+
+        if (cnt > count)
+            cnt = count;
+
+        if (cnt <= 0) {
+            start_adc(s);
+            if (file->f_flags & O_NONBLOCK) 
+            {
+                ret = ret ? ret : -EAGAIN;
+                goto out;
+            }
+
+            spin_unlock_irqrestore(&s->lock, flags);
+            timed_out = interruptible_sleep_on_timeout(&s->dma_adc.wait, HZ) == 0;
+            spin_lock_irqsave(&s->lock, flags);
+
+            if(timed_out) {
+                printk("read: chip lockup? dmasz %u fragsz %u count %u hwptr %u swptr %u\n",
+                       s->dma_adc.dmasize, s->dma_adc.fragsize, s->dma_adc.count, 
+                       s->dma_adc.hwptr, s->dma_adc.swptr);
+                stop_adc(s);
+                set_dmac(s, virt_to_bus(s->dma_adc.rawbuf), s->dma_adc.numfrag << s->dma_adc.fragshift);
+                s->dma_adc.count = s->dma_adc.hwptr = s->dma_adc.swptr = 0;
+            }
+            if (signal_pending(current)) 
+            {
+                ret = ret ? ret : -ERESTARTSYS;
+                goto out;
+            }
+            continue;
+        }
+    
+        spin_unlock_irqrestore(&s->lock, flags);
+        if (copy_to_user(buffer, s->dma_adc.rawbuf + swptr, cnt)) {
+            ret = ret ? ret : -EFAULT;
+            return ret;
+        }
+        spin_lock_irqsave(&s->lock, flags);
+
+        swptr = (swptr + cnt) % s->dma_adc.dmasize;
+        s->dma_adc.swptr = swptr;
+        s->dma_adc.count -= cnt;
+        count -= cnt;
+        buffer += cnt;
+        ret += cnt;
+        start_adc(s);
+    }
+
+out:
+    spin_unlock_irqrestore(&s->lock, flags);
+    return ret;
+}
+
+static ssize_t m3_write(struct file *file, const char *buffer, size_t count, loff_t *ppos)
+{
+    struct m3_state *s = (struct m3_state *)file->private_data;
+    ssize_t ret;
+    unsigned long flags;
+    unsigned swptr;
+    int cnt;
+    
+    VALIDATE_STATE(s);
+    if (ppos != &file->f_pos)
+        return -ESPIPE;
+    if (s->dma_dac.mapped)
+        return -ENXIO;
+    if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+        return ret;
+    if (!access_ok(VERIFY_READ, buffer, count))
+        return -EFAULT;
+    ret = 0;
+
+    spin_lock_irqsave(&s->lock, flags);
+
+    while (count > 0) {
+        int timed_out;
+
+        if (s->dma_dac.count < 0) {
+            s->dma_dac.count = 0;
+            s->dma_dac.swptr = s->dma_dac.hwptr;
+        }
+        swptr = s->dma_dac.swptr;
+
+        cnt = s->dma_dac.dmasize-swptr;
+
+        if (s->dma_dac.count + cnt > s->dma_dac.dmasize)
+            cnt = s->dma_dac.dmasize - s->dma_dac.count;
+
+
+        if (cnt > count)
+            cnt = count;
+
+        if (cnt <= 0) {
+            start_dac(s);
+            if (file->f_flags & O_NONBLOCK) {
+                if(!ret) ret = -EAGAIN;
+                goto out;
+            }
+            spin_unlock_irqrestore(&s->lock, flags);
+            timed_out = interruptible_sleep_on_timeout(&s->dma_dac.wait, HZ) == 0;
+            spin_lock_irqsave(&s->lock, flags);
+            if(timed_out) {
+                DPRINTK(DPCRAP,"write: chip lockup? dmasz %u fragsz %u count %u hwptr %u swptr %u\n",
+                       s->dma_dac.dmasize, s->dma_dac.fragsize, s->dma_dac.count, 
+                       s->dma_dac.hwptr, s->dma_dac.swptr);
+                stop_dac(s);
+                set_dmaa(s, virt_to_bus(s->dma_dac.rawbuf), s->dma_dac.numfrag << s->dma_dac.fragshift);
+                s->dma_dac.count = s->dma_dac.hwptr = s->dma_dac.swptr = 0;
+            }
+            if (signal_pending(current)) {
+                if (!ret) ret = -ERESTARTSYS;
+                goto out;
+            }
+            continue;
+        }
+        spin_unlock_irqrestore(&s->lock, flags);
+        if (copy_from_user(s->dma_dac.rawbuf + swptr, buffer, cnt)) {
+            if (!ret) ret = -EFAULT;
+            return ret;
+        }
+        spin_lock_irqsave(&s->lock, flags);
+
+        DPRINTK(DPSYS,"wrote %6d bytes at sw: %6d cnt: %6d while hw: %6d\n",
+                cnt, swptr, s->dma_dac.count, s->dma_dac.hwptr);
+        
+        swptr = (swptr + cnt) % s->dma_dac.dmasize;
+
+        s->dma_dac.swptr = swptr;
+        s->dma_dac.count += cnt;
+        s->dma_dac.endcleared = 0;
+        count -= cnt;
+        buffer += cnt;
+        ret += cnt;
+        start_dac(s);
+    }
+out:
+    spin_unlock_irqrestore(&s->lock, flags);
+    return ret;
+}
+
+static unsigned int m3_poll(struct file *file, struct poll_table_struct *wait)
+{
+    struct m3_state *s = (struct m3_state *)file->private_data;
+    unsigned long flags;
+    unsigned int mask = 0;
+
+    VALIDATE_STATE(s);
+    if (file->f_mode & FMODE_WRITE)
+        poll_wait(file, &s->dma_dac.wait, wait);
+    if (file->f_mode & FMODE_READ)
+        poll_wait(file, &s->dma_adc.wait, wait);
+
+    spin_lock_irqsave(&s->lock, flags);
+    m3_update_ptr(s);
+
+    if (file->f_mode & FMODE_READ) {
+        if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)
+            mask |= POLLIN | POLLRDNORM;
+    }
+    if (file->f_mode & FMODE_WRITE) {
+        if (s->dma_dac.mapped) {
+            if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 
+                mask |= POLLOUT | POLLWRNORM;
+        } else {
+            if ((signed)s->dma_dac.dmasize >= s->dma_dac.count + (signed)s->dma_dac.fragsize)
+                mask |= POLLOUT | POLLWRNORM;
+        }
+    }
+
+    spin_unlock_irqrestore(&s->lock, flags);
+    return mask;
+}
+
+static int m3_mmap(struct file *file, struct vm_area_struct *vma)
+{
+    struct m3_state *s = (struct m3_state *)file->private_data;
+    unsigned long max_size, size, start, offset;
+    struct dmabuf *db;
+    int ret = -EINVAL;
+
+    VALIDATE_STATE(s);
+    if (vma->vm_flags & VM_WRITE) {
+        if ((ret = prog_dmabuf(s, 0)) != 0)
+            return ret;
+        db = &s->dma_dac;
+    } else 
+    if (vma->vm_flags & VM_READ) {
+        if ((ret = prog_dmabuf(s, 1)) != 0)
+            return ret;
+        db = &s->dma_adc;
+    } else  
+        return -EINVAL;
+
+    max_size = db->dmasize;
+
+    start = vma->vm_start;
+    offset = (vma->vm_pgoff << PAGE_SHIFT);
+    size = vma->vm_end - vma->vm_start;
+
+    if(size > max_size)
+        goto out;
+    if(offset > max_size - size)
+        goto out;
+
+    /*
+     * this will be ->nopage() once I can 
+     * ask Jeff what the hell I'm doing wrong.
+     */
+    ret = -EAGAIN;
+    if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf), size, vma->vm_page_prot))
+        goto out;
+
+    db->mapped = 1;
+    ret = 0;
+
+out:
+    return ret;
+}
+
+/*
+ * this function is a disaster..
+ */
+#define get_user_ret(x, ptr,  ret) ({ if(get_user(x, ptr)) return ret; })
+static int m3_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+    struct m3_state *s = (struct m3_state *)file->private_data;
+    unsigned long flags;
+    audio_buf_info abinfo;
+    count_info cinfo;
+    int val, mapped, ret;
+    unsigned char fmtm, fmtd;
+
+    VALIDATE_STATE(s);
+
+    mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||
+        ((file->f_mode & FMODE_READ) && s->dma_adc.mapped);
+
+    DPRINTK(DPSYS,"m3_ioctl: cmd %d\n", cmd);
+
+    switch (cmd) {
+    case OSS_GETVERSION:
+        return put_user(SOUND_VERSION, (int *)arg);
+
+    case SNDCTL_DSP_SYNC:
+        if (file->f_mode & FMODE_WRITE)
+            return drain_dac(s, file->f_flags & O_NONBLOCK);
+        return 0;
+        
+    case SNDCTL_DSP_SETDUPLEX:
+        /* XXX fix */
+        return 0;
+
+    case SNDCTL_DSP_GETCAPS:
+        return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);
+        
+    case SNDCTL_DSP_RESET:
+        spin_lock_irqsave(&s->lock, flags);
+        if (file->f_mode & FMODE_WRITE) {
+            stop_dac(s);
+            synchronize_irq();
+            s->dma_dac.swptr = s->dma_dac.hwptr = s->dma_dac.count = s->dma_dac.total_bytes = 0;
+        }
+        if (file->f_mode & FMODE_READ) {
+            stop_adc(s);
+            synchronize_irq();
+            s->dma_adc.swptr = s->dma_adc.hwptr = s->dma_adc.count = s->dma_adc.total_bytes = 0;
+        }
+        spin_unlock_irqrestore(&s->lock, flags);
+        return 0;
+
+    case SNDCTL_DSP_SPEED:
+        get_user_ret(val, (int *)arg, -EFAULT);
+        spin_lock_irqsave(&s->lock, flags);
+        if (val >= 0) {
+            if (file->f_mode & FMODE_READ) {
+                stop_adc(s);
+                s->dma_adc.ready = 0;
+                set_adc_rate(s, val);
+            }
+            if (file->f_mode & FMODE_WRITE) {
+                stop_dac(s);
+                s->dma_dac.ready = 0;
+                set_dac_rate(s, val);
+            }
+        }
+        spin_unlock_irqrestore(&s->lock, flags);
+        return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+        
+    case SNDCTL_DSP_STEREO:
+        get_user_ret(val, (int *)arg, -EFAULT);
+        spin_lock_irqsave(&s->lock, flags);
+        fmtd = 0;
+        fmtm = ~0;
+        if (file->f_mode & FMODE_READ) {
+            stop_adc(s);
+            s->dma_adc.ready = 0;
+            if (val)
+                fmtd |= ESS_FMT_STEREO << ESS_ADC_SHIFT;
+            else
+                fmtm &= ~(ESS_FMT_STEREO << ESS_ADC_SHIFT);
+        }
+        if (file->f_mode & FMODE_WRITE) {
+            stop_dac(s);
+            s->dma_dac.ready = 0;
+            if (val)
+                fmtd |= ESS_FMT_STEREO << ESS_DAC_SHIFT;
+            else
+                fmtm &= ~(ESS_FMT_STEREO << ESS_DAC_SHIFT);
+        }
+        set_fmt(s, fmtm, fmtd);
+        spin_unlock_irqrestore(&s->lock, flags);
+        return 0;
+
+    case SNDCTL_DSP_CHANNELS:
+        get_user_ret(val, (int *)arg, -EFAULT);
+        spin_lock_irqsave(&s->lock, flags);
+        if (val != 0) {
+            fmtd = 0;
+            fmtm = ~0;
+            if (file->f_mode & FMODE_READ) {
+                stop_adc(s);
+                s->dma_adc.ready = 0;
+                if (val >= 2)
+                    fmtd |= ESS_FMT_STEREO << ESS_ADC_SHIFT;
+                else
+                    fmtm &= ~(ESS_FMT_STEREO << ESS_ADC_SHIFT);
+            }
+            if (file->f_mode & FMODE_WRITE) {
+                stop_dac(s);
+                s->dma_dac.ready = 0;
+                if (val >= 2)
+                    fmtd |= ESS_FMT_STEREO << ESS_DAC_SHIFT;
+                else
+                    fmtm &= ~(ESS_FMT_STEREO << ESS_DAC_SHIFT);
+            }
+            set_fmt(s, fmtm, fmtd);
+        }
+        spin_unlock_irqrestore(&s->lock, flags);
+        return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_FMT_STEREO << ESS_ADC_SHIFT) 
+                       : (ESS_FMT_STEREO << ESS_DAC_SHIFT))) ? 2 : 1, (int *)arg);
+        
+    case SNDCTL_DSP_GETFMTS: /* Returns a mask */
+        return put_user(AFMT_U8|AFMT_S16_LE, (int *)arg);
+        
+    case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/
+        get_user_ret(val, (int *)arg, -EFAULT);
+        spin_lock_irqsave(&s->lock, flags);
+        if (val != AFMT_QUERY) {
+            fmtd = 0;
+            fmtm = ~0;
+            if (file->f_mode & FMODE_READ) {
+                stop_adc(s);
+                s->dma_adc.ready = 0;
+                if (val == AFMT_S16_LE)
+                    fmtd |= ESS_FMT_16BIT << ESS_ADC_SHIFT;
+                else
+                    fmtm &= ~(ESS_FMT_16BIT << ESS_ADC_SHIFT);
+            }
+            if (file->f_mode & FMODE_WRITE) {
+                stop_dac(s);
+                s->dma_dac.ready = 0;
+                if (val == AFMT_S16_LE)
+                    fmtd |= ESS_FMT_16BIT << ESS_DAC_SHIFT;
+                else
+                    fmtm &= ~(ESS_FMT_16BIT << ESS_DAC_SHIFT);
+            }
+            set_fmt(s, fmtm, fmtd);
+        }
+        spin_unlock_irqrestore(&s->lock, flags);
+        return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? 
+            (ESS_FMT_16BIT << ESS_ADC_SHIFT) 
+            : (ESS_FMT_16BIT << ESS_DAC_SHIFT))) ? 
+                AFMT_S16_LE : 
+                AFMT_U8, 
+            (int *)arg);
+        
+    case SNDCTL_DSP_POST:
+        return 0;
+
+    case SNDCTL_DSP_GETTRIGGER:
+        val = 0;
+        if ((file->f_mode & FMODE_READ) && (s->enable & ADC_RUNNING))
+            val |= PCM_ENABLE_INPUT;
+        if ((file->f_mode & FMODE_WRITE) && (s->enable & DAC_RUNNING)) 
+            val |= PCM_ENABLE_OUTPUT;
+        return put_user(val, (int *)arg);
+        
+    case SNDCTL_DSP_SETTRIGGER:
+        get_user_ret(val, (int *)arg, -EFAULT);
+        if (file->f_mode & FMODE_READ) {
+            if (val & PCM_ENABLE_INPUT) {
+                if (!s->dma_adc.ready && (ret =  prog_dmabuf(s, 1)))
+                    return ret;
+                start_adc(s);
+            } else
+                stop_adc(s);
+        }
+        if (file->f_mode & FMODE_WRITE) {
+            if (val & PCM_ENABLE_OUTPUT) {
+                if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0)))
+                    return ret;
+                start_dac(s);
+            } else
+                stop_dac(s);
+        }
+        return 0;
+
+    case SNDCTL_DSP_GETOSPACE:
+        if (!(file->f_mode & FMODE_WRITE))
+            return -EINVAL;
+        if (!(s->enable & DAC_RUNNING) && (val = prog_dmabuf(s, 0)) != 0)
+            return val;
+        spin_lock_irqsave(&s->lock, flags);
+        m3_update_ptr(s);
+        abinfo.fragsize = s->dma_dac.fragsize;
+        abinfo.bytes = s->dma_dac.dmasize - s->dma_dac.count;
+        abinfo.fragstotal = s->dma_dac.numfrag;
+        abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      
+        spin_unlock_irqrestore(&s->lock, flags);
+        return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+
+    case SNDCTL_DSP_GETISPACE:
+        if (!(file->f_mode & FMODE_READ))
+            return -EINVAL;
+        if (!(s->enable & ADC_RUNNING) && (val = prog_dmabuf(s, 1)) != 0)
+            return val;
+        spin_lock_irqsave(&s->lock, flags);
+        m3_update_ptr(s);
+        abinfo.fragsize = s->dma_adc.fragsize;
+        abinfo.bytes = s->dma_adc.count;
+        abinfo.fragstotal = s->dma_adc.numfrag;
+        abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      
+        spin_unlock_irqrestore(&s->lock, flags);
+        return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;
+        
+    case SNDCTL_DSP_NONBLOCK:
+        file->f_flags |= O_NONBLOCK;
+        return 0;
+
+    case SNDCTL_DSP_GETODELAY:
+        if (!(file->f_mode & FMODE_WRITE))
+            return -EINVAL;
+        spin_lock_irqsave(&s->lock, flags);
+        m3_update_ptr(s);
+        val = s->dma_dac.count;
+        spin_unlock_irqrestore(&s->lock, flags);
+        return put_user(val, (int *)arg);
+
+    case SNDCTL_DSP_GETIPTR:
+        if (!(file->f_mode & FMODE_READ))
+            return -EINVAL;
+        spin_lock_irqsave(&s->lock, flags);
+        m3_update_ptr(s);
+        cinfo.bytes = s->dma_adc.total_bytes;
+        cinfo.blocks = s->dma_adc.count >> s->dma_adc.fragshift;
+        cinfo.ptr = s->dma_adc.hwptr;
+        if (s->dma_adc.mapped)
+            s->dma_adc.count &= s->dma_adc.fragsize-1;
+        spin_unlock_irqrestore(&s->lock, flags);
+        return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+    case SNDCTL_DSP_GETOPTR:
+        if (!(file->f_mode & FMODE_WRITE))
+            return -EINVAL;
+        spin_lock_irqsave(&s->lock, flags);
+        m3_update_ptr(s);
+        cinfo.bytes = s->dma_dac.total_bytes;
+        cinfo.blocks = s->dma_dac.count >> s->dma_dac.fragshift;
+        cinfo.ptr = s->dma_dac.hwptr;
+        if (s->dma_dac.mapped)
+            s->dma_dac.count &= s->dma_dac.fragsize-1;
+        spin_unlock_irqrestore(&s->lock, flags);
+        return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));
+
+    case SNDCTL_DSP_GETBLKSIZE:
+        if (file->f_mode & FMODE_WRITE) {
+            if ((val = prog_dmabuf(s, 0)))
+                return val;
+            return put_user(s->dma_dac.fragsize, (int *)arg);
+        }
+        if ((val = prog_dmabuf(s, 1)))
+            return val;
+        return put_user(s->dma_adc.fragsize, (int *)arg);
+
+    case SNDCTL_DSP_SETFRAGMENT:
+        get_user_ret(val, (int *)arg, -EFAULT);
+        spin_lock_irqsave(&s->lock, flags);
+        if (file->f_mode & FMODE_READ) {
+            s->dma_adc.ossfragshift = val & 0xffff;
+            s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;
+            if (s->dma_adc.ossfragshift < 4)
+                s->dma_adc.ossfragshift = 4;
+            if (s->dma_adc.ossfragshift > 15)
+                s->dma_adc.ossfragshift = 15;
+            if (s->dma_adc.ossmaxfrags < 4)
+                s->dma_adc.ossmaxfrags = 4;
+        }
+        if (file->f_mode & FMODE_WRITE) {
+            s->dma_dac.ossfragshift = val & 0xffff;
+            s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;
+            if (s->dma_dac.ossfragshift < 4)
+                s->dma_dac.ossfragshift = 4;
+            if (s->dma_dac.ossfragshift > 15)
+                s->dma_dac.ossfragshift = 15;
+            if (s->dma_dac.ossmaxfrags < 4)
+                s->dma_dac.ossmaxfrags = 4;
+        }
+        spin_unlock_irqrestore(&s->lock, flags);
+        return 0;
+
+    case SNDCTL_DSP_SUBDIVIDE:
+        if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||
+            (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))
+            return -EINVAL;
+                get_user_ret(val, (int *)arg, -EFAULT);
+        if (val != 1 && val != 2 && val != 4)
+            return -EINVAL;
+        if (file->f_mode & FMODE_READ)
+            s->dma_adc.subdivision = val;
+        if (file->f_mode & FMODE_WRITE)
+            s->dma_dac.subdivision = val;
+        return 0;
+
+    case SOUND_PCM_READ_RATE:
+        return put_user((file->f_mode & FMODE_READ) ? s->rateadc : s->ratedac, (int *)arg);
+
+    case SOUND_PCM_READ_CHANNELS:
+        return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_FMT_STEREO << ESS_ADC_SHIFT) 
+                       : (ESS_FMT_STEREO << ESS_DAC_SHIFT))) ? 2 : 1, (int *)arg);
+
+    case SOUND_PCM_READ_BITS:
+        return put_user((s->fmt & ((file->f_mode & FMODE_READ) ? (ESS_FMT_16BIT << ESS_ADC_SHIFT) 
+                       : (ESS_FMT_16BIT << ESS_DAC_SHIFT))) ? 16 : 8, (int *)arg);
+
+    case SOUND_PCM_WRITE_FILTER:
+    case SNDCTL_DSP_SETSYNCRO:
+    case SOUND_PCM_READ_FILTER:
+        return -EINVAL;
+        
+    }
+    return -EINVAL;
+}
+
+static int
+allocate_dmabuf(struct pci_dev *pci_dev, struct dmabuf *db)
+{
+    int order;
+
+    DPRINTK(DPSTR,"allocating for dmabuf %p\n", db);
+
+    /* 
+     * alloc as big a chunk as we can, start with 
+     * 64k 'cause we're insane.  based on order cause
+     * the amazingly complicated prog_dmabuf wants it.
+     *
+     * pci_alloc_sonsistent guarantees that it won't cross a natural
+     * boundry; the m3 hardware can't have dma cross a 64k bus
+     * address boundry.
+     */
+    for (order = 16-PAGE_SHIFT; order >= 1; order--) {
+        db->rawbuf = pci_alloc_consistent(pci_dev, PAGE_SIZE << order,
+                        &(db->handle));
+        if(db->rawbuf)
+            break;
+    }
+
+    if (!db->rawbuf)
+        return 1;
+
+    DPRINTK(DPSTR,"allocated %ld (%d) bytes at %p\n",
+            PAGE_SIZE<<order, order, db->rawbuf);
+
+    {
+        struct page *page, *pend;
+
+        pend = virt_to_page(db->rawbuf + (PAGE_SIZE << order) - 1);
+        for (page = virt_to_page(db->rawbuf); page <= pend; page++)
+            mem_map_reserve(page);
+    }
+
+
+    db->buforder = order;
+    db->ready = 0;
+    db->mapped = 0;
+
+    return 0;
+}
+
+static void
+nuke_lists(struct m3_card *card, struct dmabuf *db)
+{
+    m3_remove_list(card, &(card->dma_list), db->dma_index);
+    m3_remove_list(card, &(card->msrc_list), db->msrc_index);
+    db->in_lists = 0;
+}
+
+static void
+free_dmabuf(struct pci_dev *pci_dev, struct dmabuf *db)
+{
+    DPRINTK(DPSTR,"freeing %p from dmabuf %p\n",db->rawbuf, db);
+
+    {
+        struct page *page, *pend;
+        pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);
+        for (page = virt_to_page(db->rawbuf); page <= pend; page++)
+            mem_map_unreserve(page);
+    }
+
+
+    pci_free_consistent(pci_dev, PAGE_SIZE << db->buforder,
+            db->rawbuf, db->handle);
+
+    db->rawbuf = NULL;
+    db->buforder = 0;
+    db->mapped = 0;
+    db->ready = 0;
+}
+
+static int m3_open(struct inode *inode, struct file *file)
+{
+    int minor = MINOR(inode->i_rdev);
+    struct m3_card *c;
+    struct m3_state *s = NULL;
+    int i, ret = 0;
+    unsigned char fmtm = ~0, fmts = 0;
+    unsigned long flags;
+
+    /*
+     *    Scan the cards and find the channel. We only
+     *    do this at open time so it is ok
+     */
+    for(c = devs ; c != NULL ; c = c->next) {
+
+        for(i=0;i<NR_DSPS;i++) {
+
+            if(c->channels[i].dev_audio < 0)
+                continue;
+            if((c->channels[i].dev_audio ^ minor) & ~0xf)
+                continue;
+
+            s = &c->channels[i];
+            break;
+        }
+    }
+        
+    if (!s)
+        return -ENODEV;
+        
+    VALIDATE_STATE(s);
+
+    file->private_data = s;
+
+    /* wait for device to become free */
+    down(&s->open_sem);
+    while (s->open_mode & file->f_mode) {
+        if (file->f_flags & O_NONBLOCK) {
+            up(&s->open_sem);
+            return -EWOULDBLOCK;
+        }
+        up(&s->open_sem);
+        interruptible_sleep_on(&s->open_wait);
+        if (signal_pending(current))
+            return -ERESTARTSYS;
+        down(&s->open_sem);
+    }
+    
+    spin_lock_irqsave(&s->lock, flags);
+
+    if (file->f_mode & FMODE_READ) {
+        if(allocate_dmabuf(s->card->pcidev, &(s->dma_adc)))  {
+            ret = -ENOMEM;
+            goto out;
+        }
+        fmtm &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_ADC_SHIFT);
+        if ((minor & 0xf) == SND_DEV_DSP16)
+            fmts |= ESS_FMT_16BIT << ESS_ADC_SHIFT; 
+
+        s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags = s->dma_adc.subdivision = 0;
+        set_adc_rate(s, 8000);
+    }
+    if (file->f_mode & FMODE_WRITE) {
+        if(allocate_dmabuf(s->card->pcidev, &(s->dma_dac)))  {
+            ret = -ENOMEM;
+            goto out;
+        }
+        fmtm &= ~((ESS_FMT_STEREO | ESS_FMT_16BIT) << ESS_DAC_SHIFT);
+        if ((minor & 0xf) == SND_DEV_DSP16)
+            fmts |= ESS_FMT_16BIT << ESS_DAC_SHIFT;
+
+        s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags = s->dma_dac.subdivision = 0;
+        set_dac_rate(s, 8000);
+    }
+    set_fmt(s, fmtm, fmts);
+    s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);
+
+    MOD_INC_USE_COUNT;
+out:
+    up(&s->open_sem);
+    spin_unlock_irqrestore(&s->lock, flags);
+    return 0;
+}
+
+static int m3_release(struct inode *inode, struct file *file)
+{
+    struct m3_state *s = (struct m3_state *)file->private_data;
+    unsigned long flags;
+
+    VALIDATE_STATE(s);
+    if (file->f_mode & FMODE_WRITE)
+        drain_dac(s, file->f_flags & O_NONBLOCK);
+
+    down(&s->open_sem);
+    spin_lock_irqsave(&s->lock, flags);
+
+    if (file->f_mode & FMODE_WRITE) {
+        stop_dac(s);
+        if(s->dma_dac.in_lists) {
+            m3_remove_list(s->card, &(s->card->mixer_list), s->dma_dac.mixer_index);
+            nuke_lists(s->card, &(s->dma_dac));
+        }
+        free_dmabuf(s->card->pcidev, &(s->dma_dac));
+    }
+    if (file->f_mode & FMODE_READ) {
+        stop_adc(s);
+        if(s->dma_adc.in_lists) {
+            m3_remove_list(s->card, &(s->card->adc1_list), s->dma_adc.adc1_index);
+            nuke_lists(s->card, &(s->dma_adc));
+        }
+        free_dmabuf(s->card->pcidev, &(s->dma_adc));
+    }
+        
+    s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);
+
+    spin_unlock_irqrestore(&s->lock, flags);
+    up(&s->open_sem);
+    wake_up(&s->open_wait);
+
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+/*
+ * Wait for the ac97 serial bus to be free.
+ * return nonzero if the bus is still busy.
+ */
+static int m3_ac97_wait(struct m3_card *card)
+{
+    int i = 10000;
+
+    while( (m3_inb(card, 0x30) & 1) && i--) ;
+
+    return i == 0;
+}
+
+u16 m3_ac97_read(struct ac97_codec *codec, u8 reg)
+{
+    u16 ret = 0;
+    struct m3_card *card = codec->private_data;
+
+    spin_lock(&card->ac97_lock);
+
+    if(m3_ac97_wait(card)) {
+        printk(KERN_ERR PFX "serial bus busy reading reg 0x%x\n",reg);
+        goto out;
+    }
+
+    m3_outb(card, 0x80 | (reg & 0x7f), 0x30);
+
+    if(m3_ac97_wait(card)) {
+        printk(KERN_ERR PFX "serial bus busy finishing read reg 0x%x\n",reg);
+        goto out;
+    }
+
+    ret =  m3_inw(card, 0x32);
+    DPRINTK(DPCRAP,"reading 0x%04x from 0x%02x\n",ret, reg);
+
+out:
+    spin_unlock(&card->ac97_lock);
+    return ret;
+}
+
+void m3_ac97_write(struct ac97_codec *codec, u8 reg, u16 val)
+{
+    struct m3_card *card = codec->private_data;
+
+    spin_lock(&card->ac97_lock);
+
+    if(m3_ac97_wait(card)) {
+        printk(KERN_ERR PFX "serial bus busy writing 0x%x to 0x%x\n",val, reg);
+        goto out;
+    }
+    DPRINTK(DPCRAP,"writing 0x%04x  to  0x%02x\n", val, reg);
+
+    m3_outw(card, val, 0x32);
+    m3_outb(card, reg & 0x7f, 0x30);
+out:
+    spin_unlock(&card->ac97_lock);
+}
+/* OSS /dev/mixer file operation methods */
+static int m3_open_mixdev(struct inode *inode, struct file *file)
+{
+    int minor = MINOR(inode->i_rdev);
+    struct m3_card *card = devs;
+
+    MOD_INC_USE_COUNT;
+    for (card = devs; card != NULL; card = card->next) {
+        if((card->ac97 != NULL) && (card->ac97->dev_mixer == minor))
+                break;
+    }
+
+    if (!card) {
+        MOD_DEC_USE_COUNT;
+        return -ENODEV;
+    }
+
+    file->private_data = card->ac97;
+
+    return 0;
+}
+
+static int m3_release_mixdev(struct inode *inode, struct file *file)
+{
+    MOD_DEC_USE_COUNT;
+    return 0;
+}
+
+static int m3_ioctl_mixdev(struct inode *inode, struct file *file, unsigned int cmd,
+                                    unsigned long arg)
+{
+    struct ac97_codec *codec = (struct ac97_codec *)file->private_data;
+
+    return codec->mixer_ioctl(codec, cmd, arg);
+}
+
+static struct file_operations m3_mixer_fops = {
+    llseek:         m3_llseek,
+    ioctl:          m3_ioctl_mixdev,
+    open:           m3_open_mixdev,
+    release:        m3_release_mixdev,
+};
+
+void remote_codec_config(int io, int isremote)
+{
+    isremote = isremote ? 1 : 0;
+
+    outw(  (inw(io + RING_BUS_CTRL_B) & ~SECOND_CODEC_ID_MASK) | isremote,
+            io + RING_BUS_CTRL_B);
+    outw(  (inw(io + SDO_OUT_DEST_CTRL) & ~COMMAND_ADDR_OUT) | isremote,
+            io + SDO_OUT_DEST_CTRL);
+    outw(  (inw(io + SDO_IN_DEST_CTRL) & ~STATUS_ADDR_IN) | isremote,
+            io + SDO_IN_DEST_CTRL);
+}
+
+/* 
+ * hack, returns non zero on err 
+ */
+static int try_read_vendor(struct m3_card *card)
+{
+    u16 ret;
+
+    if(m3_ac97_wait(card)) 
+        return 1;
+
+    m3_outb(card, 0x80 | (AC97_VENDOR_ID1 & 0x7f), 0x30);
+
+    if(m3_ac97_wait(card)) 
+        return 1;
+
+    ret =  m3_inw(card, 0x32);
+
+    return (ret == 0) || (ret == 0xffff);
+}
+
+static void m3_codec_reset(struct m3_card *card, int busywait)
+{
+    u16 dir;
+    int delay1 = 0, delay2 = 0, i;
+    int io = card->iobase;
+
+    switch (card->card_type) {
+        /*
+         * the onboard codec on the allegro seems 
+         * to want to wait a very long time before
+         * coming back to life 
+         */
+        case ESS_ALLEGRO:
+            delay1 = 50;
+            delay2 = 800;
+        break;
+        case ESS_MAESTRO3:
+        case ESS_MAESTRO3HW:
+            delay1 = 20;
+            delay2 = 500;
+        break;
+    }
+
+    for(i = 0; i < 5; i ++) {
+        dir = inw(io + GPIO_DIRECTION);
+        dir |= 0x10; /* assuming pci bus master? */
+
+        remote_codec_config(io, 0);
+
+        outw(IO_SRAM_ENABLE, io + RING_BUS_CTRL_A);
+        udelay(20);
+
+        outw(dir & ~GPO_PRIMARY_AC97 , io + GPIO_DIRECTION);
+        outw(~GPO_PRIMARY_AC97 , io + GPIO_MASK);
+        outw(0, io + GPIO_DATA);
+        outw(dir | GPO_PRIMARY_AC97, io + GPIO_DIRECTION);
+
+        if(busywait)  {
+            mdelay(delay1);
+        } else {
+            current->state = TASK_UNINTERRUPTIBLE;
+            schedule_timeout((delay1 * HZ) / 1000);
+        }
+
+        outw(GPO_PRIMARY_AC97, io + GPIO_DATA);
+        udelay(5);
+        /* ok, bring back the ac-link */
+        outw(IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE, io + RING_BUS_CTRL_A);
+        outw(~0, io + GPIO_MASK);
+
+        if(busywait) {
+            mdelay(delay2);
+        } else {
+            current->state = TASK_UNINTERRUPTIBLE;
+            schedule_timeout((delay2 * HZ) / 1000);
+        }
+        if(! try_read_vendor(card))
+            break;
+
+        delay1 += 10;
+        delay2 += 100;
+
+        DPRINTK(DPMOD, "retrying codec reset with delays of %d and %d ms\n",
+                delay1, delay2);
+    }
+
+#if 0
+    /* more gung-ho reset that doesn't
+     * seem to work anywhere :)
+     */
+    tmp = inw(io + RING_BUS_CTRL_A);
+    outw(RAC_SDFS_ENABLE|LAC_SDFS_ENABLE, io + RING_BUS_CTRL_A);
+    mdelay(20);
+    outw(tmp, io + RING_BUS_CTRL_A);
+    mdelay(50);
+#endif
+}
+
+static int __init m3_codec_install(struct m3_card *card)
+{
+    struct ac97_codec *codec;
+
+    if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
+        return -ENOMEM;
+    memset(codec, 0, sizeof(struct ac97_codec));
+
+    codec->private_data = card;
+    codec->codec_read = m3_ac97_read;
+    codec->codec_write = m3_ac97_write;
+
+    if (ac97_probe_codec(codec) == 0) {
+        printk(KERN_ERR PFX "codec probe failed\n");
+        kfree(codec);
+        return -1;
+    }
+
+    if ((codec->dev_mixer = register_sound_mixer(&m3_mixer_fops, -1)) < 0) {
+        printk(KERN_ERR PFX "couldn't register mixer!\n");
+        kfree(codec);
+        return -1;
+    }
+
+    card->ac97 = codec;
+
+    return 0;
+}
+
+
+#define MINISRC_LPF_LEN 10
+static u16 minisrc_lpf[MINISRC_LPF_LEN] = {
+    0X0743, 0X1104, 0X0A4C, 0XF88D, 0X242C,
+    0X1023, 0X1AA9, 0X0B60, 0XEFDD, 0X186F
+};
+static void m3_assp_init(struct m3_card *card)
+{
+    int i;
+
+    /* zero kernel data */
+    for(i = 0 ; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++)
+        m3_assp_write(card, MEMTYPE_INTERNAL_DATA, 
+                KDATA_BASE_ADDR + i, 0);
+
+    /* zero mixer data? */
+    for(i = 0 ; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++)
+        m3_assp_write(card, MEMTYPE_INTERNAL_DATA, 
+                KDATA_BASE_ADDR2 + i, 0);
+
+    /* init dma pointer */
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA, 
+            KDATA_CURRENT_DMA, 
+            KDATA_DMA_XFER0);
+
+    /* write kernel into code memory.. */
+    for(i = 0 ; i < sizeof(assp_kernel_image) / 2; i++) {
+        m3_assp_write(card, MEMTYPE_INTERNAL_CODE, 
+                REV_B_CODE_MEMORY_BEGIN + i, 
+                assp_kernel_image[i]);
+    }
+
+    /*
+     * We only have this one client and we know that 0x400
+     * is free in our kernel's mem map, so lets just
+     * drop it there.  It seems that the minisrc doesn't
+     * need vectors, so we won't bother with them..
+     */
+    for(i = 0 ; i < sizeof(assp_minisrc_image) / 2; i++) {
+        m3_assp_write(card, MEMTYPE_INTERNAL_CODE, 
+                0x400 + i, 
+                assp_minisrc_image[i]);
+    }
+
+    /*
+     * write the coefficients for the low pass filter?
+     */
+    for(i = 0; i < MINISRC_LPF_LEN ; i++) {
+        m3_assp_write(card, MEMTYPE_INTERNAL_CODE,
+            0x400 + MINISRC_COEF_LOC + i,
+            minisrc_lpf[i]);
+    }
+
+    m3_assp_write(card, MEMTYPE_INTERNAL_CODE,
+        0x400 + MINISRC_COEF_LOC + MINISRC_LPF_LEN,
+        0x8000);
+
+    /*
+     * the minisrc is the only thing on
+     * our task list..
+     */
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA, 
+            KDATA_TASK0, 
+            0x400);
+
+    /*
+     * init the mixer number..
+     */
+
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+            KDATA_MIXER_TASK_NUMBER,0);
+
+    /*
+     * EXTREME KERNEL MASTER VOLUME
+     */
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+        KDATA_DAC_LEFT_VOLUME, ARB_VOLUME);
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+        KDATA_DAC_RIGHT_VOLUME, ARB_VOLUME);
+
+    card->mixer_list.mem_addr = KDATA_MIXER_XFER0;
+    card->mixer_list.max = MAX_VIRTUAL_MIXER_CHANNELS;
+    card->adc1_list.mem_addr = KDATA_ADC1_XFER0;
+    card->adc1_list.max = MAX_VIRTUAL_ADC1_CHANNELS;
+    card->dma_list.mem_addr = KDATA_DMA_XFER0;
+    card->dma_list.max = MAX_VIRTUAL_DMA_CHANNELS;
+    card->msrc_list.mem_addr = KDATA_INSTANCE0_MINISRC;
+    card->msrc_list.max = MAX_INSTANCE_MINISRC;
+}
+
+static int setup_msrc(struct m3_card *card,
+        struct assp_instance *inst, int index)
+{
+    int data_bytes = 2 * ( MINISRC_TMP_BUFFER_SIZE / 2 + 
+            MINISRC_IN_BUFFER_SIZE / 2 +
+            1 + MINISRC_OUT_BUFFER_SIZE / 2 + 1 );
+    int address, i;
+
+    /*
+     * the revb memory map has 0x1100 through 0x1c00
+     * free.  
+     */
+
+    /*
+     * align instance address to 256 bytes so that it's
+     * shifted list address is aligned.  
+     * list address = (mem address >> 1) >> 7;
+     */
+    data_bytes = (data_bytes + 255) & ~255;
+    address = 0x1100 + ((data_bytes/2) * index);
+
+    if((address + (data_bytes/2)) >= 0x1c00) {
+        printk(KERN_ERR PFX "no memory for %d bytes at ind %d (addr 0x%x)\n",
+                data_bytes, index, address);
+        return -1;
+    }
+
+    for(i = 0; i < data_bytes/2 ; i++) 
+        m3_assp_write(card, MEMTYPE_INTERNAL_DATA,
+                address + i, 0);
+
+    inst->code = 0x400;
+    inst->data = address;
+
+    return 0;
+}
+
+static int m3_assp_client_init(struct m3_state *s)
+{
+    setup_msrc(s->card, &(s->dac_inst), s->index * 2);
+    setup_msrc(s->card, &(s->adc_inst), (s->index * 2) + 1);
+
+    return 0;
+}
+
+static void m3_amp_enable(struct m3_card *card, int enable)
+{
+    /* 
+     * this works for the reference board, have to find
+     * out about others
+     *
+     * this needs more magic for 4 speaker, but..
+     */
+    int io = card->iobase;
+    u16 gpo, polarity_port, polarity;
+
+    if(!external_amp)
+        return;
+
+    switch (card->card_type) {
+        case ESS_ALLEGRO:
+            polarity_port = 0x1800;
+            break;
+        default:
+            /* presumably this is for all 'maestro3's.. */
+            polarity_port = 0x1100;
+            break;
+    }
+
+    gpo = (polarity_port >> 8) & 0x0F;
+    polarity = polarity_port >> 12;
+    if ( enable )
+        polarity = !polarity;
+    polarity = polarity << gpo;
+    gpo = 1 << gpo;
+
+    outw(~gpo , io + GPIO_MASK);
+
+    outw( inw(io + GPIO_DIRECTION) | gpo ,
+            io + GPIO_DIRECTION);
+
+    outw( (GPO_SECONDARY_AC97 | GPO_PRIMARY_AC97 | polarity) ,
+            io + GPIO_DATA);
+
+    outw(0xffff , io + GPIO_MASK);
+}
+
+static int
+maestro_config(struct m3_card *card) 
+{
+    struct pci_dev *pcidev = card->pcidev;
+    u32 n;
+    u8  t; /* makes as much sense as 'n', no? */
+
+    pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
+    n &= REDUCED_DEBOUNCE;
+    n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
+    pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
+
+    outb(RESET_ASSP, card->iobase + ASSP_CONTROL_B);
+    pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
+    n &= ~INT_CLK_SELECT;
+    if(card->card_type >= ESS_MAESTRO3)  {
+        n &= ~INT_CLK_MULT_ENABLE; 
+        n |= INT_CLK_SRC_NOT_PCI;
+    }
+    n &=  ~( CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2 );
+    pci_write_config_dword(pcidev, PCI_ALLEGRO_CONFIG, n);
+
+    if(card->card_type <= ESS_ALLEGRO) {
+        pci_read_config_dword(pcidev, PCI_USER_CONFIG, &n);
+        n |= IN_CLK_12MHZ_SELECT;
+        pci_write_config_dword(pcidev, PCI_USER_CONFIG, n);
+    }
+
+    t = inb(card->iobase + ASSP_CONTROL_A);
+    t &= ~( DSP_CLK_36MHZ_SELECT  | ASSP_CLK_49MHZ_SELECT);
+    t |= ASSP_CLK_49MHZ_SELECT;
+    t |= ASSP_0_WS_ENABLE; 
+    outb(t, card->iobase + ASSP_CONTROL_A);
+
+    outb(RUN_ASSP, card->iobase + ASSP_CONTROL_B); 
+
+    return 0;
+} 
+
+static void m3_enable_ints(struct m3_card *card)
+{
+    unsigned long io = card->iobase;
+
+    outw(ASSP_INT_ENABLE, io + HOST_INT_CTRL);
+    outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
+            io + ASSP_CONTROL_C);
+}
+
+static struct file_operations m3_audio_fops = {
+    llseek:     &m3_llseek,
+    read:       &m3_read,
+    write:      &m3_write,
+    poll:       &m3_poll,
+    ioctl:      &m3_ioctl,
+    mmap:       &m3_mmap,
+    open:       &m3_open,
+    release:    &m3_release,
+};
+
+#ifdef CONFIG_PM
+int alloc_dsp_suspendmem(struct m3_card *card)
+{
+    int len = sizeof(u16) * (REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH);
+
+    if( (card->suspend_mem = vmalloc(len)) == NULL)
+        return 1;
+
+    return 0;
+}
+void free_dsp_suspendmem(struct m3_card *card)
+{
+   if(card->suspend_mem)
+       vfree(card->suspend_mem);
+}
+
+#else
+#define alloc_dsp_suspendmem(args...) 0
+#define free_dsp_suspendmem(args...) 
+#endif
+
+/*
+ * great day!  this function is ugly as hell.
+ */
+static int __init m3_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id)
+{
+    u32 n;
+    int i;
+    struct m3_card *card = NULL;
+    int ret = 0;
+    int card_type = pci_id->driver_data;
+
+    DPRINTK(DPMOD, "in maestro_install\n");
+
+    if (!pci_dma_supported(pci_dev, 0xffffffff)) {
+        printk(KERN_ERR PFX "architecture does not support 32bit PCI busmaster DMA\n");
+        return -ENODEV;
+    }
+        
+    if (pci_enable_device(pci_dev))
+        return -EIO;
+
+    pci_set_master(pci_dev);
+
+    if( (card = kmalloc(sizeof(struct m3_card), GFP_KERNEL)) == NULL) {
+        printk(KERN_WARNING PFX "out of memory\n");
+        return -ENOMEM;
+    }
+    memset(card, 0, sizeof(struct m3_card));
+    card->pcidev = pci_dev;
+    init_waitqueue_head(&card->suspend_queue);
+
+    if ( ! request_region(pci_resource_start(pci_dev, 0),
+                pci_resource_len (pci_dev, 0), M3_MODULE_NAME)) {
+
+        printk(KERN_WARNING PFX "unable to reserve I/O space.\n");
+        ret = -EBUSY;
+        goto out;
+    }
+
+    card->iobase = pci_resource_start(pci_dev, 0);
+
+    if(alloc_dsp_suspendmem(card)) {
+        printk(KERN_WARNING PFX "couldn't alloc %d bytes for saving dsp state on suspend\n",
+                REV_B_CODE_MEMORY_LENGTH + REV_B_DATA_MEMORY_LENGTH);
+        ret = -ENOMEM;
+        goto out;
+    }
+
+    card->card_type = card_type;
+    card->irq = pci_dev->irq;
+    card->next = devs;
+    card->magic = M3_CARD_MAGIC;
+    spin_lock_init(&card->lock);
+    spin_lock_init(&card->ac97_lock);
+    devs = card;
+    for(i = 0; i<NR_DSPS; i++) {
+        struct m3_state *s = &(card->channels[i]);
+        s->dev_audio = -1;
+    }
+
+    printk(KERN_INFO PFX "Configuring ESS %s found at IO 0x%04X IRQ %d\n", 
+        card_names[card->card_type], card->iobase, card->irq);
+
+    pci_read_config_dword(pci_dev, PCI_SUBSYSTEM_VENDOR_ID, &n);
+    printk(KERN_INFO PFX " subvendor id: 0x%08x\n",n); 
+
+    maestro_config(card);
+    m3_assp_halt(card);
+
+    m3_codec_reset(card, 0);
+
+    if(m3_codec_install(card))  {
+        ret = -EIO; 
+        goto out;
+    }
+
+    m3_assp_init(card);
+    m3_amp_enable(card, 1);
+    
+    for(i=0;i<NR_DSPS;i++) {
+        struct m3_state *s=&card->channels[i];
+
+        s->index = i;
+
+        s->card = card;
+        init_waitqueue_head(&s->dma_adc.wait);
+        init_waitqueue_head(&s->dma_dac.wait);
+        init_waitqueue_head(&s->open_wait);
+        spin_lock_init(&s->lock);
+        init_MUTEX(&(s->open_sem));
+        s->magic = M3_STATE_MAGIC;
+
+        m3_assp_client_init(s);
+        
+        if(s->dma_adc.ready || s->dma_dac.ready || s->dma_adc.rawbuf)
+            printk(KERN_WARNING PFX "initing a dsp device that is already in use?\n");
+        /* register devices */
+        if ((s->dev_audio = register_sound_dsp(&m3_audio_fops, -1)) < 0) {
+            break;
+        }
+    }
+    
+    if(request_irq(card->irq, m3_interrupt, SA_SHIRQ, card_names[card->card_type], card)) {
+
+        printk(KERN_ERR PFX "unable to allocate irq %d,\n", card->irq);
+
+        ret = -EIO;
+        goto out;
+    }
+
+    pci_dev->driver_data = card;
+    
+    m3_enable_ints(card);
+    m3_assp_continue(card);
+
+out:
+    if(ret) {
+        if(card->iobase)
+            release_region(pci_resource_start(pci_dev, 0), pci_resource_len(pci_dev, 0));
+        free_dsp_suspendmem(card);
+        if(card->ac97) {
+            unregister_sound_mixer(card->ac97->dev_mixer);
+            kfree(card->ac97);
+        }
+        for(i=0;i<NR_DSPS;i++)
+        {
+            struct m3_state *s = &card->channels[i];
+            if(s->dev_audio != -1)
+                unregister_sound_dsp(s->dev_audio);
+        }
+        kfree(card);
+    }
+
+    return ret; 
+}
+
+static void m3_remove(struct pci_dev *pci_dev)
+{
+    struct m3_card *card;
+
+    unregister_reboot_notifier(&m3_reboot_nb);
+
+    while ((card = devs)) {
+        int i;
+        devs = devs->next;
+    
+        free_irq(card->irq, card);
+        unregister_sound_mixer(card->ac97->dev_mixer);
+        kfree(card->ac97);
+
+        for(i=0;i<NR_DSPS;i++)
+        {
+            struct m3_state *s = &card->channels[i];
+            if(s->dev_audio != -1)
+                unregister_sound_dsp(s->dev_audio);
+        }
+
+        release_region(card->iobase, 256);
+        free_dsp_suspendmem(card);
+        kfree(card);
+    }
+    devs = NULL;
+}
+
+/*
+ * some bioses like the sound chip to be powered down
+ * at shutdown.  We're just calling _suspend to
+ * achieve that..
+ */
+static int m3_notifier(struct notifier_block *nb, unsigned long event, void *buf)
+{
+    struct m3_card *card;
+
+    DPRINTK(DPMOD, "notifier suspending all cards\n");
+
+    for(card = devs; card != NULL; card = card->next) {
+        if(!card->in_suspend)
+            m3_suspend(card->pcidev); /* XXX legal? */
+    }
+    return 0;
+}
+
+static void m3_suspend(struct pci_dev *pci_dev)
+{
+    unsigned long flags;
+    int i;
+    struct m3_card *card = pci_dev->driver_data;
+
+    /* must be a better way.. */
+    save_flags(flags);
+    cli();
+
+    DPRINTK(DPMOD, "pm in dev %p\n",card);
+
+    for(i=0;i<NR_DSPS;i++) {
+        struct m3_state *s = &card->channels[i];
+
+        if(s->dev_audio == -1)
+            continue;
+
+        DPRINTK(DPMOD, "stop_adc/dac() device %d\n",i);
+        stop_dac(s);
+        stop_adc(s);
+    }
+
+    mdelay(10); /* give the assp a chance to idle.. */
+
+    m3_assp_halt(card);
+
+    if(card->suspend_mem) {
+        int index = 0;
+
+        DPRINTK(DPMOD, "saving code\n");
+        for(i = REV_B_CODE_MEMORY_BEGIN ; i <= REV_B_CODE_MEMORY_END; i++)
+            card->suspend_mem[index++] = 
+                m3_assp_read(card, MEMTYPE_INTERNAL_CODE, i);
+        DPRINTK(DPMOD, "saving data\n");
+        for(i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
+            card->suspend_mem[index++] = 
+                m3_assp_read(card, MEMTYPE_INTERNAL_DATA, i);
+    }
+
+    DPRINTK(DPMOD, "powering down apci regs\n");
+    m3_outw(card, 0xffff, 0x54);
+    m3_outw(card, 0xffff, 0x56);
+
+    card->in_suspend = 1;
+
+    restore_flags(flags);
+}
+
+static void m3_resume(struct pci_dev *pci_dev)
+{
+    unsigned long flags;
+    int index;
+    int i;
+    struct m3_card *card = pci_dev->driver_data;
+
+    save_flags(flags); /* paranoia */
+    cli();
+    card->in_suspend = 0;
+
+    DPRINTK(DPMOD, "resuming\n");
+
+    /* first lets just bring everything back. .*/
+
+    DPRINTK(DPMOD, "bringing power back on card 0x%p\n",card);
+    m3_outw(card, 0, 0x54);
+    m3_outw(card, 0, 0x56);
+
+    DPRINTK(DPMOD, "restoring pci configs and reseting codec\n");
+    maestro_config(card);
+    m3_assp_halt(card);
+    m3_codec_reset(card, 1);
+
+    DPRINTK(DPMOD, "restoring dsp code card\n");
+    index = 0;
+    for(i = REV_B_CODE_MEMORY_BEGIN ; i <= REV_B_CODE_MEMORY_END; i++)
+        m3_assp_write(card, MEMTYPE_INTERNAL_CODE, i, 
+            card->suspend_mem[index++]);
+    for(i = REV_B_DATA_MEMORY_BEGIN ; i <= REV_B_DATA_MEMORY_END; i++)
+        m3_assp_write(card, MEMTYPE_INTERNAL_DATA, i, 
+            card->suspend_mem[index++]);
+
+     /* tell the dma engine to restart itself */
+    m3_assp_write(card, MEMTYPE_INTERNAL_DATA, 
+        KDATA_DMA_ACTIVE, 0);
+
+    DPRINTK(DPMOD, "resuming dsp\n");
+    m3_assp_continue(card);
+
+    DPRINTK(DPMOD, "enabling ints\n");
+    m3_enable_ints(card);
+
+    /* bring back the old school flavor */
+    for(i = 0; i < SOUND_MIXER_NRDEVICES ; i++) {
+        int state = card->ac97->mixer_state[i];
+        if (!supported_mixer(card->ac97, i)) 
+                continue;
+
+        card->ac97->write_mixer(card->ac97, i, 
+                state & 0xff, (state >> 8) & 0xff);
+    }
+
+    m3_amp_enable(card, 1);
+
+    /* 
+     * now we flip on the music 
+     */
+    for(i=0;i<NR_DSPS;i++) {
+        struct m3_state *s = &card->channels[i];
+        if(s->dev_audio == -1)
+            continue;
+        /*
+         * db->ready makes it so these guys can be
+         * called unconditionally..
+         */
+        DPRINTK(DPMOD, "turning on dacs ind %d\n",i);
+        start_dac(s);    
+        start_adc(s);    
+    }
+
+    restore_flags(flags);
+
+    /* 
+     * all right, we think things are ready, 
+     * wake up people who were using the device 
+     * when we suspended
+     */
+    wake_up(&card->suspend_queue);
+}
+
+MODULE_AUTHOR("Zach Brown <zab@zabbo.net>");
+MODULE_DESCRIPTION("ESS Maestro3/Allegro Driver");
+#ifdef M_DEBUG
+MODULE_PARM(debug,"i");
+#endif
+MODULE_PARM(external_amp,"i");
+
+static struct pci_driver m3_pci_driver = {
+    name:       "ess_m3_audio",
+    id_table:   m3_id_table,
+    probe:      m3_probe,
+    remove:     m3_remove,
+    suspend:    m3_suspend,
+    resume:     m3_resume,
+};
+
+static int __init m3_init_module(void)
+{
+    if (!pci_present())   /* No PCI bus in this machine! */
+        return -ENODEV;
+
+    printk(KERN_INFO PFX "version " DRIVER_VERSION " built at " __TIME__ " " __DATE__ "\n");
+
+    if (register_reboot_notifier(&m3_reboot_nb)) {
+        printk(KERN_WARNING PFX "reboot notifier registration failed\n");
+        return -ENODEV; /* ? */
+    }
+
+    if (!pci_register_driver(&m3_pci_driver)) {
+        pci_unregister_driver(&m3_pci_driver);
+        return -ENODEV;
+    }
+    return 0;
+}
+
+static void __exit m3_cleanup_module(void)
+{
+    pci_unregister_driver(&m3_pci_driver);
+}
+
+module_init(m3_init_module);
+module_exit(m3_cleanup_module);
+
+void check_suspend(struct m3_card *card)
+{
+    DECLARE_WAITQUEUE(wait, current);
+
+    if(!card->in_suspend) 
+        return;
+
+    card->in_suspend++;
+    add_wait_queue(&card->suspend_queue, &wait);
+    current->state = TASK_UNINTERRUPTIBLE;
+    schedule();
+    remove_wait_queue(&card->suspend_queue, &wait);
+    current->state = TASK_RUNNING;
+}
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/maestro3.h linux/drivers/sound/maestro3.h
--- v2.4.1/linux/drivers/sound/maestro3.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/sound/maestro3.h	Sun Feb  4 10:05:29 2001
@@ -0,0 +1,821 @@
+/*
+ *      ESS Technology allegro audio driver.
+ *
+ *      Copyright (C) 1992-2000  Don Kim (don.kim@esstech.com)
+ *
+ *      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.
+ *
+ *      Hacked for the maestro3 driver by zab
+ */
+
+// Allegro PCI configuration registers
+#define PCI_LEGACY_AUDIO_CTRL   0x40
+#define SOUND_BLASTER_ENABLE    0x00000001
+#define FM_SYNTHESIS_ENABLE     0x00000002
+#define GAME_PORT_ENABLE        0x00000004
+#define MPU401_IO_ENABLE        0x00000008
+#define MPU401_IRQ_ENABLE       0x00000010
+#define ALIAS_10BIT_IO          0x00000020
+#define SB_DMA_MASK             0x000000C0
+#define SB_DMA_0                0x00000040
+#define SB_DMA_1                0x00000040
+#define SB_DMA_R                0x00000080
+#define SB_DMA_3                0x000000C0
+#define SB_IRQ_MASK             0x00000700
+#define SB_IRQ_5                0x00000000
+#define SB_IRQ_7                0x00000100
+#define SB_IRQ_9                0x00000200
+#define SB_IRQ_10               0x00000300
+#define MIDI_IRQ_MASK           0x00003800
+#define SERIAL_IRQ_ENABLE       0x00004000
+#define DISABLE_LEGACY          0x00008000
+
+#define PCI_ALLEGRO_CONFIG      0x50
+#define SB_ADDR_240             0x00000004
+#define MPU_ADDR_MASK           0x00000018
+#define MPU_ADDR_330            0x00000000
+#define MPU_ADDR_300            0x00000008
+#define MPU_ADDR_320            0x00000010
+#define MPU_ADDR_340            0x00000018
+#define USE_PCI_TIMING          0x00000040
+#define POSTED_WRITE_ENABLE     0x00000080
+#define DMA_POLICY_MASK         0x00000700
+#define DMA_DDMA                0x00000000
+#define DMA_TDMA                0x00000100
+#define DMA_PCPCI               0x00000200
+#define DMA_WBDMA16             0x00000400
+#define DMA_WBDMA4              0x00000500
+#define DMA_WBDMA2              0x00000600
+#define DMA_WBDMA1              0x00000700
+#define DMA_SAFE_GUARD          0x00000800
+#define HI_PERF_GP_ENABLE       0x00001000
+#define PIC_SNOOP_MODE_0        0x00002000
+#define PIC_SNOOP_MODE_1        0x00004000
+#define SOUNDBLASTER_IRQ_MASK   0x00008000
+#define RING_IN_ENABLE          0x00010000
+#define SPDIF_TEST_MODE         0x00020000
+#define CLK_MULT_MODE_SELECT_2  0x00040000
+#define EEPROM_WRITE_ENABLE     0x00080000
+#define CODEC_DIR_IN            0x00100000
+#define HV_BUTTON_FROM_GD       0x00200000
+#define REDUCED_DEBOUNCE        0x00400000
+#define HV_CTRL_ENABLE          0x00800000
+#define SPDIF_ENABLE            0x01000000
+#define CLK_DIV_SELECT          0x06000000
+#define CLK_DIV_BY_48           0x00000000
+#define CLK_DIV_BY_49           0x02000000
+#define CLK_DIV_BY_50           0x04000000
+#define CLK_DIV_RESERVED        0x06000000
+#define PM_CTRL_ENABLE          0x08000000
+#define CLK_MULT_MODE_SELECT    0x30000000
+#define CLK_MULT_MODE_SHIFT     28
+#define CLK_MULT_MODE_0         0x00000000
+#define CLK_MULT_MODE_1         0x10000000
+#define CLK_MULT_MODE_2         0x20000000
+#define CLK_MULT_MODE_3         0x30000000
+#define INT_CLK_SELECT          0x40000000
+#define INT_CLK_MULT_RESET      0x80000000
+
+// M3
+#define INT_CLK_SRC_NOT_PCI     0x00100000
+#define INT_CLK_MULT_ENABLE     0x80000000
+
+#define PCI_ACPI_CONTROL        0x54
+#define PCI_ACPI_D0             0x00000000
+#define PCI_ACPI_D1             0xB4F70000
+#define PCI_ACPI_D2             0xB4F7B4F7
+
+#define PCI_USER_CONFIG         0x58
+#define EXT_PCI_MASTER_ENABLE   0x00000001
+#define SPDIF_OUT_SELECT        0x00000002
+#define TEST_PIN_DIR_CTRL       0x00000004
+#define AC97_CODEC_TEST         0x00000020
+#define TRI_STATE_BUFFER        0x00000080
+#define IN_CLK_12MHZ_SELECT     0x00000100
+#define MULTI_FUNC_DISABLE      0x00000200
+#define EXT_MASTER_PAIR_SEL     0x00000400
+#define PCI_MASTER_SUPPORT      0x00000800
+#define STOP_CLOCK_ENABLE       0x00001000
+#define EAPD_DRIVE_ENABLE       0x00002000
+#define REQ_TRI_STATE_ENABLE    0x00004000
+#define REQ_LOW_ENABLE          0x00008000
+#define MIDI_1_ENABLE           0x00010000
+#define MIDI_2_ENABLE           0x00020000
+#define SB_AUDIO_SYNC           0x00040000
+#define HV_CTRL_TEST            0x00100000
+#define SOUNDBLASTER_TEST       0x00400000
+
+#define PCI_USER_CONFIG_C       0x5C
+
+#define PCI_DDMA_CTRL           0x60
+#define DDMA_ENABLE             0x00000001
+
+
+// Allegro registers
+#define HOST_INT_CTRL           0x18
+#define SB_INT_ENABLE           0x0001
+#define MPU401_INT_ENABLE       0x0002
+#define ASSP_INT_ENABLE         0x0010
+#define RING_INT_ENABLE         0x0020
+#define HV_INT_ENABLE           0x0040
+#define CLKRUN_GEN_ENABLE       0x0100
+#define HV_CTRL_TO_PME          0x0400
+#define SOFTWARE_RESET_ENABLE   0x8000
+
+/*
+ * should be using the above defines, probably.
+ */
+#define REGB_ENABLE_RESET               0x01
+#define REGB_STOP_CLOCK                 0x10
+
+#define HOST_INT_STATUS         0x1A
+#define SB_INT_PENDING          0x01
+#define MPU401_INT_PENDING      0x02
+#define ASSP_INT_PENDING        0x10
+#define RING_INT_PENDING        0x20
+#define HV_INT_PENDING          0x40
+
+#define HARDWARE_VOL_CTRL       0x1B
+#define SHADOW_MIX_REG_VOICE    0x1C
+#define HW_VOL_COUNTER_VOICE    0x1D
+#define SHADOW_MIX_REG_MASTER   0x1E
+#define HW_VOL_COUNTER_MASTER   0x1F
+
+#define CODEC_COMMAND           0x30
+#define CODEC_READ_B            0x80
+
+#define CODEC_STATUS            0x30
+#define CODEC_BUSY_B            0x01
+
+#define CODEC_DATA              0x32
+
+#define RING_BUS_CTRL_A         0x36
+#define RAC_PME_ENABLE          0x0100
+#define RAC_SDFS_ENABLE         0x0200
+#define LAC_PME_ENABLE          0x0400
+#define LAC_SDFS_ENABLE         0x0800
+#define SERIAL_AC_LINK_ENABLE   0x1000
+#define IO_SRAM_ENABLE          0x2000
+#define IIS_INPUT_ENABLE        0x8000
+
+#define RING_BUS_CTRL_B         0x38
+#define SECOND_CODEC_ID_MASK    0x0003
+#define SPDIF_FUNC_ENABLE       0x0010
+#define SECOND_AC_ENABLE        0x0020
+#define SB_MODULE_INTF_ENABLE   0x0040
+#define SSPE_ENABLE             0x0040
+#define M3I_DOCK_ENABLE         0x0080
+
+#define SDO_OUT_DEST_CTRL       0x3A
+#define COMMAND_ADDR_OUT        0x0003
+#define PCM_LR_OUT_LOCAL        0x0000
+#define PCM_LR_OUT_REMOTE       0x0004
+#define PCM_LR_OUT_MUTE         0x0008
+#define PCM_LR_OUT_BOTH         0x000C
+#define LINE1_DAC_OUT_LOCAL     0x0000
+#define LINE1_DAC_OUT_REMOTE    0x0010
+#define LINE1_DAC_OUT_MUTE      0x0020
+#define LINE1_DAC_OUT_BOTH      0x0030
+#define PCM_CLS_OUT_LOCAL       0x0000
+#define PCM_CLS_OUT_REMOTE      0x0040
+#define PCM_CLS_OUT_MUTE        0x0080
+#define PCM_CLS_OUT_BOTH        0x00C0
+#define PCM_RLF_OUT_LOCAL       0x0000
+#define PCM_RLF_OUT_REMOTE      0x0100
+#define PCM_RLF_OUT_MUTE        0x0200
+#define PCM_RLF_OUT_BOTH        0x0300
+#define LINE2_DAC_OUT_LOCAL     0x0000
+#define LINE2_DAC_OUT_REMOTE    0x0400
+#define LINE2_DAC_OUT_MUTE      0x0800
+#define LINE2_DAC_OUT_BOTH      0x0C00
+#define HANDSET_OUT_LOCAL       0x0000
+#define HANDSET_OUT_REMOTE      0x1000
+#define HANDSET_OUT_MUTE        0x2000
+#define HANDSET_OUT_BOTH        0x3000
+#define IO_CTRL_OUT_LOCAL       0x0000
+#define IO_CTRL_OUT_REMOTE      0x4000
+#define IO_CTRL_OUT_MUTE        0x8000
+#define IO_CTRL_OUT_BOTH        0xC000
+
+#define SDO_IN_DEST_CTRL        0x3C
+#define STATUS_ADDR_IN          0x0003
+#define PCM_LR_IN_LOCAL         0x0000
+#define PCM_LR_IN_REMOTE        0x0004
+#define PCM_LR_RESERVED         0x0008
+#define PCM_LR_IN_BOTH          0x000C
+#define LINE1_ADC_IN_LOCAL      0x0000
+#define LINE1_ADC_IN_REMOTE     0x0010
+#define LINE1_ADC_IN_MUTE       0x0020
+#define MIC_ADC_IN_LOCAL        0x0000
+#define MIC_ADC_IN_REMOTE       0x0040
+#define MIC_ADC_IN_MUTE         0x0080
+#define LINE2_DAC_IN_LOCAL      0x0000
+#define LINE2_DAC_IN_REMOTE     0x0400
+#define LINE2_DAC_IN_MUTE       0x0800
+#define HANDSET_IN_LOCAL        0x0000
+#define HANDSET_IN_REMOTE       0x1000
+#define HANDSET_IN_MUTE         0x2000
+#define IO_STATUS_IN_LOCAL      0x0000
+#define IO_STATUS_IN_REMOTE     0x4000
+
+#define SPDIF_IN_CTRL           0x3E
+#define SPDIF_IN_ENABLE         0x0001
+
+#define GPIO_DATA               0x60
+#define GPIO_DATA_MASK          0x0FFF
+#define GPIO_HV_STATUS          0x3000
+#define GPIO_PME_STATUS         0x4000
+
+#define GPIO_MASK               0x64
+#define GPIO_DIRECTION          0x68
+#define GPO_PRIMARY_AC97        0x0001
+#define GPI_LINEOUT_SENSE       0x0004
+#define GPO_SECONDARY_AC97      0x0008
+#define GPI_VOL_DOWN            0x0010
+#define GPI_VOL_UP              0x0020
+#define GPI_IIS_CLK             0x0040
+#define GPI_IIS_LRCLK           0x0080
+#define GPI_IIS_DATA            0x0100
+#define GPI_DOCKING_STATUS      0x0100
+#define GPI_HEADPHONE_SENSE     0x0200
+#define GPO_EXT_AMP_SHUTDOWN    0x1000
+
+// M3
+#define GPO_M3_EXT_AMP_SHUTDN   0x0002
+
+#define ASSP_INDEX_PORT         0x80
+#define ASSP_MEMORY_PORT        0x82
+#define ASSP_DATA_PORT          0x84
+
+#define MPU401_DATA_PORT        0x98
+#define MPU401_STATUS_PORT      0x99
+
+#define CLK_MULT_DATA_PORT      0x9C
+
+#define ASSP_CONTROL_A          0xA2
+#define ASSP_0_WS_ENABLE        0x01
+#define ASSP_CTRL_A_RESERVED1   0x02
+#define ASSP_CTRL_A_RESERVED2   0x04
+#define ASSP_CLK_49MHZ_SELECT   0x08
+#define FAST_PLU_ENABLE         0x10
+#define ASSP_CTRL_A_RESERVED3   0x20
+#define DSP_CLK_36MHZ_SELECT    0x40
+
+#define ASSP_CONTROL_B          0xA4
+#define RESET_ASSP              0x00
+#define RUN_ASSP                0x01
+#define ENABLE_ASSP_CLOCK       0x00
+#define STOP_ASSP_CLOCK         0x10
+#define RESET_TOGGLE            0x40
+
+#define ASSP_CONTROL_C          0xA6
+#define ASSP_HOST_INT_ENABLE    0x01
+#define FM_ADDR_REMAP_DISABLE   0x02
+#define HOST_WRITE_PORT_ENABLE  0x08
+
+#define ASSP_HOST_INT_STATUS    0xAC
+#define DSP2HOST_REQ_PIORECORD  0x01
+#define DSP2HOST_REQ_I2SRATE    0x02
+#define DSP2HOST_REQ_TIMER      0x04
+
+// AC97 registers
+// XXX fix this crap up
+/*#define AC97_RESET              0x00*/
+
+#define AC97_VOL_MUTE_B         0x8000
+#define AC97_VOL_M              0x1F
+#define AC97_LEFT_VOL_S         8
+
+#define AC97_MASTER_VOL         0x02
+#define AC97_LINE_LEVEL_VOL     0x04
+#define AC97_MASTER_MONO_VOL    0x06
+#define AC97_PC_BEEP_VOL        0x0A
+#define AC97_PC_BEEP_VOL_M      0x0F
+#define AC97_SROUND_MASTER_VOL  0x38
+#define AC97_PC_BEEP_VOL_S      1
+
+/*#define AC97_PHONE_VOL          0x0C
+#define AC97_MIC_VOL            0x0E*/
+#define AC97_MIC_20DB_ENABLE    0x40
+
+/*#define AC97_LINEIN_VOL         0x10
+#define AC97_CD_VOL             0x12
+#define AC97_VIDEO_VOL          0x14
+#define AC97_AUX_VOL            0x16*/
+#define AC97_PCM_OUT_VOL        0x18
+/*#define AC97_RECORD_SELECT      0x1A*/
+#define AC97_RECORD_MIC         0x00
+#define AC97_RECORD_CD          0x01
+#define AC97_RECORD_VIDEO       0x02
+#define AC97_RECORD_AUX         0x03
+#define AC97_RECORD_MONO_MUX    0x02
+#define AC97_RECORD_DIGITAL     0x03
+#define AC97_RECORD_LINE        0x04
+#define AC97_RECORD_STEREO      0x05
+#define AC97_RECORD_MONO        0x06
+#define AC97_RECORD_PHONE       0x07
+
+/*#define AC97_RECORD_GAIN        0x1C*/
+#define AC97_RECORD_VOL_M       0x0F
+
+/*#define AC97_GENERAL_PURPOSE    0x20*/
+#define AC97_POWER_DOWN_CTRL    0x26
+#define AC97_ADC_READY          0x0001
+#define AC97_DAC_READY          0x0002
+#define AC97_ANALOG_READY       0x0004
+#define AC97_VREF_ON            0x0008
+#define AC97_PR0                0x0100
+#define AC97_PR1                0x0200
+#define AC97_PR2                0x0400
+#define AC97_PR3                0x0800
+#define AC97_PR4                0x1000
+
+#define AC97_RESERVED1          0x28
+
+#define AC97_VENDOR_TEST        0x5A
+
+#define AC97_CLOCK_DELAY        0x5C
+#define AC97_LINEOUT_MUX_SEL    0x0001
+#define AC97_MONO_MUX_SEL       0x0002
+#define AC97_CLOCK_DELAY_SEL    0x1F
+#define AC97_DAC_CDS_SHIFT      6
+#define AC97_ADC_CDS_SHIFT      11
+
+#define AC97_MULTI_CHANNEL_SEL  0x74
+
+/*#define AC97_VENDOR_ID1         0x7C
+#define AC97_VENDOR_ID2         0x7E*/
+
+/*
+ * ASSP control regs
+ */
+#define DSP_PORT_TIMER_COUNT    0x06
+
+#define DSP_PORT_MEMORY_INDEX   0x80
+
+#define DSP_PORT_MEMORY_TYPE    0x82
+#define MEMTYPE_INTERNAL_CODE   0x0002
+#define MEMTYPE_INTERNAL_DATA   0x0003
+#define MEMTYPE_MASK            0x0003
+
+#define DSP_PORT_MEMORY_DATA    0x84
+
+#define DSP_PORT_CONTROL_REG_A  0xA2
+#define DSP_PORT_CONTROL_REG_B  0xA4
+#define DSP_PORT_CONTROL_REG_C  0xA6
+
+#define REV_A_CODE_MEMORY_BEGIN         0x0000
+#define REV_A_CODE_MEMORY_END           0x0FFF
+#define REV_A_CODE_MEMORY_UNIT_LENGTH   0x0040
+#define REV_A_CODE_MEMORY_LENGTH        (REV_A_CODE_MEMORY_END - REV_A_CODE_MEMORY_BEGIN + 1)
+
+#define REV_B_CODE_MEMORY_BEGIN         0x0000
+#define REV_B_CODE_MEMORY_END           0x0BFF
+#define REV_B_CODE_MEMORY_UNIT_LENGTH   0x0040
+#define REV_B_CODE_MEMORY_LENGTH        (REV_B_CODE_MEMORY_END - REV_B_CODE_MEMORY_BEGIN + 1)
+
+#define REV_A_DATA_MEMORY_BEGIN         0x1000
+#define REV_A_DATA_MEMORY_END           0x2FFF
+#define REV_A_DATA_MEMORY_UNIT_LENGTH   0x0080
+#define REV_A_DATA_MEMORY_LENGTH        (REV_A_DATA_MEMORY_END - REV_A_DATA_MEMORY_BEGIN + 1)
+
+#define REV_B_DATA_MEMORY_BEGIN         0x1000
+#define REV_B_DATA_MEMORY_END           0x2BFF
+#define REV_B_DATA_MEMORY_UNIT_LENGTH   0x0080
+#define REV_B_DATA_MEMORY_LENGTH        (REV_B_DATA_MEMORY_END - REV_B_DATA_MEMORY_BEGIN + 1)
+
+
+#define NUM_UNITS_KERNEL_CODE          16
+#define NUM_UNITS_KERNEL_DATA           2
+
+#define NUM_UNITS_KERNEL_CODE_WITH_HSP 16
+#define NUM_UNITS_KERNEL_DATA_WITH_HSP  5
+
+/*
+ * Kernel data layout
+ */
+
+#define DP_SHIFT_COUNT                  7
+
+#define KDATA_BASE_ADDR                 0x1000
+#define KDATA_BASE_ADDR2                0x1080
+
+#define KDATA_TASK0                     (KDATA_BASE_ADDR + 0x0000)
+#define KDATA_TASK1                     (KDATA_BASE_ADDR + 0x0001)
+#define KDATA_TASK2                     (KDATA_BASE_ADDR + 0x0002)
+#define KDATA_TASK3                     (KDATA_BASE_ADDR + 0x0003)
+#define KDATA_TASK4                     (KDATA_BASE_ADDR + 0x0004)
+#define KDATA_TASK5                     (KDATA_BASE_ADDR + 0x0005)
+#define KDATA_TASK6                     (KDATA_BASE_ADDR + 0x0006)
+#define KDATA_TASK7                     (KDATA_BASE_ADDR + 0x0007)
+#define KDATA_TASK_ENDMARK              (KDATA_BASE_ADDR + 0x0008)
+
+#define KDATA_CURRENT_TASK              (KDATA_BASE_ADDR + 0x0009)
+#define KDATA_TASK_SWITCH               (KDATA_BASE_ADDR + 0x000A)
+
+#define KDATA_INSTANCE0_POS3D           (KDATA_BASE_ADDR + 0x000B)
+#define KDATA_INSTANCE1_POS3D           (KDATA_BASE_ADDR + 0x000C)
+#define KDATA_INSTANCE2_POS3D           (KDATA_BASE_ADDR + 0x000D)
+#define KDATA_INSTANCE3_POS3D           (KDATA_BASE_ADDR + 0x000E)
+#define KDATA_INSTANCE4_POS3D           (KDATA_BASE_ADDR + 0x000F)
+#define KDATA_INSTANCE5_POS3D           (KDATA_BASE_ADDR + 0x0010)
+#define KDATA_INSTANCE6_POS3D           (KDATA_BASE_ADDR + 0x0011)
+#define KDATA_INSTANCE7_POS3D           (KDATA_BASE_ADDR + 0x0012)
+#define KDATA_INSTANCE8_POS3D           (KDATA_BASE_ADDR + 0x0013)
+#define KDATA_INSTANCE_POS3D_ENDMARK    (KDATA_BASE_ADDR + 0x0014)
+
+#define KDATA_INSTANCE0_SPKVIRT         (KDATA_BASE_ADDR + 0x0015)
+#define KDATA_INSTANCE_SPKVIRT_ENDMARK  (KDATA_BASE_ADDR + 0x0016)
+
+#define KDATA_INSTANCE0_SPDIF           (KDATA_BASE_ADDR + 0x0017)
+#define KDATA_INSTANCE_SPDIF_ENDMARK    (KDATA_BASE_ADDR + 0x0018)
+
+#define KDATA_INSTANCE0_MODEM           (KDATA_BASE_ADDR + 0x0019)
+#define KDATA_INSTANCE_MODEM_ENDMARK    (KDATA_BASE_ADDR + 0x001A)
+
+#define KDATA_INSTANCE0_SRC             (KDATA_BASE_ADDR + 0x001B)
+#define KDATA_INSTANCE1_SRC             (KDATA_BASE_ADDR + 0x001C)
+#define KDATA_INSTANCE_SRC_ENDMARK      (KDATA_BASE_ADDR + 0x001D)
+
+#define KDATA_INSTANCE0_MINISRC         (KDATA_BASE_ADDR + 0x001E)
+#define KDATA_INSTANCE1_MINISRC         (KDATA_BASE_ADDR + 0x001F)
+#define KDATA_INSTANCE2_MINISRC         (KDATA_BASE_ADDR + 0x0020)
+#define KDATA_INSTANCE3_MINISRC         (KDATA_BASE_ADDR + 0x0021)
+#define KDATA_INSTANCE_MINISRC_ENDMARK  (KDATA_BASE_ADDR + 0x0022)
+
+#define KDATA_INSTANCE0_CPYTHRU         (KDATA_BASE_ADDR + 0x0023)
+#define KDATA_INSTANCE1_CPYTHRU         (KDATA_BASE_ADDR + 0x0024)
+#define KDATA_INSTANCE_CPYTHRU_ENDMARK  (KDATA_BASE_ADDR + 0x0025)
+
+#define KDATA_CURRENT_DMA               (KDATA_BASE_ADDR + 0x0026)
+#define KDATA_DMA_SWITCH                (KDATA_BASE_ADDR + 0x0027)
+#define KDATA_DMA_ACTIVE                (KDATA_BASE_ADDR + 0x0028)
+
+#define KDATA_DMA_XFER0                 (KDATA_BASE_ADDR + 0x0029)
+#define KDATA_DMA_XFER1                 (KDATA_BASE_ADDR + 0x002A)
+#define KDATA_DMA_XFER2                 (KDATA_BASE_ADDR + 0x002B)
+#define KDATA_DMA_XFER3                 (KDATA_BASE_ADDR + 0x002C)
+#define KDATA_DMA_XFER4                 (KDATA_BASE_ADDR + 0x002D)
+#define KDATA_DMA_XFER5                 (KDATA_BASE_ADDR + 0x002E)
+#define KDATA_DMA_XFER6                 (KDATA_BASE_ADDR + 0x002F)
+#define KDATA_DMA_XFER7                 (KDATA_BASE_ADDR + 0x0030)
+#define KDATA_DMA_XFER8                 (KDATA_BASE_ADDR + 0x0031)
+#define KDATA_DMA_XFER_ENDMARK          (KDATA_BASE_ADDR + 0x0032)
+
+#define KDATA_I2S_SAMPLE_COUNT          (KDATA_BASE_ADDR + 0x0033)
+#define KDATA_I2S_INT_METER             (KDATA_BASE_ADDR + 0x0034)
+#define KDATA_I2S_ACTIVE                (KDATA_BASE_ADDR + 0x0035)
+
+#define KDATA_TIMER_COUNT_RELOAD        (KDATA_BASE_ADDR + 0x0036)
+#define KDATA_TIMER_COUNT_CURRENT       (KDATA_BASE_ADDR + 0x0037)
+
+#define KDATA_HALT_SYNCH_CLIENT         (KDATA_BASE_ADDR + 0x0038)
+#define KDATA_HALT_SYNCH_DMA            (KDATA_BASE_ADDR + 0x0039)
+#define KDATA_HALT_ACKNOWLEDGE          (KDATA_BASE_ADDR + 0x003A)
+
+#define KDATA_ADC1_XFER0                (KDATA_BASE_ADDR + 0x003B)
+#define KDATA_ADC1_XFER_ENDMARK         (KDATA_BASE_ADDR + 0x003C)
+#define KDATA_ADC1_LEFT_VOLUME			(KDATA_BASE_ADDR + 0x003D)
+#define KDATA_ADC1_RIGHT_VOLUME  		(KDATA_BASE_ADDR + 0x003E)
+#define KDATA_ADC1_LEFT_SUR_VOL			(KDATA_BASE_ADDR + 0x003F)
+#define KDATA_ADC1_RIGHT_SUR_VOL		(KDATA_BASE_ADDR + 0x0040)
+
+#define KDATA_ADC2_XFER0                (KDATA_BASE_ADDR + 0x0041)
+#define KDATA_ADC2_XFER_ENDMARK         (KDATA_BASE_ADDR + 0x0042)
+#define KDATA_ADC2_LEFT_VOLUME			(KDATA_BASE_ADDR + 0x0043)
+#define KDATA_ADC2_RIGHT_VOLUME			(KDATA_BASE_ADDR + 0x0044)
+#define KDATA_ADC2_LEFT_SUR_VOL			(KDATA_BASE_ADDR + 0x0045)
+#define KDATA_ADC2_RIGHT_SUR_VOL		(KDATA_BASE_ADDR + 0x0046)
+
+#define KDATA_CD_XFER0					(KDATA_BASE_ADDR + 0x0047)					
+#define KDATA_CD_XFER_ENDMARK			(KDATA_BASE_ADDR + 0x0048)
+#define KDATA_CD_LEFT_VOLUME			(KDATA_BASE_ADDR + 0x0049)
+#define KDATA_CD_RIGHT_VOLUME			(KDATA_BASE_ADDR + 0x004A)
+#define KDATA_CD_LEFT_SUR_VOL			(KDATA_BASE_ADDR + 0x004B)
+#define KDATA_CD_RIGHT_SUR_VOL			(KDATA_BASE_ADDR + 0x004C)
+
+#define KDATA_MIC_XFER0					(KDATA_BASE_ADDR + 0x004D)
+#define KDATA_MIC_XFER_ENDMARK			(KDATA_BASE_ADDR + 0x004E)
+#define KDATA_MIC_VOLUME				(KDATA_BASE_ADDR + 0x004F)
+#define KDATA_MIC_SUR_VOL				(KDATA_BASE_ADDR + 0x0050)
+
+#define KDATA_I2S_XFER0                 (KDATA_BASE_ADDR + 0x0051)
+#define KDATA_I2S_XFER_ENDMARK          (KDATA_BASE_ADDR + 0x0052)
+
+#define KDATA_CHI_XFER0                 (KDATA_BASE_ADDR + 0x0053)
+#define KDATA_CHI_XFER_ENDMARK          (KDATA_BASE_ADDR + 0x0054)
+
+#define KDATA_SPDIF_XFER                (KDATA_BASE_ADDR + 0x0055)
+#define KDATA_SPDIF_CURRENT_FRAME       (KDATA_BASE_ADDR + 0x0056)
+#define KDATA_SPDIF_FRAME0              (KDATA_BASE_ADDR + 0x0057)
+#define KDATA_SPDIF_FRAME1              (KDATA_BASE_ADDR + 0x0058)
+#define KDATA_SPDIF_FRAME2              (KDATA_BASE_ADDR + 0x0059)
+
+#define KDATA_SPDIF_REQUEST             (KDATA_BASE_ADDR + 0x005A)
+#define KDATA_SPDIF_TEMP                (KDATA_BASE_ADDR + 0x005B)
+
+#define KDATA_SPDIFIN_XFER0             (KDATA_BASE_ADDR + 0x005C)
+#define KDATA_SPDIFIN_XFER_ENDMARK      (KDATA_BASE_ADDR + 0x005D)
+#define KDATA_SPDIFIN_INT_METER         (KDATA_BASE_ADDR + 0x005E)
+
+#define KDATA_DSP_RESET_COUNT           (KDATA_BASE_ADDR + 0x005F)
+#define KDATA_DEBUG_OUTPUT              (KDATA_BASE_ADDR + 0x0060)
+
+#define KDATA_KERNEL_ISR_LIST           (KDATA_BASE_ADDR + 0x0061)
+
+#define KDATA_KERNEL_ISR_CBSR1          (KDATA_BASE_ADDR + 0x0062)
+#define KDATA_KERNEL_ISR_CBER1          (KDATA_BASE_ADDR + 0x0063)
+#define KDATA_KERNEL_ISR_CBCR           (KDATA_BASE_ADDR + 0x0064)
+#define KDATA_KERNEL_ISR_AR0            (KDATA_BASE_ADDR + 0x0065)
+#define KDATA_KERNEL_ISR_AR1            (KDATA_BASE_ADDR + 0x0066)
+#define KDATA_KERNEL_ISR_AR2            (KDATA_BASE_ADDR + 0x0067)
+#define KDATA_KERNEL_ISR_AR3            (KDATA_BASE_ADDR + 0x0068)
+#define KDATA_KERNEL_ISR_AR4            (KDATA_BASE_ADDR + 0x0069)
+#define KDATA_KERNEL_ISR_AR5            (KDATA_BASE_ADDR + 0x006A)
+#define KDATA_KERNEL_ISR_BRCR           (KDATA_BASE_ADDR + 0x006B)
+#define KDATA_KERNEL_ISR_PASR           (KDATA_BASE_ADDR + 0x006C)
+#define KDATA_KERNEL_ISR_PAER           (KDATA_BASE_ADDR + 0x006D)
+
+#define KDATA_CLIENT_SCRATCH0           (KDATA_BASE_ADDR + 0x006E)
+#define KDATA_CLIENT_SCRATCH1           (KDATA_BASE_ADDR + 0x006F)
+#define KDATA_KERNEL_SCRATCH            (KDATA_BASE_ADDR + 0x0070)
+#define KDATA_KERNEL_ISR_SCRATCH        (KDATA_BASE_ADDR + 0x0071)
+
+#define KDATA_OUEUE_LEFT                (KDATA_BASE_ADDR + 0x0072)
+#define KDATA_QUEUE_RIGHT               (KDATA_BASE_ADDR + 0x0073)
+
+#define KDATA_ADC1_REQUEST              (KDATA_BASE_ADDR + 0x0074)
+#define KDATA_ADC2_REQUEST              (KDATA_BASE_ADDR + 0x0075)
+#define KDATA_CD_REQUEST				(KDATA_BASE_ADDR + 0x0076)
+#define KDATA_MIC_REQUEST				(KDATA_BASE_ADDR + 0x0077)
+
+#define KDATA_ADC1_MIXER_REQUEST        (KDATA_BASE_ADDR + 0x0078)
+#define KDATA_ADC2_MIXER_REQUEST        (KDATA_BASE_ADDR + 0x0079)
+#define KDATA_CD_MIXER_REQUEST			(KDATA_BASE_ADDR + 0x007A)
+#define KDATA_MIC_MIXER_REQUEST			(KDATA_BASE_ADDR + 0x007B)
+#define KDATA_MIC_SYNC_COUNTER			(KDATA_BASE_ADDR + 0x007C)
+
+/*
+ * second 'segment' (?) reserved for mixer
+ * buffers..
+ */
+
+#define KDATA_MIXER_WORD0               (KDATA_BASE_ADDR2 + 0x0000)
+#define KDATA_MIXER_WORD1               (KDATA_BASE_ADDR2 + 0x0001)
+#define KDATA_MIXER_WORD2               (KDATA_BASE_ADDR2 + 0x0002)
+#define KDATA_MIXER_WORD3               (KDATA_BASE_ADDR2 + 0x0003)
+#define KDATA_MIXER_WORD4               (KDATA_BASE_ADDR2 + 0x0004)
+#define KDATA_MIXER_WORD5               (KDATA_BASE_ADDR2 + 0x0005)
+#define KDATA_MIXER_WORD6               (KDATA_BASE_ADDR2 + 0x0006)
+#define KDATA_MIXER_WORD7               (KDATA_BASE_ADDR2 + 0x0007)
+#define KDATA_MIXER_WORD8               (KDATA_BASE_ADDR2 + 0x0008)
+#define KDATA_MIXER_WORD9               (KDATA_BASE_ADDR2 + 0x0009)
+#define KDATA_MIXER_WORDA               (KDATA_BASE_ADDR2 + 0x000A)
+#define KDATA_MIXER_WORDB               (KDATA_BASE_ADDR2 + 0x000B)
+#define KDATA_MIXER_WORDC               (KDATA_BASE_ADDR2 + 0x000C)
+#define KDATA_MIXER_WORDD               (KDATA_BASE_ADDR2 + 0x000D)
+#define KDATA_MIXER_WORDE               (KDATA_BASE_ADDR2 + 0x000E)
+#define KDATA_MIXER_WORDF               (KDATA_BASE_ADDR2 + 0x000F)
+
+#define KDATA_MIXER_XFER0               (KDATA_BASE_ADDR2 + 0x0010)
+#define KDATA_MIXER_XFER1               (KDATA_BASE_ADDR2 + 0x0011)
+#define KDATA_MIXER_XFER2               (KDATA_BASE_ADDR2 + 0x0012)
+#define KDATA_MIXER_XFER3               (KDATA_BASE_ADDR2 + 0x0013)
+#define KDATA_MIXER_XFER4               (KDATA_BASE_ADDR2 + 0x0014)
+#define KDATA_MIXER_XFER5               (KDATA_BASE_ADDR2 + 0x0015)
+#define KDATA_MIXER_XFER6               (KDATA_BASE_ADDR2 + 0x0016)
+#define KDATA_MIXER_XFER7               (KDATA_BASE_ADDR2 + 0x0017)
+#define KDATA_MIXER_XFER8               (KDATA_BASE_ADDR2 + 0x0018)
+#define KDATA_MIXER_XFER9               (KDATA_BASE_ADDR2 + 0x0019)
+#define KDATA_MIXER_XFER_ENDMARK        (KDATA_BASE_ADDR2 + 0x001A)
+
+#define KDATA_MIXER_TASK_NUMBER         (KDATA_BASE_ADDR2 + 0x001B)
+#define KDATA_CURRENT_MIXER             (KDATA_BASE_ADDR2 + 0x001C)
+#define KDATA_MIXER_ACTIVE              (KDATA_BASE_ADDR2 + 0x001D)
+#define KDATA_MIXER_BANK_STATUS         (KDATA_BASE_ADDR2 + 0x001E)
+#define KDATA_DAC_LEFT_VOLUME	        (KDATA_BASE_ADDR2 + 0x001F)
+#define KDATA_DAC_RIGHT_VOLUME          (KDATA_BASE_ADDR2 + 0x0020)
+
+#define MAX_INSTANCE_MINISRC            (KDATA_INSTANCE_MINISRC_ENDMARK - KDATA_INSTANCE0_MINISRC)
+#define MAX_VIRTUAL_DMA_CHANNELS        (KDATA_DMA_XFER_ENDMARK - KDATA_DMA_XFER0)
+#define MAX_VIRTUAL_MIXER_CHANNELS      (KDATA_MIXER_XFER_ENDMARK - KDATA_MIXER_XFER0)
+#define MAX_VIRTUAL_ADC1_CHANNELS       (KDATA_ADC1_XFER_ENDMARK - KDATA_ADC1_XFER0)
+
+/*
+ * client data area offsets
+ */
+#define CDATA_INSTANCE_READY            0x00
+
+#define CDATA_HOST_SRC_ADDRL            0x01
+#define CDATA_HOST_SRC_ADDRH            0x02
+#define CDATA_HOST_SRC_END_PLUS_1L      0x03
+#define CDATA_HOST_SRC_END_PLUS_1H      0x04
+#define CDATA_HOST_SRC_CURRENTL         0x05
+#define CDATA_HOST_SRC_CURRENTH         0x06
+
+#define CDATA_IN_BUF_CONNECT            0x07
+#define CDATA_OUT_BUF_CONNECT           0x08
+
+#define CDATA_IN_BUF_BEGIN              0x09
+#define CDATA_IN_BUF_END_PLUS_1         0x0A
+#define CDATA_IN_BUF_HEAD               0x0B
+#define CDATA_IN_BUF_TAIL               0x0C
+#define CDATA_OUT_BUF_BEGIN             0x0D
+#define CDATA_OUT_BUF_END_PLUS_1        0x0E
+#define CDATA_OUT_BUF_HEAD              0x0F
+#define CDATA_OUT_BUF_TAIL              0x10
+
+#define CDATA_DMA_CONTROL               0x11
+#define CDATA_RESERVED                  0x12
+
+#define CDATA_FREQUENCY                 0x13
+#define CDATA_LEFT_VOLUME               0x14
+#define CDATA_RIGHT_VOLUME              0x15
+#define CDATA_LEFT_SUR_VOL              0x16
+#define CDATA_RIGHT_SUR_VOL             0x17
+
+#define CDATA_HEADER_LEN                0x18
+
+#define SRC3_DIRECTION_OFFSET           CDATA_HEADER_LEN
+#define SRC3_MODE_OFFSET                (CDATA_HEADER_LEN + 1)
+#define SRC3_WORD_LENGTH_OFFSET         (CDATA_HEADER_LEN + 2)
+#define SRC3_PARAMETER_OFFSET           (CDATA_HEADER_LEN + 3)
+#define SRC3_COEFF_ADDR_OFFSET          (CDATA_HEADER_LEN + 8)
+#define SRC3_FILTAP_ADDR_OFFSET         (CDATA_HEADER_LEN + 10)
+#define SRC3_TEMP_INBUF_ADDR_OFFSET     (CDATA_HEADER_LEN + 16)
+#define SRC3_TEMP_OUTBUF_ADDR_OFFSET    (CDATA_HEADER_LEN + 17)
+
+#define MINISRC_IN_BUFFER_SIZE   ( 0x50 * 2 )
+#define MINISRC_OUT_BUFFER_SIZE  ( 0x50 * 2 * 2)
+#define MINISRC_OUT_BUFFER_SIZE  ( 0x50 * 2 * 2)
+#define MINISRC_TMP_BUFFER_SIZE  ( 112 + ( MINISRC_BIQUAD_STAGE * 3 + 4 ) * 2 * 2 )
+#define MINISRC_BIQUAD_STAGE    2
+#define MINISRC_COEF_LOC          0X175
+
+#define DMACONTROL_BLOCK_MASK           0x000F
+#define  DMAC_BLOCK0_SELECTOR           0x0000
+#define  DMAC_BLOCK1_SELECTOR           0x0001
+#define  DMAC_BLOCK2_SELECTOR           0x0002
+#define  DMAC_BLOCK3_SELECTOR           0x0003
+#define  DMAC_BLOCK4_SELECTOR           0x0004
+#define  DMAC_BLOCK5_SELECTOR           0x0005
+#define  DMAC_BLOCK6_SELECTOR           0x0006
+#define  DMAC_BLOCK7_SELECTOR           0x0007
+#define  DMAC_BLOCK8_SELECTOR           0x0008
+#define  DMAC_BLOCK9_SELECTOR           0x0009
+#define  DMAC_BLOCKA_SELECTOR           0x000A
+#define  DMAC_BLOCKB_SELECTOR           0x000B
+#define  DMAC_BLOCKC_SELECTOR           0x000C
+#define  DMAC_BLOCKD_SELECTOR           0x000D
+#define  DMAC_BLOCKE_SELECTOR           0x000E
+#define  DMAC_BLOCKF_SELECTOR           0x000F
+#define DMACONTROL_PAGE_MASK            0x00F0
+#define  DMAC_PAGE0_SELECTOR            0x0030
+#define  DMAC_PAGE1_SELECTOR            0x0020
+#define  DMAC_PAGE2_SELECTOR            0x0010
+#define  DMAC_PAGE3_SELECTOR            0x0000
+#define DMACONTROL_AUTOREPEAT           0x1000
+#define DMACONTROL_STOPPED              0x2000
+#define DMACONTROL_DIRECTION            0x0100
+
+
+/*
+ * DSP Code images
+ */
+
+u16 assp_kernel_image[] = {
+    0x7980, 0x0030, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x00FB, 0x7980, 0x00DD, 0x7980, 0x03B4, 
+    0x7980, 0x0332, 0x7980, 0x0287, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 
+    0x7980, 0x031A, 0x7980, 0x03B4, 0x7980, 0x022F, 0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x03B4, 
+    0x7980, 0x03B4, 0x7980, 0x03B4, 0x7980, 0x0063, 0x7980, 0x006B, 0x7980, 0x03B4, 0x7980, 0x03B4, 
+    0xBF80, 0x2C7C, 0x8806, 0x8804, 0xBE40, 0xBC20, 0xAE09, 0x1000, 0xAE0A, 0x0001, 0x6938, 0xEB08, 
+    0x0053, 0x695A, 0xEB08, 0x00D6, 0x0009, 0x8B88, 0x6980, 0xE388, 0x0036, 0xBE30, 0xBC20, 0x6909, 
+    0xB801, 0x9009, 0xBE41, 0xBE41, 0x6928, 0xEB88, 0x0078, 0xBE41, 0xBE40, 0x7980, 0x0038, 0xBE41, 
+    0xBE41, 0x903A, 0x6938, 0xE308, 0x0056, 0x903A, 0xBE41, 0xBE40, 0xEF00, 0x903A, 0x6939, 0xE308, 
+    0x005E, 0x903A, 0xEF00, 0x690B, 0x660C, 0xEF8C, 0x690A, 0x660C, 0x620B, 0x6609, 0xEF00, 0x6910, 
+    0x660F, 0xEF04, 0xE388, 0x0075, 0x690E, 0x660F, 0x6210, 0x660D, 0xEF00, 0x690E, 0x660D, 0xEF00, 
+    0xAE70, 0x0001, 0xBC20, 0xAE27, 0x0001, 0x6939, 0xEB08, 0x005D, 0x6926, 0xB801, 0x9026, 0x0026, 
+    0x8B88, 0x6980, 0xE388, 0x00CB, 0x9028, 0x0D28, 0x4211, 0xE100, 0x007A, 0x4711, 0xE100, 0x00A0, 
+    0x7A80, 0x0063, 0xB811, 0x660A, 0x6209, 0xE304, 0x007A, 0x0C0B, 0x4005, 0x100A, 0xBA01, 0x9012, 
+    0x0C12, 0x4002, 0x7980, 0x00AF, 0x7A80, 0x006B, 0xBE02, 0x620E, 0x660D, 0xBA10, 0xE344, 0x007A, 
+    0x0C10, 0x4005, 0x100E, 0xBA01, 0x9012, 0x0C12, 0x4002, 0x1003, 0xBA02, 0x9012, 0x0C12, 0x4000, 
+    0x1003, 0xE388, 0x00BA, 0x1004, 0x7980, 0x00BC, 0x1004, 0xBA01, 0x9012, 0x0C12, 0x4001, 0x0C05, 
+    0x4003, 0x0C06, 0x4004, 0x1011, 0xBFB0, 0x01FF, 0x9012, 0x0C12, 0x4006, 0xBC20, 0xEF00, 0xAE26, 
+    0x1028, 0x6970, 0xBFD0, 0x0001, 0x9070, 0xE388, 0x007A, 0xAE28, 0x0000, 0xEF00, 0xAE70, 0x0300, 
+    0x0C70, 0xB00C, 0xAE5A, 0x0000, 0xEF00, 0x7A80, 0x038A, 0x697F, 0xB801, 0x907F, 0x0056, 0x8B88, 
+    0x0CA0, 0xB008, 0xAF71, 0xB000, 0x4E71, 0xE200, 0x00F3, 0xAE56, 0x1057, 0x0056, 0x0CA0, 0xB008, 
+    0x8056, 0x7980, 0x03A1, 0x0810, 0xBFA0, 0x1059, 0xE304, 0x03A1, 0x8056, 0x7980, 0x03A1, 0x7A80, 
+    0x038A, 0xBF01, 0xBE43, 0xBE59, 0x907C, 0x6937, 0xE388, 0x010D, 0xBA01, 0xE308, 0x010C, 0xAE71, 
+    0x0004, 0x0C71, 0x5000, 0x6936, 0x9037, 0xBF0A, 0x109E, 0x8B8A, 0xAF80, 0x8014, 0x4C80, 0xBF0A, 
+    0x0560, 0xF500, 0xBF0A, 0x0520, 0xB900, 0xBB17, 0x90A0, 0x6917, 0xE388, 0x0148, 0x0D17, 0xE100, 
+    0x0127, 0xBF0C, 0x0578, 0xBF0D, 0x057C, 0x7980, 0x012B, 0xBF0C, 0x0538, 0xBF0D, 0x053C, 0x6900, 
+    0xE308, 0x0135, 0x8B8C, 0xBE59, 0xBB07, 0x90A0, 0xBC20, 0x7980, 0x0157, 0x030C, 0x8B8B, 0xB903, 
+    0x8809, 0xBEC6, 0x013E, 0x69AC, 0x90AB, 0x69AD, 0x90AB, 0x0813, 0x660A, 0xE344, 0x0144, 0x0309, 
+    0x830C, 0xBC20, 0x7980, 0x0157, 0x6955, 0xE388, 0x0157, 0x7C38, 0xBF0B, 0x0578, 0xF500, 0xBF0B, 
+    0x0538, 0xB907, 0x8809, 0xBEC6, 0x0156, 0x10AB, 0x90AA, 0x6974, 0xE388, 0x0163, 0xAE72, 0x0540, 
+    0xF500, 0xAE72, 0x0500, 0xAE61, 0x103B, 0x7A80, 0x02F6, 0x6978, 0xE388, 0x0182, 0x8B8C, 0xBF0C, 
+    0x0560, 0xE500, 0x7C40, 0x0814, 0xBA20, 0x8812, 0x733D, 0x7A80, 0x0380, 0x733E, 0x7A80, 0x0380, 
+    0x8B8C, 0xBF0C, 0x056C, 0xE500, 0x7C40, 0x0814, 0xBA2C, 0x8812, 0x733F, 0x7A80, 0x0380, 0x7340, 
+    0x7A80, 0x0380, 0x6975, 0xE388, 0x018E, 0xAE72, 0x0548, 0xF500, 0xAE72, 0x0508, 0xAE61, 0x1041, 
+    0x7A80, 0x02F6, 0x6979, 0xE388, 0x01AD, 0x8B8C, 0xBF0C, 0x0560, 0xE500, 0x7C40, 0x0814, 0xBA18, 
+    0x8812, 0x7343, 0x7A80, 0x0380, 0x7344, 0x7A80, 0x0380, 0x8B8C, 0xBF0C, 0x056C, 0xE500, 0x7C40, 
+    0x0814, 0xBA24, 0x8812, 0x7345, 0x7A80, 0x0380, 0x7346, 0x7A80, 0x0380, 0x6976, 0xE388, 0x01B9, 
+    0xAE72, 0x0558, 0xF500, 0xAE72, 0x0518, 0xAE61, 0x1047, 0x7A80, 0x02F6, 0x697A, 0xE388, 0x01D8, 
+    0x8B8C, 0xBF0C, 0x0560, 0xE500, 0x7C40, 0x0814, 0xBA08, 0x8812, 0x7349, 0x7A80, 0x0380, 0x734A, 
+    0x7A80, 0x0380, 0x8B8C, 0xBF0C, 0x056C, 0xE500, 0x7C40, 0x0814, 0xBA14, 0x8812, 0x734B, 0x7A80, 
+    0x0380, 0x734C, 0x7A80, 0x0380, 0xBC21, 0xAE1C, 0x1090, 0x8B8A, 0xBF0A, 0x0560, 0xE500, 0x7C40, 
+    0x0812, 0xB804, 0x8813, 0x8B8D, 0xBF0D, 0x056C, 0xE500, 0x7C40, 0x0815, 0xB804, 0x8811, 0x7A80, 
+    0x034A, 0x8B8A, 0xBF0A, 0x0560, 0xE500, 0x7C40, 0x731F, 0xB903, 0x8809, 0xBEC6, 0x01F9, 0x548A, 
+    0xBE03, 0x98A0, 0x7320, 0xB903, 0x8809, 0xBEC6, 0x0201, 0x548A, 0xBE03, 0x98A0, 0x1F20, 0x2F1F, 
+    0x9826, 0xBC20, 0x6935, 0xE388, 0x03A1, 0x6933, 0xB801, 0x9033, 0xBFA0, 0x02EE, 0xE308, 0x03A1, 
+    0x9033, 0xBF00, 0x6951, 0xE388, 0x021F, 0x7334, 0xBE80, 0x5760, 0xBE03, 0x9F7E, 0xBE59, 0x9034, 
+    0x697E, 0x0D51, 0x9013, 0xBC20, 0x695C, 0xE388, 0x03A1, 0x735E, 0xBE80, 0x5760, 0xBE03, 0x9F7E, 
+    0xBE59, 0x905E, 0x697E, 0x0D5C, 0x9013, 0x7980, 0x03A1, 0x7A80, 0x038A, 0xBF01, 0xBE43, 0x6977, 
+    0xE388, 0x024E, 0xAE61, 0x104D, 0x0061, 0x8B88, 0x6980, 0xE388, 0x024E, 0x9071, 0x0D71, 0x000B, 
+    0xAFA0, 0x8010, 0xAFA0, 0x8010, 0x0810, 0x660A, 0xE308, 0x0249, 0x0009, 0x0810, 0x660C, 0xE388, 
+    0x024E, 0x800B, 0xBC20, 0x697B, 0xE388, 0x03A1, 0xBF0A, 0x109E, 0x8B8A, 0xAF80, 0x8014, 0x4C80, 
+    0xE100, 0x0266, 0x697C, 0xBF90, 0x0560, 0x9072, 0x0372, 0x697C, 0xBF90, 0x0564, 0x9073, 0x0473, 
+    0x7980, 0x0270, 0x697C, 0xBF90, 0x0520, 0x9072, 0x0372, 0x697C, 0xBF90, 0x0524, 0x9073, 0x0473, 
+    0x697C, 0xB801, 0x907C, 0xBF0A, 0x10FD, 0x8B8A, 0xAF80, 0x8010, 0x734F, 0x548A, 0xBE03, 0x9880, 
+    0xBC21, 0x7326, 0x548B, 0xBE03, 0x618B, 0x988C, 0xBE03, 0x6180, 0x9880, 0x7980, 0x03A1, 0x7A80, 
+    0x038A, 0x0D28, 0x4711, 0xE100, 0x02BE, 0xAF12, 0x4006, 0x6912, 0xBFB0, 0x0C00, 0xE388, 0x02B6, 
+    0xBFA0, 0x0800, 0xE388, 0x02B2, 0x6912, 0xBFB0, 0x0C00, 0xBFA0, 0x0400, 0xE388, 0x02A3, 0x6909, 
+    0x900B, 0x7980, 0x02A5, 0xAF0B, 0x4005, 0x6901, 0x9005, 0x6902, 0x9006, 0x4311, 0xE100, 0x02ED, 
+    0x6911, 0xBFC0, 0x2000, 0x9011, 0x7980, 0x02ED, 0x6909, 0x900B, 0x7980, 0x02B8, 0xAF0B, 0x4005, 
+    0xAF05, 0x4003, 0xAF06, 0x4004, 0x7980, 0x02ED, 0xAF12, 0x4006, 0x6912, 0xBFB0, 0x0C00, 0xE388, 
+    0x02E7, 0xBFA0, 0x0800, 0xE388, 0x02E3, 0x6912, 0xBFB0, 0x0C00, 0xBFA0, 0x0400, 0xE388, 0x02D4, 
+    0x690D, 0x9010, 0x7980, 0x02D6, 0xAF10, 0x4005, 0x6901, 0x9005, 0x6902, 0x9006, 0x4311, 0xE100, 
+    0x02ED, 0x6911, 0xBFC0, 0x2000, 0x9011, 0x7980, 0x02ED, 0x690D, 0x9010, 0x7980, 0x02E9, 0xAF10, 
+    0x4005, 0xAF05, 0x4003, 0xAF06, 0x4004, 0xBC20, 0x6970, 0x9071, 0x7A80, 0x0078, 0x6971, 0x9070, 
+    0x7980, 0x03A1, 0xBC20, 0x0361, 0x8B8B, 0x6980, 0xEF88, 0x0272, 0x0372, 0x7804, 0x9071, 0x0D71, 
+    0x8B8A, 0x000B, 0xB903, 0x8809, 0xBEC6, 0x0309, 0x69A8, 0x90AB, 0x69A8, 0x90AA, 0x0810, 0x660A, 
+    0xE344, 0x030F, 0x0009, 0x0810, 0x660C, 0xE388, 0x0314, 0x800B, 0xBC20, 0x6961, 0xB801, 0x9061, 
+    0x7980, 0x02F7, 0x7A80, 0x038A, 0x5D35, 0x0001, 0x6934, 0xB801, 0x9034, 0xBF0A, 0x109E, 0x8B8A, 
+    0xAF80, 0x8014, 0x4880, 0xAE72, 0x0550, 0xF500, 0xAE72, 0x0510, 0xAE61, 0x1051, 0x7A80, 0x02F6, 
+    0x7980, 0x03A1, 0x7A80, 0x038A, 0x5D35, 0x0002, 0x695E, 0xB801, 0x905E, 0xBF0A, 0x109E, 0x8B8A, 
+    0xAF80, 0x8014, 0x4780, 0xAE72, 0x0558, 0xF500, 0xAE72, 0x0518, 0xAE61, 0x105C, 0x7A80, 0x02F6, 
+    0x7980, 0x03A1, 0x001C, 0x8B88, 0x6980, 0xEF88, 0x901D, 0x0D1D, 0x100F, 0x6610, 0xE38C, 0x0358, 
+    0x690E, 0x6610, 0x620F, 0x660D, 0xBA0F, 0xE301, 0x037A, 0x0410, 0x8B8A, 0xB903, 0x8809, 0xBEC6, 
+    0x036C, 0x6A8C, 0x61AA, 0x98AB, 0x6A8C, 0x61AB, 0x98AD, 0x6A8C, 0x61AD, 0x98A9, 0x6A8C, 0x61A9, 
+    0x98AA, 0x7C04, 0x8B8B, 0x7C04, 0x8B8D, 0x7C04, 0x8B89, 0x7C04, 0x0814, 0x660E, 0xE308, 0x0379, 
+    0x040D, 0x8410, 0xBC21, 0x691C, 0xB801, 0x901C, 0x7980, 0x034A, 0xB903, 0x8809, 0x8B8A, 0xBEC6, 
+    0x0388, 0x54AC, 0xBE03, 0x618C, 0x98AA, 0xEF00, 0xBC20, 0xBE46, 0x0809, 0x906B, 0x080A, 0x906C, 
+    0x080B, 0x906D, 0x081A, 0x9062, 0x081B, 0x9063, 0x081E, 0x9064, 0xBE59, 0x881E, 0x8065, 0x8166, 
+    0x8267, 0x8368, 0x8469, 0x856A, 0xEF00, 0xBC20, 0x696B, 0x8809, 0x696C, 0x880A, 0x696D, 0x880B, 
+    0x6962, 0x881A, 0x6963, 0x881B, 0x6964, 0x881E, 0x0065, 0x0166, 0x0267, 0x0368, 0x0469, 0x056A, 
+    0xBE3A, 
+};
+
+/*
+ * Mini sample rate converter code image
+ * that is to be loaded at 0x400 on the DSP.
+ */
+u16 assp_minisrc_image[] = {
+
+    0xBF80, 0x101E, 0x906E, 0x006E, 0x8B88, 0x6980, 0xEF88, 0x906F, 0x0D6F, 0x6900, 0xEB08, 0x0412, 
+    0xBC20, 0x696E, 0xB801, 0x906E, 0x7980, 0x0403, 0xB90E, 0x8807, 0xBE43, 0xBF01, 0xBE47, 0xBE41, 
+    0x7A80, 0x002A, 0xBE40, 0x3029, 0xEFCC, 0xBE41, 0x7A80, 0x0028, 0xBE40, 0x3028, 0xEFCC, 0x6907, 
+    0xE308, 0x042A, 0x6909, 0x902C, 0x7980, 0x042C, 0x690D, 0x902C, 0x1009, 0x881A, 0x100A, 0xBA01, 
+    0x881B, 0x100D, 0x881C, 0x100E, 0xBA01, 0x881D, 0xBF80, 0x00ED, 0x881E, 0x050C, 0x0124, 0xB904, 
+    0x9027, 0x6918, 0xE308, 0x04B3, 0x902D, 0x6913, 0xBFA0, 0x7598, 0xF704, 0xAE2D, 0x00FF, 0x8B8D, 
+    0x6919, 0xE308, 0x0463, 0x691A, 0xE308, 0x0456, 0xB907, 0x8809, 0xBEC6, 0x0453, 0x10A9, 0x90AD, 
+    0x7980, 0x047C, 0xB903, 0x8809, 0xBEC6, 0x0460, 0x1889, 0x6C22, 0x90AD, 0x10A9, 0x6E23, 0x6C22, 
+    0x90AD, 0x7980, 0x047C, 0x101A, 0xE308, 0x046F, 0xB903, 0x8809, 0xBEC6, 0x046C, 0x10A9, 0x90A0, 
+    0x90AD, 0x7980, 0x047C, 0xB901, 0x8809, 0xBEC6, 0x047B, 0x1889, 0x6C22, 0x90A0, 0x90AD, 0x10A9, 
+    0x6E23, 0x6C22, 0x90A0, 0x90AD, 0x692D, 0xE308, 0x049C, 0x0124, 0xB703, 0xB902, 0x8818, 0x8B89, 
+    0x022C, 0x108A, 0x7C04, 0x90A0, 0x692B, 0x881F, 0x7E80, 0x055B, 0x692A, 0x8809, 0x8B89, 0x99A0, 
+    0x108A, 0x90A0, 0x692B, 0x881F, 0x7E80, 0x055B, 0x692A, 0x8809, 0x8B89, 0x99AF, 0x7B99, 0x0484, 
+    0x0124, 0x060F, 0x101B, 0x2013, 0x901B, 0xBFA0, 0x7FFF, 0xE344, 0x04AC, 0x901B, 0x8B89, 0x7A80, 
+    0x051A, 0x6927, 0xBA01, 0x9027, 0x7A80, 0x0523, 0x6927, 0xE308, 0x049E, 0x7980, 0x050F, 0x0624, 
+    0x1026, 0x2013, 0x9026, 0xBFA0, 0x7FFF, 0xE304, 0x04C0, 0x8B8D, 0x7A80, 0x051A, 0x7980, 0x04B4, 
+    0x9026, 0x1013, 0x3026, 0x901B, 0x8B8D, 0x7A80, 0x051A, 0x7A80, 0x0523, 0x1027, 0xBA01, 0x9027, 
+    0xE308, 0x04B4, 0x0124, 0x060F, 0x8B89, 0x691A, 0xE308, 0x04EA, 0x6919, 0xE388, 0x04E0, 0xB903, 
+    0x8809, 0xBEC6, 0x04DD, 0x1FA0, 0x2FAE, 0x98A9, 0x7980, 0x050F, 0xB901, 0x8818, 0xB907, 0x8809, 
+    0xBEC6, 0x04E7, 0x10EE, 0x90A9, 0x7980, 0x050F, 0x6919, 0xE308, 0x04FE, 0xB903, 0x8809, 0xBE46, 
+    0xBEC6, 0x04FA, 0x17A0, 0xBE1E, 0x1FAE, 0xBFBF, 0xFF00, 0xBE13, 0xBFDF, 0x8080, 0x99A9, 0xBE47, 
+    0x7980, 0x050F, 0xB901, 0x8809, 0xBEC6, 0x050E, 0x16A0, 0x26A0, 0xBFB7, 0xFF00, 0xBE1E, 0x1EA0, 
+    0x2EAE, 0xBFBF, 0xFF00, 0xBE13, 0xBFDF, 0x8080, 0x99A9, 0x850C, 0x860F, 0x6907, 0xE388, 0x0516, 
+    0x0D07, 0x8510, 0xBE59, 0x881E, 0xBE4A, 0xEF00, 0x101E, 0x901C, 0x101F, 0x901D, 0x10A0, 0x901E, 
+    0x10A0, 0x901F, 0xEF00, 0x101E, 0x301C, 0x9020, 0x731B, 0x5420, 0xBE03, 0x9825, 0x1025, 0x201C, 
+    0x9025, 0x7325, 0x5414, 0xBE03, 0x8B8E, 0x9880, 0x692F, 0xE388, 0x0539, 0xBE59, 0xBB07, 0x6180, 
+    0x9880, 0x8BA0, 0x101F, 0x301D, 0x9021, 0x731B, 0x5421, 0xBE03, 0x982E, 0x102E, 0x201D, 0x902E, 
+    0x732E, 0x5415, 0xBE03, 0x9880, 0x692F, 0xE388, 0x054F, 0xBE59, 0xBB07, 0x6180, 0x9880, 0x8BA0, 
+    0x6918, 0xEF08, 0x7325, 0x5416, 0xBE03, 0x98A0, 0x732E, 0x5417, 0xBE03, 0x98A0, 0xEF00, 0x8BA0, 
+    0xBEC6, 0x056B, 0xBE59, 0xBB04, 0xAA90, 0xBE04, 0xBE1E, 0x99E0, 0x8BE0, 0x69A0, 0x90D0, 0x69A0, 
+    0x90D0, 0x081F, 0xB805, 0x881F, 0x8B90, 0x69A0, 0x90D0, 0x69A0, 0x9090, 0x8BD0, 0x8BD8, 0xBE1F, 
+    0xEF00, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
+};
+
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/mpu401.c linux/drivers/sound/mpu401.c
--- v2.4.1/linux/drivers/sound/mpu401.c	Mon Jan  1 10:23:21 2001
+++ linux/drivers/sound/mpu401.c	Sun Feb  4 10:05:29 2001
@@ -14,6 +14,7 @@
  * Thomas Sailer	ioctl code reworked (vmalloc/vfree removed)
  * Alan Cox		modularisation, use normal request_irq, use dev_id
  * Bartlomiej Zolnierkiewicz	removed some __init to allow using many drivers
+ * Chris Rankin		Update the module-usage counter for the coprocessor
  */
 
 #include <linux/module.h>
@@ -73,6 +74,9 @@
 #define	COMDPORT(base)   (base+1)
 #define	STATPORT(base)   (base+1)
 
+
+static void mpu401_close(int dev);
+
 static int mpu401_status(struct mpu_config *devc)
 {
 	return inb(STATPORT(devc->base));
@@ -465,6 +469,7 @@
 {
 	int err;
 	struct mpu_config *devc;
+	struct coproc_operations *coprocessor;
 
 	if (dev < 0 || dev >= num_midis || midi_devs[dev] == NULL)
 		return -ENXIO;
@@ -490,12 +495,15 @@
 		reset_mpu401(devc);
 	}
 
-	if (midi_devs[dev]->coproc)
+	if ( (coprocessor = midi_devs[dev]->coproc) != NULL )
 	{
-		if ((err = midi_devs[dev]->coproc->
-		     open(midi_devs[dev]->coproc->devc, COPR_MIDI)) < 0)
+		if (coprocessor->owner)
+			__MOD_INC_USE_COUNT(coprocessor->owner);
+
+		if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0)
 		{
-			printk("MPU-401: Can't access coprocessor device\n");
+			printk(KERN_WARNING "MPU-401: Can't access coprocessor device\n");
+			mpu401_close(dev);
 			return err;
 		}
 	}
@@ -515,6 +523,7 @@
 static void mpu401_close(int dev)
 {
 	struct mpu_config *devc;
+	struct coproc_operations *coprocessor;
 
 	devc = &dev_conf[dev];
 	if (devc->uart_mode)
@@ -524,8 +533,13 @@
 	devc->mode = 0;
 	devc->inputintr = NULL;
 
-	if (midi_devs[dev]->coproc)
-		midi_devs[dev]->coproc->close(midi_devs[dev]->coproc->devc, COPR_MIDI);
+	coprocessor = midi_devs[dev]->coproc;
+	if (coprocessor) {
+		coprocessor->close(coprocessor->devc, COPR_MIDI);
+
+		if (coprocessor->owner)
+			__MOD_DEC_USE_COUNT(coprocessor->owner);
+	}
 	devc->opened = 0;
 }
 
@@ -791,6 +805,7 @@
 {
 	int midi_dev, err;
 	struct mpu_config *devc;
+	struct coproc_operations *coprocessor;
 
 	midi_dev = synth_devs[dev]->midi_dev;
 
@@ -822,13 +837,17 @@
 
 	devc->inputintr = NULL;
 
-	if (midi_devs[midi_dev]->coproc)
-		if ((err = midi_devs[midi_dev]->coproc->
-		 open(midi_devs[midi_dev]->coproc->devc, COPR_MIDI)) < 0)
+	coprocessor = midi_devs[midi_dev]->coproc;
+	if (coprocessor) {
+		if (coprocessor->owner)
+			__MOD_INC_USE_COUNT(coprocessor->owner);
+
+		if ((err = coprocessor->open(coprocessor->devc, COPR_MIDI)) < 0)
 		{
 			printk(KERN_WARNING "mpu401: Can't access coprocessor device\n");
 			return err;
 		}
+	}
 	devc->opened = mode;
 	reset_mpu401(devc);
 
@@ -845,6 +864,7 @@
 { 
 	int midi_dev;
 	struct mpu_config *devc;
+	struct coproc_operations *coprocessor;
 
 	midi_dev = synth_devs[dev]->midi_dev;
 
@@ -854,8 +874,13 @@
 
 	devc->inputintr = NULL;
 
-	if (midi_devs[midi_dev]->coproc)
-		midi_devs[midi_dev]->coproc->close(midi_devs[midi_dev]->coproc->devc, COPR_MIDI);
+	coprocessor = midi_devs[midi_dev]->coproc;
+	if (coprocessor) {
+		coprocessor->close(coprocessor->devc, COPR_MIDI);
+
+		if (coprocessor->owner)
+			__MOD_DEC_USE_COUNT(coprocessor->owner);
+	}
 	devc->opened = 0;
 	devc->mode = 0;
 }
@@ -1030,6 +1055,8 @@
 			(char *) &mpu401_synth_proto,
 			 sizeof(struct synth_operations));
 	}
+	if (owner)
+		mpu401_synth_operations[m]->owner = owner;
 
 	memcpy((char *) &mpu401_midi_operations[m],
 	       (char *) &mpu401_midi_proto,
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/msnd.c linux/drivers/sound/msnd.c
--- v2.4.1/linux/drivers/sound/msnd.c	Sat Nov 11 18:33:14 2000
+++ linux/drivers/sound/msnd.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
 #endif
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/types.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/msnd_pinnacle.c linux/drivers/sound/msnd_pinnacle.c
--- v2.4.1/linux/drivers/sound/msnd_pinnacle.c	Sat Nov 11 18:33:14 2000
+++ linux/drivers/sound/msnd_pinnacle.c	Fri Feb  9 11:30:23 2001
@@ -37,7 +37,7 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/opl3sa2.c linux/drivers/sound/opl3sa2.c
--- v2.4.1/linux/drivers/sound/opl3sa2.c	Fri Aug 11 08:26:43 2000
+++ linux/drivers/sound/opl3sa2.c	Fri Feb 16 16:02:37 2001
@@ -2,9 +2,12 @@
  * sound/opl3sa2.c
  *
  * A low level driver for Yamaha OPL3-SA2 and SA3 cards.
- * SAx cards should work, as they are just variants of the SA3.
+ * NOTE: All traces of the name OPL3-SAx have now (December 2000) been
+ *       removed from the driver code, as an email exchange with Yamaha
+ *       provided the information that the YMF-719 is indeed just a
+ *       re-badged 715.
  *
- * Copyright 1998, 1999 Scott Murray <scottm@interlog.com>
+ * Copyright 1998-2001 Scott Murray <scott@spiteful.org>
  *
  * Originally based on the CS4232 driver (in cs4232.c) by Hannu Savolainen
  * and others.  Now incorporates code/ideas from pss.c, also by Hannu
@@ -33,12 +36,32 @@
  *                         (with thanks to Ben Hutchings for the heuristic),
  *                         removed now unnecessary force option. (Jan 5, 1999)
  * Christoph Hellwig	   Adapted to module_init/module_exit (Mar 4, 2000)
+ * Scott Murray            Reworked SA2 versus SA3 mixer code, updated chipset
+ *                         version detection code (again!). (Dec 5, 2000)
+ * Scott Murray            Adjusted master volume mixer scaling. (Dec 6, 2000)
+ * Scott Murray            Based on a patch by Joel Yliluoma (aka Bisqwit),
+ *                         integrated wide mixer and adjusted mic, bass, treble
+ *                         scaling. (Dec 6, 2000)
+ * Scott Murray            Based on a patch by Peter Englmaier, integrated
+ *                         ymode and loopback options. (Dec 6, 2000)
+ * Scott Murray            Inspired by a patch by Peter Englmaier, and based on
+ *                         what ALSA does, added initialization code for the
+ *                         default DMA and IRQ settings. (Dec 6, 2000)
+ * Scott Murray            Added some more checks to the card detection code,
+ *                         based on what ALSA does. (Dec 12, 2000)
+ * Scott Murray            Inspired by similar patches from John Fremlin,
+ *                         Jim Radford, Mike Rolig, and Ingmar Steen, added 2.4
+ *                         ISA PnP API support, mainly based on bits from
+ *                         sb_card.c and awe_wave.c. (Dec 12, 2000)
+ * Scott Murray            Some small cleanups to the init code output.
+ *                         (Jan 7, 2001)
  *
  */
 
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/isapnp.h>
 
 #include "sound_config.h"
 
@@ -46,6 +69,9 @@
 #include "mpu401.h"
 
 /* Useful control port indexes: */
+#define OPL3SA2_SYS_CTRL     0x02
+#define OPL3SA2_IRQ_CONFIG   0x03
+#define OPL3SA2_DMA_CONFIG   0x06
 #define OPL3SA2_MASTER_LEFT  0x07
 #define OPL3SA2_MASTER_RIGHT 0x08
 #define OPL3SA2_MIC          0x09
@@ -60,83 +86,157 @@
 #define DEFAULT_MIC    50
 #define DEFAULT_TIMBRE 0
 
+/* For checking against what the card returns: */
+#define VERSION_UNKNOWN 0
+#define VERSION_YMF711  1
+#define VERSION_YMF715  2
+#define VERSION_YMF715B 3
+#define VERSION_YMF715E 4
+/* also assuming that anything > 4 but <= 7 is a 715E */
+
+/* Chipset type constants for use below */
 #define CHIPSET_UNKNOWN -1
+#define CHIPSET_OPL3SA2 0
+#define CHIPSET_OPL3SA3 1
 
-/*
- * These are used both as masks against what the card returns,
- * and as constants.
- */
-#define CHIPSET_OPL3SA2  1
-#define CHIPSET_OPL3SA3  2
-#define CHIPSET_OPL3SAX  4
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+#define OPL3SA2_CARDS_MAX 4
+#else
+#define OPL3SA2_CARDS_MAX 1
+#endif
 
+/* This should be pretty obvious */
+static int opl3sa2_cards_num; /* = 0 */
 
-/* What's my version? */
-static int chipset = CHIPSET_UNKNOWN;
+/* What's my version(s)? */
+static int chipset[OPL3SA2_CARDS_MAX] = { CHIPSET_UNKNOWN };
 
-/* Oh well, let's just cache the name */
-static char chipset_name[16];
+/* Oh well, let's just cache the name(s) */
+static char chipset_name[OPL3SA2_CARDS_MAX][12];
 
-/* Where's my mixer */
-static int opl3sa2_mixer = -1;
+/* Where's my mixer(s)? */
+static int opl3sa2_mixer[OPL3SA2_CARDS_MAX] = { -1 };
 
 /* Bag o' mixer data */
-typedef struct opl3sa2_mixerdata {
+typedef struct opl3sa2_mixerdata_tag {
 	unsigned short cfg_port;
 	unsigned short padding;
-	int            ad_mixer_dev;
 	unsigned int   volume_l;
 	unsigned int   volume_r;
 	unsigned int   mic;
-	unsigned int   bass;
-	unsigned int   treble;
+	unsigned int   bass_l;
+	unsigned int   bass_r;
+	unsigned int   treble_l;
+	unsigned int   treble_r;
+	unsigned int   wide_l;
+	unsigned int   wide_r;
 } opl3sa2_mixerdata;
+static opl3sa2_mixerdata opl3sa2_data[OPL3SA2_CARDS_MAX];
+
+static struct address_info cfg[OPL3SA2_CARDS_MAX];
+static struct address_info cfg_mss[OPL3SA2_CARDS_MAX];
+static struct address_info cfg_mpu[OPL3SA2_CARDS_MAX];
+
+/* Our parameters */
+static int __initdata io	= -1;
+static int __initdata mss_io	= -1;
+static int __initdata mpu_io	= -1;
+static int __initdata irq	= -1;
+static int __initdata dma	= -1;
+static int __initdata dma2	= -1;
+static int __initdata ymode	= -1;
+static int __initdata loopback	= -1;
+
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+/* PnP specific parameters */
+static int __initdata isapnp = 1;
+static int __initdata multiple = 1;
 
-#ifdef CONFIG_OPL3SA2_CTRL_BASE
-/* Set control port if compiled into the kernel */
-static opl3sa2_mixerdata opl3sa2_data = { CONFIG_OPL3SA2_CTRL_BASE, };
+/* PnP devices */
+struct pci_dev* opl3sa2_dev[OPL3SA2_CARDS_MAX];
+
+/* Whether said devices have been activated */
+static int opl3sa2_activated[OPL3SA2_CARDS_MAX];
 #else
-static opl3sa2_mixerdata opl3sa2_data;
+static int __initdata isapnp; /* = 0 */
+static int __initdata multiple; /* = 0 */
 #endif
 
-static opl3sa2_mixerdata *devc = &opl3sa2_data;
+MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
+MODULE_AUTHOR("Scott Murray <scott@spiteful.org>");
+
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "Set I/O base of OPL3-SA2 or SA3 card (usually 0x370.  Address must be even and must be from 0x100 to 0xFFE)");
+
+MODULE_PARM(mss_io, "i");
+MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
+
+MODULE_PARM(mpu_io, "i");
+MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be even and must be from 0x300 to 0x334)");
+
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
+
+MODULE_PARM(dma, "i");
+MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
+
+MODULE_PARM(dma2, "i");
+MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
+
+MODULE_PARM(ymode, "i");
+MODULE_PARM_DESC(ymode, "Set Yamaha 3D enhancement mode (0 = Desktop/Normal, 1 = Notebook PC (1), 2 = Notebook PC (2), 3 = Hi-Fi)");
+
+MODULE_PARM(loopback, "i");
+MODULE_PARM_DESC(loopback, "Set A/D input source. Useful for echo cancellation (0 = Mic Rch (default), 1 = Mono output loopback)");
+
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+MODULE_PARM(isapnp, "i");
+MODULE_PARM_DESC(isapnp, "When set to 0, ISA PnP support will be disabled");
+
+MODULE_PARM(multiple, "i");
+MODULE_PARM_DESC(multiple, "When set to 0, will not search for multiple cards");
+#endif
 
 
-/* Standard read and write functions */
+/*
+ * Standard read and write functions
+*/
 
-static void opl3sa2_write(unsigned short port,
-			  unsigned char  index,
-			  unsigned char  data)
+static inline void opl3sa2_write(unsigned short port,
+				 unsigned char  index,
+				 unsigned char  data)
 {
 	outb_p(index, port);
 	outb(data, port + 1);
 }
 
 
-static void opl3sa2_read(unsigned short port,
-			 unsigned char  index,
-			 unsigned char* data)
+static inline void opl3sa2_read(unsigned short port,
+				unsigned char  index,
+				unsigned char* data)
 {
 	outb_p(index, port);
 	*data = inb(port + 1);
 }
 
 
-/* All of the mixer functions... */
+/*
+ * All of the mixer functions...
+ */
 
-static void opl3sa2_set_volume(opl3sa2_mixerdata *devc, int left, int right)
+static void opl3sa2_set_volume(opl3sa2_mixerdata* devc, int left, int right)
 {
 	static unsigned char scale[101] = {
-		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 
-		0x0e, 0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 
-		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 
-		0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 
-		0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 
-		0x08, 0x08, 0x08, 0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 
-		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 
-		0x05, 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
-		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 
-		0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+		0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e,
+		0x0e, 0x0e, 0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0c,
+		0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0b, 0x0b,
+		0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x09, 0x09,
+		0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x08,
+		0x08, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x06, 0x06, 0x06,
+		0x06, 0x06, 0x06, 0x06, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
+		0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01,
+		0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
 		0x00
 	};
 	unsigned char vol;
@@ -159,12 +259,12 @@
 }
 
 
-static void opl3sa2_set_mic(opl3sa2_mixerdata *devc, int level)
+static void opl3sa2_set_mic(opl3sa2_mixerdata* devc, int level)
 {
 	unsigned char vol = 0x1F;
 
 	if((level >= 0) && (level <= 100))
-		vol = 0x1F - (unsigned char) (0x1F * level / 100L);
+		vol = 0x1F - (unsigned char) (32 * level / 101);
 
 	/* If level is zero, turn on mute */
 	if(!level)
@@ -174,283 +274,286 @@
 }
 
 
-static void opl3sa3_set_bass(opl3sa2_mixerdata *devc, int level)
+static void opl3sa3_set_bass(opl3sa2_mixerdata* devc, int left, int right)
 {
 	unsigned char bass;
 
-	bass = level ? ((unsigned char) (0x07 * level / 100L)) : 0; 
-	bass |= (bass << 4);
+	bass = left ? ((unsigned char) (8 * left / 101)) : 0; 
+	bass |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
 
 	opl3sa2_write(devc->cfg_port, OPL3SA3_BASS, bass);
 }
 
 
-static void opl3sa3_set_treble(opl3sa2_mixerdata *devc, int level)
+static void opl3sa3_set_treble(opl3sa2_mixerdata* devc, int left, int right)
 {	
 	unsigned char treble;
 
-	treble = level ? ((unsigned char) (0x07 * level / 100L)) : 0; 
-	treble |= (treble << 4);
+	treble = left ? ((unsigned char) (8 * left / 101)) : 0; 
+	treble |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
 
 	opl3sa2_write(devc->cfg_port, OPL3SA3_TREBLE, treble);
 }
 
 
-static void opl3sa2_mixer_reset(opl3sa2_mixerdata *devc)
+static void opl3sa3_set_wide(opl3sa2_mixerdata* devc, int left, int right)
+{	
+	unsigned char wide;
+
+	wide = left ? ((unsigned char) (8 * left / 101)) : 0; 
+	wide |= (right ? ((unsigned char) (8 * right / 101)) : 0) << 4;
+
+	opl3sa2_write(devc->cfg_port, OPL3SA3_WIDE, wide);
+}
+
+
+static void opl3sa2_mixer_reset(opl3sa2_mixerdata* devc, int card)
 {
-	if(devc)
-	{
+	if(devc) {
 		opl3sa2_set_volume(devc, DEFAULT_VOLUME, DEFAULT_VOLUME);
 		devc->volume_l = devc->volume_r = DEFAULT_VOLUME;
 
 		opl3sa2_set_mic(devc, DEFAULT_MIC);
 		devc->mic = DEFAULT_MIC;
 
-		opl3sa3_set_bass(devc, DEFAULT_TIMBRE);
-		opl3sa3_set_treble(devc, DEFAULT_TIMBRE);
-		devc->bass = devc->treble = DEFAULT_TIMBRE;
+		if(chipset[card] == CHIPSET_OPL3SA3) {
+			opl3sa3_set_bass(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
+			devc->bass_l = devc->bass_r = DEFAULT_TIMBRE;
+			opl3sa3_set_treble(devc, DEFAULT_TIMBRE, DEFAULT_TIMBRE);
+			devc->treble_l = devc->treble_r = DEFAULT_TIMBRE;
+		}
 	}
 }
 
 
-static void arg_to_volume_mono(unsigned int volume, int *aleft)
+static inline void arg_to_vol_mono(unsigned int vol, int* value)
 {
 	int left;
 	
-	left = volume & 0x00ff;
+	left = vol & 0x00ff;
 	if (left > 100)
 		left = 100;
-	*aleft = left;
+	*value = left;
 }
 
 
-static void arg_to_volume_stereo(unsigned int volume, int *aleft, int *aright)
+static inline void arg_to_vol_stereo(unsigned int vol, int* aleft, int* aright)
 {
-	arg_to_volume_mono(volume, aleft);
-	arg_to_volume_mono(volume >> 8, aright);
+	arg_to_vol_mono(vol, aleft);
+	arg_to_vol_mono(vol >> 8, aright);
 }
 
 
-static int ret_vol_mono(int left)
+static inline int ret_vol_mono(int vol)
 {
-	return ((left << 8) | left);
+	return ((vol << 8) | vol);
 }
 
 
-static int ret_vol_stereo(int left, int right)
+static inline int ret_vol_stereo(int left, int right)
 {
 	return ((right << 8) | left);
 }
 
 
-static int call_ad_mixer(opl3sa2_mixerdata *devc, unsigned int cmd, caddr_t arg)
-{
-	if(devc->ad_mixer_dev != -1) 
-		return mixer_devs[devc->ad_mixer_dev]->ioctl(devc->ad_mixer_dev,
-							     cmd,
-							     arg);
-	else 
-		return -EINVAL;
-}
-
-
 static int opl3sa2_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
 {
 	int cmdf = cmd & 0xff;
 
 	opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
 	
-	switch(cmdf)
-	{
+	switch(cmdf) {
 		case SOUND_MIXER_VOLUME:
 		case SOUND_MIXER_MIC:
-		case SOUND_MIXER_BASS:
-		case SOUND_MIXER_TREBLE:
 		case SOUND_MIXER_DEVMASK:
 		case SOUND_MIXER_STEREODEVS: 
 		case SOUND_MIXER_RECMASK:
-		case SOUND_MIXER_CAPS: 
 		case SOUND_MIXER_RECSRC:
+		case SOUND_MIXER_CAPS: 
 			break;
 
 		default:
-			return call_ad_mixer(devc, cmd, arg);
+			return -EINVAL;
 	}
 	
 	if(((cmd >> 8) & 0xff) != 'M')
 		return -EINVAL;
 		
-	if(_SIOC_DIR (cmd) & _SIOC_WRITE)
-	{
-		switch (cmdf)	
-		{
-			case SOUND_MIXER_RECSRC:
-				if(devc->ad_mixer_dev != -1)
-					return call_ad_mixer(devc, cmd, arg);
-				else
-				{
-					if(*(int*)arg != 0)
-						return -EINVAL;
-					return 0;
-				}
-
+	if(_SIOC_DIR (cmd) & _SIOC_WRITE) {
+		switch (cmdf) {
 			case SOUND_MIXER_VOLUME:
-				arg_to_volume_stereo(*(unsigned int*)arg,
-						     &devc->volume_l,
-						     &devc->volume_r); 
-				opl3sa2_set_volume(devc, devc->volume_l,
-						   devc->volume_r);
-				*(int*)arg = ret_vol_stereo(devc->volume_l,
-							     devc->volume_r);
+				arg_to_vol_stereo(*(unsigned int*)arg,
+						  &devc->volume_l, &devc->volume_r); 
+				opl3sa2_set_volume(devc, devc->volume_l, devc->volume_r);
+				*(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r);
 				return 0;
 		  
 			case SOUND_MIXER_MIC:
-				arg_to_volume_mono(*(unsigned int*)arg,
-						   &devc->mic);
+				arg_to_vol_mono(*(unsigned int*)arg, &devc->mic);
 				opl3sa2_set_mic(devc, devc->mic);
 				*(int*)arg = ret_vol_mono(devc->mic);
 				return 0;
-		  
-			case SOUND_MIXER_BASS:
-				if(chipset != CHIPSET_OPL3SA2)
-				{
-					arg_to_volume_mono(*(unsigned int*)arg,
-							   &devc->bass);
-					opl3sa3_set_bass(devc, devc->bass);
-					*(int*)arg = ret_vol_mono(devc->bass);
-					return 0;
-				}
-				return -EINVAL;
-		  
-			case SOUND_MIXER_TREBLE:
-				if(chipset != CHIPSET_OPL3SA2)
-				{
-					arg_to_volume_mono(*(unsigned int *)arg,
-							   &devc->treble);
-					opl3sa3_set_treble(devc, devc->treble);
-					*(int*)arg = ret_vol_mono(devc->treble);
-					return 0;
-				}
-				return -EINVAL;
-		  
+
 			default:
 				return -EINVAL;
 		}
 	}
-	else			
-	{
+	else {
 		/*
 		 * Return parameters
 		 */
-		switch (cmdf)
-		{
+		switch (cmdf) {
 			case SOUND_MIXER_DEVMASK:
-				if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
-					*(int*)arg = 0; /* no mixer devices */
-
-				*(int*)arg |= (SOUND_MASK_VOLUME | SOUND_MASK_MIC);
-
-				/* OPL3-SA2 has no bass and treble mixers */
-				if(chipset != CHIPSET_OPL3SA2)
-					*(int*)arg |= (SOUND_MASK_BASS |
-						       SOUND_MASK_TREBLE);
+				*(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC);
 				return 0;
 		  
 			case SOUND_MIXER_STEREODEVS:
-				if(call_ad_mixer(devc, cmd, arg) == -EINVAL)
-					*(int*)arg = 0; /* no stereo devices */
-				*(int*)arg |= SOUND_MASK_VOLUME;
+				*(int*)arg = SOUND_MASK_VOLUME;
 				return 0;
 		  
 			case SOUND_MIXER_RECMASK:
-				if(devc->ad_mixer_dev != -1)
-				{
-					return call_ad_mixer(devc, cmd, arg);
-				}
-				else
-				{
-					/* No recording devices */
-					return (*(int*)arg = 0);
-				}
+				/* No recording devices */
+				return (*(int*)arg = 0);
 
 			case SOUND_MIXER_CAPS:
-				if(devc->ad_mixer_dev != -1)
-				{
-					return call_ad_mixer(devc, cmd, arg);
-				}
-				else
-				{
-					*(int*)arg = SOUND_CAP_EXCL_INPUT;
-					return 0;
-				}
+				*(int*)arg = SOUND_CAP_EXCL_INPUT;
+				return 0;
 
 			case SOUND_MIXER_RECSRC:
-				if(devc->ad_mixer_dev != -1)
-				{
-					return call_ad_mixer(devc, cmd, arg);
-				}
-				else
-				{
-					/* No recording source */
-					return (*(int*)arg = 0);
-				}
+				/* No recording source */
+				return (*(int*)arg = 0);
 
 			case SOUND_MIXER_VOLUME:
-				*(int*)arg = ret_vol_stereo(devc->volume_l,
-							    devc->volume_r);
+				*(int*)arg = ret_vol_stereo(devc->volume_l, devc->volume_r);
 				return 0;
 			  
 			case SOUND_MIXER_MIC:
 				*(int*)arg = ret_vol_mono(devc->mic);
 				return 0;
 
+			default:
+				return -EINVAL;
+		}
+	}
+}
+/* opl3sa2_mixer_ioctl end */
+
+
+static int opl3sa3_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
+{
+	int cmdf = cmd & 0xff;
+
+	opl3sa2_mixerdata* devc = (opl3sa2_mixerdata*) mixer_devs[dev]->devc;
+
+	switch(cmdf) {
+		case SOUND_MIXER_BASS:
+		case SOUND_MIXER_TREBLE:
+		case SOUND_MIXER_DIGITAL1:
+		case SOUND_MIXER_DEVMASK:
+		case SOUND_MIXER_STEREODEVS: 
+			break;
+
+		default:
+			return opl3sa2_mixer_ioctl(dev, cmd, arg);
+	}
+
+	if(((cmd >> 8) & 0xff) != 'M')
+		return -EINVAL;
+		
+	if(_SIOC_DIR (cmd) & _SIOC_WRITE) {
+		switch (cmdf) {
 			case SOUND_MIXER_BASS:
-				if(chipset != CHIPSET_OPL3SA2)
-				{
-					*(int*)arg = ret_vol_mono(devc->bass);
-					return 0;
-				}
-				else
-				{
-					return -EINVAL;
-				}
-			  
+				arg_to_vol_stereo(*(unsigned int*)arg,
+						  &devc->bass_l, &devc->bass_r); 
+				opl3sa3_set_bass(devc, devc->bass_l, devc->bass_r);
+				*(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r);
+				return 0;
+		  
 			case SOUND_MIXER_TREBLE:
-				if(chipset != CHIPSET_OPL3SA2)
-				{
-					*(int*)arg = ret_vol_mono(devc->treble);
-					return 0;
-				}
-				else
-				{
-					return -EINVAL;
-				}
+				arg_to_vol_stereo(*(unsigned int*)arg,
+						  &devc->treble_l, &devc->treble_r); 
+				opl3sa3_set_treble(devc, devc->treble_l, devc->treble_r);
+				*(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r);
+				return 0;
+
+			case SOUND_MIXER_DIGITAL1:
+				arg_to_vol_stereo(*(unsigned int*)arg,
+						  &devc->wide_l, &devc->wide_r); 
+				opl3sa3_set_wide(devc, devc->wide_l, devc->wide_r);
+				*(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r);
+				return 0;
+
+			default:
+				return -EINVAL;
+		}
+	}
+	else			
+	{
+		/*
+		 * Return parameters
+		 */
+		switch (cmdf) {
+			case SOUND_MIXER_DEVMASK:
+				*(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_MIC |
+					      SOUND_MASK_BASS | SOUND_MASK_TREBLE |
+					      SOUND_MASK_DIGITAL1);
+				return 0;
+		  
+			case SOUND_MIXER_STEREODEVS:
+				*(int*)arg = (SOUND_MASK_VOLUME | SOUND_MASK_BASS |
+					      SOUND_MASK_TREBLE | SOUND_MASK_DIGITAL1);
+				return 0;
+		  
+			case SOUND_MIXER_BASS:
+				*(int*)arg = ret_vol_stereo(devc->bass_l, devc->bass_r);
+				return 0;
 			  
+			case SOUND_MIXER_TREBLE:
+				*(int*)arg = ret_vol_stereo(devc->treble_l, devc->treble_r);
+				return 0;
+
+			case SOUND_MIXER_DIGITAL1:
+				*(int*)arg = ret_vol_stereo(devc->wide_l, devc->wide_r);
+				return 0;
+
 			default:
 				return -EINVAL;
 		}
 	}
 }
+/* opl3sa3_mixer_ioctl end */
 
 
 static struct mixer_operations opl3sa2_mixer_operations =
 {
 	owner:	THIS_MODULE,
-	id:	"Yamaha",
-	name:	"", /* hmm? */
+	id:	"OPL3-SA2",
+	name:	"Yamaha OPL3-SA2",
 	ioctl:	opl3sa2_mixer_ioctl
 };
 
+static struct mixer_operations opl3sa3_mixer_operations =
+{
+	owner:	THIS_MODULE,
+	id:	"OPL3-SA3",
+	name:	"Yamaha OPL3-SA3",
+	ioctl:	opl3sa3_mixer_ioctl
+};
+
 /* End of mixer-related stuff */
 
 
-static inline int __init probe_opl3sa2_mpu(struct address_info *hw_config)
+/*
+ * Component probe, attach, unload functions
+ */
+
+static inline int __init probe_opl3sa2_mpu(struct address_info* hw_config)
 {
 	return probe_mpu401(hw_config);
 }
 
 
-static inline void __init attach_opl3sa2_mpu(struct address_info *hw_config)
+static inline void __init attach_opl3sa2_mpu(struct address_info* hw_config)
 {
 	attach_mpu401(hw_config, THIS_MODULE);
 }
@@ -462,255 +565,474 @@
 }
 
 
-static inline int __init probe_opl3sa2_mss(struct address_info *hw_config)
+static inline int __init probe_opl3sa2_mss(struct address_info* hw_config)
 {
 	return probe_ms_sound(hw_config);
 }
 
 
-static void __init attach_opl3sa2_mss(struct address_info *hw_config)
+static void __init attach_opl3sa2_mss(struct address_info* hw_config)
 {
-	char mixer_name[64];
-
-	/* Create pretty names for mixer stuff */
-	strncpy(mixer_name, chipset_name, 16);
-	strncat(mixer_name, " and AD1848 (through MSS)", 64);
-
-	strncpy(opl3sa2_mixer_operations.name, chipset_name, 16);
-	strncat(opl3sa2_mixer_operations.name, "-AD1848", 64);
-
-	/* Install master mixer */
-	devc->ad_mixer_dev = -1;
-	if((opl3sa2_mixer = sound_install_mixer(MIXER_DRIVER_VERSION,
-						mixer_name,
-						&opl3sa2_mixer_operations,
-						sizeof(struct mixer_operations),
-						devc)) < 0) 
-	{
-		printk(KERN_ERR "Could not install %s master mixer\n", chipset_name);
-		return;
-	}
-
-	opl3sa2_mixer_reset(devc);
+	int initial_mixers;
 
+	initial_mixers = num_mixers;
 	attach_ms_sound(hw_config, THIS_MODULE);	/* Slot 0 */
-	if(hw_config->slots[0] != -1)
-	{
+	if(hw_config->slots[0] != -1) {
 		/* Did the MSS driver install? */
-		if(num_mixers == (opl3sa2_mixer + 2))
-		{
-			/* The MSS mixer is installed */
-			devc->ad_mixer_dev = audio_devs[hw_config->slots[0]]->mixer_dev;
-
-			/* Reroute mixers appropiately */
+		if(num_mixers == (initial_mixers + 1)) {
+			/* The MSS mixer is installed, reroute mixers appropiately */
 			AD1848_REROUTE(SOUND_MIXER_LINE1, SOUND_MIXER_CD);
 			AD1848_REROUTE(SOUND_MIXER_LINE2, SOUND_MIXER_SYNTH);
 			AD1848_REROUTE(SOUND_MIXER_LINE3, SOUND_MIXER_LINE);
 		}
+		else {
+			printk(KERN_ERR "opl3sa2: MSS mixer not installed?\n");
+		}
 	}
 }
 
 
-static inline void __exit unload_opl3sa2_mss(struct address_info *hw_config)
+static inline void __exit unload_opl3sa2_mss(struct address_info* hw_config)
 {
 	unload_ms_sound(hw_config);
 }
 
 
-static int __init probe_opl3sa2(struct address_info *hw_config)
+static int __init probe_opl3sa2(struct address_info* hw_config, int card)
 {
-	unsigned char version = 0;
+	unsigned char misc;
+	unsigned char tmp;
+	unsigned char version;
 	char tag;
 
 	/*
 	 * Verify that the I/O port range is free.
 	 */
-	if(check_region(hw_config->io_base, 2))
-	{
-	    printk(KERN_ERR
-		   "%s: Control I/O port 0x%03x not free\n",
-		   __FILE__,
-		   hw_config->io_base);
-	    return 0;
+	if(check_region(hw_config->io_base, 2)) {
+		printk(KERN_ERR "opl3sa2: Control I/O port %#x not free\n",
+		       hw_config->io_base);
+		return 0;
 	}
 
 	/*
-	 * Determine chipset type (SA2, SA3, or SAx)
+	 * Check if writing to the read-only version bits of the miscellaneous
+	 * register succeeds or not (it should not).
 	 */
+	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
+	opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc ^ 0x07);
+	opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &tmp);
+	if(tmp != misc) {
+		printk(KERN_ERR "opl3sa2: Control I/O port %#x is not a YMF7xx chipset!\n",
+		       hw_config->io_base);
+		return 0;
+	}
 
 	/*
-	 * Look at chipset version in lower 3 bits of index 0x0A, miscellaneous
+	 * Check if the MIC register is accessible.
 	 */
-	opl3sa2_read(hw_config->io_base,
-		     OPL3SA2_MISC,
-		     (unsigned char*) &version);
-	version &= 0x07;
-
-	/* Match version number to appropiate chipset */
-	if(version & CHIPSET_OPL3SAX)
-	{
-		chipset = CHIPSET_OPL3SAX;
-		tag = 'x';
-		printk(KERN_INFO "Found OPL3-SAx (YMF719)\n");
+	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
+	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, 0x8a);
+	opl3sa2_read(hw_config->io_base, OPL3SA2_MIC, &tmp);
+	if((tmp & 0x9f) != 0x8a) {
+		printk(KERN_ERR
+		       "opl3sa2: Control I/O port %#x is not a YMF7xx chipset!\n",
+		       hw_config->io_base);
+		return 0;
 	}
-	else
-	{
- 		if(version & CHIPSET_OPL3SA3)
-		{
-			chipset = CHIPSET_OPL3SA3;
+	opl3sa2_write(hw_config->io_base, OPL3SA2_MIC, tmp);
+
+	/*
+	 * Determine chipset type (SA2 or SA3)
+	 *
+	 * This is done by looking at the chipset version in the lower 3 bits
+	 * of the miscellaneous register.
+	 */
+	version = misc & 0x07;
+	printk(KERN_DEBUG "opl3sa2: chipset version = %#x\n", version);
+	switch(version) {
+		case 0:
+			chipset[card] = CHIPSET_UNKNOWN;
+			tag = '?'; /* silence compiler warning */
+			printk(KERN_ERR
+			       "opl3sa2: Unknown Yamaha audio controller version\n");
+			break;
+
+		case VERSION_YMF711:
+			chipset[card] = CHIPSET_OPL3SA2;
+			tag = '2';
+			printk(KERN_INFO "opl3sa2: Found OPL3-SA2 (YMF711)\n");
+			break;
+
+		case VERSION_YMF715:
+			chipset[card] = CHIPSET_OPL3SA3;
 			tag = '3';
-			printk(KERN_INFO "Found OPL3-SA3 (YMF715)\n");
-		}
-		else
-		{
-			if(version & CHIPSET_OPL3SA2)
-			{
-				chipset = CHIPSET_OPL3SA2;
-				tag = '2';
-				printk(KERN_INFO "Found OPL3-SA2 (YMF711)\n");
-			}
-			else
-			{
-				chipset = CHIPSET_UNKNOWN;
-				tag = '?';
-				printk(KERN_ERR
-				       "Unknown Yamaha audio controller version\n");
-				printk(KERN_INFO
-				       "%s: chipset version = %x\n",
-				       __FILE__,
-				       version);
-			}
-		}
+			printk(KERN_INFO
+			       "opl3sa2: Found OPL3-SA3 (YMF715 or YMF719)\n");
+			break;
+
+		case VERSION_YMF715B:
+			chipset[card] = CHIPSET_OPL3SA3;
+			tag = '3';
+			printk(KERN_INFO
+			       "opl3sa2: Found OPL3-SA3 (YMF715B or YMF719B)\n");
+			break;
+
+		case VERSION_YMF715E:
+		default:
+			chipset[card] = CHIPSET_OPL3SA3;
+			tag = '3';
+			printk(KERN_INFO
+			       "opl3sa2: Found OPL3-SA3 (YMF715E or YMF719E)\n");
+			break;
 	}
 
-	if(chipset != CHIPSET_UNKNOWN)
-	{
+	if(chipset[card] != CHIPSET_UNKNOWN) {
 		/* Generate a pretty name */
-		sprintf(chipset_name, "OPL3-SA%c", tag);
+		sprintf(chipset_name[card], "OPL3-SA%c", tag);
 		return 1;
 	}
 	return 0;
 }
 
 
-static void __init attach_opl3sa2(struct address_info *hw_config)
+static void __init attach_opl3sa2(struct address_info* hw_config, int card)
+{
+   	request_region(hw_config->io_base, 2, chipset_name[card]);
+
+	/* Initialize IRQ configuration to IRQ-B: -, IRQ-A: WSS+MPU+OPL3 */
+	opl3sa2_write(hw_config->io_base, OPL3SA2_IRQ_CONFIG, 0x0d);
+
+	/* Initialize DMA configuration */
+	if(hw_config->dma2 == hw_config->dma) {
+		/* Want DMA configuration DMA-B: -, DMA-A: WSS-P+WSS-R */
+		opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x03);
+	}
+	else {
+		/* Want DMA configuration DMA-B: WSS-R, DMA-A: WSS-P */
+		opl3sa2_write(hw_config->io_base, OPL3SA2_DMA_CONFIG, 0x21);
+	}
+}
+
+
+static void __init attach_opl3sa2_mixer(struct address_info *hw_config, int card)
+{
+	struct mixer_operations* mixer_operations;
+	opl3sa2_mixerdata* devc;
+
+	/* Install master mixer */
+	if(chipset[card] == CHIPSET_OPL3SA3) {
+		mixer_operations = &opl3sa3_mixer_operations;
+	}
+	else {
+		mixer_operations = &opl3sa2_mixer_operations;
+	}
+
+	if((devc = &opl3sa2_data[card])) {
+		devc->cfg_port = hw_config->io_base;
+
+		opl3sa2_mixer[card] = sound_install_mixer(MIXER_DRIVER_VERSION,
+							  mixer_operations->name,
+							  mixer_operations,
+							  sizeof(struct mixer_operations),
+							  devc);
+		if(opl3sa2_mixer[card] < 0) {
+			printk(KERN_ERR "opl3sa2: Could not install %s master mixer\n",
+				 mixer_operations->name);
+		}
+		else
+			opl3sa2_mixer_reset(devc, card);
+	}
+}
+
+
+static void __init opl3sa2_clear_slots(struct address_info* hw_config)
+{
+	int i;
+
+	for(i = 0; i < 6; i++) {
+		hw_config->slots[i] = -1;
+	}
+}
+
+
+static void __init opl3sa2_set_ymode(struct address_info* hw_config, int ymode)
 {
-   	request_region(hw_config->io_base, 2, chipset_name);
+	/*
+	 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
+	 * it's supported.
+	 *
+	 * 0: Desktop (aka normal)   5-12 cm speakers
+	 * 1: Notebook PC mode 1     3 cm speakers
+	 * 2: Notebook PC mode 2     1.5 cm speakers
+	 * 3: Hi-fi                  16-38 cm speakers
+	 */
+	if(ymode >= 0 && ymode <= 3) {
+		unsigned char sys_ctrl;
+
+		opl3sa2_read(hw_config->io_base, OPL3SA2_SYS_CTRL, &sys_ctrl);
+		sys_ctrl = (sys_ctrl & 0xcf) | ((ymode & 3) << 4);
+		opl3sa2_write(hw_config->io_base, OPL3SA2_SYS_CTRL, sys_ctrl);
+	}
+	else {
+		printk(KERN_ERR "opl3sa2: not setting ymode, it must be one of 0,1,2,3\n");
+	}
+}
+
+
+static void __init opl3sa2_set_loopback(struct address_info* hw_config, int loopback)
+{
+	if(loopback >= 0 && loopback <= 1) {
+		unsigned char misc;
 
-	devc->cfg_port = hw_config->io_base;
+		opl3sa2_read(hw_config->io_base, OPL3SA2_MISC, &misc);
+		misc = (misc & 0xef) | ((loopback & 1) << 4);
+		opl3sa2_write(hw_config->io_base, OPL3SA2_MISC, misc);
+	}
+	else {
+		printk(KERN_ERR "opl3sa2: not setting loopback, it must be either 0 or 1\n");
+	}
 }
 
 
-static void __exit unload_opl3sa2(struct address_info *hw_config)
+static void __exit unload_opl3sa2(struct address_info* hw_config, int card)
 {
         /* Release control ports */
 	release_region(hw_config->io_base, 2);
 
 	/* Unload mixer */
-	if(opl3sa2_mixer >= 0)
-		sound_unload_mixerdev(opl3sa2_mixer);
+	if(opl3sa2_mixer[card] >= 0)
+		sound_unload_mixerdev(opl3sa2_mixer[card]);
 }
 
-static struct address_info cfg;
-static struct address_info cfg2;
-static struct address_info cfg_mpu;
 
-static int __initdata io	= -1;
-static int __initdata mss_io	= -1;
-static int __initdata mpu_io	= -1;
-static int __initdata irq	= -1;
-static int __initdata dma	= -1;
-static int __initdata dma2	= -1;
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+static int __init opl3sa2_isapnp_probe(struct address_info* hw_cfg,
+				       struct address_info* mss_cfg,
+				       struct address_info* mpu_cfg,
+				       int card)
+{
+	static struct pci_dev* dev;
+	int ret;
+
+	/* Find and configure device */
+	dev = isapnp_find_dev(NULL,
+			      ISAPNP_VENDOR('Y','M','H'),
+			      ISAPNP_FUNCTION(0x0021),
+			      dev);
+	if(dev == NULL) {
+		return -ENODEV;
+	}
 
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "Set i/o base of OPL3-SA2 or SA3 card (usually 0x370)");
+	/*
+	 * If device is active, assume configured with /proc/isapnp
+	 * and use anyway. Any other way to check this?
+	 */
+	ret = dev->prepare(dev);
+	if(ret && ret != -EBUSY) {
+		printk(KERN_ERR "opl3sa2: ISA PnP found device that could not be autoconfigured.\n");
+		return -ENODEV;
+	}
+	if(ret == -EBUSY) {
+		opl3sa2_activated[card] = 1;
+	}
+	else {
+		if(dev->activate(dev) < 0) {
+			printk(KERN_WARNING "opl3sa2: ISA PnP activate failed\n");
+			opl3sa2_activated[card] = 0;
+			return -ENODEV;
+		}
 
-MODULE_PARM(mss_io, "i");
-MODULE_PARM_DESC(mss_io, "Set MSS (audio) I/O base (0x530, 0xE80, or other. Address must end in 0 or 4 and must be from 0x530 to 0xF48)");
+		printk(KERN_DEBUG
+		       "opl3sa2: Activated ISA PnP card %d (active=%d)\n",
+		       card, dev->active);
 
-MODULE_PARM(mpu_io, "i");
-MODULE_PARM_DESC(mpu_io, "Set MIDI I/O base (0x330 or other. Address must be on 4 location boundaries and must be from 0x300 to 0x334)");
+	}
 
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(mss_irq, "Set MSS (audio) IRQ (5, 7, 9, 10, 11, 12)");
+	/* Our own config: */
+	hw_cfg->io_base = dev->resource[4].start;
+	hw_cfg->irq     = 0;
+	hw_cfg->dma     = -1;
+	hw_cfg->dma2    = -1;
+	
+	/* The MSS config: */
+	mss_cfg->io_base      = dev->resource[1].start;
+	mss_cfg->irq          = dev->irq_resource[0].start;
+	mss_cfg->dma          = dev->dma_resource[0].start;
+	mss_cfg->dma2         = dev->dma_resource[1].start;
+	mss_cfg->card_subtype = 1; /* No IRQ or DMA setup */
+
+	mpu_cfg->io_base       = dev->resource[3].start;
+	mpu_cfg->irq           = dev->irq_resource[0].start;
+	mpu_cfg->dma           = -1;
+	mpu_cfg->dma2          = -1;
+	mpu_cfg->always_detect = 1; /* It's there, so use shared IRQs */
 
-MODULE_PARM(dma, "i");
-MODULE_PARM_DESC(dma, "Set MSS (audio) first DMA channel (0, 1, 3)");
+	/* Call me paranoid: */
+	opl3sa2_clear_slots(hw_cfg);
+	opl3sa2_clear_slots(mss_cfg);
+	opl3sa2_clear_slots(mpu_cfg);
 
-MODULE_PARM(dma2, "i");
-MODULE_PARM_DESC(dma2, "Set MSS (audio) second DMA channel (0, 1, 3)");
+	opl3sa2_dev[card] = dev;
+
+	return 0;
+}
+#endif /* CONFIG_ISAPNP || CONFIG_ISAPNP_MODULE */
+
+/* End of component functions */
 
-MODULE_DESCRIPTION("Module for OPL3-SA2 and SA3 sound cards (uses AD1848 MSS driver).");
-MODULE_AUTHOR("Scott Murray <scottm@interlog.com>");
 
 /*
- * Install a OPL3SA2 based card.
+ * Install OPL3-SA2 based card(s).
  *
  * Need to have ad1848 and mpu401 loaded ready.
  */
 static int __init init_opl3sa2(void)
 {
-        int i;
+        int card;
+	int max;
 
-        /* Our own config: */
-        cfg.io_base = io;
-	cfg.irq     = irq;
-	cfg.dma     = dma;
-	cfg.dma2    = dma2;
+	/* Sanitize isapnp and multiple settings */
+	isapnp = isapnp != 0 ? 1 : 0;
+	multiple = multiple != 0 ? 1 : 0;
 	
-        /* The MSS config: */
-	cfg2.io_base      = mss_io;
-	cfg2.irq          = irq;
-	cfg2.dma          = dma;
-	cfg2.dma2         = dma2;
-	cfg2.card_subtype = 1;      /* No IRQ or DMA setup */
-
-	cfg_mpu.io_base       = mpu_io;
-	cfg_mpu.irq           = irq;
-	cfg_mpu.dma           = dma;
-	cfg_mpu.always_detect = 1;  /* It's there, so use shared IRQs */
+	max = (multiple && isapnp) ? OPL3SA2_CARDS_MAX : 1;
+	for(card = 0; card < max; card++, opl3sa2_cards_num++) {
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+		/*
+		 * Please remember that even with CONFIG_ISAPNP defined one
+		 * should still be able to disable PNP support for this 
+		 * single driver!
+		 */
+		if(isapnp && opl3sa2_isapnp_probe(&cfg[card],
+						  &cfg_mss[card],
+						  &cfg_mpu[card],
+						  card) < 0) {
+			if(!opl3sa2_cards_num)
+				printk(KERN_NOTICE "opl3sa2: No cards found\n");
+			break;
+		}
+#endif
+		/* If a user wants an I/O then assume they meant it */
+		
+		if(!isapnp && io == -1 ) {
+			if(io == -1 || irq == -1 || dma == -1 ||
+			   dma2 == -1 || mss_io == -1) {
+				printk(KERN_ERR
+				       "opl3sa2: io, mss_io, irq, dma, and dma2 must be set\n");
+				return -EINVAL;
+			}
 
-	if(cfg.io_base == -1 || cfg.irq == -1 || cfg.dma == -1 || cfg.dma2 == -1 || cfg2.io_base == -1) {
-		printk(KERN_ERR "opl3sa2: io, mss_io, irq, dma, and dma2 must be set.\n");
-		return -EINVAL;
-	}
+			/*
+			 * Our own config:
+			 * (NOTE: IRQ and DMA aren't used, so they're set to
+			 *  give pretty output from conf_printf. :)
+			 */
+			cfg[card].io_base = io;
+			cfg[card].irq     = 0;
+			cfg[card].dma     = -1;
+			cfg[card].dma2    = -1;
+	
+			/* The MSS config: */
+			cfg_mss[card].io_base      = mss_io;
+			cfg_mss[card].irq          = irq;
+			cfg_mss[card].dma          = dma;
+			cfg_mss[card].dma2         = dma2;
+			cfg_mss[card].card_subtype = 1; /* No IRQ or DMA setup */
+
+			cfg_mpu[card].io_base       = mpu_io;
+			cfg_mpu[card].irq           = irq;
+			cfg_mpu[card].dma           = -1;
+			cfg_mpu[card].always_detect = 1; /* Use shared IRQs */
+
+			/* Call me paranoid: */
+			opl3sa2_clear_slots(&cfg[card]);
+			opl3sa2_clear_slots(&cfg_mss[card]);
+			opl3sa2_clear_slots(&cfg_mpu[card]);
+		}
 
-	/* Call me paranoid: */
-	for(i = 0; i < 6; i++)
-	{
-		cfg.slots[i] = cfg2.slots[i] = cfg_mpu.slots[i] = -1;
-	}
+		if(!probe_opl3sa2(&cfg[card], card) ||
+		   !probe_opl3sa2_mss(&cfg_mss[card])) {
+			/*
+			 * If one or more cards are already registered, don't
+			 * return an error but print a warning.  Note, this
+			 * should never really happen unless the hardware or
+			 * ISA PnP screwed up.
+			 */
+			if(opl3sa2_cards_num) {
+				printk(KERN_WARNING
+				       "opl3sa2: There was a problem probing one "
+				       " of the ISA PNP cards, continuing\n");
+				opl3sa2_cards_num--;
+				continue;
+			} else
+				return -ENODEV;
+		}
 
-	if(probe_opl3sa2(&cfg) == 0)
-	{
-		return -ENODEV;
-	}
+		attach_opl3sa2(&cfg[card], card);
+		conf_printf(chipset_name[card], &cfg[card]);
+		attach_opl3sa2_mss(&cfg_mss[card]);
+		attach_opl3sa2_mixer(&cfg[card], card);
 
-	if(probe_opl3sa2_mss(&cfg2) == 0)
-	{
-		return -ENODEV;
-	}
+		/*
+		 * Set the Yamaha 3D enhancement mode (aka Ymersion) if asked to and
+		 * it's supported.
+		 */
+		if(ymode != -1) {
+			if(chipset[card] == CHIPSET_OPL3SA2) {
+				printk(KERN_ERR
+				       "opl3sa2: ymode not supported on OPL3-SA2\n");
+			}
+			else {
+				opl3sa2_set_ymode(&cfg[card], ymode);
+			}
+		}
 
-	attach_opl3sa2(&cfg);
-	attach_opl3sa2_mss(&cfg2);
 
-	if(cfg_mpu.io_base != -1) {
-		if(probe_opl3sa2_mpu(&cfg_mpu)) {
-			attach_opl3sa2_mpu(&cfg_mpu);
+		/* Set A/D input to Mono loopback if asked to. */
+		if(loopback != -1) {
+			opl3sa2_set_loopback(&cfg[card], loopback);
 		}
+		
+		/* Attach MPU if we've been asked to do so */
+		if(cfg_mpu[card].io_base != -1) {
+			if(probe_opl3sa2_mpu(&cfg_mpu[card])) {
+				attach_opl3sa2_mpu(&cfg_mpu[card]);
+			}
+		}
+	}
+
+	if(isapnp) {
+		printk(KERN_NOTICE "opl3sa2: %d PnP card(s) found.\n", opl3sa2_cards_num);
 	}
 
 	return 0;
 }
 
 
+/*
+ * Uninstall OPL3-SA2 based card(s).
+ */
 static void __exit cleanup_opl3sa2(void)
 {
-        if(cfg_mpu.slots[1] != -1) {
-		unload_opl3sa2_mpu(&cfg_mpu);
+	int card;
+
+	for(card = 0; card < opl3sa2_cards_num; card++) {
+	        if(cfg_mpu[card].slots[1] != -1) {
+			unload_opl3sa2_mpu(&cfg_mpu[card]);
+		}
+		unload_opl3sa2_mss(&cfg_mss[card]);
+		unload_opl3sa2(&cfg[card], card);
+
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+		if(opl3sa2_activated[card] && opl3sa2_dev[card]) {
+			opl3sa2_dev[card]->deactivate(opl3sa2_dev[card]);
+
+			printk(KERN_DEBUG
+			       "opl3sa2: Deactivated ISA PnP card %d (active=%d)\n",
+			       card, opl3sa2_dev[card]->active);
+		}
+#endif
 	}
-	unload_opl3sa2_mss(&cfg2);
-	unload_opl3sa2(&cfg);
 }
 
 module_init(init_opl3sa2);
@@ -719,18 +1041,26 @@
 #ifndef MODULE
 static int __init setup_opl3sa2(char *str)
 {
-	/* io, irq, dma, dma2 */
-	int ints[7];
-	
+	/* io, irq, dma, dma2,... */
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+	int ints[11];
+#else
+	int ints[9];
+#endif
 	str = get_options(str, ARRAY_SIZE(ints), ints);
 	
-	io	= ints[1];
-	irq	= ints[2];
-	dma	= ints[3];
-	dma2	= ints[4];
-	mss_io	= ints[5];
-	mpu_io	= ints[6];
-
+	io       = ints[1];
+	irq      = ints[2];
+	dma      = ints[3];
+	dma2     = ints[4];
+	mss_io   = ints[5];
+	mpu_io   = ints[6];
+	ymode    = ints[7];
+	loopback = ints[8];
+#if defined CONFIG_ISAPNP || defined CONFIG_ISAPNP_MODULE
+	isapnp   = ints[9];
+	multiple = ints[10];
+#endif
 	return 1;
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/os.h linux/drivers/sound/os.h
--- v2.4.1/linux/drivers/sound/os.h	Thu Jan  4 14:52:14 2001
+++ linux/drivers/sound/os.h	Wed Feb 21 16:11:22 2001
@@ -20,7 +20,7 @@
 #include <asm/param.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <asm/page.h>
 #include <asm/system.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/pss.c linux/drivers/sound/pss.c
--- v2.4.1/linux/drivers/sound/pss.c	Sat Nov 11 18:33:14 2000
+++ linux/drivers/sound/pss.c	Sun Feb  4 10:05:29 2001
@@ -52,6 +52,8 @@
  *	    Adapted to module_init/module_exit
  * 11-10-2000: Bartlomiej Zolnierkiewicz <bkz@linux-ide.org>
  *	    Added __init to probe_pss(), attach_pss() and probe_pss_mpu()
+ * 02-Jan-2001: Chris Rankin
+ *          Specify that this module owns the coprocessor
  */
 
 
@@ -979,6 +981,7 @@
 static coproc_operations pss_coproc_operations =
 {
 	"ADSP-2115",
+	THIS_MODULE,
 	pss_coproc_open,
 	pss_coproc_close,
 	pss_coproc_ioctl,
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sb.h linux/drivers/sound/sb.h
--- v2.4.1/linux/drivers/sound/sb.h	Wed Sep 27 13:53:56 2000
+++ linux/drivers/sound/sb.h	Fri Feb 16 16:02:37 2001
@@ -137,6 +137,8 @@
 	   void (*midi_input_intr) (int dev, unsigned char data);
 	   void *midi_irq_cookie;		/* IRQ cookie for the midi */
 
+	   spinlock_t lock;
+
 	   struct sb_module_options sbmo;	/* Module options */
 
 	} sb_devc;
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sb_audio.c linux/drivers/sound/sb_audio.c
--- v2.4.1/linux/drivers/sound/sb_audio.c	Fri Aug 11 08:26:43 2000
+++ linux/drivers/sound/sb_audio.c	Fri Feb 16 16:02:37 2001
@@ -19,8 +19,11 @@
  * Daniel J. Rodriksson: Changes to make sb16 work full duplex.
  *                       Maybe other 16 bit cards in this code could behave
  *                       the same.
+ * Chris Rankin:         Use spinlocks instead of CLI/STI
  */
 
+#include <linux/spinlock.h>
+
 #include "sound_config.h"
 
 #include "sb_mixer.h"
@@ -43,23 +46,22 @@
 		if (mode == OPEN_READ)
 			return -EPERM;
 	}
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (devc->opened)
 	{
-		  restore_flags(flags);
+		  spin_unlock_irqrestore(&devc->lock, flags);
 		  return -EBUSY;
 	}
 	if (devc->dma16 != -1 && devc->dma16 != devc->dma8 && !devc->duplex)
 	{
 		if (sound_open_dma(devc->dma16, "Sound Blaster 16 bit"))
 		{
-			restore_flags(flags);
+		  	spin_unlock_irqrestore(&devc->lock, flags);
 			return -EBUSY;
 		}
 	}
 	devc->opened = mode;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	devc->irq_mode = IMODE_NONE;
 	devc->irq_mode_16 = IMODE_NONE;
@@ -182,8 +184,7 @@
 
 	devc->irq_mode = IMODE_OUTPUT;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x14))		/* 8 bit DAC using DMA */
 	{
 		sb_dsp_command(devc, (unsigned char) (count & 0xff));
@@ -191,7 +192,7 @@
 	}
 	else
 		printk(KERN_WARNING "Sound Blaster:  unable to start DAC.\n");
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 	devc->intr_active = 1;
 }
 
@@ -213,8 +214,7 @@
 
 	devc->irq_mode = IMODE_INPUT;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x24))		/* 8 bit ADC using DMA */
 	{
 		sb_dsp_command(devc, (unsigned char) (count & 0xff));
@@ -222,7 +222,7 @@
 	}
 	else
 		printk(KERN_ERR "Sound Blaster:  unable to start ADC.\n");
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	devc->intr_active = 1;
 }
@@ -258,12 +258,11 @@
 	sb_devc *devc = audio_devs[dev]->devc;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x40))
 		sb_dsp_command(devc, devc->tconst);
 	sb_dsp_command(devc, DSP_CMD_SPKOFF);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	devc->trigger_bits = 0;
 	return 0;
@@ -274,12 +273,11 @@
 	sb_devc *devc = audio_devs[dev]->devc;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x40))
 		sb_dsp_command(devc, devc->tconst);
 	sb_dsp_command(devc, DSP_CMD_SPKON);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 	devc->trigger_bits = 0;
 	return 0;
 }
@@ -327,10 +325,9 @@
 	unsigned long flags;
 	sb_devc *devc = audio_devs[dev]->devc;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	sb_dsp_reset(devc);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 /*
@@ -353,8 +350,7 @@
 
 	devc->irq_mode = IMODE_OUTPUT;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x48))		/* DSP Block size */
 	{
 		sb_dsp_command(devc, (unsigned char) (count & 0xff));
@@ -370,7 +366,7 @@
 	}
 	else
 		printk(KERN_ERR "Sound Blaster: unable to start DAC.\n");
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 	devc->intr_active = 1;
 }
 
@@ -393,8 +389,7 @@
 
 	devc->irq_mode = IMODE_INPUT;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x48))		/* DSP Block size */
 	{
 		sb_dsp_command(devc, (unsigned char) (count & 0xff));
@@ -410,7 +405,7 @@
 	}
 	else
 		printk(KERN_ERR "Sound Blaster:  unable to start ADC.\n");
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 	devc->intr_active = 1;
 }
 
@@ -484,8 +479,7 @@
 		if (devc->bits == AFMT_S16_LE)
 			bits = 0x04;	/* 16 bit mode */
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x40))
 		sb_dsp_command(devc, devc->tconst);
 	sb_dsp_command(devc, DSP_CMD_SPKOFF);
@@ -493,7 +487,7 @@
 		sb_dsp_command(devc, 0xa0 | bits);	/* Mono input */
 	else
 		sb_dsp_command(devc, 0xa8 | bits);	/* Stereo input */
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	devc->trigger_bits = 0;
 	return 0;
@@ -511,8 +505,7 @@
 	if (devc->model == MDL_SBPRO)
 		sb_mixer_set_stereo(devc, devc->channels == 2);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (sb_dsp_command(devc, 0x40))
 		sb_dsp_command(devc, devc->tconst);
 	sb_dsp_command(devc, DSP_CMD_SPKON);
@@ -536,7 +529,7 @@
 			tmp |= 0x02;
 		sb_setmixer(devc, 0x0e, tmp);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 	devc->trigger_bits = 0;
 	return 0;
 }
@@ -706,21 +699,19 @@
 	}
 
 	/* save value */
-	save_flags (flags);
-	cli ();
+	spin_lock_irqsave(&devc->lock, flags);
 	bits = devc->bits;
 	if (devc->fullduplex)
 		devc->bits = (devc->bits == AFMT_S16_LE) ?
 			AFMT_U8 : AFMT_S16_LE;
-	restore_flags (flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	cnt = count;
 	if (devc->bits == AFMT_S16_LE)
 		cnt >>= 1;
 	cnt--;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 
 	/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_WRITE); */
 
@@ -736,7 +727,7 @@
 
 	/* restore real value after all programming */
 	devc->bits = bits;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 
@@ -768,8 +759,7 @@
 		cnt >>= 1;
 	cnt--;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 
 	/* DMAbuf_start_dma (dev, buf, count, DMA_MODE_READ); */
 
@@ -783,7 +773,7 @@
 	sb_dsp_command(devc, (unsigned char) (cnt & 0xff));
 	sb_dsp_command(devc, (unsigned char) (cnt >> 8));
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 static void sb16_audio_trigger(int dev, int bits)
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sb_card.c linux/drivers/sound/sb_card.c
--- v2.4.1/linux/drivers/sound/sb_card.c	Sun Dec 31 09:27:57 2000
+++ linux/drivers/sound/sb_card.c	Sun Feb  4 10:05:29 2001
@@ -484,6 +484,188 @@
 	{0}
 };
 
+static struct isapnp_device_id id_table[] __devinitdata = {
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0024),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0025),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0026), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0027), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0028), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0029), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002a),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x002b), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0051), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0070), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0080), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00F0), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0043), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0039), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0042), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0043), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0044),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0048), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x0054), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0031), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009C), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009F),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0041), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009D), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x009E), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00B2),
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0044), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C1), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0042), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C3), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C5), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00C7), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
+
+	{	ISAPNP_VENDOR('C','T','L'), ISAPNP_DEVICE(0x00E4), 
+		ISAPNP_VENDOR('C','T','L'), ISAPNP_FUNCTION(0x0045), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0968), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x0968), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1868), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1868), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x8611), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x0003), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1869), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1869), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1878), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1878), 0 },
+
+	{	ISAPNP_VENDOR('E','S','S'), ISAPNP_DEVICE(0x1879), 
+		ISAPNP_VENDOR('E','S','S'), ISAPNP_FUNCTION(0x1879), 0 },
+
+	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('C','M','I'), ISAPNP_DEVICE(0x0001), 
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('R','W','B'), ISAPNP_DEVICE(0x1688), 
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0007),
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0001), 
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x1001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x1001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0110),
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0120),
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x0020), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x0020), 0 },
+
+	{	ISAPNP_VENDOR('A','L','S'), ISAPNP_DEVICE(0x0200),
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+
+	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
+		ISAPNP_VENDOR('@','@','@'), ISAPNP_FUNCTION(0x2001), 0 },
+
+	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
+		ISAPNP_VENDOR('@','X','@'), ISAPNP_FUNCTION(0x2001), 0 },
+
+	{	ISAPNP_VENDOR('R','T','L'), ISAPNP_DEVICE(0x3000),
+		ISAPNP_VENDOR('@','H','@'), ISAPNP_FUNCTION(0x0001), 0 },
+	{0}
+};
+
+MODULE_DEVICE_TABLE(isapnp, id_table);
+
 static struct pci_dev *activate_dev(char *devname, char *resname, struct pci_dev *dev)
 {
 	int err;
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sb_common.c linux/drivers/sound/sb_common.c
--- v2.4.1/linux/drivers/sound/sb_common.c	Wed Sep 27 13:53:56 2000
+++ linux/drivers/sound/sb_common.c	Fri Feb 16 16:02:37 2001
@@ -21,12 +21,16 @@
  *
  * 2000/09/18 - got rid of attach_uart401
  * Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ *
+ * 2001/01/26 - replaced CLI/STI with spinlocks
+ * Chris Rankin <rankinc@zipworld.com.au>
  */
 
 #include <linux/config.h>
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/spinlock.h>
 
 #include "sound_config.h"
 #include "sound_firmware.h"
@@ -62,6 +66,7 @@
 
 static int jazz16_base = 0;		/* Not detected */
 static unsigned char jazz16_bits = 0;	/* I/O relocation bits */
+static spinlock_t jazz16_lock = SPIN_LOCK_UNLOCKED;
 
 /*
  * Logitech Soundman Wave specific initialization code
@@ -251,8 +256,7 @@
 	unsigned long   flags;
 
 	DDB(printk("Entered dsp_get_vers()\n"));
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	devc->major = devc->minor = 0;
 	sb_dsp_command(devc, 0xe1);	/* Get version */
 
@@ -269,8 +273,8 @@
 			}
 		}
 	}
+	spin_unlock_irqrestore(&devc->lock, flags);
 	DDB(printk("DSP version %d.%02d\n", devc->major, devc->minor));
-	restore_flags(flags);
 }
 
 static int sb16_set_dma_hw(sb_devc * devc)
@@ -368,12 +372,11 @@
 	/*
 	 *	Magic wake up sequence by writing to 0x201 (aka Joystick port)
 	 */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&jazz16_lock, flags);
 	outb((0xAF), 0x201);
 	outb((0x50), 0x201);
 	outb((bits), 0x201);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&jazz16_lock, flags);
 }
 
 static int init_Jazz16(sb_devc * devc, struct address_info *hw_config)
@@ -523,6 +526,7 @@
 		return 0;
 	}
 
+	devc->lock = SPIN_LOCK_UNLOCKED;
 	devc->type = hw_config->card_subtype;
 
 	devc->base = hw_config->io_base;
@@ -552,7 +556,9 @@
 	
 	if (devc->sbmo.acer)
 	{
-		cli();
+		unsigned long flags;
+
+		spin_lock_irqsave(&devc->lock, flags);
 		inb(devc->base + 0x09);
 		inb(devc->base + 0x09);
 		inb(devc->base + 0x09);
@@ -564,7 +570,7 @@
 		inb(devc->base + 0x0b);
 		inb(devc->base + 0x09);
 		inb(devc->base + 0x00);
-		sti();
+		spin_unlock_irqrestore(&devc->lock, flags);
 	}
 	/*
 	 * Detect the device
@@ -631,7 +637,7 @@
 		printk(KERN_ERR "sb: Can't allocate memory for device information\n");
 		return 0;
 	}
-	memcpy((char *) detected_devc, (char *) devc, sizeof(sb_devc));
+	memcpy(detected_devc, devc, sizeof(sb_devc));
 	MDB(printk(KERN_INFO "SB %d.%02d detected OK (%x)\n", devc->major, devc->minor, hw_config->io_base));
 	return 1;
 }
@@ -937,15 +943,14 @@
 
 	if (devc->model == MDL_ESS) return ess_setmixer (devc, port, value);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 
 	outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
 	udelay(20);
 	outb(((unsigned char) (value & 0xff)), MIXER_DATA);
 	udelay(20);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 unsigned int sb_getmixer(sb_devc * devc, unsigned int port)
@@ -955,15 +960,14 @@
 
 	if (devc->model == MDL_ESS) return ess_getmixer (devc, port);
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 
 	outb(((unsigned char) (port & 0xff)), MIXER_ADDR);
 	udelay(20);
 	val = inb(MIXER_DATA);
 	udelay(20);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	return val;
 }
@@ -986,14 +990,13 @@
 {
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&jazz16_lock, flags);  /* NOT the SB card? */
 
 	outb((addr & 0xff), base + 1);	/* Low address bits */
 	outb((addr >> 8), base + 2);	/* High address bits */
 	outb((val), base);	/* Data */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&jazz16_lock, flags);
 }
 
 static unsigned char smw_getmem(sb_devc * devc, int base, int addr)
@@ -1001,14 +1004,13 @@
 	unsigned long flags;
 	unsigned char val;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&jazz16_lock, flags);  /* NOT the SB card? */
 
 	outb((addr & 0xff), base + 1);	/* Low address bits */
 	outb((addr >> 8), base + 2);	/* High address bits */
 	val = inb(base);	/* Data */
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&jazz16_lock, flags);
 	return val;
 }
 
@@ -1168,12 +1170,11 @@
 	/*
 	 *	Magic wake up sequence by writing to 0x201 (aka Joystick port)
 	 */
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&jazz16_lock, flags);
 	outb(0xAF, 0x201);
 	outb(0x50, 0x201);
 	outb(bits, 0x201);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&jazz16_lock, flags);
 
 	hw_config->name = "Jazz16";
 	smw_midi_init(devc, hw_config);
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sb_ess.c linux/drivers/sound/sb_ess.c
--- v2.4.1/linux/drivers/sound/sb_ess.c	Mon Jan  1 10:23:21 2001
+++ linux/drivers/sound/sb_ess.c	Fri Feb 16 16:02:37 2001
@@ -186,6 +186,7 @@
  */
 
 #include <linux/delay.h>
+#include <linux/spinlock.h>
 
 #include "sound_config.h"
 #include "sb_mixer.h"
@@ -524,10 +525,9 @@
 	unsigned long flags;
 	sb_devc *devc = audio_devs[dev]->devc;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	sb_dsp_reset(devc);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	/*
 	 * Audio 2 may still be operational! Creates awful sounds!
@@ -969,8 +969,7 @@
 	unsigned int val;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	outb(((unsigned char) (0x40 & 0xff)), MIXER_ADDR);
 
 	udelay(20);
@@ -978,7 +977,7 @@
 	udelay(20);
 	val |= inb(MIXER_DATA);
 	udelay(20);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	return val;
 }
@@ -1565,8 +1564,7 @@
 printk(KERN_INFO "FKS: write mixer %x: %x\n", port, value);
 #endif
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (port >= 0xa0) {
 		ess_write (devc, port, value);
 	} else {
@@ -1576,7 +1574,7 @@
 		outb(((unsigned char) (value & 0xff)), MIXER_DATA);
 		udelay(20);
 	};
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 unsigned int ess_getmixer (sb_devc * devc, unsigned int port)
@@ -1584,8 +1582,7 @@
 	unsigned int val;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 
 	if (port >= 0xa0) {
 		val = ess_read (devc, port);
@@ -1596,7 +1593,7 @@
 		val = inb(MIXER_DATA);
 		udelay(20);
 	}
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	return val;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sb_midi.c linux/drivers/sound/sb_midi.c
--- v2.4.1/linux/drivers/sound/sb_midi.c	Fri Aug 11 08:26:43 2000
+++ linux/drivers/sound/sb_midi.c	Fri Feb 16 16:02:37 2001
@@ -11,6 +11,8 @@
  * for more info.
  */
 
+#include <linux/spinlock.h>
+
 #include "sound_config.h"
 
 #include "sb.h"
@@ -36,15 +38,14 @@
 	if (devc == NULL)
 		return -ENXIO;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	if (devc->opened)
 	{
-		restore_flags(flags);
+		spin_unlock_irqrestore(&devc->lock, flags);
 		return -EBUSY;
 	}
 	devc->opened = 1;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 
 	devc->irq_mode = IMODE_MIDI;
 	devc->midi_broken = 0;
@@ -74,13 +75,12 @@
 	if (devc == NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 	sb_dsp_reset(devc);
 	devc->intr_active = 0;
 	devc->input_opened = 0;
 	devc->opened = 0;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 static int sb_midi_out(int dev, unsigned char midi_byte)
@@ -131,14 +131,13 @@
 	if (devc == NULL)
 		return;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&devc->lock, flags);
 
 	data = inb(DSP_READ);
 	if (devc->input_opened)
 		devc->midi_input_intr(devc->my_mididev, data);
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&devc->lock, flags);
 }
 
 #define MIDI_SYNTH_NAME	"Sound Blaster Midi"
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sonicvibes.c linux/drivers/sound/sonicvibes.c
--- v2.4.1/linux/drivers/sound/sonicvibes.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/sonicvibes.c	Fri Feb  9 11:30:23 2001
@@ -100,7 +100,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
--- v2.4.1/linux/drivers/sound/sound_core.c	Sun Dec  3 17:45:23 2000
+++ linux/drivers/sound/sound_core.c	Fri Feb  9 11:30:23 2001
@@ -37,7 +37,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sound_firmware.c linux/drivers/sound/sound_firmware.c
--- v2.4.1/linux/drivers/sound/sound_firmware.c	Tue Mar 14 17:54:42 2000
+++ linux/drivers/sound/sound_firmware.c	Fri Feb  9 11:30:23 2001
@@ -3,7 +3,7 @@
 #include <linux/module.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/unistd.h>
 #include <asm/uaccess.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/soundcard.c linux/drivers/sound/soundcard.c
--- v2.4.1/linux/drivers/sound/soundcard.c	Mon Sep 25 12:32:54 2000
+++ linux/drivers/sound/soundcard.c	Fri Feb  9 11:30:23 2001
@@ -37,7 +37,7 @@
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <linux/wait.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/sscape.c linux/drivers/sound/sscape.c
--- v2.4.1/linux/drivers/sound/sscape.c	Sat Nov 11 18:33:14 2000
+++ linux/drivers/sound/sscape.c	Fri Feb  9 11:30:23 2001
@@ -15,6 +15,8 @@
  * Sergey Smitienko	: ensoniq p'n'p support
  * Christoph Hellwig	: adapted to module_init/module_exit
  * Bartlomiej Zolnierkiewicz : added __init to attach_sscape()
+ * Chris Rankin		: Specify that this module owns the coprocessor
+ * Arnaldo C. de Melo	: added missing restore_flags in sscape_pnp_upload_file
  */
 
 #include <linux/init.h>
@@ -34,7 +36,7 @@
 #include <asm/io.h>
 #include <asm/segment.h>
 #include <linux/wait.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/proc_fs.h>
@@ -600,6 +602,7 @@
 static coproc_operations sscape_coproc_operations =
 {
 	"SoundScape M68K",
+	THIS_MODULE,
 	sscape_coproc_open,
 	sscape_coproc_close,
 	sscape_coproc_ioctl,
@@ -671,7 +674,7 @@
 		return;
 	}
 	
-	if (sscape_is_pnp == 0) {
+	if (!sscape_is_pnp) {
 	
 	    save_flags(flags);
 	    cli();
@@ -967,7 +970,10 @@
 		memcpy(devc->raw_buf, dt, l); dt += l;
 		sscape_start_dma(devc->dma, devc->raw_buf_phys, l, 0x48);
 		sscape_pnp_start_dma ( devc, 0 );
-		if (sscape_pnp_wait_dma ( devc, 0 ) == 0) return 0;
+		if (sscape_pnp_wait_dma ( devc, 0 ) == 0) {
+			restore_flags(flags);	    
+			return 0;
+		}
 	}
 	
 	restore_flags(flags);	    
@@ -1087,8 +1093,8 @@
 		sscape_pnp_write_codec( devc, 10, (sscape_pnp_read_codec(devc, 10) & 0x7f) |
 		 ( sscape_mic_enable == 0 ? 0x00 : 0x80) );
 	}
-	sscape_write_host_ctrl2( devc, 0x84, 0x32 );
-	sscape_write_host_ctrl2( devc, 0x86, 0x32 );
+	sscape_write_host_ctrl2( devc, 0x84, 0x64 );  /* MIDI volume */
+	sscape_write_host_ctrl2( devc, 0x86, 0x64 );  /* MIDI volume?? */
 	sscape_write_host_ctrl2( devc, 0x8A, sscape_ext_midi);
 
 	sscape_pnp_write_codec ( devc, 6, 0x3f ); //WAV_VOL
@@ -1239,10 +1245,7 @@
 
 	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 0) | 0x20);
 	sscape_pnp_write_codec( devc, 0, sscape_pnp_read_codec( devc, 1) | 0x20);
-	
-	release_region(devc->codec, 2);
-	release_region(devc->base, 8);		
-		
+
 	return 1;	
 }
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/trident.c linux/drivers/sound/trident.c
--- v2.4.1/linux/drivers/sound/trident.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/sound/trident.c	Fri Feb  9 11:30:23 2001
@@ -108,7 +108,7 @@
 #include <linux/sched.h>
 #include <linux/delay.h>
 #include <linux/sound.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/soundcard.h>
 #include <linux/pci.h>
 #include <asm/io.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/uart401.c linux/drivers/sound/uart401.c
--- v2.4.1/linux/drivers/sound/uart401.c	Wed Sep 27 13:53:57 2000
+++ linux/drivers/sound/uart401.c	Sun Feb  4 10:05:29 2001
@@ -202,7 +202,7 @@
 #define MIDI_SYNTH_CAPS	SYNTH_CAP_INPUT
 #include "midi_synth.h"
 
-static struct midi_operations uart401_operations =
+static const struct midi_operations uart401_operations =
 {
 	owner:		THIS_MODULE,
 	info:		{"MPU-401 (UART) MIDI", 0, 0, SNDCARD_MPU401},
@@ -351,7 +351,6 @@
 		goto cleanup_irq;
 	}
 	conf_printf(name, hw_config);
-	std_midi_synth.midi_dev = devc->my_dev;
 	midi_devs[devc->my_dev] = kmalloc(sizeof(struct midi_operations), GFP_KERNEL);
 	if (!midi_devs[devc->my_dev]) {
 		printk(KERN_ERR "uart401: Failed to allocate memory\n");
@@ -371,6 +370,11 @@
 	memcpy(midi_devs[devc->my_dev]->converter, &std_midi_synth, sizeof(struct synth_operations));
 	strcpy(midi_devs[devc->my_dev]->info.name, name);
 	midi_devs[devc->my_dev]->converter->id = "UART401";
+	midi_devs[devc->my_dev]->converter->midi_dev = devc->my_dev;
+
+	if (owner)
+		midi_devs[devc->my_dev]->converter->owner = owner;
+
 	hw_config->slots[4] = devc->my_dev;
 	sequencer_init();
 	devc->opened = 0;
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/via82cxxx_audio.c linux/drivers/sound/via82cxxx_audio.c
--- v2.4.1/linux/drivers/sound/via82cxxx_audio.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sound/via82cxxx_audio.c	Tue Feb  6 22:04:12 2001
@@ -34,8 +34,8 @@
 #include <linux/smp_lock.h>
 #include <linux/ioport.h>
 #include <linux/wrapper.h>
+#include <linux/delay.h>
 #include <asm/io.h>
-#include <asm/delay.h>
 #include <asm/uaccess.h>
 #include <asm/hardirq.h>
 #include <asm/semaphore.h>
@@ -1535,6 +1535,9 @@
 
 	/* acknowledge any flagged bits ASAP */
 	outb (status, chan->iobase);
+
+	if (!chan->sgtable) /* XXX: temporary solution */
+		return;
 
 	/* grab current h/w ptr value */
 	n = atomic_read (&chan->hw_ptr);
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/wavfront.c linux/drivers/sound/wavfront.c
--- v2.4.1/linux/drivers/sound/wavfront.c	Sun Dec 31 10:26:18 2000
+++ linux/drivers/sound/wavfront.c	Fri Feb  9 11:30:23 2001
@@ -2534,7 +2534,7 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/fs.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/unistd.h>
 #include <asm/uaccess.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/ymf_sb.c linux/drivers/sound/ymf_sb.c
--- v2.4.1/linux/drivers/sound/ymf_sb.c	Sun Dec 31 10:26:17 2000
+++ linux/drivers/sound/ymf_sb.c	Wed Dec 31 16:00:00 1969
@@ -1,853 +0,0 @@
-/*
-  Legacy audio driver for YMF724, 740, 744, 754 series.
-  Copyright 2000 Daisuke Nagano <breeze.nagano@nifty.ne.jp>
-
-  Based on the VIA 82Cxxx driver by Jeff Garzik <jgarzik@pobox.com>
-  And ported to 2.3.x by Jeff Garzik too :)  My it is a small world.
-
-  Distribued under the GNU PUBLIC LICENSE (GPL) Version 2.
-  See the "COPYING" file distributed with kernel source tree for more info.
-
-  -------------------------------------------------------------------------
-
-  It only supports SBPro compatible function of YMF7xx series s.t.
-    * 22.05kHz, 8-bit and stereo sample
-    * OPL3-compatible FM synthesizer
-    * MPU-401 compatible "external" MIDI interface
-
-  -------------------------------------------------------------------------
-
-  Revision history
-
-   Tue May 14 19:00:00 2000   0.0.1
-   * initial release
-
-   Tue May 16 19:29:29 2000   0.0.2
-
-   * add a little delays for reset devices.
-   * fixed addressing bug.
-
-   Sun May 21 15:14:37 2000   0.0.3
-
-   * Add 'master_vol' module parameter to change 'PCM out Vol' of AC'97.
-   * remove native UART401 support. External MIDI port should be supported 
-     by sb_midi driver.
-   * add support for SPDIF OUT. Module parameter 'spdif_out' is now available.
-
-   Wed May 31 00:13:57 2000   0.0.4
-
-   * remove entries in Hwmcode.h. Now YMF744 / YMF754 sets instructions 
-     in 724hwmcode.h.
-   * fixed wrong legacy_io setting on YMF744/YMF754 .
-
-   Thu Sep 21 05:32:51 BRT 2000 0.0.5
-   * got rid of attach_uart401 and attach_sbmpu
-     Arnaldo Carvalho de Melo <acme@conectiva.com.br>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/ac97_codec.h>
-
-#include <asm/io.h>
-
-#include "sound_config.h"
-#include "sb.h"
-
-#include "724hwmcode.h"
-
-#undef YMF_DEBUG
-#define SUPPORT_UART401_MIDI 1
-
-/* ---------------------------------------------------------------------- */
-
-#ifndef PCI_VENDOR_ID_YAMAHA
-#define PCI_VENDOR_ID_YAMAHA  0x1073
-#endif
-#ifndef PCI_DEVICE_ID_YMF724
-#define PCI_DEVICE_ID_YMF724  0x0004
-#endif
-#ifndef PCI_DEVICE_ID_YMF740
-#define PCI_DEVICE_ID_YMF740  0x000A
-#endif
-#ifndef PCI_DEVICE_ID_YMF740C
-#define PCI_DEVICE_ID_YMF740C 0x000C
-#endif
-#ifndef PCI_DEVICE_ID_YMF724F
-#define PCI_DEVICE_ID_YMF724F 0x000D
-#endif
-#ifndef PCI_DEVICE_ID_YMF744
-#define PCI_DEVICE_ID_YMF744  0x0010
-#endif
-#ifndef PCI_DEVICE_ID_YMF754
-#define PCI_DEVICE_ID_YMF754  0x0012
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-#define YMFSB_RESET_DELAY               5
-
-#define YMFSB_REGSIZE                   0x8000
-
-#define YMFSB_AC97TIMEOUT               2000
-
-#define	YMFSB_WORKBITTIMEOUT            250000
-
-#define	YMFSB_DSPLENGTH                 0x0080
-#define	YMFSB_CTRLLENGTH                0x3000
-
-#define YMFSB_PCIR_VENDORID             0x00
-#define YMFSB_PCIR_DEVICEID             0x02
-#define YMFSB_PCIR_CMD                  0x04
-#define YMFSB_PCIR_REVISIONID           0x08
-#define YMFSB_PCIR_BASEADDR             0x10
-#define YMFSB_PCIR_IRQ                  0x3c
-
-#define	YMFSB_PCIR_LEGCTRL              0x40
-#define	YMFSB_PCIR_ELEGCTRL             0x42
-#define	YMFSB_PCIR_DSXGCTRL             0x48
-#define YMFSB_PCIR_OPLADR               0x60
-#define YMFSB_PCIR_SBADR                0x62
-#define YMFSB_PCIR_MPUADR               0x64
-
-#define	YMFSB_INTFLAG                   0x0004
-#define	YMFSB_ACTIVITY                  0x0006
-#define	YMFSB_GLOBALCTRL                0x0008
-#define	YMFSB_ZVCTRL                    0x000A
-#define	YMFSB_TIMERCTRL                 0x0010
-#define	YMFSB_TIMERCOUNT                0x0012
-#define	YMFSB_SPDIFOUTCTRL              0x0018
-#define	YMFSB_SPDIFOUTSTATUS            0x001C
-#define	YMFSB_EEPROMCTRL                0x0020
-#define	YMFSB_SPDIFINCTRL               0x0034
-#define	YMFSB_SPDIFINSTATUS             0x0038
-#define	YMFSB_DSPPROGRAMDL              0x0048
-#define	YMFSB_DLCNTRL                   0x004C
-#define	YMFSB_GPIOININTFLAG             0x0050
-#define	YMFSB_GPIOININTENABLE           0x0052
-#define	YMFSB_GPIOINSTATUS              0x0054
-#define	YMFSB_GPIOOUTCTRL               0x0056
-#define	YMFSB_GPIOFUNCENABLE            0x0058
-#define	YMFSB_GPIOTYPECONFIG            0x005A
-#define	YMFSB_AC97CMDDATA               0x0060
-#define	YMFSB_AC97CMDADR                0x0062
-#define	YMFSB_PRISTATUSDATA             0x0064
-#define	YMFSB_PRISTATUSADR              0x0066
-#define	YMFSB_SECSTATUSDATA             0x0068
-#define	YMFSB_SECSTATUSADR              0x006A
-#define	YMFSB_SECCONFIG                 0x0070
-#define	YMFSB_LEGACYOUTVOL              0x0080
-#define	YMFSB_LEGACYOUTVOLL             0x0080
-#define	YMFSB_LEGACYOUTVOLR             0x0082
-#define	YMFSB_NATIVEDACOUTVOL           0x0084
-#define	YMFSB_NATIVEDACOUTVOLL          0x0084
-#define	YMFSB_NATIVEDACOUTVOLR          0x0086
-#define	YMFSB_SPDIFOUTVOL               0x0088
-#define	YMFSB_SPDIFOUTVOLL              0x0088
-#define	YMFSB_SPDIFOUTVOLR              0x008A
-#define	YMFSB_AC3OUTVOL                 0x008C
-#define	YMFSB_AC3OUTVOLL                0x008C
-#define	YMFSB_AC3OUTVOLR                0x008E
-#define	YMFSB_PRIADCOUTVOL              0x0090
-#define	YMFSB_PRIADCOUTVOLL             0x0090
-#define	YMFSB_PRIADCOUTVOLR             0x0092
-#define	YMFSB_LEGACYLOOPVOL             0x0094
-#define	YMFSB_LEGACYLOOPVOLL            0x0094
-#define	YMFSB_LEGACYLOOPVOLR            0x0096
-#define	YMFSB_NATIVEDACLOOPVOL          0x0098
-#define	YMFSB_NATIVEDACLOOPVOLL         0x0098
-#define	YMFSB_NATIVEDACLOOPVOLR         0x009A
-#define	YMFSB_SPDIFLOOPVOL              0x009C
-#define	YMFSB_SPDIFLOOPVOLL             0x009E
-#define	YMFSB_SPDIFLOOPVOLR             0x009E
-#define	YMFSB_AC3LOOPVOL                0x00A0
-#define	YMFSB_AC3LOOPVOLL               0x00A0
-#define	YMFSB_AC3LOOPVOLR               0x00A2
-#define	YMFSB_PRIADCLOOPVOL             0x00A4
-#define	YMFSB_PRIADCLOOPVOLL            0x00A4
-#define	YMFSB_PRIADCLOOPVOLR            0x00A6
-#define	YMFSB_NATIVEADCINVOL            0x00A8
-#define	YMFSB_NATIVEADCINVOLL           0x00A8
-#define	YMFSB_NATIVEADCINVOLR           0x00AA
-#define	YMFSB_NATIVEDACINVOL            0x00AC
-#define	YMFSB_NATIVEDACINVOLL           0x00AC
-#define	YMFSB_NATIVEDACINVOLR           0x00AE
-#define	YMFSB_BUF441OUTVOL              0x00B0
-#define	YMFSB_BUF441OUTVOLL             0x00B0
-#define	YMFSB_BUF441OUTVOLR             0x00B2
-#define	YMFSB_BUF441LOOPVOL             0x00B4
-#define	YMFSB_BUF441LOOPVOLL            0x00B4
-#define	YMFSB_BUF441LOOPVOLR            0x00B6
-#define	YMFSB_SPDIFOUTVOL2              0x00B8
-#define	YMFSB_SPDIFOUTVOL2L             0x00B8
-#define	YMFSB_SPDIFOUTVOL2R             0x00BA
-#define	YMFSB_SPDIFLOOPVOL2             0x00BC
-#define	YMFSB_SPDIFLOOPVOL2L            0x00BC
-#define	YMFSB_SPDIFLOOPVOL2R            0x00BE
-#define	YMFSB_ADCSLOTSR                 0x00C0
-#define	YMFSB_RECSLOTSR                 0x00C4
-#define	YMFSB_ADCFORMAT                 0x00C8
-#define	YMFSB_RECFORMAT                 0x00CC
-#define	YMFSB_P44SLOTSR                 0x00D0
-#define	YMFSB_STATUS                    0x0100
-#define	YMFSB_CTRLSELECT                0x0104
-#define	YMFSB_MODE                      0x0108
-#define	YMFSB_SAMPLECOUNT               0x010C
-#define	YMFSB_NUMOFSAMPLES              0x0110
-#define	YMFSB_CONFIG                    0x0114
-#define	YMFSB_PLAYCTRLSIZE              0x0140
-#define	YMFSB_RECCTRLSIZE               0x0144
-#define	YMFSB_EFFCTRLSIZE               0x0148
-#define	YMFSB_WORKSIZE                  0x014C
-#define	YMFSB_MAPOFREC                  0x0150
-#define	YMFSB_MAPOFEFFECT               0x0154
-#define	YMFSB_PLAYCTRLBASE              0x0158
-#define	YMFSB_RECCTRLBASE               0x015C
-#define	YMFSB_EFFCTRLBASE               0x0160
-#define	YMFSB_WORKBASE                  0x0164
-#define	YMFSB_DSPINSTRAM                0x1000
-#define	YMFSB_CTRLINSTRAM               0x4000
-
-
-/* ---------------------------------------------------------------------- */
-
-#define MAX_CARDS	4
-
-#define PFX		"ymf_sb: "
-
-#define YMFSB_VERSION	"0.0.6"
-#define YMFSB_CARD_NAME	"YMF7xx Legacy Audio driver " YMFSB_VERSION
-
-#ifdef SUPPORT_UART401_MIDI
-#if 0
-# define ymf7xxsb_probe_midi probe_uart401
-# define ymf7xxsb_unload_midi unload_uart401
-#else
-# define ymf7xxsb_probe_midi probe_sbmpu
-# define ymf7xxsb_unload_midi unload_sbmpu
-#endif
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-static struct address_info	sb_data[MAX_CARDS];
-static struct address_info	opl3_data[MAX_CARDS];
-#ifdef SUPPORT_UART401_MIDI
-static struct address_info	mpu_data[MAX_CARDS];
-#endif
-static unsigned			cards = 0;
-static unsigned short          *ymfbase[MAX_CARDS];
-
-/* ---------------------------------------------------------------------- */
-
-#ifdef MODULE
-#ifdef SUPPORT_UART401_MIDI
-static int mpu_io   = 0;
-#endif
-static int synth_io = 0;
-static int io       = 0;
-static int dma      = 0;
-static int master_vol = -1;
-static int spdif_out = 0;
-#ifdef SUPPORT_UART401_MIDI
-MODULE_PARM(mpu_io, "i");
-#endif
-MODULE_PARM(synth_io, "i");
-MODULE_PARM(io,"i");
-MODULE_PARM(dma,"i");
-MODULE_PARM(master_vol,"i");
-MODULE_PARM(spdif_out,"i");
-#else
-#ifdef SUPPORT_UART401_MIDI
-static int mpu_io     = 0x330;
-#endif
-static int synth_io   = 0x388;
-static int io         = 0x220;
-static int dma        = 1;
-static int master_vol = 80;
-static int spdif_out  = 0;
-#endif
-
-/* ---------------------------------------------------------------------- */
-
-static int readRegWord( int adr ) {
-
-	if (ymfbase[cards]==NULL) return 0;
-
-	return readw(ymfbase[cards]+adr/2);
-}
-
-static void writeRegWord( int adr, int val ) {
-
-	if (ymfbase[cards]==NULL) return;
-
-	writew((unsigned short)(val&0xffff), ymfbase[cards] + adr/2);
-
-	return;
-}
-
-static int readRegDWord( int adr ) {
-
-	if (ymfbase[cards]==NULL) return 0;
-
-	return (readl(ymfbase[cards]+adr/2));
-}
-
-static void writeRegDWord( int adr, int val ) {
-
-	if (ymfbase[cards]==NULL) return;
-
-	writel((unsigned int)(val&0xffffffff), ymfbase[cards]+adr/2);
-
-	return;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int checkPrimaryBusy( void )
-{
-	int timeout=0;
-
-	while ( timeout++ < YMFSB_AC97TIMEOUT )
-	{
-		if ( (readRegWord(YMFSB_PRISTATUSADR) & 0x8000) == 0x0000 )
-			return 0;
-	}
-	return -1;
-}
-
-static int writeAc97( int adr, unsigned short val )
-{
-
-	if ( adr > 0x7f || adr < 0x00 ) return -1;
-
-	if ( checkPrimaryBusy() ) return -1;
-
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "AC97 0x%0x = 0x%0x\n",adr,val);
-#endif
-
-	writeRegWord( YMFSB_AC97CMDADR,  0x0000 | adr );
-	writeRegWord( YMFSB_AC97CMDDATA, val );
-
-	return 0;
-}
-
-static int __init checkCodec( struct pci_dev *pcidev )
-{
-	u8 tmp8;
-
-	pci_read_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, &tmp8);
-	if ( tmp8 & 0x03 ) {
-		pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc);
-		mdelay(YMFSB_RESET_DELAY);
-		pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8|0x03);
-		mdelay(YMFSB_RESET_DELAY);
-		pci_write_config_byte(pcidev, YMFSB_PCIR_DSXGCTRL, tmp8&0xfc);
-		mdelay(YMFSB_RESET_DELAY);
-	}
-
-	if ( checkPrimaryBusy() ) return -1;
-
-	return 0;
-}
-
-static int __init setupLegacyIO( struct pci_dev *pcidev )
-{
-	int v;
-	int sbio=0,mpuio=0,oplio=0,dma=0;
-
-	switch(sb_data[cards].io_base) {
-	case 0x220:
-		sbio = 0;
-		break;
-	case 0x240:
-		sbio = 1;
-		break;
-	case 0x260:
-		sbio = 2;
-		break;
-	case 0x280:
-		sbio = 3;
-		break;
-	default:
-		return -1;
-		break;
-	}
-#ifdef YMF_DEBUG
-	printk(PFX "set SBPro I/O at 0x%x\n",sb_data[cards].io_base);
-#endif
-
-#ifdef SUPPORT_UART401_MIDI
-	switch(mpu_data[cards].io_base) {
-	case 0x330:
-		mpuio = 0;
-		break;
-	case 0x300:
-		mpuio = 1;
-		break;
-	case 0x332:
-		mpuio = 2;
-		break;
-	case 0x334:
-		mpuio = 3;
-		break;
-	default:
-		mpuio = 0;
-		break;
-	}
-# ifdef YMF_DEBUG
-	printk(PFX "set MPU401 I/O at 0x%x\n",mpu_data[cards].io_base);
-# endif
-#endif
-
-	switch(opl3_data[cards].io_base) {
-	case 0x388:
-		oplio = 0;
-		break;
-	case 0x398:
-		oplio = 1;
-		break;
-	case 0x3a0:
-		oplio = 2;
-		break;
-	case 0x3a8:
-		oplio = 3;
-		break;
-	default:
-		return -1;
-		break;
-	}
-#ifdef YMF_DEBUG
-	printk(PFX "set OPL3 I/O at 0x%x\n",opl3_data[cards].io_base);
-#endif
-
-	dma = sb_data[cards].dma;
-#ifdef YMF_DEBUG
-	printk(PFX "set DMA address at 0x%x\n",sb_data[cards].dma);
-#endif
-
-	v = 0x0000 | ((dma & 0x03) << 6) | 0x003f;
-	pci_write_config_word(pcidev, YMFSB_PCIR_LEGCTRL, v);
-#ifdef YMF_DEBUG
-	printk(PFX "LEGCTRL: 0x%x\n",v);
-#endif
-	switch( pcidev->device ) {
-	case PCI_DEVICE_ID_YMF724:
-	case PCI_DEVICE_ID_YMF740:
-	case PCI_DEVICE_ID_YMF724F:
-	case PCI_DEVICE_ID_YMF740C:
-		v = 0x8800 | ((mpuio & 0x03) << 4)
-			   | ((sbio & 0x03) << 2)
-			   | (oplio & 0x03);
-		pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);
-#ifdef YMF_DEBUG
-		printk(PFX "ELEGCTRL: 0x%x\n",v);
-#endif
-		break;
-
-	case PCI_DEVICE_ID_YMF744:
-	case PCI_DEVICE_ID_YMF754:
-		v = 0x8800;
-		pci_write_config_word(pcidev, YMFSB_PCIR_ELEGCTRL, v);
-#ifdef YMF_DEBUG
-		printk(PFX "ELEGCTRL: 0x%x\n",v);
-#endif
-		pci_write_config_word(pcidev, YMFSB_PCIR_OPLADR, opl3_data[cards].io_base);
-		pci_write_config_word(pcidev, YMFSB_PCIR_SBADR,  sb_data[cards].
-io_base);
-#ifdef SUPPORT_UART401_MIDI
-		pci_write_config_word(pcidev, YMFSB_PCIR_MPUADR, mpu_data[cards].io_base);
-#endif
-		break;
-
-	default:
-		printk(KERN_ERR PFX "Invalid device ID: %d\n",pcidev->device);
-		return -1;
-		break;
-	}
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void enableDSP( void )
-{
-	writeRegDWord( YMFSB_CONFIG, 0x00000001 );
-	return;
-}
-
-static void disableDSP( void )
-{
-	int val;
-	int i;
-
-	val = readRegDWord( YMFSB_CONFIG );
-	if ( val ) {
-		writeRegDWord( YMFSB_CONFIG, 0 );
-	}
-
-	i=0;
-	while( ++i < YMFSB_WORKBITTIMEOUT ) {
-		val = readRegDWord(YMFSB_STATUS);
-		if ( (val & 0x00000002) == 0x00000000 ) break;
-	}
-
-	return;
-}
-
-static int __init setupInstruction( struct pci_dev *pcidev )
-{
-	int i;
-	int val;
-
-	writeRegDWord( YMFSB_NATIVEDACOUTVOL, 0 ); /* mute dac */
-	disableDSP();
-
-	writeRegDWord( YMFSB_MODE, 0x00010000 );
-
-	/* DS-XG Software Reset */
-	writeRegDWord( YMFSB_MODE,         0x00000000 );
-	writeRegDWord( YMFSB_MAPOFREC,     0x00000000 );
-	writeRegDWord( YMFSB_MAPOFEFFECT,  0x00000000 );
-	writeRegDWord( YMFSB_PLAYCTRLBASE, 0x00000000 );
-	writeRegDWord( YMFSB_RECCTRLBASE,  0x00000000 );
-	writeRegDWord( YMFSB_EFFCTRLBASE,  0x00000000 );
-
-	val = readRegWord( YMFSB_GLOBALCTRL );
-	writeRegWord( YMFSB_GLOBALCTRL, (val&~0x0007) );
-
-	/* setup DSP instruction code */
-	for ( i=0 ; i<YMFSB_DSPLENGTH ; i+=4 ) {
-	  writeRegDWord( YMFSB_DSPINSTRAM+i, DspInst[i>>2] );
-	}
-
-	switch( pcidev->device ) {
-	case PCI_DEVICE_ID_YMF724:
-	case PCI_DEVICE_ID_YMF740:
-		/* setup Control instruction code */
-		for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) {
-			writeRegDWord( YMFSB_CTRLINSTRAM+i, CntrlInst[i>>2] );
-		}
-		break;
-
-	case PCI_DEVICE_ID_YMF724F:
-	case PCI_DEVICE_ID_YMF740C:
-	case PCI_DEVICE_ID_YMF744:
-	case PCI_DEVICE_ID_YMF754:
-		/* setup Control instruction code */
-		for ( i=0 ; i<YMFSB_CTRLLENGTH ; i+=4 ) {
-			writeRegDWord( YMFSB_CTRLINSTRAM+i, CntrlInst1E[i>>2] );
-		}
-		break;
-
-	default:
-		return -1;
-	}
-
-	enableDSP();
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static int __init ymf7xx_init(struct pci_dev *pcidev)
-{
-	unsigned short v;
-
-	/* Read hardware information */
-#ifdef YMF_DEBUG
-	unsigned int   dv;
-	pci_read_config_word(pcidev, YMFSB_PCIR_VENDORID, &v);
-	printk(KERN_INFO PFX "Vendor ID = 0x%x\n",v);
-	pci_read_config_word(pcidev, YMFSB_PCIR_DEVICEID, &v);
-	printk(KERN_INFO PFX "Device ID = 0x%x\n",v);
-	pci_read_config_word(pcidev, YMFSB_PCIR_REVISIONID, &v);
-	printk(KERN_INFO PFX "Revision ID = 0x%x\n",v&0xff);
-	pci_read_config_dword(pcidev, YMFSB_PCIR_BASEADDR, &dv);
-	printk(KERN_INFO PFX "Base address = 0x%x\n",dv);
-	pci_read_config_word(pcidev, YMFSB_PCIR_IRQ, &v);
-	printk(KERN_INFO PFX "IRQ line = 0x%x\n",v&0xff);
-#endif
-
-	/* enables memory space access / bus mastering */
-	pci_read_config_word(pcidev, YMFSB_PCIR_CMD, &v);
-	pci_write_config_word(pcidev, YMFSB_PCIR_CMD, v|0x06);
-
-	/* check codec */
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "check codec...\n");
-#endif
-	if (checkCodec(pcidev)) return -1;
-
-	/* setup legacy I/O */
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup legacy I/O...\n");
-#endif
-	if (setupLegacyIO(pcidev)) return -1;
-	
-	/* setup instruction code */	
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup instructions...\n");
-#endif
-	if (setupInstruction(pcidev)) return -1;
-
-	/* AC'97 setup */	
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup AC'97...\n");
-#endif
-	if ( writeAc97(AC97_RESET            ,0x0000) )  /* Reset */
-		return -1;
-	if ( writeAc97(AC97_MASTER_VOL_STEREO,0x0000) )  /* Master Volume */
-		return -1;
-
-	v = 31*(100-master_vol)/100;
-	v = (v<<8 | v)&0x7fff;
-	if ( writeAc97(AC97_PCMOUT_VOL       ,v     ) )  /* PCM out Volume */
-		return -1;
-
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup Legacy Volume...\n");
-#endif
-	/* Legacy Audio Output Volume L & R ch */
-	writeRegDWord( YMFSB_LEGACYOUTVOL, 0x3fff3fff );
-
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "setup SPDIF output control...\n");
-#endif
-	/* SPDIF Output control */
-	v = spdif_out != 0 ? 0x0001 : 0x0000;
-	writeRegWord( YMFSB_SPDIFOUTCTRL, v );
-	/* no copyright protection, 
-	   sample-rate converted,
-	   re-recorded software comercially available (the 1st generation),
-	   original */
-	writeRegWord( YMFSB_SPDIFOUTSTATUS, 0x9a04 );
-
-	return 0;
-}
-
-/* ---------------------------------------------------------------------- */
-
-static void __init ymf7xxsb_attach_sb(struct address_info *hw_config)
-{
-	if(!sb_dsp_init(hw_config, THIS_MODULE))
-		hw_config->slots[0] = -1;
-}
-
-static int __init ymf7xxsb_probe_sb(struct address_info *hw_config)
-{
-	if (check_region(hw_config->io_base, 16))
-	{
-		printk(KERN_DEBUG PFX "SBPro port 0x%x is already in use\n",
-		       hw_config->io_base);
-		return 0;
-	}
-	return sb_dsp_detect(hw_config, SB_PCI_YAMAHA, 0, NULL);
-}
-
-
-static void ymf7xxsb_unload_sb(struct address_info *hw_config, int unload_mpu)
-{
-	if(hw_config->slots[0]!=-1)
-		sb_dsp_unload(hw_config, unload_mpu);
-}
-
-/* ---------------------------------------------------------------------- */
-
-enum chip_types {
-	CH_YMF724 = 0,
-	CH_YMF724F,
-	CH_YMF740,
-	CH_YMF740C,
-	CH_YMF744,
-	CH_YMF754,
-};
-
-/* directly indexed by chip_types enum above */
-/* note we keep this a struct to ease adding
- * other per-board or per-chip info here */
-struct {
-	const char           *devicename;
-} devicetable[] __initdata = 
-{
-	{ "YMF724A-E" },
-	{ "YMF724F" },
-	{ "YMF740A-B" },
-	{ "YMF740C" },
-	{ "YMF744" },
-	{ "YMF754" },
-};
-
-static struct pci_device_id ymf7xxsb_pci_tbl[] __initdata = {
-	{ PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF724,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF724 },
-	{ PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF724F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF724F },
-	{ PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF740,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF740 },
-	{ PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF740C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF740C },
-	{ PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF744,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF744 },
-	{ PCI_VENDOR_ID_YAMAHA, PCI_DEVICE_ID_YMF754,  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_YMF754 },
-	{ 0, }
-};
-MODULE_DEVICE_TABLE(pci, ymf7xxsb_pci_tbl);
-
-static int __init ymf7xxsb_init_one (struct pci_dev *pcidev, const struct pci_device_id *ent)
-{
-
-	const char	*devicename;
-	unsigned long   iobase;
-
-	if (cards == MAX_CARDS) {
-	  	printk (KERN_DEBUG PFX "maximum number of cards reached\n");
-		return -ENODEV;
-	}
-
-	if ( pcidev->irq == 0 ) return -ENODEV;
-	iobase = pci_resource_start (pcidev, 0);
-	if ( iobase == 0x00000000 ) return -ENODEV;
-
-	devicename = devicetable[ent->driver_data].devicename;
-
-	/* remap memory mapped I/O onto kernel virtual memory */
-	if ( (ymfbase[cards] = ioremap_nocache(iobase, YMFSB_REGSIZE)) == 0 )
-	{
-		printk(KERN_ERR PFX "ioremap (0x%lx) returns zero\n", iobase);
-		return -ENODEV;
-	}
-	printk(KERN_INFO PFX "found %s at 0x%lx\n", devicename, iobase);
-#ifdef YMF_DEBUG
-	printk(KERN_INFO PFX "remappling to 0x%p\n", ymfbase[cards]);
-#endif
-
-	memset (&sb_data[cards], 0, sizeof (struct address_info));
-	memset (&opl3_data[cards], 0, sizeof (struct address_info));
-#ifdef SUPPORT_UART401_MIDI
-	memset (&mpu_data[cards], 0, sizeof (struct address_info));
-#endif
-
-	sb_data[cards].name   = YMFSB_CARD_NAME;
-	opl3_data[cards].name = YMFSB_CARD_NAME;
-#ifdef SUPPORT_UART401_MIDI
-	mpu_data[cards].name  = YMFSB_CARD_NAME;
-#endif
-
-	sb_data[cards].card_subtype = MDL_YMPCI;
-
-	if ( io == 0 ) io      = 0x220;
-	sb_data[cards].io_base = io;
-	sb_data[cards].irq     = pcidev->irq;
-	sb_data[cards].dma     = dma;
-
-	if ( synth_io == 0 ) synth_io = 0x388;
-	opl3_data[cards].io_base = synth_io;
-	opl3_data[cards].irq     = -1;
-
-#ifdef SUPPORT_UART401_MIDI
-	if ( mpu_io == 0 ) mpu_io = 0x330;
-	mpu_data[cards].io_base = mpu_io;
-	mpu_data[cards].irq     = -1;
-#endif
-
-	if ( ymf7xx_init(pcidev) ) {
-		printk (KERN_ERR PFX
-			"Cannot initialize %s, aborting\n",
-			devicename);
-		return -ENODEV;
-	}
-
-	/* register legacy SoundBlaster Pro */
-	if (!ymf7xxsb_probe_sb(&sb_data[cards])) {
-		printk (KERN_ERR PFX
-			"SB probe at 0x%X failed, aborting\n",
-			io);
-		return -ENODEV;
-	}
-	ymf7xxsb_attach_sb (&sb_data[cards]);
-
-#ifdef SUPPORT_UART401_MIDI
-	/* register legacy MIDI */
-	if ( mpu_io > 0 && 0)
-	{
-		if (!ymf7xxsb_probe_midi (&mpu_data[cards], THIS_MODULE)) {
-			printk (KERN_ERR PFX
-				"MIDI probe @ 0x%X failed, aborting\n",
-				mpu_io);
-			ymf7xxsb_unload_sb (&sb_data[cards], 0);
-			return -ENODEV;
-		}
-	}
-#endif
-
-	/* register legacy OPL3 */
-
-	cards++;	
-	return 0;
-}
-
-static struct pci_driver ymf7xxsb_driver = {
-	name:		"ymf7xxsb",
-	id_table:	ymf7xxsb_pci_tbl,
-	probe:		ymf7xxsb_init_one,
-};
-
-static int __init init_ymf7xxsb_module(void)
-{
-	int i;
-
-	if ( master_vol < 0 ) master_vol  = 50;
-	if ( master_vol > 100 ) master_vol = 100;
-
-	for (i=0 ; i<MAX_CARDS ; i++ )
-		ymfbase[i] = NULL;
-
-	i = pci_module_init (&ymf7xxsb_driver);
-	if (i < 0)
-		return i;
-
-	printk (KERN_INFO PFX YMFSB_CARD_NAME " loaded\n");
-	
-	return 0;
-}
-
-static void __exit free_iomaps( void )
-{
-	int i;
-
-	for ( i=0 ; i<MAX_CARDS ; i++ ) {
-		if ( ymfbase[i]!=NULL )
-			iounmap(ymfbase[i]);
-	}
-
-	return;
-}
-
-static void __exit cleanup_ymf7xxsb_module(void)
-{
-	int i;
-	
-	for (i = 0; i < cards; i++) {
-#ifdef SUPPORT_UART401_MIDI
-		ymf7xxsb_unload_sb (&sb_data[i], 0);
-		ymf7xxsb_unload_midi (&mpu_data[i]);
-#else
-		ymf7xxsb_unload_sb (&sb_data[i], 1);
-#endif
-	}
-
-	free_iomaps();
-	pci_unregister_driver(&ymf7xxsb_driver);
-
-}
-
-MODULE_AUTHOR("Daisuke Nagano, breeze.nagano@nifty.ne.jp");
-MODULE_DESCRIPTION("YMF7xx Legacy Audio Driver");
-
-module_init(init_ymf7xxsb_module);
-module_exit(cleanup_ymf7xxsb_module);
-
diff -u --recursive --new-file v2.4.1/linux/drivers/sound/ymfpci.c linux/drivers/sound/ymfpci.c
--- v2.4.1/linux/drivers/sound/ymfpci.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/sound/ymfpci.c	Fri Feb 16 16:02:37 2001
@@ -50,8 +50,9 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/poll.h>
+#include <linux/soundcard.h>
 #include <linux/ac97_codec.h>
 #include <linux/sound.h>
 
@@ -1718,21 +1719,15 @@
 	case SNDCTL_DSP_SETFRAGMENT:
 		if (get_user(val, (int *)arg))
 			return -EFAULT;
-	/* P3: these frags are for Doom. Amasingly, it sets [2,2**11]. */
-	/* P3 */ // printk("ymfpci: ioctl SNDCTL_DSP_SETFRAGMENT 0x%x\n", val);
-
 		dmabuf = &state->wpcm.dmabuf;
 		dmabuf->ossfragshift = val & 0xffff;
 		dmabuf->ossmaxfrags = (val >> 16) & 0xffff;
-		switch (dmabuf->ossmaxfrags) {
-		case 1:
-			dmabuf->ossfragshift = 12;
-			return 0;
-		default:
-			/* Fragments must be 2K long */
-			dmabuf->ossfragshift = 11;
-			dmabuf->ossmaxfrags = 2;
-		}
+		if (dmabuf->ossfragshift < 4)
+			dmabuf->ossfragshift = 4;
+		if (dmabuf->ossfragshift > 15)
+			dmabuf->ossfragshift = 15;
+		if (dmabuf->ossmaxfrags < 4)
+			dmabuf->ossmaxfrags = 4;
 		return 0;
 
 	case SNDCTL_DSP_GETOSPACE:
diff -u --recursive --new-file v2.4.1/linux/drivers/telephony/ixj.c linux/drivers/telephony/ixj.c
--- v2.4.1/linux/drivers/telephony/ixj.c	Fri Dec 29 14:35:47 2000
+++ linux/drivers/telephony/ixj.c	Fri Feb 16 16:02:37 2001
@@ -20,6 +20,7 @@
  *    
  * Fixes:
  *                  Marc Boucher, <marc@mbsi.ca>
+ *		    David Huggins-Daines <dhd@cepstral.com>
  * 
  * More information about the hardware related to this driver can be found  
  * at our website:    http://www.quicknet.net
@@ -52,7 +53,7 @@
 #include <linux/kernel.h>	/* printk() */
 #include <linux/fs.h>		/* everything... */
 #include <linux/errno.h>	/* error codes */
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/ioport.h>
 #include <linux/interrupt.h>
@@ -67,7 +68,7 @@
 #include <asm/segment.h>
 #include <asm/uaccess.h>
 
-#ifdef CONFIG_PCMCIA
+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
 #include <pcmcia/version.h>
 #include <pcmcia/cs_types.h>
 #include <pcmcia/cs.h>
@@ -90,7 +91,7 @@
 
 MODULE_PARM(ixjdebug, "i");
 
-static IXJ ixj[IXJMAX];
+static IXJ* ixj[IXJMAX];
 
 static struct timer_list ixj_timer;
 
@@ -103,7 +104,7 @@
 *
 ************************************************************************/
 
-static int Stub(IXJ * J, unsigned long arg)
+static int Stub(IXJ * j, unsigned long arg)
 {
 	return 0;
 }
@@ -117,60 +118,62 @@
 static IXJ_REGFUNC ixj_PreIoctl = &Stub;
 static IXJ_REGFUNC ixj_PostIoctl = &Stub;
 
-static void ixj_read_frame(int board);
-static void ixj_write_frame(int board);
+static void ixj_read_frame(IXJ *j);
+static void ixj_write_frame(IXJ *j);
 static void ixj_init_timer(void);
 static void ixj_add_timer(void);
 static void ixj_timeout(unsigned long ptr);
-static int read_filters(int board);
-static int LineMonitor(int board);
+static int read_filters(IXJ *j);
+static int LineMonitor(IXJ *j);
 static int ixj_fasync(int fd, struct file *, int mode);
-static int ixj_set_port(int board, int arg);
-static int ixj_set_pots(int board, int arg);
-static int ixj_hookstate(int board);
-static int ixj_record_start(int board);
-static void ixj_record_stop(int board);
-static void set_rec_volume(int board, int volume);
-static void ixj_vad(int board, int arg);
-static int ixj_play_start(int board);
-static void ixj_play_stop(int board);
-static int ixj_set_tone_on(unsigned short arg, int board);
-static int ixj_set_tone_off(unsigned short, int board);
-static int ixj_play_tone(int board, char tone);
-static int idle(int board);
-static void ixj_ring_on(int board);
-static void ixj_ring_off(int board);
-static void aec_stop(int board);
-static void ixj_ringback(int board);
-static void ixj_busytone(int board);
-static void ixj_dialtone(int board);
-static void ixj_cpt_stop(int board);
-static char daa_int_read(int board);
-static int daa_set_mode(int board, int mode);
-static int ixj_linetest(int board);
-static int ixj_daa_write(int board);
-static int ixj_daa_cid_read(int board);
-static void DAA_Coeff_US(int board);
-static void DAA_Coeff_UK(int board);
-static void DAA_Coeff_France(int board);
-static void DAA_Coeff_Germany(int board);
-static void DAA_Coeff_Australia(int board);
-static void DAA_Coeff_Japan(int board);
-static int ixj_init_filter(int board, IXJ_FILTER * jf);
-static int ixj_init_tone(int board, IXJ_TONE * ti);
-static int ixj_build_cadence(int board, IXJ_CADENCE * cp);
-static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp);
+static int ixj_set_port(IXJ *j, int arg);
+static int ixj_set_pots(IXJ *j, int arg);
+static int ixj_hookstate(IXJ *j);
+static int ixj_record_start(IXJ *j);
+static void ixj_record_stop(IXJ *j);
+static void set_rec_volume(IXJ *j, int volume);
+static void ixj_vad(IXJ *j, int arg);
+static int ixj_play_start(IXJ *j);
+static void ixj_play_stop(IXJ *j);
+static int ixj_set_tone_on(unsigned short arg, IXJ *j);
+static int ixj_set_tone_off(unsigned short, IXJ *j);
+static int ixj_play_tone(IXJ *j, char tone);
+static int idle(IXJ *j);
+static void ixj_ring_on(IXJ *j);
+static void ixj_ring_off(IXJ *j);
+static void aec_stop(IXJ *j);
+static void ixj_ringback(IXJ *j);
+static void ixj_busytone(IXJ *j);
+static void ixj_dialtone(IXJ *j);
+static void ixj_cpt_stop(IXJ *j);
+static char daa_int_read(IXJ *j);
+static int daa_set_mode(IXJ *j, int mode);
+static int ixj_linetest(IXJ *j);
+static int ixj_daa_write(IXJ *j);
+static int ixj_daa_cid_read(IXJ *j);
+static void DAA_Coeff_US(IXJ *j);
+static void DAA_Coeff_UK(IXJ *j);
+static void DAA_Coeff_France(IXJ *j);
+static void DAA_Coeff_Germany(IXJ *j);
+static void DAA_Coeff_Australia(IXJ *j);
+static void DAA_Coeff_Japan(IXJ *j);
+static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf);
+static int ixj_init_tone(IXJ *j, IXJ_TONE * ti);
+static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp);
+static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp);
 // Serial Control Interface funtions
-static int SCI_Control(int board, int control);
-static int SCI_Prepare(int board);
-static int SCI_WaitHighSCI(int board);
-static int SCI_WaitLowSCI(int board);
+static int SCI_Control(IXJ *j, int control);
+static int SCI_Prepare(IXJ *j);
+static int SCI_WaitHighSCI(IXJ *j);
+static int SCI_WaitLowSCI(IXJ *j);
 static DWORD PCIEE_GetSerialNumber(WORD wAddress);
-static int ixj_PCcontrol_wait(int board);
-static void ixj_write_cid(int board);
-static void ixj_write_cid_bit(int board, int bit);
-static int set_base_frame(int board, int size);
-static int set_play_codec(int board, int rate);
+static int ixj_PCcontrol_wait(IXJ *j);
+static void ixj_write_cid(IXJ *j);
+static void ixj_write_cid_bit(IXJ *j, int bit);
+static int set_base_frame(IXJ *j, int size);
+static int set_play_codec(IXJ *j, int rate);
+static void set_rec_depth(IXJ *j, int depth);
+static void set_play_depth(IXJ *j, int depth);
 
 /************************************************************************
 CT8020/CT8021 Host Programmers Model
@@ -183,75 +186,82 @@
 8-9		Hardware Status Register			Read Only
 A-B		Hardware Control Register			Read Write
 C-D Host Transmit (Write) Data Buffer Access Port (buffer input)Write Only
-E-F Host Recieve (Read) Data Buffer Access Port (buffer input)	Read Only
+E-F Host Receive (Read) Data Buffer Access Port (buffer input)	Read Only
 ************************************************************************/
 
-extern __inline__ void ixj_read_HSR(int board)
+extern __inline__ void ixj_read_HSR(IXJ *j)
 {
-	ixj[board].hsr.bytes.low = inb_p(ixj[board].DSPbase + 8);
-	ixj[board].hsr.bytes.high = inb_p(ixj[board].DSPbase + 9);
+	j->hsr.bytes.low = inb_p(j->DSPbase + 8);
+	j->hsr.bytes.high = inb_p(j->DSPbase + 9);
 }
 
-extern __inline__ int IsControlReady(int board)
+extern __inline__ int IsControlReady(IXJ *j)
 {
-	ixj_read_HSR(board);
-	return ixj[board].hsr.bits.controlrdy ? 1 : 0;
+	ixj_read_HSR(j);
+	return j->hsr.bits.controlrdy ? 1 : 0;
 }
 
-extern __inline__ int IsPCControlReady(int board)
+extern __inline__ int IsPCControlReady(IXJ *j)
 {
-	ixj[board].pccr1.byte = inb_p(ixj[board].XILINXbase + 3);
-	return ixj[board].pccr1.bits.crr ? 1 : 0;
+	j->pccr1.byte = inb_p(j->XILINXbase + 3);
+	return j->pccr1.bits.crr ? 1 : 0;
 }
 
-extern __inline__ int IsStatusReady(int board)
+extern __inline__ int IsStatusReady(IXJ *j)
 {
-	ixj_read_HSR(board);
-	return ixj[board].hsr.bits.statusrdy ? 1 : 0;
+	ixj_read_HSR(j);
+	return j->hsr.bits.statusrdy ? 1 : 0;
 }
 
-extern __inline__ int IsRxReady(int board)
+extern __inline__ int IsRxReady(IXJ *j)
 {
-	ixj_read_HSR(board);
+	ixj_read_HSR(j);
 #ifdef PERFMON_STATS
-	++ixj[board].rxreadycheck;
+	++j->rxreadycheck;
 #endif
-	return ixj[board].hsr.bits.rxrdy ? 1 : 0;
+	return j->hsr.bits.rxrdy ? 1 : 0;
 }
 
-extern __inline__ int IsTxReady(int board)
+extern __inline__ int IsTxReady(IXJ *j)
 {
-	ixj_read_HSR(board);
+	ixj_read_HSR(j);
 #ifdef PERFMON_STATS
-	++ixj[board].txreadycheck;
+	++j->txreadycheck;
 #endif
-	return ixj[board].hsr.bits.txrdy ? 1 : 0;
+	return j->hsr.bits.txrdy ? 1 : 0;
 }
 
-extern __inline__ void set_play_volume(int board, int volume)
+extern __inline__ void set_play_volume(IXJ *j, int volume)
 {
-	ixj_WriteDSPCommand(0xCF02, board);
-	ixj_WriteDSPCommand(volume, board);
+	ixj_WriteDSPCommand(0xCF02, j);
+	ixj_WriteDSPCommand(volume, j);
 }
 
-extern __inline__ int get_play_volume(int board)
+extern __inline__ void set_play_depth(IXJ *j, int depth)
 {
-	ixj_WriteDSPCommand(0xCF00, board);
-	return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+	if (depth > 60)
+		depth = 60;
+	if (depth < 0)
+		depth = 0;
+	ixj_WriteDSPCommand(0x5280 + depth, j);
 }
 
-extern __inline__ BYTE SLIC_GetState(int board)
+extern __inline__ int get_play_volume(IXJ *j)
 {
-	IXJ *j = &ixj[board];
+	ixj_WriteDSPCommand(0xCF00, j);
+	return j->ssr.high << 8 | j->ssr.low;
+}
 
-	if (j->cardtype == 600) {
+extern __inline__ BYTE SLIC_GetState(IXJ *j)
+{
+	if (j->cardtype == QTI_PHONECARD) {
 		j->pccr1.byte = 0;
 		j->psccr.bits.dev = 3;
 		j->psccr.bits.rw = 1;
 		outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);
-		ixj_PCcontrol_wait(board);
+		ixj_PCcontrol_wait(j);
 		j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;
-		ixj_PCcontrol_wait(board);
+		ixj_PCcontrol_wait(j);
 		if (j->pslic.bits.powerdown)
 			return PLD_SLIC_STATE_OC;
 		else if (!j->pslic.bits.ring0 && !j->pslic.bits.ring1)
@@ -264,12 +274,11 @@
 	return j->pld_slicr.bits.state;
 }
 
-static BOOL SLIC_SetState(BYTE byState, int board)
+static BOOL SLIC_SetState(BYTE byState, IXJ *j)
 {
 	BOOL fRetVal = FALSE;
-	IXJ *j = &ixj[board];
 
-	if (j->cardtype == 600) {
+	if (j->cardtype == QTI_PHONECARD) {
 		if (j->flags.pcmciasct) {
 			switch (byState) {
 			case PLD_SLIC_STATE_TIPOPEN:
@@ -309,7 +318,7 @@
 			j->psccr.bits.dev = 3;
 			j->psccr.bits.rw = 0;
 			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 		}
 	} else {
 		// Set the C1, C2, C3 & B2EN signals.
@@ -398,12 +407,14 @@
 	case G729LOADER:
 		ixj_DownloadG729 = regfunc;
 		for (cnt = 0; cnt < IXJMAX; cnt++)
-			ixj_DownloadG729(&ixj[cnt], 0L);
+			if (ixj[cnt] != NULL)
+				ixj_DownloadG729(ixj[cnt], 0L);
 		break;
 	case TS85LOADER:
 		ixj_DownloadTS85 = regfunc;
 		for (cnt = 0; cnt < IXJMAX; cnt++)
-			ixj_DownloadTS85(&ixj[cnt], 0L);
+			if (ixj[cnt] != NULL)
+				ixj_DownloadTS85(ixj[cnt], 0L);
 		break;
 	case PRE_READ:
 		ixj_PreRead = regfunc;
@@ -476,9 +487,8 @@
 	add_timer(&ixj_timer);
 }
 
-static void ixj_tone_timeout(int board)
+static void ixj_tone_timeout(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	IXJ_TONE ti;
 
 	j->tone_state++;
@@ -489,11 +499,11 @@
 			if (j->tone_cadence_state >= j->cadence_t->elements_used) {
 				switch (j->cadence_t->termination) {
 				case PLAY_ONCE:
-					ixj_cpt_stop(board);
+					ixj_cpt_stop(j);
 					break;
 				case REPEAT_LAST_ELEMENT:
 					j->tone_cadence_state--;
-					ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index);
+					ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index);
 					break;
 				case REPEAT_ALL:
 					j->tone_cadence_state = 0;
@@ -503,11 +513,11 @@
 						ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
 						ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
 						ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-						ixj_init_tone(board, &ti);
+						ixj_init_tone(j, &ti);
 					}
-					ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, board);
-					ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, board);
-					ixj_play_tone(board, j->cadence_t->ce[0].index);
+					ixj_set_tone_on(j->cadence_t->ce[0].tone_on_time, j);
+					ixj_set_tone_off(j->cadence_t->ce[0].tone_off_time, j);
+					ixj_play_tone(j, j->cadence_t->ce[0].index);
 					break;
 				}
 			} else {
@@ -517,41 +527,43 @@
 					ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
 					ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
 					ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-					ixj_init_tone(board, &ti);
+					ixj_init_tone(j, &ti);
 				}
-				ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, board);
-				ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, board);
-				ixj_play_tone(board, j->cadence_t->ce[j->tone_cadence_state].index);
+				ixj_set_tone_on(j->cadence_t->ce[j->tone_cadence_state].tone_on_time, j);
+				ixj_set_tone_off(j->cadence_t->ce[j->tone_cadence_state].tone_off_time, j);
+				ixj_play_tone(j, j->cadence_t->ce[j->tone_cadence_state].index);
 			}
 		}
 	}
 }
 
-extern __inline__ void ixj_kill_fasync(int board, int dir)
+extern __inline__ void ixj_kill_fasync(IXJ *j, int band)
 {
-	kill_fasync(&ixj[board].async_queue, SIGIO, dir);	// Send apps notice of change
-
+	kill_fasync(&j->async_queue, SIGIO, band);
 }
+
 static void ixj_timeout(unsigned long ptr)
 {
 	int board;
 	unsigned long jifon;
-	IXJ *j;
 
 	for (board = 0; board < IXJMAX; board++) {
-		j = &ixj[board];
+		IXJ *j = ixj[board];
+
+		if (j == NULL)
+			continue;
 
 		if (j->DSPbase) {
 #ifdef PERFMON_STATS
 			j->timerchecks++;
 #endif
 			if (j->tone_state) {
-				if (!ixj_hookstate(board)) {
-					ixj_cpt_stop(board);
+				if (!ixj_hookstate(j)) {
+					ixj_cpt_stop(j);
 					if (j->m_hook) {
 						j->m_hook = 0;
 						j->ex.bits.hookstate = 1;
-						ixj_kill_fasync(board, POLL_IN);
+						ixj_kill_fasync(j, POLL_PRI);
 					}
 					continue;
 				}
@@ -562,60 +574,60 @@
 					    (hertz * j->tone_off_time * 25 / 100000);
 				if (time_before(jiffies, j->tone_start_jif + jifon)) {
 					if (j->tone_state == 1) {
-						ixj_play_tone(board, j->tone_index);
+						ixj_play_tone(j, j->tone_index);
 						if (j->dsp.low == 0x20) {
 							continue;
 						}
 					} else {
-						ixj_play_tone(board, 0);
+						ixj_play_tone(j, 0);
 						if (j->dsp.low == 0x20) {
 							continue;
 						}
 					}
 				} else {
-					ixj_tone_timeout(board);
+					ixj_tone_timeout(j);
 					if (j->flags.dialtone) {
-						ixj_dialtone(board);
+						ixj_dialtone(j);
 					}
 					if (j->flags.busytone) {
-						ixj_busytone(board);
+						ixj_busytone(j);
 						if (j->dsp.low == 0x20) {
 							continue;
 						}
 					}
 					if (j->flags.ringback) {
-						ixj_ringback(board);
+						ixj_ringback(j);
 						if (j->dsp.low == 0x20) {
 							continue;
 						}
 					}
 					if (!j->tone_state) {
 						if (j->dsp.low == 0x20 || (j->play_mode == -1 && j->rec_mode == -1))
-							idle(board);
+							idle(j);
 						if (j->dsp.low == 0x20 && j->play_mode != -1)
-							ixj_play_start(board);
+							ixj_play_start(j);
 						if (j->dsp.low == 0x20 && j->rec_mode != -1)
-							ixj_record_start(board);
+							ixj_record_start(j);
 					}
 				}
 			}
-			if (!j->tone_state || j->dsp.low != 0x20) {
-				if (IsRxReady(board)) {
-					ixj_read_frame(board);
+			if (!(j->tone_state && j->dsp.low == 0x20)) {
+				if (IsRxReady(j)) {
+					ixj_read_frame(j);
 				}
-				if (IsTxReady(board) && !j->flags.cidplay) {
-					ixj_write_frame(board);
+				if (IsTxReady(j) && !j->flags.cidplay) {
+					ixj_write_frame(j);
 				}
 			}
 			if (j->flags.cringing) {
-				if (ixj_hookstate(board) & 1) {
+				if (ixj_hookstate(j) & 1) {
 					j->flags.cringing = 0;
-					ixj_ring_off(board);
+					ixj_ring_off(j);
 				} else {
 					if (jiffies - j->ring_cadence_jif >= (hertz/2)) {
 						if (j->flags.cidring && !j->flags.cidsent) {
 							j->flags.cidsent = 1;
-							ixj_write_cid(board);
+							ixj_write_cid(j);
 							j->flags.cidring = 0;
 						}
 						j->ring_cadence_t--;
@@ -624,34 +636,34 @@
 						j->ring_cadence_jif = jiffies;
 					}
 					if (j->ring_cadence & 1 << j->ring_cadence_t) {
-						ixj_ring_on(board);
+						ixj_ring_on(j);
 					} else {
-						ixj_ring_off(board);
+						ixj_ring_off(j);
 						j->flags.cidring = 1;
 					}
 					continue;
 				}
 			}
 			if (!j->flags.ringing) {
-				if (ixj_hookstate(board)) {
+				if (ixj_hookstate(j)) {
 					if (j->dsp.low != 0x20 &&
-					    SLIC_GetState(board) != PLD_SLIC_STATE_ACTIVE) {
-						SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board);
+					    SLIC_GetState(j) != PLD_SLIC_STATE_ACTIVE) {
+						SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j);
 					}
-					LineMonitor(board);
-					read_filters(board);
-					ixj_WriteDSPCommand(0x511B, board);
+					LineMonitor(j);
+					read_filters(j);
+					ixj_WriteDSPCommand(0x511B, j);
 					j->proc_load = j->ssr.high << 8 | j->ssr.low;
 					if (!j->m_hook) {
 						j->m_hook = j->ex.bits.hookstate = 1;
-						ixj_kill_fasync(board, POLL_IN);
+						ixj_kill_fasync(j, POLL_PRI);
 					}
 				} else {
 					if (j->dsp.low != 0x20 &&
-					    SLIC_GetState(board) == PLD_SLIC_STATE_ACTIVE)
+					    SLIC_GetState(j) == PLD_SLIC_STATE_ACTIVE)
 						// Internet LineJACK
 					{
-						SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+						SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
 					}
 					if (j->ex.bits.dtmf_ready) {
 						j->dtmf_wp = j->dtmf_rp = j->ex.bits.dtmf_ready = 0;
@@ -659,7 +671,7 @@
 					if (j->m_hook) {
 						j->m_hook = 0;
 						j->ex.bits.hookstate = 1;
-						ixj_kill_fasync(board, POLL_IN);
+						ixj_kill_fasync(j, POLL_PRI);
 					}
 				}
 			}
@@ -667,34 +679,34 @@
 				if (j->flags.pstn_present) {
 					j->pld_scrr.byte = inb_p(j->XILINXbase);
 					if (j->pld_scrr.bits.daaflag) {
-						daa_int_read(board);
+						daa_int_read(j);
 						if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.RING) {
 							if (!j->flags.pstn_ringing) {
 								j->flags.pstn_ringing = 1;
 								if (j->daa_mode != SOP_PU_RINGING)
-									daa_set_mode(board, SOP_PU_RINGING);
+									daa_set_mode(j, SOP_PU_RINGING);
 							}
 						}
 						if (time_after(jiffies, j->pstn_sleeptil) && j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
 							j->pstn_winkstart = 0;
 							j->pstn_ring_stop = 0;
-							ixj[board].pld_scrw.bits.led1 = 1;
+							j->pld_scrw.bits.led1 = 1;
 							if (j->flags.pstn_ringing && !j->pstn_envelope) {
 								if (j->daa_mode != SOP_PU_RINGING) {
 									j->flags.pstn_ringing = 0;
 								} else {
-									ixj[board].pld_scrw.bits.led2 = 0;
+									j->pld_scrw.bits.led2 = 0;
 									j->pstn_envelope = 1;
 									j->pstn_ring_start = jiffies;
 									j->pstn_ring_stop = 0;
 								}
 								j->ex.bits.pstn_ring = 0;
 							}
-							outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
+							outb_p(j->pld_scrw.byte, j->XILINXbase);
 						} else {
-							ixj[board].pld_scrw.bits.led1 = 0;
-							ixj[board].pld_scrw.bits.led2 = 1;
-							outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
+							j->pld_scrw.bits.led1 = 0;
+							j->pld_scrw.bits.led2 = 1;
+							outb_p(j->pld_scrw.byte, j->XILINXbase);
 							if (j->flags.pstn_ringing && j->pstn_envelope) {
 								if(!j->pstn_ring_stop) {
 									j->pstn_ring_stop = jiffies;
@@ -707,7 +719,7 @@
 								if (!j->pstn_winkstart) {
 									j->pstn_winkstart = jiffies;
 								} else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) {
-									daa_set_mode(board, SOP_PU_SLEEP);
+									daa_set_mode(j, SOP_PU_SLEEP);
 									j->pstn_winkstart = 0;
 									j->ex.bits.pstn_wink = 1;
 								}
@@ -717,7 +729,7 @@
 						}
 						if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.Cadence) {
 							if (j->daa_mode == SOP_PU_RINGING) {
-								daa_set_mode(board, SOP_PU_SLEEP);
+								daa_set_mode(j, SOP_PU_SLEEP);
 								j->flags.pstn_ringing = 0;
 								j->ex.bits.pstn_ring = 0;
 							}
@@ -730,12 +742,12 @@
 						}
 					} else {
 						if (j->pld_scrr.bits.daaflag) {
-							daa_int_read(board);
+							daa_int_read(j);
 						}
 						j->ex.bits.pstn_ring = 0;
 						if (j->pstn_cid_intr && jiffies > j->pstn_cid_received + (hertz * 3)) {
 							if (j->daa_mode == SOP_PU_RINGING) {
-								ixj_daa_cid_read(board);
+								ixj_daa_cid_read(j);
 								j->ex.bits.caller_id = 1;
 							}
 							j->pstn_cid_intr = 0;
@@ -743,9 +755,9 @@
 							j->ex.bits.caller_id = 0;
 						}
 						if (!j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
-							ixj[board].pld_scrw.bits.led1 = 0;
-							ixj[board].pld_scrw.bits.led2 = 1;
-							outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
+							j->pld_scrw.bits.led1 = 0;
+							j->pld_scrw.bits.led2 = 1;
+							outb_p(j->pld_scrw.byte, j->XILINXbase);
 							if (j->flags.pstn_ringing && j->pstn_envelope) {
 								if(!j->pstn_ring_stop) {
 									j->pstn_ring_stop = jiffies;
@@ -754,13 +766,13 @@
 									j->ex.bits.pstn_ring = 1;
 									j->pstn_envelope = 0;
 								}
-								ixj[board].pld_scrw.bits.led1 = 0;
-								outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
+								j->pld_scrw.bits.led1 = 0;
+								outb_p(j->pld_scrw.byte, j->XILINXbase);
 							} else if (j->daa_mode == SOP_PU_CONVERSATION) {
 								if (!j->pstn_winkstart) {
 									j->pstn_winkstart = jiffies;
 								} else if (time_after(jiffies, j->pstn_winkstart + (hertz * j->winktime / 1000))) {
-									daa_set_mode(board, SOP_PU_SLEEP);
+									daa_set_mode(j, SOP_PU_SLEEP);
 									j->pstn_winkstart = 0;
 									j->ex.bits.pstn_wink = 1;
 								}
@@ -771,8 +783,7 @@
 			}
 			if (j->ex.bytes) {
 				wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
-
-				ixj_kill_fasync(board, POLL_IN);
+				ixj_kill_fasync(j, POLL_PRI);
 			}
 		} else {
 			break;
@@ -781,12 +792,12 @@
 	ixj_add_timer();
 }
 
-static int ixj_status_wait(int board)
+static int ixj_status_wait(IXJ *j)
 {
 	unsigned long jif;
 
 	jif = jiffies;
-	while (!IsStatusReady(board)) {
+	while (!IsStatusReady(j)) {
 		if (jiffies - jif > (60 * (hertz / 100))) {
 			return -1;
 		}
@@ -794,12 +805,12 @@
 	return 0;
 }
 
-static int ixj_PCcontrol_wait(int board)
+static int ixj_PCcontrol_wait(IXJ *j)
 {
 	unsigned long jif;
 
 	jif = jiffies;
-	while (!IsPCControlReady(board)) {
+	while (!IsPCControlReady(j)) {
 		if (jiffies - jif > (60 * (hertz / 100))) {
 			return -1;
 		}
@@ -807,7 +818,7 @@
 	return 0;
 }
 
-int ixj_WriteDSPCommand(unsigned short cmd, int board)
+int ixj_WriteDSPCommand(unsigned short cmd, IXJ *j)
 {
 	BYTES bytes;
 	unsigned long jif;
@@ -815,22 +826,22 @@
 	bytes.high = (cmd & 0xFF00) >> 8;
 	bytes.low = cmd & 0x00FF;
 	jif = jiffies;
-	while (!IsControlReady(board)) {
+	while (!IsControlReady(j)) {
 		if (jiffies - jif > (60 * (hertz / 100))) {
 			return -1;
 		}
 	}
-	outb_p(bytes.low, ixj[board].DSPbase + 6);
-	outb_p(bytes.high, ixj[board].DSPbase + 7);
+	outb_p(bytes.low, j->DSPbase + 6);
+	outb_p(bytes.high, j->DSPbase + 7);
 
-	if (ixj_status_wait(board)) {
-		ixj[board].ssr.low = 0xFF;
-		ixj[board].ssr.high = 0xFF;
+	if (ixj_status_wait(j)) {
+		j->ssr.low = 0xFF;
+		j->ssr.high = 0xFF;
 		return -1;
 	}
 /* Read Software Status Register */
-	ixj[board].ssr.low = inb_p(ixj[board].DSPbase + 2);
-	ixj[board].ssr.high = inb_p(ixj[board].DSPbase + 3);
+	j->ssr.low = inb_p(j->DSPbase + 2);
+	j->ssr.high = inb_p(j->DSPbase + 3);
 	return 0;
 }
 
@@ -839,26 +850,26 @@
 *  General Purpose IO Register read routine
 *
 ***************************************************************************/
-extern __inline__ int ixj_gpio_read(int board)
+extern __inline__ int ixj_gpio_read(IXJ *j)
 {
-	if (ixj_WriteDSPCommand(0x5143, board))
+	if (ixj_WriteDSPCommand(0x5143, j))
 		return -1;
 
-	ixj[board].gpio.bytes.low = ixj[board].ssr.low;
-	ixj[board].gpio.bytes.high = ixj[board].ssr.high;
+	j->gpio.bytes.low = j->ssr.low;
+	j->gpio.bytes.high = j->ssr.high;
 
 	return 0;
 }
 
-extern __inline__ void LED_SetState(int state, int board)
+extern __inline__ void LED_SetState(int state, IXJ *j)
 {
-	if (ixj[board].cardtype == 300) {
-		ixj[board].pld_scrw.bits.led1 = state & 0x1 ? 1 : 0;
-		ixj[board].pld_scrw.bits.led2 = state & 0x2 ? 1 : 0;
-		ixj[board].pld_scrw.bits.led3 = state & 0x4 ? 1 : 0;
-		ixj[board].pld_scrw.bits.led4 = state & 0x8 ? 1 : 0;
+	if (j->cardtype == QTI_LINEJACK) {
+		j->pld_scrw.bits.led1 = state & 0x1 ? 1 : 0;
+		j->pld_scrw.bits.led2 = state & 0x2 ? 1 : 0;
+		j->pld_scrw.bits.led3 = state & 0x4 ? 1 : 0;
+		j->pld_scrw.bits.led4 = state & 0x8 ? 1 : 0;
 
-		outb_p(ixj[board].pld_scrw.byte, ixj[board].XILINXbase);
+		outb_p(j->pld_scrw.byte, j->XILINXbase);
 	}
 }
 
@@ -876,11 +887,9 @@
 *
 * Hook Switch changes reported on GPIO_3
 *********************************************************************/
-static int ixj_set_port(int board, int arg)
+static int ixj_set_port(IXJ *j, int arg)
 {
-	IXJ *j = &ixj[board];
-
-	if (j->cardtype == 400) {
+	if (j->cardtype == QTI_PHONEJACK_LITE) {
 		if (arg != PORT_POTS)
 			return 10;
 		else
@@ -890,20 +899,20 @@
 	case PORT_POTS:
 		j->port = PORT_POTS;
 		switch (j->cardtype) {
-		case 600:
+		case QTI_PHONECARD:
 			if (j->flags.pcmciasct == 1)
-				SLIC_SetState(PLD_SLIC_STATE_ACTIVE, board);
+				SLIC_SetState(PLD_SLIC_STATE_ACTIVE, j);
 			else
 				return 11;
 			break;
-		case 500:
+		case QTI_PHONEJACK_PCI:
 			j->pld_slicw.pcib.mic = 0;
 			j->pld_slicw.pcib.spk = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 			break;
-		case 300:
-			ixj_set_pots(board, 0);
-			if (ixj_WriteDSPCommand(0xC528, board))		/* Write CODEC config to
+		case QTI_LINEJACK:
+			ixj_set_pots(j, 0);
+			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to
 									   Software Control Register */
 				return 2;
 			j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
@@ -914,19 +923,19 @@
 			j->pld_slicw.bits.rly1 = 1;
 			j->pld_slicw.bits.spken = 0;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-			SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+			SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
 			break;
-		case 100:
+		case QTI_PHONEJACK:
 			j->gpio.bytes.high = 0x0B;
 			j->gpio.bits.gpio6 = 0;
 			j->gpio.bits.gpio7 = 0;
-			ixj_WriteDSPCommand(j->gpio.word, board);
+			ixj_WriteDSPCommand(j->gpio.word, j);
 			break;
 		}
 		break;
 	case PORT_PSTN:
-		if (j->cardtype == 300) {
-			ixj_WriteDSPCommand(0xC534, board);	/* Write CODEC config to Software Control Register */
+		if (j->cardtype == QTI_LINEJACK) {
+			ixj_WriteDSPCommand(0xC534, j);	/* Write CODEC config to Software Control Register */
 
 			j->pld_slicw.bits.rly3 = 0;
 			j->pld_slicw.bits.rly1 = 1;
@@ -940,38 +949,35 @@
 	case PORT_SPEAKER:
 		j->port = PORT_SPEAKER;
 		switch (j->cardtype) {
-		case 600:
+		case QTI_PHONECARD:
 			if (j->flags.pcmciasct) {
-				SLIC_SetState(PLD_SLIC_STATE_OC, board);
-//                              while(SLIC_GetState(board) != PLD_SLIC_STATE_OC) {
-				//                                      SLIC_SetState(PLD_SLIC_STATE_OC,board);
-				//                              }
+				SLIC_SetState(PLD_SLIC_STATE_OC, j);
 			}
 			break;
-		case 500:
+		case QTI_PHONEJACK_PCI:
 			j->pld_slicw.pcib.mic = 1;
 			j->pld_slicw.pcib.spk = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 			break;
-		case 300:
-			ixj_set_pots(board, 0);
+		case QTI_LINEJACK:
+			ixj_set_pots(j, 0);
 			break;
-		case 100:
+		case QTI_PHONEJACK:
 			j->gpio.bytes.high = 0x0B;
 			j->gpio.bits.gpio6 = 0;
 			j->gpio.bits.gpio7 = 1;
-			ixj_WriteDSPCommand(j->gpio.word, board);
+			ixj_WriteDSPCommand(j->gpio.word, j);
 			break;
 		}
 		break;
 	case PORT_HANDSET:
-		if (j->cardtype == 300 || j->cardtype == 500) {
+		if (j->cardtype == QTI_LINEJACK || j->cardtype == QTI_PHONEJACK_PCI) {
 			return 5;
 		} else {
 			j->gpio.bytes.high = 0x0B;
 			j->gpio.bits.gpio6 = 1;
 			j->gpio.bits.gpio7 = 0;
-			ixj_WriteDSPCommand(j->gpio.word, board);
+			ixj_WriteDSPCommand(j->gpio.word, j);
 			j->port = PORT_HANDSET;
 		}
 		break;
@@ -982,11 +988,9 @@
 	return 0;
 }
 
-static int ixj_set_pots(int board, int arg)
+static int ixj_set_pots(IXJ *j, int arg)
 {
-	IXJ *j = &ixj[board];
-
-	if (j->cardtype == 300) {
+	if (j->cardtype == QTI_LINEJACK) {
 		if (arg) {
 			if (j->port == PORT_PSTN) {
 				j->pld_slicw.bits.rly1 = 0;
@@ -1005,33 +1009,22 @@
 	}
 }
 
-static void ixj_ring_on(int board)
+static void ixj_ring_on(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-	if (j->dsp.low == 0x20)	// Internet PhoneJACK
-	 {
-		if (ixjdebug > 0)
-			printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", board);
-
+	if (j->dsp.low == 0x20) { // Internet PhoneJACK
 		j->gpio.bytes.high = 0x0B;
 		j->gpio.bytes.low = 0x00;
 		j->gpio.bits.gpio1 = 1;
 		j->gpio.bits.gpio2 = 1;
 		j->gpio.bits.gpio5 = 0;
-		ixj_WriteDSPCommand(j->gpio.word, board);	/* send the ring signal */
-	} else			// Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI
-	 {
-		if (ixjdebug > 0)
-			printk(KERN_INFO "IXJ Ring On /dev/phone%d\n", board);
-
-		SLIC_SetState(PLD_SLIC_STATE_RINGING, board);
+		ixj_WriteDSPCommand(j->gpio.word, j);	/* send the ring signal */
+	} else {			// Internet LineJACK, Internet PhoneJACK Lite or Internet PhoneJACK PCI
+		SLIC_SetState(PLD_SLIC_STATE_RINGING, j);
 	}
 }
 
-static int ixj_pcmcia_cable_check(int board)
+static int ixj_pcmcia_cable_check(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	j->pccr1.byte = inb_p(j->XILINXbase + 0x03);
 	if (!j->flags.pcmciastate) {
 		j->pccr2.byte = inb_p(j->XILINXbase + 0x02);
@@ -1044,13 +1037,13 @@
 			j->psccr.bits.dev = 3;
 			j->psccr.bits.rw = 1;
 			outw_p(j->psccr.byte << 8, j->XILINXbase + 0x00);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->pslic.byte = inw_p(j->XILINXbase + 0x00) & 0xFF;
 			j->pslic.bits.led2 = j->pslic.bits.det ? 1 : 0;
 			j->psccr.bits.dev = 3;
 			j->psccr.bits.rw = 0;
 			outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			return j->pslic.bits.led2 ? 1 : 0;
 		} else if (j->flags.pcmciasct) {
 			return j->r_hook;
@@ -1089,7 +1082,7 @@
 			j->psccr.bits.dev = 3;
 			j->psccr.bits.rw = 1;
 			outb_p(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->flags.pcmciascp = 1;		// Set Cable Present Flag
 
 			j->flags.pcmciasct = (inw_p(j->XILINXbase + 0x00) >> 8) & 0x03;		// Get Cable Type
@@ -1122,7 +1115,7 @@
 			j->psccr.bits.dev = 0;
 			outb(j->sic1.byte, j->XILINXbase + 0x00);
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->sic2.bits.al = 0;	// Analog Loopback DAC analog -> ADC analog
 
 			j->sic2.bits.dl2 = 0;	// Digital Loopback DAC -> ADC one bit
@@ -1140,7 +1133,7 @@
 			j->psccr.bits.dev = 0;
 			outb(j->sic2.byte, j->XILINXbase + 0x00);
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->psccr.bits.addr = 3;		// R/W Smart Cable Register Address
 
 			j->psccr.bits.rw = 0;	// Read / Write flag
@@ -1149,7 +1142,7 @@
 			outb(0x00, j->XILINXbase + 0x00);	// PLL Divide N1
 
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->psccr.bits.addr = 4;		// R/W Smart Cable Register Address
 
 			j->psccr.bits.rw = 0;	// Read / Write flag
@@ -1158,7 +1151,7 @@
 			outb(0x09, j->XILINXbase + 0x00);	// PLL Multiply M1
 
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->sirxg.bits.lig = 1;	// Line In Gain
 
 			j->sirxg.bits.lim = 1;	// Line In Mute
@@ -1178,7 +1171,7 @@
 			j->psccr.bits.dev = 0;
 			outb(j->sirxg.byte, j->XILINXbase + 0x00);
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->siadc.bits.hom = 0;	// Handset Out Mute
 
 			j->siadc.bits.lom = 0;	// Line Out Mute
@@ -1192,7 +1185,7 @@
 			j->psccr.bits.dev = 0;
 			outb(j->siadc.byte, j->XILINXbase + 0x00);
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->sidac.bits.srm = 1;	// Speaker Right Mute
 
 			j->sidac.bits.slm = 1;	// Speaker Left Mute
@@ -1206,7 +1199,7 @@
 			j->psccr.bits.dev = 0;
 			outb(j->sidac.byte, j->XILINXbase + 0x00);
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 			j->siaatt.bits.sot = 0;
 			j->psccr.bits.addr = 9;		// R/W Smart Cable Register Address
 
@@ -1215,7 +1208,7 @@
 			j->psccr.bits.dev = 0;
 			outb(j->siaatt.byte, j->XILINXbase + 0x00);
 			outb(j->psccr.byte, j->XILINXbase + 0x01);
-			ixj_PCcontrol_wait(board);
+			ixj_PCcontrol_wait(j);
 
 			if (j->flags.pcmciasct == 1 && !j->readers && !j->writers) {
 				j->psccr.byte = j->pslic.byte = 0;
@@ -1223,7 +1216,7 @@
 				j->psccr.bits.dev = 3;
 				j->psccr.bits.rw = 0;
 				outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-				ixj_PCcontrol_wait(board);
+				ixj_PCcontrol_wait(j);
 			}
 		}
 		return 0;
@@ -1234,21 +1227,20 @@
 	return 0;
 }
 
-static int ixj_hookstate(int board)
+static int ixj_hookstate(IXJ *j)
 {
 	unsigned long det;
-	IXJ *j = &ixj[board];
 	int fOffHook = 0;
 
 	switch (j->cardtype) {
-	case 100:
-		ixj_gpio_read(board);
+	case QTI_PHONEJACK:
+		ixj_gpio_read(j);
 		fOffHook = j->gpio.bits.gpio3read ? 1 : 0;
 		break;
-	case 300:
-	case 400:
-	case 500:
-		SLIC_GetState(board);
+	case QTI_LINEJACK:
+	case QTI_PHONEJACK_LITE:
+	case QTI_PHONEJACK_PCI:
+		SLIC_GetState(j);
 		if (j->pld_slicr.bits.state == PLD_SLIC_STATE_ACTIVE ||
 		    j->pld_slicr.bits.state == PLD_SLIC_STATE_STANDBY) {
 			if (j->flags.ringing) {
@@ -1259,27 +1251,27 @@
 						schedule_timeout(1);
 					}
 				}
-				SLIC_GetState(board);
+				SLIC_GetState(j);
 				if (j->pld_slicr.bits.state == PLD_SLIC_STATE_RINGING) {
-					ixj_ring_on(board);
+					ixj_ring_on(j);
 				}
 			}
-			if (j->cardtype == 500) {
+			if (j->cardtype == QTI_PHONEJACK_PCI) {
 				j->pld_scrr.byte = inb_p(j->XILINXbase);
 				fOffHook = j->pld_scrr.pcib.det ? 1 : 0;
 			} else
 				fOffHook = j->pld_slicr.bits.det ? 1 : 0;
 		}
 		break;
-	case 600:
-		fOffHook = ixj_pcmcia_cable_check(board);
+	case QTI_PHONECARD:
+		fOffHook = ixj_pcmcia_cable_check(j);
 		break;
 	}
 	if (j->r_hook != fOffHook) {
 		j->r_hook = fOffHook;
 		if (j->port != PORT_POTS) {
 			j->ex.bits.hookstate = 1;
-			ixj_kill_fasync(board, POLL_IN);
+			ixj_kill_fasync(j, POLL_PRI);
 		} else if (!fOffHook) {
 			j->flash_end = jiffies + (hertz / 10 * 6);
 		}
@@ -1299,9 +1291,8 @@
 		return fOffHook;
 }
 
-static void ixj_ring_off(board)
+static void ixj_ring_off(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 
 	if (j->dsp.low == 0x20)	// Internet PhoneJACK
 	 {
@@ -1312,57 +1303,54 @@
 		j->gpio.bits.gpio1 = 0;
 		j->gpio.bits.gpio2 = 1;
 		j->gpio.bits.gpio5 = 0;
-		ixj_WriteDSPCommand(j->gpio.word, board);
+		ixj_WriteDSPCommand(j->gpio.word, j);
 	} else			// Internet LineJACK
 	 {
 		if (ixjdebug > 0)
 			printk(KERN_INFO "IXJ Ring Off\n");
 
-		SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+		SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
 
-		SLIC_GetState(board);
+		SLIC_GetState(j);
 	}
 }
 
-static void ixj_ring_start(int board)
+static void ixj_ring_start(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	j->flags.cringing = 1;
-	if (ixj_hookstate(board) & 1) {
+	if (ixj_hookstate(j) & 1) {
 		if (j->port == PORT_POTS)
-			ixj_ring_off(board);
+			ixj_ring_off(j);
 		j->flags.cringing = 0;
 	} else {
 		j->ring_cadence_jif = jiffies;
 		j->ring_cadence_t = 15;
 		if (j->ring_cadence & 1 << j->ring_cadence_t) {
-			ixj_ring_on(board);
+			ixj_ring_on(j);
 		} else {
-			ixj_ring_off(board);
+			ixj_ring_off(j);
 		}
 	}
 }
 
-static int ixj_ring(int board)
+static int ixj_ring(IXJ *j)
 {
 	char cntr;
 	unsigned long jif, det;
-	IXJ *j = &ixj[board];
 
 	j->flags.ringing = 1;
-	if (ixj_hookstate(board) & 1) {
-		ixj_ring_off(board);
+	if (ixj_hookstate(j) & 1) {
+		ixj_ring_off(j);
 		j->flags.ringing = 0;
 		return 1;
 	}
 	det = 0;
 	for (cntr = 0; cntr < j->maxrings; cntr++) {
 		jif = jiffies + (1 * hertz);
-		ixj_ring_on(board);
+		ixj_ring_on(j);
 		while (time_before(jiffies, jif)) {
-			if (ixj_hookstate(board) & 1) {
-				ixj_ring_off(board);
+			if (ixj_hookstate(j) & 1) {
+				ixj_ring_off(j);
 				j->flags.ringing = 0;
 				return 1;
 			}
@@ -1372,9 +1360,9 @@
 				break;
 		}
 		jif = jiffies + (3 * hertz);
-		ixj_ring_off(board);
+		ixj_ring_off(j);
 		while (time_before(jiffies, jif)) {
-			if (ixj_hookstate(board) & 1) {
+			if (ixj_hookstate(j) & 1) {
 				det = jiffies + (hertz / 100);
 				while (time_before(jiffies, det)) {
 					set_current_state(TASK_INTERRUPTIBLE);
@@ -1382,7 +1370,7 @@
 					if (signal_pending(current))
 						break;
 				}
-				if (ixj_hookstate(board) & 1) {
+				if (ixj_hookstate(j) & 1) {
 					j->flags.ringing = 0;
 					return 1;
 				}
@@ -1393,14 +1381,17 @@
 				break;
 		}
 	}
-	ixj_ring_off(board);
+	ixj_ring_off(j);
 	j->flags.ringing = 0;
 	return 0;
 }
 
 int ixj_open(struct phone_device *p, struct file *file_p)
 {
-	IXJ *j = file_p->private_data = &ixj[p->board];
+	IXJ *j = file_p->private_data = ixj[p->board];
+
+	if (j == NULL)
+		return -ENODEV;
 
 	if (!j->DSPbase)
 		return -ENODEV;
@@ -1424,14 +1415,13 @@
 		}
 	}
 
-	if (j->cardtype == 600) {
+	if (j->cardtype == QTI_PHONECARD) {
 		j->pslic.bits.powerdown = 0;
 		j->psccr.bits.dev = 3;
 		j->psccr.bits.rw = 0;
 		outw_p(j->psccr.byte << 8 | j->pslic.byte, j->XILINXbase + 0x00);
-		ixj_PCcontrol_wait(p->board);
+		ixj_PCcontrol_wait(j);
 	}
-	MOD_INC_USE_COUNT;
 
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Opening board %d\n", p->board);
@@ -1443,25 +1433,22 @@
 int ixj_release(struct inode *inode, struct file *file_p)
 {
 	IXJ_TONE ti;
-//	int board = NUM(inode->i_rdev);
+	int cnt;
 	IXJ *j = file_p->private_data;
-	int board = j->p.board;
-//	IXJ *j = &ixj[board];
 
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Closing board %d\n", NUM(inode->i_rdev));
 
-	daa_set_mode(board, SOP_PU_SLEEP);
-	if (j->cardtype == 600)
-		ixj_set_port(board, PORT_SPEAKER);
+	if (j->cardtype == QTI_PHONECARD)
+		ixj_set_port(j, PORT_SPEAKER);
 	else
-		ixj_set_port(board, PORT_POTS);
-	aec_stop(board);
-	ixj_play_stop(board);
-	ixj_record_stop(board);
-	set_play_volume(board, 0x100);
-	set_rec_volume(board, 0x100);
-	ixj_ring_off(board);
+		ixj_set_port(j, PORT_POTS);
+	aec_stop(j);
+	ixj_play_stop(j);
+	ixj_record_stop(j);
+	set_play_volume(j, 0x100);
+	set_rec_volume(j, 0x100);
+	ixj_ring_off(j);
 
 	// Restore the tone table to default settings.
 	ti.tone_index = 10;
@@ -1484,97 +1471,114 @@
 	ti.freq0 = hz800;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 14;
 	ti.gain0 = 1;
 	ti.freq0 = hz1000;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 15;
 	ti.gain0 = 1;
 	ti.freq0 = hz1250;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 16;
 	ti.gain0 = 1;
 	ti.freq0 = hz950;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 17;
 	ti.gain0 = 1;
 	ti.freq0 = hz1100;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 18;
 	ti.gain0 = 1;
 	ti.freq0 = hz1400;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 19;
 	ti.gain0 = 1;
 	ti.freq0 = hz1500;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 20;
 	ti.gain0 = 1;
 	ti.freq0 = hz1600;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 21;
 	ti.gain0 = 1;
 	ti.freq0 = hz1800;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 22;
 	ti.gain0 = 1;
 	ti.freq0 = hz2100;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 23;
 	ti.gain0 = 1;
 	ti.freq0 = hz1300;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 24;
 	ti.gain0 = 1;
 	ti.freq0 = hz2450;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 25;
 	ti.gain0 = 1;
 	ti.freq0 = hz350;
 	ti.gain1 = 0;
 	ti.freq1 = hz440;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 26;
 	ti.gain0 = 1;
 	ti.freq0 = hz440;
 	ti.gain1 = 0;
 	ti.freq1 = hz480;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 	ti.tone_index = 27;
 	ti.gain0 = 1;
 	ti.freq0 = hz480;
 	ti.gain1 = 0;
 	ti.freq1 = hz620;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 
-	idle(board);
+	set_rec_depth(j, 2);	// Set Record Channel Limit to 2 frames
 
-//        if(j->cardtype == 600) { // && j->flags.pcmciasct == 1 && j->readers == 1 && j->writers == 1) {
-	SLIC_SetState(PLD_SLIC_STATE_OC, board);
-//      }
+	set_play_depth(j, 2);	// Set Playback Channel Limit to 2 frames
+
+	j->ex.bits.dtmf_ready = 0;
+	j->dtmf_state = 0;
+	j->dtmf_wp = j->dtmf_rp = 0;
+	j->rec_mode = j->play_mode = -1;
+	j->flags.ringing = 0;
+	j->maxrings = MAXRINGS;
+	j->ring_cadence = USA_RING_CADENCE;
+	j->drybuffer = 0;
+	j->winktime = 320;
+	j->flags.dtmf_oob = 0;
+	for (cnt = 0; cnt < 4; cnt++)
+		j->cadence_f[cnt].enable = 0;
+
+	idle(j);
+
+	if(j->cardtype == QTI_PHONECARD) {
+		SLIC_SetState(PLD_SLIC_STATE_OC, j);
+	}
 
 	if (file_p->f_mode & FMODE_READ)
 		j->readers--;
@@ -1596,24 +1600,23 @@
 	j->flags.cidsent = j->flags.cidring = 0;
 	ixj_fasync(-1, file_p, 0);	// remove from list of async notification
 
-	if(j->cardtype == 300 && !j->readers && !j->writers) {
-		ixj_set_port(board, PORT_PSTN);
-		ixj_set_pots(board, 1);
+	if(j->cardtype == QTI_LINEJACK && !j->readers && !j->writers) {
+		ixj_set_port(j, PORT_PSTN);
+		daa_set_mode(j, SOP_PU_SLEEP);
+		ixj_set_pots(j, 1);
 	}
-	ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+	ixj_WriteDSPCommand(0x0FE3, j);	// Put the DSP in 1/5 power mode.
 
 	file_p->private_data = NULL;
-	MOD_DEC_USE_COUNT;
 	return 0;
 }
 
-static int read_filters(int board)
+static int read_filters(IXJ *j)
 {
 	unsigned short fc, cnt;
 	int var;
-	IXJ *j = &ixj[board];
 
-	if (ixj_WriteDSPCommand(0x5144, board))
+	if (ixj_WriteDSPCommand(0x5144, j))
 		return -1;
 
 	fc = j->ssr.high << 8 | j->ssr.low;
@@ -1628,10 +1631,10 @@
 	var = 10;
 
 	for (cnt = 0; cnt < 4; cnt++) {
-		if (ixj_WriteDSPCommand(0x5154 + cnt, board))
+		if (ixj_WriteDSPCommand(0x5154 + cnt, j))
 			return -1;
 
-		if (ixj_WriteDSPCommand(0x515C, board))
+		if (ixj_WriteDSPCommand(0x515C, j))
 			return -1;
 
 		j->filter_hist[cnt] = j->ssr.high << 8 | j->ssr.low;
@@ -1756,17 +1759,14 @@
 	return 0;
 }
 
-static int LineMonitor(int board)
+static int LineMonitor(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	if (j->dtmf_proc) {
 		return -1;
 	}
 	j->dtmf_proc = 1;
 
-	if (ixj_WriteDSPCommand(0x7000, board))		// Line Monitor
-
+	if (ixj_WriteDSPCommand(0x7000, j))		// Line Monitor
 		return -1;
 
 	j->dtmf.bytes.high = j->ssr.high;
@@ -1797,9 +1797,12 @@
 ssize_t ixj_read(struct file * file_p, char *buf, size_t length, loff_t * ppos)
 {
 	unsigned long i = *ppos;
-	IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+	IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
 	DECLARE_WAITQUEUE(wait, current);
 
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
+
 	if (j->flags.inread)
 		return -EALREADY;
 
@@ -1823,7 +1826,7 @@
 			j->flags.inread = 0;
 			return -EAGAIN;
 		}
-		if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) {
+		if (!ixj_hookstate(j)) {
 			set_current_state(TASK_RUNNING);
 			remove_wait_queue(&j->read_q, &wait);
 			j->flags.inread = 0;
@@ -1857,7 +1860,10 @@
 {
 	int pre_retval;
 	ssize_t read_retval = 0;
-	IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+	IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
 
 	pre_retval = ixj_PreRead(j, 0L);
 	switch (pre_retval) {
@@ -1883,6 +1889,9 @@
 	IXJ *j = file_p->private_data;
 	DECLARE_WAITQUEUE(wait, current);
 
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
+
 	if (j->flags.inwrite)
 		return -EALREADY;
 
@@ -1907,7 +1916,7 @@
 			j->flags.inwrite = 0;
 			return -EAGAIN;
 		}
-		if (!ixj_hookstate(NUM(file_p->f_dentry->d_inode->i_rdev))) {
+		if (!ixj_hookstate(j)) {
 			set_current_state(TASK_RUNNING);
 			remove_wait_queue(&j->write_q, &wait);
 			j->flags.inwrite = 0;
@@ -1938,7 +1947,10 @@
 {
 	int pre_retval;
 	ssize_t write_retval = 0;
-	IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+	IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
 
 	pre_retval = ixj_PreWrite(j, 0L);
 	switch (pre_retval) {
@@ -1946,14 +1958,14 @@
 		write_retval = ixj_write(file_p, buf, count, ppos);
 		if (write_retval != -EFAULT) {
 			ixj_PostWrite(j, 0L);
-			j->write_buffer_wp += count;
+			j->write_buffer_wp += write_retval;
 			j->write_buffers_empty--;
 		}
 		break;
 	case NOPOST:
 		write_retval = ixj_write(file_p, buf, count, ppos);
 		if (write_retval != -EFAULT) {
-			j->write_buffer_wp += count;
+			j->write_buffer_wp += write_retval;
 			j->write_buffers_empty--;
 		}
 		break;
@@ -1966,16 +1978,15 @@
 	return write_retval;
 }
 
-static void ixj_read_frame(int board)
+static void ixj_read_frame(IXJ *j)
 {
 	int cnt, dly;
-	IXJ *j = &ixj[board];
 
 	if (j->read_buffer) {
 		for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
-			if (!(cnt % 16) && !IsRxReady(board)) {
+			if (!(cnt % 16) && !IsRxReady(j)) {
 				dly = 0;
-				while (!IsRxReady(board)) {
+				while (!IsRxReady(j)) {
 					if (dly++ > 5) {
 						dly = 0;
 						break;
@@ -1993,11 +2004,19 @@
 		}
 		++j->framesread;
 		if (j->intercom != -1) {
-			if (IsTxReady(j->intercom)) {
+			IXJ *icom = ixj[j->intercom];
+
+			if (icom == NULL) { /* shouldn't happen! */
+				printk(KERN_ERR "ixj_read_frame(): j->intercom = %d = NULL!",
+				       j->intercom);
+				return;
+			}
+
+			if (IsTxReady(icom)) {
 				for (cnt = 0; cnt < j->rec_frame_size * 2; cnt += 2) {
-					if (!(cnt % 16) && !IsTxReady(board)) {
+					if (!(cnt % 16) && !IsTxReady(j)) {
 						dly = 0;
-						while (!IsTxReady(board)) {
+						while (!IsTxReady(j)) {
 							if (dly++ > 5) {
 								dly = 0;
 								break;
@@ -2005,10 +2024,10 @@
 							udelay(10);
 						}
 					}
-					outb_p(*(j->read_buffer + cnt), ixj[j->intercom].DSPbase + 0x0C);
-					outb_p(*(j->read_buffer + cnt + 1), ixj[j->intercom].DSPbase + 0x0D);
+					outb_p(*(j->read_buffer + cnt), icom->DSPbase + 0x0C);
+					outb_p(*(j->read_buffer + cnt + 1), icom->DSPbase + 0x0D);
 				}
-				++ixj[j->intercom].frameswritten;
+				++icom->frameswritten;
 			}
 		} else {
 			j->read_buffer_ready = 1;
@@ -2016,7 +2035,7 @@
 
 			wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
 
-			ixj_kill_fasync(board, POLL_OUT);
+			ixj_kill_fasync(j, POLL_IN);
 		}
 	}
 }
@@ -2078,16 +2097,15 @@
 };
 
 
-static void ixj_write_cid_bit(int board, int bit)
+static void ixj_write_cid_bit(IXJ *j, int bit)
 {
 	int dly;
 	IXJ_WORD dat;
-	IXJ *j = &ixj[board];
 
 	while (j->fskcnt < 20) {
-		if (!IsTxReady(board)) {
+		if (!IsTxReady(j)) {
 			dly = 0;
-			while (!IsTxReady(board)) {
+			while (!IsTxReady(j)) {
 				if (dly++ > 5) {
 					dly = 0;
 					//      break;
@@ -2111,7 +2129,7 @@
 
 }
 
-static void ixj_write_cid_byte(int board, char byte)
+static void ixj_write_cid_byte(IXJ *board, char byte)
 {
 	IXJ_CBYTE cb;
 
@@ -2129,7 +2147,7 @@
 	ixj_write_cid_bit(board, 1);
 }
 
-static void ixj_write_cid_seize(int board)
+static void ixj_write_cid_seize(IXJ *board)
 {
 	int cnt;
 
@@ -2142,7 +2160,7 @@
 	}
 }
 
-static void ixj_write_cidcw_seize(int board)
+static void ixj_write_cidcw_seize(IXJ *board)
 {
 	int cnt;
 
@@ -2151,7 +2169,7 @@
 	}
 }
 
-static int ixj_write_cid_string(int board, char *s, int checksum)
+static int ixj_write_cid_string(IXJ *board, char *s, int checksum)
 {
 	int cnt;
 
@@ -2162,15 +2180,14 @@
 	return checksum;
 }
 
-static void ixj_pad_fsk(int board, int pad)
+static void ixj_pad_fsk(IXJ *j, int pad)
 {
 	int cnt, dly;
-	IXJ *j = &ixj[board];
 
 	for (cnt = 0; cnt < pad; cnt++) {
-		if (!IsTxReady(board)) {
+		if (!IsTxReady(j)) {
 			dly = 0;
-			while (!IsTxReady(board)) {
+			while (!IsTxReady(j)) {
 				if (dly++ > 5) {
 					dly = 0;
 				}
@@ -2181,9 +2198,9 @@
 		outb_p(0x00, j->DSPbase + 0x0D);
 	}
 	for (cnt = 0; cnt < 720; cnt++) {
-		if (!IsTxReady(board)) {
+		if (!IsTxReady(j)) {
 			dly = 0;
-			while (!IsTxReady(board)) {
+			while (!IsTxReady(j)) {
 				if (dly++ > 5) {
 					dly = 0;
 				}
@@ -2195,10 +2212,8 @@
 	}
 }
 
-static void ixj_write_cid(int board)
+static void ixj_write_cid(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	char sdmf1[50];
 	char sdmf2[50];
 	char sdmf3[80];
@@ -2207,13 +2222,13 @@
 
 	int checksum = 0;
 
-	if (ixj[board].dsp.low == 0x20)
+	if (j->dsp.low == 0x20)
 		return;
 
-	ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt =
-	    ixj[board].fskdcnt = 0;
+	j->fskz = j->fskphase = j->fskcnt =
+	    j->fskdcnt = 0;
 
-	ixj[board].flags.cidplay = 1;
+	j->flags.cidplay = 1;
 
 	strcpy(sdmf1, j->cid_send.month);
 	strcat(sdmf1, j->cid_send.day);
@@ -2227,65 +2242,60 @@
 	len3 = strlen(sdmf3);
 	mdmflen = len1 + len2 + len3 + 6;
 
-	printk("CID Lengths = %d %d %d %d\n", len1, len2, len3, mdmflen);
-
-	set_base_frame(board, 30);
-	set_play_codec(board, LINEAR16);
+	set_base_frame(j, 30);
+	set_play_codec(j, LINEAR16);
 
-	if (ixj[board].port == PORT_POTS)
+	if (j->port == PORT_POTS)
 		if(!j->r_hook)
-			SLIC_SetState(PLD_SLIC_STATE_OHT, board);
+			SLIC_SetState(PLD_SLIC_STATE_OHT, j);
 
-	set_play_volume(board, 0x1B);
-	ixj_play_start(board);
-	ixj_write_cid_seize(board);
+	set_play_volume(j, 0x1B);
+	ixj_play_start(j);
+	ixj_write_cid_seize(j);
 
-	ixj_write_cid_byte(board, 0x80);
+	ixj_write_cid_byte(j, 0x80);
 	checksum = 0x80;
-	ixj_write_cid_byte(board, mdmflen);
+	ixj_write_cid_byte(j, mdmflen);
 	checksum = checksum + mdmflen;
 
-	ixj_write_cid_byte(board, 0x01);
+	ixj_write_cid_byte(j, 0x01);
 	checksum = checksum + 0x01;
-	ixj_write_cid_byte(board, len1);
+	ixj_write_cid_byte(j, len1);
 	checksum = checksum + len1;
-	checksum = ixj_write_cid_string(board, sdmf1, checksum);
+	checksum = ixj_write_cid_string(j, sdmf1, checksum);
 
-	ixj_write_cid_byte(board, 0x02);
+	ixj_write_cid_byte(j, 0x02);
 	checksum = checksum + 0x02;
-	ixj_write_cid_byte(board, len2);
+	ixj_write_cid_byte(j, len2);
 	checksum = checksum + len2;
-	checksum = ixj_write_cid_string(board, sdmf2, checksum);
+	checksum = ixj_write_cid_string(j, sdmf2, checksum);
 
-	ixj_write_cid_byte(board, 0x07);
+	ixj_write_cid_byte(j, 0x07);
 	checksum = checksum + 0x07;
-	ixj_write_cid_byte(board, len3);
+	ixj_write_cid_byte(j, len3);
 	checksum = checksum + len3;
-	checksum = ixj_write_cid_string(board, sdmf3, checksum);
+	checksum = ixj_write_cid_string(j, sdmf3, checksum);
 
 	checksum %= 256;
 	checksum ^= 0xFF;
 	checksum += 1;
-	printk("14Checksum = %d\n", checksum);
 
-	ixj_write_cid_byte(board, (char) checksum);
+	ixj_write_cid_byte(j, (char) checksum);
 
 	pad = j->fskdcnt % 240;
 	if (pad) {
 		pad = 240 - pad;
 	}
-	ixj_pad_fsk(board, pad);
-	SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
-	ixj[board].flags.cidplay = 0;
-	ixj_play_stop(board);
+	ixj_pad_fsk(j, pad);
+	SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
+	j->flags.cidplay = 0;
+	ixj_play_stop(j);
 }
 
-static void ixj_write_cidcw(int board)
+static void ixj_write_cidcw(IXJ *j)
 {
 	IXJ_TONE ti;
 
-	IXJ *j = &ixj[board];
-
 	char sdmf1[50];
 	char sdmf2[50];
 	char sdmf3[80];
@@ -2294,37 +2304,37 @@
 
 	int checksum = 0;
 
-	if (ixj[board].dsp.low == 0x20)
+	if (j->dsp.low == 0x20)
 		return;
 
-	ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = ixj[board].fskdcnt = 0;
+	j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0;
 
-	ixj[board].flags.cidplay = 1;
+	j->flags.cidplay = 1;
 
 	ti.tone_index = 23;
 	ti.gain0 = 1;
 	ti.freq0 = hz440;
 	ti.gain1 = 0;
 	ti.freq1 = 0;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 
 	ti.tone_index = 24;
 	ti.gain0 = 1;
 	ti.freq0 = hz2130;
 	ti.gain1 = 0;
 	ti.freq1 = hz2750;
-	ixj_init_tone(board, &ti);
+	ixj_init_tone(j, &ti);
 
-	ixj_set_tone_on(1200, board);
-	ixj_play_tone(board, 23);
+	ixj_set_tone_on(1200, j);
+	ixj_play_tone(j, 23);
 
 	while(j->tone_state) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
 	}
 
-	ixj_set_tone_on(320, board);
-	ixj_play_tone(board, 24);
+	ixj_set_tone_on(320, j);
+	ixj_play_tone(j, 24);
 
 	while(j->tone_state) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -2354,10 +2364,8 @@
 	len3 = strlen(sdmf3);
 	mdmflen = len1 + len2 + len3 + 6;
 
-	printk("CID Lengths = %d %d %d %d\n", len1, len2, len3, mdmflen);
-
 	j->cid_play_codec = j->play_codec;
-	ixj_play_stop(board);
+	ixj_play_stop(j);
 
 	switch(j->baseframe.low) {
 		case 0xA0:
@@ -2370,99 +2378,96 @@
 			j->cid_base_frame_size = 30;
 			break;
 	}
-	set_base_frame(board, 30);
-	set_play_codec(board, LINEAR16);
+	set_base_frame(j, 30);
+	set_play_codec(j, LINEAR16);
 
-	set_play_volume(board, 0x1B);
-	ixj_play_start(board);
-	ixj_write_cidcw_seize(board);
+	set_play_volume(j, 0x1B);
+	ixj_play_start(j);
+	ixj_write_cidcw_seize(j);
 
-	ixj_write_cid_byte(board, 0x80);
+	ixj_write_cid_byte(j, 0x80);
 	checksum = 0x80;
-	ixj_write_cid_byte(board, mdmflen);
+	ixj_write_cid_byte(j, mdmflen);
 	checksum = checksum + mdmflen;
 
-	ixj_write_cid_byte(board, 0x01);
+	ixj_write_cid_byte(j, 0x01);
 	checksum = checksum + 0x01;
-	ixj_write_cid_byte(board, len1);
+	ixj_write_cid_byte(j, len1);
 	checksum = checksum + len1;
-	checksum = ixj_write_cid_string(board, sdmf1, checksum);
+	checksum = ixj_write_cid_string(j, sdmf1, checksum);
 
-	ixj_write_cid_byte(board, 0x02);
+	ixj_write_cid_byte(j, 0x02);
 	checksum = checksum + 0x02;
-	ixj_write_cid_byte(board, len2);
+	ixj_write_cid_byte(j, len2);
 	checksum = checksum + len2;
-	checksum = ixj_write_cid_string(board, sdmf2, checksum);
+	checksum = ixj_write_cid_string(j, sdmf2, checksum);
 
-	ixj_write_cid_byte(board, 0x07);
+	ixj_write_cid_byte(j, 0x07);
 	checksum = checksum + 0x07;
-	ixj_write_cid_byte(board, len3);
+	ixj_write_cid_byte(j, len3);
 	checksum = checksum + len3;
-	checksum = ixj_write_cid_string(board, sdmf3, checksum);
+	checksum = ixj_write_cid_string(j, sdmf3, checksum);
 
 	checksum %= 256;
 	checksum ^= 0xFF;
 	checksum += 1;
-	printk("14Checksum = %d\n", checksum);
 
-	ixj_write_cid_byte(board, (char) checksum);
+	ixj_write_cid_byte(j, (char) checksum);
 
 	pad = j->fskdcnt % 240;
 	if (pad) {
 		pad = 240 - pad;
 	}
-	ixj_pad_fsk(board, pad);
-	ixj[board].flags.cidplay = 0;
-	ixj_play_stop(board);
+	ixj_pad_fsk(j, pad);
+	j->flags.cidplay = 0;
+	ixj_play_stop(j);
 
-	set_base_frame(board, j->cid_base_frame_size);
-	set_play_codec(board, j->cid_play_codec);
+	set_base_frame(j, j->cid_base_frame_size);
+	set_play_codec(j, j->cid_play_codec);
 }
 
-static void ixj_write_vmwi(int board, int msg)
+static void ixj_write_vmwi(IXJ *j, int msg)
 {
-	IXJ *j = &ixj[board];
-
 	char mdmflen;
 	int pad;
 
 	int checksum = 0;
 
-	if (ixj[board].dsp.low == 0x20)
+	if (j->dsp.low == 0x20)
 		return;
 
-	ixj[board].fskz = ixj[board].fskphase = ixj[board].fskcnt = ixj[board].fskdcnt = 0;
+	j->fskz = j->fskphase = j->fskcnt = j->fskdcnt = 0;
 
-	ixj[board].flags.cidplay = 1;
+	j->flags.cidplay = 1;
 
 	mdmflen = 3;
 
-	set_base_frame(board, 30);
-	set_play_codec(board, LINEAR16);
+	set_base_frame(j, 30);
+	set_play_codec(j, LINEAR16);
 
-	if (ixj[board].port == PORT_POTS)
-		SLIC_SetState(PLD_SLIC_STATE_OHT, board);
+	if (j->port == PORT_POTS)
+		SLIC_SetState(PLD_SLIC_STATE_OHT, j);
 
-	set_play_volume(board, 0x1B);
-	ixj_play_start(board);
-	ixj_write_cid_seize(board);
+	set_play_volume(j, 0x1B);
+	ixj_play_start(j);
+	ixj_write_cid_seize(j);
 
-	ixj_write_cid_byte(board, 0x82);
+	ixj_write_cid_byte(j, 0x82);
 	checksum = 0x82;
-	ixj_write_cid_byte(board, mdmflen);
+	ixj_write_cid_byte(j, mdmflen);
 	checksum = checksum + mdmflen;
 
-	ixj_write_cid_byte(board, 0x0B);
+	ixj_write_cid_byte(j, 0x0B);
 	checksum = checksum + 0x0B;
-	ixj_write_cid_byte(board, 1);
+	ixj_write_cid_byte(j, 1);
 	checksum = checksum + 1;
 
 	if(msg) {
-		ixj_write_cid_byte(board, 0xFF);
+		ixj_write_cid_byte(j, 0xFF);
 		checksum = checksum + 0xFF;
 	}
 	else {
-		ixj_write_cid_byte(board, 0x00);
+		ixj_write_cid_byte(j, 0x00);
 		checksum = checksum + 0x00;
 	}
 
@@ -2470,23 +2475,22 @@
 	checksum ^= 0xFF;
 	checksum += 1;
 
-	ixj_write_cid_byte(board, (char) checksum);
+	ixj_write_cid_byte(j, (char) checksum);
 
 	pad = j->fskdcnt % 240;
 	if (pad) {
 		pad = 240 - pad;
 	}
-	ixj_pad_fsk(board, pad);
-	SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
-	ixj[board].flags.cidplay = 0;
-	ixj_play_stop(board);
+	ixj_pad_fsk(j, pad);
+	SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
+	j->flags.cidplay = 0;
+	ixj_play_stop(j);
 }
 
-static void ixj_write_frame(int board)
+static void ixj_write_frame(IXJ *j)
 {
 	int cnt, frame_count, dly;
 	BYTES blankword;
-	IXJ *j = &ixj[board];
 
 	frame_count = 0;
 	if (j->write_buffer && j->write_buffers_empty < 2) {
@@ -2515,9 +2519,9 @@
 					break;
 				}
 				for (cnt = 0; cnt < 16; cnt++) {
-					if (!(cnt % 16) && !IsTxReady(board)) {
+					if (!(cnt % 16) && !IsTxReady(j)) {
 						dly = 0;
-						while (!IsTxReady(board)) {
+						while (!IsTxReady(j)) {
 							if (dly++ > 5) {
 								dly = 0;
 								break;
@@ -2531,9 +2535,9 @@
 				j->flags.play_first_frame = 0;
 			}
 			for (cnt = 0; cnt < j->play_frame_size * 2; cnt += 2) {
-				if (!(cnt % 16) && !IsTxReady(board)) {
+				if (!(cnt % 16) && !IsTxReady(j)) {
 					dly = 0;
-					while (!IsTxReady(board)) {
+					while (!IsTxReady(j)) {
 						if (dly++ > 5) {
 							dly = 0;
 							break;
@@ -2561,7 +2565,7 @@
 
 			wake_up_interruptible(&j->poll_q);	// Wake any blocked selects
 
-			ixj_kill_fasync(board, POLL_OUT);
+			ixj_kill_fasync(j, POLL_OUT);
 			++j->frameswritten;
 		}
 	} else {
@@ -2569,11 +2573,9 @@
 	}
 }
 
-static int idle(int board)
+static int idle(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
-	if (ixj_WriteDSPCommand(0x0000, board))		// DSP Idle
+	if (ixj_WriteDSPCommand(0x0000, j))		// DSP Idle
 
 		return 0;
 	if (j->ssr.high || j->ssr.low)
@@ -2582,15 +2584,14 @@
 		return 1;
 }
 
-static int set_base_frame(int board, int size)
+static int set_base_frame(IXJ *j, int size)
 {
 	unsigned short cmd;
 	int cnt;
-	IXJ *j = &ixj[board];
 
-	aec_stop(board);
+	aec_stop(j);
 	for (cnt = 0; cnt < 10; cnt++) {
-		if (idle(board))
+		if (idle(j))
 			break;
 	}
 	if (j->ssr.high || j->ssr.low)
@@ -2618,7 +2619,7 @@
 		else
 			return -1;
 	}
-	if (ixj_WriteDSPCommand(cmd, board)) {
+	if (ixj_WriteDSPCommand(cmd, j)) {
 		j->baseframe.high = j->baseframe.low = 0xFF;
 		return -1;
 	} else {
@@ -2628,10 +2629,9 @@
 	return size;
 }
 
-static int set_rec_codec(int board, int rate)
+static int set_rec_codec(IXJ *j, int rate)
 {
 	int retval = 0;
-	IXJ *j = &ixj[board];
 
 	j->rec_codec = rate;
 
@@ -2790,16 +2790,15 @@
 	return retval;
 }
 
-static int ixj_record_start(int board)
+static int ixj_record_start(IXJ *j)
 {
 	unsigned short cmd = 0x0000;
-	IXJ *j = &ixj[board];
 
 	if (j->read_buffer) {
-		ixj_record_stop(board);
+		ixj_record_stop(j);
 	}
 	j->flags.recording = 1;
-	ixj_WriteDSPCommand(0x0FE0, board);	// Put the DSP in full power mode.
+	ixj_WriteDSPCommand(0x0FE0, j);	// Put the DSP in full power mode.
 
 	if (!j->rec_mode) {
 		switch (j->rec_codec) {
@@ -2830,20 +2829,21 @@
 		default:
 			return 1;
 		}
-		if (ixj_WriteDSPCommand(cmd, board))
+		if (ixj_WriteDSPCommand(cmd, j))
 			return -1;
 	}
 	if (!j->read_buffer) {
 		if (!j->read_buffer)
 			j->read_buffer = kmalloc(j->rec_frame_size * 2, GFP_ATOMIC);
 		if (!j->read_buffer) {
-			printk("Read buffer allocation for ixj board %d failed!\n", board);
+			printk("Read buffer allocation for ixj board %d failed!\n",
+			       j->p.board);
 			return -ENOMEM;
 		}
 	}
 	j->read_buffer_size = j->rec_frame_size * 2;
 
-	if (ixj_WriteDSPCommand(0x5102, board))		// Set Poll sync mode
+	if (ixj_WriteDSPCommand(0x5102, j))		// Set Poll sync mode
 
 		return -1;
 
@@ -2889,149 +2889,140 @@
 		}
 		break;
 	}
-	if (ixj_WriteDSPCommand(cmd, board))
+	if (ixj_WriteDSPCommand(cmd, j))
 		return -1;
 
 	return 0;
 }
 
-static void ixj_record_stop(int board)
+static void ixj_record_stop(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	if (j->read_buffer) {
 		kfree(j->read_buffer);
 		j->read_buffer = NULL;
 		j->read_buffer_size = 0;
 	}
 	if (j->rec_mode > -1) {
-		ixj_WriteDSPCommand(0x5120, board);
+		ixj_WriteDSPCommand(0x5120, j);
 		j->rec_mode = -1;
 	}
 	j->flags.recording = 0;
 	if (!j->flags.playing)
-		ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+		ixj_WriteDSPCommand(0x0FE3, j);	// Put the DSP in 1/5 power mode.
 
 }
-static void ixj_vad(int board, int arg)
+static void ixj_vad(IXJ *j, int arg)
 {
 	if (arg)
-		ixj_WriteDSPCommand(0x513F, board);
+		ixj_WriteDSPCommand(0x513F, j);
 	else
-		ixj_WriteDSPCommand(0x513E, board);
+		ixj_WriteDSPCommand(0x513E, j);
 }
 
-static void set_rec_depth(int board, int depth)
+static void set_rec_depth(IXJ *j, int depth)
 {
 	if (depth > 60)
 		depth = 60;
 	if (depth < 0)
 		depth = 0;
-	ixj_WriteDSPCommand(0x5180 + depth, board);
+	ixj_WriteDSPCommand(0x5180 + depth, j);
 }
 
-static void set_rec_volume(int board, int volume)
+static void set_rec_volume(IXJ *j, int volume)
 {
-	ixj_WriteDSPCommand(0xCF03, board);
-	ixj_WriteDSPCommand(volume, board);
+	ixj_WriteDSPCommand(0xCF03, j);
+	ixj_WriteDSPCommand(volume, j);
 }
 
-static int get_rec_volume(int board)
+static int get_rec_volume(IXJ *j)
 {
-	ixj_WriteDSPCommand(0xCF03, board);
-	return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+	ixj_WriteDSPCommand(0xCF01, j);
+	return j->ssr.high << 8 | j->ssr.low;
 }
 
-static int get_rec_level(int board)
+static int get_rec_level(IXJ *j)
 {
 	int retval;
 
-	IXJ *j = &ixj[board];
-
-	ixj_WriteDSPCommand(0xCF88, board);
+	ixj_WriteDSPCommand(0xCF88, j);
 
 	retval = j->ssr.high << 8 | j->ssr.low;
 	retval = (retval * 256) / 240;
 	return retval;
 }
 
-static void ixj_aec_start(int board, int level)
+static void ixj_aec_start(IXJ *j, int level)
 {
-	IXJ *j = &ixj[board];
-
 	j->aec_level = level;
 	if (!level) {
-		aec_stop(board);
+		aec_stop(j);
 	} else {
 		if (j->rec_codec == G729 || j->play_codec == G729) {
-			ixj_WriteDSPCommand(0xE022, board);	// Move AEC filter buffer
+			ixj_WriteDSPCommand(0xE022, j);	// Move AEC filter buffer
 
-			ixj_WriteDSPCommand(0x0300, board);
+			ixj_WriteDSPCommand(0x0300, j);
 		}
-		ixj_WriteDSPCommand(0xB001, board);	// AEC On
+		ixj_WriteDSPCommand(0xB001, j);	// AEC On
 
-		ixj_WriteDSPCommand(0xE013, board);	// Advanced AEC C1
+		ixj_WriteDSPCommand(0xE013, j);	// Advanced AEC C1
 
 		switch (level) {
 		case AEC_LOW:
-			ixj_WriteDSPCommand(0x0000, board);	// Advanced AEC C2 = off
+			ixj_WriteDSPCommand(0x0000, j);	// Advanced AEC C2 = off
 
-			ixj_WriteDSPCommand(0xE011, board);
-			ixj_WriteDSPCommand(0xFFFF, board);
+			ixj_WriteDSPCommand(0xE011, j);
+			ixj_WriteDSPCommand(0xFFFF, j);
 			break;
 
 		case AEC_MED:
-			ixj_WriteDSPCommand(0x0600, board);	// Advanced AEC C2 = on medium
+			ixj_WriteDSPCommand(0x0600, j);	// Advanced AEC C2 = on medium
 
-			ixj_WriteDSPCommand(0xE011, board);
-			ixj_WriteDSPCommand(0x0080, board);
+			ixj_WriteDSPCommand(0xE011, j);
+			ixj_WriteDSPCommand(0x0080, j);
 			break;
 
 		case AEC_HIGH:
-			ixj_WriteDSPCommand(0x0C00, board);	// Advanced AEC C2 = on high
+			ixj_WriteDSPCommand(0x0C00, j);	// Advanced AEC C2 = on high
 
-			ixj_WriteDSPCommand(0xE011, board);
-			ixj_WriteDSPCommand(0x0080, board);
+			ixj_WriteDSPCommand(0xE011, j);
+			ixj_WriteDSPCommand(0x0080, j);
 			break;
 
 		case AEC_AUTO:
-			ixj_WriteDSPCommand(0x0002, board);	// Attenuation scaling factor of 2
+			ixj_WriteDSPCommand(0x0002, j);	// Attenuation scaling factor of 2
 
-			ixj_WriteDSPCommand(0xE011, board);
-			ixj_WriteDSPCommand(0x0100, board);	// Higher Threshold Floor
+			ixj_WriteDSPCommand(0xE011, j);
+			ixj_WriteDSPCommand(0x0100, j);	// Higher Threshold Floor
 
-			ixj_WriteDSPCommand(0xE012, board);	// Set Train and Lock
+			ixj_WriteDSPCommand(0xE012, j);	// Set Train and Lock
 
-			ixj_WriteDSPCommand(0x0023, board);
+			ixj_WriteDSPCommand(0x0023, j);
 
-			ixj_WriteDSPCommand(0xE014, board);
-			ixj_WriteDSPCommand(0x0003, board);	// Lock threashold at 3dB
+			ixj_WriteDSPCommand(0xE014, j);
+			ixj_WriteDSPCommand(0x0003, j);	// Lock threashold at 3dB
 
 			break;
 		}
 	}
 }
 
-static void aec_stop(int board)
+static void aec_stop(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	if (j->rec_codec == G729 || j->play_codec == G729) {
-		ixj_WriteDSPCommand(0xE022, board);	// Move AEC filter buffer back
+		ixj_WriteDSPCommand(0xE022, j);	// Move AEC filter buffer back
 
-		ixj_WriteDSPCommand(0x0700, board);
+		ixj_WriteDSPCommand(0x0700, j);
 	}
-	if (ixj[board].play_mode != -1 && ixj[board].rec_mode != -1)
+	if (j->play_mode != -1 && j->rec_mode != -1)
 	{
-		ixj_WriteDSPCommand(0xB002, board);	// AEC Stop
+		ixj_WriteDSPCommand(0xB002, j);	// AEC Stop
 
 	}
 }
 
-static int set_play_codec(int board, int rate)
+static int set_play_codec(IXJ *j, int rate)
 {
 	int retval = 0;
-	IXJ *j = &ixj[board];
 
 	j->play_codec = rate;
 
@@ -3190,16 +3181,15 @@
 	return retval;
 }
 
-static int ixj_play_start(int board)
+static int ixj_play_start(IXJ *j)
 {
 	unsigned short cmd = 0x0000;
-	IXJ *j = &ixj[board];
 
 	if (j->write_buffer) {
-		ixj_play_stop(board);
+		ixj_play_stop(j);
 	}
 	j->flags.playing = 1;
-	ixj_WriteDSPCommand(0x0FE0, board);	// Put the DSP in full power mode.
+	ixj_WriteDSPCommand(0x0FE0, j);	// Put the DSP in full power mode.
 
 	j->flags.play_first_frame = 1;
 	j->drybuffer = 0;
@@ -3233,12 +3223,13 @@
 		default:
 			return 1;
 		}
-		if (ixj_WriteDSPCommand(cmd, board))
+		if (ixj_WriteDSPCommand(cmd, j))
 			return -1;
 	}
 	j->write_buffer = kmalloc(j->play_frame_size * 2, GFP_ATOMIC);
 	if (!j->write_buffer) {
-		printk("Write buffer allocation for ixj board %d failed!\n", board);
+		printk("Write buffer allocation for ixj board %d failed!\n",
+		       j->p.board);
 		return -ENOMEM;
 	}
 	j->write_buffers_empty = 2;
@@ -3246,7 +3237,7 @@
 	j->write_buffer_end = j->write_buffer + j->play_frame_size * 2;
 	j->write_buffer_rp = j->write_buffer_wp = j->write_buffer;
 
-	if (ixj_WriteDSPCommand(0x5202, board))		// Set Poll sync mode
+	if (ixj_WriteDSPCommand(0x5202, j))		// Set Poll sync mode
 
 		return -1;
 
@@ -3283,56 +3274,47 @@
 		}
 		break;
 	}
-	if (ixj_WriteDSPCommand(cmd, board))
+	if (ixj_WriteDSPCommand(cmd, j))
 		return -1;
 
-	if (ixj_WriteDSPCommand(0x2000, board))		// Playback C2
+	if (ixj_WriteDSPCommand(0x2000, j))		// Playback C2
 
 		return -1;
 
-	if (ixj_WriteDSPCommand(0x2000 + ixj[board].play_frame_size, board))	// Playback C3
+	if (ixj_WriteDSPCommand(0x2000 + j->play_frame_size, j))	// Playback C3
 
 		return -1;
 
+
+	ixj_kill_fasync(j, POLL_OUT);
 	return 0;
 }
 
-static void ixj_play_stop(int board)
+static void ixj_play_stop(IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	if (j->write_buffer) {
 		kfree(j->write_buffer);
 		j->write_buffer = NULL;
 		j->write_buffer_size = 0;
 	}
 	if (j->play_mode > -1) {
-		ixj_WriteDSPCommand(0x5221, board);	// Stop playback and flush buffers.  8022 reference page 9-40
+		ixj_WriteDSPCommand(0x5221, j);	// Stop playback and flush buffers.  8022 reference page 9-40
 
 		j->play_mode = -1;
 	}
 	j->flags.playing = 0;
 	if (!j->flags.recording)
-		ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+		ixj_WriteDSPCommand(0x0FE3, j);	// Put the DSP in 1/5 power mode.
 
 }
 
-extern __inline__ void set_play_depth(int board, int depth)
-{
-	if (depth > 60)
-		depth = 60;
-	if (depth < 0)
-		depth = 0;
-	ixj_WriteDSPCommand(0x5280 + depth, board);
-}
-
-extern __inline__ int get_play_level(int board)
+extern __inline__ int get_play_level(IXJ *j)
 {
 	int retval;
 
-	ixj_WriteDSPCommand(0xCF8F, board); // 8022 Reference page 9-38
-	return ixj[board].ssr.high << 8 | ixj[board].ssr.low;
-	retval = ixj[board].ssr.high << 8 | ixj[board].ssr.low;
+	ixj_WriteDSPCommand(0xCF8F, j); // 8022 Reference page 9-38
+	return j->ssr.high << 8 | j->ssr.low;
+	retval = j->ssr.high << 8 | j->ssr.low;
 	retval = (retval * 256) / 240;
 	return retval;
 }
@@ -3340,7 +3322,10 @@
 static unsigned int ixj_poll(struct file *file_p, poll_table * wait)
 {
 	unsigned int mask = 0;
-	IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+	IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
 
 	poll_wait(file_p, &(j->poll_q), wait);
 	if (j->read_buffer_ready > 0)
@@ -3352,15 +3337,13 @@
 	return mask;
 }
 
-static int ixj_play_tone(int board, char tone)
+static int ixj_play_tone(IXJ *j, char tone)
 {
-	IXJ *j = &ixj[board];
-
-	if (!j->tone_state)
-		idle(board);
+	if (!j->tone_state && j->dsp.low == 0x20)
+		idle(j);
 
 	j->tone_index = tone;
-	if (ixj_WriteDSPCommand(0x6000 + j->tone_index, board))
+	if (ixj_WriteDSPCommand(0x6000 + j->tone_index, j))
 		return -1;
 
 	if (!j->tone_state) {
@@ -3371,26 +3354,23 @@
 	return 0;
 }
 
-static int ixj_set_tone_on(unsigned short arg, int board)
+static int ixj_set_tone_on(unsigned short arg, IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	j->tone_on_time = arg;
 
-	if (ixj_WriteDSPCommand(0x6E04, board))		// Set Tone On Period
+	if (ixj_WriteDSPCommand(0x6E04, j))		// Set Tone On Period
 
 		return -1;
 
-	if (ixj_WriteDSPCommand(arg, board))
+	if (ixj_WriteDSPCommand(arg, j))
 		return -1;
 
 	return 0;
 }
 
-static int SCI_WaitHighSCI(int board)
+static int SCI_WaitHighSCI(IXJ *j)
 {
 	int cnt;
-	IXJ *j = &ixj[board];
 
 	j->pld_scrr.byte = inb_p(j->XILINXbase);
 	if (!j->pld_scrr.bits.sci) {
@@ -3408,10 +3388,9 @@
 		return 1;
 }
 
-static int SCI_WaitLowSCI(int board)
+static int SCI_WaitLowSCI(IXJ *j)
 {
 	int cnt;
-	IXJ *j = &ixj[board];
 
 	j->pld_scrr.byte = inb_p(j->XILINXbase);
 	if (j->pld_scrr.bits.sci) {
@@ -3429,10 +3408,8 @@
 		return 1;
 }
 
-static int SCI_Control(int board, int control)
+static int SCI_Control(IXJ *j, int control)
 {
-	IXJ *j = &ixj[board];
-
 	switch (control) {
 	case SCI_End:
 		j->pld_scrw.bits.c0 = 0;	// Set PLD Serial control interface
@@ -3471,7 +3448,7 @@
 	case SCI_Enable_DAA:
 	case SCI_Enable_Mixer:
 	case SCI_Enable_EEPROM:
-		if (!SCI_WaitHighSCI(board))
+		if (!SCI_WaitHighSCI(j))
 			return 0;
 		break;
 	default:
@@ -3481,21 +3458,20 @@
 	return 1;
 }
 
-static int SCI_Prepare(int board)
+static int SCI_Prepare(IXJ *j)
 {
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
 
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	return 1;
 }
 
-static int ixj_mixer(long val, int board)
+static int ixj_mixer(long val, IXJ *j)
 {
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 
 	bytes.high = (val & 0xFF00) >> 8;
 	bytes.low = val & 0x00FF;
@@ -3504,28 +3480,25 @@
 
 	outb_p(bytes.low, j->XILINXbase + 0x02);	// Load Mixer Data
 
-	SCI_Control(board, SCI_Enable_Mixer);
+	SCI_Control(j, SCI_Enable_Mixer);
 
-	SCI_Control(board, SCI_End);
+	SCI_Control(j, SCI_End);
 
 	return 0;
 }
 
-static int daa_load(BYTES * p_bytes, int board)
+static int daa_load(BYTES * p_bytes, IXJ *j)
 {
-	IXJ *j = &ixj[board];
-
 	outb_p(p_bytes->high, j->XILINXbase + 0x03);
 	outb_p(p_bytes->low, j->XILINXbase + 0x02);
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
 	else
 		return 1;
 }
 
-static int ixj_daa_cr4(int board, char reg)
+static int ixj_daa_cr4(IXJ *j, char reg)
 {
-	IXJ *j = &ixj[board];
 	BYTES bytes;
 
 	switch (j->daa_mode) {
@@ -3562,21 +3535,20 @@
 
 	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg;
 
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	return 1;
 }
 
-static char daa_int_read(int board)
+static char daa_int_read(IXJ *j)
 {
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x38;
@@ -3584,7 +3556,7 @@
 	outb_p(bytes.high, j->XILINXbase + 0x03);
 	outb_p(bytes.low, j->XILINXbase + 0x02);
 
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
 
 	bytes.high = inb_p(j->XILINXbase + 0x03);
@@ -3594,9 +3566,9 @@
 			printk("Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low);
 		return 0;
 	}
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
 
 	bytes.high = inb_p(j->XILINXbase + 0x03);
@@ -3606,13 +3578,12 @@
 	return 1;
 }
 
-static int ixj_daa_cid_reset(int board)
+static int ixj_daa_cid_reset(IXJ *j)
 {
 	int i;
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x58;
@@ -3620,10 +3591,10 @@
 	outb_p(bytes.high, j->XILINXbase + 0x03);
 	outb_p(bytes.low, j->XILINXbase + 0x02);
 
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
 
-	if (!SCI_WaitHighSCI(board))
+	if (!SCI_WaitHighSCI(j))
 		return 0;
 
 	for (i = 0; i < ALISDAA_CALLERID_SIZE - 1; i += 2) {
@@ -3633,29 +3604,28 @@
 		if (i < ALISDAA_CALLERID_SIZE - 1)
 			outb_p(bytes.low, j->XILINXbase + 0x02);
 
-		if (!SCI_Control(board, SCI_Enable_DAA))
+		if (!SCI_Control(j, SCI_Enable_DAA))
 			return 0;
 
-		if (!SCI_WaitHighSCI(board))
+		if (!SCI_WaitHighSCI(j))
 			return 0;
 
 	}
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
 
 	return 1;
 }
 
-static int ixj_daa_cid_read(int board)
+static int ixj_daa_cid_read(IXJ *j)
 {
 	int i;
 	BYTES bytes;
 	char CID[ALISDAA_CALLERID_SIZE], mContinue;
 	char *pIn, *pOut;
-	IXJ *j = &ixj[board];
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x78;
@@ -3663,10 +3633,10 @@
 	outb_p(bytes.high, j->XILINXbase + 0x03);
 	outb_p(bytes.low, j->XILINXbase + 0x02);
 
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
 
-	if (!SCI_WaitHighSCI(board))
+	if (!SCI_WaitHighSCI(j))
 		return 0;
 
 	bytes.high = inb_p(j->XILINXbase + 0x03);
@@ -3681,17 +3651,17 @@
 		outb_p(bytes.high, j->XILINXbase + 0x03);
 		outb_p(bytes.low, j->XILINXbase + 0x02);
 
-		if (!SCI_Control(board, SCI_Enable_DAA))
+		if (!SCI_Control(j, SCI_Enable_DAA))
 			return 0;
 
-		if (!SCI_WaitHighSCI(board))
+		if (!SCI_WaitHighSCI(j))
 			return 0;
 
 		CID[i + 0] = inb_p(j->XILINXbase + 0x03);
 		CID[i + 1] = inb_p(j->XILINXbase + 0x02);
 	}
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
 
 	pIn = CID;
@@ -3733,16 +3703,15 @@
 	pOut += 1;
 	strncpy(j->cid.name, pOut, j->cid.namelen);
 
-	ixj_daa_cid_reset(board);
+	ixj_daa_cid_reset(j);
 	return 1;
 }
 
-static char daa_get_version(int board)
+static char daa_get_version(IXJ *j)
 {
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x35;
@@ -3750,7 +3719,7 @@
 	outb_p(bytes.high, j->XILINXbase + 0x03);
 	outb_p(bytes.low, j->XILINXbase + 0x02);
 
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
 
 	bytes.high = inb_p(j->XILINXbase + 0x03);
@@ -3760,10 +3729,10 @@
 			printk("DAA Get Version Cannot read DAA ID Byte high = %d low = %d\n", bytes.high, bytes.low);
 		return 0;
 	}
-	if (!SCI_Control(board, SCI_Enable_DAA))
+	if (!SCI_Control(j, SCI_Enable_DAA))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
 
 	bytes.high = inb_p(j->XILINXbase + 0x03);
@@ -3774,7 +3743,7 @@
 	return bytes.high;
 }
 
-static int daa_set_mode(int board, int mode)
+static int daa_set_mode(IXJ *j, int mode)
 {
 	// NOTE:
 	//      The DAA *MUST* be in the conversation mode if the
@@ -3791,9 +3760,8 @@
 	//
 
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	switch (mode) {
@@ -3807,8 +3775,8 @@
 			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 			bytes.high = 0x10;
 			bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-			daa_load(&bytes, board);
-			if (!SCI_Prepare(board))
+			daa_load(&bytes, j);
+			if (!SCI_Prepare(j))
 				return 0;
 		}
 		j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
@@ -3818,8 +3786,8 @@
 		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 		bytes.high = 0x10;
 		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, board);
-		if (!SCI_Prepare(board))
+		daa_load(&bytes, j);
+		if (!SCI_Prepare(j))
 			return 0;
 
 		j->daa_mode = SOP_PU_SLEEP;
@@ -3838,19 +3806,21 @@
 		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 		bytes.high = 0x50;
 		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, board);
-		if (!SCI_Prepare(board))
+		daa_load(&bytes, j);
+		if (!SCI_Prepare(j))
 			return 0;
 		j->daa_mode = SOP_PU_RINGING;
 		break;
 	case SOP_PU_CONVERSATION:
 		bytes.high = 0x90;
 		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, board);
-		if (!SCI_Prepare(board))
+		daa_load(&bytes, j);
+		if (!SCI_Prepare(j))
 			return 0;
 		j->pld_slicw.bits.rly2 = 1;
 		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+		j->pld_scrw.bits.led1 = 0;
+		j->pld_scrw.bits.led2 = 1;
 		j->pld_scrw.bits.daafsyncen = 1;	// Turn on DAA Frame Sync
 
 		outb_p(j->pld_scrw.byte, j->XILINXbase);
@@ -3866,8 +3836,8 @@
 		outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 		bytes.high = 0xD0;
 		bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-		daa_load(&bytes, board);
-		if (!SCI_Prepare(board))
+		daa_load(&bytes, j);
+		if (!SCI_Prepare(j))
 			return 0;
 		j->daa_mode = SOP_PU_PULSEDIALING;
 		break;
@@ -3877,555 +3847,552 @@
 	return 1;
 }
 
-static int ixj_daa_write(int board)
+static int ixj_daa_write(IXJ *j)
 {
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x14;
 	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr4.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr3.reg;
 	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr2.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.SOP_REGS.SOP.cr1.reg;
 	bytes.low = j->m_DAAShadowRegs.SOP_REGS.SOP.cr0.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x1F;
 	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr7.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.XOP_xr6_W.reg;
 	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr5.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr4.reg;
 	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr3.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.XOP_REGS.XOP.xr2.reg;
 	bytes.low = j->m_DAAShadowRegs.XOP_REGS.XOP.xr1.reg;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.XOP_xr0_W.reg;
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Prepare(board))
+	if (!SCI_Prepare(j))
 		return 0;
 
 	bytes.high = 0x00;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_1[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x01;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_2[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x02;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.THFilterCoeff_3[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x03;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_1[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x04;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_1[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x05;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.IMFilterCoeff_2[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x06;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.RingerImpendance_2[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x07;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRRFilterCoeff[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x08;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.FRXFilterCoeff[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x09;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.ARFilterCoeff[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x0A;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.AXFilterCoeff[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x0B;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone1Coeff[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x0C;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x0D;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.LevelmeteringRinging[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x0E;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID1stTone[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
-	if (!SCI_WaitLowSCI(board))
+	if (!SCI_WaitLowSCI(j))
 		return 0;
 
 	bytes.high = 0x0F;
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[7];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[6];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[5];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[4];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[3];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[2];
 	bytes.low = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[1];
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	bytes.high = j->m_DAAShadowRegs.COP_REGS.COP.CallerID2ndTone[0];
 	bytes.low = 0x00;
-	if (!daa_load(&bytes, board))
+	if (!daa_load(&bytes, j))
 		return 0;
 
 	udelay(32);
 	j->pld_scrr.byte = inb_p(j->XILINXbase);
-	if (!SCI_Control(board, SCI_End))
+	if (!SCI_Control(j, SCI_End))
 		return 0;
 
 	return 1;
 }
 
-int ixj_set_tone_off(unsigned short arg, int board)
+int ixj_set_tone_off(unsigned short arg, IXJ *j)
 {
-	ixj[board].tone_off_time = arg;
-	if (ixj_WriteDSPCommand(0x6E05, board))		// Set Tone Off Period
+	j->tone_off_time = arg;
+	if (ixj_WriteDSPCommand(0x6E05, j))		// Set Tone Off Period
 
 		return -1;
-	if (ixj_WriteDSPCommand(arg, board))
+	if (ixj_WriteDSPCommand(arg, j))
 		return -1;
 	return 0;
 }
 
-static int ixj_get_tone_on(int board)
+static int ixj_get_tone_on(IXJ *j)
 {
-	if (ixj_WriteDSPCommand(0x6E06, board))		// Get Tone On Period
+	if (ixj_WriteDSPCommand(0x6E06, j))		// Get Tone On Period
 
 		return -1;
 	return 0;
 }
 
-static int ixj_get_tone_off(int board)
+static int ixj_get_tone_off(IXJ *j)
 {
-	if (ixj_WriteDSPCommand(0x6E07, board))		// Get Tone Off Period
-
+	if (ixj_WriteDSPCommand(0x6E07, j))		// Get Tone Off Period
 		return -1;
 	return 0;
 }
 
-static void ixj_busytone(int board)
+static void ixj_busytone(IXJ *j)
+{
+	j->flags.ringback = 0;
+	j->flags.dialtone = 0;
+	j->flags.busytone = 1;
+	ixj_set_tone_on(0x07D0, j);
+	ixj_set_tone_off(0x07D0, j);
+	ixj_play_tone(j, 27);
+}
+
+static void ixj_dialtone(IXJ *j)
 {
-	ixj[board].flags.ringback = 0;
-	ixj[board].flags.dialtone = 0;
-	ixj[board].flags.busytone = 1;
-	ixj_set_tone_on(0x07D0, board);
-	ixj_set_tone_off(0x07D0, board);
-	ixj_play_tone(board, 27);
-}
-
-static void ixj_dialtone(int board)
-{
-	ixj[board].flags.ringback = 0;
-	ixj[board].flags.dialtone = 1;
-	ixj[board].flags.busytone = 0;
-	if (ixj[board].dsp.low == 0x20) {
+	j->flags.ringback = 0;
+	j->flags.dialtone = 1;
+	j->flags.busytone = 0;
+	if (j->dsp.low == 0x20) {
 		return;
 	} else {
-		ixj_set_tone_on(0xFFFF, board);
-		ixj_set_tone_off(0x0000, board);
-		ixj_play_tone(board, 25);
+		ixj_set_tone_on(0xFFFF, j);
+		ixj_set_tone_off(0x0000, j);
+		ixj_play_tone(j, 25);
 	}
 }
 
-static void ixj_cpt_stop(board)
+static void ixj_cpt_stop(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	if(j->tone_state)
 	{
 		j->flags.dialtone = 0;
 		j->flags.busytone = 0;
 		j->flags.ringback = 0;
-		ixj_set_tone_on(0x0001, board);
-		ixj_set_tone_off(0x0000, board);
-		ixj_play_tone(board, 0);
+		ixj_set_tone_on(0x0001, j);
+		ixj_set_tone_off(0x0000, j);
+		ixj_play_tone(j, 0);
 		j->tone_state = 0;
 		if (j->cadence_t) {
 			if (j->cadence_t->ce) {
@@ -4436,34 +4403,34 @@
 		}
 	}
 	if (j->play_mode == -1 && j->rec_mode == -1)
-		idle(board);
-	if (j->play_mode != -1)
-		ixj_play_start(board);
-	if (j->rec_mode != -1)
-		ixj_record_start(board);
+		idle(j);
+	if (j->play_mode != -1 && j->dsp.low == 0x20)
+		ixj_play_start(j);
+	if (j->rec_mode != -1 && j->dsp.low == 0x20)
+		ixj_record_start(j);
 }
 
-static void ixj_ringback(int board)
+static void ixj_ringback(IXJ *j)
 {
-	ixj[board].flags.busytone = 0;
-	ixj[board].flags.dialtone = 0;
-	ixj[board].flags.ringback = 1;
-	ixj_set_tone_on(0x0FA0, board);
-	ixj_set_tone_off(0x2EE0, board);
-	ixj_play_tone(board, 26);
+	j->flags.busytone = 0;
+	j->flags.dialtone = 0;
+	j->flags.ringback = 1;
+	ixj_set_tone_on(0x0FA0, j);
+	ixj_set_tone_off(0x2EE0, j);
+	ixj_play_tone(j, 26);
 }
 
-static void ixj_testram(int board)
+static void ixj_testram(IXJ *j)
 {
-	ixj_WriteDSPCommand(0x3001, board);	/* Test External SRAM */
+	ixj_WriteDSPCommand(0x3001, j);	/* Test External SRAM */
 }
 
-static int ixj_build_cadence(int board, IXJ_CADENCE * cp)
+static int ixj_build_cadence(IXJ *j, IXJ_CADENCE * cp)
 {
 	IXJ_CADENCE *lcp;
 	IXJ_CADENCE_ELEMENT *lcep;
 	IXJ_TONE ti;
-	IXJ *j = &ixj[board];
+
 	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
@@ -4490,30 +4457,30 @@
 	lcp->ce = (void *) lcep;
 	j->cadence_t = lcp;
 	j->tone_cadence_state = 0;
-	ixj_set_tone_on(lcp->ce[0].tone_on_time, board);
-	ixj_set_tone_off(lcp->ce[0].tone_off_time, board);
+	ixj_set_tone_on(lcp->ce[0].tone_on_time, j);
+	ixj_set_tone_off(lcp->ce[0].tone_off_time, j);
 	if (j->cadence_t->ce[j->tone_cadence_state].freq0) {
 		ti.tone_index = j->cadence_t->ce[j->tone_cadence_state].index;
 		ti.freq0 = j->cadence_t->ce[j->tone_cadence_state].freq0;
 		ti.gain0 = j->cadence_t->ce[j->tone_cadence_state].gain0;
 		ti.freq1 = j->cadence_t->ce[j->tone_cadence_state].freq1;
 		ti.gain1 = j->cadence_t->ce[j->tone_cadence_state].gain1;
-		ixj_init_tone(board, &ti);
+		ixj_init_tone(j, &ti);
 	}
-	ixj_play_tone(board, lcp->ce[0].index);
+	ixj_play_tone(j, lcp->ce[0].index);
 	return 1;
 }
 
-static int ixj_build_filter_cadence(int board, IXJ_FILTER_CADENCE * cp)
+static int ixj_build_filter_cadence(IXJ *j, IXJ_FILTER_CADENCE * cp)
 {
 	IXJ_FILTER_CADENCE *lcp;
-	IXJ *j = &ixj[board];
+
 	lcp = kmalloc(sizeof(IXJ_CADENCE), GFP_KERNEL);
 	if (lcp == NULL)
 		return -ENOMEM;
 	if (copy_from_user(lcp, (char *) cp, sizeof(IXJ_FILTER_CADENCE)))
 		return -EFAULT;
-	if (lcp->filter > 4)
+	if (lcp->filter >= 4)
 		return -1;
 	j->cadence_f[lcp->filter].state = 0;
 	j->cadence_f[lcp->filter].enable = lcp->enable;
@@ -4540,9 +4507,8 @@
 	return 0;
 }
 
-static void add_caps(int board)
+static void add_caps(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	j->caps = 0;
 	j->caplist[j->caps].cap = PHONE_VENDOR_QUICKNET;
 	strcpy(j->caplist[j->caps].desc, "Quicknet Technologies, Inc. (www.quicknet.net)");
@@ -4550,95 +4516,139 @@
 	j->caplist[j->caps].handle = j->caps++;
 	j->caplist[j->caps].captype = device;
 	switch (j->cardtype) {
-	case 100:
+	case QTI_PHONEJACK:
 		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK");
-		j->caplist[j->caps].cap = 100;
 		break;
-	case 300:
+	case QTI_LINEJACK:
 		strcpy(j->caplist[j->caps].desc, "Quicknet Internet LineJACK");
-		j->caplist[j->caps].cap = 300;
 		break;
-	case 400:
+	case QTI_PHONEJACK_LITE:
 		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK Lite");
-		j->caplist[j->caps].cap = 400;
 		break;
-	case 500:
+	case QTI_PHONEJACK_PCI:
 		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneJACK PCI");
-		j->caplist[j->caps].cap = 500;
+		break;
+	case QTI_PHONECARD:
+		strcpy(j->caplist[j->caps].desc, "Quicknet Internet PhoneCARD");
 		break;
 	}
+	j->caplist[j->caps].cap = j->cardtype;
 	j->caplist[j->caps].handle = j->caps++;
 	strcpy(j->caplist[j->caps].desc, "POTS");
 	j->caplist[j->caps].captype = port;
 	j->caplist[j->caps].cap = pots;
 	j->caplist[j->caps].handle = j->caps++;
-	switch (ixj[board].cardtype) {
-	case 100:
+
+ 	// add devices that can do speaker/mic
+	switch (j->cardtype) {
+	case QTI_PHONEJACK:
+	case QTI_LINEJACK:
+	case QTI_PHONEJACK_PCI:
+	case QTI_PHONECARD:
 		strcpy(j->caplist[j->caps].desc, "SPEAKER");
 		j->caplist[j->caps].captype = port;
 		j->caplist[j->caps].cap = speaker;
 		j->caplist[j->caps].handle = j->caps++;
+        default:
+     		break;
+	}
+
+ 	// add devices that can do handset
+	switch (j->cardtype) {
+	case QTI_PHONEJACK:
 		strcpy(j->caplist[j->caps].desc, "HANDSET");
 		j->caplist[j->caps].captype = port;
 		j->caplist[j->caps].cap = handset;
 		j->caplist[j->caps].handle = j->caps++;
 		break;
-	case 300:
-		strcpy(j->caplist[j->caps].desc, "SPEAKER");
-		j->caplist[j->caps].captype = port;
-		j->caplist[j->caps].cap = speaker;
-		j->caplist[j->caps].handle = j->caps++;
+        default:
+     		break;
+	}
+
+ 	// add devices that can do PSTN
+	switch (j->cardtype) {
+	case QTI_LINEJACK:
 		strcpy(j->caplist[j->caps].desc, "PSTN");
 		j->caplist[j->caps].captype = port;
 		j->caplist[j->caps].cap = pstn;
 		j->caplist[j->caps].handle = j->caps++;
 		break;
+        default:
+     		break;
 	}
+
+	// add codecs - all cards can do uLaw, linear 8/16, and Windows sound system
 	strcpy(j->caplist[j->caps].desc, "ULAW");
 	j->caplist[j->caps].captype = codec;
 	j->caplist[j->caps].cap = ULAW;
 	j->caplist[j->caps].handle = j->caps++;
+
 	strcpy(j->caplist[j->caps].desc, "LINEAR 16 bit");
 	j->caplist[j->caps].captype = codec;
 	j->caplist[j->caps].cap = LINEAR16;
 	j->caplist[j->caps].handle = j->caps++;
+
 	strcpy(j->caplist[j->caps].desc, "LINEAR 8 bit");
 	j->caplist[j->caps].captype = codec;
 	j->caplist[j->caps].cap = LINEAR8;
 	j->caplist[j->caps].handle = j->caps++;
+
 	strcpy(j->caplist[j->caps].desc, "Windows Sound System");
 	j->caplist[j->caps].captype = codec;
 	j->caplist[j->caps].cap = WSS;
 	j->caplist[j->caps].handle = j->caps++;
-	if (j->ver.low != 0x12) {
+
+	// version 12 of the 8020 does the following codecs in a broken way
+	if (j->dsp.low != 0x20 || j->ver.low != 0x12) {
 		strcpy(j->caplist[j->caps].desc, "G.723.1 6.3Kbps");
 		j->caplist[j->caps].captype = codec;
 		j->caplist[j->caps].cap = G723_63;
 		j->caplist[j->caps].handle = j->caps++;
+
 		strcpy(j->caplist[j->caps].desc, "G.723.1 5.3Kbps");
 		j->caplist[j->caps].captype = codec;
 		j->caplist[j->caps].cap = G723_53;
 		j->caplist[j->caps].handle = j->caps++;
+
 		strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.8Kbps");
 		j->caplist[j->caps].captype = codec;
 		j->caplist[j->caps].cap = TS48;
 		j->caplist[j->caps].handle = j->caps++;
+
 		strcpy(j->caplist[j->caps].desc, "TrueSpeech 4.1Kbps");
 		j->caplist[j->caps].captype = codec;
 		j->caplist[j->caps].cap = TS41;
 		j->caplist[j->caps].handle = j->caps++;
 	}
-	if (j->cardtype == 100) {
+
+	// 8020 chips can do TS8.5 native, and 8021/8022 can load it
+	if (j->dsp.low == 0x20 || j->flags.ts85_loaded) {
 		strcpy(j->caplist[j->caps].desc, "TrueSpeech 8.5Kbps");
 		j->caplist[j->caps].captype = codec;
 		j->caplist[j->caps].cap = TS85;
 		j->caplist[j->caps].handle = j->caps++;
 	}
+
+	// 8021 chips can do G728
+	if (j->dsp.low == 0x21) {
+		strcpy(j->caplist[j->caps].desc, "G.728 16Kbps");
+		j->caplist[j->caps].captype = codec;
+		j->caplist[j->caps].cap = G728;
+		j->caplist[j->caps].handle = j->caps++;
+	}
+
+	// 8021/8022 chips can do G729 if loaded
+	if (j->dsp.low != 0x20 && j->flags.g729_loaded) {
+		strcpy(j->caplist[j->caps].desc, "G.729A/B");
+		j->caplist[j->caps].captype = codec;
+		j->caplist[j->caps].cap = G728;
+		j->caplist[j->caps].handle = j->caps++;
+	}
 }
-static int capabilities_check(int board, struct phone_capability *pcreq)
+
+static int capabilities_check(IXJ *j, struct phone_capability *pcreq)
 {
 	int cnt;
-	IXJ *j = &ixj[board];
 	int retval = 0;
 	for (cnt = 0; cnt < j->caps; cnt++) {
 		if (pcreq->captype == j->caplist[cnt].captype
@@ -4655,13 +4665,18 @@
 	IXJ_TONE ti;
 	IXJ_FILTER jf;
 	unsigned int minor = MINOR(inode->i_rdev);
-	int board = NUM(inode->i_rdev);
-	IXJ *j = &ixj[NUM(inode->i_rdev)];
+	unsigned int board = NUM(inode->i_rdev);
+	IXJ *j = ixj[board];
 	int retval = 0;
+
 	if (ixjdebug > 1)
 		printk(KERN_DEBUG "phone%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
 	if (minor >= IXJMAX)
 		return -ENODEV;
+
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
+
 	/*
 	 *    Check ioctls only root can use.
 	 */
@@ -4674,7 +4689,7 @@
 	}
 	switch (cmd) {
 	case IXJCTL_TESTRAM:
-		ixj_testram(board);
+		ixj_testram(j);
 		retval = (j->ssr.high << 8) + j->ssr.low;
 		break;
 	case IXJCTL_CARDTYPE:
@@ -4697,7 +4712,7 @@
 		else {
 			memset(&j->cid_send, 0, sizeof(PHONE_CID));
 		}
-		ixj_write_cidcw(board);
+		ixj_write_cidcw(j);
 		break;
 	/* Binary compatbility */
 	case OLD_PHONE_RING_START:
@@ -4710,14 +4725,14 @@
 		else {
 			memset(&j->cid_send, 0, sizeof(PHONE_CID));
 		}
-		ixj_ring_start(board);
+		ixj_ring_start(j);
 		break;
 	case PHONE_RING_STOP:
 		j->flags.cringing = 0;
-		ixj_ring_off(board);
+		ixj_ring_off(j);
 		break;
 	case PHONE_RING:
-		retval = ixj_ring(board);
+		retval = ixj_ring(j);
 		break;
 	case PHONE_EXCEPTION:
 		retval = j->ex.bytes;
@@ -4740,70 +4755,70 @@
 		retval = j->r_hook;
 		break;
 	case IXJCTL_SET_LED:
-		LED_SetState(arg, board);
+		LED_SetState(arg, j);
 		break;
 	case PHONE_FRAME:
-		retval = set_base_frame(board, arg);
+		retval = set_base_frame(j, arg);
 		break;
 	case PHONE_REC_CODEC:
-		retval = set_rec_codec(board, arg);
+		retval = set_rec_codec(j, arg);
 		break;
 	case PHONE_VAD:
-		ixj_vad(board, arg);
+		ixj_vad(j, arg);
 		break;
 	case PHONE_REC_START:
-		ixj_record_start(board);
+		ixj_record_start(j);
 		break;
 	case PHONE_REC_STOP:
-		ixj_record_stop(board);
+		ixj_record_stop(j);
 		break;
 	case PHONE_REC_DEPTH:
-		set_rec_depth(board, arg);
+		set_rec_depth(j, arg);
 		break;
 	case PHONE_REC_VOLUME:
 		if(arg == -1) {
-			retval = get_rec_volume(board);
+			retval = get_rec_volume(j);
 		}
 		else {
-			set_rec_volume(board, arg);
+			set_rec_volume(j, arg);
 			retval = arg;
 		}
 		break;
 	case PHONE_REC_LEVEL:
-		retval = get_rec_level(board);
+		retval = get_rec_level(j);
 		break;
 	case IXJCTL_AEC_START:
-		ixj_aec_start(board, arg);
+		ixj_aec_start(j, arg);
 		break;
 	case IXJCTL_AEC_STOP:
-		aec_stop(board);
+		aec_stop(j);
 		break;
 	case IXJCTL_AEC_GET_LEVEL:
 		retval = j->aec_level;
 		break;
 	case PHONE_PLAY_CODEC:
-		retval = set_play_codec(board, arg);
+		retval = set_play_codec(j, arg);
 		break;
 	case PHONE_PLAY_START:
-		retval = ixj_play_start(board);
+		retval = ixj_play_start(j);
 		break;
 	case PHONE_PLAY_STOP:
-		ixj_play_stop(board);
+		ixj_play_stop(j);
 		break;
 	case PHONE_PLAY_DEPTH:
-		set_play_depth(board, arg);
+		set_play_depth(j, arg);
 		break;
 	case PHONE_PLAY_VOLUME:
 		if(arg == -1) {
-			retval = get_play_volume(board);
+			retval = get_play_volume(j);
 		}
 		else {
-			set_play_volume(board, arg);
+			set_play_volume(j, arg);
 			retval = arg;
 		}
 		break;
 	case PHONE_PLAY_LEVEL:
-		retval = get_play_level(board);
+		retval = get_play_level(j);
 		break;
 	case IXJCTL_DSP_TYPE:
 		retval = (j->dsp.high << 8) + j->dsp.low;
@@ -4842,20 +4857,20 @@
 		j->maxrings = arg;
 		break;
 	case PHONE_SET_TONE_ON_TIME:
-		ixj_set_tone_on(arg, board);
+		ixj_set_tone_on(arg, j);
 		break;
 	case PHONE_SET_TONE_OFF_TIME:
-		ixj_set_tone_off(arg, board);
+		ixj_set_tone_off(arg, j);
 		break;
 	case PHONE_GET_TONE_ON_TIME:
-		if (ixj_get_tone_on(board)) {
+		if (ixj_get_tone_on(j)) {
 			retval = -1;
 		} else {
 			retval = (j->ssr.high << 8) + j->ssr.low;
 		}
 		break;
 	case PHONE_GET_TONE_OFF_TIME:
-		if (ixj_get_tone_off(board)) {
+		if (ixj_get_tone_off(j)) {
 			retval = -1;
 		} else {
 			retval = (j->ssr.high << 8) + j->ssr.low;
@@ -4863,7 +4878,9 @@
 		break;
 	case PHONE_PLAY_TONE:
 		if (!j->tone_state)
-			ixj_play_tone(board, arg);
+			retval = ixj_play_tone(j, arg);
+		else
+			retval = -1;
 		break;
 	case PHONE_GET_TONE_STATE:
 		retval = j->tone_state;
@@ -4872,7 +4889,7 @@
 		retval = j->ex.bits.dtmf_ready;
 		break;
 	case PHONE_GET_DTMF:
-		if (ixj_hookstate(board)) {
+		if (ixj_hookstate(j)) {
 			if (j->dtmf_rp != j->dtmf_wp) {
 				retval = j->dtmfbuffer[j->dtmf_rp];
 				j->dtmf_rp++;
@@ -4885,7 +4902,7 @@
 		}
 		break;
 	case PHONE_GET_DTMF_ASCII:
-		if (ixj_hookstate(board)) {
+		if (ixj_hookstate(j)) {
 			if (j->dtmf_rp != j->dtmf_wp) {
 				switch (j->dtmfbuffer[j->dtmf_rp]) {
 				case 10:
@@ -4934,16 +4951,16 @@
 		j->flags.dtmf_oob = arg;
 		break;
 	case PHONE_DIALTONE:
-		ixj_dialtone(board);
+		ixj_dialtone(j);
 		break;
 	case PHONE_BUSY:
-		ixj_busytone(board);
+		ixj_busytone(j);
 		break;
 	case PHONE_RINGBACK:
-		ixj_ringback(board);
+		ixj_ringback(j);
 		break;
 	case PHONE_CPT_STOP:
-		ixj_cpt_stop(board);
+		ixj_cpt_stop(j);
 		break;
 	case PHONE_QUERY_CODEC:
 	{
@@ -4972,36 +4989,36 @@
 		return 0;
 	}
 	case IXJCTL_DSP_IDLE:
-		idle(board);
+		idle(j);
 		break;
 	case IXJCTL_MIXER:
-		ixj_mixer(arg, board);
+		ixj_mixer(arg, j);
 		break;
 	case IXJCTL_DAA_COEFF_SET:
 		switch (arg) {
 		case DAA_US:
-			DAA_Coeff_US(board);
-			retval = ixj_daa_write(board);
+			DAA_Coeff_US(j);
+			retval = ixj_daa_write(j);
 			break;
 		case DAA_UK:
-			DAA_Coeff_UK(board);
-			retval = ixj_daa_write(board);
+			DAA_Coeff_UK(j);
+			retval = ixj_daa_write(j);
 			break;
 		case DAA_FRANCE:
-			DAA_Coeff_France(board);
-			retval = ixj_daa_write(board);
+			DAA_Coeff_France(j);
+			retval = ixj_daa_write(j);
 			break;
 		case DAA_GERMANY:
-			DAA_Coeff_Germany(board);
-			retval = ixj_daa_write(board);
+			DAA_Coeff_Germany(j);
+			retval = ixj_daa_write(j);
 			break;
 		case DAA_AUSTRALIA:
-			DAA_Coeff_Australia(board);
-			retval = ixj_daa_write(board);
+			DAA_Coeff_Australia(j);
+			retval = ixj_daa_write(j);
 			break;
 		case DAA_JAPAN:
-			DAA_Coeff_Japan(board);
-			retval = ixj_daa_write(board);
+			DAA_Coeff_Japan(j);
+			retval = ixj_daa_write(j);
 			break;
 		default:
 			retval = 1;
@@ -5010,13 +5027,13 @@
 		j->country = arg;
 		break;
 	case IXJCTL_DAA_AGAIN:
-		ixj_daa_cr4(board, arg | 0x02);
+		ixj_daa_cr4(j, arg | 0x02);
 		break;
 	case IXJCTL_PSTN_LINETEST:
-		retval = ixj_linetest(board);
+		retval = ixj_linetest(j);
 		break;
 	case IXJCTL_VMWI:
-		ixj_write_vmwi(board, arg);
+		ixj_write_vmwi(j, arg);
 		break;
 	case IXJCTL_CID:
 		if (copy_to_user((char *) arg, &j->cid, sizeof(PHONE_CID)))
@@ -5028,12 +5045,12 @@
 		break;
 	case IXJCTL_PORT:
 		if (arg)
-			retval = ixj_set_port(board, arg);
+			retval = ixj_set_port(j, arg);
 		else
 			retval = j->port;
 		break;
 	case IXJCTL_POTS_PSTN:
-		retval = ixj_set_pots(board, arg);
+		retval = ixj_set_pots(j, arg);
 		break;
 	case PHONE_CAPABILITIES:
 		retval = j->caps;
@@ -5043,10 +5060,10 @@
 			 return -EFAULT;
 		break;
 	case PHONE_CAPABILITIES_CHECK:
-		retval = capabilities_check(board, (struct phone_capability *) arg);
+		retval = capabilities_check(j, (struct phone_capability *) arg);
 		break;
 	case PHONE_PSTN_SET_STATE:
-		daa_set_mode(board, arg);
+		daa_set_mode(j, arg);
 		break;
 	case PHONE_PSTN_GET_STATE:
 		retval = j->daa_mode;
@@ -5055,40 +5072,47 @@
 	case IXJCTL_SET_FILTER:
 		if (copy_from_user(&jf, (char *) arg, sizeof(jf)))
 			return -EFAULT;
-		retval = ixj_init_filter(board, &jf);
+		retval = ixj_init_filter(j, &jf);
 		break;
 	case IXJCTL_GET_FILTER_HIST:
 		retval = j->filter_hist[arg];
 		break;
 	case IXJCTL_INIT_TONE:
 		copy_from_user(&ti, (char *) arg, sizeof(ti));
-		retval = ixj_init_tone(board, &ti);
+		retval = ixj_init_tone(j, &ti);
 		break;
 	case IXJCTL_TONE_CADENCE:
-		retval = ixj_build_cadence(board, (IXJ_CADENCE *) arg);
+		retval = ixj_build_cadence(j, (IXJ_CADENCE *) arg);
 		break;
 	case IXJCTL_FILTER_CADENCE:
-		retval = ixj_build_filter_cadence(board, (IXJ_FILTER_CADENCE *) arg);
+		retval = ixj_build_filter_cadence(j, (IXJ_FILTER_CADENCE *) arg);
 		break;
 	case IXJCTL_INTERCOM_STOP:
-		ixj[board].intercom = -1;
-		ixj[arg].intercom = -1;
-		ixj_record_stop(board);
-		ixj_record_stop(arg);
-		ixj_play_stop(board);
-		ixj_play_stop(arg);
-		idle(board);
-		idle(arg);
+		if (arg != j->intercom
+		    || ixj[arg]->intercom != board)
+			return -EINVAL;
+
+		j->intercom = -1;
+		ixj[arg]->intercom = -1;
+		ixj_record_stop(j);
+		ixj_record_stop(ixj[arg]);
+		ixj_play_stop(j);
+		ixj_play_stop(ixj[arg]);
+		idle(j);
+		idle(ixj[arg]);
 		break;
 	case IXJCTL_INTERCOM_START:
-		ixj[board].intercom = arg;
-		ixj[arg].intercom = board;
-		ixj_play_start(arg);
-		ixj_record_start(board);
-		ixj_play_start(board);
-		ixj_record_start(arg);
-		idle(board);
-		idle(arg);
+		if (ixj[arg] == NULL)
+			return -ENODEV;
+
+		j->intercom = arg;
+		ixj[arg]->intercom = board;
+		ixj_play_start(ixj[arg]);
+		ixj_record_start(j);
+		ixj_play_start(j);
+		ixj_record_start(ixj[arg]);
+		idle(j);
+		idle(ixj[arg]);
 		break;
 	}
 	return retval;
@@ -5096,7 +5120,11 @@
 
 static int ixj_fasync(int fd, struct file *file_p, int mode)
 {
-	IXJ *j = &ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+	IXJ *j = ixj[NUM(file_p->f_dentry->d_inode->i_rdev)];
+
+	if (j == NULL) /* shouldn't happen! */
+		return -ENODEV;
+
 	return fasync_helper(fd, file_p, mode, &j->async_queue);
 }
 
@@ -5111,16 +5139,15 @@
 	fasync:		ixj_fasync
 };
 
-static int ixj_linetest(int board)
+static int ixj_linetest(IXJ *j)
 {
 	unsigned long jifwait;
-	IXJ *j = &ixj[board];
 
 	j->flags.incheck = 1;	// Testing
 	if (!j->flags.pots_correct) {
 		j->flags.pots_correct = 1;
 
-		daa_int_read(board);	//Clear DAA Interrupt flags
+		daa_int_read(j);	//Clear DAA Interrupt flags
 		//
 		// Hold all relays in the normally de-energized position.
 		//
@@ -5136,7 +5163,7 @@
 		if (j->pld_slicr.bits.potspstn) {
 			j->flags.pots_pstn = 1;
 			j->flags.pots_correct = 0;
-			LED_SetState(0x4, board);
+			LED_SetState(0x4, j);
 		} else {
 			j->flags.pots_pstn = 0;
 			j->pld_slicw.bits.rly1 = 0;
@@ -5146,23 +5173,23 @@
 			j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
 
 			outb_p(j->pld_scrw.byte, j->XILINXbase);
-			daa_set_mode(board, SOP_PU_CONVERSATION);
+			daa_set_mode(j, SOP_PU_CONVERSATION);
 			jifwait = jiffies + hertz;
 			while (time_before(jiffies, jifwait)) {
 				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout(1);
 			}
-			daa_int_read(board);
-			daa_set_mode(board, SOP_PU_SLEEP);
+			daa_int_read(j);
+			daa_set_mode(j, SOP_PU_SLEEP);
 			if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
 				j->flags.pots_correct = 0;	// Should not be line voltage on POTS port.
 
-				LED_SetState(0x4, board);
+				LED_SetState(0x4, j);
 				j->pld_slicw.bits.rly3 = 0;
 				outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
 			} else {
 				j->flags.pots_correct = 1;
-				LED_SetState(0x8, board);
+				LED_SetState(0x8, j);
 				j->pld_slicw.bits.rly1 = 1;
 				j->pld_slicw.bits.rly2 = 0;
 				j->pld_slicw.bits.rly3 = 0;
@@ -5173,14 +5200,14 @@
 //      if (!j->flags.pstn_present) {
 	j->pld_slicw.bits.rly3 = 0;
 	outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-	daa_set_mode(board, SOP_PU_CONVERSATION);
+	daa_set_mode(j, SOP_PU_CONVERSATION);
 	jifwait = jiffies + hertz;
 	while (time_before(jiffies, jifwait)) {
 		set_current_state(TASK_INTERRUPTIBLE);
 		schedule_timeout(1);
 	}
-	daa_int_read(board);
-	daa_set_mode(board, SOP_PU_SLEEP);
+	daa_int_read(j);
+	daa_set_mode(j, SOP_PU_SLEEP);
 	if (j->m_DAAShadowRegs.XOP_REGS.XOP.xr0.bitreg.VDD_OK) {
 		j->flags.pstn_present = 1;
 	} else {
@@ -5189,50 +5216,49 @@
 //      }
 	if (j->flags.pstn_present) {
 		if (j->flags.pots_correct) {
-			LED_SetState(0xA, board);
+			LED_SetState(0xA, j);
 		} else {
-			LED_SetState(0x6, board);
+			LED_SetState(0x6, j);
 		}
 	} else {
 		if (j->flags.pots_correct) {
-			LED_SetState(0x9, board);
+			LED_SetState(0x9, j);
 		} else {
-			LED_SetState(0x5, board);
+			LED_SetState(0x5, j);
 		}
 	}
 	j->flags.incheck = 0;	// Testing
 	return j->flags.pstn_present;
 }
 
-static int ixj_selfprobe(int board)
+static int ixj_selfprobe(IXJ *j, int cnt)
 {
 	unsigned short cmd;
 	unsigned long jif;
-	int cnt;
+	int i;
 	BYTES bytes;
-	IXJ *j = &ixj[board];
 	
 	init_waitqueue_head(&j->poll_q);
 	init_waitqueue_head(&j->read_q);
 	init_waitqueue_head(&j->write_q);
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Write IDLE to Software Control Register\n");
-	ixj_WriteDSPCommand(0x0FE0, board);	// Put the DSP in full power mode.
+	ixj_WriteDSPCommand(0x0FE0, j);	// Put the DSP in full power mode.
 
-	if (ixj_WriteDSPCommand(0x0000, board))		/* Write IDLE to Software Control Register */
+	if (ixj_WriteDSPCommand(0x0000, j))		/* Write IDLE to Software Control Register */
 		return -1;
 // The read values of the SSR should be 0x00 for the IDLE command
 	if (j->ssr.low || j->ssr.high)
 		return -1;
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Get Device ID Code\n");
-	if (ixj_WriteDSPCommand(0x3400, board))		/* Get Device ID Code */
+	if (ixj_WriteDSPCommand(0x3400, j))		/* Get Device ID Code */
 		return -1;
 	j->dsp.low = j->ssr.low;
 	j->dsp.high = j->ssr.high;
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Get Device Version Code\n");
-	if (ixj_WriteDSPCommand(0x3800, board))		/* Get Device Version Code */
+	if (ixj_WriteDSPCommand(0x3800, j))		/* Get Device Version Code */
 		return -1;
 	j->ver.low = j->ssr.low;
 	j->ver.high = j->ssr.high;
@@ -5246,8 +5272,7 @@
 			if (bytes.low == bytes.high)	//  Register is read only on
 				//  Internet PhoneJack Lite
 			 {
-				j->cardtype = 400;	// Internet PhoneJACK Lite
-
+				j->cardtype = QTI_PHONEJACK_LITE;
 				if (check_region(j->XILINXbase, 4)) {
 					printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
 					return -1;
@@ -5256,7 +5281,7 @@
 				j->pld_slicw.pcib.e1 = 1;
 				outb_p(j->pld_slicw.byte, j->XILINXbase);
 			} else {
-				j->cardtype = 300;	// Internet LineJACK
+				j->cardtype = QTI_LINEJACK;
 
 				if (check_region(j->XILINXbase, 8)) {
 					printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
@@ -5265,38 +5290,32 @@
 				request_region(j->XILINXbase, 8, "ixj control");
 			}
 		} else if (j->dsp.low == 0x22) {
-			j->cardtype = 500;	// Internet PhoneJACK PCI
-
+			j->cardtype = QTI_PHONEJACK_PCI;
 			request_region(j->XILINXbase, 4, "ixj control");
 			j->pld_slicw.pcib.e1 = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase);
 		} else
-			j->cardtype = 100;	// Internet PhoneJACK
-
+			j->cardtype = QTI_PHONEJACK;
 	} else {
 		switch (j->cardtype) {
-		case 100:	// Internet PhoneJACK
-
+		case QTI_PHONEJACK:
 			if (!j->dsp.low != 0x20) {
 				j->dsp.high = 0x80;
 				j->dsp.low = 0x20;
-				ixj_WriteDSPCommand(0x3800, board);
+				ixj_WriteDSPCommand(0x3800, j);
 				j->ver.low = j->ssr.low;
 				j->ver.high = j->ssr.high;
 			}
 			break;
-		case 300:	// Internet LineJACK
-
+		case QTI_LINEJACK:
 			if (check_region(j->XILINXbase, 8)) {
 				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
 				return -1;
 			}
 			request_region(j->XILINXbase, 8, "ixj control");
 			break;
-		case 400:	//Internet PhoneJACK Lite
-
-		case 500:	//Internet PhoneJACK PCI
-
+		case QTI_PHONEJACK_LITE:
+		case QTI_PHONEJACK_PCI:
 			if (check_region(j->XILINXbase, 4)) {
 				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", j->XILINXbase);
 				return -1;
@@ -5305,36 +5324,37 @@
 			j->pld_slicw.pcib.e1 = 1;
 			outb_p(j->pld_slicw.byte, j->XILINXbase);
 			break;
-		case 600:	//Internet PhoneCARD
-
+		case QTI_PHONECARD:
 			break;
 		}
 	}
-	if (j->dsp.low == 0x20 || j->cardtype == 400 || j->cardtype == 500) {
+	if (j->dsp.low == 0x20
+	    || j->cardtype == QTI_PHONEJACK_LITE
+	    || j->cardtype == QTI_PHONEJACK_PCI) {
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Write CODEC config to Software Control Register\n");
-		if (ixj_WriteDSPCommand(0xC462, board))		/* Write CODEC config to Software Control Register */
+		if (ixj_WriteDSPCommand(0xC462, j))		/* Write CODEC config to Software Control Register */
 			return -1;
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Write CODEC timing to Software Control Register\n");
-		if (j->cardtype == 100) {
+		if (j->cardtype == QTI_PHONEJACK) {
 			cmd = 0x9FF2;
 		} else {
 			cmd = 0x9FF5;
 		}
-		if (ixj_WriteDSPCommand(cmd, board))	/* Write CODEC timing to Software Control Register */
+		if (ixj_WriteDSPCommand(cmd, j))	/* Write CODEC timing to Software Control Register */
 			return -1;
 	} else {
-		if (set_base_frame(board, 30) != 30)
+		if (set_base_frame(j, 30) != 30)
 			return -1;
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Write CODEC config to Software Control Register\n");
-		if (j->cardtype == 600) {
-			if (ixj_WriteDSPCommand(0xC528, board))		/* Write CODEC config to Software Control Register */
+		if (j->cardtype == QTI_PHONECARD) {
+			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to Software Control Register */
 				return -1;
 		}
-		if (j->cardtype == 300) {
-			if (ixj_WriteDSPCommand(0xC528, board))		/* Write CODEC config to Software Control Register */
+		if (j->cardtype == QTI_LINEJACK) {
+			if (ixj_WriteDSPCommand(0xC528, j))		/* Write CODEC config to Software Control Register */
 				return -1;
 			if (ixjdebug > 0)
 				printk(KERN_INFO "Turn on the PLD Clock at 8Khz\n");
@@ -5355,7 +5375,7 @@
 		j->gpio.bits.gpio5 = 1;
 		j->gpio.bits.gpio6 = 1;
 		j->gpio.bits.gpio7 = 1;
-		ixj_WriteDSPCommand(ixj[board].gpio.word, board);	/* Set GPIO pin directions */
+		ixj_WriteDSPCommand(j->gpio.word, j);	/* Set GPIO pin directions */
 		if (ixjdebug > 0)
 			printk(KERN_INFO "Enable SLIC\n");
 		j->gpio.bytes.high = 0x0B;
@@ -5363,45 +5383,46 @@
 		j->gpio.bits.gpio1 = 0;
 		j->gpio.bits.gpio2 = 1;
 		j->gpio.bits.gpio5 = 0;
-		ixj_WriteDSPCommand(ixj[board].gpio.word, board);	/* send the ring stop signal */
+		ixj_WriteDSPCommand(j->gpio.word, j);	/* send the ring stop signal */
 		j->port = PORT_POTS;
 	} else {
-		if (j->cardtype == 300) {
-			LED_SetState(0x1, board);
+		if (j->cardtype == QTI_LINEJACK) {
+			LED_SetState(0x1, j);
 			jif = jiffies + (hertz / 10);
 			while (time_before(jiffies, jif)) {
 				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout(1);
 			}
-			LED_SetState(0x2, board);
+			LED_SetState(0x2, j);
 			jif = jiffies + (hertz / 10);
 			while (time_before(jiffies, jif)) {
 				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout(1);
 			}
-			LED_SetState(0x4, board);
+			LED_SetState(0x4, j);
 			jif = jiffies + (hertz / 10);
 			while (time_before(jiffies, jif)) {
 				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout(1);
 			}
-			LED_SetState(0x8, board);
+			LED_SetState(0x8, j);
 			jif = jiffies + (hertz / 10);
 			while (time_before(jiffies, jif)) {
 				set_current_state(TASK_INTERRUPTIBLE);
 				schedule_timeout(1);
 			}
-			LED_SetState(0x0, board);
-			daa_get_version(board);
+			LED_SetState(0x0, j);
+			daa_get_version(j);
 			if (ixjdebug > 0)
 				printk("Loading DAA Coefficients\n");
-			DAA_Coeff_US(board);
-			if (!ixj_daa_write(board))
-				printk("DAA write failed on board %d\n", board);
-			ixj_daa_cid_reset(board);
+			DAA_Coeff_US(j);
+			if (!ixj_daa_write(j))
+				printk("DAA write failed on board %d\n",
+				       j->p.board);
+			ixj_daa_cid_reset(j);
 			j->flags.pots_correct = 0;
 			j->flags.pstn_present = 0;
-			ixj_linetest(board);
+			ixj_linetest(j);
 			if (j->flags.pots_correct) {
 				j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
 
@@ -5409,43 +5430,43 @@
 				j->pld_slicw.bits.rly1 = 1;
 				j->pld_slicw.bits.spken = 1;
 				outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
-				SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+				SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
 				j->port = PORT_POTS;
 			}
-			ixj_set_port(board, PORT_PSTN);
-			ixj_set_pots(board, 1);
+			ixj_set_port(j, PORT_PSTN);
+			ixj_set_pots(j, 1);
 			if (ixjdebug > 0)
 				printk(KERN_INFO "Enable Mixer\n");
-			ixj_mixer(0x0000, board);	//Master Volume Left unmute 0db
+			ixj_mixer(0x0000, j);	//Master Volume Left unmute 0db
 
-			ixj_mixer(0x0100, board);	//Master Volume Right unmute 0db
+			ixj_mixer(0x0100, j);	//Master Volume Right unmute 0db
 
-			ixj_mixer(0x0F00, board);	//Mono Out Volume unmute 0db
+			ixj_mixer(0x0F00, j);	//Mono Out Volume unmute 0db
 
-			ixj_mixer(0x0C00, board);	//Mono1 Volume unmute 0db
+			ixj_mixer(0x0C00, j);	//Mono1 Volume unmute 0db
 
-			ixj_mixer(0x0200, board);	//Voice Left Volume unmute 0db
+			ixj_mixer(0x0200, j);	//Voice Left Volume unmute 0db
 
-			ixj_mixer(0x0300, board);	//Voice Right Volume unmute 0db
+			ixj_mixer(0x0300, j);	//Voice Right Volume unmute 0db
 
-			ixj_mixer(0x110C, board);	//Voice Left and Right out
+			ixj_mixer(0x110C, j);	//Voice Left and Right out
 
-			ixj_mixer(0x1401, board);	//Mono1 switch on mixer left
+			ixj_mixer(0x1401, j);	//Mono1 switch on mixer left
 
-			ixj_mixer(0x1501, board);	//Mono1 switch on mixer right
+			ixj_mixer(0x1501, j);	//Mono1 switch on mixer right
 
-			ixj_mixer(0x1700, board);	//Clock select
+			ixj_mixer(0x1700, j);	//Clock select
 
-			ixj_mixer(0x1800, board);	//ADC Source select
+			ixj_mixer(0x1800, j);	//ADC Source select
 
 		} else {
-			if (j->cardtype == 600) {
-				ixj_WriteDSPCommand(0xCF07, board);
-				ixj_WriteDSPCommand(0x00B0, board);
-				ixj_set_port(board, PORT_SPEAKER);
+			if (j->cardtype == QTI_PHONECARD) {
+				ixj_WriteDSPCommand(0xCF07, j);
+				ixj_WriteDSPCommand(0x00B0, j);
+				ixj_set_port(j, PORT_SPEAKER);
 			} else {
-				ixj_set_port(board, PORT_POTS);
-				SLIC_SetState(PLD_SLIC_STATE_STANDBY, board);
+				ixj_set_port(j, PORT_POTS);
+				SLIC_SetState(PLD_SLIC_STATE_STANDBY, j);
 			}
 		}
 	}
@@ -5454,9 +5475,9 @@
 	j->framesread = j->frameswritten = 0;
 	j->read_wait = j->write_wait = 0;
 	j->rxreadycheck = j->txreadycheck = 0;
-	set_play_volume(board, 0x100);
-	set_rec_volume(board, 0x100);
-	if (ixj_WriteDSPCommand(0x0000, board))		/* Write IDLE to Software Control Register */
+	set_play_volume(j, 0x100);
+	set_rec_volume(j, 0x100);
+	if (ixj_WriteDSPCommand(0x0000, j))		/* Write IDLE to Software Control Register */
 		return -1;
 // The read values of the SSR should be 0x00 for the IDLE command
 	if (j->ssr.low || j->ssr.high)
@@ -5465,41 +5486,41 @@
 		printk(KERN_INFO "Enable Line Monitor\n");
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Set Line Monitor to Asyncronous Mode\n");
-	if (ixj_WriteDSPCommand(0x7E01, board))		// Asynchronous Line Monitor
+	if (ixj_WriteDSPCommand(0x7E01, j))		// Asynchronous Line Monitor
 
 		return -1;
 	if (ixjdebug > 0)
 		printk(KERN_INFO "Enable DTMF Detectors\n");
-	if (ixj_WriteDSPCommand(0x5151, board))		// Enable DTMF detection
+	if (ixj_WriteDSPCommand(0x5151, j))		// Enable DTMF detection
 
 		return -1;
-	if (ixj_WriteDSPCommand(0x6E01, board))		// Set Asyncronous Tone Generation
+	if (ixj_WriteDSPCommand(0x6E01, j))		// Set Asyncronous Tone Generation
 
 		return -1;
-	set_rec_depth(board, 2);	// Set Record Channel Limit to 2 frames
+	set_rec_depth(j, 2);	// Set Record Channel Limit to 2 frames
 
-	set_play_depth(board, 2);	// Set Playback Channel Limit to 2 frames
+	set_play_depth(j, 2);	// Set Playback Channel Limit to 2 frames
 
 	j->ex.bits.dtmf_ready = 0;
 	j->dtmf_state = 0;
-	j->dtmf_wp = ixj[board].dtmf_rp = 0;
-	j->rec_mode = ixj[board].play_mode = -1;
+	j->dtmf_wp = j->dtmf_rp = 0;
+	j->rec_mode = j->play_mode = -1;
 	j->flags.ringing = 0;
 	j->maxrings = MAXRINGS;
 	j->ring_cadence = USA_RING_CADENCE;
 	j->drybuffer = 0;
 	j->winktime = 320;
 	j->flags.dtmf_oob = 0;
-	for (cnt = 0; cnt < 4; cnt++)
-		j->cadence_f[cnt].enable = 0;
+	for (i = 0; i < 4; i++)
+		j->cadence_f[i].enable = 0;
 	/* must be a device on the specified address */
-	ixj_WriteDSPCommand(0x0FE3, board);	// Put the DSP in 1/5 power mode.
+	ixj_WriteDSPCommand(0x0FE3, j);	// Put the DSP in 1/5 power mode.
 	/* Register with the Telephony for Linux subsystem */
 	j->p.f_op = &ixj_fops;
 	j->p.open = ixj_open;
-	j->p.board = board;
+	j->p.board = cnt;
 	phone_register_device(&j->p, PHONE_UNIT_ANY);
-	add_caps(board);
+	add_caps(j);
 	return 0;
 }
 
@@ -5513,36 +5534,40 @@
 	len += sprintf(buf + len, "\n%s", ixj_h_rcsid);
 	len += sprintf(buf + len, "\n%s", ixjuser_h_rcsid);
 	for (cnt = 0; cnt < IXJMAX; cnt++) {
-		j = &ixj[cnt];
+		j = ixj[cnt];
+
+		if (j == NULL)
+			continue;
+
 		if (j->DSPbase) {
 			len += sprintf(buf + len, "\nCard Num %d", cnt);
 			len += sprintf(buf + len, "\nDSP Base Address 0x%4.4x", j->DSPbase);
-			if (j->cardtype != 100)
+			if (j->cardtype != QTI_PHONEJACK)
 				len += sprintf(buf + len, "\nXILINX Base Address 0x%4.4x", j->XILINXbase);
 			len += sprintf(buf + len, "\nDSP Type %2.2x%2.2x", j->dsp.high, j->dsp.low);
 			len += sprintf(buf + len, "\nDSP Version %2.2x.%2.2x", j->ver.high, j->ver.low);
 			len += sprintf(buf + len, "\nSerial Number %8.8x", j->serial);
 			switch (j->cardtype) {
-			case (100):
+			case (QTI_PHONEJACK):
 				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK");
 				break;
-			case (300):
+			case (QTI_LINEJACK):
 				len += sprintf(buf + len, "\nCard Type = Internet LineJACK");
 				if (j->flags.g729_loaded)
 					len += sprintf(buf + len, " w/G.729 A/B");
 				len += sprintf(buf + len, " Country = %d", j->country);
 				break;
-			case (400):
+			case (QTI_PHONEJACK_LITE):
 				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK Lite");
 				if (j->flags.g729_loaded)
 					len += sprintf(buf + len, " w/G.729 A/B");
 				break;
-			case (500):
+			case (QTI_PHONEJACK_PCI):
 				len += sprintf(buf + len, "\nCard Type = Internet PhoneJACK PCI");
 				if (j->flags.g729_loaded)
 					len += sprintf(buf + len, " w/G.729 A/B");
 				break;
-			case (600):
+			case (QTI_PHONECARD):
 				len += sprintf(buf + len, "\nCard Type = Internet PhoneCARD");
 				if (j->flags.g729_loaded)
 					len += sprintf(buf + len, " w/G.729 A/B");
@@ -5557,7 +5582,8 @@
 			}
 			len += sprintf(buf + len, "\nReaders %d", j->readers);
 			len += sprintf(buf + len, "\nWriters %d", j->writers);
-			len += sprintf(buf + len, "\nFSK words %d", ixj[2].fskdcnt);
+			/* FIXME: This makes no sense! */
+			len += sprintf(buf + len, "\nFSK words %d", ixj[2] ? ixj[2]->fskdcnt : 0);
 			len += sprintf(buf + len, "\nCapabilities %d", j->caps);
 			if (j->dsp.low != 0x20)
 				len += sprintf(buf + len, "\nDSP Processor load %d", j->proc_load);
@@ -5671,7 +5697,7 @@
 			}
 			len += sprintf(buf + len, "\nHook state %d", j->r_hook);	// ixj_hookstate(cnt));
 
-			if (j->cardtype == 300) {
+			if (j->cardtype == QTI_LINEJACK) {
 				len += sprintf(buf + len, "\nPOTS Correct %d", j->flags.pots_correct);
 				len += sprintf(buf + len, "\nPSTN Present %d", j->flags.pstn_present);
 				len += sprintf(buf + len, "\nPOTS to PSTN %d", j->flags.pots_pstn);
@@ -5707,7 +5733,7 @@
 			}
 			if (j->dsp.low == 0x21 || j->dsp.low == 0x22) {
 				len += sprintf(buf + len, "\nSLIC state ");
-				switch (SLIC_GetState(cnt)) {
+				switch (SLIC_GetState(j)) {
 				case PLD_SLIC_STATE_OC:
 					len += sprintf(buf + len, "OC");
 					break;
@@ -5736,7 +5762,7 @@
 					len += sprintf(buf + len, "OHTPR");
 					break;
 				default:
-					len += sprintf(buf + len, "%d", SLIC_GetState(cnt));
+					len += sprintf(buf + len, "%d", SLIC_GetState(j));
 					break;
 				}
 			}
@@ -5756,13 +5782,16 @@
 	}
 	return len;
 }
+
 int ixj_get_status_proc_fsk(char *buf)
 {
 	int len;
 	len = 0;
-	if (ixj[2].fskdcnt) {
-		memcpy(buf, &ixj[2].fskdata, (ixj[2].fskdcnt) * 2);
-		len += ixj[2].fskdcnt * 2;
+
+	/* This makes no sense - why is ixj[2] special? */
+	if (ixj[2] != NULL && ixj[2]->fskdcnt) {
+		memcpy(buf, &ixj[2]->fskdata, (ixj[2]->fskdcnt) * 2);
+		len += ixj[2]->fskdcnt * 2;
 	}
 	return len;
 }
@@ -5793,14 +5822,17 @@
 
 MODULE_DESCRIPTION("Internet Phone/Internet LineJack module - www.quicknet.net");
 MODULE_AUTHOR("Ed Okerson <eokerson@quicknet.net>");
-#ifdef CONFIG_PCMCIA
+
+#if defined(CONFIG_PCMCIA) || defined(CONFIG_PCMCIA_MODULE)
+
 #ifdef PCMCIA_DEBUG
 static int pc_debug = PCMCIA_DEBUG;
 MODULE_PARM(pc_debug, "i");
 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 #else
 #define DEBUG(n, args...)
-#endif
+#endif /* PCMCIA_DEBUG */
+
 typedef struct ixj_info_t {
 	int ndev;
 	dev_node_t node;
@@ -5830,6 +5862,8 @@
 	DEBUG(0, "ixj_attach()\n");
 	/* Create new ixj device */
 	link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
+	if (!link)
+		return NULL;
 	memset(link, 0, sizeof(struct dev_link_t));
 	link->release.function = &ixj_cs_release;
 	link->release.data = (u_long) link;
@@ -5839,6 +5873,8 @@
 	link->conf.Vcc = 50;
 	link->conf.IntType = INT_MEMORY_AND_IO;
 	link->priv = kmalloc(sizeof(struct ixj_info_t), GFP_KERNEL);
+	if (!link->priv)
+		return NULL;
 	memset(link->priv, 0, sizeof(struct ixj_info_t));
 	/* Register with Card Services */
 	link->next = dev_list;
@@ -5963,6 +5999,7 @@
 
 void ixj_config(dev_link_t * link)
 {
+	IXJ *j;
 	client_handle_t handle;
 	ixj_info_t *info;
 	tuple_t tuple;
@@ -6016,16 +6053,25 @@
 	}
 
 	CS_CHECK(RequestConfiguration, handle, &link->conf);
-	ixj[0].DSPbase = link->io.BasePort1;
-	ixj[0].XILINXbase = link->io.BasePort1 + 0x10;
-	ixj[0].cardtype = 600;
-	ixj_selfprobe(0);
+
+	
+	if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL)
+		goto cs_failed;
+
+	ixj[0] = j;
+
+	j->DSPbase = link->io.BasePort1;
+	j->XILINXbase = link->io.BasePort1 + 0x10;
+	j->cardtype = QTI_PHONECARD;
+	ixj_selfprobe(j, 0);
+
 	info->ndev = 1;
 	info->node.major = PHONE_MAJOR;
 	link->dev = &info->node;
-	ixj_get_serial(link, &ixj[0]);
+	ixj_get_serial(link, j);
 	link->state &= ~DEV_CONFIG_PENDING;
 	return;
+
       cs_failed:
 	cs_error(link->handle, last_fn, last_ret);
 	ixj_cs_release((u_long) link);
@@ -6041,6 +6087,9 @@
 	CardServices(ReleaseConfiguration, link->handle);
 	CardServices(ReleaseIO, link->handle, &link->io);
 	link->state &= ~DEV_CONFIG;
+
+	kfree(ixj[0]);
+	ixj[0] = NULL;
 }
 
 int ixj_event(event_t event, int priority, event_callback_args_t * args)
@@ -6078,38 +6127,44 @@
 	return 0;
 }
 
-#endif				// PCMCIA
+#endif /* CONFIG_PCMCIA */
 
 static void cleanup(void)
 {
 	int cnt;
 	del_timer(&ixj_timer);
 	for (cnt = 0; cnt < IXJMAX; cnt++) {
-		if (ixj[cnt].cardtype == 300) {
-			ixj[cnt].pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
+		IXJ *j = ixj[cnt];
+
+		if (j == NULL)
+			continue;
 
-			outb_p(ixj[cnt].pld_scrw.byte, ixj[cnt].XILINXbase);
-			ixj[cnt].pld_slicw.bits.rly1 = 0;
-			ixj[cnt].pld_slicw.bits.rly2 = 0;
-			ixj[cnt].pld_slicw.bits.rly3 = 0;
-			outb_p(ixj[cnt].pld_slicw.byte, ixj[cnt].XILINXbase + 0x01);
-			LED_SetState(0x0, cnt);
-			release_region(ixj[cnt].XILINXbase, 8);
-		}
-		if (ixj[cnt].cardtype == 400 || ixj[cnt].cardtype == 500) {
-			release_region(ixj[cnt].XILINXbase, 4);
-		}
-		if (ixj[cnt].DSPbase) {
-			release_region(ixj[cnt].DSPbase, 16);
-			phone_unregister_device(&ixj[cnt].p);
-		}
-		if (ixj[cnt].read_buffer)
-			kfree(ixj[cnt].read_buffer);
-		if (ixj[cnt].write_buffer)
-			kfree(ixj[cnt].write_buffer);
+		if (j->cardtype == QTI_LINEJACK) {
+			j->pld_scrw.bits.daafsyncen = 0;	// Turn off DAA Frame Sync
+
+			outb_p(j->pld_scrw.byte, j->XILINXbase);
+			j->pld_slicw.bits.rly1 = 0;
+			j->pld_slicw.bits.rly2 = 0;
+			j->pld_slicw.bits.rly3 = 0;
+			outb_p(j->pld_slicw.byte, j->XILINXbase + 0x01);
+			LED_SetState(0x0, j);
+			release_region(j->XILINXbase, 8);
+		}
+		if (j->cardtype == QTI_PHONEJACK_LITE
+		    || j->cardtype == QTI_PHONEJACK_PCI) {
+			release_region(j->XILINXbase, 4);
+		}
+		if (j->DSPbase) {
+			release_region(j->DSPbase, 16);
+			phone_unregister_device(&j->p);
+		}
+		if (j->read_buffer)
+			kfree(j->read_buffer);
+		if (j->write_buffer)
+			kfree(j->write_buffer);
 #ifdef CONFIG_ISAPNP
-		if (ixj[cnt].dev)
-			ixj[cnt].dev->deactivate(ixj[cnt].dev);
+		if (j->dev)
+			j->dev->deactivate(j->dev);
 #endif
 #ifdef CONFIG_PCMCIA
 		DEBUG(0, "ixj_cs: unloading\n");
@@ -6117,6 +6172,9 @@
 		while (dev_list != NULL)
 			ixj_detach(dev_list);
 #endif
+
+		kfree(j);
+		ixj[cnt] = NULL;
 	}
 	remove_proc_entry ("ixj", NULL);
 	remove_proc_entry ("ixjfsk", NULL);
@@ -6223,36 +6281,46 @@
 	cleanup();
 }
 
-int __init ixj_init(void)
+#if defined(CONFIG_PCMCIA)
+int __init ixj_register_pcmcia(void)
 {
-	int result;
-	int i = 0;
-	int cnt = 0;
-	int probe = 0;
-#ifdef CONFIG_ISAPNP
-	int func = 0x110;
-	struct pci_dev *dev = NULL, *old_dev = NULL;
-#endif
-#ifdef CONFIG_PCI
-	struct pci_dev *pci = NULL;
-#endif
-#ifdef CONFIG_PCMCIA
 	servinfo_t serv;
+
 	DEBUG(0, "%s\n", version);
 	CardServices(GetCardServicesInfo, &serv);
 	if (serv.Revision != CS_RELEASE_CODE) {
 		printk(KERN_NOTICE "ixj_cs: Card Services release does not match!\n");
-		return -1;
+		return -EINVAL;
 	}
 	register_pcmcia_driver(&dev_info, &ixj_attach, &ixj_detach);
-	probe = 0;
+	return 0;
+}
 #else
-#ifdef CONFIG_ISAPNP
+extern __inline__ int ixj_register_pcmcia(void)
+{
+	return 0;
+}
+
+#if defined(CONFIG_ISAPNP)
+extern __inline__ int ixj_probe_isa(int *cnt)
+{
+	return 0;
+}
+
+int __init ixj_probe_isapnp(int *cnt)
+{
+	int probe = 0;
+	int func = 0x110;
+	struct pci_dev *dev = NULL, *old_dev = NULL;
+
 	while (1) {
 		do {
+			IXJ *j;
+			int result;
+
 			old_dev = dev;
 			dev = isapnp_find_dev(NULL, ISAPNP_VENDOR('Q', 'T', 'I'),
-					 ISAPNP_FUNCTION(func), old_dev);
+					      ISAPNP_FUNCTION(func), old_dev);
 			if (!dev)
 				break;
 			result = dev->prepare(dev);
@@ -6260,8 +6328,10 @@
 				printk("preparing failed %d \n", result);
 				break;
 			}
+
 			if (!(dev->resource[0].flags & IORESOURCE_IO))
 				return -ENODEV;
+
 			dev->resource[0].flags |= IORESOURCE_AUTO;
 			if (func != 0x110)
 				dev->resource[1].flags |= IORESOURCE_AUTO;
@@ -6269,42 +6339,60 @@
 				printk("isapnp configure failed (out of resources?)\n");
 				return -ENOMEM;
 			}
-			ixj[cnt].DSPbase = dev->resource[0].start;	/* get real port */
-			if (func != 0x110)
-				ixj[cnt].XILINXbase = dev->resource[1].start;	/* get real port */
-			result = check_region(ixj[cnt].DSPbase, 16);
-			if (result) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
+
+			/* DSP base */
+			if ((result = check_region(dev->resource[0].start, 16)) < 0) {
+				printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n",
+				       dev->resource[0].start);
 				cleanup();
 				return result;
 			}
-			request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
+
+			if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) {
+				cleanup();
+				return -ENOMEM;
+			}
+
+			ixj[*cnt] = j;
+
+			j->DSPbase = dev->resource[0].start;
+
+			/* XXX is this racy? */
+			request_region(j->DSPbase, 16, "ixj DSP");
+
+			if (func != 0x110)
+				j->XILINXbase = dev->resource[1].start;
+
 			switch (func) {
 			case (0x110):
-				ixj[cnt].cardtype = 100;
+				j->cardtype = QTI_PHONEJACK;
 				break;
 			case (0x310):
-				ixj[cnt].cardtype = 300;
+				j->cardtype = QTI_LINEJACK;
 				break;
 			case (0x410):
-				ixj[cnt].cardtype = 400;
+				j->cardtype = QTI_PHONEJACK_LITE;
 				break;
 			}
-			probe = ixj_selfprobe(cnt);
-			ixj[cnt].serial = dev->bus->serial;
-			ixj[cnt].dev = dev;
+			probe = ixj_selfprobe(j, *cnt);
+			
+			j->serial = dev->bus->serial;
+			j->dev = dev;
 			switch (func) {
 			case 0x110:
-				printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n", ixj[cnt].DSPbase);
+				printk(KERN_INFO "ixj: found Internet PhoneJACK at 0x%x\n",
+				       j->DSPbase);
 				break;
 			case 0x310:
-				printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n", ixj[cnt].DSPbase);
+				printk(KERN_INFO "ixj: found Internet LineJACK at 0x%x\n",
+				       j->DSPbase);
 				break;
 			case 0x410:
-				printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n", ixj[cnt].DSPbase);
+				printk(KERN_INFO "ixj: found Internet PhoneJACK Lite at 0x%x\n",
+				       j->DSPbase);
 				break;
 			}
-			cnt++;
+			++*cnt;
 		} while (dev);
 		if (func == 0x410)
 			break;
@@ -6314,69 +6402,143 @@
 			func = 0x310;
 		dev = NULL;
 	}
-#else				//CONFIG_ISAPNP
+
+	return probe;
+}
+#else
+extern __inline__ int ixj_probe_isapnp(int *cnt)
+{
+	return 0;
+}
+
+int __init ixj_probe_isa(int *cnt)
+{
+	int i, result, probe;
+
 	/* Use passed parameters for older kernels without PnP */
 	for (i = 0; i < IXJMAX; i++) {
 		if (dspio[i]) {
-			ixj[cnt].DSPbase = dspio[i];
-			ixj[cnt].XILINXbase = xio[i];
-			ixj[cnt].cardtype = 0;
-			result = check_region(ixj[cnt].DSPbase, 16);
-			if (result) {
-				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
+			IXJ *j;
+
+			if ((result = check_region(dspio[i], 16)) < 0) {
+				printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", dspio[i]);
 				cleanup();
 				return result;
 			}
-			request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
-			probe = ixj_selfprobe(cnt);
-			ixj[cnt].dev = NULL;
-			cnt++;
+
+			if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) {
+				cleanup();
+				return -ENOMEM;
+			}
+			ixj[*cnt] = j;
+
+			j->DSPbase = dspio[i];
+			request_region(j->DSPbase, 16, "ixj DSP");
+
+			j->XILINXbase = xio[i];
+			j->cardtype = 0;
+
+			probe = ixj_selfprobe(j, *cnt);
+			j->dev = NULL;
+
+			++*cnt;
 		}
 	}
-#endif				// !CONFIG_ISAPNP
-#endif				// CONFIG_PCMCIA
-#ifdef CONFIG_PCI
-	if (pci_present()) {
-		for (i = 0; i < IXJMAX - cnt; i++) {
-			pci = pci_find_device(0x15E2, 0x0500, pci);
-			if (!pci)
-				break;
-			if (pci_enable_device(pci))
-				break;
-			{
-				ixj[cnt].DSPbase = pci_resource_start(pci, 0);
-				ixj[cnt].XILINXbase = ixj[cnt].DSPbase + 0x10;
-				ixj[cnt].serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2);
-				result = check_region(ixj[cnt].DSPbase, 16);
-				if (result) {
-					printk(KERN_INFO "ixj: can't get I/O address 0x%x\n", ixj[cnt].DSPbase);
-					cleanup();
-					return result;
-				}
-				request_region(ixj[cnt].DSPbase, 16, "ixj DSP");
-				ixj[cnt].cardtype = 500;
-				probe = ixj_selfprobe(cnt);
-				if (probe)
-					printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", ixj[cnt].DSPbase);
-				cnt++;
+
+	return 0;
+}
+#endif /* CONFIG_ISAPNP */
+#endif /* CONFIG_PCMCIA */
+
+#if defined(CONFIG_PCI)
+int __init ixj_probe_pci(int *cnt)
+{
+	struct pci_dev *pci = NULL;
+	int i, probe = 0;
+
+	for (i = 0; i < IXJMAX - *cnt; i++) {
+		pci = pci_find_device(0x15E2, 0x0500, pci);
+		if (!pci)
+			break;
+		if (pci_enable_device(pci))
+			break;
+		{
+			IXJ *j;
+			int result;
+
+			if ((result = check_region(pci_resource_start(pci, 0), 16)) < 0) {
+				printk(KERN_INFO "ixj: can't get I/O address 0x%lx\n",
+				       pci_resource_start(pci, 0));
+				cleanup();
+				return result;
+			}
+
+			if ((j = kmalloc(sizeof(*j), GFP_KERNEL)) == NULL) {
+				cleanup();
+				return -ENOMEM;
 			}
+			ixj[*cnt] = j;
+
+			j->DSPbase = pci_resource_start(pci, 0);
+			request_region(j->DSPbase, 16, "ixj DSP");
+
+			j->XILINXbase = j->DSPbase + 0x10;
+			j->serial = (PCIEE_GetSerialNumber)pci_resource_start(pci, 2);
+			j->cardtype = QTI_PHONEJACK_PCI;
+
+			probe = ixj_selfprobe(j, *cnt);
+			if (probe)
+				printk(KERN_INFO "ixj: found Internet PhoneJACK PCI at 0x%x\n", j->DSPbase);
+			++*cnt;
 		}
 	}
-#endif
+
+	return probe;
+}
+#else
+extern __inline__ int ixj_probe_pci(int *cnt)
+{
+	return 0;
+}
+#endif /* CONFIG_PCI */
+
+int __init ixj_init(void)
+{
+	int cnt = 0;
+	int probe = 0;
+
+	/* These might be no-ops, see above. */
+	if ((probe = ixj_register_pcmcia()) < 0) {
+		return probe;
+	}
+	if ((probe = ixj_probe_isapnp(&cnt)) < 0) {
+		return probe;
+	}
+	if ((probe = ixj_probe_isa(&cnt)) < 0) {
+		return probe;
+	}
+	if (pci_present()) {
+		if ((probe = ixj_probe_pci(&cnt)) < 0) {
+			return probe;
+		}
+      	}
+
 	printk("%s\n", ixj_c_rcsid);
+
 	create_proc_read_entry ("ixj", 0, NULL, ixj_read_proc, NULL);
 	create_proc_read_entry ("ixjfsk", 0, NULL, ixj_read_proc_fsk, NULL);
+
 	ixj_init_timer();
 	ixj_add_timer();
+
 	return probe;
 }
 
 module_init(ixj_init);
 module_exit(ixj_exit);
 
-static void DAA_Coeff_US(int board)
+static void DAA_Coeff_US(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	int i;
 
 	j->daa_country = DAA_US;
@@ -6559,9 +6721,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
 }
 
-static void DAA_Coeff_UK(int board)
+static void DAA_Coeff_UK(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	int i;
 
 	j->daa_country = DAA_UK;
@@ -6740,9 +6901,8 @@
 }
 
 
-static void DAA_Coeff_France(int board)
+static void DAA_Coeff_France(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	int i;
 
 	j->daa_country = DAA_FRANCE;
@@ -6921,9 +7081,8 @@
 }
 
 
-static void DAA_Coeff_Germany(int board)
+static void DAA_Coeff_Germany(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	int i;
 
 	j->daa_country = DAA_GERMANY;
@@ -7102,9 +7261,8 @@
 }
 
 
-static void DAA_Coeff_Australia(int board)
+static void DAA_Coeff_Australia(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	int i;
 
 	j->daa_country = DAA_AUSTRALIA;
@@ -7282,9 +7440,8 @@
 	j->m_DAAShadowRegs.COP_REGS.COP.Tone2Coeff[0] = 0xB3;
 }
 
-static void DAA_Coeff_Japan(int board)
+static void DAA_Coeff_Japan(IXJ *j)
 {
-	IXJ *j = &ixj[board];
 	int i;
 
 	j->daa_country = DAA_JAPAN;
@@ -8998,34 +9155,34 @@
 		 0x0FF5		// shift-mask 0x0FF (look at 16 half-frames) bit count = 5
 	},
 };
-static int ixj_init_filter(int board, IXJ_FILTER * jf)
+static int ixj_init_filter(IXJ *j, IXJ_FILTER * jf)
 {
 	unsigned short cmd;
 	int cnt, max;
-	IXJ *j = &ixj[board];
+
 	if (jf->filter > 3) {
 		return -1;
 	}
-	if (ixj_WriteDSPCommand(0x5154 + jf->filter, board))	// Select Filter
+	if (ixj_WriteDSPCommand(0x5154 + jf->filter, j))	// Select Filter
 
 		return -1;
 	if (!jf->enable) {
-		if (ixj_WriteDSPCommand(0x5152, board))		// Disable Filter
+		if (ixj_WriteDSPCommand(0x5152, j))		// Disable Filter
 
 			return -1;
 		else
 			return 0;
 	} else {
-		if (ixj_WriteDSPCommand(0x5153, board))		// Enable Filter
+		if (ixj_WriteDSPCommand(0x5153, j))		// Enable Filter
 
 			return -1;
 		// Select the filter (f0 - f3) to use.
-		if (ixj_WriteDSPCommand(0x5154 + jf->filter, board))
+		if (ixj_WriteDSPCommand(0x5154 + jf->filter, j))
 			return -1;
 	}
 	if (jf->freq < 12 && jf->freq > 3) {
 		// Select the frequency for the selected filter.
-		if (ixj_WriteDSPCommand(0x5170 + jf->freq, board))
+		if (ixj_WriteDSPCommand(0x5170 + jf->freq, j))
 			return -1;
 	} else if (jf->freq > 11) {
 		// We need to load a programmable filter set for undefined
@@ -9033,7 +9190,7 @@
 		// Since there are only 4 filters and 4 programmable sets, we will
 		// just point the filter to the same number set and program it for the
 		// frequency we want.
-		if (ixj_WriteDSPCommand(0x5170 + jf->filter, board))
+		if (ixj_WriteDSPCommand(0x5170 + jf->filter, j))
 			return -1;
 		if (j->ver.low != 0x12) {
 			cmd = 0x515B;
@@ -9042,10 +9199,10 @@
 			cmd = 0x515E;
 			max = 15;
 		}
-		if (ixj_WriteDSPCommand(cmd, board))
+		if (ixj_WriteDSPCommand(cmd, j))
 			return -1;
 		for (cnt = 0; cnt < max; cnt++) {
-			if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], board))
+			if (ixj_WriteDSPCommand(tone_table[jf->freq - 12][cnt], j))
 				return -1;
 		}
 	}
@@ -9053,7 +9210,7 @@
 	return 0;
 }
 
-static int ixj_init_tone(int board, IXJ_TONE * ti)
+static int ixj_init_tone(IXJ *j, IXJ_TONE * ti)
 {
 	int freq0, freq1;
 	unsigned short data;
@@ -9071,15 +9228,15 @@
 
 	if(ti->tone_index > 12 && ti->tone_index < 28)
 	{
-		if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, board))
+		if (ixj_WriteDSPCommand(0x6800 + ti->tone_index, j))
 			return -1;
-		if (ixj_WriteDSPCommand(0x6000 + (ti->gain0 << 4) + ti->gain1, board))
+		if (ixj_WriteDSPCommand(0x6000 + (ti->gain0 << 4) + ti->gain1, j))
 			return -1;
 		data = freq0;
-		if (ixj_WriteDSPCommand(data, board))
+		if (ixj_WriteDSPCommand(data, j))
 			return -1;
 		data = freq1;
-		if (ixj_WriteDSPCommand(data, board))
+		if (ixj_WriteDSPCommand(data, j))
 			return -1;
 	}
 	return freq0;
diff -u --recursive --new-file v2.4.1/linux/drivers/telephony/ixj.h linux/drivers/telephony/ixj.h
--- v2.4.1/linux/drivers/telephony/ixj.h	Fri Dec 29 14:35:47 2000
+++ linux/drivers/telephony/ixj.h	Sun Feb  4 10:05:29 2001
@@ -93,8 +93,6 @@
 	  char  cbyte;
 } IXJ_CBYTE;
 
-int ixj_WriteDSPCommand(unsigned short, int board);
-
 /******************************************************************************
 *
 *  This structure represents the Hardware Control Register of the CT8020/8021
@@ -1280,6 +1278,8 @@
 	short fskdata[8000];
 	int fskdcnt;
 } IXJ;
+
+int ixj_WriteDSPCommand(unsigned short, IXJ *);
 
 typedef int (*IXJ_REGFUNC) (IXJ * j, unsigned long arg);
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/acm.c linux/drivers/usb/acm.c
--- v2.4.1/linux/drivers/usb/acm.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/acm.c	Fri Feb 16 16:06:17 2001
@@ -45,11 +45,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #undef DEBUG
 #include <linux/usb.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/audio.c linux/drivers/usb/audio.c
--- v2.4.1/linux/drivers/usb/audio.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/audio.c	Fri Feb  9 11:30:23 2001
@@ -170,7 +170,7 @@
 
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/bluetooth.c linux/drivers/usb/bluetooth.c
--- v2.4.1/linux/drivers/usb/bluetooth.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/bluetooth.c	Fri Feb  9 11:30:23 2001
@@ -75,11 +75,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 
 #define DEBUG
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/dc2xx.c linux/drivers/usb/dc2xx.c
--- v2.4.1/linux/drivers/usb/dc2xx.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/dc2xx.c	Fri Feb  9 11:30:23 2001
@@ -60,7 +60,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 
 #ifdef CONFIG_USB_DEBUG
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/dsbr100.c linux/drivers/usb/dsbr100.c
--- v2.4.1/linux/drivers/usb/dsbr100.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/dsbr100.c	Fri Feb  9 11:30:23 2001
@@ -60,7 +60,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/videodev.h>
 #include <linux/usb.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/hid.c linux/drivers/usb/hid.c
--- v2.4.1/linux/drivers/usb/hid.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/hid.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
  */
 
 #include <linux/module.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/hid.h linux/drivers/usb/hid.h
--- v2.4.1/linux/drivers/usb/hid.h	Mon Dec 11 13:17:49 2000
+++ linux/drivers/usb/hid.h	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/list.h>
 
 /*
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/hub.c linux/drivers/usb/hub.c
--- v2.4.1/linux/drivers/usb/hub.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/hub.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/list.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/ibmcam.c linux/drivers/usb/ibmcam.c
--- v2.4.1/linux/drivers/usb/ibmcam.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/ibmcam.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/list.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/videodev.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/mdc800.c linux/drivers/usb/mdc800.c
--- v2.4.1/linux/drivers/usb/mdc800.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/mdc800.c	Fri Feb  9 11:30:23 2001
@@ -84,7 +84,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/microtek.c linux/drivers/usb/microtek.c
--- v2.4.1/linux/drivers/usb/microtek.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/microtek.c	Fri Feb  9 11:30:23 2001
@@ -114,7 +114,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/smp_lock.h>
 #include <linux/usb.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/pegasus.c linux/drivers/usb/pegasus.c
--- v2.4.1/linux/drivers/usb/pegasus.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/pegasus.c	Fri Feb  9 11:30:23 2001
@@ -41,7 +41,7 @@
 
 
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/printer.c linux/drivers/usb/printer.c
--- v2.4.1/linux/drivers/usb/printer.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/printer.c	Tue Feb 13 16:40:24 2001
@@ -17,6 +17,7 @@
  *	v0.4 - fixes in unidirectional mode
  *	v0.5 - add DEVICE_ID string support
  *	v0.6 - never time out
+ *	v0.? - fixed bulk-IN read and poll (David Paschal, paschal@rcsis.com)
  */
 
 /*
@@ -42,7 +43,7 @@
 #include <linux/signal.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/lp.h>
 #undef DEBUG
 #include <linux/usb.h>
@@ -256,8 +257,8 @@
 {
 	struct usblp *usblp = file->private_data;
 	poll_wait(file, &usblp->wait, wait);
-	return ((usblp->bidir || usblp->readurb.status  == -EINPROGRESS) ? 0 : POLLIN  | POLLRDNORM)
-	     		      | (usblp->writeurb.status == -EINPROGRESS  ? 0 : POLLOUT | POLLWRNORM);
+ 	return ((!usblp->bidir || usblp->readurb.status  == -EINPROGRESS) ? 0 : POLLIN  | POLLRDNORM)
+ 			       | (usblp->writeurb.status == -EINPROGRESS  ? 0 : POLLOUT | POLLWRNORM);
 }
 
 static int usblp_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
@@ -404,6 +405,7 @@
 		err("usblp%d: error %d reading from printer",
 			usblp->minor, usblp->readurb.status);
 		usblp->readurb.dev = usblp->dev;
+ 		usblp->readcount = 0;
 		usb_submit_urb(&usblp->readurb);
 		return -EIO;
 	}
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/rio500.c linux/drivers/usb/rio500.c
--- v2.4.1/linux/drivers/usb/rio500.c	Sat Feb  3 19:51:29 2001
+++ linux/drivers/usb/rio500.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/random.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/usb.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/scanner.h linux/drivers/usb/scanner.h
--- v2.4.1/linux/drivers/usb/scanner.h	Mon Dec 11 13:17:51 2000
+++ linux/drivers/usb/scanner.h	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/errno.h>
 #include <asm/uaccess.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/ioctl.h>
 #include <linux/sched.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/belkin_sa.c linux/drivers/usb/serial/belkin_sa.c
--- v2.4.1/linux/drivers/usb/serial/belkin_sa.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/belkin_sa.c	Fri Feb  9 11:30:23 2001
@@ -57,11 +57,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/digi_acceleport.c linux/drivers/usb/serial/digi_acceleport.c
--- v2.4.1/linux/drivers/usb/serial/digi_acceleport.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/digi_acceleport.c	Fri Feb  9 11:30:23 2001
@@ -233,11 +233,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/tqueue.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/empeg.c linux/drivers/usb/serial/empeg.c
--- v2.4.1/linux/drivers/usb/serial/empeg.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/empeg.c	Fri Feb  9 11:30:23 2001
@@ -13,9 +13,16 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  * 
+ * (01/22/2001) gb
+ *	Added write_room() and chars_in_buffer() support. 
+ * 
+ * (12/21/2000) gb
+ *	Moved termio stuff inside the port->active check.
+ *	Moved MOD_DEC_USE_COUNT to end of empeg_close().
+ * 
  * (12/03/2000) gb
  *	Added port->tty->ldisc.set_termios(port->tty, NULL) to empeg_open()
- *      This notifies the tty driver that the termios have changed.
+ *	This notifies the tty driver that the termios have changed.
  * 
  * (11/13/2000) gb
  *	Moved tty->low_latency = 1 from empeg_read_bulk_callback() to empeg_open()
@@ -41,11 +48,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #ifdef CONFIG_USB_SERIAL_DEBUG
@@ -57,27 +64,35 @@
 
 #include "usb-serial.h"
 
-#define EMPEG_VENDOR_ID                 0x084f
-#define EMPEG_PRODUCT_ID                0x0001
+#define EMPEG_VENDOR_ID			0x084f
+#define EMPEG_PRODUCT_ID		0x0001
 
 #define MIN(a,b)		(((a)<(b))?(a):(b))
 
 /* function prototypes for an empeg-car player */
-static int  empeg_open		(struct usb_serial_port *port, struct file *filp);
-static void empeg_close		(struct usb_serial_port *port, struct file *filp);
-static int  empeg_write		(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
-static void empeg_throttle	(struct usb_serial_port *port);
-static void empeg_unthrottle	(struct usb_serial_port *port);
-static int  empeg_startup	(struct usb_serial *serial);
-static void empeg_shutdown	(struct usb_serial *serial);
-static int  empeg_ioctl		(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg);
-static void empeg_set_termios	(struct usb_serial_port *port, struct termios *old_termios);
+static int  empeg_open			(struct usb_serial_port *port, struct file *filp);
+static void empeg_close			(struct usb_serial_port *port, struct file *filp);
+static int  empeg_write			(struct usb_serial_port *port,
+					int from_user,
+					const unsigned char *buf,
+					int count);
+static int  empeg_write_room		(struct usb_serial_port *port);
+static int  empeg_chars_in_buffer	(struct usb_serial_port *port);
+static void empeg_throttle		(struct usb_serial_port *port);
+static void empeg_unthrottle		(struct usb_serial_port *port);
+static int  empeg_startup		(struct usb_serial *serial);
+static void empeg_shutdown		(struct usb_serial *serial);
+static int  empeg_ioctl			(struct usb_serial_port *port,
+					struct file * file,
+					unsigned int cmd,
+					unsigned long arg);
+static void empeg_set_termios		(struct usb_serial_port *port, struct termios *old_termios);
 static void empeg_write_bulk_callback	(struct urb *urb);
 static void empeg_read_bulk_callback	(struct urb *urb);
 
 static __devinitdata struct usb_device_id id_table [] = {
 	{ USB_DEVICE(EMPEG_VENDOR_ID, EMPEG_PRODUCT_ID) },
-        { }                                     /* Terminating entry */
+	{ }					/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table);
@@ -101,6 +116,8 @@
 	ioctl:			empeg_ioctl,
 	set_termios:		empeg_set_termios,
 	write:			empeg_write,
+	write_room:		empeg_write_room,
+	chars_in_buffer:	empeg_chars_in_buffer,
 	write_bulk_callback:	empeg_write_bulk_callback,
 	read_bulk_callback:	empeg_read_bulk_callback,
 };
@@ -132,64 +149,58 @@
 	++port->open_count;
 	MOD_INC_USE_COUNT;
 
-	/* gb - 2000/11/05
-	 *
-	 * personally, I think these termios should be set in
-	 * empeg_startup(), but it appears doing so leads to one
-	 * of those chicken/egg problems. :)
-	 *
-	 */
-	port->tty->termios->c_iflag
-		&= ~(IGNBRK
-		| BRKINT
-		| PARMRK
-		| ISTRIP
-		| INLCR
-		| IGNCR
-		| ICRNL
-		| IXON);
-
-	port->tty->termios->c_oflag
-		&= ~OPOST;
-
-	port->tty->termios->c_lflag
-		&= ~(ECHO
-		| ECHONL
-		| ICANON
-		| ISIG
-		| IEXTEN);
-
-	port->tty->termios->c_cflag
-		&= ~(CSIZE
-		| PARENB);
-
-	port->tty->termios->c_cflag
-		|= CS8;
-
-	/* gb - 2000/12/03
-	 *
-	 * Contributed by Borislav Deianov
-	 *
-	 * Notify the tty driver that the termios have changed!!
-	 *
-	 */
-        port->tty->ldisc.set_termios(port->tty, NULL);
-
-	/* gb - 2000/11/05
-	 *
-	 * force low_latency on
-	 *
-	 * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually
-	 * force the data through if low_latency is set.  Otherwise the pushes are
-	 * scheduled; this is bad as it opens up the possibility of dropping bytes
-	 * on the floor.  We are trying to sustain high data transfer rates; and
-	 * don't want to drop bytes on the floor.
-	 * Moral: use low_latency - drop no bytes - life is good. :)
-	 *
-	 */
-	port->tty->low_latency = 1;
-
 	if (!port->active) {
+
+		/* gb - 2000/11/05
+		 * personally, I think these termios should be set in
+		 * empeg_startup(), but it appears doing so leads to one
+		 * of those chicken/egg problems. :)
+		 */
+		port->tty->termios->c_iflag
+			&= ~(IGNBRK
+			| BRKINT
+			| PARMRK
+			| ISTRIP
+			| INLCR
+			| IGNCR
+			| ICRNL
+			| IXON);
+
+		port->tty->termios->c_oflag
+			&= ~OPOST;
+
+		port->tty->termios->c_lflag
+			&= ~(ECHO
+			| ECHONL
+			| ICANON
+			| ISIG
+			| IEXTEN);
+
+		port->tty->termios->c_cflag
+			&= ~(CSIZE
+			| PARENB);
+
+		port->tty->termios->c_cflag
+			|= CS8;
+
+		/* gb - 2000/12/03
+		 * Contributed by Borislav Deianov
+		 * Notify the tty driver that the termios have changed!!
+		 */
+		port->tty->ldisc.set_termios(port->tty, NULL);
+
+		/* gb - 2000/11/05
+		 * force low_latency on
+		 *
+		 * The tty_flip_buffer_push()'s in empeg_read_bulk_callback() will actually
+		 * force the data through if low_latency is set.  Otherwise the pushes are
+		 * scheduled; this is bad as it opens up the possibility of dropping bytes
+		 * on the floor.  We are trying to sustain high data transfer rates; and
+		 * don't want to drop bytes on the floor.
+		 * Moral: use low_latency - drop no bytes - life is good. :)
+		 */
+		port->tty->low_latency = 1;
+
 		port->active = 1;
 		bytes_in = 0;
 		bytes_out = 0;
@@ -238,7 +249,6 @@
 	spin_lock_irqsave (&port->port_lock, flags);
 
 	--port->open_count;
-	MOD_DEC_USE_COUNT;
 
 	if (port->open_count <= 0) {
 		transfer_buffer =  kmalloc (0x12, GFP_KERNEL);
@@ -260,6 +270,8 @@
 	/* Uncomment the following line if you want to see some statistics in your syslog */
 	/* info ("Bytes In = %d  Bytes Out = %d", bytes_in, bytes_out); */
 
+	MOD_DEC_USE_COUNT;
+
 }
 
 
@@ -315,8 +327,6 @@
 			memcpy (urb->transfer_buffer, current_position, transfer_size);
 		}
 
-		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
 		/* build up our urb */
 		FILL_BULK_URB (
 			urb,
@@ -348,6 +358,58 @@
 } 
 
 
+static int empeg_write_room (struct usb_serial_port *port)
+{
+	unsigned long flags;
+	int i;
+	int room = 0;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	/* tally up the number of bytes available */
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (write_urb_pool[i]->status != -EINPROGRESS) {
+			room += URB_TRANSFER_BUFFER_SIZE;
+		}
+	} 
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	dbg(__FUNCTION__ " - returns %d", room);
+
+	return (room);
+
+}
+
+
+static int empeg_chars_in_buffer (struct usb_serial_port *port)
+{
+	unsigned long flags;
+	int i;
+	int chars = 0;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	/* tally up the number of bytes waiting */
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (write_urb_pool[i]->status == -EINPROGRESS) {
+			chars += URB_TRANSFER_BUFFER_SIZE;
+		}
+	}
+
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	dbg (__FUNCTION__ " - returns %d", chars);
+
+	return (chars);
+
+}
+
+
 static void empeg_write_bulk_callback (struct urb *urb)
 {
 	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
@@ -407,9 +469,6 @@
 			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
 				tty_flip_buffer_push(tty);
 				}
-			/* gb - 2000/11/13
-			 * This doesn't push the data through unless tty->low_latency is set.
-			 */
 			tty_insert_flip_char(tty, data[i], 0);
 		}
 		/* gb - 2000/11/13
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/ftdi_sio.c linux/drivers/usb/serial/ftdi_sio.c
--- v2.4.1/linux/drivers/usb/serial/ftdi_sio.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/ftdi_sio.c	Fri Feb  9 11:30:23 2001
@@ -71,11 +71,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/keyspan.c linux/drivers/usb/serial/keyspan.c
--- v2.4.1/linux/drivers/usb/serial/keyspan.c	Mon Dec 11 13:47:32 2000
+++ linux/drivers/usb/serial/keyspan.c	Fri Feb  9 11:30:23 2001
@@ -55,11 +55,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/keyspan_pda.c linux/drivers/usb/serial/keyspan_pda.c
--- v2.4.1/linux/drivers/usb/serial/keyspan_pda.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/keyspan_pda.c	Fri Feb  9 11:30:23 2001
@@ -59,11 +59,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/tqueue.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/mct_u232.c linux/drivers/usb/serial/mct_u232.c
--- v2.4.1/linux/drivers/usb/serial/mct_u232.c	Thu Dec  7 16:13:38 2000
+++ linux/drivers/usb/serial/mct_u232.c	Fri Feb  9 11:30:23 2001
@@ -24,6 +24,10 @@
  *   Basic tests have been performed with minicom/zmodem transfers and
  *   modem dialing under Linux 2.4.0-test10 (for me it works fine).
  *
+ * 06-Jan-2001 Cornel Ciocirlan 
+ *   - Added support for Sitecom U232-P25 model (Product Id 0x0230)
+ *   - Added support for D-Link DU-H3SP USB BAY (Product Id 0x0200)
+ *
  * 29-Nov-2000 Greg Kroah-Hartman
  *   - Added device id table to fit with 2.4.0-test11 structure.
  *   - took out DEAL_WITH_TWO_INT_IN_ENDPOINTS #define as it's not needed
@@ -42,11 +46,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
@@ -101,17 +105,34 @@
 /*
  * All of the device info needed for the MCT USB-RS232 converter.
  */
-static __devinitdata struct usb_device_id id_table [] = {
-	{ idVendor: MCT_U232_VID, idProduct: MCT_U232_PID },
-	{ }					/* Terminating entry */
+static __devinitdata struct usb_device_id id_table_combined [] = {
+	{ USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
+	{ USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
+	{ USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
+	{ }		/* Terminating entry */
+};
+
+static __devinitdata struct usb_device_id mct_u232_table [] = {
+        { USB_DEVICE(MCT_U232_VID, MCT_U232_PID) },
+        { }                        /* Terminating entry */
 };
 
-MODULE_DEVICE_TABLE (usb, id_table);
+static __devinitdata struct usb_device_id mct_u232_sitecom_table [] = {
+        { USB_DEVICE(MCT_U232_VID, MCT_U232_SITECOM_PID) },
+        { }                        /* Terminating entry */
+};
+
+static __devinitdata struct usb_device_id mct_u232_du_h3sp_table [] = {
+        { USB_DEVICE(MCT_U232_VID, MCT_U232_DU_H3SP_PID) },
+        { }                        /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE (usb, id_table_combined);
 
 
 struct usb_serial_device_type mct_u232_device = {
 	name:		     "Magic Control Technology USB-RS232",
-	id_table:	     id_table,
+	id_table:	     mct_u232_table,
 	needs_interrupt_in:  MUST_HAVE,	 /* 2 interrupt-in endpoints */
 	needs_bulk_in:	     MUST_HAVE_NOT,   /* no bulk-in endpoint */
 	needs_bulk_out:	     MUST_HAVE,	      /* 1 bulk-out endpoint */
@@ -133,6 +154,57 @@
 	shutdown:	     mct_u232_shutdown,
 };
 
+struct usb_serial_device_type mct_u232_sitecom_device = {
+	name:		     "MCT/Sitecom USB-RS232",
+	id_table:	     mct_u232_sitecom_table,
+	needs_interrupt_in:  MUST_HAVE,	 /* 2 interrupt-in endpoints */
+	needs_bulk_in:	     MUST_HAVE_NOT,   /* no bulk-in endpoint */
+	needs_bulk_out:	     MUST_HAVE,	      /* 1 bulk-out endpoint */
+	num_interrupt_in:    2,
+	num_bulk_in:	     0,
+	num_bulk_out:	     1,
+	num_ports:	     1,
+	open:		     mct_u232_open,
+	close:		     mct_u232_close,
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+	write:		     mct_u232_write,
+	write_bulk_callback: mct_u232_write_bulk_callback,
+#endif
+	read_int_callback:   mct_u232_read_int_callback,
+	ioctl:		     mct_u232_ioctl,
+	set_termios:	     mct_u232_set_termios,
+	break_ctl:	     mct_u232_break_ctl,
+	startup:	     mct_u232_startup,
+	shutdown:	     mct_u232_shutdown,
+};
+
+struct usb_serial_device_type mct_u232_du_h3sp_device = {
+        name:                "MCT/D-Link DU-H3SP USB BAY",
+        id_table:            mct_u232_du_h3sp_table,
+        needs_interrupt_in:  MUST_HAVE,  /* 2 interrupt-in endpoints */
+        needs_bulk_in:       MUST_HAVE_NOT,   /* no bulk-in endpoint */
+        needs_bulk_out:      MUST_HAVE,       /* 1 bulk-out endpoint */
+        num_interrupt_in:    2,
+        num_bulk_in:         0,
+        num_bulk_out:        1,
+        num_ports:           1,
+        open:                mct_u232_open,
+        close:               mct_u232_close,
+#ifdef FIX_WRITE_RETURN_CODE_PROBLEM
+        write:               mct_u232_write,
+        write_bulk_callback: mct_u232_write_bulk_callback,
+#endif
+        read_int_callback:   mct_u232_read_int_callback,
+        ioctl:               mct_u232_ioctl,
+        set_termios:         mct_u232_set_termios,
+        break_ctl:           mct_u232_break_ctl,
+        startup:             mct_u232_startup,
+        shutdown:            mct_u232_shutdown,
+};
+
+
+
+
 struct mct_u232_private {
 	unsigned long	     control_state; /* Modem Line Setting (TIOCM) */
 	unsigned char        last_lcr;      /* Line Control Register */
@@ -750,6 +822,8 @@
 static int __init mct_u232_init (void)
 {
 	usb_serial_register (&mct_u232_device);
+	usb_serial_register (&mct_u232_sitecom_device);
+	usb_serial_register (&mct_u232_du_h3sp_device);
 	
 	return 0;
 }
@@ -758,6 +832,8 @@
 static void __exit mct_u232_exit (void)
 {
 	usb_serial_deregister (&mct_u232_device);
+	usb_serial_deregister (&mct_u232_sitecom_device);
+	usb_serial_deregister (&mct_u232_du_h3sp_device);
 }
 
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/mct_u232.h linux/drivers/usb/serial/mct_u232.h
--- v2.4.1/linux/drivers/usb/serial/mct_u232.h	Thu Dec  7 16:13:38 2000
+++ linux/drivers/usb/serial/mct_u232.h	Thu Feb  8 16:30:40 2001
@@ -24,7 +24,14 @@
 #define __LINUX_USB_SERIAL_MCT_U232_H
 
 #define MCT_U232_VID	                0x0711	/* Vendor Id */
-#define MCT_U232_PID	                0x0210	/* Product Id */
+#define MCT_U232_PID	                0x0210	/* Original MCT Product Id */
+
+/* U232-P25, Sitecom */
+#define MCT_U232_SITECOM_PID		0x0230	/* Sitecom Product Id */
+
+/* DU-H3SP USB BAY hub */
+
+#define MCT_U232_DU_H3SP_PID		0x0200	/* D-Link DU-H3SP USB BAY */
 
 /*
  * Vendor Request Interface
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/omninet.c linux/drivers/usb/serial/omninet.c
--- v2.4.1/linux/drivers/usb/serial/omninet.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/omninet.c	Fri Feb  9 11:30:23 2001
@@ -36,11 +36,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/usbserial.c linux/drivers/usb/serial/usbserial.c
--- v2.4.1/linux/drivers/usb/serial/usbserial.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/usb/serial/usbserial.c	Fri Feb  9 11:30:23 2001
@@ -15,6 +15,14 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * 2001_02_05 gkh
+ *	Fixed buffer overflows bug with the generic serial driver.  Thanks to
+ *	Todd Squires <squirest@ct0.com> for fixing this.
+ *
+ * (01/10/2001) gkh
+ *	Fixed bug where the generic serial adaptor grabbed _any_ device that was
+ *	offered to it.
+ *
  * (12/12/2000) gkh
  *	Removed MOD_INC and MOD_DEC from poll and disconnect functions, and
  *	moved them to the serial_open and serial_close functions.
@@ -255,11 +263,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/list.h>
@@ -742,6 +750,11 @@
 	if (!port->active) {
 		port->active = 1;
 
+		/* force low_latency on so that our tty_push actually forces the data through, 
+		   otherwise it is scheduled, and with high data rates (like with OHCI) data
+		   can get lost. */
+		port->tty->low_latency = 1;
+		
 		/* if we have a bulk interrupt, start reading from it */
 		if (serial->num_bulk_in) {
 			/* Start reading from the device */
@@ -907,8 +920,13 @@
 	tty = port->tty;
 	if (urb->actual_length) {
 		for (i = 0; i < urb->actual_length ; ++i) {
-			 tty_insert_flip_char(tty, data[i], 0);
-	  	}
+			/* if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. */
+			if(tty->flip.count >= TTY_FLIPBUF_SIZE) {
+				tty_flip_buffer_push(tty);
+			}
+			/* this doesn't actually push the data through unless tty->low_latency is set */
+			tty_insert_flip_char(tty, data[i], 0);
+		}
 	  	tty_flip_buffer_push(tty);
 	}
 
@@ -1361,6 +1379,7 @@
 #ifdef CONFIG_USB_SERIAL_GENERIC
 	generic_device_ids[0].idVendor = vendor;
 	generic_device_ids[0].idProduct = product;
+	generic_device_ids[0].match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT;
 	/* register our generic driver with ourselves */
 	usb_serial_register (&generic_device);
 #endif
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/visor.c linux/drivers/usb/serial/visor.c
--- v2.4.1/linux/drivers/usb/serial/visor.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/usb/serial/visor.c	Fri Feb  9 11:30:23 2001
@@ -11,6 +11,13 @@
  *
  * See Documentation/usb/usb-serial.txt for more information on using this driver
  *
+ * (01/21/2000) gkh
+ *	Added write_room and chars_in_buffer, as they were previously using the
+ *	generic driver versions which is all wrong now that we are using an urb
+ *	pool.  Thanks to Wolfgang Grandegger for pointing this out to me.
+ *	Removed count assignment in the write function, which was not needed anymore
+ *	either.  Thanks to Al Borchers for pointing this out.
+ *
  * (12/12/2000) gkh
  *	Moved MOD_DEC to end of visor_close to be nicer, as the final write 
  *	message can sleep.
@@ -78,11 +85,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
@@ -103,6 +110,8 @@
 static int  visor_open		(struct usb_serial_port *port, struct file *filp);
 static void visor_close		(struct usb_serial_port *port, struct file *filp);
 static int  visor_write		(struct usb_serial_port *port, int from_user, const unsigned char *buf, int count);
+static int  visor_write_room		(struct usb_serial_port *port);
+static int  visor_chars_in_buffer	(struct usb_serial_port *port);
 static void visor_throttle	(struct usb_serial_port *port);
 static void visor_unthrottle	(struct usb_serial_port *port);
 static int  visor_startup	(struct usb_serial *serial);
@@ -142,6 +151,8 @@
 	ioctl:			visor_ioctl,
 	set_termios:		visor_set_termios,
 	write:			visor_write,
+	write_room:		visor_write_room,
+	chars_in_buffer:	visor_chars_in_buffer,
 	write_bulk_callback:	visor_write_bulk_callback,
 	read_bulk_callback:	visor_read_bulk_callback,
 };
@@ -289,8 +300,6 @@
 		else
 			memcpy (urb->transfer_buffer, current_position, transfer_size);
 		
-		count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
-
 		/* build up our urb */
 		FILL_BULK_URB (urb, serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), 
 				urb->transfer_buffer, transfer_size, visor_write_bulk_callback, port);
@@ -310,6 +319,52 @@
 exit:
 	return bytes_sent;
 } 
+
+
+static int visor_write_room (struct usb_serial_port *port)
+{
+	unsigned long flags;
+	int i;
+	int room = 0;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+	
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (write_urb_pool[i]->status != -EINPROGRESS) {
+			room += URB_TRANSFER_BUFFER_SIZE;
+		}
+	}
+	
+	spin_unlock_irqrestore (&port->port_lock, flags);
+	
+	dbg(__FUNCTION__ " - returns %d", room);
+	return (room);
+}
+
+
+static int visor_chars_in_buffer (struct usb_serial_port *port)
+{
+	unsigned long flags;
+	int i;
+	int chars = 0;
+
+	dbg(__FUNCTION__ " - port %d", port->number);
+	
+	spin_lock_irqsave (&port->port_lock, flags);
+
+	for (i = 0; i < NUM_URBS; ++i) {
+		if (write_urb_pool[i]->status == -EINPROGRESS) {
+			chars += URB_TRANSFER_BUFFER_SIZE;
+		}
+	}
+	
+	spin_unlock_irqrestore (&port->port_lock, flags);
+
+	dbg (__FUNCTION__ " - returns %d", chars);
+	return (chars);
+}
 
 
 static void visor_write_bulk_callback (struct urb *urb)
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/serial/whiteheat.c linux/drivers/usb/serial/whiteheat.c
--- v2.4.1/linux/drivers/usb/serial/whiteheat.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/serial/whiteheat.c	Fri Feb  9 11:30:23 2001
@@ -55,11 +55,11 @@
 #include <linux/errno.h>
 #include <linux/poll.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/tty_flip.h>
-#include <linux/tty.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/storage/scsiglue.c linux/drivers/usb/storage/scsiglue.c
--- v2.4.1/linux/drivers/usb/storage/scsiglue.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/usb/storage/scsiglue.c	Fri Feb  9 11:30:23 2001
@@ -49,7 +49,7 @@
 #include "debug.h"
 #include "transport.h"
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 /*
  * kernel thread actions
@@ -248,7 +248,7 @@
         for (i = 0; i < us->pusb_dev->actconfig->bNumInterfaces; i++) {
  		struct usb_interface *intf =
 			&us->pusb_dev->actconfig->interface[i];
-		struct usb_device_id *id;
+		const struct usb_device_id *id;
 
 		/* if this is an unclaimed interface, skip it */
 		if (!intf->driver) {
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/storage/sddr09.c linux/drivers/usb/storage/sddr09.c
--- v2.4.1/linux/drivers/usb/storage/sddr09.c	Tue Nov 28 21:50:07 2000
+++ linux/drivers/usb/storage/sddr09.c	Fri Feb  9 11:30:23 2001
@@ -38,7 +38,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) )
 #define LSB_of(s) ((s)&0xFF)
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/storage/shuttle_usbat.c linux/drivers/usb/storage/shuttle_usbat.c
--- v2.4.1/linux/drivers/usb/storage/shuttle_usbat.c	Tue Nov 28 21:50:07 2000
+++ linux/drivers/usb/storage/shuttle_usbat.c	Fri Feb  9 11:30:23 2001
@@ -44,7 +44,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 extern int usb_stor_control_msg(struct us_data *us, unsigned int pipe,
 	u8 request, u8 requesttype, u16 value, u16 index,
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/storage/transport.c linux/drivers/usb/storage/transport.c
--- v2.4.1/linux/drivers/usb/storage/transport.c	Tue Nov 28 21:50:07 2000
+++ linux/drivers/usb/storage/transport.c	Fri Feb  9 11:30:23 2001
@@ -52,7 +52,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 /***********************************************************************
  * Helper routines
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/storage/usb.c linux/drivers/usb/storage/usb.c
--- v2.4.1/linux/drivers/usb/storage/usb.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/usb/storage/usb.c	Fri Feb  9 11:30:23 2001
@@ -70,7 +70,7 @@
 #include <linux/sched.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 /* Some informational data */
 MODULE_AUTHOR("Matthew Dharm <mdharm-usb@one-eyed-alien.net>");
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/uhci.c linux/drivers/usb/uhci.c
--- v2.4.1/linux/drivers/usb/uhci.c	Thu Dec  7 16:42:28 2000
+++ linux/drivers/usb/uhci.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/usb-debug.c linux/drivers/usb/usb-debug.c
--- v2.4.1/linux/drivers/usb/usb-debug.c	Thu Mar 30 18:00:01 2000
+++ linux/drivers/usb/usb-debug.c	Fri Feb  9 11:30:23 2001
@@ -8,7 +8,7 @@
 #include <linux/version.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #ifdef CONFIG_USB_DEBUG
 	#define DEBUG
 #else
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/usb-ohci.c linux/drivers/usb/usb-ohci.c
--- v2.4.1/linux/drivers/usb/usb-ohci.c	Tue Nov 14 23:36:01 2000
+++ linux/drivers/usb/usb-ohci.c	Fri Feb  9 11:30:23 2001
@@ -47,7 +47,7 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/usb-uhci.c linux/drivers/usb/usb-uhci.c
--- v2.4.1/linux/drivers/usb/usb-uhci.c	Sat Dec  9 10:14:11 2000
+++ linux/drivers/usb/usb-uhci.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/errno.h>
 #include <linux/unistd.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/usb.c linux/drivers/usb/usb.c
--- v2.4.1/linux/drivers/usb/usb.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/usb.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/bitops.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>  /* for in_interrupt() */
 #include <linux/kmod.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/usbkbd.c linux/drivers/usb/usbkbd.c
--- v2.4.1/linux/drivers/usb/usbkbd.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/usbkbd.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/input.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/usbmouse.c linux/drivers/usb/usbmouse.c
--- v2.4.1/linux/drivers/usb/usbmouse.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/usbmouse.c	Fri Feb  9 11:30:23 2001
@@ -29,7 +29,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/usb/wacom.c linux/drivers/usb/wacom.c
--- v2.4.1/linux/drivers/usb/wacom.c	Thu Jan  4 13:15:32 2001
+++ linux/drivers/usb/wacom.c	Fri Feb  9 11:30:23 2001
@@ -51,7 +51,7 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -285,7 +285,7 @@
 
 struct wacom_features wacom_features[] = {
 	{ "Wacom Graphire",      8, 10206,  7422,  511, 32, wacom_graphire_irq,
-		BIT(EV_REL), 0, REL_WHEEL, 0 },
+		BIT(EV_REL), 0, BIT(REL_WHEEL), 0 },
 	{ "Wacom Intuos 4x5",   10, 12700, 10360, 1023, 15, wacom_intuos_irq,
 		0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
 	{ "Wacom Intuos 6x8",   10, 20320, 15040, 1023, 15, wacom_intuos_irq,
diff -u --recursive --new-file v2.4.1/linux/drivers/video/S3triofb.c linux/drivers/video/S3triofb.c
--- v2.4.1/linux/drivers/video/S3triofb.c	Tue Nov  7 10:59:43 2000
+++ linux/drivers/video/S3triofb.c	Fri Feb  9 11:30:23 2001
@@ -30,7 +30,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/acornfb.c linux/drivers/video/acornfb.c
--- v2.4.1/linux/drivers/video/acornfb.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/video/acornfb.c	Fri Feb  9 11:30:23 2001
@@ -23,7 +23,7 @@
 #include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fb.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/amifb.c linux/drivers/video/amifb.c
--- v2.4.1/linux/drivers/video/amifb.c	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/amifb.c	Fri Feb  9 11:30:23 2001
@@ -46,7 +46,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/config.h>
 #include <linux/interrupt.h>
@@ -1534,7 +1534,7 @@
 			}
 			return i;
 		}
-#endif */ DEBUG */
+#endif	/* DEBUG */
 	}
 	return -EINVAL;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.4.1/linux/drivers/video/atafb.c	Mon Nov 27 18:00:49 2000
+++ linux/drivers/video/atafb.c	Fri Feb  9 11:30:23 2001
@@ -54,7 +54,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/aty128fb.c linux/drivers/video/aty128fb.c
--- v2.4.1/linux/drivers/video/aty128fb.c	Sun Dec  3 17:45:23 2000
+++ linux/drivers/video/aty128fb.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.4.1/linux/drivers/video/atyfb.c	Thu Jan  4 12:38:41 2001
+++ linux/drivers/video/atyfb.c	Fri Feb  9 11:30:23 2001
@@ -45,7 +45,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/bwtwofb.c linux/drivers/video/bwtwofb.c
--- v2.4.1/linux/drivers/video/bwtwofb.c	Mon Feb 14 15:31:14 2000
+++ linux/drivers/video/bwtwofb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: bwtwofb.c,v 1.13 2000/02/14 02:50:25 davem Exp $
+/* $Id: bwtwofb.c,v 1.14 2001/02/13 01:17:14 davem Exp $
  * bwtwofb.c: BWtwo frame buffer driver
  *
  * Copyright (C) 1998 Jakub Jelinek   (jj@ultra.linux.cz)
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/cgfourteenfb.c linux/drivers/video/cgfourteenfb.c
--- v2.4.1/linux/drivers/video/cgfourteenfb.c	Tue Aug 29 14:09:15 2000
+++ linux/drivers/video/cgfourteenfb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: cgfourteenfb.c,v 1.8 2000/08/29 07:01:56 davem Exp $
+/* $Id: cgfourteenfb.c,v 1.9 2001/02/13 01:17:14 davem Exp $
  * cgfourteenfb.c: CGfourteen frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/cgsixfb.c linux/drivers/video/cgsixfb.c
--- v2.4.1/linux/drivers/video/cgsixfb.c	Wed Jul 26 18:36:44 2000
+++ linux/drivers/video/cgsixfb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: cgsixfb.c,v 1.23 2000/07/26 23:02:51 davem Exp $
+/* $Id: cgsixfb.c,v 1.24 2001/02/13 01:17:14 davem Exp $
  * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/cgthreefb.c linux/drivers/video/cgthreefb.c
--- v2.4.1/linux/drivers/video/cgthreefb.c	Tue Mar 21 23:38:25 2000
+++ linux/drivers/video/cgthreefb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: cgthreefb.c,v 1.9 2000/03/19 04:20:44 anton Exp $
+/* $Id: cgthreefb.c,v 1.10 2001/02/13 01:17:14 davem Exp $
  * cgthreefb.c: CGthree frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/chipsfb.c linux/drivers/video/chipsfb.c
--- v2.4.1/linux/drivers/video/chipsfb.c	Sun Sep 17 09:48:05 2000
+++ linux/drivers/video/chipsfb.c	Fri Feb  9 11:30:23 2001
@@ -21,7 +21,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.4.1/linux/drivers/video/clgenfb.c	Thu Jan  4 12:38:41 2001
+++ linux/drivers/video/clgenfb.c	Fri Feb  9 11:30:23 2001
@@ -40,7 +40,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/controlfb.c linux/drivers/video/controlfb.c
--- v2.4.1/linux/drivers/video/controlfb.c	Mon Oct 16 12:37:52 2000
+++ linux/drivers/video/controlfb.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.4.1/linux/drivers/video/creatorfb.c	Wed Jul 26 18:36:44 2000
+++ linux/drivers/video/creatorfb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.32 2000/07/26 23:02:51 davem Exp $
+/* $Id: creatorfb.c,v 1.33 2001/02/13 01:17:14 davem Exp $
  * creatorfb.c: Creator/Creator3D frame buffer driver
  *
  * Copyright (C) 1997,1998,1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -11,7 +11,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
--- v2.4.1/linux/drivers/video/cyber2000fb.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/video/cyber2000fb.c	Fri Feb  9 11:30:23 2001
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.4.1/linux/drivers/video/cyberfb.c	Tue Nov  7 10:59:43 2000
+++ linux/drivers/video/cyberfb.c	Fri Feb  9 11:30:23 2001
@@ -82,7 +82,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/zorro.h>
 #include <linux/fb.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/dn_cfb4.c linux/drivers/video/dn_cfb4.c
--- v2.4.1/linux/drivers/video/dn_cfb4.c	Sun Aug  6 11:25:46 2000
+++ linux/drivers/video/dn_cfb4.c	Fri Feb  9 11:30:23 2001
@@ -3,7 +3,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/dn_cfb8.c linux/drivers/video/dn_cfb8.c
--- v2.4.1/linux/drivers/video/dn_cfb8.c	Sun Aug  6 11:25:46 2000
+++ linux/drivers/video/dn_cfb8.c	Fri Feb  9 11:30:23 2001
@@ -3,7 +3,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/dnfb.c linux/drivers/video/dnfb.c
--- v2.4.1/linux/drivers/video/dnfb.c	Mon Oct 16 12:37:52 2000
+++ linux/drivers/video/dnfb.c	Fri Feb  9 11:30:23 2001
@@ -3,7 +3,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <asm/setup.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.4.1/linux/drivers/video/fbcon.c	Sat Oct 28 22:17:34 2000
+++ linux/drivers/video/fbcon.c	Fri Feb  9 11:30:23 2001
@@ -67,7 +67,7 @@
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/kd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.4.1/linux/drivers/video/fbmem.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/video/fbmem.c	Fri Feb  9 11:30:23 2001
@@ -17,7 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mman.h>
 #include <linux/tty.h>
 #include <linux/console.h>
@@ -598,12 +598,9 @@
 	pgprot_val(vma->vm_page_prot) &= ~_CACHE_MASK;
 	pgprot_val(vma->vm_page_prot) |= _CACHE_UNCACHED;
 #elif defined(__arm__)
-#if defined(CONFIG_CPU_32) && !defined(CONFIG_ARCH_ACORN)
-	/* On Acorn architectures, we want to keep the framebuffer
-	 * cached.
-	 */
-	pgprot_val(vma->vm_page_prot) &= ~(PTE_CACHEABLE | PTE_BUFFERABLE);
-#endif
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	/* This is an IO map - tell maydump to skip this VMA */
+	vma->vm_flags |= VM_IO;
 #elif defined(__sh__)
 	pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
 #else
diff -u --recursive --new-file v2.4.1/linux/drivers/video/g364fb.c linux/drivers/video/g364fb.c
--- v2.4.1/linux/drivers/video/g364fb.c	Tue Nov  7 10:59:43 2000
+++ linux/drivers/video/g364fb.c	Fri Feb  9 11:30:23 2001
@@ -21,7 +21,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/hgafb.c linux/drivers/video/hgafb.c
--- v2.4.1/linux/drivers/video/hgafb.c	Thu Aug 17 23:07:55 2000
+++ linux/drivers/video/hgafb.c	Fri Feb  9 11:30:23 2001
@@ -7,6 +7,8 @@
  *
  * History:
  *
+ * - Revision 0.1.7 (23 Jan 2001): fix crash resulting from MDA only cards 
+ *				   being detected as Hercules.	 (Paul G.)
  * - Revision 0.1.6 (17 Aug 2000): new style structs
  *                                 documentation
  * - Revision 0.1.5 (13 Mar 2000): spinlocks instead of saveflags();cli();etc
@@ -35,7 +37,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
@@ -358,21 +360,22 @@
 		udelay(2);
 	}
 
-	if (p_save != q_save) {
-		switch (inb_p(HGA_STATUS_PORT) & 0x70) {
-			case 0x10:
-				hga_type = TYPE_HERCPLUS;
-				hga_type_name = "HerculesPlus";
-				break;
-			case 0x50:
-				hga_type = TYPE_HERCCOLOR;
-				hga_type_name = "HerculesColor";
-				break;
-			default:
-				hga_type = TYPE_HERC;
-				hga_type_name = "Hercules";
-				break;
-		}
+	if (p_save == q_save) 
+		return 0;
+
+	switch (inb_p(HGA_STATUS_PORT) & 0x70) {
+		case 0x10:
+			hga_type = TYPE_HERCPLUS;
+			hga_type_name = "HerculesPlus";
+			break;
+		case 0x50:
+			hga_type = TYPE_HERCCOLOR;
+			hga_type_name = "HerculesColor";
+			break;
+		default:
+			hga_type = TYPE_HERC;
+			hga_type_name = "Hercules";
+			break;
 	}
 	return 1;
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/video/hitfb.c linux/drivers/video/hitfb.c
--- v2.4.1/linux/drivers/video/hitfb.c	Wed Aug  9 13:59:04 2000
+++ linux/drivers/video/hitfb.c	Fri Feb  9 11:30:23 2001
@@ -17,7 +17,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/nubus.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/hpfb.c linux/drivers/video/hpfb.c
--- v2.4.1/linux/drivers/video/hpfb.c	Tue Nov  7 10:59:43 2000
+++ linux/drivers/video/hpfb.c	Fri Feb  9 11:30:23 2001
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/fb.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/igafb.c linux/drivers/video/igafb.c
--- v2.4.1/linux/drivers/video/igafb.c	Wed Jul 26 11:08:41 2000
+++ linux/drivers/video/igafb.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
--- v2.4.1/linux/drivers/video/imsttfb.c	Fri Aug  4 18:06:34 2000
+++ linux/drivers/video/imsttfb.c	Fri Feb  9 11:30:23 2001
@@ -22,7 +22,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/leofb.c linux/drivers/video/leofb.c
--- v2.4.1/linux/drivers/video/leofb.c	Wed Jul 26 18:36:44 2000
+++ linux/drivers/video/leofb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: leofb.c,v 1.11 2000/07/26 23:02:52 davem Exp $
+/* $Id: leofb.c,v 1.12 2001/02/13 01:17:15 davem Exp $
  * leofb.c: Leo (ZX) 24/8bit frame buffer driver
  *
  * Copyright (C) 1996-1999 Jakub Jelinek (jj@ultra.linux.cz)
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/macfb.c linux/drivers/video/macfb.c
--- v2.4.1/linux/drivers/video/macfb.c	Mon Oct 16 12:37:52 2000
+++ linux/drivers/video/macfb.c	Fri Feb  9 11:30:23 2001
@@ -25,7 +25,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/nubus.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/matrox/matroxfb_DAC1064.c linux/drivers/video/matrox/matroxfb_DAC1064.c
--- v2.4.1/linux/drivers/video/matrox/matroxfb_DAC1064.c	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/matrox/matroxfb_DAC1064.c	Sun Feb  4 10:05:30 2001
@@ -1,81 +1,12 @@
 /*
  *
- * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
+ * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200, G400 and G450.
  *
- * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.50 2000/08/10
+ * Version: 1.52 2001/02/02
  *
- * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
- *
- * Contributors: "menion?" <menion@mindless.com>
- *                     Betatesting, fixes, ideas
- *
- *               "Kurt Garloff" <garloff@suse.de>
- *                     Betatesting, fixes, ideas, videomodes, videomodes timmings
- *
- *               "Tom Rini" <trini@kernel.crashing.org>
- *                     MTRR stuff, PPC cleanups, betatesting, fixes, ideas
- *
- *               "Bibek Sahu" <scorpio@dodds.net>
- *                     Access device through readb|w|l and write b|w|l
- *                     Extensive debugging stuff
- *
- *               "Daniel Haun" <haund@usa.net>
- *                     Testing, hardware cursor fixes
- *
- *               "Scott Wood" <sawst46+@pitt.edu>
- *                     Fixes
- *
- *               "Gerd Knorr" <kraxel@goldbach.isdn.cs.tu-berlin.de>
- *                     Betatesting
- *
- *               "Kelly French" <targon@hazmat.com>
- *               "Fernando Herrera" <fherrera@eurielec.etsit.upm.es>
- *                     Betatesting, bug reporting
- *
- *               "Pablo Bianucci" <pbian@pccp.com.ar>
- *                     Fixes, ideas, betatesting
- *
- *               "Inaky Perez Gonzalez" <inaky@peloncho.fis.ucm.es>
- *                     Fixes, enhandcements, ideas, betatesting
- *
- *               "Ryuichi Oikawa" <roikawa@rr.iiij4u.or.jp>
- *                     PPC betatesting, PPC support, backward compatibility
- *
- *               "Paul Womar" <Paul@pwomar.demon.co.uk>
- *               "Owen Waller" <O.Waller@ee.qub.ac.uk>
- *                     PPC betatesting
- *
- *               "Thomas Pornin" <pornin@bolet.ens.fr>
- *                     Alpha betatesting
- *
- *               "Pieter van Leuven" <pvl@iae.nl>
- *               "Ulf Jaenicke-Roessler" <ujr@physik.phy.tu-dresden.de>
- *                     G100 testing
- *
- *               "H. Peter Arvin" <hpa@transmeta.com>
- *                     Ideas
- *
- *               "Cort Dougan" <cort@cs.nmt.edu>
- *                     CHRP fixes and PReP cleanup
- *
- *               "Mark Vojkovich" <mvojkovi@ucsd.edu>
- *                     G400 support
- *
- *               "Ken Aaker" <kdaaker@rchland.vnet.ibm.com>
- *                     memtype extension (needed for GXT130P RS/6000 adapter)
- *
- * (following author is not in any relation with this code, but his code
- *  is included in this driver)
- *
- * Based on framebuffer driver for VBE 2.0 compliant graphic boards
- *     (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
- *
- * (following author is not in any relation with this code, but his ideas
- *  were used when writting this driver)
- *
- *		 FreeVBE/AF (Matrox), "Shawn Hargreaves" <shawn@talula.demon.co.uk>
+ * See matroxfb_base.c for contributors.
  *
  */
 
@@ -787,6 +718,11 @@
 
 	ACCESS_FBINFO(primout) = &m1064;
 
+	if (ACCESS_FBINFO(devflags.g450dac)) {
+		/* we must do this always, BIOS does not do it for us
+		   and accelerator dies without it */
+		mga_outl(0x1C0C, 0);
+	}
 	if (ACCESS_FBINFO(devflags.noinit))
 		return 0;
 	hw->MXoptionReg &= 0xC0000100;
diff -u --recursive --new-file v2.4.1/linux/drivers/video/matrox/matroxfb_base.c linux/drivers/video/matrox/matroxfb_base.c
--- v2.4.1/linux/drivers/video/matrox/matroxfb_base.c	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/matrox/matroxfb_base.c	Sun Feb  4 10:05:30 2001
@@ -2,9 +2,9 @@
  *
  * Hardware accelerated Matrox Millennium I, II, Mystique, G100, G200 and G400
  *
- * (c) 1998,1999,2000 Petr Vandrovec <vandrove@vc.cvut.cz>
+ * (c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>
  *
- * Version: 1.50 2000/08/10
+ * Version: 1.52 2001/02/02
  *
  * MTRR stuff: 1998 Tom Rini <trini@kernel.crashing.org>
  *
@@ -1409,12 +1409,12 @@
 
 #define DEVF_VIDEO64BIT		0x0001
 #define	DEVF_SWAPS		0x0002
-#define DEVF_MILLENNIUM		0x0004
-#define	DEVF_MILLENNIUM2	0x0008
+/* #define DEVF_recycled	0x0004 */
+/* #define DEVF_recycled	0x0008 */
 #define DEVF_CROSS4MB		0x0010
 #define DEVF_TEXT4B		0x0020
 #define DEVF_DDC_8_2		0x0040
-#define DEVF_DMA		0x0080
+/* #define DEVF_recycled	0x0080 */
 #define DEVF_SUPPORT32MB	0x0100
 #define DEVF_ANY_VXRES		0x0200
 #define DEVF_TEXT16B		0x0400
@@ -1441,19 +1441,19 @@
 #ifdef CONFIG_FB_MATROX_MILLENIUM
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL,	0xFF,
 		0,			0,
-		DEVF_MILLENNIUM | DEVF_TEXT4B,
+		DEVF_TEXT4B,
 		230000,
 		&vbMillennium,
 		"Millennium (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2,	0xFF,
 		0,			0,
-		DEVF_MILLENNIUM | DEVF_MILLENNIUM2 | DEVF_SWAPS,
+		DEVF_SWAPS,
 		220000,
 		&vbMillennium2,
 		"Millennium II (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MIL_2_AGP,	0xFF,
 		0,			0,
-		DEVF_MILLENNIUM | DEVF_MILLENNIUM2 | DEVF_SWAPS,
+		DEVF_SWAPS,
 		250000,
 		&vbMillennium2A,
 		"Millennium II (AGP)"},
@@ -1461,13 +1461,13 @@
 #ifdef CONFIG_FB_MATROX_MYSTIQUE
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,	0x02,
 		0,			0,
-		DEVF_VIDEO64BIT,
+		DEVF_VIDEO64BIT | DEVF_CROSS4MB,
 		180000,
 		&vbMystique,
 		"Mystique (PCI)"},
 	{PCI_VENDOR_ID_MATROX,	PCI_DEVICE_ID_MATROX_MYS,	0xFF,
 		0,			0,
-		DEVF_VIDEO64BIT | DEVF_SWAPS,
+		DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB,
 		220000,
 		&vbMystique,
 		"Mystique 220 (PCI)"},
@@ -1842,33 +1842,33 @@
 	}
 
 	/* FIXME: Where to move this?! */
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_ALL_PPC)
 #if defined(CONFIG_FB_COMPAT_XPMAC)
 	strcpy(ACCESS_FBINFO(matrox_name), "MTRX,");	/* OpenFirmware naming convension */
 	strncat(ACCESS_FBINFO(matrox_name), b->name, 26);
 	if (!console_fb_info)
 		console_fb_info = &ACCESS_FBINFO(fbcon);
 #endif
-	if ((xres <= 640) && (yres <= 480)) {
+#ifndef MODULE
+	if (_machine == _MACH_Pmac) {
 		struct fb_var_screeninfo var;
-		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 <= 0 || default_vmode > VMODE_MAX)
 			default_vmode = VMODE_640_480_60;
+#ifdef CONFIG_NVRAM
 		if (default_cmode == CMODE_NVRAM)
 			default_cmode = nvram_read_byte(NV_CMODE);
+#endif
 		if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
 			default_cmode = CMODE_8;
 		if (!mac_vmode_to_var(default_vmode, default_cmode, &var)) {
 			var.accel_flags = vesafb_defined.accel_flags;
 			var.xoffset = var.yoffset = 0;
-			vesafb_defined = var; /* Note: mac_vmode_to_var() doesnot set all parameters */
+			/* Note: mac_vmode_to_var() does not set all parameters */
+			vesafb_defined = var;
 		}
 	}
-#endif /* CONFIG_PPC */
+#endif /* !MODULE */
+#endif /* CONFIG_ALL_PPC */
 	vesafb_defined.xres_virtual = vesafb_defined.xres;
 	if (nopan) {
 		vesafb_defined.yres_virtual = vesafb_defined.yres;
@@ -2005,6 +2005,7 @@
 	u_int32_t cmd;
 #ifndef CONFIG_FB_MATROX_MULTIHEAD
 	static int registered = 0;
+	static struct display global_disp;
 #endif
 	DBG("matroxfb_probe")
 
@@ -2502,8 +2503,8 @@
 
 /* *************************** init module code **************************** */
 
-MODULE_AUTHOR("(c) 1998,1999 Petr Vandrovec <vandrove@vc.cvut.cz>");
-MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400");
+MODULE_AUTHOR("(c) 1998-2001 Petr Vandrovec <vandrove@vc.cvut.cz>");
+MODULE_DESCRIPTION("Accelerated FBDev driver for Matrox Millennium/Mystique/G100/G200/G400/G450");
 MODULE_PARM(mem, "i");
 MODULE_PARM_DESC(mem, "Size of available memory in MB, KB or B (2,4,8,12,16MB, default=autodetect)");
 MODULE_PARM(disabled, "i");
diff -u --recursive --new-file v2.4.1/linux/drivers/video/matrox/matroxfb_base.h linux/drivers/video/matrox/matroxfb_base.h
--- v2.4.1/linux/drivers/video/matrox/matroxfb_base.h	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/matrox/matroxfb_base.h	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
@@ -589,7 +589,6 @@
 #else
 
 extern struct matrox_fb_info matroxfb_global_mxinfo;
-struct display global_disp;
 
 #define ACCESS_FBINFO(x) (matroxfb_global_mxinfo.x)
 #define ACCESS_FBINFO2(info, x) (matroxfb_global_mxinfo.x)
@@ -787,11 +786,7 @@
 #define mga_setr(addr,port,val) do { mga_outb(addr, port); mga_outb((addr)+1, val); } while (0)
 #endif
 
-#ifdef __LITTLE_ENDIAN
-#define mga_fifo(n)	do {} while (mga_inb(M_FIFOSTATUS) < (n))
-#else
 #define mga_fifo(n)	do {} while ((mga_inl(M_FIFOSTATUS) & 0xFF) < (n))
-#endif
 
 #define WaitTillIdle()	do {} while (mga_inl(M_STATUS) & 0x10000)
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/mdacon.c linux/drivers/video/mdacon.c
--- v2.4.1/linux/drivers/video/mdacon.c	Mon Dec 11 13:47:20 2000
+++ linux/drivers/video/mdacon.c	Fri Feb  9 11:30:23 2001
@@ -33,7 +33,7 @@
 #include <linux/console_struct.h>
 #include <linux/string.h>
 #include <linux/kd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vt_kern.h>
 #include <linux/vt_buffer.h>
 #include <linux/selection.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.4.1/linux/drivers/video/offb.c	Mon Oct 16 12:37:52 2000
+++ linux/drivers/video/offb.c	Fri Feb  9 11:30:23 2001
@@ -19,7 +19,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/p9100fb.c linux/drivers/video/p9100fb.c
--- v2.4.1/linux/drivers/video/p9100fb.c	Mon Dec 20 22:06:42 1999
+++ linux/drivers/video/p9100fb.c	Fri Feb  9 11:30:23 2001
@@ -11,7 +11,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/platinumfb.c linux/drivers/video/platinumfb.c
--- v2.4.1/linux/drivers/video/platinumfb.c	Sun Dec  3 17:45:24 2000
+++ linux/drivers/video/platinumfb.c	Fri Feb  9 11:30:23 2001
@@ -24,7 +24,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c
--- v2.4.1/linux/drivers/video/pm2fb.c	Mon Jul 24 18:24:26 2000
+++ linux/drivers/video/pm2fb.c	Fri Feb  9 11:30:23 2001
@@ -20,7 +20,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/promcon.c linux/drivers/video/promcon.c
--- v2.4.1/linux/drivers/video/promcon.c	Mon Oct 16 12:53:18 2000
+++ linux/drivers/video/promcon.c	Fri Feb  9 11:30:23 2001
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/console.h>
 #include <linux/console_struct.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/q40fb.c linux/drivers/video/q40fb.c
--- v2.4.1/linux/drivers/video/q40fb.c	Mon Oct 16 12:37:52 2000
+++ linux/drivers/video/q40fb.c	Fri Feb  9 11:30:23 2001
@@ -3,7 +3,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.4.1/linux/drivers/video/retz3fb.c	Thu Jan  4 13:00:55 2001
+++ linux/drivers/video/retz3fb.c	Fri Feb  9 11:30:23 2001
@@ -26,7 +26,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/zorro.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/Makefile linux/drivers/video/riva/Makefile
--- v2.4.1/linux/drivers/video/riva/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/drivers/video/riva/Makefile	Sat Feb  3 12:48:00 2001
@@ -9,7 +9,7 @@
 
 O_TARGET := rivafb.o
 
-obj-y    := fbdev.o riva_hw.o
+obj-y    := fbdev.o riva_hw.o accel.o
 obj-m    := $(O_TARGET)
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/accel.c linux/drivers/video/riva/accel.c
--- v2.4.1/linux/drivers/video/riva/accel.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/riva/accel.c	Sat Feb  3 12:48:00 2001
@@ -0,0 +1,424 @@
+/*
+ * linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver
+ *
+ * Copyright 2000 Jindrich Makovicka, Ani Joshi
+ *
+ * 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.
+ */
+
+#include "rivafb.h"
+
+/* acceleration routines */
+
+inline void wait_for_idle(struct rivafb_info *rinfo)
+{
+	while (rinfo->riva.Busy(&rinfo->riva));
+}
+
+/* set copy ROP, no mask */
+static void riva_setup_ROP(struct rivafb_info *rinfo)
+{
+	RIVA_FIFO_FREE(rinfo->riva, Patt, 5);
+	rinfo->riva.Patt->Shape = 0;
+	rinfo->riva.Patt->Color0 = 0xffffffff;
+	rinfo->riva.Patt->Color1 = 0xffffffff;
+	rinfo->riva.Patt->Monochrome[0] = 0xffffffff;
+	rinfo->riva.Patt->Monochrome[1] = 0xffffffff;
+
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0xCC;
+}
+
+void riva_setup_accel(struct rivafb_info *rinfo)
+{
+	RIVA_FIFO_FREE(rinfo->riva, Clip, 2);
+	rinfo->riva.Clip->TopLeft     = 0x0;
+	rinfo->riva.Clip->WidthHeight = 0x80008000;
+	riva_setup_ROP(rinfo);
+	wait_for_idle(rinfo);
+}
+
+static void riva_rectfill(struct rivafb_info *rinfo, int sy,
+			  int sx, int height, int width, u_int color)
+{
+	RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1);
+	rinfo->riva.Bitmap->Color1A = color;
+
+	RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2);
+	rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft     = (sx << 16) | sy; 
+	rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height;
+}
+
+static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx,
+			    int height, int width)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	dx *= fontwidth(p);
+	dy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	RIVA_FIFO_FREE(rinfo->riva, Blt, 3);
+	rinfo->riva.Blt->TopLeftSrc  = (sy << 16) | sx;
+	rinfo->riva.Blt->TopLeftDst  = (dy << 16) | dx;
+	rinfo->riva.Blt->WidthHeight = (height  << 16) | width;
+}
+
+static void riva_clear_margins(struct vc_data *conp, struct display *p,
+				int bottom_only, u32 bgx)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	unsigned int right_start = conp->vc_cols*fontwidth(p);
+	unsigned int bottom_start = conp->vc_rows*fontheight(p);
+	unsigned int right_width, bottom_width;
+
+	if (!bottom_only && (right_width = p->var.xres - right_start))
+		riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual,
+			      right_width, bgx);
+	if ((bottom_width = p->var.yres - bottom_start))
+		riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0,
+			      bottom_width, right_start, bgx);
+}
+
+static u8 byte_rev[256] = {
+	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 
+	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 
+	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 
+	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 
+	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 
+	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 
+	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 
+	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 
+	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 
+	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 
+	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 
+	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 
+	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 
+	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 
+	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+static inline void fbcon_reverse_order(u32 *l)
+{
+	u8 *a = (u8 *)l;
+	*a++ = byte_rev[*a];
+/*	*a++ = byte_rev[*a];
+	*a++ = byte_rev[*a];*/
+	*a = byte_rev[*a];
+}
+
+static void fbcon_riva_writechr(struct vc_data *conp, struct display *p,
+			        int c, int fgx, int bgx, int yy, int xx)
+{
+	u8 *cdat;
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+	int w, h;
+	volatile u32 *d;
+	u32 cdat2;
+	int i, j, cnt;
+
+	w = fontwidth(p);
+	h = fontheight(p);
+
+	if (w <= 8)
+		cdat = p->fontdata + (c & p->charmask) * h;
+	else
+		cdat = p->fontdata + ((c & p->charmask) * h << 1);
+
+        RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7);
+        rinfo->riva.Bitmap->ClipE.TopLeft     = (yy << 16) | (xx & 0xFFFF);
+        rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff);
+        rinfo->riva.Bitmap->Color0E           = bgx;
+        rinfo->riva.Bitmap->Color1E           = fgx;
+        rinfo->riva.Bitmap->WidthHeightInE  = (h << 16) | 32;
+        rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32;
+        rinfo->riva.Bitmap->PointE          = (yy << 16) | (xx & 0xFFFF);
+	
+	d = &rinfo->riva.Bitmap->MonochromeData01E;
+	for (i = h; i > 0; i-=16) {
+		if (i >= 16)
+			cnt = 16;
+		else
+			cnt = i;
+		RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt);
+		for (j = 0; j < cnt; j++) {
+			if (w <= 8) 
+				cdat2 = *cdat++;
+			else
+				cdat2 = *((u16*)cdat)++;
+			fbcon_reverse_order(&cdat2);
+			d[j] = cdat2;
+		}
+	}
+}
+
+#ifdef FBCON_HAS_CFB8
+void fbcon_riva8_setup(struct display *p)
+{
+    p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
+    p->next_plane = 0;
+}
+
+static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width)
+{
+	u32 bgx;
+
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	bgx = attr_bgcol_ec(p, conp);
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	riva_rectfill(rinfo, sy, sx, height, width, bgx);
+}
+
+static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx)
+{
+	u32 fgx,bgx;
+
+	fgx = attr_fgcol(p,c);
+	bgx = attr_bgcol(p,c);
+	
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+}
+
+static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy,
+			     int xx)
+{
+	u16 c;
+	u32 fgx,bgx;
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	while (count--) {
+		c = scr_readw(s++);
+		fgx = attr_fgcol(p,c);
+		bgx = attr_bgcol(p,c);
+		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+		xx += fontwidth(p);
+	}
+}
+
+static void fbcon_riva8_revc(struct display *p, int xx, int yy)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0x66; // XOR
+	riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f);
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
+}
+
+static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p,
+				       int bottom_only)
+{
+	riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp));
+}
+
+struct display_switch fbcon_riva8 = {
+	setup:		fbcon_riva8_setup,
+	bmove:		fbcon_riva_bmove,
+	clear:		fbcon_riva8_clear,
+	putc:		fbcon_riva8_putc,
+	putcs:		fbcon_riva8_putcs,
+	revc:		fbcon_riva8_revc,
+	clear_margins:	fbcon_riva8_clear_margins,
+	fontwidthmask:	FONTWIDTHRANGE(4, 16)
+};
+#endif
+
+#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
+static void fbcon_riva1632_revc(struct display *p, int xx, int yy)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0x66; // XOR
+	riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff);
+	RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
+	rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
+}
+#endif
+
+#ifdef FBCON_HAS_CFB16
+void fbcon_riva16_setup(struct display *p)
+{
+    p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
+    p->next_plane = 0;
+}
+
+static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width)
+{
+	u32 bgx;
+
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	riva_rectfill(rinfo, sy, sx, height, width, bgx);
+}
+
+static inline void convert_bgcolor_16(u32 *col)
+{
+	*col = ((*col & 0x00007C00) << 9)
+             | ((*col & 0x000003E0) << 6)
+             | ((*col & 0x0000001F) << 3)
+             |          0xFF000000;
+}
+
+static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx)
+{
+	u32 fgx,bgx;
+
+	fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
+	bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
+	if (p->var.green.length == 6)
+		convert_bgcolor_16(&bgx);
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+}
+
+static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy,
+			     int xx)
+{
+	u16 c;
+	u32 fgx,bgx;
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	while (count--) {
+		c = scr_readw(s++);
+		fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
+		bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
+		if (p->var.green.length == 6)
+			convert_bgcolor_16(&bgx);
+		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+		xx += fontwidth(p);
+	}
+}
+
+static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p,
+				       int bottom_only)
+{
+	riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
+}
+
+struct display_switch fbcon_riva16 = {
+	setup:		fbcon_riva16_setup,
+	bmove:		fbcon_riva_bmove,
+	clear:		fbcon_riva16_clear,
+	putc:		fbcon_riva16_putc,
+	putcs:		fbcon_riva16_putcs,
+	revc:		fbcon_riva1632_revc,
+	clear_margins:	fbcon_riva16_clear_margins,
+	fontwidthmask:	FONTWIDTHRANGE(4, 16)
+};
+#endif
+
+#ifdef FBCON_HAS_CFB32
+void fbcon_riva32_setup(struct display *p)
+{
+    p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
+    p->next_plane = 0;
+}
+
+static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy,
+			     int sx, int height, int width)
+{
+	u32 bgx;
+
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+
+	bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+	sx *= fontwidth(p);
+	sy *= fontheight(p);
+	width *= fontwidth(p);
+	height *= fontheight(p);
+
+	riva_rectfill(rinfo, sy, sx, height, width, bgx);
+}
+
+static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
+			    int yy, int xx)
+{
+	u32 fgx,bgx;
+
+	fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
+	bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+	fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+}
+
+static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
+			     const unsigned short *s, int count, int yy,
+			     int xx)
+{
+	u16 c;
+	u32 fgx,bgx;
+
+	xx *= fontwidth(p);
+	yy *= fontheight(p);
+
+	while (count--) {
+		c = scr_readw(s++);
+		fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
+		bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
+		fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
+		xx += fontwidth(p);
+	}
+}
+
+static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p,
+				       int bottom_only)
+{
+	riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
+}
+
+struct display_switch fbcon_riva32 = {
+	setup:		fbcon_riva32_setup,
+	bmove:		fbcon_riva_bmove,
+	clear:		fbcon_riva32_clear,
+	putc:		fbcon_riva32_putc,
+	putcs:		fbcon_riva32_putcs,
+	revc:		fbcon_riva1632_revc,
+	clear_margins:	fbcon_riva32_clear_margins,
+	fontwidthmask:	FONTWIDTHRANGE(4, 16)
+};
+#endif
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/fbdev.c linux/drivers/video/riva/fbdev.c
--- v2.4.1/linux/drivers/video/riva/fbdev.c	Tue Nov 14 11:28:39 2000
+++ linux/drivers/video/riva/fbdev.c	Tue Feb 13 13:15:05 2001
@@ -12,6 +12,8 @@
  *
  *	Ferenc Bakonyi:  Bug fixes, cleanup, modularization
  *
+ *	Jindrich Makovicka:  Accel code help, hw cursor, mtrr
+ *
  * Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
  * Includes riva_hw.c from nVidia, see copyright below.
  * KGI code provided the basis for state storage, init, and mode switching.
@@ -19,11 +21,13 @@
  * 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.
+ *
+ * Known bugs and issues:
+ *	restoring text mode fails
+ *	doublescan modes are broken
+ *	option 'noaccel' has no effect
  */
 
-/* version number of this driver */
-#define RIVAFB_VERSION "0.7.3"
-
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -32,34 +36,36 @@
 #include <linux/mm.h>
 #include <linux/selection.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/pci.h>
-
-#include <video/fbcon.h>
-
-#include "riva_hw.h"
-#include "nv4ref.h"
+#include <linux/console.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
+#include "rivafb.h"
 #include "nvreg.h"
-#include "../vga.h"
-#include <video/fbcon-cfb4.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
 
 #ifndef CONFIG_PCI		/* sanity check */
 #error This driver requires PCI support.
 #endif
 
-/*****************************************************************
+
+
+/* version number of this driver */
+#define RIVAFB_VERSION "0.9.2a"
+
+
+
+/* ------------------------------------------------------------------------- *
  *
  * various helpful macros and constants
  *
- */
+ * ------------------------------------------------------------------------- */
 
-/* #define RIVAFBDEBUG */
+#undef RIVAFBDEBUG
 #ifdef RIVAFBDEBUG
 #define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
 #else
@@ -69,31 +75,50 @@
 #ifndef RIVA_NDEBUG
 #define assert(expr) \
 	if(!(expr)) { \
-        printk( "Assertion failed! %s,%s,%s,line=%d\n",\
-        #expr,__FILE__,__FUNCTION__,__LINE__); \
+	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
+	#expr,__FILE__,__FUNCTION__,__LINE__); \
 	BUG(); \
-        }
+	}
 #else
 #define assert(expr)
 #endif
 
-/* GGI compatibility macros */
-#define io_out8			outb
-#define io_in8			inb
-#define NUM_SEQ_REGS		0x05
-#define NUM_CRT_REGS		0x41
-#define NUM_GRC_REGS		0x09
-#define NUM_ATC_REGS		0x15
-
 #define PFX "rivafb: "
 
-#define CNVT_TOHW(val,width)	((((val)<<(width))+0x7FFF-(val))>>16)
-
 /* macro that allows you to set overflow bits */
 #define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
 #define SetBit(n)		(1<<(n))
 #define Set8Bits(value)		((value)&0xff)
 
+/* HW cursor parameters */
+#define DEFAULT_CURSOR_BLINK_RATE	(40)
+#define CURSOR_HIDE_DELAY		(20)
+#define CURSOR_SHOW_DELAY		(3)
+
+#define CURSOR_COLOR		0x7fff
+#define TRANSPARENT_COLOR	0x0000
+#define MAX_CURS		32
+
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * prototypes
+ *
+ * ------------------------------------------------------------------------- */
+
+static void rivafb_blank(int blank, struct fb_info *info);
+
+extern void riva_setup_accel(struct rivafb_info *rinfo);
+extern inline void wait_for_idle(struct rivafb_info *rinfo);
+
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * card identification
+ *
+ * ------------------------------------------------------------------------- */
 
 enum riva_chips {
 	CH_RIVA_128 = 0,
@@ -103,187 +128,170 @@
 	CH_RIVA_VTNT2,	/* VTNT2 */
 	CH_RIVA_UVTNT2,	/* VTNT2 */
 	CH_RIVA_ITNT2,	/* ITNT2 */
+	CH_GEFORCE_SDR,
+	CH_GEFORCE_DDR,
+	CH_QUADRO,
+	CH_GEFORCE2_MX,
+	CH_QUADRO2_MXR,
+	CH_GEFORCE2_GTS,
+	CH_GEFORCE2_ULTRA,
+	CH_QUADRO2_PRO,
 };
 
-
 /* directly indexed by riva_chips enum, above */
 static struct riva_chip_info {
 	const char *name;
 	unsigned arch_rev;
 } riva_chip_info[] __devinitdata = {
-	{ "RIVA-128", 3 },
-	{ "RIVA-TNT", 4 },
-	{ "RIVA-TNT2", 5 },
-	{ "RIVA-UTNT2", 5 },
-	{ "RIVA-VTNT2", 5 },
-	{ "RIVA-UVTNT2", 5 },
-	{ "RIVA-ITNT2", 5 },
+	{ "RIVA-128", NV_ARCH_03 },
+	{ "RIVA-TNT", NV_ARCH_04 },
+	{ "RIVA-TNT2", NV_ARCH_04 },
+	{ "RIVA-UTNT2", NV_ARCH_04 },
+	{ "RIVA-VTNT2", NV_ARCH_04 },
+	{ "RIVA-UVTNT2", NV_ARCH_04 },
+	{ "RIVA-ITNT2", NV_ARCH_04 },
+	{ "GeForce-SDR", NV_ARCH_10},
+	{ "GeForce-DDR", NV_ARCH_10},
+	{ "Quadro", NV_ARCH_10},
+	{ "GeForce2-MX", NV_ARCH_10},
+	{ "Quadro2-MXR", NV_ARCH_10},
+	{ "GeForce2-GTS", NV_ARCH_10},
+	{ "GeForce2-ULTRA", NV_ARCH_10},
+	{ "Quadro2-PRO", NV_ARCH_10},
 };
 
-
 static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
-	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
-	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
+	{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_SDR },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_DDR },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_MXR },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
+	{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
 	{ 0, } /* terminate list */
 };
 MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
 
 
-/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
- * From KGI originally. */
-struct riva_regs {
-	u8 attr[NUM_ATC_REGS];
-	u8 crtc[NUM_CRT_REGS];
-	u8 gra[NUM_GRC_REGS];
-	u8 seq[NUM_SEQ_REGS];
-	u8 misc_output;
-	RIVA_HW_STATE ext;
-};
 
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer related structures
+ *
+ * ------------------------------------------------------------------------- */
 
-/*
- * describes the state of a Riva board
- */
+#ifdef FBCON_HAS_CFB8
+extern struct display_switch fbcon_riva8;
+#endif
+#ifdef FBCON_HAS_CFB16
+extern struct display_switch fbcon_riva16;
+#endif
+#ifdef FBCON_HAS_CFB32
+extern struct display_switch fbcon_riva32;
+#endif
+
+#if 0
+/* describes the state of a Riva board */
 struct rivafb_par {
 	struct riva_regs state;	/* state of hw board */
 	__u32 visual;		/* FB_VISUAL_xxx */
 	unsigned depth;		/* bpp of current mode */
 };
-
-typedef struct {
-	unsigned char red, green, blue, transp;
-} riva_cfb8_cmap_t;
-
-
-
-struct rivafb_info;
-struct rivafb_info {
-	struct fb_info info;	/* kernel framebuffer info */
-
-	RIVA_HW_INST riva;	/* interface to riva_hw.c */
-
-	const char *drvr_name;	/* Riva hardware board type */
-
-	unsigned long ctrl_base_phys;	/* physical control register base addr */
-	unsigned long fb_base_phys;	/* physical framebuffer base addr */
-
-	caddr_t ctrl_base;	/* virtual control register base addr */
-	caddr_t fb_base;	/* virtual framebuffer base addr */
-
-	unsigned ram_amount;	/* amount of RAM on card, in bytes */
-	unsigned dclk_max;	/* max DCLK */
-
-	struct riva_regs initial_state;	/* initial startup video mode */
-
-	struct display disp;
-	int currcon;
-	struct display *currcon_display;
-
-	struct rivafb_info *next;
-
-	struct pci_dev *pd;	/* pointer to board's pci info */
-	unsigned base0_region_size;	/* size of control register region */
-	unsigned base1_region_size;	/* size of framebuffer region */
-
-	riva_cfb8_cmap_t palette[256];	/* VGA DAC palette cache */
-
-#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
-	union {
-#ifdef FBCON_HAS_CFB16
-		u_int16_t cfb16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-		u_int32_t cfb32[16];
 #endif
-	} con_cmap;
-#endif				/* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
+
+struct riva_cursor {
+	int enable;
+	int on;
+	int vbl_cnt;
+	int last_move_delay;
+	int blink_rate;
+	struct {
+		u16 x, y;
+	} pos, size;
+	unsigned short image[MAX_CURS*MAX_CURS];
+	struct timer_list *timer;
 };
 
-/* ------------------- global variables ------------------------ */
 
 
-static struct rivafb_info *riva_boards = NULL;
+/* ------------------------------------------------------------------------- *
+ *
+ * global variables
+ *
+ * ------------------------------------------------------------------------- */
+
+struct rivafb_info *riva_boards = NULL;
 
 /* command line data, set in rivafb_setup() */
 static char fontname[40] __initdata = { 0 };
+static char noaccel __initdata = 0;
+static char nomove = 0;
+static char nohwcursor __initdata = 0;
+static char noblink = 0;
+#ifdef CONFIG_MTRR
+static char nomtrr __initdata = 0;
+#endif
+
 #ifndef MODULE
-static char noaccel __initdata = 0;	/* unused */
 static const char *mode_option __initdata = NULL;
+#else
+static char *font = NULL;
 #endif
 
 static struct fb_var_screeninfo rivafb_default_var = {
-	/* 640x480-8@60, yres_virtual=2400 (fits for all Riva cards */
-	640, 480, 640, 2400, 0, 0, 8, 0,
-	{0, 6, 0}, {0, 6, 0}, {0, 6, 0}, {0, 0, 0},
-	0, 0, -1, -1, 0, 39721, 40, 24, 32, 11, 96, 2,
-	0, FB_VMODE_NONINTERLACED
-};
-
-
-/* ------------------- prototypes ------------------------------ */
-
-static int rivafb_get_fix (struct fb_fix_screeninfo *fix, int con,
-		    struct fb_info *info);
-static int rivafb_get_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info);
-static int rivafb_set_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info);
-static int rivafb_get_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info);
-static int rivafb_set_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info);
-static int rivafb_pan_display (struct fb_var_screeninfo *var, int con,
-			struct fb_info *info);
-static int rivafb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-		  unsigned long arg, int con, struct fb_info *info);
-static int rivafb_switch (int con, struct fb_info *info);
-static int rivafb_updatevar (int con, struct fb_info *info);
-static void rivafb_blank (int blank, struct fb_info *info);
-
-static void riva_load_video_mode (struct rivafb_info *rivainfo,
-				  struct fb_var_screeninfo *video_mode);
-static int riva_getcolreg (unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info);
-static int riva_setcolreg (unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info);
-static int riva_get_cmap_len (const struct fb_var_screeninfo *var);
-
-static int riva_set_fbinfo (struct rivafb_info *rinfo);
-
-static void riva_save_state (struct rivafb_info *rinfo, struct riva_regs *regs);
-static void riva_load_state (struct rivafb_info *rinfo, struct riva_regs *regs);
-static struct rivafb_info *riva_board_list_add (struct rivafb_info *board_list,
-					 struct rivafb_info *new_node);
-static struct rivafb_info *riva_board_list_del (struct rivafb_info *board_list,
-					 struct rivafb_info *del_node);
-static void riva_wclut (unsigned char regnum, unsigned char red,
-			unsigned char green, unsigned char blue);
-
-
-
-
-/* kernel interface */
-static struct fb_ops riva_fb_ops = {
-	owner:		THIS_MODULE,
-	fb_get_fix:	rivafb_get_fix,
-	fb_get_var:	rivafb_get_var,
-	fb_set_var:	rivafb_set_var,
-	fb_get_cmap:	rivafb_get_cmap,
-	fb_set_cmap:	rivafb_set_cmap,
-	fb_pan_display:	rivafb_pan_display,
-	fb_ioctl:	rivafb_ioctl,
+	xres:		640,
+	yres:		480,
+	xres_virtual:	640,
+	yres_virtual:	480,
+	xoffset:	0,
+	yoffset:	0,
+	bits_per_pixel:	8,
+	grayscale:	0,
+	red:		{0, 6, 0},
+	green:		{0, 6, 0},
+	blue:		{0, 6, 0},
+	transp:		{0, 0, 0},
+	nonstd:		0,
+	activate:	0,
+	height:		-1,
+	width:		-1,
+	accel_flags:	0,
+	pixclock:	39721,
+	left_margin:	40,
+	right_margin:	24,
+	upper_margin:	32,
+	lower_margin:	11,
+	hsync_len:	96,
+	vsync_len:	2,
+	sync:		0,
+	vmode:		FB_VMODE_NONINTERLACED
 };
 
-
-
-
 /* from GGI */
 static const struct riva_regs reg_template = {
 	{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,	/* ATTR */
@@ -297,425 +305,985 @@
 	 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,	/* 0x30 */
 	 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	 0x00,			/* 0x40 */
+	 0x00,							/* 0x40 */
 	 },
 	{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F,	/* GRA  */
 	 0xFF},
-	{0x03, 0x01, 0x0F, 0x00, 0x0E},	/* SEQ  */
-	0xEB			/* MISC */
+	{0x03, 0x01, 0x0F, 0x00, 0x0E},				/* SEQ  */
+	0xEB							/* MISC */
 };
 
 
 
-/* ------------------- general utility functions -------------------------- */
-
-/**
- * riva_set_dispsw
- * @rinfo: pointer to internal driver struct for a given Riva card
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Sets up console Low level operations depending on the current? color depth
- * of the display
- */
+ * MMIO access macros
+ *
+ * ------------------------------------------------------------------------- */
 
-static void riva_set_dispsw (struct rivafb_info *rinfo)
+static inline void CRTCout(struct rivafb_info *rinfo, unsigned char index,
+			   unsigned char val)
 {
-	struct display *disp = &rinfo->disp;
+	VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
+	VGA_WR08(rinfo->riva.PCIO, 0x3d5, val);
+}
 
-	DPRINTK ("ENTER\n");
+static inline unsigned char CRTCin(struct rivafb_info *rinfo,
+				   unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
+	return (VGA_RD08(rinfo->riva.PCIO, 0x3d5));
+}
 
-	assert (rinfo != NULL);
+static inline void GRAout(struct rivafb_info *rinfo, unsigned char index,
+			  unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
+	VGA_WR08(rinfo->riva.PVIO, 0x3cf, val);
+}
 
-	disp->dispsw_data = NULL;
+static inline unsigned char GRAin(struct rivafb_info *rinfo,
+				  unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
+	return (VGA_RD08(rinfo->riva.PVIO, 0x3cf));
+}
 
-	switch (disp->var.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		disp->dispsw = &fbcon_mfb;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB4
-	case 4:
-		disp->dispsw = &fbcon_cfb4;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		disp->dispsw = &fbcon_cfb8;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 15:
-	case 16:
-		disp->dispsw = &fbcon_cfb16;
-		disp->dispsw_data = &rinfo->con_cmap.cfb16;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB24
-	case 24:
-		disp->dispsw = &fbcon_cfb24;
-		disp->dispsw_data = rinfo->con_cmap.cfb24;
-		break;
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		disp->dispsw = &fbcon_cfb32;
-		disp->dispsw_data = rinfo->con_cmap.cfb32;
-		break;
-#endif
-	default:
-		DPRINTK ("Setting fbcon_dummy renderer\n");
-		disp->dispsw = &fbcon_dummy;
-	}
+static inline void SEQout(struct rivafb_info *rinfo, unsigned char index,
+			  unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
+	VGA_WR08(rinfo->riva.PVIO, 0x3c5, val);
+}
 
-	DPRINTK ("EXIT\n");
+static inline unsigned char SEQin(struct rivafb_info *rinfo,
+				  unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
+	return (VGA_RD08(rinfo->riva.PVIO, 0x3c5));
 }
 
+static inline void ATTRout(struct rivafb_info *rinfo, unsigned char index,
+			   unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
+	VGA_WR08(rinfo->riva.PCIO, 0x3c0, val);
+}
 
+static inline unsigned char ATTRin(struct rivafb_info *rinfo,
+				   unsigned char index)
+{
+	VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
+	return (VGA_RD08(rinfo->riva.PCIO, 0x3c1));
+}
 
+static inline void MISCout(struct rivafb_info *rinfo, unsigned char val)
+{
+	VGA_WR08(rinfo->riva.PVIO, 0x3c2, val);
+}
 
-static int riva_init_disp_var (struct rivafb_info *rinfo)
+static inline unsigned char MISCin(struct rivafb_info *rinfo)
 {
-#ifndef MODULE
-	if (mode_option)
-		fb_find_mode (&rinfo->disp.var, &rinfo->info, mode_option,
-			      NULL, 0, NULL, 8);
-#endif				/* !MODULE */
-	return 0;
+	return (VGA_RD08(rinfo->riva.PVIO, 0x3cc));
 }
 
 
 
+/* ------------------------------------------------------------------------- *
+ *
+ * cursor stuff
+ *
+ * ------------------------------------------------------------------------- */
 
-static int __devinit riva_init_disp (struct rivafb_info *rinfo)
+/**
+ * riva_cursor_timer_handler - blink timer
+ * @dev_addr: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Cursor blink timer.
+ */
+static void riva_cursor_timer_handler(unsigned long dev_addr)
 {
-	struct fb_info *info;
-	struct display *disp;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rinfo != NULL);
+	struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr;
 
-	info = &rinfo->info;
-	disp = &rinfo->disp;
-
-	disp->var = rivafb_default_var;
-	info->disp = disp;
+	if (!rinfo->cursor) return;
 
-	/* FIXME: assure that disp->cmap is completely filled out */
+	if (!rinfo->cursor->enable) goto out;
 
-	disp->screen_base = rinfo->fb_base;
-	disp->visual = FB_VISUAL_PSEUDOCOLOR;
-	disp->type = FB_TYPE_PACKED_PIXELS;
-	disp->type_aux = 0;
-	disp->ypanstep = 1;
-	disp->ywrapstep = 0;
-	disp->next_line = disp->line_length =
-	    (disp->var.xres_virtual * disp->var.bits_per_pixel) >> 3;
-	disp->can_soft_blank = 1;
-	disp->inverse = 0;
+	if (rinfo->cursor->last_move_delay < 1000)
+		rinfo->cursor->last_move_delay++;
 
-	riva_set_dispsw (rinfo);
+	if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) {
+		rinfo->cursor->on ^= 1;
+		if (rinfo->cursor->on)
+			*(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF)
+						   | (rinfo->cursor->pos.y << 16);
+		rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on);
+		if (!noblink)
+			rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate;
+	}
+out:
+	rinfo->cursor->timer->expires = jiffies + (HZ / 100);
+	add_timer(rinfo->cursor->timer);
+}
 
-	disp->scrollmode = 0;
+/**
+ * rivafb_init_cursor - allocates cursor structure and starts blink timer
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Allocates cursor structure and starts blink timer.
+ *
+ * RETURNS:
+ * Pointer to allocated cursor structure.
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
+{
+	struct riva_cursor *cursor;
 
-	rinfo->currcon_display = disp;
+	cursor = kmalloc(sizeof(struct riva_cursor), GFP_KERNEL);
+	if (!cursor) return 0;
+	memset(cursor, 0, sizeof(*cursor));
 
-	if ((riva_init_disp_var (rinfo)) < 0) {	/* must be done last */
-		DPRINTK ("EXIT, returning -1\n");
-		return -1;
+	cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+	if (!cursor->timer) {
+		kfree(cursor);
+		return 0;
 	}
+	memset(cursor->timer, 0, sizeof(*cursor->timer));
 
-	DPRINTK ("EXIT, returning 0\n");
-	return 0;
+	cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
 
+	init_timer(cursor->timer);
+	cursor->timer->expires = jiffies + (HZ / 100);
+	cursor->timer->data = (unsigned long)rinfo;
+	cursor->timer->function = riva_cursor_timer_handler;
+	add_timer(cursor->timer);
+
+	return cursor;
 }
 
+/**
+ * rivafb_exit_cursor - stops blink timer and releases cursor structure
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Stops blink timer and releases cursor structure.
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ * rivafb_remove_one()
+ */
+static void rivafb_exit_cursor(struct rivafb_info *rinfo)
+{
+	struct riva_cursor *cursor = rinfo->cursor;
 
+	if (cursor) {
+		if (cursor->timer) {
+			del_timer_sync(cursor->timer);
+			kfree(cursor->timer);
+		}
+		kfree(cursor);
+		rinfo->cursor = 0;
+	}
+}
 
-static int __devinit riva_set_fbinfo (struct rivafb_info *rinfo)
+/**
+ * rivafb_download_cursor - writes cursor shape into card registers
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Writes cursor shape into card registers.
+ *
+ * CALLED FROM:
+ * riva_load_video_mode()
+ */
+static void rivafb_download_cursor(struct rivafb_info *rinfo)
 {
-	struct fb_info *info;
+	int i, save;
+	int *image;
+	
+	if (!rinfo->cursor) return;
 
-	assert (rinfo != NULL);
+	image = (int *)rinfo->cursor->image;
+	save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
+	for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++)
+		writel(image[i], rinfo->riva.CURSOR + i);
 
-	info = &rinfo->info;
+	rinfo->riva.ShowHideCursor(&rinfo->riva, save);
+}
 
-	strcpy (info->modename, rinfo->drvr_name);
-	info->node = -1;
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->fbops = &riva_fb_ops;
+/**
+ * rivafb_create_cursor - sets rectangular cursor
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @width: cursor width in pixels
+ * @height: cursor height in pixels
+ *
+ * DESCRIPTION:
+ * Sets rectangular cursor.
+ *
+ * CALLED FROM:
+ * rivafb_set_font()
+ * rivafb_set_var()
+ */
+static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int height)
+{
+	struct riva_cursor *c = rinfo->cursor;
+	int i, j, idx;
 
-	/* FIXME: set monspecs to what??? */
+	if (c) {
+		if (width <= 0 || height <= 0) {
+			width = 8;
+			height = 16;
+		}
+		if (width > MAX_CURS) width = MAX_CURS;
+		if (height > MAX_CURS) height = MAX_CURS;
 
-	info->display_fg = NULL;
-	strncpy (info->fontname, fontname, sizeof (info->fontname));
-	info->fontname[sizeof (info->fontname) - 1] = 0;
+		c->size.x = width;
+		c->size.y = height;
+		
+		idx = 0;
 
-	info->changevar = NULL;
-	info->switch_con = rivafb_switch;
-	info->updatevar = rivafb_updatevar;
-	info->blank = rivafb_blank;
+		for (i = 0; i < height; i++) {
+			for (j = 0; j < width; j++,idx++)
+				c->image[idx] = CURSOR_COLOR;
+			for (j = width; j < MAX_CURS; j++,idx++)
+				c->image[idx] = TRANSPARENT_COLOR;
+		}
+		for (i = height; i < MAX_CURS; i++)
+			for (j = 0; j < MAX_CURS; j++,idx++)
+				c->image[idx] = TRANSPARENT_COLOR;
+	}
+}
 
-	if (riva_init_disp (rinfo) < 0)	/* must be done last */
-		return -1;
+/**
+ * rivafb_set_font - change font size
+ * @p: pointer to display object
+ * @width: font width in pixels
+ * @height: font height in pixels
+ *
+ * DESCRIPTION:
+ * Callback function called if font settings changed.
+ *
+ * RETURNS:
+ * 1 (Always succeeds.)
+ */
+static int rivafb_set_font(struct display *p, int width, int height)
+{
+	struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info);
 
-	return 0;
+	rivafb_create_cursor(fb, width, height);
+	return 1;
 }
 
+/**
+ * rivafb_cursor - cursor handler
+ * @p: pointer to display object
+ * @mode: cursor mode (see CM_*)
+ * @x: cursor x coordinate in characters
+ * @y: cursor y coordinate in characters
+ *
+ * DESCRIPTION:
+ * Cursor handler.
+ */
+static void rivafb_cursor(struct display *p, int mode, int x, int y)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+	struct riva_cursor *c = rinfo->cursor;
+
+	if (!c)	return;
 
+	x = x * fontwidth(p) - p->var.xoffset;
+	y = y * fontheight(p) - p->var.yoffset;
+
+	if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
+		return;
 
+	c->enable = 0;
+	if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
+		
+	c->pos.x = x;
+	c->pos.y = y;
 
-/* ----------------------------- PCI bus ----------------------------- */
+	switch (mode) {
+	case CM_ERASE:
+		c->on = 0;
+		break;
+	case CM_DRAW:
+	case CM_MOVE:
+		if (c->last_move_delay <= 1) { /* rapid cursor movement */
+			c->vbl_cnt = CURSOR_SHOW_DELAY;
+		} else {
+			*(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
+			rinfo->riva.ShowHideCursor(&rinfo->riva, 1);
+			if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
+			c->on = 1;
+		}
+		c->last_move_delay = 0;
+		c->enable = 1;
+		break;
+	}
+}
 
 
 
+/* ------------------------------------------------------------------------- *
+ *
+ * general utility functions
+ *
+ * ------------------------------------------------------------------------- */
 
-static int __devinit rivafb_init_one (struct pci_dev *pd,
-				      const struct pci_device_id *ent)
+/**
+ * riva_set_dispsw - sets dispsw
+ * @rinfo: pointer to internal driver struct for a given Riva card
+ * @disp: pointer to display object
+ *
+ * DESCRIPTION:
+ * Sets up console low level operations depending on the current? color depth
+ * of the display.
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ * rivafb_switch()
+ * riva_init_disp()
+ */
+static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp)
 {
-	struct rivafb_info *rinfo;
-	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
+	int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
 
-	assert (pd != NULL);
-	assert (rci != NULL);
+	DPRINTK("ENTER\n");
 
-	rinfo = kmalloc (sizeof (struct rivafb_info), GFP_KERNEL);
-	if (!rinfo)
-		goto err_out;
+	assert(rinfo != NULL);
 
-	memset (rinfo, 0, sizeof (struct rivafb_info));
+	disp->dispsw_data = NULL;
 
-	rinfo->drvr_name = rci->name;
-	rinfo->riva.Architecture = rci->arch_rev;
-
-	rinfo->pd = pd;
-	rinfo->base0_region_size = pci_resource_len (pd, 0);
-	rinfo->base1_region_size = pci_resource_len (pd, 1);
+	disp->screen_base = rinfo->fb_base;
+	disp->type = FB_TYPE_PACKED_PIXELS;
+	disp->type_aux = 0;
+	disp->ypanstep = 1;
+	disp->ywrapstep = 0;
+	disp->can_soft_blank = 1;
+	disp->inverse = 0;
 
-	assert (rinfo->base0_region_size >= 0x00800000);	/* from GGI */
-	assert (rinfo->base1_region_size >= 0x01000000);	/* from GGI */
+	switch (disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8;
+		disp->dispsw = &rinfo->dispsw;
+		disp->line_length = disp->var.xres_virtual;
+		disp->visual = FB_VISUAL_PSEUDOCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16;
+		disp->dispsw_data = &rinfo->con_cmap.cfb16;
+		disp->dispsw = &rinfo->dispsw;
+		disp->line_length = disp->var.xres_virtual * 2;
+		disp->visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32;
+		disp->dispsw_data = rinfo->con_cmap.cfb32;
+		disp->dispsw = &rinfo->dispsw;
+		disp->line_length = disp->var.xres_virtual * 4;
+		disp->visual = FB_VISUAL_DIRECTCOLOR;
+		break;
+#endif
+	default:
+		DPRINTK("Setting fbcon_dummy renderer\n");
+		rinfo->dispsw = fbcon_dummy;
+		disp->dispsw = &rinfo->dispsw;
+	}
 
-	rinfo->ctrl_base_phys = pci_resource_start (rinfo->pd, 0);
-	rinfo->fb_base_phys = pci_resource_start (rinfo->pd, 1);
+	/* FIXME: verify that the above code sets dsp->* fields correctly */
 
-	if (!request_mem_region (rinfo->ctrl_base_phys,
-				 rinfo->base0_region_size, "rivafb")) {
-		printk (KERN_ERR PFX "cannot reserve MMIO region\n");
-		goto err_out_kfree;
+	if (rinfo->cursor) {
+		rinfo->dispsw.cursor = rivafb_cursor;
+		rinfo->dispsw.set_font = rivafb_set_font;
 	}
 
-	if (!request_mem_region (rinfo->fb_base_phys,
-				 rinfo->base1_region_size, "rivafb")) {
-		printk (KERN_ERR PFX "cannot reserve FB region\n");
-		goto err_out_free_base0;
+	DPRINTK("EXIT\n");
+}
+
+/**
+ * riva_wclut - set CLUT entry
+ * @chip: pointer to RIVA_HW_INST object
+ * @regnum: register number
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ *
+ * DESCRIPTION:
+ * Sets color register @regnum.
+ *
+ * CALLED FROM:
+ * riva_setcolreg()
+ */
+static void riva_wclut(RIVA_HW_INST *chip,
+		       unsigned char regnum, unsigned char red,
+		       unsigned char green, unsigned char blue)
+{
+	VGA_WR08(chip->PDIO, 0x3c8, regnum);
+	VGA_WR08(chip->PDIO, 0x3c9, red);
+	VGA_WR08(chip->PDIO, 0x3c9, green);
+	VGA_WR08(chip->PDIO, 0x3c9, blue);
+}
+
+/**
+ * riva_save_state - saves current chip state
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Saves current chip state to @regs.
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+/* from GGI */
+static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
+{
+	int i;
+
+	rinfo->riva.LockUnlock(&rinfo->riva, 0);
+
+	rinfo->riva.UnloadStateExt(&rinfo->riva, &regs->ext);
+
+	regs->misc_output = MISCin(rinfo);
+
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		regs->crtc[i] = CRTCin(rinfo, i);
 	}
 
-	rinfo->ctrl_base = ioremap (rinfo->ctrl_base_phys,
-				    rinfo->base0_region_size);
-	if (!rinfo->ctrl_base) {
-		printk (KERN_ERR PFX "cannot ioremap MMIO base\n");
-		goto err_out_free_base1;
+	for (i = 0; i < NUM_ATC_REGS; i++) {
+		regs->attr[i] = ATTRin(rinfo, i);
 	}
-	
-	rinfo->fb_base = ioremap (rinfo->fb_base_phys,
-				  rinfo->base1_region_size);
-	if (!rinfo->fb_base) {
-		printk (KERN_ERR PFX "cannot ioremap FB base\n");
-		goto err_out_iounmap_ctrl;
+
+	for (i = 0; i < NUM_GRC_REGS; i++) {
+		regs->gra[i] = GRAin(rinfo, i);
 	}
-	
-	rinfo->riva.EnableIRQ = 0;
-	rinfo->riva.IO = (inb (0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
-	rinfo->riva.PRAMDAC = (unsigned *) (rinfo->ctrl_base + 0x00680000);
-	rinfo->riva.PFB = (unsigned *) (rinfo->ctrl_base + 0x00100000);
-	rinfo->riva.PFIFO = (unsigned *) (rinfo->ctrl_base + 0x00002000);
-	rinfo->riva.PGRAPH = (unsigned *) (rinfo->ctrl_base + 0x00400000);
-	rinfo->riva.PEXTDEV = (unsigned *) (rinfo->ctrl_base + 0x00101000);
-	rinfo->riva.PTIMER = (unsigned *) (rinfo->ctrl_base + 0x00009000);
-	rinfo->riva.PMC = (unsigned *) (rinfo->ctrl_base + 0x00000000);
-	rinfo->riva.FIFO = (unsigned *) (rinfo->ctrl_base + 0x00800000);
 
-	switch (rinfo->riva.Architecture) {
-	case 3:
-		rinfo->riva.PRAMIN =
-		    (unsigned *) (rinfo->fb_base + 0x00C00000);
-		break;
-	case 4:
-	case 5:
-		rinfo->riva.PCRTC =
-		    (unsigned *) (rinfo->ctrl_base + 0x00600000);
-		rinfo->riva.PRAMIN =
-		    (unsigned *) (rinfo->ctrl_base + 0x00710000);
-		break;
+	for (i = 0; i < NUM_SEQ_REGS; i++) {
+		regs->seq[i] = SEQin(rinfo, i);
 	}
+}
 
-	RivaGetConfig (&rinfo->riva);
+/**
+ * riva_load_state - loads current chip state
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @regs: pointer to riva_regs object
+ *
+ * DESCRIPTION:
+ * Loads chip state from @regs.
+ *
+ * CALLED FROM:
+ * riva_load_video_mode()
+ * rivafb_init_one()
+ * rivafb_remove_one()
+ */
+/* from GGI */
+static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
+{
+	int i;
+	RIVA_HW_STATE *state = &regs->ext;
 
-	/* back to normal */
+	CRTCout(rinfo, 0x11, 0x00);
 
-	assert (rinfo->pd != NULL);
+	rinfo->riva.LockUnlock(&rinfo->riva, 0);
 
-	/* unlock io */
-	vga_io_wcrt (0x11, 0xFF);	/* vgaHWunlock() + riva unlock (0x7F) */
-	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
-	outb (0x57, rinfo->riva.LockUnlockIO + 1);
-
-	memcpy (&rinfo->initial_state, &reg_template,
-		sizeof (reg_template));
-	riva_save_state (rinfo, &rinfo->initial_state);
+	rinfo->riva.LoadStateExt(&rinfo->riva, state);
 
-	rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;
-	rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
+	MISCout(rinfo, regs->misc_output);
 
-	riva_set_fbinfo (rinfo);
+	for (i = 0; i < NUM_CRT_REGS; i++) {
+		switch (i) {
+		case 0x19:
+		case 0x20 ... 0x40:
+			break;
+		default:
+			CRTCout(rinfo, i, regs->crtc[i]);
+		}
+	}
 
-	fb_memset (rinfo->fb_base, 0, rinfo->ram_amount);
+	for (i = 0; i < NUM_ATC_REGS; i++) {
+		ATTRout(rinfo, i, regs->attr[i]);
+	}
 
-	riva_load_video_mode (rinfo, &rinfo->disp.var);
+	for (i = 0; i < NUM_GRC_REGS; i++) {
+		GRAout(rinfo, i, regs->gra[i]);
+	}
 
-	if (register_framebuffer ((struct fb_info *) rinfo) < 0) {
-		printk (KERN_ERR PFX
-			"error registering riva framebuffer\n");
-		goto err_out_iounmap_fb;
+	for (i = 0; i < NUM_SEQ_REGS; i++) {
+		SEQout(rinfo, i, regs->seq[i]);
 	}
+}
 
-	riva_boards = riva_board_list_add(riva_boards, rinfo);
+/**
+ * riva_load_video_mode - calculate timings
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @video_mode: video mode to set
+ *
+ * DESCRIPTION:
+ * Calculate some timings and then send em off to riva_load_state().
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ */
+static void riva_load_video_mode(struct rivafb_info *rinfo,
+				 struct fb_var_screeninfo *video_mode)
+{
+	struct riva_regs newmode;
+	int bpp, width, hDisplaySize, hDisplay, hStart,
+	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
 
-	pci_set_drvdata (pd, rinfo);
+	/* time to calculate */
 
-	printk (KERN_INFO PFX
-		"PCI Riva NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
-		rinfo->riva.Architecture,
-		RIVAFB_VERSION,
-		rinfo->drvr_name,
-		rinfo->ram_amount / (1024 * 1024) + 1,
-		rinfo->fb_base_phys);
+	rivafb_blank(1, (struct fb_info *)rinfo);
 
-	return 0;
+	bpp = video_mode->bits_per_pixel;
+	if (bpp == 16 && video_mode->green.length == 5)
+		bpp = 15;
+	width = video_mode->xres_virtual;
+	hDisplaySize = video_mode->xres;
+	hDisplay = (hDisplaySize / 8) - 1;
+	hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2;
+	hEnd = (hDisplaySize + video_mode->right_margin +
+		video_mode->hsync_len) / 8 - 1;
+	hTotal = (hDisplaySize + video_mode->right_margin +
+		  video_mode->hsync_len + video_mode->left_margin) / 8 - 1;
+	height = video_mode->yres_virtual;
+	vDisplay = video_mode->yres - 1;
+	vStart = video_mode->yres + video_mode->lower_margin - 1;
+	vEnd = video_mode->yres + video_mode->lower_margin +
+	       video_mode->vsync_len - 1;
+	vTotal = video_mode->yres + video_mode->lower_margin +
+		 video_mode->vsync_len + video_mode->upper_margin + 2;
+	dotClock = 1000000000 / video_mode->pixclock;
 
-err_out_iounmap_fb:
-	iounmap (rinfo->fb_base);
-err_out_iounmap_ctrl:
-	iounmap (rinfo->ctrl_base);
-err_out_free_base1:
-	release_mem_region (rinfo->fb_base_phys, rinfo->base1_region_size);
-err_out_free_base0:
-	release_mem_region (rinfo->ctrl_base_phys, rinfo->base0_region_size);
-err_out_kfree:
-	kfree (rinfo);
-err_out:
-	return -ENODEV;
+	memcpy(&newmode, &reg_template, sizeof(struct riva_regs));
+
+	newmode.crtc[0x0] = Set8Bits (hTotal - 4);
+	newmode.crtc[0x1] = Set8Bits (hDisplay);
+	newmode.crtc[0x2] = Set8Bits (hDisplay);
+	newmode.crtc[0x3] = SetBitField (hTotal, 4: 0, 4:0) | SetBit (7);
+	newmode.crtc[0x4] = Set8Bits (hStart);
+	newmode.crtc[0x5] = SetBitField (hTotal, 5: 5, 7:7)
+		| SetBitField (hEnd, 4: 0, 4:0);
+	newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
+	newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
+		| SetBitField (vDisplay, 8: 8, 1:1)
+		| SetBitField (vStart, 8: 8, 2:2)
+		| SetBitField (vDisplay, 8: 8, 3:3)
+		| SetBit (4)
+		| SetBitField (vTotal, 9: 9, 5:5)
+		| SetBitField (vDisplay, 9: 9, 6:6)
+		| SetBitField (vStart, 9: 9, 7:7);
+	newmode.crtc[0x9] = SetBitField (vDisplay, 9: 9, 5:5)
+		| SetBit (6);
+	newmode.crtc[0x10] = Set8Bits (vStart);
+	newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
+		| SetBit (5);
+	newmode.crtc[0x12] = Set8Bits (vDisplay);
+	newmode.crtc[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF;
+	newmode.crtc[0x15] = Set8Bits (vDisplay);
+	newmode.crtc[0x16] = Set8Bits (vTotal + 1);
+
+	newmode.ext.bpp = bpp;
+	newmode.ext.width = width;
+	newmode.ext.height = height;
+
+	rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width,
+				  hDisplaySize, hDisplay, hStart, hEnd,
+				  hTotal, height, vDisplay, vStart, vEnd,
+				  vTotal, dotClock);
+
+	rinfo->current_state = newmode;
+	riva_load_state(rinfo, &rinfo->current_state);
+
+	rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */
+	rivafb_download_cursor(rinfo);
 }
 
+/**
+ * riva_board_list_add - maintains board list
+ * @board_list: root node of list of boards
+ * @new_node: new node to be added
+ *
+ * DESCRIPTION:
+ * Adds @new_node to the list referenced by @board_list.
+ *
+ * RETURNS:
+ * New root node
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list,
+					       struct rivafb_info *new_node)
+{
+	struct rivafb_info *i_p = board_list;
 
-static void __devexit rivafb_remove_one (struct pci_dev *pd)
+	new_node->next = NULL;
+
+	if (board_list == NULL)
+		return new_node;
+
+	while (i_p->next != NULL)
+		i_p = i_p->next;
+	i_p->next = new_node;
+
+	return board_list;
+}
+
+/**
+ * riva_board_list_del - maintains board list
+ * @board_list: root node of list of boards
+ * @del_node: node to be removed
+ *
+ * DESCRIPTION:
+ * Removes @del_node from the list referenced by @board_list.
+ *
+ * RETURNS:
+ * New root node
+ *
+ * CALLED FROM:
+ * rivafb_remove_one()
+ */
+static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
+					       struct rivafb_info *del_node)
 {
-	struct rivafb_info *board = pci_get_drvdata (pd);
-	
-	if (!board)
-		return;
-		
-	riva_boards = riva_board_list_del(riva_boards, board);
+	struct rivafb_info *i_p = board_list;
 
-	riva_load_state (board, &board->initial_state);
+	if (board_list == del_node)
+		return del_node->next;
 
-	unregister_framebuffer ((struct fb_info *) board);
+	while (i_p->next != del_node)
+		i_p = i_p->next;
+	i_p->next = del_node->next;
+
+	return board_list;
+}
 
-	iounmap (board->ctrl_base);
-	iounmap (board->fb_base);
+/**
+ * rivafb_do_maximize - 
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
+ * @var:
+ * @v:
+ * @nom:
+ * @den:
+ *
+ * DESCRIPTION:
+ * .
+ *
+ * RETURNS:
+ * -EINVAL on failure, 0 on success
+ * 
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ */
+static int rivafb_do_maximize(struct rivafb_info *rinfo,
+			      struct fb_var_screeninfo *var,
+			      struct fb_var_screeninfo *v,
+			      int nom, int den)
+{
+	static struct {
+		int xres, yres;
+	} modes[] = {
+		{1600, 1280},
+		{1280, 1024},
+		{1024, 768},
+		{800, 600},
+		{640, 480},
+		{-1, -1}
+	};
+	int i;
 
-	release_mem_region (board->ctrl_base_phys,
-			    board->base0_region_size);
-	release_mem_region (board->fb_base_phys,
-			    board->base1_region_size);
+	/* use highest possible virtual resolution */
+	if (v->xres_virtual == -1 && v->yres_virtual == -1) {
+		printk(KERN_WARNING PFX
+		       "using maximum available virtual resolution\n");
+		for (i = 0; modes[i].xres != -1; i++) {
+			if (modes[i].xres * nom / den * modes[i].yres <
+			    rinfo->ram_amount / 2)
+				break;
+		}
+		if (modes[i].xres == -1) {
+			printk(KERN_ERR PFX
+			       "could not find a virtual resolution that fits into video memory!!\n");
+			DPRINTK("EXIT - EINVAL error\n");
+			return -EINVAL;
+		}
+		v->xres_virtual = modes[i].xres;
+		v->yres_virtual = modes[i].yres;
 
-	kfree (board);
+		printk(KERN_INFO PFX
+		       "virtual resolution set to maximum of %dx%d\n",
+		       v->xres_virtual, v->yres_virtual);
+	} else if (v->xres_virtual == -1) {
+		v->xres_virtual = (rinfo->ram_amount * den /
+			(nom * v->yres_virtual * 2)) & ~15;
+		printk(KERN_WARNING PFX
+		       "setting virtual X resolution to %d\n", v->xres_virtual);
+	} else if (v->yres_virtual == -1) {
+		v->xres_virtual = (v->xres_virtual + 15) & ~15;
+		v->yres_virtual = rinfo->ram_amount * den /
+			(nom * v->xres_virtual * 2);
+		printk(KERN_WARNING PFX
+		       "setting virtual Y resolution to %d\n", v->yres_virtual);
+	} else {
+		v->xres_virtual = (v->xres_virtual + 15) & ~15;
+		if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) {
+			printk(KERN_ERR PFX
+			       "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;
+		}
+	}
+	
+	if (v->xres_virtual * nom / den >= 8192) {
+		printk(KERN_WARNING PFX
+		       "virtual X resolution (%d) is too high, lowering to %d\n",
+		       v->xres_virtual, 8192 * den / nom - 16);
+		v->xres_virtual = 8192 * den / nom - 16;
+	}
+	
+	if (v->xres_virtual < v->xres) {
+		printk(KERN_ERR PFX
+		       "virtual X resolution (%d) is smaller than real\n", v->xres_virtual);
+		return -EINVAL;
+	}
 
-	pci_set_drvdata (pd, NULL);
+	if (v->yres_virtual < v->yres) {
+		printk(KERN_ERR PFX
+		       "virtual Y resolution (%d) is smaller than real\n", v->yres_virtual);
+		return -EINVAL;
+	}
+	
+	return 0;
 }
 
 
-/*** riva_wclut - set CLUT entry ***/
-static void riva_wclut (unsigned char regnum, unsigned char red,
-			unsigned char green, unsigned char blue)
+
+/* ------------------------------------------------------------------------- *
+ *
+ * internal fb_ops helper functions
+ *
+ * ------------------------------------------------------------------------- */
+
+/**
+ * riva_get_cmap_len - query current color map length
+ * @var: standard kernel fb changeable data
+ *
+ * DESCRIPTION:
+ * Get current color map length.
+ *
+ * RETURNS:
+ * Length of color map
+ *
+ * CALLED FROM:
+ * riva_getcolreg()
+ * riva_setcolreg()
+ * rivafb_get_cmap()
+ * rivafb_set_cmap()
+ */
+static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
 {
-	unsigned int data = VGA_PEL_D;
+	int rc = 16;		/* reasonable default */
+
+	assert(var != NULL);
 
-	/* address write mode register is not translated.. */
-	vga_io_w (VGA_PEL_IW, regnum);
+	switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		rc = 256;	/* pseudocolor... 256 entries HW palette */
+		break;
+#endif
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		rc = 16;	/* directcolor... 16 entries SW palette */
+		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		rc = 16;	/* directcolor... 16 entries SW palette */
+		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+	default:
+		assert(0);
+		/* should not occur */
+		break;
+	}
 
-	vga_io_w (data, red);
-	vga_io_w (data, green);
-	vga_io_w (data, blue);
+	return rc;
 }
 
+/**
+ * riva_getcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Read a single color register and split it into colors/transparent.
+ * The return values must have a 16 bit magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * rivafb_get_cmap()
+ * rivafb_switch()
+ * fbcmap.c:fb_get_cmap()
+ *	fbgen.c:fbgen_get_cmap()
+ *	fbgen.c:fbgen_switch()
+ */
+static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+			  unsigned *blue, unsigned *transp,
+			  struct fb_info *info)
+{
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
+	if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
+		return 1;
 
-/* ------------ Hardware Independent Functions ------------ */
+	*red = rivainfo->palette[regno].red;
+	*green = rivainfo->palette[regno].green;
+	*blue = rivainfo->palette[regno].blue;
+	*transp = 0;
 
-#ifndef MODULE
-int __init rivafb_setup (char *options)
+	return 0;
+}
+
+/**
+ * riva_setcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Set a single color register. The values supplied have a 16 bit
+ * magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * rivafb_set_cmap()
+ * fbcmap.c:fb_set_cmap()
+ *	fbgen.c:fbgen_get_cmap()
+ *	fbgen.c:fbgen_install_cmap()
+ *		fbgen.c:fbgen_set_var()
+ *		fbgen.c:fbgen_switch()
+ *		fbgen.c:fbgen_blank()
+ *	fbgen.c:fbgen_blank()
+ */
+static int riva_setcolreg(unsigned regno, unsigned red, unsigned green,
+			  unsigned blue, unsigned transp,
+			  struct fb_info *info)
 {
-	char *this_opt;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+	RIVA_HW_INST *chip = &rivainfo->riva;
+	struct display *p;
 
-	if (!options || !*options)
-		return 0;
+	DPRINTK("ENTER\n");
 
-	for (this_opt = strtok (options, ","); this_opt;
-	     this_opt = strtok (NULL, ",")) {
-		if (!strncmp (this_opt, "font:", 5)) {
-			char *p;
-			int i;
+	assert(rivainfo != NULL);
+	assert(rivainfo->currcon_display != NULL);
 
-			p = this_opt + 5;
-			for (i = 0; i < sizeof (fontname) - 1; i++)
-				if (!*p || *p == ' ' || *p == ',')
-					break;
-			memcpy (fontname, this_opt + 5, i);
-			fontname[i] = 0;
-		}
+	p = rivainfo->currcon_display;
+
+	if (regno >= riva_get_cmap_len(&p->var))
+		return -EINVAL;
+
+	rivainfo->palette[regno].red = red;
+	rivainfo->palette[regno].green = green;
+	rivainfo->palette[regno].blue = blue;
+
+	if (p->var.grayscale) {
+		/* gray = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue =
+		    (red * 77 + green * 151 + blue * 28) >> 8;
+	}
 
-		else if (!strncmp (this_opt, "noaccel", 7)) {
-			noaccel = 1;
+	switch (p->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+	case 8:
+		/* "transparent" stuff is completely ignored. */
+		riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
+		break;
+#endif /* FBCON_HAS_CFB8 */
+#ifdef FBCON_HAS_CFB16
+	case 16:
+		assert(regno < 16);
+		if (p->var.green.length == 5) {
+			/* 0rrrrrgg gggbbbbb */
+			rivainfo->con_cmap.cfb16[regno] =
+			    ((red & 0xf800) >> 1) |
+			    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
+		} else {
+			/* rrrrrggg gggbbbbb */
+			rivainfo->con_cmap.cfb16[regno] =
+			    ((red & 0xf800) >> 0) |
+			    ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
 		}
-
-		else
-			mode_option = this_opt;
+		break;
+#endif /* FBCON_HAS_CFB16 */
+#ifdef FBCON_HAS_CFB32
+	case 32:
+		assert(regno < 16);
+		rivainfo->con_cmap.cfb32[regno] =
+		    ((red & 0xff00) << 8) |
+		    ((green & 0xff00)) | ((blue & 0xff00) >> 8);
+		break;
+#endif /* FBCON_HAS_CFB32 */
+	default:
+		/* do nothing */
+		break;
 	}
+
 	return 0;
 }
-#endif				/* !MODULE */
-
-    /*
-     *  Initialization
-     */
 
-/* ------------------------------------------------------------------------- */
 
 
-    /*
-     *  Frame buffer operations
-     */
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer operations
+ *
+ * ------------------------------------------------------------------------- */
 
-static int rivafb_get_fix (struct fb_fix_screeninfo *fix, int con,
-		    struct fb_info *info)
+static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+			  struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *p;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (fix != NULL);
-	assert (info != NULL);
-	assert (rivainfo->drvr_name && rivainfo->drvr_name[0]);
-	assert (rivainfo->fb_base_phys > 0);
-	assert (rivainfo->ram_amount > 0);
+	assert(fix != NULL);
+	assert(info != NULL);
+	assert(rivainfo->drvr_name && rivainfo->drvr_name[0]);
+	assert(rivainfo->fb_base_phys > 0);
+	assert(rivainfo->ram_amount > 0);
 
 	p = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
-	memset (fix, 0, sizeof (struct fb_fix_screeninfo));
-	sprintf (fix->id, "Riva %s", rivainfo->drvr_name);
+	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+	sprintf(fix->id, "nVidia %s", rivainfo->drvr_name);
 
 	fix->smem_start = rivainfo->fb_base_phys;
 	fix->smem_len = rivainfo->ram_amount;
@@ -730,71 +1298,70 @@
 
 	fix->line_length = p->line_length;
 
-	/* FIXME: set up MMIO region, export via FB_ACCEL_xxx */
-	fix->mmio_start = 0;
-	fix->mmio_len = 0;
-	fix->accel = FB_ACCEL_NONE;
+	fix->mmio_start = rivainfo->ctrl_base_phys;
+	fix->mmio_len = rivainfo->base0_region_size;
+	fix->smem_start = rivainfo->fb_base_phys;
+	fix->smem_len = rivainfo->base1_region_size;
+
+	switch (rivainfo->riva.Architecture) {
+	case NV_ARCH_03:
+		fix->accel = FB_ACCEL_NV3;
+		break;
+	case NV_ARCH_04:	/* riva_hw.c now doesn't distinguish between TNT & TNT2 */
+		fix->accel = FB_ACCEL_NV4;
+		break;
+	case NV_ARCH_10:	/* FIXME: ID for GeForce */
+		fix->accel = FB_ACCEL_NV4;
+		break;
+
+	}
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-static int rivafb_get_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info)
+static int rivafb_get_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (info != NULL);
-	assert (var != NULL);
+	assert(info != NULL);
+	assert(var != NULL);
 
 	*var = (con < 0) ? rivainfo->disp.var : fb_display[con].var;
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-
-static int rivafb_set_var (struct fb_var_screeninfo *var, int con,
-		    struct fb_info *info)
+static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
+			  struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *dsp;
 	struct fb_var_screeninfo v;
 	int nom, den;		/* translating from pixels->bytes */
-	int i;
+	int accel;
 	unsigned chgvar = 0;
-	static struct {
-		int xres, yres;
-	} modes[] = {
-		{
-		1600, 1280}, {
-		1280, 1024}, {
-		1024, 768}, {
-		800, 600}, {
-		640, 480}, {
-		-1, -1}
-	};
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (info != NULL);
-	assert (var != NULL);
+	assert(info != NULL);
+	assert(var != NULL);
 
-	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);
+	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);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
-	assert (dsp != NULL);
+	assert(dsp != NULL);
 
 	/* if var has changed, we should call changevar() later */
 	if (con >= 0) {
@@ -802,135 +1369,84 @@
 			  (dsp->var.yres != var->yres) ||
 			  (dsp->var.xres_virtual != var->xres_virtual) ||
 			  (dsp->var.yres_virtual != var->yres_virtual) ||
+			  (dsp->var.accel_flags != var->accel_flags) ||
 			  (dsp->var.bits_per_pixel != var->bits_per_pixel)
-			  || memcmp (&dsp->var.red, &var->red,
-				     sizeof (var->red))
-			  || memcmp (&dsp->var.green, &var->green,
-				     sizeof (var->green))
-			  || memcmp (&dsp->var.blue, &var->blue,
-				     sizeof (var->blue)));
+			  || memcmp(&dsp->var.red, &var->red,
+				    sizeof(var->red))
+			  || memcmp(&dsp->var.green, &var->green,
+				    sizeof(var->green))
+			  || memcmp(&dsp->var.blue, &var->blue,
+				    sizeof(var->blue)));
 	}
 
-	memcpy (&v, var, sizeof (v));
+	memcpy(&v, var, sizeof(v));
 
-	switch (v.bits_per_pixel) {
-#ifdef FBCON_HAS_MFB
-	case 1:
-		dsp->dispsw = &fbcon_mfb;
-		dsp->line_length = v.xres_virtual / 8;
-		dsp->visual = FB_VISUAL_MONO10;
-		nom = 4;
-		den = 8;
-		break;
-#endif
+	accel = v.accel_flags & FB_ACCELF_TEXT;
 
+	switch (v.bits_per_pixel) {
 #ifdef FBCON_HAS_CFB8
-	case 2 ... 8:
+	case 1 ... 8:
 		v.bits_per_pixel = 8;
-		dsp->dispsw = &fbcon_cfb8;
 		nom = 1;
 		den = 1;
-		dsp->line_length = v.xres_virtual;
-		dsp->visual = FB_VISUAL_PSEUDOCOLOR;
 		v.red.offset = 0;
-		v.red.length = 6;
+		v.red.length = 8;
 		v.green.offset = 0;
-		v.green.length = 6;
+		v.green.length = 8;
 		v.blue.offset = 0;
-		v.blue.length = 6;
+		v.blue.length = 8;
 		break;
 #endif
-
 #ifdef FBCON_HAS_CFB16
-	case 9 ... 16:
+	case 9 ... 15:
+		v.green.length = 5;
+		/* fall through */
+	case 16:
 		v.bits_per_pixel = 16;
-		dsp->dispsw = &fbcon_cfb16;
-		dsp->dispsw_data = &rivainfo->con_cmap.cfb16;
 		nom = 2;
 		den = 1;
-		dsp->line_length = v.xres_virtual * 2;
-		dsp->visual = FB_VISUAL_DIRECTCOLOR;
-#ifdef CONFIG_PREP
-		v.red.offset = 2;
-		v.green.offset = -3;
-		v.blue.offset = 8;
-#else
-		v.red.offset = 10;
-		v.green.offset = 5;
-		v.blue.offset = 0;
-#endif
-		v.red.length = 5;
-		v.green.length = 5;
-		v.blue.length = 5;
+		if (v.green.length == 5) {
+			/* 0rrrrrgg gggbbbbb */
+			v.red.offset = 10;
+			v.green.offset = 5;
+			v.blue.offset = 0;
+			v.red.length = 5;
+			v.green.length = 5;
+			v.blue.length = 5;
+		} else {
+			/* rrrrrggg gggbbbbb */
+			v.red.offset = 11;
+			v.green.offset = 5;
+			v.blue.offset = 0;
+			v.red.length = 5;
+			v.green.length = 6;
+			v.blue.length = 5;
+		}
 		break;
 #endif
-
 #ifdef FBCON_HAS_CFB32
 	case 17 ... 32:
 		v.bits_per_pixel = 32;
-		dsp->dispsw = &fbcon_cfb32;
-		dsp->dispsw_data = rivainfo->con_cmap.cfb32;
 		nom = 4;
 		den = 1;
-		dsp->line_length = v.xres_virtual * 4;
-		dsp->visual = FB_VISUAL_DIRECTCOLOR;
-#ifdef CONFIG_PREP
-		v.red.offset = 8;
-		v.green.offset = 16;
-		v.blue.offset = 24;
-#else
 		v.red.offset = 16;
 		v.green.offset = 8;
 		v.blue.offset = 0;
-#endif
 		v.red.length = 8;
 		v.green.length = 8;
 		v.blue.length = 8;
 		break;
 #endif
-
 	default:
-		printk (KERN_ERR PFX
-			"mode %dx%dx%d rejected...color depth not supported.\n",
-			var->xres, var->yres, var->bits_per_pixel);
-		DPRINTK ("EXIT, returning -EINVAL\n");
+		printk(KERN_ERR PFX
+		       "mode %dx%dx%d rejected...color depth not supported.\n",
+		       var->xres, var->yres, var->bits_per_pixel);
+		DPRINTK("EXIT, returning -EINVAL\n");
 		return -EINVAL;
 	}
 
-	if (v.xres * nom / den * v.yres > rivainfo->ram_amount) {
-		printk (KERN_ERR PFX
-			"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");
+	if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0)
 		return -EINVAL;
-	}
-
-	/* use highest possible virtual resolution */
-	if (v.xres_virtual == -1 && v.yres_virtual == -1) {
-		printk (KERN_WARNING PFX
-			"using maximum available virtual resolution\n");
-		for (i = 0; modes[i].xres != -1; i++) {
-			if (modes[i].xres * nom / den * modes[i].yres <
-			    rivainfo->ram_amount / 2)
-				break;
-		}
-		if (modes[i].xres == -1) {
-			printk (KERN_ERR PFX
-				"could not find a virtual resolution that fits into video memory!!\n");
-			DPRINTK ("EXIT - EINVAL error\n");
-			return -EINVAL;
-		}
-		v.xres_virtual = modes[i].xres;
-		v.yres_virtual = modes[i].yres;
-
-		printk (KERN_INFO PFX
-			"virtual resolution set to maximum of %dx%d\n",
-			v.xres_virtual, v.yres_virtual);
-	} else if (v.xres_virtual == -1) {
-		/* FIXME: maximize X virtual resolution only */
-	} else if (v.yres_virtual == -1) {
-		/* FIXME: maximize Y virtual resolution only */
-	}
 
 	if (v.xoffset < 0)
 		v.xoffset = 0;
@@ -951,103 +1467,107 @@
 
 	switch (v.activate & FB_ACTIVATE_MASK) {
 	case FB_ACTIVATE_TEST:
-		DPRINTK ("EXIT - FB_ACTIVATE_TEST\n");
+		DPRINTK("EXIT - FB_ACTIVATE_TEST\n");
 		return 0;
 	case FB_ACTIVATE_NXTOPEN:	/* ?? */
 	case FB_ACTIVATE_NOW:
 		break;		/* continue */
 	default:
-		DPRINTK ("EXIT - unknown activation type\n");
+		DPRINTK("EXIT - unknown activation type\n");
 		return -EINVAL;	/* unknown */
 	}
 
-	dsp->type = FB_TYPE_PACKED_PIXELS;
-
-	/* FIXME: verify that the above code sets dsp->* fields correctly */
-
-	memcpy (&dsp->var, &v, sizeof (v));
+	memcpy(&dsp->var, &v, sizeof(v));
+	if (chgvar) {
+		riva_set_dispsw(rivainfo, dsp);
+
+		if (accel) {
+			if (nomove)
+				dsp->scrollmode = SCROLL_YNOMOVE;
+			else
+				dsp->scrollmode = 0;
+		} else
+			dsp->scrollmode = SCROLL_YREDRAW;
+
+		if (info && info->changevar)
+			info->changevar(con);
+	}
+
+	rivafb_create_cursor(rivainfo, fontwidth(dsp), fontheight(dsp));
+	riva_load_video_mode(rivainfo, &v);
+	if (accel) riva_setup_accel(rivainfo);
 
-	riva_load_video_mode (rivainfo, &v);
-
-	if (chgvar && info && info->changevar)
-		info->changevar (con);
-
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 	return 0;
 }
 
-
-
-static int rivafb_get_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info)
+static int rivafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *dsp;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (rivainfo != NULL);
-	assert (cmap != NULL);
+	assert(rivainfo != NULL);
+	assert(cmap != NULL);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
 	if (con == rivainfo->currcon) {	/* current console? */
-		int rc = fb_get_cmap (cmap, kspc, riva_getcolreg, info);
-		DPRINTK ("EXIT - returning %d\n", rc);
+		int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info);
+		DPRINTK("EXIT - returning %d\n", rc);
 		return rc;
 	} else if (dsp->cmap.len)	/* non default colormap? */
-		fb_copy_cmap (&dsp->cmap, cmap, kspc ? 0 : 2);
+		fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
 	else
-		fb_copy_cmap (fb_default_cmap
-			      (riva_get_cmap_len (&dsp->var)), cmap,
-			      kspc ? 0 : 2);
+		fb_copy_cmap(fb_default_cmap
+			     (riva_get_cmap_len(&dsp->var)), cmap,
+			     kspc ? 0 : 2);
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-static int rivafb_set_cmap (struct fb_cmap *cmap, int kspc, int con,
-		     struct fb_info *info)
+static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+			   struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct display *dsp;
 	unsigned int cmap_len;
 
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
-	assert (cmap != NULL);
+	DPRINTK("ENTER\n");
+	
+	assert(rivainfo != NULL);
+	assert(cmap != NULL);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
-	cmap_len = riva_get_cmap_len (&dsp->var);
+	cmap_len = riva_get_cmap_len(&dsp->var);
 	if (dsp->cmap.len != cmap_len) {
-		int err = fb_alloc_cmap (&dsp->cmap, cmap_len, 0);
+		int err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0);
 		if (err) {
-			DPRINTK ("EXIT - returning %d\n", err);
+			DPRINTK("EXIT - returning %d\n", err);
 			return err;
 		}
 	}
 	if (con == rivainfo->currcon) {	/* current console? */
-		int rc = fb_set_cmap (cmap, kspc, riva_setcolreg, info);
-		DPRINTK ("EXIT - returning %d\n", rc);
+		int rc = fb_set_cmap(cmap, kspc, riva_setcolreg, info);
+		DPRINTK("EXIT - returning %d\n", rc);
 		return rc;
 	} else
-		fb_copy_cmap (cmap, &dsp->cmap, kspc ? 0 : 1);
+		fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-
 /**
  * rivafb_pan_display
  * @var: standard kernel fb changeable data
- * @con:
+ * @con: TODO
  * @info: pointer to rivafb_info object containing info for current riva board
  *
  * DESCRIPTION:
@@ -1057,17 +1577,16 @@
  *
  * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
  */
-
-static int rivafb_pan_display (struct fb_var_screeninfo *var, int con,
-			struct fb_info *info)
+static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
+			      struct fb_info *info)
 {
 	unsigned int base;
 	struct display *dsp;
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (rivainfo != NULL);
+	assert(rivainfo != NULL);
 
 	if (var->xoffset > (var->xres_virtual - var->xres))
 		return -EINVAL;
@@ -1089,7 +1608,7 @@
 	base = var->yoffset * dsp->line_length + var->xoffset;
 
 	if (con == rivainfo->currcon) {
-		rivainfo->riva.SetStartAddress (&rivainfo->riva, base);
+		rivainfo->riva.SetStartAddress(&rivainfo->riva, base);
 	}
 
 	dsp->var.xoffset = var->xoffset;
@@ -1100,606 +1619,512 @@
 	else
 		dsp->var.vmode &= ~FB_VMODE_YWRAP;
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 
 	return 0;
 }
 
-
-static int rivafb_ioctl (struct inode *inode, struct file *file, unsigned int cmd,
-		  unsigned long arg, int con, struct fb_info *info)
+static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+			unsigned long arg, int con, struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	assert (rivainfo != NULL);
+	assert(rivainfo != NULL);
 
 	/* no rivafb-specific ioctls */
 
-	DPRINTK ("EXIT, returning -EINVAL\n");
+	DPRINTK("EXIT, returning -EINVAL\n");
 
 	return -EINVAL;
 }
 
+static int rivafb_rasterimg(struct fb_info *info, int start)
+{
+	struct rivafb_info *rinfo = (struct rivafb_info *)info;
+
+	wait_for_idle(rinfo);
+
+	return 0;
+}
 
-static int rivafb_switch (int con, struct fb_info *info)
+static int rivafb_switch(int con, struct fb_info *info)
 {
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
+	struct rivafb_info *rivainfo = (struct rivafb_info *)info;
 	struct fb_cmap *cmap;
 	struct display *dsp;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
+	
+	DPRINTK("ENTER\n");
+	
+	assert(rivainfo != NULL);
 
 	dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
 
 	if (rivainfo->currcon >= 0) {
 		/* Do we have to save the colormap? */
 		cmap = &(rivainfo->currcon_display->cmap);
-		DPRINTK ("switch1: con = %d, cmap.len = %d\n",
+		DPRINTK("switch1: con = %d, cmap.len = %d\n",
 			 rivainfo->currcon, cmap->len);
 
 		if (cmap->len) {
-			DPRINTK ("switch1a: %p %p %p %p\n", cmap->red,
+			DPRINTK("switch1a: %p %p %p %p\n", cmap->red,
 				 cmap->green, cmap->blue, cmap->transp);
-			fb_get_cmap (cmap, 1, riva_getcolreg, info);
-#ifdef DEBUG
-			if (cmap->red) {
-				DPRINTK ("switch1r: %X\n", cmap->red[0]);
-			}
-#endif
+			fb_get_cmap(cmap, 1, riva_getcolreg, info);
 		}
 	}
 	rivainfo->currcon = con;
 	rivainfo->currcon_display = dsp;
-	dsp->var.activate = FB_ACTIVATE_NOW;
-
-#ifdef riva_DEBUG
-	cmap = &dsp->cmap;
-	DPRINTK ("switch2: con = %d, cmap.len = %d\n", con, cmap->len);
-	DPRINTK ("switch2a: %p %p %p %p\n", cmap->red, cmap->green,
-		 cmap->blue, cmap->transp);
-	if (dsp->cmap.red) {
-		DPRINTK ("switch2r: %X\n", cmap->red[0]);
-	}
-#endif
 
-	rivafb_set_var (&dsp->var, con, info);
-
-#ifdef riva_DEBUG
-	DPRINTK ("switch3: con = %d, cmap.len = %d\n", con, cmap->len);
-	DPRINTK ("switch3a: %p %p %p %p\n", cmap->red, cmap->green,
-		 cmap->blue, cmap->transp);
-	if (dsp->cmap.red) {
-		DPRINTK ("switch3r: %X\n", cmap->red[0]);
-	}
-#endif
+	rivafb_set_var(&dsp->var, con, info);
+	riva_set_dispsw(rivainfo, dsp);
 
-	DPRINTK ("EXIT, returning 0\n");
+	DPRINTK("EXIT, returning 0\n");
 	return 0;
 }
 
-static int rivafb_updatevar (int con, struct fb_info *info)
+static int rivafb_updatevar(int con, struct fb_info *info)
 {
 	int rc;
 
-	DPRINTK ("ENTER\n");
+	DPRINTK("ENTER\n");
 
-	rc = (con <
-		0) ? -EINVAL : rivafb_pan_display (&fb_display[con].var,
-						   con, info);
-	DPRINTK ("EXIT, returning %d\n", rc);
+	rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var,
+						      con, info);
+	DPRINTK("EXIT, returning %d\n", rc);
 	return rc;
 }
 
-
-static void rivafb_blank (int blank, struct fb_info *info)
+static void rivafb_blank(int blank, struct fb_info *info)
 {
-	unsigned char tmp;
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
-
-	tmp = vga_io_rseq (VGA_SEQ_CLOCK_MODE) & ~VGA_SR01_SCREEN_OFF;
-
-	if (blank)
-		tmp |= VGA_SR01_SCREEN_OFF;
-
-	vga_io_wseq (VGA_SEQ_CLOCK_MODE, tmp);
-
-	DPRINTK ("EXIT\n");
-}
-
-
-/* -------------------------------------------------------------------------
- *
- * internal fb_ops helper functions
- *
- * -------------------------------------------------------------------------
- */
-
-
-/**
- * riva_get_cmap_len
- * @var:
- *
- * DESCRIPTION:
- */
+	unsigned char tmp, vesa;
+	struct rivafb_info *rinfo = (struct rivafb_info *)info;
 
-static int riva_get_cmap_len (const struct fb_var_screeninfo *var)
-{
-	int rc = 16;		/* reasonable default */
+	DPRINTK("ENTER\n");
 
-	assert (var != NULL);
+	assert(rinfo != NULL);
 
-	switch (var->bits_per_pixel) {
-#ifdef FBCON_HAS_CFB4
-	case 4:
-		rc = 16;	/* pseudocolor... 16 entries HW palette */
-		break;
-#endif
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		rc = 256;	/* pseudocolor... 256 entries HW palette */
-		break;
-#endif
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		rc = 16;	/* directcolor... 16 entries SW palette */
-		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-#endif
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		rc = 16;	/* directcolor... 16 entries SW palette */
-		break;		/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
-#endif
-	default:
-		assert (0);
-		/* should not occur */
-		break;
+	tmp = SEQin(rinfo, 0x01) & ~0x20;	/* screen on/off */
+	vesa = CRTCin(rinfo, 0x1a) & ~0xc0;	/* sync on/off */
+
+	if (blank) {
+		tmp |= 0x20;
+		switch (blank - 1) {
+		case VESA_NO_BLANKING:
+			break;
+		case VESA_VSYNC_SUSPEND:
+			vesa |= 0x80;
+			break;
+		case VESA_HSYNC_SUSPEND:
+			vesa |= 0x40;
+			break;
+		case VESA_POWERDOWN:
+			vesa |= 0xc0;
+			break;
+		}
 	}
 
-	return rc;
-}
-
-
-/**
- * riva_getcolreg
- * @regno:
- * @red:
- * @green:
- * @blue:
- * @transp:
- * @info: pointer to rivafb_info object containing info for current riva board
- *
- * DESCRIPTION:
- * Read a single color register and split it into colors/transparent.
- * The return values must have a 16 bit magnitude.
- * Return != 0 for invalid regno.
- *
- * CALLED FROM:
- * fbcmap.c:fb_get_cmap()
- *	fbgen.c:fbgen_get_cmap()
- *	fbgen.c:fbgen_switch()
- */
-
-static int riva_getcolreg (unsigned regno, unsigned *red, unsigned *green,
-			   unsigned *blue, unsigned *transp,
-			   struct fb_info *info)
-{
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
-
-	if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
-		return 1;
-
-	*red = rivainfo->palette[regno].red;
-	*green = rivainfo->palette[regno].green;
-	*blue = rivainfo->palette[regno].blue;
-	*transp = 0;
+	SEQout(rinfo, 0x01, tmp);
+	CRTCout(rinfo, 0x1a, vesa);
 
-	return 0;
+	DPRINTK("EXIT\n");
 }
 
 
-/**
- * riva_setcolreg
- * @regno:
- * @red:
- * @green:
- * @blue:
- * @transp:
- * @info: pointer to rivafb_info object containing info for current riva board
+
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Set a single color register. The values supplied have a 16 bit
- * magnitude.
- * Return != 0 for invalid regno.
+ * initialization helper functions
  *
- * CALLED FROM:
- * fbcmap.c:fb_set_cmap()
- *	fbgen.c:fbgen_get_cmap()
- *	fbgen.c:fbgen_install_cmap()
- *		fbgen.c:fbgen_set_var()
- *		fbgen.c:fbgen_switch()
- *		fbgen.c:fbgen_blank()
- *	fbgen.c:fbgen_blank()
- */
-
-static int riva_setcolreg (unsigned regno, unsigned red, unsigned green,
-			   unsigned blue, unsigned transp,
-			   struct fb_info *info)
-{
-	struct rivafb_info *rivainfo = (struct rivafb_info *) info;
-	struct display *p;
-	unsigned shift = 8;
-
-	DPRINTK ("ENTER\n");
-
-	assert (rivainfo != NULL);
-	assert (rivainfo->currcon_display != NULL);
-
-	p = rivainfo->currcon_display;
-
-	if (regno >= riva_get_cmap_len(&p->var))
-		return -EINVAL;
-
-	rivainfo->palette[regno].red = red;
-	rivainfo->palette[regno].green = green;
-	rivainfo->palette[regno].blue = blue;
-
-	if (p->var.grayscale) {
-		/* gray = 0.30*R + 0.59*G + 0.11*B */
-		red = green = blue =
-		    (red * 77 + green * 151 + blue * 28) >> 8;
-	}
-
-	switch (rivainfo->riva.Architecture) {
-	case 3:
-		shift = 10;
-		break;
-	case 4:
-	case 5:
-		shift = 8;
-		break;
-	}
-
-	switch (p->var.bits_per_pixel) {
-#ifdef FBCON_HAS_CFB8
-	case 8:
-		/* "transparent" stuff is completely ignored. */
-		riva_wclut (regno, red >> shift, green >> shift, blue >> shift);
-		break;
-#endif				/* FBCON_HAS_CFB8 */
-
-#ifdef FBCON_HAS_CFB16
-	case 16:
-		assert (regno < 16);
-#ifdef CONFIG_PREP
-		rivainfo->con_cmap.cfb16[regno] =
-		    ((red & 0xf800) >> 9) |
-		    ((green & 0xf800) >> 14) |
-		    ((green & 0xf800) << 2) | ((blue & 0xf800) >> 3);
-#else
-		rivainfo->con_cmap.cfb16[regno] =
-		    ((red & 0xf800) >> 1) |
-		    ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
-#endif
-		break;
-#endif				/* FBCON_HAS_CFB16 */
-
-#ifdef FBCON_HAS_CFB32
-	case 32:
-		assert (regno < 16);
-#ifdef CONFIG_PREP
-		rivainfo->con_cmap.cfb32[regno] =
-		    ((red & 0xff00)) |
-		    ((green & 0xff00) << 8) | ((blue & 0xff00) << 16);
-#else
-		rivainfo->con_cmap.cfb32[regno] =
-		    ((red & 0xff00) << 8) |
-		    ((green & 0xff00)) | ((blue & 0xff00) >> 8);
-#endif
-		break;
-#endif				/* FBCON_HAS_CFB32 */
+ * ------------------------------------------------------------------------- */
 
-	default:
-		/* do nothing */
-		break;
-	}
+/* kernel interface */
+static struct fb_ops riva_fb_ops = {
+	owner:		THIS_MODULE,
+	fb_get_fix:	rivafb_get_fix,
+	fb_get_var:	rivafb_get_var,
+	fb_set_var:	rivafb_set_var,
+	fb_get_cmap:	rivafb_get_cmap,
+	fb_set_cmap:	rivafb_set_cmap,
+	fb_pan_display:	rivafb_pan_display,
+	fb_ioctl:	rivafb_ioctl,
+	fb_rasterimg:	rivafb_rasterimg,
+};
 
+static int __devinit riva_init_disp_var(struct rivafb_info *rinfo)
+{
+#ifndef MODULE
+	if (mode_option)
+		fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option,
+			     NULL, 0, NULL, 8);
+#endif
 	return 0;
 }
 
+static int __devinit riva_init_disp(struct rivafb_info *rinfo)
+{
+	struct fb_info *info;
+	struct display *disp;
 
+	DPRINTK("ENTER\n");
 
-/*
- * riva_load_video_mode()
- *
- * calculate some timings and then send em off to riva_load_state()
- */
+	assert(rinfo != NULL);
 
-static void riva_load_video_mode (struct rivafb_info *rinfo,
-				  struct fb_var_screeninfo *video_mode)
-{
-	struct riva_regs newmode;
-	int bpp, width, hDisplaySize, hDisplay, hStart,
-	    hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
+	info = &rinfo->info;
+	disp = &rinfo->disp;
 
-	/* time to calculate */
+	disp->var = rivafb_default_var;
+	
+	if (noaccel)
+		disp->var.accel_flags &= ~FB_ACCELF_TEXT;
+	else
+		disp->var.accel_flags |= FB_ACCELF_TEXT;
+	
+	info->disp = disp;
 
-	bpp = video_mode->bits_per_pixel;
-	width = hDisplaySize = video_mode->xres;
-	hDisplay = (hDisplaySize / 8) - 1;
-	hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2;
-	hEnd = (hDisplaySize + video_mode->right_margin +
-		video_mode->hsync_len) / 8 - 1;
-	hTotal = (hDisplaySize + video_mode->right_margin +
-		  video_mode->hsync_len + video_mode->left_margin) / 8 - 1;
-	height = video_mode->yres;
-	vDisplay = video_mode->yres - 1;
-	vStart = video_mode->yres + video_mode->lower_margin - 1;
-	vEnd = video_mode->yres + video_mode->lower_margin +
-	    video_mode->vsync_len - 1;
-	vTotal = video_mode->yres + video_mode->lower_margin +
-	    video_mode->vsync_len + video_mode->upper_margin + 2;
-	dotClock = 1000000000 / video_mode->pixclock;
+	/* FIXME: assure that disp->cmap is completely filled out */
 
-	memcpy (&newmode, &reg_template, sizeof (struct riva_regs));
+	rinfo->currcon_display = disp;
 
-	newmode.crtc[0x0] = Set8Bits (hTotal - 4);
-	newmode.crtc[0x1] = Set8Bits (hDisplay);
-	newmode.crtc[0x2] = Set8Bits (hDisplay);
-	newmode.crtc[0x3] = SetBitField (hTotal, 4: 0, 4:0) | SetBit (7);
-	newmode.crtc[0x4] = Set8Bits (hStart);
-	newmode.crtc[0x5] = SetBitField (hTotal, 5: 5, 7:7)
-		| SetBitField (hEnd, 4: 0, 4:0);
-	newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
-	newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
-		| SetBitField (vDisplay, 8: 8, 1:1)
-		| SetBitField (vStart, 8: 8, 2:2)
-		| SetBitField (vDisplay, 8: 8, 3:3)
-		| SetBit (4)
-		| SetBitField (vTotal, 9: 9, 5:5)
-		| SetBitField (vDisplay, 9: 9, 6:6)
-		| SetBitField (vStart, 9: 9, 7:7);
-	newmode.crtc[0x9] = SetBitField (vDisplay, 9: 9, 5:5)
-		| SetBit (6);
-	newmode.crtc[0x10] = Set8Bits (vStart);
-	newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
-		| SetBit (5);
-	newmode.crtc[0x12] = Set8Bits (vDisplay);
-	newmode.crtc[0x13] = ((width / 8) * (bpp / 8)) & 0xFF;
-	newmode.crtc[0x15] = Set8Bits (vDisplay);
-	newmode.crtc[0x16] = Set8Bits (vTotal + 1);
+	if ((riva_init_disp_var(rinfo)) < 0) {
+		DPRINTK("EXIT, returning -1\n");
+		return -1;
+	}
 
-	newmode.ext.bpp = bpp;
-	newmode.ext.width = width;
-	newmode.ext.height = height;
+	riva_set_dispsw(rinfo, disp);
 
-	rinfo->riva.CalcStateExt (&rinfo->riva, &newmode.ext, bpp, width,
-				  hDisplaySize, hDisplay, hStart, hEnd,
-				  hTotal, height, vDisplay, vStart, vEnd,
-				  vTotal, dotClock);
+	DPRINTK("EXIT, returning 0\n");
+	return 0;
 
-	rinfo->initial_state = newmode;
-	riva_load_state (rinfo, &newmode);
 }
 
+static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
+{
+	struct fb_info *info;
 
-/* ------------------------------------------------------------------------- */
+	assert(rinfo != NULL);
 
+	info = &rinfo->info;
 
-    /*
-     *  Modularization
-     */
+	strcpy(info->modename, rinfo->drvr_name);
+	info->node = -1;
+	info->flags = FBINFO_FLAG_DEFAULT;
+	info->fbops = &riva_fb_ops;
 
-static struct pci_driver rivafb_driver = {
-	name:		"rivafb",
-	id_table:	rivafb_pci_tbl,
-	probe:		rivafb_init_one,
-	remove:		rivafb_remove_one,
-};
+	/* FIXME: set monspecs to what??? */
 
+	info->display_fg = NULL;
+	strncpy(info->fontname, fontname, sizeof(info->fontname));
+	info->fontname[sizeof(info->fontname) - 1] = 0;
 
-int __init rivafb_init (void)
-{
-	return pci_module_init (&rivafb_driver);
-}
+	info->changevar = NULL;
+	info->switch_con = rivafb_switch;
+	info->updatevar = rivafb_updatevar;
+	info->blank = rivafb_blank;
 
+	if (riva_init_disp(rinfo) < 0)	/* must be done last */
+		return -1;
 
-static void __exit rivafb_exit (void)
-{
-	pci_unregister_driver (&rivafb_driver);
+	return 0;
 }
 
 
-#ifdef MODULE
-module_init(rivafb_init);
-#endif				/* MODULE */
-module_exit(rivafb_exit);
-
-MODULE_AUTHOR("Ani Joshi, maintainer");
-MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");
 
+/* ------------------------------------------------------------------------- *
+ *
+ * PCI bus
+ *
+ * ------------------------------------------------------------------------- */
 
-/* from GGI */
-static void riva_save_state (struct rivafb_info *rinfo, struct riva_regs *regs)
+static int __devinit rivafb_init_one(struct pci_dev *pd,
+				     const struct pci_device_id *ent)
 {
-	int i;
+	struct rivafb_info *rinfo;
+	struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
 
-	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
-	outb (0x57, rinfo->riva.LockUnlockIO + 1);
+	assert(pd != NULL);
+	assert(rci != NULL);
 
-	rinfo->riva.UnloadStateExt (&rinfo->riva, &regs->ext);
+	rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL);
+	if (!rinfo)
+		goto err_out;
 
-	regs->misc_output = io_in8 (0x3CC);
+	memset(rinfo, 0, sizeof(struct rivafb_info));
 
-	for (i = 0; i < NUM_CRT_REGS; i++) {
-		io_out8 (i, 0x3D4);
-		regs->crtc[i] = io_in8 (0x3D5);
-	}
+	rinfo->drvr_name = rci->name;
+	rinfo->riva.Architecture = rci->arch_rev;
 
-	for (i = 0; i < NUM_ATC_REGS; i++) {
-		io_out8 (i, 0x3C0);
-		regs->attr[i] = io_in8 (0x3C1);
+	rinfo->pd = pd;
+	rinfo->base0_region_size = pci_resource_len(pd, 0);
+	rinfo->base1_region_size = pci_resource_len(pd, 1);
+
+	assert(rinfo->base0_region_size >= 0x00800000);	/* from GGI */
+	assert(rinfo->base1_region_size >= 0x01000000);	/* from GGI */
+
+	rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0);
+	rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1);
+
+	if (!request_mem_region(rinfo->ctrl_base_phys,
+				rinfo->base0_region_size, "rivafb")) {
+		printk(KERN_ERR PFX "cannot reserve MMIO region\n");
+		goto err_out_kfree;
 	}
 
-	for (i = 0; i < NUM_GRC_REGS; i++) {
-		io_out8 (i, 0x3CE);
-		regs->gra[i] = io_in8 (0x3CF);
+	if (!request_mem_region(rinfo->fb_base_phys,
+				rinfo->base1_region_size, "rivafb")) {
+		printk(KERN_ERR PFX "cannot reserve FB region\n");
+		goto err_out_free_base0;
+	}
+	
+	rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
+				   rinfo->base0_region_size);
+	if (!rinfo->ctrl_base) {
+		printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
+		goto err_out_free_base1;
+	}
+	
+	rinfo->fb_base = ioremap(rinfo->fb_base_phys,
+				 rinfo->base1_region_size);
+	if (!rinfo->fb_base) {
+		printk(KERN_ERR PFX "cannot ioremap FB base\n");
+		goto err_out_iounmap_ctrl;
+	}
+	
+#ifdef CONFIG_MTRR
+	if (!nomtrr) {
+		rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys,
+					    rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1);
+		if (rinfo->mtrr.vram < 0) {
+			printk(KERN_ERR PFX "unable to setup MTRR\n");
+		} else {
+			rinfo->mtrr.vram_valid = 1;
+			/* let there be speed */
+			printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
+		}
 	}
+#endif /* CONFIG_MTRR */
 
+	rinfo->riva.EnableIRQ = 0;
+	rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
+	rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
+	rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000);
+	rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000);
+	rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000);
+	rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000);
+	rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000);
+	rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000);
+
+	rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000);
+	rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000);
+	rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000);
 
-	for (i = 0; i < NUM_SEQ_REGS; i++) {
-		io_out8 (i, 0x3C4);
-		regs->seq[i] = io_in8 (0x3C5);
+	rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0;
+
+	switch (rinfo->riva.Architecture) {
+	case NV_ARCH_03:
+		rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000);
+		break;
+	case NV_ARCH_04:
+	case NV_ARCH_10:
+		rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
+		rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
+		break;
 	}
-}
 
+	RivaGetConfig(&rinfo->riva);
 
-/* from GGI */
-static
-void riva_load_state (struct rivafb_info *rinfo, struct riva_regs *regs)
-{
-	int i;
-	RIVA_HW_STATE *state = &regs->ext;
+	/* back to normal */
 
-	io_out8 (0x11, 0x3D4);
-	io_out8 (0x00, 0x3D5);
+	assert(rinfo->pd != NULL);
 
-	outb (rinfo->riva.LockUnlockIndex, rinfo->riva.LockUnlockIO);
-	outb (0x57, rinfo->riva.LockUnlockIO + 1);
+	/* unlock io */
+	CRTCout(rinfo, 0x11, 0xFF);	/* vgaHWunlock() + riva unlock (0x7F) */
+	rinfo->riva.LockUnlock(&rinfo->riva, 0);
 
-	rinfo->riva.LoadStateExt (&rinfo->riva, state);
+	riva_save_state(rinfo, &rinfo->initial_state);
 
-	io_out8 (regs->misc_output, 0x3C2);
+	rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;
+	rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
 
-	for (i = 0; i < NUM_CRT_REGS; i++) {
-		if (i < 0x19) {
-			io_out8 (i, 0x3D4);
-			io_out8 (regs->crtc[i], 0x3D5);
-		} else {
-			switch (i) {
-			case 0x19:
-			case 0x20:
-			case 0x21:
-			case 0x22:
-			case 0x23:
-			case 0x24:
-			case 0x25:
-			case 0x26:
-			case 0x27:
-			case 0x28:
-			case 0x29:
-			case 0x2a:
-			case 0x2b:
-			case 0x2c:
-			case 0x2d:
-			case 0x2e:
-			case 0x2f:
-			case 0x30:
-			case 0x31:
-			case 0x32:
-			case 0x33:
-			case 0x34:
-			case 0x35:
-			case 0x36:
-			case 0x37:
-			case 0x38:
-			case 0x39:
-			case 0x3a:
-			case 0x3b:
-			case 0x3c:
-			case 0x3d:
-			case 0x3e:
-			case 0x3f:
-			case 0x40:
-				break;
-			default:
-				io_out8 (i, 0x3D4);
-				io_out8 (regs->crtc[i], 0x3D5);
-			}
-		}
-	}
+	if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo);
 
-	for (i = 0; i < NUM_ATC_REGS; i++) {
-		io_out8 (i, 0x3C0);
-		io_out8 (regs->attr[i], 0x3C0);
+	if (riva_set_fbinfo(rinfo) < 0) {
+		printk(KERN_ERR PFX "error setting initial video mode\n");
+		goto err_out_cursor;
 	}
 
-	for (i = 0; i < NUM_GRC_REGS; i++) {
-		io_out8 (i, 0x3CE);
-		io_out8 (regs->gra[i], 0x3CF);
+	if (register_framebuffer((struct fb_info *)rinfo) < 0) {
+		printk(KERN_ERR PFX
+			"error registering riva framebuffer\n");
+		goto err_out_load_state;
 	}
 
-	for (i = 0; i < NUM_SEQ_REGS; i++) {
-		io_out8 (i, 0x3C4);
-		io_out8 (regs->seq[i], 0x3C5);
-	}
+	riva_boards = riva_board_list_add(riva_boards, rinfo);
+
+	pci_set_drvdata(pd, rinfo);
+
+	printk(KERN_INFO PFX
+		"PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
+		rinfo->riva.Architecture,
+		RIVAFB_VERSION,
+		rinfo->drvr_name,
+		rinfo->ram_amount / (1024 * 1024),
+		rinfo->fb_base_phys);
+
+	return 0;
+
+err_out_load_state:
+	riva_load_state(rinfo, &rinfo->initial_state);
+err_out_cursor:
+	rivafb_exit_cursor(rinfo);
+/* err_out_iounmap_fb: */
+	iounmap(rinfo->fb_base);
+err_out_iounmap_ctrl:
+	iounmap(rinfo->ctrl_base);
+err_out_free_base1:
+	release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);
+err_out_free_base0:
+	release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size);
+err_out_kfree:
+	kfree(rinfo);
+err_out:
+	return -ENODEV;
 }
 
+static void __devexit rivafb_remove_one(struct pci_dev *pd)
+{
+	struct rivafb_info *board = pci_get_drvdata(pd);
+	
+	if (!board)
+		return;
+
+	riva_boards = riva_board_list_del(riva_boards, board);
 
+	riva_load_state(board, &board->initial_state);
 
+	unregister_framebuffer((struct fb_info *)board);
 
-/**
- * riva_board_list_add
- * @board_list: Root node of list of boards
- * @new_node: New node to be added
+	rivafb_exit_cursor(board);
+
+#ifdef CONFIG_MTRR
+	if (board->mtrr.vram_valid)
+		mtrr_del(board->mtrr.vram, board->fb_base_phys,
+			 board->base1_region_size);
+#endif /* CONFIG_MTRR */
+
+	iounmap(board->ctrl_base);
+	iounmap(board->fb_base);
+
+	release_mem_region(board->ctrl_base_phys,
+			   board->base0_region_size);
+	release_mem_region(board->fb_base_phys,
+			   board->base1_region_size);
+
+	kfree(board);
+
+	pci_set_drvdata(pd, NULL);
+}
+
+
+
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Adds @new_node to the list referenced by @board_list
+ * initialization
  *
- * RETURNS:
- * New root node
- */
-static
-struct rivafb_info *riva_board_list_add (struct rivafb_info *board_list,
-					 struct rivafb_info *new_node)
+ * ------------------------------------------------------------------------- */
+
+#ifndef MODULE
+int __init rivafb_setup(char *options)
 {
-	struct rivafb_info *i_p = board_list;
+	char *this_opt;
 
-	new_node->next = NULL;
+	if (!options || !*options)
+		return 0;
 
-	if (board_list == NULL)
-		return new_node;
+	for (this_opt = strtok(options, ","); this_opt;
+	     this_opt = strtok(NULL, ",")) {
+		if (!strncmp(this_opt, "font:", 5)) {
+			char *p;
+			int i;
 
-	while (i_p->next != NULL)
-		i_p = i_p->next;
-	i_p->next = new_node;
+			p = this_opt + 5;
+			for (i = 0; i < sizeof(fontname) - 1; i++)
+				if (!*p || *p == ' ' || *p == ',')
+					break;
+			memcpy(fontname, this_opt + 5, i);
+			fontname[i] = 0;
 
-	return board_list;
+		} else if (!strncmp(this_opt, "noblink", 7)) {
+			noblink = 1;
+		} else if (!strncmp(this_opt, "noaccel", 7)) {
+			noaccel = 1;
+		} else if (!strncmp(this_opt, "nomove", 6)) {
+			nomove = 1;
+#ifdef CONFIG_MTRR
+		} else if (!strncmp(this_opt, "nomtrr", 6)) {
+			nomtrr = 1;
+#endif
+		} else if (!strncmp(this_opt, "nohwcursor", 10)) {
+			nohwcursor = 1;
+		} else
+			mode_option = this_opt;
+	}
+	return 0;
 }
+#endif /* !MODULE */
+
+static struct pci_driver rivafb_driver = {
+	name:		"rivafb",
+	id_table:	rivafb_pci_tbl,
+	probe:		rivafb_init_one,
+	remove:		rivafb_remove_one,
+};
 
 
 
-/**
- * riva_board_list_del
- * @board_list: Root node of list of boards
- * @del_node: Node to be removed
+/* ------------------------------------------------------------------------- *
  *
- * DESCRIPTION:
- * Removes @del_node from the list referenced by @board_list
+ * modularization
  *
- * RETURNS:
- * New root node
- */
-static
-struct rivafb_info *riva_board_list_del (struct rivafb_info *board_list,
-					 struct rivafb_info *del_node)
-{
-	struct rivafb_info *i_p = board_list;
+ * ------------------------------------------------------------------------- */
 
-	if (board_list == del_node)
-		return del_node->next;
+int __init rivafb_init(void)
+{
+	int err;
+#ifdef MODULE
+	if (font) strncpy(fontname, font, sizeof(fontname)-1);
+#endif
+	err = pci_module_init(&rivafb_driver);
+	if (err)
+		return err;
+	return 0;
+}
 
-	while (i_p->next != del_node)
-		i_p = i_p->next;
-	i_p->next = del_node->next;
 
-	return board_list;
+#ifdef MODULE
+static void __exit rivafb_exit(void)
+{
+	pci_unregister_driver(&rivafb_driver);
 }
 
+module_init(rivafb_init);
+module_exit(rivafb_exit);
+
+MODULE_PARM(font, "s");
+MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");
+MODULE_PARM(nomove, "i");
+MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)");
+MODULE_PARM(nohwcursor, "i");
+MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)");
+MODULE_PARM(noblink, "i");
+MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)");
+#ifdef CONFIG_MTRR
+MODULE_PARM(nomtrr, "i");
+MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+#endif
+#endif /* MODULE */
+
+MODULE_AUTHOR("Ani Joshi, maintainer");
+MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2");
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/riva_hw.c linux/drivers/video/riva/riva_hw.c
--- v2.4.1/linux/drivers/video/riva/riva_hw.c	Wed Jul  5 10:56:12 2000
+++ linux/drivers/video/riva/riva_hw.c	Tue Feb 13 13:15:05 2001
@@ -1,6 +1,6 @@
  /***************************************************************************\
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
 |*     international laws.  Users and possessors of this source code are     *|
@@ -11,7 +11,7 @@
 |*     tion and  internal comments to the code,  notices to the end user     *|
 |*     as follows:                                                           *|
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
@@ -36,52 +36,84 @@
 |*     those rights set forth herein.                                        *|
 |*                                                                           *|
  \***************************************************************************/
-/* 
- * GPL licensing note -- nVidia is allowing a liberal interpretation of 
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
  * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived 
- * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99 
  */
 
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/riva_hw.c,v 1.1.2.3 1998/12/26 00:12:39 dawes Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.c,v 1.8 2000/02/08 17:19:11 dawes Exp $ */
 
-#include <linux/kernel.h>
-#include <asm/io.h>
 #include "riva_hw.h"
 #include "riva_tbl.h"
-
-
 /*
  * This file is an OS-agnostic file used to make RIVA 128 and RIVA TNT
  * operate identically (except TNT has more memory and better 3D quality.
  */
-
 static int nv3Busy
 (
     RIVA_HW_INST *chip
 )
 {
-    return ((!(chip->PFIFO[0x00001214/4] & 0x10)) | (chip->PGRAPH[0x000006B0/4] & 0x01));
+    return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x000006B0/4] & 0x01));
 }
 static int nv4Busy
 (
     RIVA_HW_INST *chip
 )
 {
-    return ((!(chip->PFIFO[0x00001214/4] & 0x10)) | (chip->PGRAPH[0x00000700/4] & 0x01));
+    return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
 }
+static int nv10Busy
+(
+    RIVA_HW_INST *chip
+)
+{
+    return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
+}
+static void nv3LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           LockUnlock
+)
+{
+    VGA_WR08(chip->PVIO, 0x3C4, 0x06);
+    VGA_WR08(chip->PVIO, 0x3C5, LockUnlock ? 0x99 : 0x57);
+}
+static void nv4LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           LockUnlock
+)
+{
+    VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
+    VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
+}
+static void nv10LockUnlock
+(
+    RIVA_HW_INST *chip,
+    int           LockUnlock
+)
+{
+    VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
+    VGA_WR08(chip->PCIO, 0x3D5, LockUnlock ? 0x99 : 0x57);
+}
+
 static int ShowHideCursor
 (
     RIVA_HW_INST *chip,
     int           ShowHide
 )
 {
-    int xcurrent;
-    xcurrent                     =  chip->CurrentState->cursor1;
-    chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) | (ShowHide & 0x01);
-    outb(0x31, 0x3D4);
-    outb(chip->CurrentState->cursor1, 0x3D5);
-    return (xcurrent & 0x01);
+    int current;
+    current                     =  chip->CurrentState->cursor1;
+    chip->CurrentState->cursor1 = (chip->CurrentState->cursor1 & 0xFE) |
+	                          (ShowHide & 0x01);
+    VGA_WR08(chip->PCIO, 0x3D4, 0x31);
+    VGA_WR08(chip->PCIO, 0x3D5, chip->CurrentState->cursor1);
+    return (current & 0x01);
 }
 
 /****************************************************************************\
@@ -171,6 +203,27 @@
   char mem_aligned;
   char enable_mp;
 } nv4_sim_state;
+typedef struct {
+  int graphics_lwm;
+  int video_lwm;
+  int graphics_burst_size;
+  int video_burst_size;
+  int valid;
+} nv10_fifo_info;
+typedef struct {
+  int pclk_khz;
+  int mclk_khz;
+  int nvclk_khz;
+  char mem_page_miss;
+  char mem_latency;
+  int memory_type;
+  int memory_width;
+  char enable_video;
+  char gr_during_vid;
+  char pix_bpp;
+  char mem_aligned;
+  char enable_mp;
+} nv10_sim_state;
 static int nv3_iterate(nv3_fifo_info *res_info, nv3_sim_state * state, nv3_arb_info *ainfo)
 {
     int iter = 0;
@@ -215,7 +268,7 @@
             if (ainfo->wcglwm > glwm) ainfo->wcglwm = glwm ;
             if (ainfo->wcgocc > ainfo->gocc) ainfo->wcgocc = ainfo->gocc;
             ns = 1000000 * (ainfo->gburst_size/(state->memory_width/8))/state->mclk_khz;
-            gfsize = ns *ainfo->gdrain_rate/1000000;
+            gfsize = (ns * (long) ainfo->gdrain_rate)/1000000;
             gfsize = ainfo->wcglwm - ainfo->gburst_size + gfsize;
         }
         mfsize = 0;
@@ -312,7 +365,7 @@
         }
         ns = 1000000*ainfo->gburst_size/(state->memory_width/8)/state->mclk_khz;
         tmp = ns * ainfo->gdrain_rate/1000000;
-        if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7)    - tmp > max_gfsize)
+        if (ABS(ainfo->gburst_size) + ((ABS(ainfo->wcglwm) + 16 ) & ~0x7) - tmp > max_gfsize)
         {
             ainfo->converged = 0;
             return (1);
@@ -468,32 +521,27 @@
     int done, g,v, p;
     
     done = 0;
-    if (state->gr_during_vid && ainfo->vid_en)
-        ainfo->priority = MPORT;
-    else
-        ainfo->priority = ainfo->gdrain_rate < ainfo->vdrain_rate ? VIDEO: GRAPHICS;
-    for (p=0; p < 2 && done != 1; p++)
+    for (p=0; p < 2; p++)
     {
-        for (g=128 ; (g > 32) && (done != 1); g= g>> 1)
+        for (g=128 ; g > 32; g= g>> 1)
         {
-            for (v=128; (v >=32) && (done !=1); v = v>> 1)
+            for (v=128; v >=32; v = v>> 1)
             {
                 ainfo->priority = p;
                 ainfo->gburst_size = g;     
                 ainfo->vburst_size = v;
                 done = nv3_arb(res_info, state,ainfo);
-                if (g==128)
-                {
+                if (done && (g==128))
                     if ((res_info->graphics_lwm + g) > 256)
                         done = 0;
-                }
+                if (done)
+                    goto Done;
             }
         }
     }
-    if (!done)
-        return (0);
-    else
-        return (1);
+
+ Done:
+    return done;
 }
 static void nv3CalcArbitration 
 (
@@ -509,7 +557,7 @@
     ainfo.vid_en = state->enable_video;
     ainfo.vid_only_once = 0;
     ainfo.gr_only_once = 0;
-    ainfo.gdrain_rate = (int) state->pclk_khz * state -> pix_bpp/8;
+    ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
     ainfo.vdrain_rate = (int) state->pclk_khz * 2;
     if (state->video_scale != 0)
         ainfo.vdrain_rate = ainfo.vdrain_rate/state->video_scale;
@@ -527,7 +575,7 @@
         ainfo.vid_en = 1;
         ainfo.vid_only_once = 1;
         ainfo.gr_en = 1;
-        ainfo.gdrain_rate = (int) state->pclk_khz * state -> pix_bpp/8;
+        ainfo.gdrain_rate = (int) state->pclk_khz * (state->pix_bpp/8);
         ainfo.vdrain_rate = 0;
         res_gr = nv3_get_param(res_info, state,  &ainfo);
         res_gr = ainfo.converged;
@@ -543,7 +591,7 @@
         res_info->valid = ainfo.converged;
     }
 }
-void nv3UpdateArbitrationSettings
+static void nv3UpdateArbitrationSettings
 (
     unsigned      VClk, 
     unsigned      pixelDepth, 
@@ -565,9 +613,10 @@
     sim_data.video_scale    = 1;
     sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
     sim_data.memory_width   = 128;
-    sim_data.mem_latency    = 11;
+
+    sim_data.mem_latency    = 9;
     sim_data.mem_aligned    = 1;
-    sim_data.mem_page_miss  = 9;
+    sim_data.mem_page_miss  = 11;
     sim_data.gr_during_vid  = 0;
     sim_data.pclk_khz       = VClk;
     sim_data.mclk_khz       = MClk;
@@ -582,7 +631,7 @@
     else
     {
         *lwm   = 0x24;
-        *burst = 0x02;
+        *burst = 0x2;
     }
 }
 static void nv4CalcArbitration 
@@ -592,7 +641,7 @@
 )
 {
     int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
-    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs=0;
+    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
     int found, mclk_extra, mclk_loop, cbs, m1, p1;
     int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
     int us_m, us_n, us_p, video_drain_rate, crtc_drain_rate;
@@ -636,6 +685,7 @@
     nvclks += 0;
     pclks += 0;
     found = 0;
+    vbs = 0;
     while (found != 1)
     {
         fifo->valid = 1;
@@ -768,6 +818,268 @@
         *lwm   = fifo_data.graphics_lwm >> 3;
     }
 }
+static void nv10CalcArbitration 
+(
+    nv10_fifo_info *fifo,
+    nv10_sim_state *arb
+)
+{
+    int data, pagemiss, cas,width, video_enable, color_key_enable, bpp, align;
+    int nvclks, mclks, pclks, vpagemiss, crtpagemiss, vbs;
+    int nvclk_fill, us_extra;
+    int found, mclk_extra, mclk_loop, cbs, m1;
+    int mclk_freq, pclk_freq, nvclk_freq, mp_enable;
+    int us_m, us_m_min, us_n, us_p, video_drain_rate, crtc_drain_rate;
+    int vus_m, vus_n, vus_p;
+    int vpm_us, us_video, vlwm, cpm_us, us_crt,clwm;
+    int clwm_rnd_down;
+    int craw, m2us, us_pipe, us_pipe_min, vus_pipe, p1clk, p2;
+    int pclks_2_top_fifo, min_mclk_extra;
+    int us_min_mclk_extra;
+
+    fifo->valid = 1;
+    pclk_freq = arb->pclk_khz; /* freq in KHz */
+    mclk_freq = arb->mclk_khz;
+    nvclk_freq = arb->nvclk_khz;
+    pagemiss = arb->mem_page_miss;
+    cas = arb->mem_latency;
+    width = arb->memory_width/64;
+    video_enable = arb->enable_video;
+    color_key_enable = arb->gr_during_vid;
+    bpp = arb->pix_bpp;
+    align = arb->mem_aligned;
+    mp_enable = arb->enable_mp;
+    clwm = 0;
+    vlwm = 1024;
+
+    cbs = 512;
+    vbs = 512;
+
+    pclks = 4; /* lwm detect. */
+
+    nvclks = 3; /* lwm -> sync. */
+    nvclks += 2; /* fbi bus cycles (1 req + 1 busy) */
+
+    mclks  = 1;   /* 2 edge sync.  may be very close to edge so just put one. */
+
+    mclks += 1;   /* arb_hp_req */
+    mclks += 5;   /* ap_hp_req   tiling pipeline */
+
+    mclks += 2;    /* tc_req     latency fifo */
+    mclks += 2;    /* fb_cas_n_  memory request to fbio block */
+    mclks += 7;    /* sm_d_rdv   data returned from fbio block */
+
+    /* fb.rd.d.Put_gc   need to accumulate 256 bits for read */
+    if (arb->memory_type == 0)
+      if (arb->memory_width == 64) /* 64 bit bus */
+        mclks += 4;
+      else
+        mclks += 2;
+    else
+      if (arb->memory_width == 64) /* 64 bit bus */
+        mclks += 2;
+      else
+        mclks += 1;
+
+    if ((!video_enable) && (arb->memory_width == 128))
+    {  
+      mclk_extra = (bpp == 32) ? 31 : 42; /* Margin of error */
+      min_mclk_extra = 17;
+    }
+    else
+    {
+      mclk_extra = (bpp == 32) ? 8 : 4; /* Margin of error */
+      /* mclk_extra = 4; */ /* Margin of error */
+      min_mclk_extra = 18;
+    }
+
+    nvclks += 1; /* 2 edge sync.  may be very close to edge so just put one. */
+    nvclks += 1; /* fbi_d_rdv_n */
+    nvclks += 1; /* Fbi_d_rdata */
+    nvclks += 1; /* crtfifo load */
+
+    if(mp_enable)
+      mclks+=4; /* Mp can get in with a burst of 8. */
+    /* Extra clocks determined by heuristics */
+
+    nvclks += 0;
+    pclks += 0;
+    found = 0;
+    while(found != 1) {
+      fifo->valid = 1;
+      found = 1;
+      mclk_loop = mclks+mclk_extra;
+      us_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+      us_m_min = mclks * 1000*1000 / mclk_freq; /* Minimum Mclk latency in us */
+      us_min_mclk_extra = min_mclk_extra *1000*1000 / mclk_freq;
+      us_n = nvclks*1000*1000 / nvclk_freq;/* nvclk latency in us */
+      us_p = pclks*1000*1000 / pclk_freq;/* nvclk latency in us */
+      us_pipe = us_m + us_n + us_p;
+      us_pipe_min = us_m_min + us_n + us_p;
+      us_extra = 0;
+
+      vus_m = mclk_loop *1000*1000 / mclk_freq; /* Mclk latency in us */
+      vus_n = (4)*1000*1000 / nvclk_freq;/* nvclk latency in us */
+      vus_p = 0*1000*1000 / pclk_freq;/* pclk latency in us */
+      vus_pipe = vus_m + vus_n + vus_p;
+
+      if(video_enable) {
+        video_drain_rate = pclk_freq * 4; /* MB/s */
+        crtc_drain_rate = pclk_freq * bpp/8; /* MB/s */
+
+        vpagemiss = 1; /* self generating page miss */
+        vpagemiss += 1; /* One higher priority before */
+
+        crtpagemiss = 2; /* self generating page miss */
+        if(mp_enable)
+            crtpagemiss += 1; /* if MA0 conflict */
+
+        vpm_us = (vpagemiss * pagemiss)*1000*1000/mclk_freq;
+
+        us_video = vpm_us + vus_m; /* Video has separate read return path */
+
+        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+        us_crt =
+          us_video  /* Wait for video */
+          +cpm_us /* CRT Page miss */
+          +us_m + us_n +us_p /* other latency */
+          ;
+
+        clwm = us_crt * crtc_drain_rate/(1000*1000);
+        clwm++; /* fixed point <= float_point - 1.  Fixes that */
+      } else {
+        crtc_drain_rate = pclk_freq * bpp/8; /* bpp * pclk/8 */
+
+        crtpagemiss = 1; /* self generating page miss */
+        crtpagemiss += 1; /* MA0 page miss */
+        if(mp_enable)
+            crtpagemiss += 1; /* if MA0 conflict */
+        cpm_us = crtpagemiss  * pagemiss *1000*1000/ mclk_freq;
+        us_crt =  cpm_us + us_m + us_n + us_p ;
+        clwm = us_crt * crtc_drain_rate/(1000*1000);
+        clwm++; /* fixed point <= float_point - 1.  Fixes that */
+
+  /*
+          //
+          // Another concern, only for high pclks so don't do this
+          // with video:
+          // What happens if the latency to fetch the cbs is so large that
+          // fifo empties.  In that case we need to have an alternate clwm value
+          // based off the total burst fetch
+          //
+          us_crt = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+          us_crt = us_crt + us_m + us_n + us_p + (4 * 1000 * 1000)/mclk_freq;
+          clwm_mt = us_crt * crtc_drain_rate/(1000*1000);
+          clwm_mt ++;
+          if(clwm_mt > clwm)
+              clwm = clwm_mt;
+  */
+          /* Finally, a heuristic check when width == 64 bits */
+          if(width == 1){
+              nvclk_fill = nvclk_freq * 8;
+              if(crtc_drain_rate * 100 >= nvclk_fill * 102)
+                      clwm = 0xfff; /*Large number to fail */
+
+              else if(crtc_drain_rate * 100  >= nvclk_fill * 98) {
+                  clwm = 1024;
+                  cbs = 512;
+                  us_extra = (cbs * 1000 * 1000)/ (8*width)/mclk_freq ;
+              }
+          }
+      }
+
+
+      /*
+        Overfill check:
+
+        */
+
+      clwm_rnd_down = ((int)clwm/8)*8;
+      if (clwm_rnd_down < clwm)
+          clwm += 8;
+
+      m1 = clwm + cbs -  1024; /* Amount of overfill */
+      m2us = us_pipe_min + us_min_mclk_extra;
+      pclks_2_top_fifo = (1024-clwm)/(8*width);
+
+      /* pclk cycles to drain */
+      p1clk = m2us * pclk_freq/(1000*1000); 
+      p2 = p1clk * bpp / 8; /* bytes drained. */
+
+      if((p2 < m1) && (m1 > 0)) {
+          fifo->valid = 0;
+          found = 0;
+          if(min_mclk_extra == 0)   {
+            if(cbs <= 32) {
+              found = 1; /* Can't adjust anymore! */
+            } else {
+              cbs = cbs/2;  /* reduce the burst size */
+            }
+          } else {
+            min_mclk_extra--;
+          }
+      } else {
+        if (clwm > 1023){ /* Have some margin */
+          fifo->valid = 0;
+          found = 0;
+          if(min_mclk_extra == 0)   
+              found = 1; /* Can't adjust anymore! */
+          else 
+              min_mclk_extra--;
+        }
+      }
+      craw = clwm;
+
+      if(clwm < (1024-cbs+8)) clwm = 1024-cbs+8;
+      data = (int)(clwm);
+      /*  printf("CRT LWM: %f bytes, prog: 0x%x, bs: 256\n", clwm, data ); */
+      fifo->graphics_lwm = data;   fifo->graphics_burst_size = cbs;
+
+      /*  printf("VID LWM: %f bytes, prog: 0x%x, bs: %d\n, ", vlwm, data, vbs ); */
+      fifo->video_lwm = 1024;  fifo->video_burst_size = 512;
+    }
+}
+static void nv10UpdateArbitrationSettings
+(
+    unsigned      VClk, 
+    unsigned      pixelDepth, 
+    unsigned     *burst,
+    unsigned     *lwm,
+    RIVA_HW_INST *chip
+)
+{
+    nv10_fifo_info fifo_data;
+    nv10_sim_state sim_data;
+    unsigned int M, N, P, pll, MClk, NVClk, cfg1;
+
+    pll = chip->PRAMDAC[0x00000504/4];
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    MClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    pll = chip->PRAMDAC[0x00000500/4];
+    M = (pll >> 0)  & 0xFF; N = (pll >> 8)  & 0xFF; P = (pll >> 16) & 0x0F;
+    NVClk  = (N * chip->CrystalFreqKHz / M) >> P;
+    cfg1 = chip->PFB[0x00000204/4];
+    sim_data.pix_bpp        = (char)pixelDepth;
+    sim_data.enable_video   = 0;
+    sim_data.enable_mp      = 0;
+    sim_data.memory_type    = (chip->PFB[0x00000200/4] & 0x01) ? 1 : 0;
+    sim_data.memory_width   = (chip->PEXTDEV[0x00000000/4] & 0x10) ? 128 : 64;
+    sim_data.mem_latency    = (char)cfg1 & 0x0F;
+    sim_data.mem_aligned    = 1;
+    sim_data.mem_page_miss  = (char)(((cfg1 >> 4) &0x0F) + ((cfg1 >> 31) & 0x01));
+    sim_data.gr_during_vid  = 0;
+    sim_data.pclk_khz       = VClk;
+    sim_data.mclk_khz       = MClk;
+    sim_data.nvclk_khz      = NVClk;
+    nv10CalcArbitration(&fifo_data, &sim_data);
+    if (fifo_data.valid)
+    {
+        int  b = fifo_data.graphics_burst_size >> 4;
+        *burst = 0;
+        while (b >>= 1) (*burst)++;
+        *lwm   = fifo_data.graphics_lwm >> 3;
+    }
+}
 
 /****************************************************************************\
 *                                                                            *
@@ -781,6 +1093,7 @@
 static int CalcVClock
 (
     int           clockIn,
+    int           double_scan,
     int          *clockOut,
     int          *mOut,
     int          *nOut,
@@ -794,18 +1107,23 @@
     unsigned M, N, P;
     
     DeltaOld = 0xFFFFFFFF;
+
     VClk     = (unsigned)clockIn;
+    if (double_scan)
+        VClk *= 2;
+    
     if (chip->CrystalFreqKHz == 14318)
     {
         lowM  = 8;
-        highM = 14 - (chip->Architecture == 3);
+        highM = 14 - (chip->Architecture == NV_ARCH_03);
     }
     else
     {
         lowM  = 7;
-        highM = 13 - (chip->Architecture == 3);
+        highM = 13 - (chip->Architecture == NV_ARCH_03);
     }                      
-    highP = 4 - (chip->Architecture == 3);
+
+    highP = 4 - (chip->Architecture == NV_ARCH_03);
     for (P = 0; P <= highP; P ++)
     {
         Freq = VClk << P;
@@ -866,10 +1184,12 @@
      * Extended RIVA registers.
      */
     pixelDepth = (bpp + 1)/8;
-    CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
+    CalcVClock(dotClock, hDisplaySize < 512,  /* double scan? */
+               &VClk, &m, &n, &p, chip);
+
     switch (chip->Architecture)
     {
-	    case 3:
+        case NV_ARCH_03:
             nv3UpdateArbitrationSettings(VClk, 
                                          pixelDepth * 8, 
                                         &(state->arbitration0),
@@ -882,11 +1202,10 @@
             state->config   = ((width + 31)/32)
                             | (((pixelDepth > 2) ? 3 : pixelDepth) << 8)
                             | 0x1000;
-            state->general  = 0x00000100;
+            state->general  = 0x00100100;
             state->repaint1 = hDisplaySize < 1280 ? 0x06 : 0x02;
             break;
-	    case 4:
-	    case 5:
+        case NV_ARCH_04:
             nv4UpdateArbitrationSettings(VClk, 
                                          pixelDepth * 8, 
                                         &(state->arbitration0),
@@ -900,6 +1219,20 @@
             state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
             state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
             break;
+        case NV_ARCH_10:
+            nv10UpdateArbitrationSettings(VClk, 
+                                          pixelDepth * 8, 
+                                         &(state->arbitration0),
+                                         &(state->arbitration1),
+                                          chip);
+            state->cursor0  = 0x00;
+            state->cursor1  = 0xFC;
+            state->cursor2  = 0x00000000;
+            state->pllsel   = 0x10000700;
+            state->config   = chip->PFB[0x00000200/4];
+            state->general  = bpp == 16 ? 0x00101100 : 0x00100100;
+            state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
+            break;
     }
     state->vpll     = (p << 16) | (n << 8) | m;
     state->screen   = ((hTotal   & 0x040) >> 2)
@@ -909,7 +1242,7 @@
                     | ((vTotal   & 0x400) >> 10);
     state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
     state->horiz    = hTotal     < 260 ? 0x00 : 0x01;
-    state->pixel    = (pixelDepth > 2 ? 3 : pixelDepth) | 0x40;
+    state->pixel    = pixelDepth > 2   ? 3    : pixelDepth;
     state->offset0  =
     state->offset1  =
     state->offset2  =
@@ -937,6 +1270,31 @@
 #define LOAD_FIXED_STATE_32BPP(tbl,dev)                                 \
     for (i = 0; i < sizeof(tbl##Table##dev##_32BPP)/8; i++)           \
         chip->dev[tbl##Table##dev##_32BPP[i][0]] = tbl##Table##dev##_32BPP[i][1]
+static void UpdateFifoState
+(
+    RIVA_HW_INST  *chip
+)
+{
+    int i;
+
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_04:
+            LOAD_FIXED_STATE(nv4,FIFO);
+            chip->Tri03 = 0L;
+            chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
+            break;
+        case NV_ARCH_10:
+            /*
+             * Initialize state for the RivaTriangle3D05 routines.
+             */
+            LOAD_FIXED_STATE(nv10tri05,PGRAPH);
+            LOAD_FIXED_STATE(nv10,FIFO);
+            chip->Tri03 = 0L;
+            chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
+            break;
+    }
+}
 static void LoadStateExt
 (
     RIVA_HW_INST  *chip,
@@ -944,18 +1302,19 @@
 )
 {
     int i;
+
     /*
      * Load HW fixed function state.
      */
     LOAD_FIXED_STATE(Riva,PMC);
     LOAD_FIXED_STATE(Riva,PTIMER);
-    /*
-     * Make sure frame buffer config gets set before loading PRAMIN.
-     */
-    chip->PFB[0x00000200/4] = state->config;
     switch (chip->Architecture)
     {
-        case 3:
+        case NV_ARCH_03:
+            /*
+             * Make sure frame buffer config gets set before loading PRAMIN.
+             */
+            chip->PFB[0x00000200/4] = state->config;
             LOAD_FIXED_STATE(nv3,PFIFO);
             LOAD_FIXED_STATE(nv3,PRAMIN);
             LOAD_FIXED_STATE(nv3,PGRAPH);
@@ -991,8 +1350,11 @@
             chip->PGRAPH[0x00000658/4] = state->pitch2;
             chip->PGRAPH[0x0000065C/4] = state->pitch3;
             break;
-	    case 4:
-	    case 5:
+        case NV_ARCH_04:
+            /*
+             * Make sure frame buffer config gets set before loading PRAMIN.
+             */
+            chip->PFB[0x00000200/4] = state->config;
             LOAD_FIXED_STATE(nv4,PFIFO);
             LOAD_FIXED_STATE(nv4,PRAMIN);
             LOAD_FIXED_STATE(nv4,PGRAPH);
@@ -1030,22 +1392,142 @@
             chip->PGRAPH[0x00000678/4] = state->pitch2;
             chip->PGRAPH[0x0000067C/4] = state->pitch3;
             break;
+        case NV_ARCH_10:
+            LOAD_FIXED_STATE(nv10,PFIFO);
+            LOAD_FIXED_STATE(nv10,PRAMIN);
+            LOAD_FIXED_STATE(nv10,PGRAPH);
+            switch (state->bpp)
+            {
+                case 15:
+                    LOAD_FIXED_STATE_15BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_15BPP(nv10,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 16:
+                    LOAD_FIXED_STATE_16BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_16BPP(nv10,PGRAPH);
+                    chip->Tri03 = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
+                    break;
+                case 24:
+                case 32:
+                    LOAD_FIXED_STATE_32BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_32BPP(nv10,PGRAPH);
+                    chip->Tri03 = 0L;
+                    break;
+                case 8:
+                default:
+                    LOAD_FIXED_STATE_8BPP(nv10,PRAMIN);
+                    LOAD_FIXED_STATE_8BPP(nv10,PGRAPH);
+                    chip->Tri03 = 0L;
+                    break;
+            }
+            chip->PGRAPH[0x00000640/4] = state->offset0;
+            chip->PGRAPH[0x00000644/4] = state->offset1;
+            chip->PGRAPH[0x00000648/4] = state->offset2;
+            chip->PGRAPH[0x0000064C/4] = state->offset3;
+            chip->PGRAPH[0x00000670/4] = state->pitch0;
+            chip->PGRAPH[0x00000674/4] = state->pitch1;
+            chip->PGRAPH[0x00000678/4] = state->pitch2;
+            chip->PGRAPH[0x0000067C/4] = state->pitch3;
+            chip->PGRAPH[0x00000680/4] = state->pitch3;
+            chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
+            chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
+            chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
+            chip->PGRAPH[0x00000B0C/4] = chip->PFB[0x0000024C/4];
+            chip->PGRAPH[0x00000B10/4] = chip->PFB[0x00000250/4];
+            chip->PGRAPH[0x00000B14/4] = chip->PFB[0x00000254/4];
+            chip->PGRAPH[0x00000B18/4] = chip->PFB[0x00000258/4];
+            chip->PGRAPH[0x00000B1C/4] = chip->PFB[0x0000025C/4];
+            chip->PGRAPH[0x00000B20/4] = chip->PFB[0x00000260/4];
+            chip->PGRAPH[0x00000B24/4] = chip->PFB[0x00000264/4];
+            chip->PGRAPH[0x00000B28/4] = chip->PFB[0x00000268/4];
+            chip->PGRAPH[0x00000B2C/4] = chip->PFB[0x0000026C/4];
+            chip->PGRAPH[0x00000B30/4] = chip->PFB[0x00000270/4];
+            chip->PGRAPH[0x00000B34/4] = chip->PFB[0x00000274/4];
+            chip->PGRAPH[0x00000B38/4] = chip->PFB[0x00000278/4];
+            chip->PGRAPH[0x00000B3C/4] = chip->PFB[0x0000027C/4];
+            chip->PGRAPH[0x00000B40/4] = chip->PFB[0x00000280/4];
+            chip->PGRAPH[0x00000B44/4] = chip->PFB[0x00000284/4];
+            chip->PGRAPH[0x00000B48/4] = chip->PFB[0x00000288/4];
+            chip->PGRAPH[0x00000B4C/4] = chip->PFB[0x0000028C/4];
+            chip->PGRAPH[0x00000B50/4] = chip->PFB[0x00000290/4];
+            chip->PGRAPH[0x00000B54/4] = chip->PFB[0x00000294/4];
+            chip->PGRAPH[0x00000B58/4] = chip->PFB[0x00000298/4];
+            chip->PGRAPH[0x00000B5C/4] = chip->PFB[0x0000029C/4];
+            chip->PGRAPH[0x00000B60/4] = chip->PFB[0x000002A0/4];
+            chip->PGRAPH[0x00000B64/4] = chip->PFB[0x000002A4/4];
+            chip->PGRAPH[0x00000B68/4] = chip->PFB[0x000002A8/4];
+            chip->PGRAPH[0x00000B6C/4] = chip->PFB[0x000002AC/4];
+            chip->PGRAPH[0x00000B70/4] = chip->PFB[0x000002B0/4];
+            chip->PGRAPH[0x00000B74/4] = chip->PFB[0x000002B4/4];
+            chip->PGRAPH[0x00000B78/4] = chip->PFB[0x000002B8/4];
+            chip->PGRAPH[0x00000B7C/4] = chip->PFB[0x000002BC/4];
+            chip->PGRAPH[0x00000F40/4] = 0x10000000;
+            chip->PGRAPH[0x00000F44/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000040;
+            chip->PGRAPH[0x00000F54/4] = 0x00000008;
+            chip->PGRAPH[0x00000F50/4] = 0x00000200;
+            for (i = 0; i < (3*16); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000040;
+            chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000800;
+            for (i = 0; i < (16*16); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F40/4] = 0x30000000;
+            chip->PGRAPH[0x00000F44/4] = 0x00000004;
+            chip->PGRAPH[0x00000F50/4] = 0x00006400;
+            for (i = 0; i < (59*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00006800;
+            for (i = 0; i < (47*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00006C00;
+            for (i = 0; i < (3*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00007000;
+            for (i = 0; i < (19*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00007400;
+            for (i = 0; i < (12*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00007800;
+            for (i = 0; i < (12*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00004400;
+            for (i = 0; i < (8*4); i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000000;
+            for (i = 0; i < 16; i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            chip->PGRAPH[0x00000F50/4] = 0x00000040;
+            for (i = 0; i < 4; i++)
+                chip->PGRAPH[0x00000F54/4] = 0x00000000;
+            break;
     }
-//NOTICE("8");
-//    LOAD_FIXED_STATE(Riva,FIFO); /* FIX ME*/
-//NOTICE("9");
+    LOAD_FIXED_STATE(Riva,FIFO);
+    UpdateFifoState(chip);
     /*
      * Load HW mode state.
      */
-    outb(0x19, 0x3D4); outb(state->repaint0, 0x3D5);
-    outb(0x1A, 0x3D4); outb(state->repaint1, 0x3D5);
-    outb(0x25, 0x3D4); outb(state->screen, 0x3D5);
-    outb(0x28, 0x3D4); outb(state->pixel, 0x3D5);
-    outb(0x2D, 0x3D4); outb(state->horiz, 0x3D5);
-    outb(0x1B, 0x3D4); outb(state->arbitration0, 0x3D5);
-    outb(0x20, 0x3D4); outb(state->arbitration1, 0x3D5);
-    outb(0x30, 0x3D4); outb(state->cursor0, 0x3D5);
-    outb(0x31, 0x3D4); outb(state->cursor1, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+    VGA_WR08(chip->PCIO, 0x03D5, state->repaint0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+    VGA_WR08(chip->PCIO, 0x03D5, state->repaint1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+    VGA_WR08(chip->PCIO, 0x03D5, state->screen);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+    VGA_WR08(chip->PCIO, 0x03D5, state->pixel);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+    VGA_WR08(chip->PCIO, 0x03D5, state->horiz);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+    VGA_WR08(chip->PCIO, 0x03D5, state->arbitration1);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor0);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+    VGA_WR08(chip->PCIO, 0x03D5, state->cursor1);
     chip->PRAMDAC[0x00000300/4]  = state->cursor2;
     chip->PRAMDAC[0x00000508/4]  = state->vpll;
     chip->PRAMDAC[0x0000050C/4]  = state->pllsel;
@@ -1053,8 +1535,8 @@
     /*
      * Turn off VBlank enable and reset.
      */
-//    *(chip->VBLANKENABLE) = 0;		/* FIXME*/
-//    *(chip->VBLANK)       = chip->VBlankBit; /*FIXME*/
+    *(chip->VBLANKENABLE) = 0;
+    *(chip->VBLANK)       = chip->VBlankBit;
     /*
      * Set interrupt enable.
      */    
@@ -1064,9 +1546,11 @@
      */
     chip->CurrentState = state;
     /*
-     * Reset FIFO free count.
+     * Reset FIFO free and empty counts.
      */
-    chip->FifoFreeCount = 0;
+    chip->FifoFreeCount  = 0;
+    /* Free count from first subchannel */
+    chip->FifoEmptyCount = chip->Rop->FifoFree; 
 }
 static void UnloadStateExt
 (
@@ -1077,44 +1561,62 @@
     /*
      * Save current HW state.
      */
-    outb(0x19, 0x3D4); state->repaint0     = inb(0x3D5);
-    outb(0x1A, 0x3D4); state->repaint1     = inb(0x3D5);
-    outb(0x25, 0x3D4); state->screen       = inb(0x3D5);
-    outb(0x28, 0x3D4); state->pixel        = inb(0x3D5);
-    outb(0x2D, 0x3D4); state->horiz        = inb(0x3D5);
-    outb(0x1B, 0x3D4); state->arbitration0 = inb(0x3D5);
-    outb(0x20, 0x3D4); state->arbitration1 = inb(0x3D5);
-    outb(0x30, 0x3D4); state->cursor0      = inb(0x3D5);
-    outb(0x31, 0x3D4); state->cursor1      = inb(0x3D5);
-                      state->cursor2      = chip->PRAMDAC[0x00000300/4];
-                      state->vpll         = chip->PRAMDAC[0x00000508/4];
-                      state->pllsel       = chip->PRAMDAC[0x0000050C/4];
-                      state->general      = chip->PRAMDAC[0x00000600/4];
-                      state->config       = chip->PFB[0x00000200/4];
-                      switch (chip->Architecture)
-                      {
-			      case 3:
-                              state->offset0  = chip->PGRAPH[0x00000630/4];
-                              state->offset1  = chip->PGRAPH[0x00000634/4];
-                              state->offset2  = chip->PGRAPH[0x00000638/4];
-                              state->offset3  = chip->PGRAPH[0x0000063C/4];
-                              state->pitch0   = chip->PGRAPH[0x00000650/4];
-                              state->pitch1   = chip->PGRAPH[0x00000654/4];
-                              state->pitch2   = chip->PGRAPH[0x00000658/4];
-                              state->pitch3   = chip->PGRAPH[0x0000065C/4];
-                              break;
-			      case 4:
-			      case 5:
-                              state->offset0  = chip->PGRAPH[0x00000640/4];
-                              state->offset1  = chip->PGRAPH[0x00000644/4];
-                              state->offset2  = chip->PGRAPH[0x00000648/4];
-                              state->offset3  = chip->PGRAPH[0x0000064C/4];
-                              state->pitch0   = chip->PGRAPH[0x00000670/4];
-                              state->pitch1   = chip->PGRAPH[0x00000674/4];
-                              state->pitch2   = chip->PGRAPH[0x00000678/4];
-                              state->pitch3   = chip->PGRAPH[0x0000067C/4];
-                              break;
-                      }
+    VGA_WR08(chip->PCIO, 0x03D4, 0x19);
+    state->repaint0     = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1A);
+    state->repaint1     = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x25);
+    state->screen       = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x28);
+    state->pixel        = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x2D);
+    state->horiz        = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x1B);
+    state->arbitration0 = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x20);
+    state->arbitration1 = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x30);
+    state->cursor0      = VGA_RD08(chip->PCIO, 0x03D5);
+    VGA_WR08(chip->PCIO, 0x03D4, 0x31);
+    state->cursor1      = VGA_RD08(chip->PCIO, 0x03D5);
+    state->cursor2      = chip->PRAMDAC[0x00000300/4];
+    state->vpll         = chip->PRAMDAC[0x00000508/4];
+    state->pllsel       = chip->PRAMDAC[0x0000050C/4];
+    state->general      = chip->PRAMDAC[0x00000600/4];
+    state->config       = chip->PFB[0x00000200/4];
+    switch (chip->Architecture)
+    {
+        case NV_ARCH_03:
+            state->offset0  = chip->PGRAPH[0x00000630/4];
+            state->offset1  = chip->PGRAPH[0x00000634/4];
+            state->offset2  = chip->PGRAPH[0x00000638/4];
+            state->offset3  = chip->PGRAPH[0x0000063C/4];
+            state->pitch0   = chip->PGRAPH[0x00000650/4];
+            state->pitch1   = chip->PGRAPH[0x00000654/4];
+            state->pitch2   = chip->PGRAPH[0x00000658/4];
+            state->pitch3   = chip->PGRAPH[0x0000065C/4];
+            break;
+        case NV_ARCH_04:
+            state->offset0  = chip->PGRAPH[0x00000640/4];
+            state->offset1  = chip->PGRAPH[0x00000644/4];
+            state->offset2  = chip->PGRAPH[0x00000648/4];
+            state->offset3  = chip->PGRAPH[0x0000064C/4];
+            state->pitch0   = chip->PGRAPH[0x00000670/4];
+            state->pitch1   = chip->PGRAPH[0x00000674/4];
+            state->pitch2   = chip->PGRAPH[0x00000678/4];
+            state->pitch3   = chip->PGRAPH[0x0000067C/4];
+            break;
+        case NV_ARCH_10:
+            state->offset0  = chip->PGRAPH[0x00000640/4];
+            state->offset1  = chip->PGRAPH[0x00000644/4];
+            state->offset2  = chip->PGRAPH[0x00000648/4];
+            state->offset3  = chip->PGRAPH[0x0000064C/4];
+            state->pitch0   = chip->PGRAPH[0x00000670/4];
+            state->pitch1   = chip->PGRAPH[0x00000674/4];
+            state->pitch2   = chip->PGRAPH[0x00000678/4];
+            state->pitch3   = chip->PGRAPH[0x0000067C/4];
+            break;
+    }
 }
 static void SetStartAddress
 (
@@ -1129,24 +1631,24 @@
     /*
      * Unlock extended registers.
      */
-    outb(chip->LockUnlockIndex, chip->LockUnlockIO);
-    outb(0x57, chip->LockUnlockIO + 1);
+    chip->LockUnlock(chip, 0);
     /*
      * Set start address.
      */
-    outb(0x0D, 0x3D4);
-    outb(offset, 0x3D5);
-    outb(0x0C, 0x3D4);
-    outb(offset >> 8, 0x3D5);
-    outb(0x19, 0x3D4);
-    tmp = inb(0x3D5);
-    outb(((offset >> 16) & 0x0F) | (tmp & 0xF0), 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D4, 0x0D); VGA_WR08(chip->PCIO, 0x3D5, offset);
+    offset >>= 8;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x0C); VGA_WR08(chip->PCIO, 0x3D5, offset);
+    offset >>= 8;
+    VGA_WR08(chip->PCIO, 0x3D4, 0x19); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x01F) | (tmp & ~0x1F));
+    VGA_WR08(chip->PCIO, 0x3D4, 0x2D); tmp = VGA_RD08(chip->PCIO, 0x3D5);
+    VGA_WR08(chip->PCIO, 0x3D5, (offset & 0x60) | (tmp & ~0x60));
     /*
      * 4 pixel pan register.
      */
-    offset = inb(chip->IO + 0x0A);
-    outb(0x13, 0x3C0);
-    outb(pan, 0x3C0);
+    offset = VGA_RD08(chip->PCIO, chip->IO + 0x0A);
+    VGA_WR08(chip->PCIO, 0x3C0, 0x13);
+    VGA_WR08(chip->PCIO, 0x3C0, pan);
 }
 static void nv3SetSurfaces2D
 (
@@ -1155,9 +1657,14 @@
     unsigned     surf1
 )
 {
-    while (nv3Busy(chip));
-    chip->PGRAPH[0x00000630/4] = surf0;
-    chip->PGRAPH[0x00000634/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,5);
+    chip->FIFO[0x00003800] = 0x80000003;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000004;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000013;
 }
 static void nv4SetSurfaces2D
 (
@@ -1166,9 +1673,28 @@
     unsigned     surf1
 )
 {
-    while (nv4Busy(chip));
-    chip->PGRAPH[0x00000640/4] = surf0;
-    chip->PGRAPH[0x00000644/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    chip->FIFO[0x00003800] = 0x80000003;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000004;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000014;
+}
+static void nv10SetSurfaces2D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    chip->FIFO[0x00003800] = 0x80000003;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000004;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000014;
 }
 static void nv3SetSurfaces3D
 (
@@ -1177,9 +1703,14 @@
     unsigned     surf1
 )
 {
-    while (nv3Busy(chip));
-    chip->PGRAPH[0x00000638/4] = surf0;
-    chip->PGRAPH[0x0000063C/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,5);
+    chip->FIFO[0x00003800] = 0x80000005;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000006;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000013;
 }
 static void nv4SetSurfaces3D
 (
@@ -1188,9 +1719,28 @@
     unsigned     surf1
 )
 {
-    while (nv4Busy(chip));
-    chip->PGRAPH[0x00000648/4] = surf0;
-    chip->PGRAPH[0x0000064C/4] = surf1;
+    RivaSurface *Surface = (RivaSurface *)&(chip->FIFO[0x0000E000/4]);
+
+    chip->FIFO[0x00003800] = 0x80000005;
+    Surface->Offset        = surf0;
+    chip->FIFO[0x00003800] = 0x80000006;
+    Surface->Offset        = surf1;
+    chip->FIFO[0x00003800] = 0x80000014;
+}
+static void nv10SetSurfaces3D
+(
+    RIVA_HW_INST *chip,
+    unsigned     surf0,
+    unsigned     surf1
+)
+{
+    RivaSurface3D *Surfaces3D = (RivaSurface3D *)&(chip->FIFO[0x0000E000/4]);
+
+    RIVA_FIFO_FREE(*chip,Tri03,4);
+    chip->FIFO[0x00003800]         = 0x80000007;
+    Surfaces3D->RenderBufferOffset = surf0;
+    Surfaces3D->ZBufferOffset      = surf1;
+    chip->FIFO[0x00003800]         = 0x80000014;
 }
 
 /****************************************************************************\
@@ -1199,7 +1749,7 @@
 *                                                                            *
 \****************************************************************************/
 
-void nv3GetConfig
+static void nv3GetConfig
 (
     RIVA_HW_INST *chip
 )
@@ -1219,20 +1769,20 @@
             switch (chip->PFB[0x00000000/4] & 0x03)
             {
                 case 2:
-                    chip->RamAmountKBytes = 1024 * 4 - 32;
+                    chip->RamAmountKBytes = 1024 * 4;
                     break;
                 case 1:
-                    chip->RamAmountKBytes = 1024 * 2 - 32;
+                    chip->RamAmountKBytes = 1024 * 2;
                     break;
                 default:
-                    chip->RamAmountKBytes = 1024 * 8 - 32;
+                    chip->RamAmountKBytes = 1024 * 8;
                     break;
             }
         }            
         else            
         {
             chip->RamBandwidthKBytesPerSec = 1000000;
-            chip->RamAmountKBytes          = 1024 * 8 - 32;
+            chip->RamAmountKBytes          = 1024 * 8;
         }            
     }
     else
@@ -1244,13 +1794,13 @@
         switch (chip->PFB[0x00000000/4] & 0x00000003)
         {
             case 0:
-                chip->RamAmountKBytes = 1024 * 8 - 32;
+                chip->RamAmountKBytes = 1024 * 8;
                 break;
             case 2:
-                chip->RamAmountKBytes = 1024 * 4 - 32;
+                chip->RamAmountKBytes = 1024 * 4;
                 break;
             default:
-                chip->RamAmountKBytes = 1024 * 2 - 32;
+                chip->RamAmountKBytes = 1024 * 2;
                 break;
         }
     }        
@@ -1260,9 +1810,7 @@
     chip->VBLANKENABLE     = &(chip->PGRAPH[0x0140/4]);
     chip->VBLANK           = &(chip->PGRAPH[0x0100/4]);
     chip->VBlankBit        = 0x00000100;
-    chip->MaxVClockFreqKHz = 230000;
-    chip->LockUnlockIO     = 0x3C4;
-    chip->LockUnlockIndex  = 0x06;
+    chip->MaxVClockFreqKHz = 256000;
     /*
      * Set chip functions.
      */
@@ -1274,9 +1822,9 @@
     chip->SetStartAddress = SetStartAddress;
     chip->SetSurfaces2D   = nv3SetSurfaces2D;
     chip->SetSurfaces3D   = nv3SetSurfaces3D;
+    chip->LockUnlock      = nv3LockUnlock;
 }
-
-void nv4GetConfig
+static void nv4GetConfig
 (
     RIVA_HW_INST *chip
 )
@@ -1284,21 +1832,29 @@
     /*
      * Fill in chip configuration.
      */
-    switch (chip->PFB[0x00000000/4] & 0x00000003)
+    if (chip->PFB[0x00000000/4] & 0x00000100)
     {
-        case 0:
-            chip->RamAmountKBytes = 1024 * 32 - 128;
-            break;
-        case 1:
-            chip->RamAmountKBytes = 1024 * 4 - 128;
-            break;
-        case 2:
-            chip->RamAmountKBytes = 1024 * 8 - 128;
-            break;
-        case 3:
-        default:
-            chip->RamAmountKBytes = 1024 * 16 - 128;
-            break;
+        chip->RamAmountKBytes = ((chip->PFB[0x00000000/4] >> 12) & 0x0F) * 1024 * 2
+                              + 1024 * 2;
+    }
+    else
+    {
+        switch (chip->PFB[0x00000000/4] & 0x00000003)
+        {
+            case 0:
+                chip->RamAmountKBytes = 1024 * 32;
+                break;
+            case 1:
+                chip->RamAmountKBytes = 1024 * 4;
+                break;
+            case 2:
+                chip->RamAmountKBytes = 1024 * 8;
+                break;
+            case 3:
+            default:
+                chip->RamAmountKBytes = 1024 * 16;
+                break;
+        }
     }
     switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
     {
@@ -1315,9 +1871,7 @@
     chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
     chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
     chip->VBlankBit        = 0x00000001;
-    chip->MaxVClockFreqKHz = 250000;
-    chip->LockUnlockIO     = 0x3D4;
-    chip->LockUnlockIndex  = 0x1F;
+    chip->MaxVClockFreqKHz = 350000;
     /*
      * Set chip functions.
      */
@@ -1329,9 +1883,9 @@
     chip->SetStartAddress = SetStartAddress;
     chip->SetSurfaces2D   = nv4SetSurfaces2D;
     chip->SetSurfaces3D   = nv4SetSurfaces3D;
+    chip->LockUnlock      = nv4LockUnlock;
 }
-
-void nv5GetConfig
+static void nv10GetConfig
 (
     RIVA_HW_INST *chip
 )
@@ -1339,20 +1893,31 @@
     /*
      * Fill in chip configuration.
      */
-    switch (chip->PFB[0x00000000/4] & 0x00000003)
+    switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF)
     {
-        case 0:
-            chip->RamAmountKBytes = 1024 * 32 - 128;
+        case 0x02:
+            chip->RamAmountKBytes = 1024 * 2;
             break;
-        case 1:
-            chip->RamAmountKBytes = 1024 * 4 - 128;
+        case 0x04:
+            chip->RamAmountKBytes = 1024 * 4;
             break;
-        case 2:
-            chip->RamAmountKBytes = 1024 * 8 - 128;
+        case 0x08:
+            chip->RamAmountKBytes = 1024 * 8;
+            break;
+        case 0x10:
+            chip->RamAmountKBytes = 1024 * 16;
+            break;
+        case 0x20:
+            chip->RamAmountKBytes = 1024 * 32;
+            break;
+        case 0x40:
+            chip->RamAmountKBytes = 1024 * 64;
+            break;
+        case 0x80:
+            chip->RamAmountKBytes = 1024 * 128;
             break;
-        case 3:
         default:
-            chip->RamAmountKBytes = 1024 * 16 - 128;
+            chip->RamAmountKBytes = 1024 * 16;
             break;
     }
     switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
@@ -1370,22 +1935,20 @@
     chip->VBLANKENABLE     = &(chip->PCRTC[0x0140/4]);
     chip->VBLANK           = &(chip->PCRTC[0x0100/4]);
     chip->VBlankBit        = 0x00000001;
-    chip->MaxVClockFreqKHz = 250000;
-    chip->LockUnlockIO     = 0x3D4;
-    chip->LockUnlockIndex  = 0x1F;
+    chip->MaxVClockFreqKHz = 350000;
     /*
      * Set chip functions.
      */
-    chip->Busy            = nv4Busy;
+    chip->Busy            = nv10Busy;
     chip->ShowHideCursor  = ShowHideCursor;
     chip->CalcStateExt    = CalcStateExt;
     chip->LoadStateExt    = LoadStateExt;
     chip->UnloadStateExt  = UnloadStateExt;
     chip->SetStartAddress = SetStartAddress;
-    chip->SetSurfaces2D   = nv4SetSurfaces2D;
-    chip->SetSurfaces3D   = nv4SetSurfaces3D;
+    chip->SetSurfaces2D   = nv10SetSurfaces2D;
+    chip->SetSurfaces3D   = nv10SetSurfaces3D;
+    chip->LockUnlock      = nv10LockUnlock;
 }
-
 int RivaGetConfig
 (
     RIVA_HW_INST *chip
@@ -1400,14 +1963,15 @@
      */
     switch (chip->Architecture)
     {
-        case 3:
+        case NV_ARCH_03:
             nv3GetConfig(chip);
             break;
-        case 4:
+        case NV_ARCH_04:
             nv4GetConfig(chip);
             break;
-	    case 5:
-	    nv5GetConfig(chip);
+        case NV_ARCH_10:
+            nv10GetConfig(chip);
+            break;
         default:
             return (-1);
     }
@@ -1420,6 +1984,7 @@
     chip->Pixmap = (RivaPixmap              *)&(chip->FIFO[0x00006000/4]);
     chip->Blt    = (RivaScreenBlt           *)&(chip->FIFO[0x00008000/4]);
     chip->Bitmap = (RivaBitmap              *)&(chip->FIFO[0x0000A000/4]);
+    chip->Line   = (RivaLine                *)&(chip->FIFO[0x0000C000/4]);
     chip->Tri03  = (RivaTexturedTriangle03  *)&(chip->FIFO[0x0000E000/4]);
     return (0);
 }
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/riva_hw.h linux/drivers/video/riva/riva_hw.h
--- v2.4.1/linux/drivers/video/riva/riva_hw.h	Tue Feb 29 11:07:04 2000
+++ linux/drivers/video/riva/riva_hw.h	Tue Feb 13 13:15:05 2001
@@ -1,6 +1,6 @@
 /***************************************************************************\
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
 |*     international laws.  Users and possessors of this source code are     *|
@@ -11,7 +11,7 @@
 |*     tion and  internal comments to the code,  notices to the end user     *|
 |*     as follows:                                                           *|
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
@@ -36,18 +36,44 @@
 |*     those rights set forth herein.                                        *|
 |*                                                                           *|
 \***************************************************************************/
-/* 
- * GPL licensing note -- nVidia is allowing a liberal interpretation of 
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
  * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived 
- * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99 
  */
 
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/riva_hw.h,v 1.1.2.2 1998/12/22 16:33:19 hohndel Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.6 2000/02/08 17:19:12 dawes Exp $ */
 #ifndef __RIVA_HW_H__
 #define __RIVA_HW_H__
-#define RIVA_SW_VERSION 0x00010000
+#define RIVA_SW_VERSION 0x00010003
 
+/*
+ * Typedefs to force certain sized values.
+ */
+typedef unsigned char  U008;
+typedef unsigned short U016;
+typedef unsigned int   U032;
+
+/*
+ * HW access macros.
+ */
+#define NV_WR08(p,i,d)  (((U008 *)(p))[i]=(d))
+#define NV_RD08(p,i)    (((U008 *)(p))[i])
+#define NV_WR16(p,i,d)  (((U016 *)(p))[(i)/2]=(d))
+#define NV_RD16(p,i)    (((U016 *)(p))[(i)/2])
+#define NV_WR32(p,i,d)  (((U032 *)(p))[(i)/4]=(d))
+#define NV_RD32(p,i)    (((U032 *)(p))[(i)/4])
+#define VGA_WR08(p,i,d) NV_WR08(p,i,d)
+#define VGA_RD08(p,i)   NV_RD08(p,i)
+
+/*
+ * Define supported architectures.
+ */
+#define NV_ARCH_03  0x03
+#define NV_ARCH_04  0x04
+#define NV_ARCH_10  0x10
 /***************************************************************************\
 *                                                                           *
 *                             FIFO registers.                               *
@@ -59,161 +85,165 @@
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned Rop3;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 Rop3;
 } RivaRop;
 /*
  * 8X8 Monochrome pattern.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BD];
-    unsigned Shape;
-    unsigned reserved03[0x001];
-    unsigned Color0;
-    unsigned Color1;
-    unsigned Monochrome[2];
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BD];
+    U032 Shape;
+    U032 reserved03[0x001];
+    U032 Color0;
+    U032 Color1;
+    U032 Monochrome[2];
 } RivaPattern;
 /*
  * Scissor clip rectangle.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned TopLeft;
-    unsigned WidthHeight;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 TopLeft;
+    U032 WidthHeight;
 } RivaClip;
 /*
  * 2D filled rectangle.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop[1];
-    unsigned reserved01[0x0BC];
-    unsigned Color;
-    unsigned reserved03[0x03E];
-    unsigned TopLeft;
-    unsigned WidthHeight;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop[1];
+    U032 reserved01[0x0BC];
+    U032 Color;
+    U032 reserved03[0x03E];
+    U032 TopLeft;
+    U032 WidthHeight;
 } RivaRectangle;
 /*
  * 2D screen-screen BLT.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned TopLeftSrc;
-    unsigned TopLeftDst;
-    unsigned WidthHeight;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 TopLeftSrc;
+    U032 TopLeftDst;
+    U032 WidthHeight;
 } RivaScreenBlt;
 /*
  * 2D pixel BLT.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop[1];
-    unsigned reserved01[0x0BC];
-    unsigned TopLeft;
-    unsigned WidthHeight;
-    unsigned WidthHeightIn;
-    unsigned reserved02[0x03C];
-    unsigned Pixels;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop[1];
+    U032 reserved01[0x0BC];
+    U032 TopLeft;
+    U032 WidthHeight;
+    U032 WidthHeightIn;
+    U032 reserved02[0x03C];
+    U032 Pixels;
 } RivaPixmap;
 /*
  * Filled rectangle combined with monochrome expand.  Useful for glyphs.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BB];
-    unsigned reserved03[(0x040)-1];
-    unsigned Color1A;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 reserved03[(0x040)-1];
+    U032 Color1A;
     struct
     {
-        unsigned TopLeft;
-        unsigned WidthHeight;
+        U032 TopLeft;
+        U032 WidthHeight;
     } UnclippedRectangle[64];
-    unsigned reserved04[(0x080)-3];
+    U032 reserved04[(0x080)-3];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipB;
-    unsigned Color1B;
+    U032 Color1B;
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClippedRectangle[64];
-    unsigned reserved05[(0x080)-5];
+    U032 reserved05[(0x080)-5];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipC;
-    unsigned Color1C;
-    unsigned WidthHeightC;
-    unsigned PointC;
-    unsigned MonochromeData1C;
-    unsigned reserved06[(0x080)+121];
+    U032 Color1C;
+    U032 WidthHeightC;
+    U032 PointC;
+    U032 MonochromeData1C;
+    U032 reserved06[(0x080)+121];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipD;
-    unsigned Color1D;
-    unsigned WidthHeightInD;
-    unsigned WidthHeightOutD;
-    unsigned PointD;
-    unsigned MonochromeData1D;
-    unsigned reserved07[(0x080)+120];
+    U032 Color1D;
+    U032 WidthHeightInD;
+    U032 WidthHeightOutD;
+    U032 PointD;
+    U032 MonochromeData1D;
+    U032 reserved07[(0x080)+120];
     struct
     {
-        unsigned TopLeft;
-        unsigned BottomRight;
+        U032 TopLeft;
+        U032 BottomRight;
     } ClipE;
-    unsigned Color0E;
-    unsigned Color1E;
-    unsigned WidthHeightInE;
-    unsigned WidthHeightOutE;
-    unsigned PointE;
-    unsigned MonochromeData01E;
+    U032 Color0E;
+    U032 Color1E;
+    U032 WidthHeightInE;
+    U032 WidthHeightOutE;
+    U032 PointE;
+    U032 MonochromeData01E;
 } RivaBitmap;
 /*
  * 3D textured, Z buffered triangle.
  */
 typedef volatile struct
 {
-    unsigned reserved00[4];
-    unsigned short FifoFree;
-    unsigned short Nop;
-    unsigned reserved01[0x0BC];
-    unsigned TextureOffset;
-    unsigned TextureFormat;
-    unsigned TextureFilter;
-    unsigned FogColor;
-    unsigned Control;
-    unsigned AlphaTest;
-    unsigned reserved02[0x339];
-    unsigned FogAndIndex;
-    unsigned Color;
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BC];
+    U032 TextureOffset;
+    U032 TextureFormat;
+    U032 TextureFilter;
+    U032 FogColor;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+    U032 Control;
+    U032 AlphaTest;
+    U032 reserved02[0x339];
+    U032 FogAndIndex;
+    U032 Color;
     float ScreenX;
     float ScreenY;
     float ScreenZ;
@@ -221,7 +251,90 @@
     float TextureS;
     float TextureT;
 } RivaTexturedTriangle03;
-
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BB];
+    U032 ColorKey;
+    U032 TextureOffset;
+    U032 TextureFormat;
+    U032 TextureFilter;
+    U032 Blend;
+/* This is a problem on LynxOS */
+#ifdef Control
+#undef Control
+#endif
+    U032 Control;
+    U032 FogColor;
+    U032 reserved02[0x39];
+    struct
+    {
+        float ScreenX;
+        float ScreenY;
+        float ScreenZ;
+        float EyeM;
+        U032 Color;
+        U032 Specular;
+        float TextureS;
+        float TextureT;
+    } Vertex[16];
+    U032 DrawTriangle3D;
+} RivaTexturedTriangle05;
+/*
+ * 2D line.
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop[1];
+    U032 reserved01[0x0BC];
+    U032 Color;             /* source color               0304-0307*/
+    U032 Reserved02[0x03e];
+    struct {                /* start aliased methods in array   0400-    */
+        U032 point0;        /* y_x S16_S16 in pixels            0-   3*/
+        U032 point1;        /* y_x S16_S16 in pixels            4-   7*/
+    } Lin[16];              /* end of aliased methods in array      -047f*/
+    struct {                /* start aliased methods in array   0480-    */
+        U032 point0X;       /* in pixels, 0 at left                0-   3*/
+        U032 point0Y;       /* in pixels, 0 at top                 4-   7*/
+        U032 point1X;       /* in pixels, 0 at left                8-   b*/
+        U032 point1Y;       /* in pixels, 0 at top                 c-   f*/
+    } Lin32[8];             /* end of aliased methods in array      -04ff*/
+    U032 PolyLin[32];       /* y_x S16_S16 in pixels         0500-057f*/
+    struct {                /* start aliased methods in array   0580-    */
+        U032 x;             /* in pixels, 0 at left                0-   3*/
+        U032 y;             /* in pixels, 0 at top                 4-   7*/
+    } PolyLin32[16];        /* end of aliased methods in array      -05ff*/
+    struct {                /* start aliased methods in array   0600-    */
+        U032 color;         /* source color                     0-   3*/
+        U032 point;         /* y_x S16_S16 in pixels            4-   7*/
+    } ColorPolyLin[16];     /* end of aliased methods in array      -067f*/
+} RivaLine;
+/*
+ * 2D/3D surfaces
+ */
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BE];
+    U032 Offset;
+} RivaSurface;
+typedef volatile struct
+{
+    U032 reserved00[4];
+    U016 FifoFree;
+    U016 Nop;
+    U032 reserved01[0x0BD];
+    U032 Pitch;
+    U032 RenderBufferOffset;
+    U032 ZBufferOffset;
+} RivaSurface3D;
+    
 /***************************************************************************\
 *                                                                           *
 *                        Virtualized RIVA H/W interface.                    *
@@ -238,35 +351,37 @@
     /*
      * Chip specific settings.
      */
-    unsigned Architecture;
-    unsigned Version;
-    unsigned CrystalFreqKHz;
-    unsigned RamAmountKBytes;
-    unsigned MaxVClockFreqKHz;
-    unsigned RamBandwidthKBytesPerSec;
-    unsigned EnableIRQ;
-    unsigned IO;
-    unsigned LockUnlockIO;
-    unsigned LockUnlockIndex;
-    unsigned VBlankBit;
-    unsigned FifoFreeCount;
+    U032 Architecture;
+    U032 Version;
+    U032 CrystalFreqKHz;
+    U032 RamAmountKBytes;
+    U032 MaxVClockFreqKHz;
+    U032 RamBandwidthKBytesPerSec;
+    U032 EnableIRQ;
+    U032 IO;
+    U032 VBlankBit;
+    U032 FifoFreeCount;
+    U032 FifoEmptyCount;
     /*
      * Non-FIFO registers.
      */
-    volatile unsigned *PCRTC;
-    volatile unsigned *PRAMDAC;
-    volatile unsigned *PFB;
-    volatile unsigned *PFIFO;
-    volatile unsigned *PGRAPH;
-    volatile unsigned *PEXTDEV;
-    volatile unsigned *PTIMER;
-    volatile unsigned *PMC;
-    volatile unsigned *PRAMIN;
-    volatile unsigned *FIFO;
-    volatile unsigned *CURSOR;
-    volatile unsigned *CURSORPOS;
-    volatile unsigned *VBLANKENABLE;
-    volatile unsigned *VBLANK;
+    volatile U032 *PCRTC;
+    volatile U032 *PRAMDAC;
+    volatile U032 *PFB;
+    volatile U032 *PFIFO;
+    volatile U032 *PGRAPH;
+    volatile U032 *PEXTDEV;
+    volatile U032 *PTIMER;
+    volatile U032 *PMC;
+    volatile U032 *PRAMIN;
+    volatile U032 *FIFO;
+    volatile U032 *CURSOR;
+    volatile U032 *CURSORPOS;
+    volatile U032 *VBLANKENABLE;
+    volatile U032 *VBLANK;
+    volatile U008 *PCIO;
+    volatile U008 *PVIO;
+    volatile U008 *PDIO;
     /*
      * Common chip functions.
      */
@@ -274,10 +389,11 @@
     void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int);
     void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
     void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
-    void (*SetStartAddress)(struct _riva_hw_inst *,unsigned);
-    void (*SetSurfaces2D)(struct _riva_hw_inst *,unsigned,unsigned);
-    void (*SetSurfaces3D)(struct _riva_hw_inst *,unsigned,unsigned);
+    void (*SetStartAddress)(struct _riva_hw_inst *,U032);
+    void (*SetSurfaces2D)(struct _riva_hw_inst *,U032,U032);
+    void (*SetSurfaces3D)(struct _riva_hw_inst *,U032,U032);
     int  (*ShowHideCursor)(struct _riva_hw_inst *,int);
+    void (*LockUnlock)(struct _riva_hw_inst *, int);
     /*
      * Current extended mode settings.
      */
@@ -291,38 +407,40 @@
     RivaPixmap              *Pixmap;
     RivaScreenBlt           *Blt;
     RivaBitmap              *Bitmap;
+    RivaLine                *Line;
     RivaTexturedTriangle03  *Tri03;
+    RivaTexturedTriangle05  *Tri05;
 } RIVA_HW_INST;
 /*
  * Extended mode state information.
  */
 typedef struct _riva_hw_state
 {
-    unsigned bpp;
-    unsigned width;
-    unsigned height;
-    unsigned repaint0;
-    unsigned repaint1;
-    unsigned screen;
-    unsigned pixel;
-    unsigned horiz;
-    unsigned arbitration0;
-    unsigned arbitration1;
-    unsigned vpll;
-    unsigned pllsel;
-    unsigned general;
-    unsigned config;
-    unsigned cursor0;
-    unsigned cursor1;
-    unsigned cursor2;
-    unsigned offset0;
-    unsigned offset1;
-    unsigned offset2;
-    unsigned offset3;
-    unsigned pitch0;
-    unsigned pitch1;
-    unsigned pitch2;
-    unsigned pitch3;
+    U032 bpp;
+    U032 width;
+    U032 height;
+    U032 repaint0;
+    U032 repaint1;
+    U032 screen;
+    U032 pixel;
+    U032 horiz;
+    U032 arbitration0;
+    U032 arbitration1;
+    U032 vpll;
+    U032 pllsel;
+    U032 general;
+    U032 config;
+    U032 cursor0;
+    U032 cursor1;
+    U032 cursor2;
+    U032 offset0;
+    U032 offset1;
+    U032 offset2;
+    U032 offset3;
+    U032 pitch0;
+    U032 pitch1;
+    U032 pitch2;
+    U032 pitch3;
 } RIVA_HW_STATE;
 /*
  * External routines.
@@ -331,13 +449,12 @@
 /*
  * FIFO Free Count. Should attempt to yield processor if RIVA is busy.
  */
-#define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                                    \
-{                                                                           \
-while ((hwinst).FifoFreeCount < (cnt))                                      \
-{                                                                           \
-    (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2;                 \
-}                                                                           \
-(hwinst).FifoFreeCount -= (cnt);                                            \
+
+#define RIVA_FIFO_FREE(hwinst,hwptr,cnt)                           \
+{                                                                  \
+   while ((hwinst).FifoFreeCount < (cnt))                          \
+	(hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2;        \
+   (hwinst).FifoFreeCount -= (cnt);                                \
 }
 #endif /* __RIVA_HW_H__ */
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/riva_tbl.h linux/drivers/video/riva/riva_tbl.h
--- v2.4.1/linux/drivers/video/riva/riva_tbl.h	Wed Jul  5 10:56:12 2000
+++ linux/drivers/video/riva/riva_tbl.h	Tue Feb 13 13:15:05 2001
@@ -1,6 +1,6 @@
  /***************************************************************************\
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
 |*     international laws.  Users and possessors of this source code are     *|
@@ -11,7 +11,7 @@
 |*     tion and  internal comments to the code,  notices to the end user     *|
 |*     as follows:                                                           *|
 |*                                                                           *|
-|*       Copyright 1993-1998 NVIDIA, Corporation.  All rights reserved.      *|
+|*       Copyright 1993-1999 NVIDIA, Corporation.  All rights reserved.      *|
 |*                                                                           *|
 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
@@ -36,14 +36,15 @@
 |*     those rights set forth herein.                                        *|
 |*                                                                           *|
  \***************************************************************************/
-/* 
- * GPL licensing note -- nVidia is allowing a liberal interpretation of 
+
+/*
+ * GPL licensing note -- nVidia is allowing a liberal interpretation of
  * the documentation restriction above, to merely say that this nVidia's
- * copyright and disclaimer should be included with all code derived 
- * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99
+ * copyright and disclaimer should be included with all code derived
+ * from this source.  -- Jeff Garzik <jgarzik@mandrakesoft.com>, 01/Nov/99 
  */
 
-/* $XFree86: xc/programs/Xserver/hw/xfree86/vga256/drivers/nv/riva_tbl.h,v 1.1.2.2 1998/12/22 16:33:20 hohndel Exp $ */
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_tbl.h,v 1.5 2000/02/08 17:19:12 dawes Exp $ */
 /*
  * RIVA Fixed Functionality Init Tables.
  */
@@ -60,8 +61,6 @@
     {0x00000050, 0x00000000},
     {0x00000040, 0xFFFFFFFF}
 };
-
-#if 0
 static unsigned RivaTableFIFO[][2] =
 {
     {0x00000000, 0x80000000},
@@ -72,8 +71,6 @@
     {0x00002800, 0x80000012},
     {0x00003800, 0x80000013}
 };
-#endif
-
 static unsigned nv3TablePFIFO[][2] =
 {
     {0x00000140, 0x00000000},
@@ -161,6 +158,14 @@
     {0x00000205, 0x00C50342},
     {0x00000208, 0x80000002},
     {0x00000209, 0x00C60343},
+    {0x0000020C, 0x80000003},
+    {0x0000020D, 0x00DC0348},
+    {0x00000210, 0x80000004},
+    {0x00000211, 0x00DC0349},
+    {0x00000214, 0x80000005},
+    {0x00000215, 0x00DC034A},
+    {0x00000218, 0x80000006},
+    {0x00000219, 0x00DC034B},
     {0x00000240, 0x80000010},
     {0x00000241, 0x00D10344},
     {0x00000244, 0x80000011},
@@ -189,13 +194,31 @@
     {0x00000D1B, 0x00000000},
     {0x00000D1D, 0x00000140},
     {0x00000D1E, 0x00000000},
-    {0x00000D1F, 0x00000000}
+    {0x00000D1F, 0x00000000},
+    {0x00000D20, 0x10100200},
+    {0x00000D21, 0x00000000},
+    {0x00000D22, 0x00000000},
+    {0x00000D23, 0x00000000},
+    {0x00000D24, 0x10210200},
+    {0x00000D25, 0x00000000},
+    {0x00000D26, 0x00000000},
+    {0x00000D27, 0x00000000},
+    {0x00000D28, 0x10420200},
+    {0x00000D29, 0x00000000},
+    {0x00000D2A, 0x00000000},
+    {0x00000D2B, 0x00000000},
+    {0x00000D2C, 0x10830200},
+    {0x00000D2D, 0x00000000},
+    {0x00000D2E, 0x00000000},
+    {0x00000D2F, 0x00000000} 
 };
 static unsigned nv3TablePRAMIN_8BPP[][2] =
 {
+    /*           0xXXXXX3XX For  MSB mono format */
+    /*           0xXXXXX2XX For  LSB mono format */
     {0x00000D04, 0x10110203},
     {0x00000D08, 0x10110203},
-    {0x00000D0C, 0x10110203},
+    {0x00000D0C, 0x1011020B},
     {0x00000D10, 0x10118203},
     {0x00000D14, 0x10110203},
     {0x00000D18, 0x10110203},
@@ -203,9 +226,11 @@
 };
 static unsigned nv3TablePRAMIN_15BPP[][2] =
 {
+    /*           0xXXXXX2XX For  MSB mono format */
+    /*           0xXXXXX3XX For  LSB mono format */
     {0x00000D04, 0x10110200},
     {0x00000D08, 0x10110200},
-    {0x00000D0C, 0x10110200},
+    {0x00000D0C, 0x10110208},
     {0x00000D10, 0x10118200},
     {0x00000D14, 0x10110200},
     {0x00000D18, 0x10110200},
@@ -213,19 +238,27 @@
 };
 static unsigned nv3TablePRAMIN_32BPP[][2] =
 {
+    /*           0xXXXXX3XX For  MSB mono format */
+    /*           0xXXXXX2XX For  LSB mono format */
     {0x00000D04, 0x10110201},
     {0x00000D08, 0x10110201},
-    {0x00000D0C, 0x10110201},
+    {0x00000D0C, 0x10110209},
     {0x00000D10, 0x10118201},
     {0x00000D14, 0x10110201},
     {0x00000D18, 0x10110201},
     {0x00000D1C, 0x10419208}
 };
+static unsigned nv4TableFIFO[][2] =
+{
+    {0x00003800, 0x80000014}
+};
 static unsigned nv4TablePFIFO[][2] =
 {
     {0x00000140, 0x00000000},
     {0x00000480, 0x00000000},
     {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x0000048B, 0x00000000},
     {0x00000400, 0x00000000},
     {0x00000414, 0x00000000},
     {0x00000084, 0x03000100},  
@@ -284,45 +317,44 @@
     {0x0000005A, 0x00000000},
     {0x0000005B, 0x00000000},
     {0x00000196, 0x00000000},
-    {0x000001A1, 0x00FFFFFF},
+    {0x000001A1, 0x01FFFFFF},
     {0x00000197, 0x00000000},
-    {0x000001A2, 0x00FFFFFF},
+    {0x000001A2, 0x01FFFFFF},
     {0x00000198, 0x00000000},
-    {0x000001A3, 0x00FFFFFF},
+    {0x000001A3, 0x01FFFFFF},
     {0x00000199, 0x00000000},
-    {0x000001A4, 0x00FFFFFF},
+    {0x000001A4, 0x01FFFFFF},
     {0x00000050, 0x00000000},
     {0x00000040, 0xFFFFFFFF},
     {0x0000005C, 0x10010100},
-    {0x000001C8, 0x00000001}
+    {0x000001C4, 0xFFFFFFFF},
+    {0x000001C8, 0x00000001},
+    {0x00000204, 0x00000000},
+    {0x000001C3, 0x00000001}
 };
 static unsigned nv4TablePGRAPH_8BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x00111111},
     {0x00000186, 0x00001010},
-    {0x0000020C, 0x01010101}
+    {0x0000020C, 0x03020202}
 };
 static unsigned nv4TablePGRAPH_15BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x00226222},
     {0x00000186, 0x00002071},
-    {0x0000020C, 0x09090909}
+    {0x0000020C, 0x09080808}
 };
 static unsigned nv4TablePGRAPH_16BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x00556555},
     {0x00000186, 0x000050C2},
-    {0x0000020C, 0x0C0C0C0C}
+    {0x0000020C, 0x0C0B0B0B}
 };
 static unsigned nv4TablePGRAPH_32BPP[][2] =
 {
-    {0x000001C4, 0xFFFFFFFF},
     {0x000001C9, 0x0077D777},
     {0x00000186, 0x000070E5},
-    {0x0000020C, 0x07070707}
+    {0x0000020C, 0x0E0D0D0D}
 };
 static unsigned nv4TablePRAMIN[][2] =
 {
@@ -334,14 +366,26 @@
     {0x00000005, 0x80011147},
     {0x00000006, 0x80000013},
     {0x00000007, 0x80011148},
+    {0x00000008, 0x80000014},
+    {0x00000009, 0x80011149},
+    {0x0000000A, 0x80000015},
+    {0x0000000B, 0x8001114A},
     {0x00000020, 0x80000000},
     {0x00000021, 0x80011142},
     {0x00000022, 0x80000001},
     {0x00000023, 0x80011143},
     {0x00000024, 0x80000002},
     {0x00000025, 0x80011144}, 
+    {0x00000026, 0x80000003},
+    {0x00000027, 0x8001114B},
+    {0x00000028, 0x80000004},
+    {0x00000029, 0x8001114C},
+    {0x0000002A, 0x80000005},
+    {0x0000002B, 0x8001114D},
+    {0x0000002C, 0x80000006},
+    {0x0000002D, 0x8001114E},
     {0x00000500, 0x00003000},
-    {0x00000501, 0x02FFFFFF},
+    {0x00000501, 0x01FFFFFF},
     {0x00000502, 0x00000002},
     {0x00000503, 0x00000002},
     {0x00000508, 0x01008043},
@@ -350,57 +394,558 @@
     {0x0000050C, 0x01008019},
     {0x0000050E, 0x00000000},
     {0x0000050F, 0x00000000},
+#if 1
     {0x00000510, 0x01008018},
+#else
+    {0x00000510, 0x01008044},
+#endif
     {0x00000512, 0x00000000},
     {0x00000513, 0x00000000},
-    {0x00000514, 0x0100A033},
+    {0x00000514, 0x01008021},
     {0x00000516, 0x00000000},
     {0x00000517, 0x00000000},
     {0x00000518, 0x0100805F},
     {0x0000051A, 0x00000000},
     {0x0000051B, 0x00000000},
+#if 1
     {0x0000051C, 0x0100804B},
+#else
+    {0x0000051C, 0x0100804A},
+#endif
     {0x0000051E, 0x00000000},
     {0x0000051F, 0x00000000},
     {0x00000520, 0x0100A048},
     {0x00000521, 0x00000D01},
     {0x00000522, 0x11401140},
-    {0x00000523, 0x00000000}
+    {0x00000523, 0x00000000},
+    {0x00000524, 0x0300A054},
+    {0x00000525, 0x00000D01},
+    {0x00000526, 0x11401140},
+    {0x00000527, 0x00000000},
+    {0x00000528, 0x0300A055},
+    {0x00000529, 0x00000D01},
+    {0x0000052A, 0x11401140},
+    {0x0000052B, 0x00000000},
+    {0x0000052C, 0x00000058},
+    {0x0000052E, 0x11401140},
+    {0x0000052F, 0x00000000},
+    {0x00000530, 0x00000059},
+    {0x00000532, 0x11401140},
+    {0x00000533, 0x00000000},
+    {0x00000534, 0x0000005A},
+    {0x00000536, 0x11401140},
+    {0x00000537, 0x00000000},
+    {0x00000538, 0x0000005B},
+    {0x0000053A, 0x11401140},
+    {0x0000053B, 0x00000000} 
 };
 static unsigned nv4TablePRAMIN_8BPP[][2] =
 {
-    {0x00000509, 0x00000301},
-    {0x0000050D, 0x00000301},
-    {0x00000511, 0x00000301},
-    {0x00000515, 0x00000301},
-    {0x00000519, 0x00000301},
-    {0x0000051D, 0x00000301}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000302},
+    {0x0000050D, 0x00000302},
+    {0x00000511, 0x00000202},
+    {0x00000515, 0x00000302},
+    {0x00000519, 0x00000302},
+    {0x0000051D, 0x00000302},
+    {0x0000052D, 0x00000302},
+    {0x0000052E, 0x00000302},
+    {0x00000535, 0x00000000},
+    {0x00000539, 0x00000000} 
 };
 static unsigned nv4TablePRAMIN_15BPP[][2] =
 {
-    {0x00000509, 0x00000901},
-    {0x0000050D, 0x00000901},
-    {0x00000511, 0x00000901},
-    {0x00000515, 0x00000901},
-    {0x00000519, 0x00000901},
-    {0x0000051D, 0x00000901}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000902},
+    {0x0000050D, 0x00000902},
+    {0x00000511, 0x00000802},
+    {0x00000515, 0x00000902},
+    {0x00000519, 0x00000902},
+    {0x0000051D, 0x00000902},
+    {0x0000052D, 0x00000902},
+    {0x0000052E, 0x00000902},
+    {0x00000535, 0x00000702},
+    {0x00000539, 0x00000702} 
 };
 static unsigned nv4TablePRAMIN_16BPP[][2] =
 {
-    {0x00000509, 0x00000C01},
-    {0x0000050D, 0x00000C01},
-    {0x00000511, 0x00000C01},
-    {0x00000515, 0x00000C01},
-    {0x00000519, 0x00000C01},
-    {0x0000051D, 0x00000C01}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000C02},
+    {0x0000050D, 0x00000C02},
+    {0x00000511, 0x00000B02},
+    {0x00000515, 0x00000C02},
+    {0x00000519, 0x00000C02},
+    {0x0000051D, 0x00000C02},
+    {0x0000052D, 0x00000C02},
+    {0x0000052E, 0x00000C02},
+    {0x00000535, 0x00000702},
+    {0x00000539, 0x00000702} 
 };
 static unsigned nv4TablePRAMIN_32BPP[][2] =
 {
-    {0x00000509, 0x00000E01},
-    {0x0000050D, 0x00000E01},
-    {0x00000511, 0x00000E01},
-    {0x00000515, 0x00000E01},
-    {0x00000519, 0x00000E01},
-    {0x0000051D, 0x00000E01}
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000E02},
+    {0x0000050D, 0x00000E02},
+    {0x00000511, 0x00000D02},
+    {0x00000515, 0x00000E02},
+    {0x00000519, 0x00000E02},
+    {0x0000051D, 0x00000E02},
+    {0x0000052D, 0x00000E02},
+    {0x0000052E, 0x00000E02},
+    {0x00000535, 0x00000E02},
+    {0x00000539, 0x00000E02} 
+};
+static unsigned nv10TableFIFO[][2] =
+{
+    {0x00003800, 0x80000014}
+};
+static unsigned nv10TablePFIFO[][2] =
+{
+    {0x00000140, 0x00000000},
+    {0x00000480, 0x00000000},
+    {0x00000494, 0x00000000},
+    {0x00000481, 0x00000000},
+    {0x0000048B, 0x00000000},
+    {0x00000400, 0x00000000},
+    {0x00000414, 0x00000000},
+    {0x00000084, 0x03000100},
+    {0x00000085, 0x00000110},
+    {0x00000086, 0x00000112},
+    {0x00000143, 0x0000FFFF},
+    {0x00000496, 0x0000FFFF},
+    {0x00000050, 0x00000000},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000415, 0x00000001},
+    {0x00000480, 0x00000001},
+    {0x00000494, 0x00000001},
+    {0x00000495, 0x00000001},
+    {0x00000140, 0x00000001}
+};
+static unsigned nv10TablePGRAPH[][2] =
+{
+    {0x00000020, 0x0003FFFF},
+    {0x00000021, 0x00118701},
+    {0x00000022, 0x24F82AD9},
+    {0x00000023, 0x55DE0030},
+    {0x00000020, 0x00000000},
+    {0x00000024, 0x00000000},
+    {0x00000058, 0x00000000},
+    {0x00000060, 0x00000000},
+    {0x00000068, 0x00000000},
+    {0x00000070, 0x00000000},
+    {0x00000078, 0x00000000},
+    {0x00000059, 0x00000000},
+    {0x00000061, 0x00000000},
+    {0x00000069, 0x00000000},
+    {0x00000071, 0x00000000},
+    {0x00000079, 0x00000000},
+    {0x0000005A, 0x00000000},
+    {0x00000062, 0x00000000},
+    {0x0000006A, 0x00000000},
+    {0x00000072, 0x00000000},
+    {0x0000007A, 0x00000000},
+    {0x0000005B, 0x00000000},
+    {0x00000063, 0x00000000},
+    {0x0000006B, 0x00000000},
+    {0x00000073, 0x00000000},
+    {0x0000007B, 0x00000000},
+    {0x0000005C, 0x00000000},
+    {0x00000064, 0x00000000},
+    {0x0000006C, 0x00000000},
+    {0x00000074, 0x00000000},
+    {0x0000007C, 0x00000000},
+    {0x0000005D, 0x00000000},
+    {0x00000065, 0x00000000},
+    {0x0000006D, 0x00000000},
+    {0x00000075, 0x00000000},
+    {0x0000007D, 0x00000000},
+    {0x0000005E, 0x00000000},
+    {0x00000066, 0x00000000},
+    {0x0000006E, 0x00000000},
+    {0x00000076, 0x00000000},
+    {0x0000007E, 0x00000000},
+    {0x0000005F, 0x00000000},
+    {0x00000067, 0x00000000},
+    {0x0000006F, 0x00000000},
+    {0x00000077, 0x00000000},
+    {0x0000007F, 0x00000000},
+    {0x00000053, 0x00000000},
+    {0x00000054, 0x00000000},
+    {0x00000055, 0x00000000},
+    {0x00000056, 0x00000000},
+    {0x00000057, 0x00000000},
+    {0x00000196, 0x00000000},
+    {0x000001A1, 0x01FFFFFF},
+    {0x00000197, 0x00000000},
+    {0x000001A2, 0x01FFFFFF},
+    {0x00000198, 0x00000000},
+    {0x000001A3, 0x01FFFFFF},
+    {0x00000199, 0x00000000},
+    {0x000001A4, 0x01FFFFFF},
+    {0x0000019A, 0x00000000},
+    {0x000001A5, 0x01FFFFFF},
+    {0x0000019B, 0x00000000},
+    {0x000001A6, 0x01FFFFFF},
+    {0x00000050, 0x01111111},
+    {0x00000040, 0xFFFFFFFF},
+    {0x00000051, 0x10010100},
+    {0x000001C5, 0xFFFFFFFF},
+    {0x000001C8, 0x00000001},
+    {0x00000204, 0x00000000},
+    {0x000001C4, 0x00000001}
+};
+static unsigned nv10TablePGRAPH_8BPP[][2] =
+{
+    {0x000001C9, 0x00111111},
+    {0x00000186, 0x00001010},
+    {0x0000020C, 0x03020202}
+};
+static unsigned nv10TablePGRAPH_15BPP[][2] =
+{
+    {0x000001C9, 0x00226222},
+    {0x00000186, 0x00002071},
+    {0x0000020C, 0x09080808}
+};
+static unsigned nv10TablePGRAPH_16BPP[][2] =
+{
+    {0x000001C9, 0x00556555},
+    {0x00000186, 0x000050C2},
+    {0x0000020C, 0x000B0B0C}
+};
+static unsigned nv10TablePGRAPH_32BPP[][2] =
+{
+    {0x000001C9, 0x0077D777},
+    {0x00000186, 0x000070E5},
+    {0x0000020C, 0x0E0D0D0D}
+};
+static unsigned nv10tri05TablePGRAPH[][2] =
+{
+    {(0x00000E00/4), 0x00000000},
+    {(0x00000E04/4), 0x00000000},
+    {(0x00000E08/4), 0x00000000},
+    {(0x00000E0C/4), 0x00000000},
+    {(0x00000E10/4), 0x00001000},
+    {(0x00000E14/4), 0x00001000},
+    {(0x00000E18/4), 0x4003ff80},
+    {(0x00000E1C/4), 0x00000000},
+    {(0x00000E20/4), 0x00000000},
+    {(0x00000E24/4), 0x00000000},
+    {(0x00000E28/4), 0x00000000},
+    {(0x00000E2C/4), 0x00000000},
+    {(0x00000E30/4), 0x00080008},
+    {(0x00000E34/4), 0x00080008},
+    {(0x00000E38/4), 0x00000000},
+    {(0x00000E3C/4), 0x00000000},
+    {(0x00000E40/4), 0x00000000},
+    {(0x00000E44/4), 0x00000000},
+    {(0x00000E48/4), 0x00000000},
+    {(0x00000E4C/4), 0x00000000},
+    {(0x00000E50/4), 0x00000000},
+    {(0x00000E54/4), 0x00000000},
+    {(0x00000E58/4), 0x00000000},
+    {(0x00000E5C/4), 0x00000000},
+    {(0x00000E60/4), 0x00000000},
+    {(0x00000E64/4), 0x10000000},
+    {(0x00000E68/4), 0x00000000},
+    {(0x00000E6C/4), 0x00000000},
+    {(0x00000E70/4), 0x00000000},
+    {(0x00000E74/4), 0x00000000},
+    {(0x00000E78/4), 0x00000000},
+    {(0x00000E7C/4), 0x00000000},
+    {(0x00000E80/4), 0x00000000},
+    {(0x00000E84/4), 0x00000000},
+    {(0x00000E88/4), 0x08000000},
+    {(0x00000E8C/4), 0x00000000},
+    {(0x00000E90/4), 0x00000000},
+    {(0x00000E94/4), 0x00000000},
+    {(0x00000E98/4), 0x00000000},
+    {(0x00000E9C/4), 0x4B7FFFFF},
+    {(0x00000EA0/4), 0x00000000},
+    {(0x00000EA4/4), 0x00000000},
+    {(0x00000EA8/4), 0x00000000},
+    {(0x00000F00/4), 0x07FF0800},
+    {(0x00000F04/4), 0x07FF0800},
+    {(0x00000F08/4), 0x07FF0800},
+    {(0x00000F0C/4), 0x07FF0800},
+    {(0x00000F10/4), 0x07FF0800},
+    {(0x00000F14/4), 0x07FF0800},
+    {(0x00000F18/4), 0x07FF0800},
+    {(0x00000F1C/4), 0x07FF0800},
+    {(0x00000F20/4), 0x07FF0800},
+    {(0x00000F24/4), 0x07FF0800},
+    {(0x00000F28/4), 0x07FF0800},
+    {(0x00000F2C/4), 0x07FF0800},
+    {(0x00000F30/4), 0x07FF0800},
+    {(0x00000F34/4), 0x07FF0800},
+    {(0x00000F38/4), 0x07FF0800},
+    {(0x00000F3C/4), 0x07FF0800},
+    {(0x00000F40/4), 0x10000000},
+    {(0x00000F44/4), 0x00000000},
+    {(0x00000F50/4), 0x00006740},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006750},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F54/4), 0x40000000},
+    {(0x00000F50/4), 0x00006760},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006770},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006780},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000067A0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AB0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AC0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006C10},
+    {(0x00000F54/4), 0xBF800000},
+    {(0x00000F50/4), 0x00007030},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007040},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007050},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007060},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007070},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007080},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00007090},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x000070A0},
+    {(0x00000F54/4), 0x7149F2CA},
+    {(0x00000F50/4), 0x00006A80},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x00006AA0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00000040},
+    {(0x00000F54/4), 0x00000005},
+    {(0x00000F50/4), 0x00006400},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x4B7FFFFF},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006410},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006420},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x00006430},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064C0},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F54/4), 0x477FFFFF},
+    {(0x00000F54/4), 0x3F800000},
+    {(0x00000F50/4), 0x000064D0},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0xC5000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064E0},
+    {(0x00000F54/4), 0xC4FFF000},
+    {(0x00000F54/4), 0xC4FFF000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F50/4), 0x000064F0},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F54/4), 0x00000000},
+    {(0x00000F40/4), 0x30000000},
+    {(0x00000F44/4), 0x00000004},
+    {(0x00000F48/4), 0x10000000},
+    {(0x00000F4C/4), 0x00000000}
+};
+static unsigned nv10TablePRAMIN[][2] =
+{
+    {0x00000000, 0x80000010},
+    {0x00000001, 0x80011145},
+    {0x00000002, 0x80000011},
+    {0x00000003, 0x80011146},
+    {0x00000004, 0x80000012},
+    {0x00000005, 0x80011147},
+    {0x00000006, 0x80000013},
+    {0x00000007, 0x80011148},
+    {0x00000008, 0x80000014},
+    {0x00000009, 0x80011149},
+    {0x0000000A, 0x80000015},
+    {0x0000000B, 0x8001114A},
+    {0x00000020, 0x80000000},
+    {0x00000021, 0x80011142},
+    {0x00000022, 0x80000001},
+    {0x00000023, 0x80011143},
+    {0x00000024, 0x80000002},
+    {0x00000025, 0x80011144},
+    {0x00000026, 0x80000003},
+    {0x00000027, 0x8001114B},
+    {0x00000028, 0x80000004},
+    {0x00000029, 0x8001114C},
+    {0x0000002A, 0x80000005},
+    {0x0000002B, 0x8001114D},
+    {0x0000002C, 0x80000006},
+    {0x0000002D, 0x8001114E},
+    {0x0000002E, 0x80000007},
+    {0x0000002F, 0x8001114F},
+    {0x00000500, 0x00003000},
+    {0x00000501, 0x01FFFFFF},
+    {0x00000502, 0x00000002},
+    {0x00000503, 0x00000002},
+    {0x00000508, 0x01008043},
+    {0x0000050A, 0x00000000},
+    {0x0000050B, 0x00000000},
+    {0x0000050C, 0x01008019},
+    {0x0000050E, 0x00000000},
+    {0x0000050F, 0x00000000},
+#if 1
+    {0x00000510, 0x01008018},
+#else
+    {0x00000510, 0x01008044},
+#endif
+    {0x00000512, 0x00000000},
+    {0x00000513, 0x00000000},
+    {0x00000514, 0x01008021},
+    {0x00000516, 0x00000000},
+    {0x00000517, 0x00000000},
+    {0x00000518, 0x0100805F},
+    {0x0000051A, 0x00000000},
+    {0x0000051B, 0x00000000},
+#if 1
+    {0x0000051C, 0x0100804B},
+#else
+    {0x0000051C, 0x0100804A},
+#endif
+    {0x0000051E, 0x00000000},
+    {0x0000051F, 0x00000000},
+    {0x00000520, 0x0100A048},
+    {0x00000521, 0x00000D01},
+    {0x00000522, 0x11401140},
+    {0x00000523, 0x00000000},
+    {0x00000524, 0x0300A094},
+    {0x00000525, 0x00000D01},
+    {0x00000526, 0x11401140},
+    {0x00000527, 0x00000000},
+    {0x00000528, 0x0300A095},
+    {0x00000529, 0x00000D01},
+    {0x0000052A, 0x11401140},
+    {0x0000052B, 0x00000000},
+    {0x0000052C, 0x00000058},
+    {0x0000052E, 0x11401140},
+    {0x0000052F, 0x00000000},
+    {0x00000530, 0x00000059},
+    {0x00000532, 0x11401140},
+    {0x00000533, 0x00000000},
+    {0x00000534, 0x0000005A},
+    {0x00000536, 0x11401140},
+    {0x00000537, 0x00000000},
+    {0x00000538, 0x0000005B},
+    {0x0000053A, 0x11401140},
+    {0x0000053B, 0x00000000},
+    {0x0000053C, 0x00000093},
+    {0x0000053E, 0x11401140},
+    {0x0000053F, 0x00000000} 
+};
+static unsigned nv10TablePRAMIN_8BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000302},
+    {0x0000050D, 0x00000302},
+    {0x00000511, 0x00000202},
+    {0x00000515, 0x00000302},
+    {0x00000519, 0x00000302},
+    {0x0000051D, 0x00000302},
+    {0x0000052D, 0x00000302},
+    {0x0000052E, 0x00000302},
+    {0x00000535, 0x00000000},
+    {0x00000539, 0x00000000},
+    {0x0000053D, 0x00000000} 
+};
+static unsigned nv10TablePRAMIN_15BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000902},
+    {0x0000050D, 0x00000902},
+    {0x00000511, 0x00000802},
+    {0x00000515, 0x00000902},
+    {0x00000519, 0x00000902},
+    {0x0000051D, 0x00000902},
+    {0x0000052D, 0x00000902},
+    {0x0000052E, 0x00000902},
+    {0x00000535, 0x00000902},
+    {0x00000539, 0x00000902}, 
+    {0x0000053D, 0x00000902} 
+};
+static unsigned nv10TablePRAMIN_16BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000C02},
+    {0x0000050D, 0x00000C02},
+    {0x00000511, 0x00000B02},
+    {0x00000515, 0x00000C02},
+    {0x00000519, 0x00000C02},
+    {0x0000051D, 0x00000C02},
+    {0x0000052D, 0x00000C02},
+    {0x0000052E, 0x00000C02},
+    {0x00000535, 0x00000C02},
+    {0x00000539, 0x00000C02},
+    {0x0000053D, 0x00000C02} 
+};
+static unsigned nv10TablePRAMIN_32BPP[][2] =
+{
+    /*           0xXXXXXX01 For  MSB mono format */
+    /*           0xXXXXXX02 For  LSB mono format */
+    {0x00000509, 0x00000E02},
+    {0x0000050D, 0x00000E02},
+    {0x00000511, 0x00000D02},
+    {0x00000515, 0x00000E02},
+    {0x00000519, 0x00000E02},
+    {0x0000051D, 0x00000E02},
+    {0x0000052D, 0x00000E02},
+    {0x0000052E, 0x00000E02},
+    {0x00000535, 0x00000E02},
+    {0x00000539, 0x00000E02},
+    {0x0000053D, 0x00000E02} 
 };
 
diff -u --recursive --new-file v2.4.1/linux/drivers/video/riva/rivafb.h linux/drivers/video/riva/rivafb.h
--- v2.4.1/linux/drivers/video/riva/rivafb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/riva/rivafb.h	Sat Feb  3 12:48:00 2001
@@ -0,0 +1,85 @@
+#ifndef __RIVAFB_H
+#define __RIVAFB_H
+
+#include <linux/config.h>
+#include <linux/fb.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb4.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb32.h>
+#include "riva_hw.h"
+
+/* GGI compatibility macros */
+#define NUM_SEQ_REGS		0x05
+#define NUM_CRT_REGS		0x41
+#define NUM_GRC_REGS		0x09
+#define NUM_ATC_REGS		0x15
+
+/* holds the state of the VGA core and extended Riva hw state from riva_hw.c.
+ * From KGI originally. */
+struct riva_regs {
+	u8 attr[NUM_ATC_REGS];
+	u8 crtc[NUM_CRT_REGS];
+	u8 gra[NUM_GRC_REGS];
+	u8 seq[NUM_SEQ_REGS];
+	u8 misc_output;
+	RIVA_HW_STATE ext;
+};
+
+typedef struct {
+	unsigned char red, green, blue, transp;
+} riva_cfb8_cmap_t;
+
+struct rivafb_info;
+struct rivafb_info {
+	struct fb_info info;	/* kernel framebuffer info */
+
+	RIVA_HW_INST riva;	/* interface to riva_hw.c */
+
+	const char *drvr_name;	/* Riva hardware board type */
+
+	unsigned long ctrl_base_phys;	/* physical control register base addr */
+	unsigned long fb_base_phys;	/* physical framebuffer base addr */
+
+	caddr_t ctrl_base;	/* virtual control register base addr */
+	caddr_t fb_base;	/* virtual framebuffer base addr */
+
+	unsigned ram_amount;	/* amount of RAM on card, in bytes */
+	unsigned dclk_max;	/* max DCLK */
+
+	struct riva_regs initial_state;	/* initial startup video mode */
+	struct riva_regs current_state;
+
+	struct display disp;
+	int currcon;
+	struct display *currcon_display;
+
+	struct rivafb_info *next;
+
+	struct pci_dev *pd;	/* pointer to board's pci info */
+	unsigned base0_region_size;	/* size of control register region */
+	unsigned base1_region_size;	/* size of framebuffer region */
+
+	struct riva_cursor *cursor;
+
+	struct display_switch dispsw;
+
+	riva_cfb8_cmap_t palette[256];	/* VGA DAC palette cache */
+
+#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
+	union {
+#ifdef FBCON_HAS_CFB16
+		u_int16_t cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u_int32_t cfb32[16];
+#endif
+	} con_cmap;
+#endif				/* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
+#ifdef CONFIG_MTRR
+	struct { int vram; int vram_valid; } mtrr;
+#endif
+};
+
+#endif /* __RIVAFB_H */
\ No newline at end of file
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sa1100fb.c linux/drivers/video/sa1100fb.c
--- v2.4.1/linux/drivers/video/sa1100fb.c	Mon Sep 18 15:15:22 2000
+++ linux/drivers/video/sa1100fb.c	Fri Feb  9 11:30:23 2001
@@ -65,7 +65,7 @@
 #include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.4.1/linux/drivers/video/sbusfb.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/video/sbusfb.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sgivwfb.c linux/drivers/video/sgivwfb.c
--- v2.4.1/linux/drivers/video/sgivwfb.c	Sun Aug  6 11:25:46 2000
+++ linux/drivers/video/sgivwfb.c	Fri Feb  9 11:30:23 2001
@@ -16,7 +16,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sis/sis_main.c linux/drivers/video/sis/sis_main.c
--- v2.4.1/linux/drivers/video/sis/sis_main.c	Sun Nov 12 20:40:42 2000
+++ linux/drivers/video/sis/sis_main.c	Fri Feb  9 11:30:23 2001
@@ -18,7 +18,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/skeletonfb.c linux/drivers/video/skeletonfb.c
--- v2.4.1/linux/drivers/video/skeletonfb.c	Wed Jul 26 11:08:41 2000
+++ linux/drivers/video/skeletonfb.c	Fri Feb  9 11:30:23 2001
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sticon-bmode.c linux/drivers/video/sticon-bmode.c
--- v2.4.1/linux/drivers/video/sticon-bmode.c	Wed Dec  6 11:46:39 2000
+++ linux/drivers/video/sticon-bmode.c	Fri Feb  9 11:30:23 2001
@@ -67,7 +67,7 @@
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/kd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/ioport.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sticore.c linux/drivers/video/sticore.c
--- v2.4.1/linux/drivers/video/sticore.c	Wed Dec  6 11:46:39 2000
+++ linux/drivers/video/sticore.c	Fri Feb  9 11:30:23 2001
@@ -1,7 +1,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/stifb.c linux/drivers/video/stifb.c
--- v2.4.1/linux/drivers/video/stifb.c	Tue Dec  5 12:29:39 2000
+++ linux/drivers/video/stifb.c	Fri Feb  9 11:30:23 2001
@@ -28,7 +28,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/sun3fb.c linux/drivers/video/sun3fb.c
--- v2.4.1/linux/drivers/video/sun3fb.c	Thu Oct 12 11:18:36 2000
+++ linux/drivers/video/sun3fb.c	Fri Feb  9 11:30:23 2001
@@ -32,7 +32,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/tcxfb.c linux/drivers/video/tcxfb.c
--- v2.4.1/linux/drivers/video/tcxfb.c	Mon Dec 20 22:06:42 1999
+++ linux/drivers/video/tcxfb.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: tcxfb.c,v 1.11 1999/11/19 09:57:21 davem Exp $
+/* $Id: tcxfb.c,v 1.12 2001/02/13 01:17:15 davem Exp $
  * tcxfb.c: TCX 24/8bit frame buffer driver
  *
  * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/tdfxfb.c linux/drivers/video/tdfxfb.c
--- v2.4.1/linux/drivers/video/tdfxfb.c	Sun Dec  3 17:45:24 2000
+++ linux/drivers/video/tdfxfb.c	Fri Feb  9 11:30:23 2001
@@ -61,7 +61,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/tgafb.c linux/drivers/video/tgafb.c
--- v2.4.1/linux/drivers/video/tgafb.c	Tue Nov  7 10:59:43 2000
+++ linux/drivers/video/tgafb.c	Fri Feb  9 11:30:23 2001
@@ -34,7 +34,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/valkyriefb.c linux/drivers/video/valkyriefb.c
--- v2.4.1/linux/drivers/video/valkyriefb.c	Sun Sep 17 09:48:05 2000
+++ linux/drivers/video/valkyriefb.c	Fri Feb  9 11:30:23 2001
@@ -44,7 +44,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/vesafb.c linux/drivers/video/vesafb.c
--- v2.4.1/linux/drivers/video/vesafb.c	Mon Oct 16 12:37:52 2000
+++ linux/drivers/video/vesafb.c	Fri Feb  9 11:30:23 2001
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/vfb.c linux/drivers/video/vfb.c
--- v2.4.1/linux/drivers/video/vfb.c	Sat Feb  3 19:51:30 2001
+++ linux/drivers/video/vfb.c	Fri Feb  9 11:30:23 2001
@@ -14,7 +14,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/vga16fb.c linux/drivers/video/vga16fb.c
--- v2.4.1/linux/drivers/video/vga16fb.c	Wed Jul 26 11:08:41 2000
+++ linux/drivers/video/vga16fb.c	Fri Feb  9 11:30:23 2001
@@ -15,7 +15,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/console.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/vgacon.c linux/drivers/video/vgacon.c
--- v2.4.1/linux/drivers/video/vgacon.c	Tue Nov 28 22:34:31 2000
+++ linux/drivers/video/vgacon.c	Fri Feb  9 11:30:23 2001
@@ -43,7 +43,7 @@
 #include <linux/console_struct.h>
 #include <linux/string.h>
 #include <linux/kd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vt_kern.h>
 #include <linux/selection.h>
 #include <linux/spinlock.h>
diff -u --recursive --new-file v2.4.1/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.4.1/linux/drivers/video/virgefb.c	Tue Nov  7 10:59:43 2000
+++ linux/drivers/video/virgefb.c	Fri Feb  9 11:30:23 2001
@@ -22,7 +22,7 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/tty.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/zorro.h>
 #include <linux/fb.h>
diff -u --recursive --new-file v2.4.1/linux/fs/adfs/super.c linux/fs/adfs/super.c
--- v2.4.1/linux/fs/adfs/super.c	Mon Sep 18 15:14:06 2000
+++ linux/fs/adfs/super.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/adfs_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.4.1/linux/fs/affs/file.c linux/fs/affs/file.c
--- v2.4.1/linux/fs/affs/file.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/affs/file.c	Fri Feb  9 11:29:44 2001
@@ -21,7 +21,7 @@
 #include <linux/fcntl.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/fs/affs/inode.c linux/fs/affs/inode.c
--- v2.4.1/linux/fs/affs/inode.c	Thu Nov 16 13:18:26 2000
+++ linux/fs/affs/inode.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <asm/div64.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/affs_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/affs/super.c linux/fs/affs/super.c
--- v2.4.1/linux/fs/affs/super.c	Tue Sep  5 14:07:29 2000
+++ linux/fs/affs/super.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/sched.h>
 #include <linux/affs_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/autofs/autofs_i.h linux/fs/autofs/autofs_i.h
--- v2.4.1/linux/fs/autofs/autofs_i.h	Mon Dec 11 13:27:15 2000
+++ linux/fs/autofs/autofs_i.h	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #define AUTOFS_IOC_COUNT     32
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/wait.h>
diff -u --recursive --new-file v2.4.1/linux/fs/autofs/inode.c linux/fs/autofs/inode.c
--- v2.4.1/linux/fs/autofs/inode.c	Fri Nov 17 11:35:27 2000
+++ linux/fs/autofs/inode.c	Fri Feb  9 11:29:44 2001
@@ -11,7 +11,7 @@
  * ------------------------------------------------------------------------- */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/locks.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/fs/autofs/waitq.c linux/fs/autofs/waitq.c
--- v2.4.1/linux/fs/autofs/waitq.c	Fri Sep  1 14:35:04 2000
+++ linux/fs/autofs/waitq.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
  *
  * ------------------------------------------------------------------------- */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/fs/autofs4/autofs_i.h linux/fs/autofs4/autofs_i.h
--- v2.4.1/linux/fs/autofs4/autofs_i.h	Thu Jan  4 14:50:54 2001
+++ linux/fs/autofs4/autofs_i.h	Wed Feb 21 16:09:58 2001
@@ -20,7 +20,7 @@
 #define AUTOFS_IOC_COUNT     32
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/string.h>
 #include <linux/wait.h>
diff -u --recursive --new-file v2.4.1/linux/fs/autofs4/inode.c linux/fs/autofs4/inode.c
--- v2.4.1/linux/fs/autofs4/inode.c	Thu Nov 16 13:18:26 2000
+++ linux/fs/autofs4/inode.c	Fri Feb  9 11:29:44 2001
@@ -11,7 +11,7 @@
  * ------------------------------------------------------------------------- */
 
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/locks.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/fs/autofs4/waitq.c linux/fs/autofs4/waitq.c
--- v2.4.1/linux/fs/autofs4/waitq.c	Fri Sep  1 14:35:16 2000
+++ linux/fs/autofs4/waitq.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
  *
  * ------------------------------------------------------------------------- */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/signal.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/fs/binfmt_aout.c linux/fs/binfmt_aout.c
--- v2.4.1/linux/fs/binfmt_aout.c	Fri Jul  7 15:54:01 2000
+++ linux/fs/binfmt_aout.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
 #include <linux/user.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/binfmts.h>
 #include <linux/personality.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/fs/binfmt_elf.c linux/fs/binfmt_elf.c
--- v2.4.1/linux/fs/binfmt_elf.c	Tue Nov 28 21:53:45 2000
+++ linux/fs/binfmt_elf.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/file.h>
 #include <linux/fcntl.h>
 #include <linux/ptrace.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/personality.h>
 #include <linux/elfcore.h>
diff -u --recursive --new-file v2.4.1/linux/fs/binfmt_em86.c linux/fs/binfmt_em86.c
--- v2.4.1/linux/fs/binfmt_em86.c	Mon Jun 26 11:36:44 2000
+++ linux/fs/binfmt_em86.c	Fri Feb  9 11:29:44 2001
@@ -11,7 +11,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/stat.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
 #include <linux/binfmts.h>
diff -u --recursive --new-file v2.4.1/linux/fs/binfmt_misc.c linux/fs/binfmt_misc.c
--- v2.4.1/linux/fs/binfmt_misc.c	Mon Jul 31 10:51:09 2000
+++ linux/fs/binfmt_misc.c	Fri Feb  9 11:29:44 2001
@@ -21,7 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/binfmts.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/binfmt_script.c linux/fs/binfmt_script.c
--- v2.4.1/linux/fs/binfmt_script.c	Mon Jul 31 10:51:09 2000
+++ linux/fs/binfmt_script.c	Fri Feb  9 11:29:44 2001
@@ -8,7 +8,7 @@
 #include <linux/module.h>
 #include <linux/string.h>
 #include <linux/stat.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/binfmts.h>
 #include <linux/init.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/fs/block_dev.c linux/fs/block_dev.c
--- v2.4.1/linux/fs/block_dev.c	Fri Dec  8 17:36:41 2000
+++ linux/fs/block_dev.c	Fri Feb  9 11:29:44 2001
@@ -9,8 +9,9 @@
 #include <linux/mm.h>
 #include <linux/locks.h>
 #include <linux/fcntl.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kmod.h>
+#include <linux/major.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/buffer.c linux/fs/buffer.c
--- v2.4.1/linux/fs/buffer.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/buffer.c	Fri Feb  9 11:29:44 2001
@@ -31,7 +31,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/locks.h>
 #include <linux/errno.h>
 #include <linux/swap.h>
diff -u --recursive --new-file v2.4.1/linux/fs/coda/cnode.c linux/fs/coda/cnode.c
--- v2.4.1/linux/fs/coda/cnode.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/coda/cnode.c	Fri Feb  9 10:18:27 2001
@@ -194,8 +194,13 @@
 		return NULL;
 	}
 
-	/* check if this inode is linked to a cnode */
 	cii = ITOC(inode);
+
+	/* The inode might already be purged due to memory pressure */
+	if ( coda_fideq(&cii->c_fid, &NullFID) ) {
+		iput(inode);
+		return NULL;
+	}
 
 	/* we shouldn't have inode collisions anymore */
 	if ( !coda_fideq(fid, &cii->c_fid) ) BUG();
diff -u --recursive --new-file v2.4.1/linux/fs/coda/psdev.c linux/fs/coda/psdev.c
--- v2.4.1/linux/fs/coda/psdev.c	Mon Oct 16 12:58:51 2000
+++ linux/fs/coda/psdev.c	Fri Feb  9 11:29:44 2001
@@ -23,7 +23,7 @@
 #include <linux/major.h>
 #include <linux/sched.h>
 #include <linux/lp.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/fcntl.h>
 #include <linux/delay.h>
diff -u --recursive --new-file v2.4.1/linux/fs/coda/sysctl.c linux/fs/coda/sysctl.c
--- v2.4.1/linux/fs/coda/sysctl.c	Tue Sep 19 15:08:59 2000
+++ linux/fs/coda/sysctl.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/sysctl.h>
 #include <linux/swapctl.h>
 #include <linux/proc_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/ctype.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/fs/coda/upcall.c linux/fs/coda/upcall.c
--- v2.4.1/linux/fs/coda/upcall.c	Tue Sep 19 15:08:59 2000
+++ linux/fs/coda/upcall.c	Fri Feb  9 10:18:27 2001
@@ -519,7 +519,7 @@
 
         /* build packet for Venus */
         if (data->vi.in_size > VC_MAXDATASIZE) {
-	        error = EINVAL;
+	        error = -EINVAL;
 		goto exit;
         }
 
@@ -539,7 +539,7 @@
         /* get the data out of user space */
         if ( copy_from_user((char*)inp + (long)inp->coda_ioctl.data,
 			    data->vi.in, data->vi.in_size) ) {
-	        error = EINVAL;
+	        error = -EINVAL;
 	        goto exit;
 	}
 
@@ -557,7 +557,7 @@
                 CDEBUG(D_FILE, "return len %d <= request len %d\n",
                       outp->coda_ioctl.len, 
                       data->vi.out_size);
-                error = EINVAL;
+                error = -EINVAL;
         } else {
 		error = verify_area(VERIFY_WRITE, data->vi.out, 
                                     data->vi.out_size);
@@ -566,7 +566,7 @@
 		if (copy_to_user(data->vi.out, 
 				 (char *)outp + (long)outp->coda_ioctl.data, 
 				 data->vi.out_size)) {
-		        error = EINVAL;
+		        error = -EINVAL;
 			goto exit;
 		}
         }
diff -u --recursive --new-file v2.4.1/linux/fs/dcache.c linux/fs/dcache.c
--- v2.4.1/linux/fs/dcache.c	Wed Jan  3 11:03:35 2001
+++ linux/fs/dcache.c	Fri Feb 16 16:06:17 2001
@@ -18,7 +18,6 @@
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
@@ -52,13 +51,8 @@
 static struct list_head *dentry_hashtable;
 static LIST_HEAD(dentry_unused);
 
-struct {
-	int nr_dentry;
-	int nr_unused;
-	int age_limit;		/* age in seconds */
-	int want_pages;		/* pages requested by system */
-	int dummy[2];
-} dentry_stat = {0, 0, 45, 0,};
+/* Statistics gathering. */
+struct dentry_stat_t dentry_stat = {0, 0, 45, 0,};
 
 /* no dcache_lock, please */
 static inline void d_free(struct dentry *dentry)
@@ -346,8 +340,7 @@
 		if (dentry->d_flags & DCACHE_REFERENCED) {
 			dentry->d_flags &= ~DCACHE_REFERENCED;
 			list_add(&dentry->d_lru, &dentry_unused);
-			count--;
-			continue;
+			goto next;
 		}
 		dentry_stat.nr_unused--;
 
@@ -356,6 +349,7 @@
 			BUG();
 
 		prune_one_dentry(dentry);
+	next:
 		if (!--count)
 			break;
 	}
@@ -696,7 +690,7 @@
 static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)
 {
 	hash += (unsigned long) parent / L1_CACHE_BYTES;
-	hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2);
+	hash = hash ^ (hash >> D_HASHBITS);
 	return dentry_hashtable + (hash & D_HASHMASK);
 }
 
diff -u --recursive --new-file v2.4.1/linux/fs/devfs/base.c linux/fs/devfs/base.c
--- v2.4.1/linux/fs/devfs/base.c	Fri Nov 17 11:36:27 2000
+++ linux/fs/devfs/base.c	Fri Feb  9 11:29:44 2001
@@ -491,7 +491,7 @@
 #include <linux/kernel.h>
 #include <linux/wait.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
diff -u --recursive --new-file v2.4.1/linux/fs/devpts/inode.c linux/fs/devpts/inode.c
--- v2.4.1/linux/fs/devpts/inode.c	Thu Nov 16 13:18:26 2000
+++ linux/fs/devpts/inode.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/locks.h>
 #include <linux/major.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/tty.h>
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/fs/dquot.c linux/fs/dquot.c
--- v2.4.1/linux/fs/dquot.c	Tue Nov 28 22:40:50 2000
+++ linux/fs/dquot.c	Fri Feb 16 16:06:17 2001
@@ -47,12 +47,11 @@
 #include <linux/stat.h>
 #include <linux/tty.h>
 #include <linux/file.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mount.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
-#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 
@@ -1536,7 +1535,7 @@
 			break;
 		case Q_GETQUOTA:
 			if (((type == USRQUOTA && current->euid != id) ||
-			     (type == GRPQUOTA && in_egroup_p(id))) &&
+			     (type == GRPQUOTA && !in_egroup_p(id))) &&
 			    !capable(CAP_SYS_RESOURCE))
 				goto out;
 			break;
diff -u --recursive --new-file v2.4.1/linux/fs/exec.c linux/fs/exec.c
--- v2.4.1/linux/fs/exec.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/exec.c	Fri Feb  9 19:03:39 2001
@@ -395,7 +395,7 @@
 
 	mm = mm_alloc();
 	if (mm) {
-		struct mm_struct *active_mm = current->active_mm;
+		struct mm_struct *active_mm;
 
 		if (init_new_context(current, mm)) {
 			mmdrop(mm);
@@ -409,6 +409,7 @@
 		spin_unlock(&mmlist_lock);
 
 		task_lock(current);
+		active_mm = current->active_mm;
 		current->mm = mm;
 		current->active_mm = mm;
 		task_unlock(current);
diff -u --recursive --new-file v2.4.1/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
--- v2.4.1/linux/fs/ext2/namei.c	Fri Dec  8 17:35:54 2000
+++ linux/fs/ext2/namei.c	Thu Feb 15 12:32:21 2001
@@ -235,6 +235,7 @@
 				return retval;
 			if (dir->i_size <= offset) {
 				if (dir->i_size == 0) {
+					brelse(bh);
 					return -ENOENT;
 				}
 
diff -u --recursive --new-file v2.4.1/linux/fs/fat/buffer.c linux/fs/fat/buffer.c
--- v2.4.1/linux/fs/fat/buffer.c	Tue Sep  5 14:07:29 2000
+++ linux/fs/fat/buffer.c	Fri Feb  9 11:29:44 2001
@@ -5,7 +5,7 @@
  */
 
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/fs.h>
 #include <linux/msdos_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/fat/inode.c linux/fs/fat/inode.c
--- v2.4.1/linux/fs/fat/inode.c	Sun Dec 31 11:02:21 2000
+++ linux/fs/fat/inode.c	Fri Feb  9 11:29:44 2001
@@ -27,7 +27,7 @@
 #include <linux/stat.h>
 #include <linux/locks.h>
 #include <linux/fat_cvf.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 
 #include "msbuffer.h"
diff -u --recursive --new-file v2.4.1/linux/fs/fifo.c linux/fs/fifo.c
--- v2.4.1/linux/fs/fifo.c	Sat Jul  8 19:26:13 2000
+++ linux/fs/fifo.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
  */
 
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 
 static void wait_for_partner(struct inode* inode, unsigned int* cnt)
diff -u --recursive --new-file v2.4.1/linux/fs/file.c linux/fs/file.c
--- v2.4.1/linux/fs/file.c	Tue Nov 28 22:43:39 2000
+++ linux/fs/file.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/fs.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <asm/bitops.h>
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/balloc.c linux/fs/hfs/balloc.c
--- v2.4.1/linux/fs/hfs/balloc.c	Mon May 15 10:47:12 2000
+++ linux/fs/hfs/balloc.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/balloc.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * hfs_bnode_alloc() and hfs_bnode_bitop() are based on GPLed code
  * Copyright (C) 1995  Michael Dreher
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/bdelete.c linux/fs/hfs/bdelete.c
--- v2.4.1/linux/fs/hfs/bdelete.c	Wed Dec 23 14:10:36 1998
+++ linux/fs/hfs/bdelete.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/bdelete.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to delete records in a B-tree.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/bfind.c linux/fs/hfs/bfind.c
--- v2.4.1/linux/fs/hfs/bfind.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/bfind.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/bfind.c
  *
  * Copyright (C) 1995, 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to access records in a btree.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/bins_del.c linux/fs/hfs/bins_del.c
--- v2.4.1/linux/fs/hfs/bins_del.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/bins_del.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/bins_del.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code common to inserting and deleting records
  * in a B-tree.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/binsert.c linux/fs/hfs/binsert.c
--- v2.4.1/linux/fs/hfs/binsert.c	Tue Nov 24 11:27:54 1998
+++ linux/fs/hfs/binsert.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/binsert.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to insert records in a B-tree.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/bitmap.c linux/fs/hfs/bitmap.c
--- v2.4.1/linux/fs/hfs/bitmap.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/bitmap.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/bitmap.c
  *
  * Copyright (C) 1996-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * Based on GPLed code Copyright (C) 1995  Michael Dreher
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/bitops.c linux/fs/hfs/bitops.c
--- v2.4.1/linux/fs/hfs/bitops.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/bitops.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/bitops.c
  *
  * Copyright (C) 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains functions to handle bitmaps in "left-to-right"
  * bit-order such that the MSB of a 32-bit big-endian word is bit 0.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/bnode.c linux/fs/hfs/bnode.c
--- v2.4.1/linux/fs/hfs/bnode.c	Fri Jun  4 13:30:25 1999
+++ linux/fs/hfs/bnode.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/bnode.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to access nodes in the B-tree structure.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/brec.c linux/fs/hfs/brec.c
--- v2.4.1/linux/fs/hfs/brec.c	Sun Jan  4 10:40:17 1998
+++ linux/fs/hfs/brec.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/brec.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to access records in a btree.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/btree.c linux/fs/hfs/btree.c
--- v2.4.1/linux/fs/hfs/btree.c	Fri Jun  4 13:30:25 1999
+++ linux/fs/hfs/btree.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/btree.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to manipulate the B-tree structure.
  * The catalog and extents files are both B-trees.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/catalog.c linux/fs/hfs/catalog.c
--- v2.4.1/linux/fs/hfs/catalog.c	Mon May 15 12:00:34 2000
+++ linux/fs/hfs/catalog.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/catalog.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the functions related to the catalog B-tree.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/dir.c linux/fs/hfs/dir.c
--- v2.4.1/linux/fs/hfs/dir.c	Sat May 20 10:55:27 2000
+++ linux/fs/hfs/dir.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/dir.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains directory-related functions independent of which
  * scheme is being used to represent forks.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/dir_cap.c linux/fs/hfs/dir_cap.c
--- v2.4.1/linux/fs/hfs/dir_cap.c	Fri Aug 11 14:29:02 2000
+++ linux/fs/hfs/dir_cap.c	Tue Feb 13 14:13:45 2001
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the inode_operations and file_operations
  * structures for HFS directories under the CAP scheme.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/dir_dbl.c linux/fs/hfs/dir_dbl.c
--- v2.4.1/linux/fs/hfs/dir_dbl.c	Fri Aug 11 14:29:02 2000
+++ linux/fs/hfs/dir_dbl.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/dir_dbl.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the inode_operations and file_operations
  * structures for HFS directories.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/dir_nat.c linux/fs/hfs/dir_nat.c
--- v2.4.1/linux/fs/hfs/dir_nat.c	Fri Aug 11 14:29:02 2000
+++ linux/fs/hfs/dir_nat.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/dir_nat.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the inode_operations and file_operations
  * structures for HFS directories.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/extent.c linux/fs/hfs/extent.c
--- v2.4.1/linux/fs/hfs/extent.c	Thu Jan 13 11:54:37 2000
+++ linux/fs/hfs/extent.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/extent.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the functions related to the extents B-tree.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/file.c linux/fs/hfs/file.c
--- v2.4.1/linux/fs/hfs/file.c	Thu Oct 26 23:35:48 2000
+++ linux/fs/hfs/file.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/file.c
  *
  * Copyright (C) 1995, 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the file-related functions which are independent of
  * which scheme is being used to represent forks.
@@ -135,9 +135,9 @@
  * This is the read field in the inode_operations structure for
  * "regular" (non-header) files.  The purpose is to transfer up to
  * 'count' bytes from the file corresponding to 'inode', beginning at
- * 'filp->offset' bytes into the file.	The data is transfered to
+ * 'filp->offset' bytes into the file.	The data is transferred to
  * user-space at the address 'buf'.  Returns the number of bytes
- * successfully transfered.  This function checks the arguments, does
+ * successfully transferred.  This function checks the arguments, does
  * some setup and then calls hfs_do_read() to do the actual transfer.  */
 static hfs_rwret_t hfs_file_read(struct file * filp, char * buf, 
 				 hfs_rwarg_t count, loff_t *ppos)
@@ -277,7 +277,7 @@
  * hfs_do_read()
  *
  * This function transfers actual data from disk to user-space memory,
- * returning the number of bytes successfully transfered.  'fork' tells
+ * returning the number of bytes successfully transferred.  'fork' tells
  * which file on the disk to read from.  'pos' gives the offset into
  * the Linux file at which to begin the transfer.  Note that this will
  * differ from 'filp->offset' in the case of an AppleDouble header file
@@ -433,7 +433,7 @@
  * hfs_do_write()
  *
  * This function transfers actual data from user-space memory to disk,
- * returning the number of bytes successfully transfered.  'fork' tells
+ * returning the number of bytes successfully transferred.  'fork' tells
  * which file on the disk to write to.  'pos' gives the offset into
  * the Linux file at which to begin the transfer.  Note that this will
  * differ from 'filp->offset' in the case of an AppleDouble header file
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/file_cap.c linux/fs/hfs/file_cap.c
--- v2.4.1/linux/fs/hfs/file_cap.c	Sat Feb 26 20:33:42 2000
+++ linux/fs/hfs/file_cap.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/file_cap.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the file_ops and inode_ops for the metadata
  * files under the CAP representation.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/file_hdr.c linux/fs/hfs/file_hdr.c
--- v2.4.1/linux/fs/hfs/file_hdr.c	Mon May 15 12:00:34 2000
+++ linux/fs/hfs/file_hdr.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/file_hdr.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the file_ops and inode_ops for the metadata
  * files under the AppleDouble and Netatalk representations.
@@ -348,9 +348,9 @@
  * This is the read field in the inode_operations structure for
  * header files.  The purpose is to transfer up to 'count' bytes
  * from the file corresponding to 'inode', beginning at
- * 'filp->offset' bytes into the file.	The data is transfered to
+ * 'filp->offset' bytes into the file.	The data is transferred to
  * user-space at the address 'buf'.  Returns the number of bytes
- * successfully transfered.
+ * successfully transferred.
  */
 /* XXX: what about the entry count changing on us? */
 static hfs_rwret_t hdr_read(struct file * filp, char * buf, 
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/hfs.h linux/fs/hfs/hfs.h
--- v2.4.1/linux/fs/hfs/hfs.h	Mon Dec 11 13:25:24 2000
+++ linux/fs/hfs/hfs.h	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/hfs.h
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * "XXX" in a comment is a note to myself to consider changing something.
  */
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/hfs_btree.h linux/fs/hfs/hfs_btree.h
--- v2.4.1/linux/fs/hfs/hfs_btree.h	Mon Dec 11 13:25:24 2000
+++ linux/fs/hfs/hfs_btree.h	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/hfs_btree.h
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the declarations of the private B-tree
  * structures and functions.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/inode.c linux/fs/hfs/inode.c
--- v2.4.1/linux/fs/hfs/inode.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/hfs/inode.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/inode.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains inode-related functions which do not depend on
  * which scheme is being used to represent forks.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/mdb.c linux/fs/hfs/mdb.c
--- v2.4.1/linux/fs/hfs/mdb.c	Mon May 15 12:00:34 2000
+++ linux/fs/hfs/mdb.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/mdb.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains functions for reading/writing the MDB.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/part_tbl.c linux/fs/hfs/part_tbl.c
--- v2.4.1/linux/fs/hfs/part_tbl.c	Mon May 15 12:00:34 2000
+++ linux/fs/hfs/part_tbl.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/part_tbl.c
  *
  * Copyright (C) 1996-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * Original code to handle the new style Mac partition table based on
  * a patch contributed by Holger Schemel (aeglos@valinor.owl.de).
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/string.c linux/fs/hfs/string.c
--- v2.4.1/linux/fs/hfs/string.c	Mon Nov  2 09:35:16 1998
+++ linux/fs/hfs/string.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/string.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the string comparison function for the
  * Macintosh character set.
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/super.c linux/fs/hfs/super.c
--- v2.4.1/linux/fs/hfs/super.c	Mon Mar 13 12:35:39 2000
+++ linux/fs/hfs/super.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/super.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains hfs_read_super(), some of the super_ops and
  * init_module() and cleanup_module().	The remaining super_ops are in
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/sysdep.c linux/fs/hfs/sysdep.c
--- v2.4.1/linux/fs/hfs/sysdep.c	Wed Jul  5 11:31:01 2000
+++ linux/fs/hfs/sysdep.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/sysdep.c
  *
  * Copyright (C) 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the code to do various system dependent things.
  *
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/trans.c linux/fs/hfs/trans.c
--- v2.4.1/linux/fs/hfs/trans.c	Mon Oct 16 12:58:51 2000
+++ linux/fs/hfs/trans.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/trans.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains routines for converting between the Macintosh
  * character set and various other encodings.  This includes dealing
diff -u --recursive --new-file v2.4.1/linux/fs/hfs/version.c linux/fs/hfs/version.c
--- v2.4.1/linux/fs/hfs/version.c	Mon Nov  2 09:35:17 1998
+++ linux/fs/hfs/version.c	Tue Feb 13 14:13:45 2001
@@ -2,7 +2,7 @@
  * linux/fs/hfs/version.c
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains the version string for this release.
  */
diff -u --recursive --new-file v2.4.1/linux/fs/hpfs/hpfs_fn.h linux/fs/hpfs/hpfs_fn.h
--- v2.4.1/linux/fs/hpfs/hpfs_fn.h	Mon Dec 11 13:26:31 2000
+++ linux/fs/hpfs/hpfs_fn.h	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/fs.h>
 #include <linux/hpfs_fs.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/locks.h>
diff -u --recursive --new-file v2.4.1/linux/fs/inode.c linux/fs/inode.c
--- v2.4.1/linux/fs/inode.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/inode.c	Fri Feb  9 11:34:18 2001
@@ -67,11 +67,7 @@
 /*
  * Statistics gathering..
  */
-struct {
-	int nr_inodes;
-	int nr_unused;
-	int dummy[5];
-} inodes_stat;
+struct inodes_stat_t inodes_stat;
 
 static kmem_cache_t * inode_cachep;
 
@@ -728,8 +724,8 @@
 
 static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
 {
-	unsigned long tmp = i_ino | ((unsigned long) sb / L1_CACHE_BYTES);
-	tmp = tmp + (tmp >> I_HASHBITS) + (tmp >> I_HASHBITS*2);
+	unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES);
+	tmp = tmp + (tmp >> I_HASHBITS);
 	return tmp & I_HASHMASK;
 }
 
diff -u --recursive --new-file v2.4.1/linux/fs/iobuf.c linux/fs/iobuf.c
--- v2.4.1/linux/fs/iobuf.c	Thu Mar  9 21:12:27 2000
+++ linux/fs/iobuf.c	Fri Feb 16 16:06:17 2001
@@ -7,7 +7,6 @@
  */
 
 #include <linux/iobuf.h>
-#include <linux/malloc.h>
 #include <linux/slab.h>
 
 static kmem_cache_t *kiobuf_cachep;
diff -u --recursive --new-file v2.4.1/linux/fs/ioctl.c linux/fs/ioctl.c
--- v2.4.1/linux/fs/ioctl.c	Sat Aug 12 19:48:04 2000
+++ linux/fs/ioctl.c	Fri Feb  9 11:29:44 2001
@@ -9,6 +9,7 @@
 #include <linux/file.h>
 
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 
 static int file_ioctl(struct file *filp,unsigned int cmd,unsigned long arg)
 {
diff -u --recursive --new-file v2.4.1/linux/fs/isofs/dir.c linux/fs/isofs/dir.c
--- v2.4.1/linux/fs/isofs/dir.c	Wed Nov 29 10:11:38 2000
+++ linux/fs/isofs/dir.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/stat.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/locks.h>
 #include <linux/config.h>
diff -u --recursive --new-file v2.4.1/linux/fs/isofs/inode.c linux/fs/isofs/inode.c
--- v2.4.1/linux/fs/isofs/inode.c	Mon Jan  1 10:23:21 2001
+++ linux/fs/isofs/inode.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/mm.h>
 #include <linux/string.h>
 #include <linux/locks.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/cdrom.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/fs/isofs/joliet.c linux/fs/isofs/joliet.c
--- v2.4.1/linux/fs/isofs/joliet.c	Fri Nov 17 15:29:55 2000
+++ linux/fs/isofs/joliet.c	Fri Feb  9 11:29:44 2001
@@ -8,7 +8,7 @@
 
 #include <linux/string.h>
 #include <linux/nls.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/iso_fs.h>
 
 /*
diff -u --recursive --new-file v2.4.1/linux/fs/isofs/namei.c linux/fs/isofs/namei.c
--- v2.4.1/linux/fs/isofs/namei.c	Wed Nov 29 10:11:38 2000
+++ linux/fs/isofs/namei.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/config.h>	/* Joliet? */
 
diff -u --recursive --new-file v2.4.1/linux/fs/isofs/rock.c linux/fs/isofs/rock.c
--- v2.4.1/linux/fs/isofs/rock.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/isofs/rock.c	Fri Feb  9 11:29:44 2001
@@ -11,7 +11,7 @@
 #include <linux/iso_fs.h>
 #include <linux/string.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/jffs/inode-v23.c linux/fs/jffs/inode-v23.c
--- v2.4.1/linux/fs/jffs/inode-v23.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/jffs/inode-v23.c	Fri Feb  9 11:29:44 2001
@@ -39,7 +39,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/jffs.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
diff -u --recursive --new-file v2.4.1/linux/fs/jffs/intrep.c linux/fs/jffs/intrep.c
--- v2.4.1/linux/fs/jffs/intrep.c	Fri Nov 17 16:44:55 2000
+++ linux/fs/jffs/intrep.c	Fri Feb  9 11:29:44 2001
@@ -58,7 +58,7 @@
 
 #define __NO_VERSION__
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/jffs.h>
 #include <linux/fs.h>
 #include <linux/stat.h>
diff -u --recursive --new-file v2.4.1/linux/fs/jffs/jffs_fm.c linux/fs/jffs/jffs_fm.c
--- v2.4.1/linux/fs/jffs/jffs_fm.c	Fri Sep  8 12:44:55 2000
+++ linux/fs/jffs/jffs_fm.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
  *
  */
 #define __NO_VERSION__
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/blkdev.h>
 #include <linux/jffs.h>
 #include "jffs_fm.h"
diff -u --recursive --new-file v2.4.1/linux/fs/lockd/host.c linux/fs/lockd/host.c
--- v2.4.1/linux/fs/lockd/host.c	Sun Oct  1 20:35:16 2000
+++ linux/fs/lockd/host.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
diff -u --recursive --new-file v2.4.1/linux/fs/lockd/svc.c linux/fs/lockd/svc.c
--- v2.4.1/linux/fs/lockd/svc.c	Fri Dec 29 14:07:23 2000
+++ linux/fs/lockd/svc.c	Fri Feb  9 11:29:44 2001
@@ -22,7 +22,7 @@
 #include <linux/uio.h>
 #include <linux/version.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/lockd/svc4proc.c linux/fs/lockd/svc4proc.c
--- v2.4.1/linux/fs/lockd/svc4proc.c	Mon Apr  3 13:24:05 2000
+++ linux/fs/lockd/svc4proc.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
diff -u --recursive --new-file v2.4.1/linux/fs/lockd/svcproc.c linux/fs/lockd/svcproc.c
--- v2.4.1/linux/fs/lockd/svcproc.c	Mon Apr  3 13:24:06 2000
+++ linux/fs/lockd/svcproc.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/sunrpc/svc.h>
 #include <linux/sunrpc/clnt.h>
diff -u --recursive --new-file v2.4.1/linux/fs/lockd/svcshare.c linux/fs/lockd/svcshare.c
--- v2.4.1/linux/fs/lockd/svcshare.c	Thu Sep 21 13:38:58 2000
+++ linux/fs/lockd/svcshare.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/sched.h>
 #include <linux/unistd.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/sunrpc/clnt.h>
 #include <linux/sunrpc/svc.h>
diff -u --recursive --new-file v2.4.1/linux/fs/locks.c linux/fs/locks.c
--- v2.4.1/linux/fs/locks.c	Sun Dec  3 10:24:07 2000
+++ linux/fs/locks.c	Fri Feb  9 11:29:44 2001
@@ -115,7 +115,7 @@
  *  Stephen Rothwell <sfr@linuxcare.com>, June, 2000.
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/file.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
diff -u --recursive --new-file v2.4.1/linux/fs/minix/inode.c linux/fs/minix/inode.c
--- v2.4.1/linux/fs/minix/inode.c	Mon Dec  4 18:59:30 2000
+++ linux/fs/minix/inode.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/stat.h>
 #include <linux/locks.h>
diff -u --recursive --new-file v2.4.1/linux/fs/ncpfs/dir.c linux/fs/ncpfs/dir.c
--- v2.4.1/linux/fs/ncpfs/dir.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/ncpfs/dir.c	Fri Feb  9 11:29:44 2001
@@ -15,7 +15,7 @@
 #include <linux/errno.h>
 #include <linux/stat.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/mm.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/fs/ncpfs/file.c linux/fs/ncpfs/file.c
--- v2.4.1/linux/fs/ncpfs/file.c	Fri Nov 17 11:36:27 2000
+++ linux/fs/ncpfs/file.c	Fri Feb  9 11:29:44 2001
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 #include <linux/mm.h>
 #include <linux/locks.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 
 #include <linux/ncp_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/ncpfs/inode.c linux/fs/ncpfs/inode.c
--- v2.4.1/linux/fs/ncpfs/inode.c	Thu Nov 16 13:18:26 2000
+++ linux/fs/ncpfs/inode.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/locks.h>
 #include <linux/file.h>
 #include <linux/fcntl.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/ncpfs/mmap.c linux/fs/ncpfs/mmap.c
--- v2.4.1/linux/fs/ncpfs/mmap.c	Sat Nov 11 18:50:28 2000
+++ linux/fs/ncpfs/mmap.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/mman.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fcntl.h>
 #include <linux/ncp_fs.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/ncpfs/ncplib_kernel.h linux/fs/ncpfs/ncplib_kernel.h
--- v2.4.1/linux/fs/ncpfs/ncplib_kernel.h	Mon Dec 11 13:26:24 2000
+++ linux/fs/ncpfs/ncplib_kernel.h	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/fs.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/pagemap.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/dir.c linux/fs/nfs/dir.c
--- v2.4.1/linux/fs/nfs/dir.c	Sun Dec 10 09:55:48 2000
+++ linux/fs/nfs/dir.c	Fri Feb  9 11:29:44 2001
@@ -23,7 +23,7 @@
 #include <linux/fcntl.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/file.c linux/fs/nfs/file.c
--- v2.4.1/linux/fs/nfs/file.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/nfs/file.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/nfs_fs.h>
 #include <linux/nfs_mount.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/lockd/bind.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/flushd.c linux/fs/nfs/flushd.c
--- v2.4.1/linux/fs/nfs/flushd.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/nfs/flushd.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/inode.c linux/fs/nfs/inode.c
--- v2.4.1/linux/fs/nfs/inode.c	Mon Dec 11 17:46:04 2000
+++ linux/fs/nfs/inode.c	Tue Feb 13 16:14:28 2001
@@ -100,6 +100,7 @@
 	inode->i_rdev = 0;
 	NFS_FILEID(inode) = 0;
 	NFS_FSID(inode) = 0;
+	NFS_FLAGS(inode) = 0;
 	INIT_LIST_HEAD(&inode->u.nfs_i.read);
 	INIT_LIST_HEAD(&inode->u.nfs_i.dirty);
 	INIT_LIST_HEAD(&inode->u.nfs_i.commit);
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/nfs2xdr.c linux/fs/nfs/nfs2xdr.c
--- v2.4.1/linux/fs/nfs/nfs2xdr.c	Mon Oct 16 13:36:08 2000
+++ linux/fs/nfs/nfs2xdr.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
 #include <linux/param.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/utsname.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/nfs3xdr.c linux/fs/nfs/nfs3xdr.c
--- v2.4.1/linux/fs/nfs/nfs3xdr.c	Mon Oct 16 13:36:08 2000
+++ linux/fs/nfs/nfs3xdr.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
 #include <linux/param.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/utsname.h>
 #include <linux/errno.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/proc.c linux/fs/nfs/proc.c
--- v2.4.1/linux/fs/nfs/proc.c	Sun Dec  3 18:01:01 2000
+++ linux/fs/nfs/proc.c	Fri Feb  9 11:29:44 2001
@@ -29,7 +29,7 @@
 
 #include <linux/types.h>
 #include <linux/param.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/utsname.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/read.c linux/fs/nfs/read.c
--- v2.4.1/linux/fs/nfs/read.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/nfs/read.c	Fri Feb  9 11:29:44 2001
@@ -22,7 +22,7 @@
 #include <linux/fcntl.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/sunrpc/clnt.h>
 #include <linux/nfs_fs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/symlink.c linux/fs/nfs/symlink.c
--- v2.4.1/linux/fs/nfs/symlink.c	Sun Dec  3 18:01:01 2000
+++ linux/fs/nfs/symlink.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/pagemap.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/unlink.c linux/fs/nfs/unlink.c
--- v2.4.1/linux/fs/nfs/unlink.c	Sun Oct  1 20:35:16 2000
+++ linux/fs/nfs/unlink.c	Fri Feb  9 11:29:44 2001
@@ -6,7 +6,7 @@
  * NOTE: we rely on holding the BKL for list manipulation protection.
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/dcache.h>
 #include <linux/sunrpc/sched.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfs/write.c linux/fs/nfs/write.c
--- v2.4.1/linux/fs/nfs/write.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/nfs/write.c	Fri Feb  9 11:29:44 2001
@@ -48,7 +48,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/swap.h>
 #include <linux/pagemap.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/export.c linux/fs/nfsd/export.c
--- v2.4.1/linux/fs/nfsd/export.c	Sun Oct  1 20:35:16 2000
+++ linux/fs/nfsd/export.c	Fri Feb  9 11:29:44 2001
@@ -15,7 +15,7 @@
  */
 
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/stat.h>
 #include <linux/in.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfs3proc.c linux/fs/nfsd/nfs3proc.c
--- v2.4.1/linux/fs/nfsd/nfs3proc.c	Wed Sep 27 13:41:33 2000
+++ linux/fs/nfsd/nfs3proc.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/in.h>
 #include <linux/version.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/major.h>
 
 #include <linux/sunrpc/svc.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfscache.c linux/fs/nfsd/nfscache.c
--- v2.4.1/linux/fs/nfsd/nfscache.c	Mon Oct 16 12:58:51 2000
+++ linux/fs/nfsd/nfscache.c	Thu Feb 15 10:56:29 2001
@@ -12,7 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 
 #include <linux/sunrpc/svc.h>
@@ -192,7 +192,7 @@
 		    xid == rp->c_xid && proc == rp->c_proc &&
 		    proto == rp->c_prot && vers == rp->c_vers &&
 		    time_before(jiffies, rp->c_timestamp + 120*HZ) &&
-		    memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, rqstp->rq_addrlen)==0) {
+		    memcmp((char*)&rqstp->rq_addr, (char*)&rp->c_addr, sizeof(rp->c_addr))==0) {
 			nfsdstats.rchits++;
 			goto found_entry;
 		}
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfsctl.c linux/fs/nfsd/nfsctl.c
--- v2.4.1/linux/fs/nfsd/nfsctl.c	Sun Oct  1 20:35:16 2000
+++ linux/fs/nfsd/nfsctl.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/net.h>
 #include <linux/in.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/proc_fs.h>
 
 #include <linux/nfs.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfsfh.c linux/fs/nfsd/nfsfh.c
--- v2.4.1/linux/fs/nfsd/nfsfh.c	Thu Jan  4 12:50:17 2001
+++ linux/fs/nfsd/nfsfh.c	Fri Feb  9 11:29:44 2001
@@ -9,7 +9,7 @@
  */
 
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/unistd.h>
 #include <linux/string.h>
@@ -454,6 +454,7 @@
 		if (tmp != dentry) {
 			/* we lost a race,  try again
 			 */
+			dput(pdentry);
 			dput(tmp);
 			dput(dentry);
 			dput(result);	/* this will discard the whole free path, so we can up the semaphore */
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfsproc.c linux/fs/nfsd/nfsproc.c
--- v2.4.1/linux/fs/nfsd/nfsproc.c	Mon Jun 26 11:44:15 2000
+++ linux/fs/nfsd/nfsproc.c	Fri Feb  9 11:29:44 2001
@@ -18,7 +18,7 @@
 #include <linux/in.h>
 #include <linux/version.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <linux/sunrpc/svc.h>
 #include <linux/nfsd/nfsd.h>
@@ -252,8 +252,19 @@
 	if (attr->ia_valid & ATTR_MODE) { 
 		type = attr->ia_mode & S_IFMT;
 		mode = attr->ia_mode & ~S_IFMT;
-		if (!type)	/* HP weirdness */
-			type = S_IFREG;
+		if (!type) {
+			/* no type, so if target exists, assume same as that,
+			 * else assume a file */
+			if (inode) {
+				type = inode->i_mode & S_IFMT;
+				if (type == S_IFCHR || type == S_IFBLK) {
+					/* reserve rdev for later checking */
+					attr->ia_size = inode->i_rdev;
+					attr->ia_valid |= ATTR_SIZE;
+				}
+			} else
+				type = S_IFREG;
+		}
 	} else if (inode) {
 		type = inode->i_mode & S_IFMT;
 		mode = inode->i_mode & ~S_IFMT;
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfssvc.c linux/fs/nfsd/nfssvc.c
--- v2.4.1/linux/fs/nfsd/nfssvc.c	Sun Oct  1 20:35:16 2000
+++ linux/fs/nfsd/nfssvc.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 #include <linux/uio.h>
 #include <linux/version.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/nfsxdr.c linux/fs/nfsd/nfsxdr.c
--- v2.4.1/linux/fs/nfsd/nfsxdr.c	Fri Sep 22 14:21:19 2000
+++ linux/fs/nfsd/nfsxdr.c	Thu Feb  8 19:38:38 2001
@@ -26,7 +26,7 @@
  * Mapping of S_IF* types to NFS file types
  */
 static u32	nfs_ftypes[] = {
-	NFNON,  NFFIFO, NFCHR, NFBAD,
+	NFNON,  NFCHR,  NFCHR, NFBAD,
 	NFDIR,  NFBAD,  NFBLK, NFBAD,
 	NFREG,  NFBAD,  NFLNK, NFBAD,
 	NFSOCK, NFBAD,  NFLNK, NFBAD,
@@ -136,20 +136,25 @@
 static inline u32 *
 encode_fattr(struct svc_rqst *rqstp, u32 *p, struct inode *inode)
 {
+	int type = (inode->i_mode & S_IFMT);
 	if (!inode)
 		return 0;
-	*p++ = htonl(nfs_ftypes[(inode->i_mode & S_IFMT) >> 12]);
+	*p++ = htonl(nfs_ftypes[type >> 12]);
 	*p++ = htonl((u32) inode->i_mode);
 	*p++ = htonl((u32) inode->i_nlink);
 	*p++ = htonl((u32) nfsd_ruid(rqstp, inode->i_uid));
 	*p++ = htonl((u32) nfsd_rgid(rqstp, inode->i_gid));
-	if (S_ISLNK(inode->i_mode) && inode->i_size > NFS_MAXPATHLEN) {
+
+	if (S_ISLNK(type) && inode->i_size > NFS_MAXPATHLEN) {
 		*p++ = htonl(NFS_MAXPATHLEN);
 	} else {
 		*p++ = htonl((u32) inode->i_size);
 	}
 	*p++ = htonl((u32) inode->i_blksize);
-	*p++ = htonl((u32) inode->i_rdev);
+	if (S_ISCHR(type) || S_ISBLK(type))
+		*p++ = htonl((u32) inode->i_rdev);
+	else
+		*p++ = htonl(0xffffffff);
 	*p++ = htonl((u32) inode->i_blocks);
 	*p++ = htonl((u32) inode->i_dev);
 	*p++ = htonl((u32) inode->i_ino);
diff -u --recursive --new-file v2.4.1/linux/fs/nfsd/vfs.c linux/fs/nfsd/vfs.c
--- v2.4.1/linux/fs/nfsd/vfs.c	Fri Dec 29 14:07:23 2000
+++ linux/fs/nfsd/vfs.c	Fri Feb  9 11:29:44 2001
@@ -29,7 +29,7 @@
 #include <linux/fcntl.h>
 #include <linux/net.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #define __NO_VERSION__
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.1/linux/fs/nls/nls_base.c linux/fs/nls/nls_base.c
--- v2.4.1/linux/fs/nls/nls_base.c	Mon Oct 16 12:58:51 2000
+++ linux/fs/nls/nls_base.c	Fri Feb  9 11:29:44 2001
@@ -13,7 +13,7 @@
 #include <linux/string.h>
 #include <linux/config.h>
 #include <linux/nls.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #ifdef CONFIG_KMOD
 #include <linux/kmod.h>
diff -u --recursive --new-file v2.4.1/linux/fs/open.c linux/fs/open.c
--- v2.4.1/linux/fs/open.c	Thu Oct 26 08:11:21 2000
+++ linux/fs/open.c	Fri Feb  9 11:29:44 2001
@@ -13,6 +13,7 @@
 #include <linux/dnotify.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/tty.h>
 
 #include <asm/uaccess.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/openpromfs/inode.c linux/fs/openpromfs/inode.c
--- v2.4.1/linux/fs/openpromfs/inode.c	Sat Aug 12 12:08:50 2000
+++ linux/fs/openpromfs/inode.c	Sun Feb 18 19:49:55 2001
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.13 2000/08/12 13:25:46 davem Exp $
+/* $Id: inode.c,v 1.14 2001/02/13 01:17:17 davem Exp $
  * openpromfs.c: /proc/openprom handling routines
  *
  * Copyright (C) 1996-1999 Jakub Jelinek  (jakub@redhat.com)
@@ -12,7 +12,7 @@
 #include <linux/openprom_fs.h>
 #include <linux/locks.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 
 #include <asm/openprom.h>
diff -u --recursive --new-file v2.4.1/linux/fs/partitions/Config.in linux/fs/partitions/Config.in
--- v2.4.1/linux/fs/partitions/Config.in	Sun Jul  9 22:21:41 2000
+++ linux/fs/partitions/Config.in	Fri Feb 16 16:02:37 2001
@@ -21,6 +21,7 @@
    bool '  PC BIOS (MSDOS partition tables) support' CONFIG_MSDOS_PARTITION
    if [ "$CONFIG_MSDOS_PARTITION" = "y" ]; then
       bool '    BSD disklabel (FreeBSD partition tables) support' CONFIG_BSD_DISKLABEL
+      bool '    Minix subpartition support' CONFIG_MINIX_SUBPARTITION
       bool '    Solaris (x86) partition table support' CONFIG_SOLARIS_X86_PARTITION
       bool '    Unixware slices support' CONFIG_UNIXWARE_DISKLABEL
    fi
diff -u --recursive --new-file v2.4.1/linux/fs/partitions/check.c linux/fs/partitions/check.c
--- v2.4.1/linux/fs/partitions/check.c	Sun Dec 31 11:06:00 2000
+++ linux/fs/partitions/check.c	Fri Feb 16 16:02:37 2001
@@ -76,7 +76,7 @@
 };
 
 /*
- * disk_name() is used by genhd.c and blkpg.c.
+ * disk_name() is used by partition check code and the md driver.
  * 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).
diff -u --recursive --new-file v2.4.1/linux/fs/partitions/ibm.c linux/fs/partitions/ibm.c
--- v2.4.1/linux/fs/partitions/ibm.c	Wed Apr 12 09:47:30 2000
+++ linux/fs/partitions/ibm.c	Fri Feb 16 16:02:37 2001
@@ -1,8 +1,12 @@
 /*
- * File...........: linux/fs/partitions/ibm.c
+ * File...........: linux/fs/partitions/ibm.c      
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+
+ * History of changes (starts July 2000)
+ * 07/10/00 Fixed detection of CMS formatted disks               
+
  */
 
 #include <linux/fs.h>
@@ -11,9 +15,21 @@
 #include <linux/major.h>
 #include <linux/string.h>
 #include <linux/blk.h>
-
+#include <linux/malloc.h>
+#include <linux/hdreg.h>
+#include <linux/ioctl.h>
+#include <linux/version.h>
 #include <asm/ebcdic.h>
-#include "../../drivers/s390/block/dasd_types.h"
+#include <asm/uaccess.h>
+#include <asm/dasd.h>
+
+#include "ibm.h"
+#include "check.h"
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+/* We hook in when DASD is a module... */
+int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
+#endif /* LINUX_IS_24 */
 
 typedef enum {
   ibm_partition_none = 0,
@@ -25,98 +41,131 @@
 static ibm_partition_t
 get_partition_type ( char * type )
 {
-  static char lnx[5]="LNX1";
-  static char vol[5]="VOL1";
-  static char cms[5]="CMS1";
-  if ( ! strncmp ( lnx, "LNX1",4 ) ) {
-    ASCEBC(lnx,4);
-    ASCEBC(vol,4);
-    ASCEBC(cms,4);
-  }
-  if ( ! strncmp (type,lnx,4) || 
-       ! strncmp (type,"LNX1",4) )
-    return ibm_partition_lnx1;
-  if ( ! strncmp (type,vol,4) )
-    return ibm_partition_vol1;
-  if ( ! strncmp (type,cms,4) )
-    return ibm_partition_cms1;
-  return ibm_partition_none;
+        static char lnx[5]="LNX1";
+        static char vol[5]="VOL1";
+        static char cms[5]="CMS1";
+        if ( ! strncmp ( lnx, "LNX1",4 ) ) {
+                ASCEBC(lnx,4);
+                ASCEBC(vol,4);
+                ASCEBC(cms,4);
+        }
+        if ( ! strncmp (type,lnx,4) ||
+             ! strncmp (type,"LNX1",4) )
+                return ibm_partition_lnx1;
+        if ( ! strncmp (type,vol,4) )
+                return ibm_partition_vol1;
+        if ( ! strncmp (type,cms,4) )
+                return ibm_partition_cms1;
+        return ibm_partition_none;
 }
 
-void
-ibm_partition (struct gendisk *hd, kdev_t dev)
+int 
+ibm_partition(struct gendisk *hd, kdev_t dev, unsigned long first_sector, int
+first_part_minor)
 {
 	struct buffer_head *bh;
 	ibm_partition_t partition_type;
-	int di = MINOR(dev) >> PARTN_BITS;
 	char type[5] = {0,};
 	char name[7] = {0,};
-	if ( bh = bread( dev, 
-			 dasd_info[di]->sizes.label_block, 
-			 get_ptable_blocksize(dev) ) ) {
+	struct hd_geometry geo;
+	mm_segment_t old_fs;
+	int blocksize;
+	struct file *filp = NULL;
+	struct inode *inode = NULL;
+	int offset, size;
+
+	blocksize = hardsect_size[MAJOR(dev)][MINOR(dev)];
+	if ( blocksize <= 0 ) {
+		return 0;
+	}
+	set_blocksize(dev, blocksize);  /* OUCH !! */
+
+	/* find out offset of volume label (partn table) */
+	inode = get_empty_inode();
+	inode -> i_rdev = dev;
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	inode -> i_bdev = bdget(kdev_t_to_nr(dev));
+#endif /* KERNEL_VERSION */
+	filp = (struct file *)kmalloc (sizeof(struct file),GFP_KERNEL);
+	if (!filp)
+		return 0;
+	memset(filp,0,sizeof(struct file));
+	filp ->f_mode = 1; /* read only */
+	blkdev_open(inode,filp);
+	old_fs=get_fs();
+	set_fs(KERNEL_DS);
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	inode-> i_bdev -> bd_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
+#else
+	filp->f_op->ioctl (inode, filp, HDIO_GETGEO, (unsigned long)(&geo));
+#endif /* KERNEL_VERSION */
+	set_fs(old_fs);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0))
+        blkdev_put(inode->i_bdev,BDEV_FILE);
+#elif (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	blkdev_close(inode,filp);
+#else
+	blkdev_release(inode);
+#endif /* LINUX_VERSION_CODE */
+
+	size = hd -> sizes[MINOR(dev)]<<1;
+	if ( ( bh = bread( dev, geo.start, blocksize) ) != NULL ) {
 		strncpy ( type,bh -> b_data, 4);
 		strncpy ( name,bh -> b_data + 4, 6);
         } else {
-		return;
+		return 0;
 	}
 	if ( (*(char *)bh -> b_data) & 0x80 ) {
 		EBCASC(name,6);
 	}
 	switch ( partition_type = get_partition_type(type) ) {
-	case ibm_partition_lnx1:
+	case ibm_partition_lnx1: 
+		offset = (geo.start + 1);
 		printk ( "(LNX1)/%6s:",name);
-		add_gd_partition( hd, MINOR(dev) + 1, 
-				  (dasd_info [di]->sizes.label_block + 1) <<
-				  dasd_info [di]->sizes.s2b_shift,
-				  (dasd_info [di]->sizes.blocks -
-				   dasd_info [di]->sizes.label_block - 1) <<
-				  dasd_info [di]->sizes.s2b_shift );
 		break;
 	case ibm_partition_vol1:
+		offset = 0;
+		size = 0;
 		printk ( "(VOL1)/%6s:",name);
 		break;
 	case ibm_partition_cms1:
 		printk ( "(CMS1)/%6s:",name);
 		if (* (((long *)bh->b_data) + 13) == 0) {
-		  /* disk holds a CMS filesystem */
-		  add_gd_partition( hd, MINOR(dev) + 1, 
-				    (dasd_info [di]->sizes.label_block + 1) <<
-				    dasd_info [di]->sizes.s2b_shift,
-				    (dasd_info [di]->sizes.blocks -
-				     dasd_info [di]->sizes.label_block) <<
-				    dasd_info [di]->sizes.s2b_shift );
-		  printk ("(CMS)");
+			/* disk holds a CMS filesystem */
+			offset = (geo.start + 1);
+			printk ("(CMS)");
 		} else {
-		  /* disk is reserved minidisk */
-		  int offset = (*(((long *)bh->b_data) + 13));
-		  int size = (*(((long *)bh->b_data) + 7)) - 1 - 
-		    (*(((long *)bh->b_data) + 13)) *
-		    ((*(((long *)bh->b_data) + 3)) >> 9);
-		  add_gd_partition( hd, MINOR(dev) + 1, 
-				    offset << dasd_info [di]->sizes.s2b_shift,
-				    size << dasd_info [di]->sizes.s2b_shift );
-		  printk ("(MDSK)");
+			/* disk is reserved minidisk */
+			// mdisk_setup_data.size[i] =
+			// (label[7] - 1 - label[13]) *
+			// (label[3] >> 9) >> 1;
+			long *label=(long*)bh->b_data;
+			blocksize = label[3];
+			offset = label[13];
+			size = (label[7]-1)*(blocksize>>9); 
+			printk ("(MDSK)");
 		}
 		break;
 	case ibm_partition_none:
 		printk ( "(nonl)/      :");
-/*
-		printk ( "%d %d %d ", MINOR(dev) + 1, 
-			 (dasd_info [di]->sizes.label_block + 1) <<
-			 dasd_info [di]->sizes.s2b_shift,
-			 (dasd_info [di]->sizes.blocks -
-			  dasd_info [di]->sizes.label_block - 1) <<
-			 dasd_info [di]->sizes.s2b_shift );
-*/
-		add_gd_partition( hd, MINOR(dev) + 1, 
-				  (dasd_info [di]->sizes.label_block + 1) <<
-				  dasd_info [di]->sizes.s2b_shift,
-				  (dasd_info [di]->sizes.blocks -
-				   dasd_info [di]->sizes.label_block - 1) <<
-				  dasd_info [di]->sizes.s2b_shift );
+		offset = (geo.start+1);
 		break;
+	default:
+		offset = 0;
+		size = 0;
+		
 	}
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+	add_gd_partition( hd, MINOR(dev), 0,size);
+	add_gd_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
+			  size-offset*(blocksize>>9));
+#else
+	add_partition( hd, MINOR(dev), 0,size,0);
+	add_partition( hd, MINOR(dev) + 1, offset * (blocksize >> 9),
+			  size-offset*(blocksize>>9) ,0 );
+#endif /* LINUX_VERSION */
 	printk ( "\n" );
 	bforget(bh);
+	return 1;
 }
 
diff -u --recursive --new-file v2.4.1/linux/fs/partitions/ibm.h linux/fs/partitions/ibm.h
--- v2.4.1/linux/fs/partitions/ibm.h	Wed Apr 12 09:47:30 2000
+++ linux/fs/partitions/ibm.h	Fri Feb 16 16:02:37 2001
@@ -1 +1 @@
-void ibm_partition (struct gendisk *hd, kdev_t dev);
+int ibm_partition(struct gendisk *, kdev_t, unsigned long, int);
diff -u --recursive --new-file v2.4.1/linux/fs/partitions/msdos.c linux/fs/partitions/msdos.c
--- v2.4.1/linux/fs/partitions/msdos.c	Sat Feb  3 19:51:30 2001
+++ linux/fs/partitions/msdos.c	Fri Feb 16 16:02:37 2001
@@ -68,6 +68,23 @@
 }
 
 /*
+ * partition_name() formats the short partition name into the supplied
+ * buffer, and returns a pointer to that buffer.
+ * Used by several partition types which makes conditional inclusion messy,
+ * use __attribute__ ((unused)) instead.
+ */
+static char __attribute__ ((unused))
+	*partition_name (struct gendisk *hd, int minor, char *buf)
+{
+#ifdef CONFIG_DEVFS_FS
+	sprintf(buf, "p%d", (minor & ((1 << hd->minor_shift) - 1)));
+	return buf;
+#else
+	return disk_name(hd, minor, buf);
+#endif
+}
+
+/*
  * 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
@@ -194,23 +211,27 @@
 	struct buffer_head *bh;
 	struct solaris_x86_vtoc *v;
 	struct solaris_x86_slice *s;
+	int mask = (1 << hd->minor_shift) - 1;
 	int i;
 	char buf[40];
 
 	if(!(bh = get_partition_table_block(hd, minor, 0)))
 		return;
 	v = (struct solaris_x86_vtoc *)(bh->b_data + 512);
-	if(v->v_sanity != SOLARIS_X86_VTOC_SANE) {
+	if(le32_to_cpu(v->v_sanity) != SOLARIS_X86_VTOC_SANE) {
 		brelse(bh);
 		return;
 	}
-	printk(" %s: <solaris:", disk_name(hd, minor, buf));
-	if(v->v_version != 1) {
-		printk("  cannot handle version %ld vtoc>\n", v->v_version);
+	printk(" %s: <solaris:", partition_name(hd, minor, buf));
+	if(le32_to_cpu(v->v_version) != 1) {
+		printk("  cannot handle version %d vtoc>\n",
+			le32_to_cpu(v->v_version));
 		brelse(bh);
 		return;
 	}
 	for(i=0; i<SOLARIS_X86_NUMSLICE; i++) {
+		if ((current_minor & mask) == 0)
+			break;
 		s = &v->v_slice[i];
 
 		if (s->s_size == 0)
@@ -220,7 +241,8 @@
 		 * 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);
+		add_gd_partition(hd, current_minor, le32_to_cpu(s->s_start)+offset,
+				 le32_to_cpu(s->s_size));
 		current_minor++;
 	}
 	brelse(bh);
@@ -237,21 +259,22 @@
 	for (lin_p = hd->part + 1 + minor;
 	     lin_p - hd->part - minor < 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)
+		if (lin_p->start_sect + lin_p->nr_sects <= le32_to_cpu(bsd_p->p_offset) ||
+		    lin_p->start_sect >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(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) 
+		if (lin_p->start_sect == le32_to_cpu(bsd_p->p_offset) && 
+			lin_p->nr_sects == le32_to_cpu(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) {
+		if (lin_p->start_sect <= le32_to_cpu(bsd_p->p_offset) && lin_p->start_sect 
+			+ lin_p->nr_sects >= le32_to_cpu(bsd_p->p_offset) + le32_to_cpu(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);
+				le32_to_cpu(bsd_p->p_offset),
+				le32_to_cpu(bsd_p->p_size));
 #endif
 			break;
 		}
@@ -259,14 +282,15 @@
 #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);
+			le32_to_cpu(bsd_p->p_offset), le32_to_cpu(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);
+	add_gd_partition(hd, current_minor, le32_to_cpu(bsd_p->p_offset),
+			 le32_to_cpu(bsd_p->p_size));
 	current_minor++;
 }
 
@@ -285,20 +309,20 @@
 	if (!(bh = get_partition_table_block(hd, minor, 0)))
 		return;
 	l = (struct bsd_disklabel *) (bh->b_data+512);
-	if (l->d_magic != BSD_DISKMAGIC) {
+	if (le32_to_cpu(l->d_magic) != BSD_DISKMAGIC) {
 		brelse(bh);
 		return;
 	}
-	printk(" %s:", disk_name(hd, minor, buf));
+	printk(" %s:", partition_name(hd, minor, buf));
 	printk((type == OPENBSD_PARTITION) ? " <openbsd:" :
 	       (type == NETBSD_PARTITION) ? " <netbsd:" : " <bsd:");
 
 	max_partitions = ((type == OPENBSD_PARTITION) ? OPENBSD_MAXPARTITIONS
 			                              : BSD_MAXPARTITIONS);
-	if (l->d_npartitions < max_partitions)
-		max_partitions = l->d_npartitions;
+	if (le16_to_cpu(l->d_npartitions) < max_partitions)
+		max_partitions = le16_to_cpu(l->d_npartitions);
 	for (p = l->d_partitions; p - l->d_partitions <  max_partitions; p++) {
-		if ((current_minor & mask) >= (4 + hd->max_p))
+		if ((current_minor & mask) == 0)
 			break;
 
 		if (p->p_fstype != BSD_FS_UNUSED) 
@@ -332,7 +356,7 @@
 		brelse(bh);
 		return;
 	}
-	printk(" %s: <unixware:", disk_name(hd, minor, buf));
+	printk(" %s: <unixware:", partition_name(hd, minor, buf));
 	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) {
@@ -352,6 +376,49 @@
 }
 #endif
 
+#ifdef CONFIG_MINIX_SUBPARTITION
+/*
+ * Minix 2.0.0/2.0.2 subpartition support.
+ * Anand Krishnamurthy <anandk@wiproge.med.ge.com>
+ * Rajeev V. Pillai    <rajeevvp@yahoo.com>
+ */
+static void minix_partition(struct gendisk *hd, int minor)
+{
+	struct buffer_head *bh;
+	struct partition *p;
+	int mask = (1 << hd->minor_shift) - 1;
+	int i;
+	char buf[40];
+
+	if (!(bh = get_partition_table_block(hd, minor, 0)))
+		return;
+	bh->b_state = 0;
+
+	p = (struct partition *)(bh->b_data + 0x1be);
+
+	/* The first sector of a Minix partition can have either
+	 * a secondary MBR describing its subpartitions, or
+	 * the normal boot sector. */
+	if ((*(__u16 *) (bh->b_data + 510)) != cpu_to_le16(MSDOS_LABEL_MAGIC) &&
+	    SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */
+
+		printk(" %s: <minix:", partition_name(hd, minor, buf));
+		for (i = 0; i < MINIX_NR_SUBPARTITIONS; i++, p++) {
+			if ((current_minor & mask) == 0)
+				break;
+			/* add each partition in use */
+			if (SYS_IND(p) == MINIX_PARTITION) {
+				add_gd_partition(hd, current_minor,
+					      START_SECT(p), NR_SECTS(p));
+				current_minor++;
+			}
+		}
+		printk(" >\n");
+	}
+	brelse(bh);
+}
+#endif /* CONFIG_MINIX_SUBPARTITION */
+ 
 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;
@@ -499,6 +566,11 @@
 		    SYS_IND(p) == NETBSD_PARTITION ||
 		    SYS_IND(p) == OPENBSD_PARTITION)
 			bsd_disklabel_partition(hd, minor, SYS_IND(p));
+#endif
+#ifdef CONFIG_MINIX_SUBPARTITION
+		if (SYS_IND(p) == MINIX_PARTITION) {
+			minix_partition(hd, minor);
+		}
 #endif
 #ifdef CONFIG_UNIXWARE_DISKLABEL
 		if (SYS_IND(p) == UNIXWARE_PARTITION)
diff -u --recursive --new-file v2.4.1/linux/fs/partitions/osf.c linux/fs/partitions/osf.c
--- v2.4.1/linux/fs/partitions/osf.c	Wed Feb 16 15:42:06 2000
+++ linux/fs/partitions/osf.c	Fri Feb 16 16:02:37 2001
@@ -62,21 +62,21 @@
 	}
 	label = (struct disklabel *) (bh->b_data+64);
 	partition = label->d_partitions;
-	if (label->d_magic != DISKLABELMAGIC) {
+	if (le32_to_cpu(label->d_magic) != DISKLABELMAGIC) {
 		brelse(bh);
 		return 0;
 	}
-	if (label->d_magic2 != DISKLABELMAGIC) {
+	if (le32_to_cpu(label->d_magic2) != DISKLABELMAGIC) {
 		brelse(bh);
 		return 0;
 	}
-	for (i = 0 ; i < label->d_npartitions; i++, partition++) {
+	for (i = 0 ; i < le16_to_cpu(label->d_npartitions); i++, partition++) {
 		if ((current_minor & mask) == 0)
 		        break;
-		if (partition->p_size)
+		if (le32_to_cpu(partition->p_size))
 			add_gd_partition(hd, current_minor,
-				first_sector+partition->p_offset,
-				partition->p_size);
+				first_sector+le32_to_cpu(partition->p_offset),
+				le32_to_cpu(partition->p_size));
 		current_minor++;
 	}
 	printk("\n");
diff -u --recursive --new-file v2.4.1/linux/fs/pipe.c linux/fs/pipe.c
--- v2.4.1/linux/fs/pipe.c	Thu Nov 16 13:18:26 2000
+++ linux/fs/pipe.c	Fri Feb  9 11:29:44 2001
@@ -7,11 +7,12 @@
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/poll.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/init.h>
 
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 
 /*
  * We use a start+len construction, which provides full use of the 
diff -u --recursive --new-file v2.4.1/linux/fs/qnx4/inode.c linux/fs/qnx4/inode.c
--- v2.4.1/linux/fs/qnx4/inode.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/qnx4/inode.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/qnx4_fs.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
diff -u --recursive --new-file v2.4.1/linux/fs/qnx4/truncate.c linux/fs/qnx4/truncate.c
--- v2.4.1/linux/fs/qnx4/truncate.c	Tue Sep  1 10:43:13 1998
+++ linux/fs/qnx4/truncate.c	Fri Feb  9 11:29:44 2001
@@ -13,7 +13,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/qnx4_fs.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
diff -u --recursive --new-file v2.4.1/linux/fs/read_write.c linux/fs/read_write.c
--- v2.4.1/linux/fs/read_write.c	Fri Sep 22 14:21:19 2000
+++ linux/fs/read_write.c	Fri Feb  9 11:29:44 2001
@@ -4,7 +4,7 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  */
 
-#include <linux/malloc.h> 
+#include <linux/slab.h> 
 #include <linux/stat.h>
 #include <linux/fcntl.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/fs/reiserfs/namei.c linux/fs/reiserfs/namei.c
--- v2.4.1/linux/fs/reiserfs/namei.c	Sat Feb  3 19:51:31 2001
+++ linux/fs/reiserfs/namei.c	Sun Feb 18 19:49:44 2001
@@ -1,11 +1,21 @@
 /*
  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
+ *
+ * Trivial changes by Alan Cox to remove EHASHCOLLISION for compatibility
+ *
+ * Trivial Changes:
+ * Rights granted to Hans Reiser to redistribute under other terms providing
+ * he accepts all liability including but not limited to patent, fitness
+ * for purpose, and direct or indirect claims arising from failure to perform.
+ *
+ * NO WARRANTY
  */
 
 #ifdef __KERNEL__
 
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/bitops.h>
 #include <linux/reiserfs_fs.h>
 #include <linux/smp_lock.h>
 
@@ -472,7 +482,7 @@
 	    if (buffer != small_buf)
 		reiserfs_kfree (buffer, buflen, dir->i_sb);
 	    pathrelse (&path);
-	    return -EHASHCOLLISION;//EBADSLT
+	    return -EBUSY; //HASHCOLLISION;//EBADSLT
 	}
 	/* adjust offset of directory enrty */
 	deh->deh_offset = cpu_to_le32 (SET_GENERATION_NUMBER (deh_offset (deh), gen_number));
@@ -485,7 +495,7 @@
 	    if (buffer != small_buf)
 		reiserfs_kfree (buffer, buflen, dir->i_sb);
 	    pathrelse (&path);
-	    return -EHASHCOLLISION;
+	    return -EBUSY;
 	}
     } else {
 	deh->deh_offset = cpu_to_le32 (SET_GENERATION_NUMBER (le32_to_cpu (deh->deh_offset), 0));
diff -u --recursive --new-file v2.4.1/linux/fs/reiserfs/tail_conversion.c linux/fs/reiserfs/tail_conversion.c
--- v2.4.1/linux/fs/reiserfs/tail_conversion.c	Sat Feb  3 19:51:31 2001
+++ linux/fs/reiserfs/tail_conversion.c	Mon Feb 19 10:07:32 2001
@@ -92,7 +92,7 @@
     /* Move bytes from the direct items to the new unformatted node
        and delete them. */
     while (1)  {
-	int item_len, first_direct;
+	int tail_size;
 
 	/* end_key.k_offset is set so, that we will always have found
            last item of the file */
@@ -103,13 +103,11 @@
 #ifdef CONFIG_REISERFS_CHECK
 	if (!is_direct_le_ih (p_le_ih))
 	    reiserfs_panic (sb, "vs-14055: direct2indirect: "
-			    "direct item expected, found %h", p_le_ih);
+			    "direct item expected(%k), found %h", 
+				&end_key, p_le_ih);
 #endif
-	if ((le_ih_k_offset (p_le_ih) & (n_blk_size - 1)) == 1)
-	    first_direct = 1;
-	else
-	    first_direct = 0;
-	item_len = le16_to_cpu (p_le_ih->ih_item_len);
+	tail_size = (le_ih_k_offset (p_le_ih) & (n_blk_size - 1))
+	    + ih_item_len(p_le_ih) - 1;
 
 	/* we only send the unbh pointer if the buffer is not up to date.
 	** this avoids overwriting good data from writepage() with old data
@@ -123,7 +121,7 @@
 	n_retval = reiserfs_delete_item (th, path, &end_key, inode, 
 	                                 up_to_date_bh) ;
 
-	if (first_direct && item_len == n_retval)
+	if (tail_size == n_retval)
 	    // done: file does not have direct items anymore
 	    break;
 
diff -u --recursive --new-file v2.4.1/linux/fs/romfs/inode.c linux/fs/romfs/inode.c
--- v2.4.1/linux/fs/romfs/inode.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/romfs/inode.c	Fri Feb  9 11:29:44 2001
@@ -67,7 +67,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/romfs_fs.h>
 #include <linux/fs.h>
 #include <linux/locks.h>
diff -u --recursive --new-file v2.4.1/linux/fs/select.c linux/fs/select.c
--- v2.4.1/linux/fs/select.c	Thu Nov 16 12:54:18 2000
+++ linux/fs/select.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
  *     of fds to overcome nfds < 16390 descriptors limit (Tigran Aivazian).
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/poll.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/ChangeLog linux/fs/smbfs/ChangeLog
--- v2.4.1/linux/fs/smbfs/ChangeLog	Mon Aug 14 13:31:10 2000
+++ linux/fs/smbfs/ChangeLog	Fri Feb 16 16:03:24 2001
@@ -1,5 +1,14 @@
 ChangeLog for smbfs.
 
+2001-02-10 Urban Widmark <urban@teststation.com>
+
+	* dir.c: replace non-bigmem safe cache with cache code from ncpfs
+	  and fix some other bigmem bugs in smbfs.
+	* inode.c: root dentry not properly initialized
+	* proc.c, sock.c: adjust max parameters & max data to follow max_xmit
+	  lots of servers were having find_next trouble with this.
+	* proc.c: use documented write method of truncating (NetApp fix)
+
 2000-08-14 Urban Widmark <urban@svenskatest.se>
 
 	* dir.c: support case sensitive shares
@@ -31,7 +40,7 @@
 
 	* *.c: replace ugly #ifdef's with less ugly debug macros.
 
-2000-01-?? cpg@aladdin.de
+2000-01-03 Christian Groessler <cpg@aladdin.de>
 
 	* proc.c: added posix semantics for unlink
 
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/Makefile linux/fs/smbfs/Makefile
--- v2.4.1/linux/fs/smbfs/Makefile	Fri Dec 29 14:07:23 2000
+++ linux/fs/smbfs/Makefile	Fri Feb 16 16:04:24 2001
@@ -20,5 +20,6 @@
 #EXTRA_CFLAGS += -DSMBFS_DEBUG_VERBOSE
 #EXTRA_CFLAGS += -DDEBUG_SMB_MALLOC
 #EXTRA_CFLAGS += -DDEBUG_SMB_TIMESTAMP
+#EXTRA_CFLAGS += -Werror
 
 include $(TOPDIR)/Rules.make
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/cache.c linux/fs/smbfs/cache.c
--- v2.4.1/linux/fs/smbfs/cache.c	Wed Nov  8 19:01:34 2000
+++ linux/fs/smbfs/cache.c	Fri Feb 16 16:03:24 2001
@@ -4,8 +4,7 @@
  * Copyright (C) 1997 by Bill Hawes
  *
  * Routines to support directory cacheing using the page cache.
- * Right now this only works for smbfs, but will be generalized
- * for use with other filesystems.
+ * This cache code is almost directly taken from ncpfs.
  *
  * Please add a note about your changes to smbfs in the ChangeLog file.
  */
@@ -22,271 +21,222 @@
 
 #include "smb_debug.h"
 
-
-static inline struct address_space * 
-get_cache_inode(struct cache_head *cachep)
-{
-	return page_cache_entry((unsigned long) cachep)->mapping;
-}
-
 /*
- * Try to reassemble the old dircache. If we fail - set ->valid to 0.
- * In any case, get at least the page at offset 0 (with ->valid==0 if
- * the old one didn't make it, indeed).
+ * Force the next attempt to use the cache to be a timeout.
+ * If we can't find the page that's fine, it will cause a refresh.
  */
-struct cache_head *
-smb_get_dircache(struct dentry * dentry)
+void
+smb_invalid_dir_cache(struct inode * dir)
 {
-	struct address_space * mapping = &dentry->d_inode->i_data;
-	struct cache_head * cachep = NULL;
-	struct page *page;
-
-	page = find_lock_page(mapping, 0);
-	if (!page) {
-		/* Sorry, not even page 0 around */
-		page = grab_cache_page(mapping, 0);
-		if (!page)
-			goto out;
-		cachep = kmap(page);
-		memset((char*)cachep, 0, PAGE_SIZE);
+	struct smb_sb_info *server = server_from_inode(dir);
+	union  smb_dir_cache *cache = NULL;
+	struct page *page = NULL;
+
+	page = grab_cache_page(&dir->i_data, 0);
+	if (!page)
 		goto out;
-	}
-	cachep = kmap(page);
-	if (cachep->valid) {
-		/*
-		 * OK, at least the page 0 survived and seems to be promising.
-		 * Let's try to reassemble the rest.
-		 */
-		struct cache_index * index = cachep->index;
-		unsigned long offset;
-		int i;
-
-		for (offset = 0, i = 0; i < cachep->pages; i++, index++) {
-			offset += PAGE_SIZE;
-			page = find_lock_page(mapping,offset>>PAGE_CACHE_SHIFT);
-			if (!page) {
-				/* Alas, poor Yorick */
-				cachep->valid = 0;
-				goto out;
-			}
-			index->block = kmap(page);
-		}
-	}
-out:
-	return cachep;
-}
 
-/*
- * Unlock and release the data blocks.
- */
-static void
-smb_free_cache_blocks(struct cache_head * cachep)
-{
-	struct cache_index * index = cachep->index;
-	struct page * page;
-	int i;
-
-	VERBOSE("freeing %d blocks\n", cachep->pages);
-	for (i = 0; i < cachep->pages; i++, index++) {
-		if (!index->block)
-			continue;
-		page = page_cache_entry((unsigned long) index->block);
-		index->block = NULL;
-		kunmap(page);
-		UnlockPage(page);
-		page_cache_release(page);
-	}
-}
+	if (!Page_Uptodate(page))
+		goto out_unlock;
+
+	cache = kmap(page);
+	cache->head.time = jiffies - SMB_MAX_AGE(server);
 
-/*
- * Unlocks and releases the dircache.
- */
-void
-smb_free_dircache(struct cache_head * cachep)
-{
-	struct page *page;
-	VERBOSE("freeing cache\n");
-	smb_free_cache_blocks(cachep);
-	page = page_cache_entry((unsigned long) cachep);
 	kunmap(page);
+	SetPageUptodate(page);
+out_unlock:
 	UnlockPage(page);
 	page_cache_release(page);
+out:
 }
 
 /*
- * Initializes the dircache. We release any existing data blocks,
- * and then clear the cache_head structure.
+ * Mark all dentries for 'parent' as invalid, forcing them to be re-read
  */
 void
-smb_init_dircache(struct cache_head * cachep)
+smb_invalidate_dircache_entries(struct dentry *parent)
 {
-	VERBOSE("initializing cache, %d blocks\n", cachep->pages);
-	smb_free_cache_blocks(cachep);
-	memset(cachep, 0, sizeof(struct cache_head));
+	struct smb_sb_info *server = server_from_dentry(parent);
+	struct list_head *next;
+	struct dentry *dentry;
+
+	spin_lock(&dcache_lock);
+	next = parent->d_subdirs.next;
+	while (next != &parent->d_subdirs) {
+		dentry = list_entry(next, struct dentry, d_child);
+		dentry->d_fsdata = NULL;
+		smb_age_dentry(server, dentry);
+		next = next->next;
+	}
+	spin_unlock(&dcache_lock);
 }
 
-/*
- * Add a new entry to the cache.  This assumes that the
- * entries are coming in order and are added to the end.
- */
-void
-smb_add_to_cache(struct cache_head * cachep, struct cache_dirent *entry,
-			off_t fpos)
-{
-	struct address_space * mapping = get_cache_inode(cachep);
-	struct cache_index * index;
-	struct cache_block * block;
-	struct page *page;
-	unsigned long page_off;
-	unsigned int nent, offset, len = entry->len;
-	unsigned int needed = len + sizeof(struct cache_entry);
-
-	VERBOSE("cache %p, status %d, adding %.*s at %ld\n",
-		mapping, cachep->status, entry->len, entry->name, fpos);
 
+static int
+smb_d_validate(struct dentry *dentry)
+{
+	unsigned long dent_addr = (unsigned long) dentry;
+	unsigned long min_addr = PAGE_OFFSET;
+	unsigned long align_mask = 0x0F;
+	unsigned int len;
+	int valid = 0;
+
+	if (dent_addr < min_addr)
+		goto bad_addr;
+	if (dent_addr > (unsigned long)high_memory - sizeof(struct dentry))
+		goto bad_addr;
+	if ((dent_addr & ~align_mask) != dent_addr)
+		goto bad_align;
+	if ((!kern_addr_valid(dent_addr)) || (!kern_addr_valid(dent_addr -1 +
+						       sizeof(struct dentry))))
+		goto bad_addr;
 	/*
-	 * Don't do anything if we've had an error ...
+	 * Looks safe enough to dereference ...
 	 */
-	if (cachep->status)
+	len = dentry->d_name.len;
+	if (len > SMB_MAXPATHLEN)
 		goto out;
-
-	index = &cachep->index[cachep->idx];
-	if (!index->block)
-		goto get_block;
-
-	/* space available? */
-	if (needed < index->space) {
-	add_entry:
-		nent = index->num_entries;
-		index->num_entries++;
-		index->space -= needed;
-		offset = index->space + 
-			 index->num_entries * sizeof(struct cache_entry);
-		block = index->block;
-		memcpy(&block->cb_data.names[offset], entry->name, len);
-		block->cb_data.table[nent].namelen = len;
-		block->cb_data.table[nent].offset = offset;
-		block->cb_data.table[nent].ino = entry->ino;
-		cachep->entries++;
-
-		VERBOSE("added entry %.*s, len=%d, pos=%ld, entries=%d\n",
-			entry->len, entry->name, len, fpos, cachep->entries);
-		return;
-	}
-	/*
-	 * This block is full ... advance the index.
-	 */
-	cachep->idx++;
-	if (cachep->idx > NINDEX) /* not likely */
-		goto out_full;
-	index++;
 	/*
-	 * Get the next cache block. We don't care for its contents.
+	 * Note: d_validate doesn't dereference the parent pointer ...
+	 * just combines it with the name hash to find the hash chain.
 	 */
-get_block:
-	cachep->pages++;
-	page_off = PAGE_SIZE + (cachep->idx << PAGE_SHIFT);
-	page = grab_cache_page(mapping, page_off>>PAGE_CACHE_SHIFT);
-	if (page) {
-		block = kmap(page);
-		index->block = block;
-		index->space = PAGE_SIZE;
-		goto add_entry;
-	}
-	/*
-	 * On failure, just set the return status ...
-	 */
-out_full:
-	cachep->status = -ENOMEM;
+	valid = d_validate(dentry, dentry->d_parent, dentry->d_name.hash, len);
 out:
-	return;
-}
+	return valid;
 
-int
-smb_find_in_cache(struct cache_head * cachep, off_t pos, 
-		struct cache_dirent *entry)
-{
-	struct cache_index * index = cachep->index;
-	struct cache_block * block;
-	unsigned int i, nent, offset = 0;
-	off_t next_pos = 2;
-
-	VERBOSE("smb_find_in_cache: cache %p, looking for pos=%ld\n",
-		cachep, pos);
-	for (i = 0; i < cachep->pages; i++, index++)
-	{
-		if (pos < next_pos)
-			break;
-		nent = pos - next_pos;
-		next_pos += index->num_entries;
-		if (pos >= next_pos)
-			continue;
-		/*
-		 * The entry is in this block. Note: we return
-		 * then name as a reference with _no_ null byte.
-		 */
-		block = index->block;
-		entry->ino = block->cb_data.table[nent].ino;
-		entry->len = block->cb_data.table[nent].namelen;
-		offset = block->cb_data.table[nent].offset;
-		entry->name = &block->cb_data.names[offset];
-
-		VERBOSE("found %.*s, len=%d, pos=%ld\n",
-			entry->len, entry->name, entry->len, pos);
-		break;
-	}
-	return offset;
+bad_addr:
+	printk(KERN_ERR "smb_d_validate: invalid address %lx\n", dent_addr);
+	goto out;
+bad_align:
+	printk(KERN_ERR "smb_d_validate: unaligned address %lx\n", dent_addr);
+	goto out;
 }
 
-int
-smb_refill_dircache(struct cache_head * cachep, struct dentry *dentry)
+/*
+ * dget, but require that fpos and parent matches what the dentry contains.
+ * dentry is not known to be a valid pointer at entry.
+ */
+struct dentry *
+smb_dget_fpos(struct dentry *dentry, struct dentry *parent, unsigned long fpos)
 {
-	struct inode * inode = dentry->d_inode;
-	int result;
+	struct dentry *dent = dentry;
+	struct list_head *next;
 
-	VERBOSE("smb_refill_dircache: cache %s/%s, blocks=%d\n",
-		DENTRY_PATH(dentry), cachep->pages);
-	/*
-	 * Fill the cache, starting at position 2.
-	 */
-retry:
-	inode->u.smbfs_i.cache_valid |= SMB_F_CACHEVALID;
-	result = smb_proc_readdir(dentry, 2, cachep);
-	if (result < 0)
-	{
-		PARANOIA("readdir failed, result=%d\n", result);
-		goto out;
+	if (smb_d_validate(dent)) {
+		if (dent->d_parent == parent &&
+		    (unsigned long)dent->d_fsdata == fpos) {
+			if (!dent->d_inode) {
+				dput(dent);
+				dent = NULL;
+			}
+			return dent;
+		}
+		dput(dent);
 	}
 
-	/*
-	 * Check whether the cache was invalidated while
-	 * we were doing the scan ...
-	 */
-	if (!(inode->u.smbfs_i.cache_valid & SMB_F_CACHEVALID))
-	{
-		PARANOIA("cache invalidated, retrying\n");
-		goto retry;
+	/* If a pointer is invalid, we search the dentry. */
+	spin_lock(&dcache_lock);
+	next = parent->d_subdirs.next;
+	while (next != &parent->d_subdirs) {
+		dent = list_entry(next, struct dentry, d_child);
+		if ((unsigned long)dent->d_fsdata == fpos) {
+			if (dent->d_inode)
+				dget_locked(dent);
+			else
+				dent = NULL;
+			goto out_unlock;
+		}
+		next = next->next;
 	}
+	dent = NULL;
+out_unlock:
+	spin_unlock(&dcache_lock);
+	return dent;
+}
+
+
+/*
+ * Create dentry/inode for this file and add it to the dircache.
+ */
+int
+smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+	       struct smb_cache_control *ctrl, struct qstr *qname,
+	       struct smb_fattr *entry)
+{
+	struct dentry *newdent, *dentry = filp->f_dentry;
+	struct inode *newino, *inode = dentry->d_inode;
+	struct smb_cache_control ctl = *ctrl;
+	int valid = 0;
+	ino_t ino = 0;
+
+	qname->hash = full_name_hash(qname->name, qname->len);
+
+	if (dentry->d_op && dentry->d_op->d_hash)
+		if (dentry->d_op->d_hash(dentry, qname) != 0)
+			goto end_advance;
+
+	newdent = d_lookup(dentry, qname);
+
+	if (!newdent) {
+		newdent = d_alloc(dentry, qname);
+		if (!newdent)
+			goto end_advance;
+	} else
+		memcpy((char *) newdent->d_name.name, qname->name,
+		       newdent->d_name.len);
+
+	if (!newdent->d_inode) {
+		smb_renew_times(newdent);
+		entry->f_ino = iunique(inode->i_sb, 2);
+		newino = smb_iget(inode->i_sb, entry);
+		if (newino) {
+			smb_new_dentry(newdent);
+			d_add(newdent, newino);
+		}
+	} else
+		smb_set_inode_attr(newdent->d_inode, entry);
 
-	result = cachep->status;
-	if (!result)
-	{
-		cachep->valid = 1;
+        if (newdent->d_inode) {
+		ino = newdent->d_inode->i_ino;
+		newdent->d_fsdata = (void *) ctl.fpos;
+		smb_new_dentry(newdent);
 	}
-	VERBOSE("cache %s/%s status=%d, entries=%d\n",
-		DENTRY_PATH(dentry), cachep->status, cachep->entries);
-out:
-	return result;
-}
 
-void
-smb_invalid_dir_cache(struct inode * dir)
-{
-	/*
-	 * Get rid of any unlocked pages, and clear the
-	 * 'valid' flag in case a scan is in progress.
-	 */
-	invalidate_inode_pages(dir);
-	dir->u.smbfs_i.cache_valid &= ~SMB_F_CACHEVALID;
-	dir->u.smbfs_i.oldmtime = 0;
+	if (ctl.idx >= SMB_DIRCACHE_SIZE) {
+		if (ctl.page) {
+			kunmap(ctl.page);
+			SetPageUptodate(ctl.page);
+			UnlockPage(ctl.page);
+			page_cache_release(ctl.page);
+		}
+		ctl.cache = NULL;
+		ctl.idx  -= SMB_DIRCACHE_SIZE;
+		ctl.ofs  += 1;
+		ctl.page  = grab_cache_page(&inode->i_data, ctl.ofs);
+		if (ctl.page)
+			ctl.cache = kmap(ctl.page);
+	}
+	if (ctl.cache) {
+		ctl.cache->dentry[ctl.idx] = newdent;
+		valid = 1;
+	}
+	dput(newdent);
+
+end_advance:
+	if (!valid)
+		ctl.valid = 0;
+	if (!ctl.filled && (ctl.fpos == filp->f_pos)) {
+		if (!ino)
+			ino = find_inode_number(dentry, qname);
+		if (!ino)
+			ino = iunique(inode->i_sb, 2);
+		ctl.filled = filldir(dirent, qname->name, qname->len,
+				     filp->f_pos, ino, DT_UNKNOWN);
+		if (!ctl.filled)
+			filp->f_pos += 1;
+	}
+	ctl.fpos += 1;
+	ctl.idx  += 1;
+	*ctrl = ctl;
+	return (ctl.valid || !ctl.filled);
 }
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
--- v2.4.1/linux/fs/smbfs/dir.c	Sun Dec 10 08:48:18 2000
+++ linux/fs/smbfs/dir.c	Fri Feb 16 16:03:24 2001
@@ -19,8 +19,6 @@
 
 #include "smb_debug.h"
 
-#define SMBFS_MAX_AGE 5*HZ
-
 static int smb_readdir(struct file *, void *, filldir_t);
 static int smb_dir_open(struct inode *, struct file *);
 
@@ -52,27 +50,39 @@
 	setattr:	smb_notify_change,
 };
 
+/*
+ * Read a directory, using filldir to fill the dirent memory.
+ * smb_proc_readdir does the actual reading from the smb server.
+ *
+ * The cache code is almost directly taken from ncpfs
+ */
 static int 
 smb_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
 	struct dentry *dentry = filp->f_dentry;
 	struct inode *dir = dentry->d_inode;
-	struct cache_head *cachep;
+	struct smb_sb_info *server = server_from_dentry(dentry);
+	union  smb_dir_cache *cache = NULL;
+	struct smb_cache_control ctl;
+	struct page *page = NULL;
 	int result;
 
+	ctl.page  = NULL;
+	ctl.cache = NULL;
+
 	VERBOSE("reading %s/%s, f_pos=%d\n",
 		DENTRY_PATH(dentry),  (int) filp->f_pos);
 
 	result = 0;
-	switch ((unsigned int) filp->f_pos)
-	{
+	switch ((unsigned int) filp->f_pos) {
 	case 0:
 		if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
 			goto out;
 		filp->f_pos = 1;
+		/* fallthrough */
 	case 1:
 		if (filldir(dirent, "..", 2, 1,
-				dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
+			    dentry->d_parent->d_inode->i_ino, DT_DIR) < 0)
 			goto out;
 		filp->f_pos = 2;
 	}
@@ -83,61 +93,119 @@
 	result = smb_revalidate_inode(dentry);
 	if (result)
 		goto out;
-	/*
-	 * Get the cache pointer ...
-	 */
-	result = -EIO;
-	cachep = smb_get_dircache(dentry);
-	if (!cachep)
-		goto out;
 
-	/*
-	 * Make sure the cache is up-to-date.
-	 *
-	 * To detect changes on the server we refill on each "new" access.
-	 *
-	 * Directory mtime would be nice to use for finding changes,
-	 * unfortunately some servers (NT4) doesn't update on local changes.
-	 */
-	if (!cachep->valid || filp->f_pos == 2)
-	{
-		result = smb_refill_dircache(cachep, dentry);
-		if (result)
-			goto out_free;
-	}
 
-	result = 0;
-
-	while (1)
-	{
-		struct cache_dirent this_dirent, *entry = &this_dirent;
+	page = grab_cache_page(&dir->i_data, 0);
+	if (!page)
+		goto read_really;
+
+	ctl.cache = cache = kmap(page);
+	ctl.head  = cache->head;
+
+	if (!Page_Uptodate(page) || !ctl.head.eof) {
+		VERBOSE("%s/%s, page uptodate=%d, eof=%d\n",
+			 DENTRY_PATH(dentry), Page_Uptodate(page),ctl.head.eof);
+		goto init_cache;
+	}
+
+	if (filp->f_pos == 2) {
+		if (jiffies - ctl.head.time >= SMB_MAX_AGE(server))
+			goto init_cache;
 
-		if (!smb_find_in_cache(cachep, filp->f_pos, entry))
-			break;
 		/*
-		 * Check whether to look up the inode number.
+		 * N.B. ncpfs checks mtime of dentry too here, we don't.
+		 *   1. common smb servers do not update mtime on dir changes
+		 *   2. it requires an extra smb request
+		 *      (revalidate has the same timeout as ctl.head.time)
+		 *
+		 * Instead smbfs invalidates its own cache on local changes
+		 * and remote changes are not seen until timeout.
 		 */
-		if (!entry->ino) {
-			struct qstr qname;
-			/* N.B. Make cache_dirent name a qstr! */
-			qname.name = entry->name;
-			qname.len  = entry->len;
-			entry->ino = find_inode_number(dentry, &qname);
-			if (!entry->ino)
-				entry->ino = iunique(dentry->d_sb, 2);
-		}
-
-		if (filldir(dirent, entry->name, entry->len, 
-				    filp->f_pos, entry->ino, DT_UNKNOWN) < 0)
-			break;
-		filp->f_pos += 1;
 	}
 
-	/*
-	 * Release the dircache.
-	 */
-out_free:
-	smb_free_dircache(cachep);
+	if (filp->f_pos > ctl.head.end)
+		goto finished;
+
+	ctl.fpos = filp->f_pos + (SMB_DIRCACHE_START - 2);
+	ctl.ofs  = ctl.fpos / SMB_DIRCACHE_SIZE;
+	ctl.idx  = ctl.fpos % SMB_DIRCACHE_SIZE;
+
+	for (;;) {
+		if (ctl.ofs != 0) {
+			ctl.page = find_lock_page(&dir->i_data, ctl.ofs);
+			if (!ctl.page)
+				goto invalid_cache;
+			ctl.cache = kmap(ctl.page);
+			if (!Page_Uptodate(ctl.page))
+				goto invalid_cache;
+		}
+		while (ctl.idx < SMB_DIRCACHE_SIZE) {
+			struct dentry *dent;
+			int res;
+
+			dent = smb_dget_fpos(ctl.cache->dentry[ctl.idx],
+					     dentry, filp->f_pos);
+			if (!dent)
+				goto invalid_cache;
+
+			res = filldir(dirent, dent->d_name.name,
+				      dent->d_name.len, filp->f_pos,
+				      dent->d_inode->i_ino, DT_UNKNOWN);
+			dput(dent);
+			if (res)
+				goto finished;
+			filp->f_pos += 1;
+			ctl.idx += 1;
+			if (filp->f_pos > ctl.head.end)
+				goto finished;
+		}
+		if (ctl.page) {
+			kunmap(ctl.page);
+			SetPageUptodate(ctl.page);
+			UnlockPage(ctl.page);
+			page_cache_release(ctl.page);
+			ctl.page = NULL;
+		}
+		ctl.idx  = 0;
+		ctl.ofs += 1;
+	}
+invalid_cache:
+	if (ctl.page) {
+		kunmap(ctl.page);
+		UnlockPage(ctl.page);
+		page_cache_release(ctl.page);
+		ctl.page = NULL;
+	}
+	ctl.cache = cache;
+init_cache:
+	smb_invalidate_dircache_entries(dentry);
+	ctl.head.time = jiffies;
+	ctl.head.eof = 0;
+	ctl.fpos = 2;
+	ctl.ofs = 0;
+	ctl.idx = SMB_DIRCACHE_START;
+	ctl.filled = 0;
+	ctl.valid  = 1;
+read_really:
+	result = smb_proc_readdir(filp, dirent, filldir, &ctl);
+	if (ctl.idx == -1)
+		goto invalid_cache;	/* retry */
+	ctl.head.end = ctl.fpos - 1;
+	ctl.head.eof = ctl.valid;
+finished:
+	if (page) {
+		cache->head = ctl.head;
+		kunmap(page);
+		SetPageUptodate(page);
+		UnlockPage(page);
+		page_cache_release(page);
+	}
+	if (ctl.page) {
+		kunmap(ctl.page);
+		SetPageUptodate(ctl.page);
+		UnlockPage(ctl.page);
+		page_cache_release(ctl.page);
+	}
 out:
 	return result;
 }
@@ -204,16 +272,17 @@
 static int
 smb_lookup_validate(struct dentry * dentry, int flags)
 {
+	struct smb_sb_info *server = server_from_dentry(dentry);
 	struct inode * inode = dentry->d_inode;
 	unsigned long age = jiffies - dentry->d_time;
 	int valid;
 
 	/*
 	 * The default validation is based on dentry age:
-	 * we believe in dentries for 5 seconds.  (But each
+	 * we believe in dentries for a few seconds.  (But each
 	 * successful server lookup renews the timestamp.)
 	 */
-	valid = (age <= SMBFS_MAX_AGE);
+	valid = (age <= SMB_MAX_AGE(server));
 #ifdef SMBFS_DEBUG_VERBOSE
 	if (!valid)
 		VERBOSE("%s/%s not valid, age=%lu\n", 
@@ -286,6 +355,22 @@
 }
 
 /*
+ * Initialize a new dentry
+ */
+void
+smb_new_dentry(struct dentry *dentry)
+{
+	struct smb_sb_info *server = server_from_dentry(dentry);
+
+	if (server->mnt->flags & SMB_MOUNT_CASE)
+		dentry->d_op = &smbfs_dentry_operations_case;
+	else
+		dentry->d_op = &smbfs_dentry_operations;
+	dentry->d_time = jiffies;
+}
+
+
+/*
  * Whenever a lookup succeeds, we know the parent directories
  * are all valid, so we want to update the dentry timestamps.
  * N.B. Move this to dcache?
@@ -441,6 +526,7 @@
 	if (!d_unhashed(dentry))
 		goto out;
 
+	smb_invalid_dir_cache(dir);
 	error = smb_proc_rmdir(dentry);
 
 out:
@@ -457,6 +543,7 @@
 	 */
 	smb_close(dentry->d_inode);
 
+	smb_invalid_dir_cache(dir);
 	error = smb_proc_unlink(dentry);
 	if (!error)
 		smb_renew_times(dentry);
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/file.c linux/fs/smbfs/file.c
--- v2.4.1/linux/fs/smbfs/file.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/smbfs/file.c	Fri Feb 16 16:03:24 2001
@@ -13,7 +13,7 @@
 #include <linux/fcntl.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 
@@ -38,7 +38,7 @@
 static int
 smb_readpage_sync(struct dentry *dentry, struct page *page)
 {
-	char *buffer = page_address(page);
+	char *buffer = kmap(page);
 	unsigned long offset = page->index << PAGE_CACHE_SHIFT;
 	int rsize = smb_get_rsize(server_from_dentry(dentry));
 	int count = PAGE_SIZE;
@@ -76,6 +76,7 @@
 	result = 0;
 
 io_error:
+	kunmap(page);
 	UnlockPage(page);
 	return result;
 }
@@ -89,8 +90,6 @@
 	int		error;
 	struct dentry  *dentry = file->f_dentry;
 
-	DEBUG1("readpage %p\n", page_address(page));
-
 	get_page(page);
 	error = smb_readpage_sync(dentry, page);
 	put_page(page);
@@ -105,7 +104,7 @@
 smb_writepage_sync(struct inode *inode, struct page *page,
 		   unsigned long offset, unsigned int count)
 {
-	u8 *buffer = page_address(page) + offset;
+	char *buffer = kmap(page) + offset;
 	int wsize = smb_get_wsize(server_from_inode(inode));
 	int result, written = 0;
 
@@ -139,8 +138,10 @@
 		inode->i_mtime = inode->i_atime = CURRENT_TIME;
 		if (offset > inode->i_size)
 			inode->i_size = offset;
-		inode->u.smbfs_i.cache_valid |= SMB_F_LOCALWRITE;
+		inode->u.smbfs_i.flags |= SMB_F_LOCALWRITE;
 	} while (count);
+
+	kunmap(page);
 	return written ? written : result;
 }
 
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/inode.c linux/fs/smbfs/inode.c
--- v2.4.1/linux/fs/smbfs/inode.c	Sun Dec 10 08:48:18 2000
+++ linux/fs/smbfs/inode.c	Fri Feb 16 16:03:24 2001
@@ -16,7 +16,7 @@
 #include <linux/stat.h>
 #include <linux/errno.h>
 #include <linux/locks.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/file.h>
 #include <linux/dcache.h>
@@ -43,7 +43,6 @@
 static void smb_delete_inode(struct inode *);
 static void smb_put_super(struct super_block *);
 static int  smb_statfs(struct super_block *, struct statfs *);
-static void smb_set_inode_attr(struct inode *, struct smb_fattr *);
 
 static struct super_operations smb_sops =
 {
@@ -110,7 +109,7 @@
 		fattr->attr |= aRONLY;
 }
 
-static void
+void
 smb_set_inode_attr(struct inode *inode, struct smb_fattr *fattr)
 {
 	inode->i_mode	= fattr->f_mode;
@@ -125,8 +124,7 @@
 	 * Don't change the size and mtime/atime fields
 	 * if we're writing to the file.
 	 */
-	if (!(inode->u.smbfs_i.cache_valid & SMB_F_LOCALWRITE))
-	{
+	if (!(inode->u.smbfs_i.flags & SMB_F_LOCALWRITE)) {
 		inode->i_size  = fattr->f_size;
 		inode->i_mtime = fattr->f_mtime;
 		inode->i_atime = fattr->f_atime;
@@ -211,6 +209,7 @@
 int
 smb_revalidate_inode(struct dentry *dentry)
 {
+	struct smb_sb_info *s = server_from_dentry(dentry);
 	struct inode *inode = dentry->d_inode;
 	time_t last_time;
 	int error = 0;
@@ -221,8 +220,7 @@
 	 * the inode will be up-to-date.
 	 */
 	lock_kernel();
-	if (S_ISREG(inode->i_mode) && smb_is_open(inode))
-	{
+	if (S_ISREG(inode->i_mode) && smb_is_open(inode)) {
 		if (inode->u.smbfs_i.access != SMB_O_RDONLY)
 			goto out;
 	}
@@ -230,10 +228,9 @@
 	/*
 	 * Check whether we've recently refreshed the inode.
 	 */
-	if (time_before(jiffies, inode->u.smbfs_i.oldmtime + HZ/10))
-	{
-		VERBOSE("up-to-date, jiffies=%lu, oldtime=%lu\n",
-			jiffies, inode->u.smbfs_i.oldmtime);
+	if (time_before(jiffies, inode->u.smbfs_i.oldmtime + SMB_MAX_AGE(s))) {
+		VERBOSE("up-to-date, ino=%ld, jiffies=%lu, oldtime=%lu\n",
+			inode->i_ino, jiffies, inode->u.smbfs_i.oldmtime);
 		goto out;
 	}
 
@@ -243,16 +240,13 @@
 	 */
 	last_time = inode->i_mtime;
 	error = smb_refresh_inode(dentry);
-	if (error || inode->i_mtime != last_time)
-	{
+	if (error || inode->i_mtime != last_time) {
 		VERBOSE("%s/%s changed, old=%ld, new=%ld\n",
 			DENTRY_PATH(dentry),
 			(long) last_time, (long) inode->i_mtime);
 
 		if (!S_ISDIR(inode->i_mode))
 			invalidate_inode_pages(inode);
-		else
-			smb_invalid_dir_cache(inode);
 	}
 out:
 	unlock_kernel();
@@ -287,6 +281,7 @@
 	{ "dir_mode",	1, 0, 'd' },
 	{ "iocharset",	1, 0, 'i' },
 	{ "codepage",	1, 0, 'c' },
+	{ "ttl",	1, 0, 't' },
 	{ NULL,		0, 0, 0}
 };
 
@@ -339,6 +334,9 @@
 			strncpy(mnt->codepage.remote_name, optarg,
 				SMB_NLS_MAXNAMELEN);
 			break;
+		case 't':
+			mnt->ttl = value;
+			break;
 		default:
 			printk ("smbfs: Unrecognized mount option %s\n",
 				optopt);
@@ -437,6 +435,7 @@
 	strncpy(mnt->codepage.remote_name, SMB_NLS_REMOTE,
 		SMB_NLS_MAXNAMELEN);
 
+	mnt->ttl = 1000;
 	if (ver == SMB_MOUNT_OLDVERSION) {
 		mnt->version = oldmnt->version;
 
@@ -483,6 +482,7 @@
 	sb->s_root = d_alloc_root(root_inode);
 	if (!sb->s_root)
 		goto out_no_root;
+	smb_new_dentry(sb->s_root);
 
 	return sb;
 
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/proc.c linux/fs/smbfs/proc.c
--- v2.4.1/linux/fs/smbfs/proc.c	Sun Dec 10 08:48:18 2000
+++ linux/fs/smbfs/proc.c	Fri Feb 16 16:03:24 2001
@@ -9,7 +9,7 @@
 
 #include <linux/types.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/fs.h>
 #include <linux/file.h>
 #include <linux/stat.h>
@@ -78,6 +78,7 @@
 	}
 }
 
+#if 0
 static void
 str_lower(char *name, int len)
 {
@@ -88,6 +89,7 @@
 		name++;
 	}
 }
+#endif
 
 /* reverse a string inline. This is used by the dircache walking routines */
 static void reverse_string(char *buf, int len)
@@ -358,6 +360,72 @@
 	*date = nl_day - day_n[month - 1] + 1 + (month << 5) + (year << 9);
 }
 
+/* The following are taken from fs/ntfs/util.c */
+
+/*
+ * Convert the NT UTC (based 1601-01-01, in hundred nanosecond units)
+ * into Unix UTC (based 1970-01-01, in seconds).
+ *
+ * This is very gross because
+ * 1: We must do 64-bit division on a 32-bit machine
+ * 2: We can't use libgcc for long long operations in the kernel
+ * 3: Floating point math in the kernel would corrupt user data
+ */
+static time_t
+smb_ntutc2unixutc(struct smb_sb_info *server, u64 ntutc)
+{
+	const unsigned int D = 10000000;
+	unsigned int H = (unsigned int)(ntutc >> 32);
+	unsigned int L = (unsigned int)ntutc;
+	unsigned int numerator2;
+	unsigned int lowseconds;
+	unsigned int result;
+
+	/*
+	 * It is best to subtract 0x019db1ded53e8000 first.
+	 * Then the 1601-based date becomes a 1970-based date.
+	 */
+	if (L < (unsigned)0xd53e8000) H--;
+	L -= (unsigned)0xd53e8000;
+	H -= (unsigned)0x019db1de;
+
+	/*
+	 * Now divide 64-bit numbers on a 32-bit machine :-)
+	 * With the subtraction already done, the result fits in 32 bits.
+	 * The numerator fits in 56 bits and the denominator fits
+	 * in 24 bits, so we can shift by 8 bits to make this work.
+	 */
+
+	numerator2  = (H<<8) | (L>>24);
+	result      = (numerator2 / D);   /* shifted 24 right!! */
+	lowseconds  = result << 24;
+
+	numerator2  = ((numerator2-result*D)<<8) | ((L>>16)&0xff);
+	result      = (numerator2 / D);   /* shifted 16 right!! */
+	lowseconds |= result << 16;
+
+	numerator2  = ((numerator2-result*D)<<8) | ((L>>8)&0xff);
+	result      = (numerator2 / D);   /* shifted 8 right!! */
+	lowseconds |= result << 8;
+
+	numerator2  = ((numerator2-result*D)<<8) | (L&0xff);
+	result      = (numerator2 / D);   /* not shifted */
+	lowseconds |= result;
+
+	return lowseconds;
+}
+
+#if 0
+/* Convert the Unix UTC into NT time */
+static u64
+smb_unixutc2ntutc(struct smb_sb_info *server, time_t t)
+{
+	/* Note: timezone conversion is probably wrong. */
+	return ((utc2local(server, t) + (u64)(369*365+89)*24*3600) * 10000000);
+}
+#endif
+
+
 /*****************************************************************************/
 /*                                                                           */
 /*  Support section.                                                         */
@@ -421,22 +489,16 @@
 }
 
 /*
- * Returns the maximum read or write size for the current packet size
- * and max_xmit value.
+ * Returns the maximum read or write size for the "payload". Making all of the
+ * packet fit within the negotiated max_xmit size.
+ *
  * N.B. Since this value is usually computed before locking the server,
  * the server's packet size must never be decreased!
  */
-static int
+static inline int
 smb_get_xmitsize(struct smb_sb_info *server, int overhead)
 {
-	int size = server->packet_size;
-
-	/*
-	 * Start with the smaller of packet size and max_xmit ...
-	 */
-	if (size > server->opt.max_xmit)
-		size = server->opt.max_xmit;
-	return size - overhead;
+	return server->opt.max_xmit - overhead;
 }
 
 /*
@@ -783,6 +845,23 @@
 		server->opt.protocol, server->opt.max_xmit, server->conn_pid,
 		server->opt.capabilities);
 
+	/* Make sure we can fit a message of the negotiated size in our
+	   packet buffer. */
+	if (server->opt.max_xmit > server->packet_size) {
+		int len = smb_round_length(server->opt.max_xmit);
+		char *buf = smb_vmalloc(len);
+		if (buf) {
+			server->packet = buf;
+			server->packet_size = len;
+		} else {
+			/* else continue with the too small buffer? */
+			PARANOIA("Failed to allocate new packet buffer: "
+				 "max_xmit=%d, packet_size=%d\n",
+				 server->opt.max_xmit, server->packet_size);
+			server->opt.max_xmit = server->packet_size;
+		}
+	}
+
 out:
 #ifdef SMB_RETRY_INTR
 	wake_up_interruptible(&server->wait);
@@ -1025,7 +1104,7 @@
 
 		result = smb_proc_close(server, ino->u.smbfs_i.fileid,
 						ino->i_mtime);
-		ino->u.smbfs_i.cache_valid &= ~SMB_F_LOCALWRITE;
+		ino->u.smbfs_i.flags &= ~SMB_F_LOCALWRITE;
 		/*
 		 * Force a revalidation after closing ... some servers
 		 * don't post the size until the file has been closed.
@@ -1115,7 +1194,7 @@
 
 out:
 	VERBOSE("ino=%ld, fileid=%d, count=%d, result=%d\n",
-		inode->ino, inode->u.smbfs_i.fileid, count, result);
+		inode->i_ino, inode->u.smbfs_i.fileid, count, result);
 	smb_unlock_server(server);
 	return result;
 }
@@ -1128,7 +1207,7 @@
 	__u8 *p;
 	
 	VERBOSE("ino=%ld, fileid=%d, count=%d@%ld, packet_size=%d\n",
-		inode->ino, inode->u.smbfs_i.fileid, count, offset,
+		inode->i_ino, inode->u.smbfs_i.fileid, count, offset,
 		server->packet_size);
 
 	smb_lock_server(server);
@@ -1355,14 +1434,13 @@
 	smb_lock_server(server);
 
       retry:
-	p = smb_setup_header(server, SMBwrite, 5, 0);
+	p = smb_setup_header(server, SMBwrite, 5, 3);
 	WSET(server->packet, smb_vwv0, fid);
 	WSET(server->packet, smb_vwv1, 0);
 	DSET(server->packet, smb_vwv2, length);
 	WSET(server->packet, smb_vwv4, 0);
-	*p++ = 4;
-	*p++ = 0;
-	smb_setup_bcc(server, p);
+	*p++ = 1;
+	WSET(p, 0, 0);
 
 	if ((result = smb_request_ok(server, SMBwrite, 1, 0)) < 0) {
 		if (smb_retry(server))
@@ -1419,38 +1497,47 @@
 }
 
 /*
- * Note that we are now returning the name as a reference to avoid
- * an extra copy, and that the upper/lower casing is done in place.
+ * Decode a dirent for old protocols
+ *
+ * qname is filled with the decoded, and possibly translated, name.
+ * fattr receives decoded attributes
  *
  * Bugs Noted:
  * (1) Pathworks servers may pad the name with extra spaces.
  */
-static __u8 *
-smb_decode_dirent(struct smb_sb_info *server, __u8 *p, 
-			struct cache_dirent *entry)
+static char *
+smb_decode_short_dirent(struct smb_sb_info *server, char *p,
+			struct qstr *qname, struct smb_fattr *fattr)
 {
 	int len;
 
 	/*
 	 * SMB doesn't have a concept of inode numbers ...
 	 */
-	entry->ino = 0;
+	smb_init_dirent(server, fattr);
+	fattr->f_ino = 0;	/* FIXME: do we need this? */
 
 	p += SMB_STATUS_SIZE;	/* reserved (search_status) */
-	entry->name = p + 9;
-	len = strlen(entry->name);
-	if (len > 12)
-		len = 12;
+	fattr->attr = *p;
+	fattr->f_mtime = date_dos2unix(server, WVAL(p, 3), WVAL(p, 1));
+	fattr->f_size = DVAL(p, 5);
+	fattr->f_ctime = fattr->f_mtime;
+	fattr->f_atime = fattr->f_mtime;
+	qname->name = p + 9;
+	len = strnlen(qname->name, 12);
 
 	/*
 	 * Trim trailing blanks for Pathworks servers
 	 */
-	while (len > 2 && entry->name[len-1] == ' ')
+	while (len > 2 && qname->name[len-1] == ' ')
 		len--;
-	entry->len = len;
+	qname->len = len;
+
+	smb_finish_dirent(server, fattr);
 
+#if 0
 	/* FIXME: These only work for ascii chars, and recent smbmount doesn't
-	   allow the flag to be set anyway. Remove? */
+	   allow the flag to be set anyway. It kills const. Remove? */
 	switch (server->opt.case_handling) {
 	case SMB_CASE_UPPER:
 		str_upper(entry->name, len);
@@ -1461,24 +1548,31 @@
 	default:
 		break;
 	}
+#endif
 
-	entry->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
-				     entry->name, len,
+	qname->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
+				     qname->name, len,
 				     server->remote_nls, server->local_nls);
-	entry->name = server->name_buf;
+	qname->name = server->name_buf;
 
-	DEBUG1("len=%d, name=%.*s\n", entry->len, entry->len, entry->name);
+	DEBUG1("len=%d, name=%.*s\n", qname->len, qname->len, qname->name);
 	return p + 22;
 }
 
-/* This routine is used to read in directory entries from the network.
-   Note that it is for short directory name seeks, i.e.: protocol <
-   SMB_PROTOCOL_LANMAN2 */
-
+/*
+ * This routine is used to read in directory entries from the network.
+ * Note that it is for short directory name seeks, i.e.: protocol <
+ * SMB_PROTOCOL_LANMAN2
+ */
 static int
-smb_proc_readdir_short(struct smb_sb_info *server, struct dentry *dir, int fpos,
-		       void *cachep)
+smb_proc_readdir_short(struct file *filp, void *dirent, filldir_t filldir,
+		       struct smb_cache_control *ctl)
 {
+	struct dentry *dir = filp->f_dentry;
+	struct smb_sb_info *server = server_from_dentry(dir);
+	struct qstr qname;
+	struct smb_fattr fattr;
+
 	unsigned char *p;
 	int result;
 	int i, first, entries_seen, entries;
@@ -1489,13 +1583,10 @@
 	static struct qstr mask = { "*.*", 3, 0 };
 	unsigned char *last_status;
 
-	VERBOSE("%s/%s, pos=%d\n", DENTRY_PATH(dir), fpos);
+	VERBOSE("%s/%s\n", DENTRY_PATH(dir));
 
 	smb_lock_server(server);
 
-	/* N.B. We need to reinitialize the cache to restart */
-retry:
-	smb_init_dircache(cachep);
 	first = 1;
 	entries = 0;
 	entries_seen = 2; /* implicit . and .. */
@@ -1530,8 +1621,10 @@
 			if ((server->rcls == ERRDOS) && 
 			    (server->err  == ERRnofiles))
 				break;
-			if (smb_retry(server))
-				goto retry;
+			if (smb_retry(server)) {
+				ctl->idx = -1;	/* retry */
+				result = 0;
+			}
 			goto unlock_return;
 		}
 		p = SMB_VWV(server->packet);
@@ -1568,23 +1661,18 @@
 		/* Now we are ready to parse smb directory entries. */
 
 		for (i = 0; i < count; i++) {
-			struct cache_dirent this_ent, *entry = &this_ent;
+			p = smb_decode_short_dirent(server, p, 
+						    &qname, &fattr);
 
-			p = smb_decode_dirent(server, p, entry);
-			if (entries_seen == 2 && entry->name[0] == '.') {
-				if (entry->len == 1)
+			if (entries_seen == 2 && qname.name[0] == '.') {
+				if (qname.len == 1)
 					continue;
-				if (entry->name[1] == '.' && entry->len == 2)
+				if (qname.name[1] == '.' && qname.len == 2)
 					continue;
 			}
-			if (entries_seen >= fpos) {
-				DEBUG1("fpos=%u\n", entries_seen);
-				smb_add_to_cache(cachep, entry, entries_seen);
-				entries++;
-			} else {
-				VERBOSE("skipped, seen=%d, i=%d, fpos=%d\n",
-					entries_seen, i, fpos);
-			}
+			if (!smb_fill_cache(filp, dirent, filldir, ctl, 
+					    &qname, &fattr))
+				;	/* stop reading? */
 			entries_seen++;
 		}
 	}
@@ -1600,44 +1688,69 @@
  *   level 1 for anything below NT1 protocol
  *   level 260 for NT1 protocol
  *
- * We return a reference to the name string to avoid copying, and perform
- * any needed upper/lower casing in place.
+ * qname is filled with the decoded, and possibly translated, name
+ * fattr receives decoded attributes.
  *
  * Bugs Noted:
  * (1) Win NT 4.0 appends a null byte to names and counts it in the length!
  */
 static char *
-smb_decode_long_dirent(struct smb_sb_info *server, char *p,
-			struct cache_dirent *entry, int level)
+smb_decode_long_dirent(struct smb_sb_info *server, char *p, int level,
+		       struct qstr *qname, struct smb_fattr *fattr)
 {
 	char *result;
 	unsigned int len = 0;
+	__u16 date, time;
 
 	/*
 	 * SMB doesn't have a concept of inode numbers ...
 	 */
-	entry->ino = 0;
+	smb_init_dirent(server, fattr);
+	fattr->f_ino = 0;	/* FIXME: do we need this? */
 
 	switch (level) {
 	case 1:
 		len = *((unsigned char *) p + 22);
-		entry->name = p + 23;
+		qname->name = p + 23;
 		result = p + 24 + len;
 
+		date = WVAL(p, 0);
+		time = WVAL(p, 2);
+		fattr->f_ctime = date_dos2unix(server, date, time);
+
+		date = WVAL(p, 4);
+		time = WVAL(p, 6);
+		fattr->f_atime = date_dos2unix(server, date, time);
+
+		date = WVAL(p, 8);
+		time = WVAL(p, 10);
+		fattr->f_mtime = date_dos2unix(server, date, time);
+		fattr->f_size = DVAL(p, 12);
+		/* ULONG allocation size */
+		fattr->attr = WVAL(p, 20);
+
 		VERBOSE("info 1 at %p, len=%d, name=%.*s\n",
-			p, len, len, entry->name);
+			p, len, len, qname->name);
 		break;
 	case 260:
 		result = p + WVAL(p, 0);
 		len = DVAL(p, 60);
 		if (len > 255) len = 255;
 		/* NT4 null terminates */
-		entry->name = p + 94;
-		if (len && entry->name[len-1] == '\0')
+		qname->name = p + 94;
+		if (len && qname->name[len-1] == '\0')
 			len--;
 
+		fattr->f_ctime = smb_ntutc2unixutc(server, LVAL(p, 8));
+		fattr->f_atime = smb_ntutc2unixutc(server, LVAL(p, 16));
+		fattr->f_mtime = smb_ntutc2unixutc(server, LVAL(p, 24));
+		/* change time (32) */
+		fattr->f_size = DVAL(p, 40);
+		/* alloc size (48) */
+		fattr->attr = DVAL(p, 56);
+
 		VERBOSE("info 260 at %p, len=%d, name=%.*s\n",
-			p, len, len, entry->name);
+			p, len, len, qname->name);
 		break;
 	default:
 		PARANOIA("Unknown info level %d\n", level);
@@ -1645,21 +1758,28 @@
 		goto out;
 	}
 
+	smb_finish_dirent(server, fattr);
+
+#if 0
+	/* FIXME: These only work for ascii chars, and recent smbmount doesn't
+	   allow the flag to be set anyway. Remove? */
 	switch (server->opt.case_handling) {
 	case SMB_CASE_UPPER:
-		str_upper(entry->name, len);
+		str_upper(qname->name, len);
 		break;
 	case SMB_CASE_LOWER:
-		str_lower(entry->name, len);
+		str_lower(qname->name, len);
 		break;
 	default:
 		break;
 	}
+#endif
 
-	entry->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
-				     entry->name, len,
+	qname->len = server->convert(server->name_buf, SMB_MAXNAMELEN,
+				     qname->name, len,
 				     server->remote_nls, server->local_nls);
-	entry->name = server->name_buf;
+	qname->name = server->name_buf;
+
 out:
 	return result;
 }
@@ -1682,13 +1802,18 @@
  * single file. (E.g. echo hi >foo breaks, rm -f foo works.)
  */
 static int
-smb_proc_readdir_long(struct smb_sb_info *server, struct dentry *dir, int fpos,
-		      void *cachep)
+smb_proc_readdir_long(struct file *filp, void *dirent, filldir_t filldir,
+		      struct smb_cache_control *ctl)
 {
-	unsigned char *p;
-	char *mask, *lastname, *param = server->temp_buf;
+	struct dentry *dir = filp->f_dentry;
+	struct smb_sb_info *server = server_from_dentry(dir);
+	struct qstr qname;
+	struct smb_fattr fattr;
+
+	unsigned char *p, *lastname;
+	char *mask, *param = server->temp_buf;
 	__u16 command;
-	int first, entries, entries_seen;
+	int first, entries_seen;
 
 	/* Both NT and OS/2 accept info level 1 (but see note below). */
 	int info_level = 260;
@@ -1714,7 +1839,6 @@
 
 	smb_lock_server(server);
 
-retry:
 	/*
 	 * Encode the initial path
 	 */
@@ -1722,17 +1846,13 @@
 
 	mask_len = smb_encode_path(server, mask, dir, &star);
 	if (mask_len < 0) {
-		entries = mask_len;
+		result = mask_len;
 		goto unlock_return;
 	}
 	first = 1;
-	VERBOSE("starting fpos=%d, mask=%s\n", fpos, mask);
+	VERBOSE("starting mask_len=%d, mask=%s\n", mask_len, mask);
 
-	/*
-	 * We must reinitialize the dircache when retrying.
-	 */
-	smb_init_dircache(cachep);
-	entries = 0;
+	result = 0;
 	entries_seen = 2;
 	ff_eos = 0;
 
@@ -1741,7 +1861,7 @@
 		if (loop_count > 10) {
 			printk(KERN_WARNING "smb_proc_readdir_long: "
 			       "Looping in FIND_NEXT??\n");
-			entries = -EIO;
+			result = -EIO;
 			break;
 		}
 
@@ -1773,10 +1893,11 @@
 		if (result < 0) {
 			if (smb_retry(server)) {
 				PARANOIA("error=%d, retrying\n", result);
-				goto retry;
+				ctl->idx = -1;	/* retry */
+				result = 0;
+				goto unlock_return;
 			}
 			PARANOIA("error=%d, breaking\n", result);
-			entries = result;
 			break;
 		}
 
@@ -1788,10 +1909,10 @@
 			continue;
                 }
 
-		if (server->rcls != 0) { 
-			PARANOIA("name=%s, entries=%d, rcls=%d, err=%d\n",
-				 mask, entries, server->rcls, server->err);
-			entries = -smb_errno(server);
+		if (server->rcls != 0) {
+			result = -smb_errno(server);
+			PARANOIA("name=%s, result=%d, rcls=%d, err=%d\n",
+				 mask, result, server->rcls, server->err);
 			break;
 		}
 
@@ -1810,41 +1931,44 @@
 		if (ff_searchcount == 0)
 			break;
 
-		/* we might need the lastname for continuations */
+		/*
+		 * We might need the lastname for continuations.
+		 *
+		 * Note that some servers (win95?) point to the filename and
+		 * others (NT4, Samba using NT1) to the dir entry. We assume
+		 * here that those who do not point to a filename do not need
+		 * this info to continue the listing. OS/2 needs this, but it
+		 * talks "infolevel 1"
+		 */
 		mask_len = 0;
-		if (ff_lastname > 0) {
+		if (info_level == 1 && ff_lastname > 0 &&
+		    ff_lastname < resp_data_len) {
 			lastname = resp_data + ff_lastname;
-			switch (info_level) {
-			case 260:
-				if (ff_lastname < resp_data_len)
-					mask_len = resp_data_len - ff_lastname;
-				break;
-			case 1:
-				/* Win NT 4.0 doesn't set the length byte */
-				lastname++;
-				if (ff_lastname + 2 < resp_data_len)
-					mask_len = strlen(lastname);
-				break;
-			}
+
+			/* lastname points to a length byte */
+			mask_len = *lastname++;
+			if (ff_lastname + 1 + mask_len > resp_data_len)
+				mask_len = resp_data_len-ff_lastname-1;
+
 			/*
 			 * Update the mask string for the next message.
 			 */
+			if (mask_len < 0)
+				mask_len = 0;
 			if (mask_len > 255)
 				mask_len = 255;
 			if (mask_len)
 				strncpy(mask, lastname, mask_len);
 		}
-		mask[mask_len] = 0;
-		VERBOSE("new mask, len=%d@%d, mask=%s\n",
-			mask_len, ff_lastname, mask);
+		mask_len = strnlen(mask, mask_len);
+		VERBOSE("new mask, len=%d@%d of %d, mask=%.*s\n",
+			mask_len, ff_lastname, resp_data_len, mask_len, mask);
 
 		/* Now we are ready to parse smb directory entries. */
 
 		/* point to the data bytes */
 		p = resp_data;
 		for (i = 0; i < ff_searchcount; i++) {
-			struct cache_dirent this_ent, *entry = &this_ent;
-
 			/* make sure we stay within the buffer */
 			if (p >= resp_data + resp_data_len) {
 				printk(KERN_ERR "smb_proc_readdir_long: "
@@ -1856,21 +1980,21 @@
 				goto unlock_return;
 			}
 
-			p = smb_decode_long_dirent(server, p, entry,
-							info_level);
+			p = smb_decode_long_dirent(server, p, info_level,
+						   &qname, &fattr);
 
 			/* ignore . and .. from the server */
-			if (entries_seen == 2 && entry->name[0] == '.') {
-				if (entry->len == 1)
+			if (entries_seen == 2 && qname.name[0] == '.') {
+				if (qname.len == 1)
 					continue;
-				if (entry->name[1] == '.' && entry->len == 2)
+				if (qname.name[1] == '.' && qname.len == 2)
 					continue;
 			}
-			if (entries_seen >= fpos) {
-				smb_add_to_cache(cachep, entry, entries_seen);
-				entries += 1;
-			}
- 			entries_seen++;
+
+			if (!smb_fill_cache(filp, dirent, filldir, ctl, 
+					    &qname, &fattr))
+				;	/* stop reading? */
+			entries_seen++;
 		}
 
 		VERBOSE("received %d entries, eos=%d\n", ff_searchcount,ff_eos);
@@ -1881,19 +2005,19 @@
 
 unlock_return:
 	smb_unlock_server(server);
-	return entries;
+	return result;
 }
 
 int
-smb_proc_readdir(struct dentry *dir, int fpos, void *cachep)
+smb_proc_readdir(struct file *filp, void *dirent, filldir_t filldir,
+		 struct smb_cache_control *ctl)
 {
-	struct smb_sb_info *server;
+	struct smb_sb_info *server = server_from_dentry(filp->f_dentry);
 
-	server = server_from_dentry(dir);
 	if (server->opt.protocol >= SMB_PROTOCOL_LANMAN2)
-		return smb_proc_readdir_long(server, dir, fpos, cachep);
+		return smb_proc_readdir_long(filp, dirent, filldir, ctl);
 	else
-		return smb_proc_readdir_short(server, dir, fpos, cachep);
+		return smb_proc_readdir_short(filp, dirent, filldir, ctl);
 }
 
 /*
diff -u --recursive --new-file v2.4.1/linux/fs/smbfs/sock.c linux/fs/smbfs/sock.c
--- v2.4.1/linux/fs/smbfs/sock.c	Mon Dec 11 12:39:45 2000
+++ linux/fs/smbfs/sock.c	Fri Feb 16 16:03:24 2001
@@ -109,7 +109,7 @@
 	struct data_callback* job=ptr;
 	struct socket *socket = job->sk->socket;
 	unsigned char peek_buf[4];
-	int result;
+	int result = 0;
 	mm_segment_t fs;
 	int count = 100;   /* this is a lot, we should have some data waiting */
 	int found = 0;
@@ -477,14 +477,12 @@
 	unsigned int total_p = 0, total_d = 0, buf_len = 0;
 	int result;
 
-	while (1)
-	{
+	while (1) {
 		result = smb_receive(server);
 		if (result < 0)
 			goto out;
 		inbuf = server->packet;
-		if (server->rcls != 0)
-		{
+		if (server->rcls != 0) {
 			*parm = *data = inbuf;
 			*ldata = *lparm = 0;
 			goto out;
@@ -508,13 +506,11 @@
 		parm_len += parm_count;
 		data_len += data_count;
 
-		if (!rcv_buf)
-		{
+		if (!rcv_buf) {
 			/*
 			 * Check for fast track processing ... just this packet.
 			 */
-			if (parm_count == parm_tot && data_count == data_tot)
-			{
+			if (parm_count == parm_tot && data_count == data_tot) {
 				VERBOSE("fast track, parm=%u %u %u, data=%u %u %u\n",
 					parm_disp, parm_offset, parm_count,
 					data_disp, data_offset, data_count);
@@ -523,10 +519,6 @@
 				goto success;
 			}
 
-			if (parm_tot > TRANS2_MAX_TRANSFER ||
-	  		    data_tot > TRANS2_MAX_TRANSFER)
-				goto out_too_long;
-
 			/*
 			 * Save the total parameter and data length.
 			 */
@@ -537,14 +529,15 @@
 			if (server->packet_size > buf_len)
 				buf_len = server->packet_size;
 			buf_len = smb_round_length(buf_len);
+			if (buf_len > SMB_MAX_PACKET_SIZE)
+				goto out_too_long;
 
 			rcv_buf = smb_vmalloc(buf_len);
 			if (!rcv_buf)
 				goto out_no_mem;
 			*parm = rcv_buf;
 			*data = rcv_buf + total_p;
-		}
-		else if (data_tot > total_d || parm_tot > total_p)
+		} else if (data_tot > total_d || parm_tot > total_p)
 			goto out_data_grew;
 
 		if (parm_disp + parm_count > total_p)
@@ -571,8 +564,7 @@
 	 * old one, in which case we just copy the data.
 	 */
 	inbuf = server->packet;
-	if (buf_len >= server->packet_size)
-	{
+	if (buf_len >= server->packet_size) {
 		server->packet_size = buf_len;
 		server->packet = rcv_buf;
 		rcv_buf = inbuf;
@@ -716,6 +708,7 @@
 	struct socket *sock = server_sock(server);
 	struct scm_cookie scm;
 	int err;
+	int mparam, mdata;
 
 	/* I know the following is very ugly, but I want to build the
 	   smb packet as efficiently as possible. */
@@ -737,19 +730,30 @@
 	struct iovec iov[4];
 	struct msghdr msg;
 
-	/* N.B. This test isn't valid! packet_size may be < max_xmit */
+	/* FIXME! this test needs to include SMB overhead too, I think ... */
 	if ((bcc + oparam) > server->opt.max_xmit)
-	{
 		return -ENOMEM;
-	}
 	p = smb_setup_header(server, SMBtrans2, smb_parameters, bcc);
 
+	/*
+	 * max parameters + max data + max setup == max_xmit to make NT4 happy
+	 * and not abort the transfer or split into multiple responses.
+	 *
+	 * -100 is to make room for headers, which OS/2 seems to include in the
+	 * size calculation while NT4 does not?
+	 */
+	mparam = SMB_TRANS2_MAX_PARAM;
+	mdata = server->opt.max_xmit - mparam - 100;
+	if (mdata < 1024) {
+		mdata = 1024;
+		mparam = 20;
+	}
+
 	WSET(server->packet, smb_tpscnt, lparam);
 	WSET(server->packet, smb_tdscnt, ldata);
-	/* N.B. these values should reflect out current packet size */
-	WSET(server->packet, smb_mprcnt, TRANS2_MAX_TRANSFER);
-	WSET(server->packet, smb_mdrcnt, TRANS2_MAX_TRANSFER);
-	WSET(server->packet, smb_msrcnt, 0);
+	WSET(server->packet, smb_mprcnt, mparam);
+	WSET(server->packet, smb_mdrcnt, mdata);
+	WSET(server->packet, smb_msrcnt, 0);    /* max setup always 0 ? */
 	WSET(server->packet, smb_flags, 0);
 	DSET(server->packet, smb_timeout, 0);
 	WSET(server->packet, smb_pscnt, lparam);
@@ -781,8 +785,7 @@
 	iov[3].iov_len = ldata;
 
 	err = scm_send(sock, &msg, &scm);
-        if (err >= 0)
-	{
+        if (err >= 0) {
 		err = sock->ops->sendmsg(sock, &msg, packet_length, &scm);
 		scm_destroy(&scm);
 	}
diff -u --recursive --new-file v2.4.1/linux/fs/super.c linux/fs/super.c
--- v2.4.1/linux/fs/super.c	Sat Feb  3 19:51:31 2001
+++ linux/fs/super.c	Fri Feb  9 11:29:44 2001
@@ -22,12 +22,13 @@
 
 #include <linux/config.h>
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/locks.h>
 #include <linux/smp_lock.h>
 #include <linux/devfs_fs_kernel.h>
 #include <linux/fd.h>
 #include <linux/init.h>
+#include <linux/major.h>
 #include <linux/quotaops.h>
 #include <linux/acct.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/udf/dir.c linux/fs/udf/dir.c
--- v2.4.1/linux/fs/udf/dir.c	Fri Nov 17 11:36:27 2000
+++ linux/fs/udf/dir.c	Fri Feb  9 11:29:44 2001
@@ -38,7 +38,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/udf_fs.h>
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/fs/udf/namei.c linux/fs/udf/namei.c
--- v2.4.1/linux/fs/udf/namei.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/udf/namei.c	Fri Feb  9 11:29:44 2001
@@ -31,7 +31,7 @@
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/quotaops.h>
 #include <linux/udf_fs.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/udf/partition.c linux/fs/udf/partition.c
--- v2.4.1/linux/fs/udf/partition.c	Thu Mar  2 11:17:32 2000
+++ linux/fs/udf/partition.c	Fri Feb  9 11:29:44 2001
@@ -30,7 +30,7 @@
 #include <linux/fs.h>
 #include <linux/string.h>
 #include <linux/udf_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 inline Uint32 udf_get_pblock(struct super_block *sb, Uint32 block, Uint16 partition, Uint32 offset)
 {
diff -u --recursive --new-file v2.4.1/linux/fs/udf/super.c linux/fs/udf/super.c
--- v2.4.1/linux/fs/udf/super.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/udf/super.c	Fri Feb  9 11:29:44 2001
@@ -48,7 +48,7 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/blkdev.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/locks.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.1/linux/fs/udf/symlink.c linux/fs/udf/symlink.c
--- v2.4.1/linux/fs/udf/symlink.c	Fri Dec 29 14:07:57 2000
+++ linux/fs/udf/symlink.c	Fri Feb  9 11:29:44 2001
@@ -32,7 +32,7 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/stat.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 #include <linux/smp_lock.h>
 #include "udf_i.h"
diff -u --recursive --new-file v2.4.1/linux/fs/ufs/super.c linux/fs/ufs/super.c
--- v2.4.1/linux/fs/ufs/super.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/ufs/super.c	Fri Feb  9 11:29:44 2001
@@ -73,7 +73,7 @@
 #include <linux/errno.h>
 #include <linux/fs.h>
 #include <linux/ufs_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sched.h>
 #include <linux/stat.h>
 #include <linux/string.h>
diff -u --recursive --new-file v2.4.1/linux/fs/ufs/util.c linux/fs/ufs/util.c
--- v2.4.1/linux/fs/ufs/util.c	Tue Sep  5 14:07:30 2000
+++ linux/fs/ufs/util.c	Fri Feb  9 11:29:44 2001
@@ -7,7 +7,7 @@
  */
  
 #include <linux/string.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/locks.h>
 
 #include "swab.h"
diff -u --recursive --new-file v2.4.1/linux/fs/umsdos/dir.c linux/fs/umsdos/dir.c
--- v2.4.1/linux/fs/umsdos/dir.c	Wed Nov  8 19:01:34 2000
+++ linux/fs/umsdos/dir.c	Fri Feb  9 11:29:44 2001
@@ -15,7 +15,7 @@
 #include <linux/stat.h>
 #include <linux/limits.h>
 #include <linux/umsdos_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/pagemap.h>
 
 #define UMSDOS_SPECIAL_DIRFPOS	3
diff -u --recursive --new-file v2.4.1/linux/fs/umsdos/namei.c linux/fs/umsdos/namei.c
--- v2.4.1/linux/fs/umsdos/namei.c	Wed Aug  2 12:06:11 2000
+++ linux/fs/umsdos/namei.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/string.h>
 #include <linux/msdos_fs.h>
 #include <linux/umsdos_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #define UMSDOS_DIR_LOCK
 
diff -u --recursive --new-file v2.4.1/linux/fs/umsdos/rdir.c linux/fs/umsdos/rdir.c
--- v2.4.1/linux/fs/umsdos/rdir.c	Fri Aug 11 14:29:01 2000
+++ linux/fs/umsdos/rdir.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #include <linux/stat.h>
 #include <linux/limits.h>
 #include <linux/umsdos_fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/uaccess.h>
 
diff -u --recursive --new-file v2.4.1/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.4.1/linux/fs/vfat/namei.c	Sun Dec 31 10:26:17 2000
+++ linux/fs/vfat/namei.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
 #include <linux/ctype.h>
 #include <linux/stat.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include "../fat/msbuffer.h"
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/errno.h linux/include/asm-alpha/errno.h
--- v2.4.1/linux/include/asm-alpha/errno.h	Sat Feb  3 19:51:31 2001
+++ linux/include/asm-alpha/errno.h	Fri Feb  9 11:40:02 2001
@@ -139,6 +139,4 @@
 #define ENOMEDIUM	129	/* No medium found */
 #define EMEDIUMTYPE	130	/* Wrong medium type */
 
-#define EHASHCOLLISION  131     /* Number of hash collisons exceeds maximum generation counter value.  */
-
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/io.h linux/include/asm-alpha/io.h
--- v2.4.1/linux/include/asm-alpha/io.h	Mon Jun 19 17:59:33 2000
+++ linux/include/asm-alpha/io.h	Tue Feb 13 14:56:41 2001
@@ -440,6 +440,22 @@
 	return retval;
 }
 
+
+/*
+ * ISA space is mapped to some machine-specific location on Alpha.
+ * Call into the existing hooks to get the address translated.
+ */
+#define isa_readb(a)			readb(__ioremap(a))
+#define isa_readw(a)			readw(__ioremap(a))
+#define isa_readl(a)			readl(__ioremap(a))
+#define isa_writeb(b,a)			writeb((b),__ioremap(a))
+#define isa_writew(w,a)			writew((w),__ioremap(a))
+#define isa_writel(l,a)			writel((l),__ioremap(a))
+#define isa_memset_io(a,b,c)		memset_io(__ioremap(a),(b),(c))
+#define isa_memcpy_fromio(a,b,c)	memcpy_fromio((a),__ioremap(b),(c))
+#define isa_memcpy_toio(a,b,c)		memcpy_toio(__ioremap(a),(b),(c))
+
+
 /*
  * The Alpha Jensen hardware for some rather strange reason puts
  * the RTC clock at 0x170 instead of 0x70. Probably due to some
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/page.h linux/include/asm-alpha/page.h
--- v2.4.1/linux/include/asm-alpha/page.h	Wed Aug  9 13:46:01 2000
+++ linux/include/asm-alpha/page.h	Thu Feb  8 12:56:29 2001
@@ -12,64 +12,10 @@
 
 #define STRICT_MM_TYPECHECKS
 
-/*
- * A _lot_ of the kernel time is spent clearing pages, so
- * do this as fast as we possibly can. Also, doing this
- * as a separate inline function (rather than memset())
- * results in clearer kernel profiles as we see _who_ is
- * doing page clearing or copying.
- */
-static inline void clear_page(void * page)
-{
-	unsigned long count = PAGE_SIZE/64;
-	unsigned long *ptr = (unsigned long *)page;
-
-	do {
-		ptr[0] = 0;
-		ptr[1] = 0;
-		ptr[2] = 0;
-		ptr[3] = 0;
-		count--;
-		ptr[4] = 0;
-		ptr[5] = 0;
-		ptr[6] = 0;
-		ptr[7] = 0;
-		ptr += 8;
-	} while (count);
-}
-
+extern void clear_page(void *page);
 #define clear_user_page(page, vaddr)	clear_page(page)
 
-static inline void copy_page(void * _to, void * _from)
-{
-	unsigned long count = PAGE_SIZE/64;
-	unsigned long *to = (unsigned long *)_to;
-	unsigned long *from = (unsigned long *)_from;
-
-	do {
-		unsigned long a,b,c,d,e,f,g,h;
-		a = from[0];
-		b = from[1];
-		c = from[2];
-		d = from[3];
-		e = from[4];
-		f = from[5];
-		g = from[6];
-		h = from[7];
-		count--;
-		from += 8;
-		to[0] = a;
-		to[1] = b;
-		to[2] = c;
-		to[3] = d;
-		to[4] = e;
-		to[5] = f;
-		to[6] = g;
-		to[7] = h;
-		to += 8;
-	} while (count);
-}
-
+extern void copy_page(void * _to, void * _from);
 #define copy_user_page(to, from, vaddr)	copy_page(to, from)
 
 #ifdef STRICT_MM_TYPECHECKS
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/socket.h linux/include/asm-alpha/socket.h
--- v2.4.1/linux/include/asm-alpha/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-alpha/socket.h	Sat Feb  3 11:26:44 2001
@@ -29,6 +29,7 @@
 #define	SO_SNDLOWAT	0x1011
 #define	SO_RCVTIMEO	0x1012
 #define	SO_SNDTIMEO	0x1013
+#define SO_ACCEPTCONN	0x1014
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -u --recursive --new-file v2.4.1/linux/include/asm-alpha/termios.h linux/include/asm-alpha/termios.h
--- v2.4.1/linux/include/asm-alpha/termios.h	Fri Sep 22 14:21:17 2000
+++ linux/include/asm-alpha/termios.h	Sat Feb  3 20:00:45 2001
@@ -78,7 +78,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-arc/io.h linux/include/asm-arm/arch-arc/io.h
--- v2.4.1/linux/include/asm-arm/arch-arc/io.h	Mon Sep 18 15:15:22 2000
+++ linux/include/asm-arm/arch-arc/io.h	Thu Feb  8 16:32:44 2001
@@ -16,6 +16,49 @@
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
+ * GCC is totally crap at loading/storing data.  We try to persuade it
+ * to do the right thing by using these whereever possible instead of
+ * the above.
+ */
+#define __arch_base_getb(b,o)			\
+ ({						\
+	unsigned int v, r = (b);		\
+	__asm__ __volatile__(			\
+		"ldrb	%0, [%1, %2]"		\
+		: "=r" (v)			\
+		: "r" (r), "Ir" (o));		\
+	v;					\
+ })
+
+#define __arch_base_getl(b,o)			\
+ ({						\
+	unsigned int v, r = (b);		\
+	__asm__ __volatile__(			\
+		"ldr	%0, [%1, %2]"		\
+		: "=r" (v)			\
+		: "r" (r), "Ir" (o));		\
+	v;					\
+ })
+
+#define __arch_base_putb(v,b,o)			\
+ ({						\
+	unsigned int r = (b);			\
+	__asm__ __volatile__(			\
+		"strb	%0, [%1, %2]"		\
+		:				\
+		: "r" (v), "r" (r), "Ir" (o));	\
+ })
+
+#define __arch_base_putl(v,b,o)			\
+ ({						\
+	unsigned int r = (b);			\
+	__asm__ __volatile__(			\
+		"str	%0, [%1, %2]"		\
+		:				\
+		: "r" (v), "r" (r), "Ir" (o));	\
+ })
+
+/*
  * We use two different types of addressing - PC style addresses, and ARM
  * addresses.  PC style accesses the PC hardware with the normal PC IO
  * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
@@ -75,7 +118,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
+	"ldr" instr "	%1, [%0, %2, lsl #2]	@ in" #fnsuffix			\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -203,22 +246,7 @@
 #define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
 #define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
 #define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p)								\
-	(*(volatile unsigned char *)(p) = (v))
-
-#define inb_t(p)								\
-	(*(volatile unsigned char *)(p))
-
-#define outl_t(v,p)								\
-	(*(volatile unsigned long *)(p) = (v))
-
-#define inl_t(p)								\
-	(*(volatile unsigned long *)(p))
+/* the following macro is depreciated */
+#define ioaddr(port)			__ioaddr((port))
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-arc/irqs.h linux/include/asm-arm/arch-arc/irqs.h
--- v2.4.1/linux/include/asm-arm/arch-arc/irqs.h	Mon Sep 18 15:15:22 2000
+++ linux/include/asm-arm/arch-arc/irqs.h	Thu Feb  8 16:32:44 2001
@@ -52,4 +52,9 @@
 
 #define IRQ_TIMER		IRQ_TIMER0
 
+/*
+ * This is the offset of the FIQ "IRQ" numbers
+ */
+#define FIQ_START		64
+
 #define irq_cannonicalize(i)	(i)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-cl7500/io.h linux/include/asm-arm/arch-cl7500/io.h
--- v2.4.1/linux/include/asm-arm/arch-cl7500/io.h	Thu Feb 24 22:44:47 2000
+++ linux/include/asm-arm/arch-cl7500/io.h	Thu Feb  8 16:32:44 2001
@@ -13,6 +13,49 @@
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
+ * GCC is totally crap at loading/storing data.  We try to persuade it
+ * to do the right thing by using these whereever possible instead of
+ * the above.
+ */
+#define __arch_base_getb(b,o)			\
+ ({						\
+	unsigned int v, r = (b);		\
+	__asm__ __volatile__(			\
+		"ldrb	%0, [%1, %2]"		\
+		: "=r" (v)			\
+		: "r" (r), "Ir" (o));		\
+	v;					\
+ })
+
+#define __arch_base_getl(b,o)			\
+ ({						\
+	unsigned int v, r = (b);		\
+	__asm__ __volatile__(			\
+		"ldr	%0, [%1, %2]"		\
+		: "=r" (v)			\
+		: "r" (r), "Ir" (o));		\
+	v;					\
+ })
+
+#define __arch_base_putb(v,b,o)			\
+ ({						\
+	unsigned int r = (b);			\
+	__asm__ __volatile__(			\
+		"strb	%0, [%1, %2]"		\
+		:				\
+		: "r" (v), "r" (r), "Ir" (o));	\
+ })
+
+#define __arch_base_putl(v,b,o)			\
+ ({						\
+	unsigned int r = (b);			\
+	__asm__ __volatile__(			\
+		"str	%0, [%1, %2]"		\
+		:				\
+		: "r" (v), "r" (r), "Ir" (o));	\
+ })
+
+/*
  * We use two different types of addressing - PC style addresses, and ARM
  * addresses.  PC style accesses the PC hardware with the normal PC IO
  * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
@@ -72,7 +115,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
+	"ldr" instr "	%1, [%0, %2, lsl #2]	@ in" #fnsuffix			\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -193,22 +236,7 @@
 #define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
 #define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
 #define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p)								\
-	(*(volatile unsigned char *)(p) = (v))
-
-#define inb_t(p)								\
-	(*(volatile unsigned char *)(p))
-
-#define outl_t(v,p)								\
-	(*(volatile unsigned long *)(p) = (v))
-
-#define inl_t(p)								\
-	(*(volatile unsigned long *)(p))
+/* the following macro is depreciated */
+#define ioaddr(port)			__ioaddr((port))
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-cl7500/irqs.h linux/include/asm-arm/arch-cl7500/irqs.h
--- v2.4.1/linux/include/asm-arm/arch-cl7500/irqs.h	Tue Nov 23 22:23:11 1999
+++ linux/include/asm-arm/arch-cl7500/irqs.h	Thu Feb  8 16:32:44 2001
@@ -56,4 +56,9 @@
 #define FIQ_INT8		6
 #define FIQ_FORCE		7
 
+/*
+ * This is the offset of the FIQ "IRQ" numbers
+ */
+#define FIQ_START		64
+
 #define IRQ_TIMER		IRQ_TIMER0
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-ebsa110/io.h linux/include/asm-arm/arch-ebsa110/io.h
--- v2.4.1/linux/include/asm-arm/arch-ebsa110/io.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-ebsa110/io.h	Thu Feb  8 16:32:44 2001
@@ -16,186 +16,11 @@
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
- * We use two different types of addressing - PC style addresses, and ARM
- * addresses.  PC style accesses the PC hardware with the normal PC IO
- * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
- * and are translated to the start of IO.  Note that all addresses are
- * shifted left!
+ * Generic virtual read/write
  */
-#define __PORT_PCIO(x)	(!((x) & 0x80000000))
+#define __arch_getw(a)		(*(volatile unsigned short *)(a))
+#define __arch_putw(v,a)	(*(volatile unsigned short *)(a) = (v))
 
-/*
- * Dynamic IO functions - let the compiler
- * optimize the expressions
- */
-#define DECLARE_DYN_OUT(fnsuffix,instr)						\
-extern __inline__ void __out##fnsuffix (unsigned int value, unsigned int port)	\
-{										\
-	unsigned long temp;							\
-	__asm__ __volatile__(							\
-	"tst	%2, #0x80000000\n\t"						\
-	"mov	%0, %4\n\t"							\
-	"addeq	%0, %0, %3\n\t"							\
-	"str" ##instr## "	%1, [%0, %2, lsl #2]	@ out"###fnsuffix	\
-	: "=&r" (temp)								\
-	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)	\
-	: "cc");								\
-}
-
-#define DECLARE_DYN_IN(sz,fnsuffix,instr)					\
-extern __inline__ unsigned sz __in##fnsuffix (unsigned int port)		\
-{										\
-	unsigned long temp, value;						\
-	__asm__ __volatile__(							\
-	"tst	%2, #0x80000000\n\t"						\
-	"mov	%0, %4\n\t"							\
-	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
-	: "=&r" (temp), "=r" (value)						\
-	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
-	: "cc");								\
-	return (unsigned sz)value;						\
-}
-
-extern __inline__ unsigned int __ioaddr (unsigned int port)			\
-{										\
-	if (__PORT_PCIO(port))							\
-		return (unsigned int)(PCIO_BASE + (port << 2));			\
-	else									\
-		return (unsigned int)(IO_BASE + (port << 2));			\
-}
-
-#define DECLARE_IO(sz,fnsuffix,instr)	\
-	DECLARE_DYN_OUT(fnsuffix,instr)	\
-	DECLARE_DYN_IN(sz,fnsuffix,instr)
-
-DECLARE_IO(char,b,"b")
-DECLARE_IO(short,w,"")
-DECLARE_IO(int,l,"")
-
-#undef DECLARE_IO
-#undef DECLARE_DYN_OUT
-#undef DECLARE_DYN_IN
-
-/*
- * Constant address IO functions
- *
- * These have to be macros for the 'J' constraint to work -
- * +/-4096 immediate operand.
- */
-#define __outbc(value,port)							\
-({										\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]		@ outbc"			\
-		: : "r" (value), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"strb	%0, [%1, %2]		@ outbc"			\
-		: : "r" (value), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inbc(port)								\
-({										\
-	unsigned char result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]		@ inbc"				\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldrb	%0, [%1, %2]		@ inbc"				\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result;									\
-})
-
-#define __outwc(value,port)							\
-({										\
-	unsigned long v = value;						\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]		@ outwc"			\
-		: : "r" (v|v<<16), "r" (PCIO_BASE), "Jr" ((port) << 2));	\
-	else									\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]		@ outwc"			\
-		: : "r" (v|v<<16), "r" (IO_BASE), "r" ((port) << 2));		\
-})
-
-#define __inwc(port)								\
-({										\
-	unsigned short result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]		@ inwc"				\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]		@ inwc"				\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result & 0xffff;							\
-})
-
-#define __outlc(v,p)								\
-({										\
-	unsigned long v = value;						\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]		@ outlc"			\
-		: : "r" (v), "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"str	%0, [%1, %2]		@ outlc"			\
-		: : "r" (v), "r" (IO_BASE), "r" ((port) << 2));			\
-})
-
-#define __inlc(port)								\
-({										\
-	unsigned long result;							\
-	if (__PORT_PCIO((port)))						\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]		@ inlc"				\
-		: "=r" (result) : "r" (PCIO_BASE), "Jr" ((port) << 2));		\
-	else									\
-		__asm__ __volatile__(						\
-		"ldr	%0, [%1, %2]		@ inlc"				\
-		: "=r" (result) : "r" (IO_BASE), "r" ((port) << 2));		\
-	result;									\
-})
-
-#define __ioaddrc(port)								\
-({										\
-	unsigned long addr;							\
-	if (__PORT_PCIO((port)))						\
-		addr = PCIO_BASE + ((port) << 2);				\
-	else									\
-		addr = IO_BASE + ((port) << 2);					\
-	addr;									\
-})
-
-#define inb(p)	 	(__builtin_constant_p((p)) ? __inbc(p)    : __inb(p))
-#define inw(p)	 	(__builtin_constant_p((p)) ? __inwc(p)    : __inw(p))
-#define inl(p)	 	(__builtin_constant_p((p)) ? __inlc(p)    : __inl(p))
-#define outb(v,p)	(__builtin_constant_p((p)) ? __outbc(v,p) : __outb(v,p))
-#define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
-#define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
-#define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p)								\
-	(*(volatile unsigned char *)(p) = (v))
-
-#define inb_t(p)								\
-	(*(volatile unsigned char *)(p))
-
-#define outl_t(v,p)								\
-	(*(volatile unsigned long *)(p) = (v))
-
-#define inl_t(p)								\
-	(*(volatile unsigned long *)(p))
+#define __io(p)		(ISAIO_BASE + ((p) << 2))
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-ebsa110/memory.h linux/include/asm-arm/arch-ebsa110/memory.h
--- v2.4.1/linux/include/asm-arm/arch-ebsa110/memory.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-ebsa110/memory.h	Thu Feb  8 16:32:44 2001
@@ -23,6 +23,12 @@
 #define TASK_SIZE_26	(0x04000000UL)
 
 /*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
  * Page offset: 3GB
  */
 #define PAGE_OFFSET	(0xc0000000UL)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-ebsa110/processor.h linux/include/asm-arm/arch-ebsa110/processor.h
--- v2.4.1/linux/include/asm-arm/arch-ebsa110/processor.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-ebsa110/processor.h	Wed Dec 31 16:00:00 1969
@@ -1,30 +0,0 @@
-/*
- *  linux/include/asm-arm/arch-ebsa110/processor.h
- *
- *  Copyright (C) 1996-1999 Russell King
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Changelog:
- *   21-Mar-1999 RMK	Added asm/arch/memory.h
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-ebsa285/io.h linux/include/asm-arm/arch-ebsa285/io.h
--- v2.4.1/linux/include/asm-arm/arch-ebsa285/io.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-ebsa285/io.h	Thu Feb  8 16:32:44 2001
@@ -19,7 +19,7 @@
 /*
  * Translation of various region addresses to virtual addresses
  */
-#define __io_pci(a)		(PCIO_BASE + (a))
+#define __io(a)			(PCIO_BASE + (a))
 #if 1
 #define __mem_pci(a)		((unsigned long)(a))
 #define __mem_isa(a)		(PCIMEM_BASE + (unsigned long)(a))
@@ -42,41 +42,11 @@
 #define __mem_isa(a)		___mem_isa((unsigned long)(a))
 #endif
 
-/* the following macro is depreciated */
-#define __ioaddr(p)		__io_pci(p)
-
 /*
  * Generic virtual read/write
  */
-#define __arch_getb(a)		(*(volatile unsigned char *)(a))
-#define __arch_getl(a)		(*(volatile unsigned int  *)(a))
-
-extern __inline__ unsigned int __arch_getw(unsigned long a)
-{
-	unsigned int value;
-	__asm__ __volatile__("ldr%?h	%0, [%1, #0]	@ getw"
-		: "=&r" (value)
-		: "r" (a));
-	return value;
-}
-
-
-#define __arch_putb(v,a)	(*(volatile unsigned char *)(a) = (v))
-#define __arch_putl(v,a)	(*(volatile unsigned int  *)(a) = (v))
-
-extern __inline__ void __arch_putw(unsigned int value, unsigned long a)
-{
-	__asm__ __volatile__("str%?h	%0, [%1, #0]	@ putw"
-		: : "r" (value), "r" (a));
-}
-
-#define inb(p)			__arch_getb(__io_pci(p))
-#define inw(p)			__arch_getw(__io_pci(p))
-#define inl(p)			__arch_getl(__io_pci(p))
-
-#define outb(v,p)		__arch_putb(v,__io_pci(p))
-#define outw(v,p)		__arch_putw(v,__io_pci(p))
-#define outl(v,p)		__arch_putl(v,__io_pci(p))
+#define __arch_getw(a)		(*(volatile unsigned short *)(a))
+#define __arch_putw(v,a)	(*(volatile unsigned short *)(a) = (v))
 
 #include <asm/hardware/dec21285.h>
 
@@ -85,20 +55,9 @@
  * and convert a PCI memory address to a physical
  * address for the page tables.
  */
-#define valid_ioaddr(off,sz)	((off) < 0x80000000 && (off) + (sz) <= 0x80000000)
-#define io_to_phys(off)		((off) + DC21285_PCI_MEM)
+#define iomem_valid_addr(iomem,sz) \
+	((iomem) < 0x80000000 && (iomem) + (sz) <= 0x80000000)
 
-/*
- * ioremap takes a PCI memory address, as specified in
- * linux/Documentation/IO-mapping.txt
- */
-#define __arch_ioremap(off,size,nocache)			\
-({								\
-	unsigned long _off = (off), _size = (size);		\
-	void *_ret = (void *)0;					\
-	if (valid_ioaddr(_off, _size))				\
-		_ret = __ioremap(io_to_phys(_off), _size, 0);	\
-	_ret;							\
-})
+#define iomem_to_phys(iomem)	((iomem) + DC21285_PCI_MEM)
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-nexuspci/io.h linux/include/asm-arm/arch-nexuspci/io.h
--- v2.4.1/linux/include/asm-arm/arch-nexuspci/io.h	Mon Feb 28 14:16:37 2000
+++ linux/include/asm-arm/arch-nexuspci/io.h	Thu Feb  8 16:32:44 2001
@@ -12,7 +12,7 @@
 /*
  * Translation of various region addresses to virtual addresses
  */
-#define __io_pci(a)		(PCIO_BASE + (a))
+#define __io(a)			(PCIO_BASE + (a))
 #if 1
 #define __mem_pci(a)		((unsigned long)(a))
 #define __mem_isa(a)		(PCIMEM_BASE + (unsigned long)(a))
@@ -36,61 +36,19 @@
 #define __mem_isa(a)		___mem_isa((unsigned long)(a))
 #endif
 
-/* the following macro is depreciated */
-#define __ioaddr(p)		__io_pci(p)
-
 /*
  * Generic virtual read/write
  */
-#define __arch_getb(a)		(*(volatile unsigned char *)(a))
-#define __arch_getl(a)		(*(volatile unsigned int *)(a))
-
-extern __inline__ unsigned int __arch_getw(unsigned long a)
-{
-	unsigned int value;
-	__asm__ __volatile__("ldr%?h	%0, [%1, #0]	@ getw"
-		: "=&r" (value)
-		: "r" (a));
-	return value;
-}
-
-
-#define __arch_putb(v,a)	(*(volatile unsigned char *)(a) = (v))
-#define __arch_putl(v,a)	(*(volatile unsigned int *)(a) = (v))
-
-extern __inline__ void __arch_putw(unsigned int value, unsigned long a)
-{
-	__asm__ __volatile__("str%?h	%0, [%1, #0]	@ putw"
-		: : "r" (value), "r" (a));
-}
-
-#define inb(p)			__arch_getb(__io_pci(p))
-#define inw(p)			__arch_getw(__io_pci(p))
-#define inl(p)			__arch_getl(__io_pci(p))
-
-#define outb(v,p)		__arch_putb(v,__io_pci(p))
-#define outw(v,p)		__arch_putw(v,__io_pci(p))
-#define outl(v,p)		__arch_putl(v,__io_pci(p))
+#define __arch_getw(a)		(*(volatile unsigned short *)(a))
+#define __arch_putw(v,a)	(*(volatile unsigned short *)(a) = (v))
 
 /*
  * ioremap support - validate a PCI memory address,
  * and convert a PCI memory address to a physical
  * address for the page tables.
  */
-#define valid_ioaddr(off,sz)	((off) < 0x80000000 && (off) + (sz) <= 0x80000000)
-#define io_to_phys(off)		((off) + PLX_MEM_START)
-
-/*
- * ioremap takes a PCI memory address, as specified in
- * linux/Documentation/IO-mapping.txt
- */
-#define __arch_ioremap(off,size,nocache)			\
-({								\
-	unsigned long _off = (off), _size = (size);		\
-	void *_ret = (void *)0;					\
-	if (valid_ioaddr(_off, _size))				\
-		_ret = __ioremap(io_to_phys(_off), _size, 0);	\
-	_ret;							\
-})
+#define iomem_valid_addr(iomem,sz)	\
+	((iomem) < 0x80000000 && (iomem) + (sz) <= 0x80000000)
+#define iomem_to_phys(iomem)	((iomem) + PLX_MEM_START)
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-rpc/io.h linux/include/asm-arm/arch-rpc/io.h
--- v2.4.1/linux/include/asm-arm/arch-rpc/io.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-rpc/io.h	Thu Feb  8 16:32:44 2001
@@ -16,6 +16,49 @@
 #define IO_SPACE_LIMIT 0xffffffff
 
 /*
+ * GCC is totally crap at loading/storing data.  We try to persuade it
+ * to do the right thing by using these whereever possible instead of
+ * the above.
+ */
+#define __arch_base_getb(b,o)			\
+ ({						\
+	unsigned int v, r = (b);		\
+	__asm__ __volatile__(			\
+		"ldrb	%0, [%1, %2]"		\
+		: "=r" (v)			\
+		: "r" (r), "Ir" (o));		\
+	v;					\
+ })
+
+#define __arch_base_getl(b,o)			\
+ ({						\
+	unsigned int v, r = (b);		\
+	__asm__ __volatile__(			\
+		"ldr	%0, [%1, %2]"		\
+		: "=r" (v)			\
+		: "r" (r), "Ir" (o));		\
+	v;					\
+ })
+
+#define __arch_base_putb(v,b,o)			\
+ ({						\
+	unsigned int r = (b);			\
+	__asm__ __volatile__(			\
+		"strb	%0, [%1, %2]"		\
+		:				\
+		: "r" (v), "r" (r), "Ir" (o));	\
+ })
+
+#define __arch_base_putl(v,b,o)			\
+ ({						\
+	unsigned int r = (b);			\
+	__asm__ __volatile__(			\
+		"str	%0, [%1, %2]"		\
+		:				\
+		: "r" (v), "r" (r), "Ir" (o));	\
+ })
+
+/*
  * We use two different types of addressing - PC style addresses, and ARM
  * addresses.  PC style accesses the PC hardware with the normal PC IO
  * addresses, eg 0x3f8 for serial#1.  ARM addresses are 0x80000000+
@@ -74,7 +117,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2, lsl #2]	@ in"###fnsuffix	\
+	"ldr" instr "	%1, [%0, %2, lsl #2]	@ in" #fnsuffix			\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -195,22 +238,7 @@
 #define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
 #define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
 #define __ioaddr(p)	(__builtin_constant_p((p)) ? __ioaddr(p)  : __ioaddrc(p))
-
-/*
- * Translated address IO functions
- *
- * IO address has already been translated to a virtual address
- */
-#define outb_t(v,p)								\
-	(*(volatile unsigned char *)(p) = (v))
-
-#define inb_t(p)								\
-	(*(volatile unsigned char *)(p))
-
-#define outl_t(v,p)								\
-	(*(volatile unsigned long *)(p) = (v))
-
-#define inl_t(p)								\
-	(*(volatile unsigned long *)(p))
+/* the following macro is depreciated */
+#define ioaddr(port)			__ioaddr((port))
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-rpc/irqs.h linux/include/asm-arm/arch-rpc/irqs.h
--- v2.4.1/linux/include/asm-arm/arch-rpc/irqs.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-rpc/irqs.h	Thu Feb  8 16:32:44 2001
@@ -37,5 +37,10 @@
 #define FIQ_EXPANSIONCARD	6
 #define FIQ_FORCE		7
 
+/*
+ * This is the offset of the FIQ "IRQ" numbers
+ */
+#define FIQ_START		64
+
 #define IRQ_TIMER		IRQ_TIMER0
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/SA-1101.h linux/include/asm-arm/arch-sa1100/SA-1101.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/SA-1101.h	Tue Jul 18 22:43:25 2000
+++ linux/include/asm-arm/arch-sa1100/SA-1101.h	Tue Feb 13 14:13:44 2001
@@ -230,7 +230,7 @@
  *    IEEE_Addr		Forward transfer address register
  *    IEEE_Status	Port IO signal status register
  *    IEEE_IntStatus	Port interrupts status register
- *    IEEE_FifoLevels   Rx and Tx FIFO interupt generation levels
+ *    IEEE_FifoLevels   Rx and Tx FIFO interrupt generation levels
  *    IEEE_InitTime	Forward timeout counter initial value
  *    IEEE_TimerStatus	Forward timeout counter current value
  *    IEEE_FifoReset	Reset forward transfer FIFO
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/SA-1111.h linux/include/asm-arm/arch-sa1100/SA-1111.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/SA-1111.h	Tue Jul 18 22:43:25 2000
+++ linux/include/asm-arm/arch-sa1100/SA-1111.h	Thu Feb  8 16:32:44 2001
@@ -11,6 +11,8 @@
 #ifndef _ASM_ARCH_SA1111
 #define _ASM_ARCH_SA1111
 
+#include <asm/arch/bitfield.h>
+
 /*
  * Macro that calculates real address for registers in the SA-1111
  */
@@ -18,7 +20,21 @@
 #define _SA1111( x )    ((x) + SA1111_BASE)
 
 /*
- * System Bus Interface (SBI)
+ * 26 bits of the SA-1110 address bus are available to the SA-1111.
+ * Use these when feeding target addresses to the DMA engines.
+ */
+
+#define SA1111_ADDR_WIDTH	(26)
+#define SA1111_ADDR_MASK	((1<<SA1111_ADDR_WIDTH)-1)
+#define SA1111_DMA_ADDR(x)	((x)&SA1111_ADDR_MASK)
+
+/*
+ * Don't ask the (SAC) DMA engines to move less than this amount.
+ */
+
+#define SA1111_SAC_DMA_MIN_XFER	(0x800)
+
+/* System Bus Interface (SBI)
  *
  * Registers
  *    SKCR	Control Register
@@ -57,6 +73,7 @@
 #define SMCR_DRAC_0	(1<<2)
 #define SMCR_DRAC_1	(1<<3)
 #define SMCR_DRAC_2	(1<<4)
+#define SMCR_DRAC	Fld(3, 2)
 #define SMCR_CLAT	(1<<5)
 
 #define SKID_SIREV_MASK	(0x000000f0)
@@ -103,6 +120,186 @@
 
 #endif  /* LANGUAGE == C */
 
+#define SKPCR_UCLKEN	(1<<0)
+#define SKPCR_ACCLKEN	(1<<1)
+#define SKPCR_I2SCLKEN	(1<<2)
+#define SKPCR_L3CLKEN	(1<<3)
+#define SKPCR_SCLKEN	(1<<4)
+#define SKPCR_PMCLKEN	(1<<5)
+#define SKPCR_PTCLKEN	(1<<6)
+#define SKPCR_DCLKEN	(1<<7)
+#define SKPCR_PWMCLKEN	(1<<8)
+
+/*
+ * Serial Audio Controller
+ *
+ * Registers
+ *    SACR0             Serial Audio Common Control Register
+ *    SACR1             Serial Audio Alternate Mode (I2C/MSB) Control Register
+ *    SACR2             Serial Audio AC-link Control Register
+ *    SASR0             Serial Audio I2S/MSB Interface & FIFO Status Register
+ *    SASR1             Serial Audio AC-link Interface & FIFO Status Register
+ *    SASCR             Serial Audio Status Clear Register
+ *    L3_CAR            L3 Control Bus Address Register
+ *    L3_CDR            L3 Control Bus Data Register
+ *    ACCAR             AC-link Command Address Register
+ *    ACCDR             AC-link Command Data Register
+ *    ACSAR             AC-link Status Address Register
+ *    ACSDR             AC-link Status Data Register
+ *    SADTCS            Serial Audio DMA Transmit Control/Status Register
+ *    SADTSA            Serial Audio DMA Transmit Buffer Start Address A
+ *    SADTCA            Serial Audio DMA Transmit Buffer Count Register A
+ *    SADTSB            Serial Audio DMA Transmit Buffer Start Address B
+ *    SADTCB            Serial Audio DMA Transmit Buffer Count Register B
+ *    SADRCS            Serial Audio DMA Receive Control/Status Register
+ *    SADRSA            Serial Audio DMA Receive Buffer Start Address A
+ *    SADRCA            Serial Audio DMA Receive Buffer Count Register A
+ *    SADRSB            Serial Audio DMA Receive Buffer Start Address B
+ *    SADRCB            Serial Audio DMA Receive Buffer Count Register B
+ *    SAITR             Serial Audio Interrupt Test Register
+ *    SADR              Serial Audio Data Register (16 x 32-bit)
+ */
+
+#define _SACR0          _SA1111( 0x0600 )
+#define _SACR1          _SA1111( 0x0604 )
+#define _SACR2          _SA1111( 0x0608 )
+#define _SASR0          _SA1111( 0x060c )
+#define _SASR1          _SA1111( 0x0610 )
+#define _SASCR          _SA1111( 0x0618 )
+#define _L3_CAR         _SA1111( 0x061c )
+#define _L3_CDR         _SA1111( 0x0620 )
+#define _ACCAR          _SA1111( 0x0624 )
+#define _ACCDR          _SA1111( 0x0628 )
+#define _ACSAR          _SA1111( 0x062c )
+#define _ACSDR          _SA1111( 0x0630 )
+#define _SADTCS         _SA1111( 0x0634 )
+#define _SADTSA         _SA1111( 0x0638 )
+#define _SADTCA         _SA1111( 0x063c )
+#define _SADTSB         _SA1111( 0x0640 )
+#define _SADTCB         _SA1111( 0x0644 )
+#define _SADRCS         _SA1111( 0x0648 )
+#define _SADRSA         _SA1111( 0x064c )
+#define _SADRCA         _SA1111( 0x0650 )
+#define _SADRSB         _SA1111( 0x0654 )
+#define _SADRCB         _SA1111( 0x0658 )
+#define _SAITR          _SA1111( 0x065c )
+#define _SADR           _SA1111( 0x0680 )
+
+#if LANGUAGE == C
+
+#define SACR0		(*((volatile Word *) SA1111_p2v (_SACR0)))
+#define SACR1		(*((volatile Word *) SA1111_p2v (_SACR1)))
+#define SACR2		(*((volatile Word *) SA1111_p2v (_SACR2)))
+#define SASR0		(*((volatile Word *) SA1111_p2v (_SASR0)))
+#define SASR1		(*((volatile Word *) SA1111_p2v (_SASR1)))
+#define SASCR		(*((volatile Word *) SA1111_p2v (_SASCR)))
+#define L3_CAR		(*((volatile Word *) SA1111_p2v (_L3_CAR)))
+#define L3_CDR		(*((volatile Word *) SA1111_p2v (_L3_CDR)))
+#define ACCAR		(*((volatile Word *) SA1111_p2v (_ACCAR)))
+#define ACCDR		(*((volatile Word *) SA1111_p2v (_ACCDR)))
+#define ACSAR		(*((volatile Word *) SA1111_p2v (_ACSAR)))
+#define ACSDR		(*((volatile Word *) SA1111_p2v (_ACSDR)))
+#define SADTCS		(*((volatile Word *) SA1111_p2v (_SADTCS)))
+#define SADTSA		(*((volatile Word *) SA1111_p2v (_SADTSA)))
+#define SADTCA		(*((volatile Word *) SA1111_p2v (_SADTCA)))
+#define SADTSB		(*((volatile Word *) SA1111_p2v (_SADTSB)))
+#define SADTCB		(*((volatile Word *) SA1111_p2v (_SADTCB)))
+#define SADRCS		(*((volatile Word *) SA1111_p2v (_SADRCS)))
+#define SADRSA		(*((volatile Word *) SA1111_p2v (_SADRSA)))
+#define SADRCA		(*((volatile Word *) SA1111_p2v (_SADRCA)))
+#define SADRSB		(*((volatile Word *) SA1111_p2v (_SADRSB)))
+#define SADRCB		(*((volatile Word *) SA1111_p2v (_SADRCB)))
+#define SAITR		(*((volatile Word *) SA1111_p2v (_SAITR)))
+#define SADR		(*((volatile Word *) SA1111_p2v (_SADR)))
+
+#endif  /* LANGUAGE == C */
+
+#define SACR0_ENB	(1<<0)
+#define SACR0_BCKD	(1<<2)
+#define SACR0_RST	(1<<3)
+
+#define SACR1_AMSL	(1<<0)
+#define SACR1_L3EN	(1<<1)
+#define SACR1_L3MB	(1<<2)
+#define SACR1_DREC	(1<<3)
+#define SACR1_DRPL	(1<<4)
+#define SACR1_ENLBF	(1<<5)
+
+#define SACR2_TS3V	(1<<0)
+#define SACR2_TS4V	(1<<1)
+#define SACR2_WKUP	(1<<2)
+#define SACR2_DREC	(1<<3)
+#define SACR2_DRPL	(1<<4)
+#define SACR2_ENLBF	(1<<5)
+#define SACR2_RESET	(1<<5)
+
+#define SASR0_TNF	(1<<0)
+#define SASR0_RNE	(1<<1)
+#define SASR0_BSY	(1<<2)
+#define SASR0_TFS	(1<<3)
+#define SASR0_RFS	(1<<4)
+#define SASR0_TUR	(1<<5)
+#define SASR0_ROR	(1<<6)
+#define SASR0_L3WD	(1<<16)
+#define SASR0_L3RD	(1<<17)
+
+#define SASR1_TNF	(1<<0)
+#define SASR1_RNE	(1<<1)
+#define SASR1_BSY	(1<<2)
+#define SASR1_TFS	(1<<3)
+#define SASR1_RFS	(1<<4)
+#define SASR1_TUR	(1<<5)
+#define SASR1_ROR	(1<<6)
+#define SASR1_CADT	(1<<16)
+#define SASR1_SADR	(1<<17)
+#define SASR1_RSTO	(1<<18)
+#define SASR1_CLPM	(1<<19)
+#define SASR1_CRDY	(1<<20)
+#define SASR1_RS3V	(1<<21)
+#define SASR1_RS4V	(1<<22)
+
+#define SASCR_TUR	(1<<5)
+#define SASCR_ROR	(1<<6)
+#define SASCR_DTS	(1<<16)
+#define SASCR_RDD	(1<<17)
+#define SASCR_STO	(1<<18)
+
+#define SADTCS_TDEN	(1<<0)
+#define SADTCS_TDIE	(1<<1)
+#define SADTCS_TDBDA	(1<<3)
+#define SADTCS_TDSTA	(1<<4)
+#define SADTCS_TDBDB	(1<<5)
+#define SADTCS_TDSTB	(1<<6)
+#define SADTCS_TBIU	(1<<7)
+
+#define SADRCS_RDEN	(1<<0)
+#define SADRCS_RDIE	(1<<1)
+#define SADRCS_RDBDA	(1<<3)
+#define SADRCS_RDSTA	(1<<4)
+#define SADRCS_RDBDB	(1<<5)
+#define SADRCS_RDSTB	(1<<6)
+#define SADRCS_RBIU	(1<<7)
+
+#define SAD_CS_DEN	(1<<0)
+#define SAD_CS_DIE	(1<<1)	/* Not functional on metal 1 */
+#define SAD_CS_DBDA	(1<<3)	/* Not functional on metal 1 */
+#define SAD_CS_DSTA	(1<<4)
+#define SAD_CS_DBDB	(1<<5)	/* Not functional on metal 1 */
+#define SAD_CS_DSTB	(1<<6)
+#define SAD_CS_BIU	(1<<7)	/* Not functional on metal 1 */
+
+#define SAITR_TFS	(1<<0)
+#define SAITR_RFS	(1<<1)
+#define SAITR_TUR	(1<<2)
+#define SAITR_ROR	(1<<3)
+#define SAITR_CADT	(1<<4)
+#define SAITR_SADR	(1<<5)
+#define SAITR_RSTO	(1<<6)
+#define SAITR_TDBDA	(1<<8)
+#define SAITR_TDBDB	(1<<9)
+#define SAITR_RDBDA	(1<<10)
+#define SAITR_RDBDB	(1<<11)
+
 /*
  * General-Purpose I/O Interface
  *
@@ -211,6 +408,154 @@
 #define WAKE_EN1	(*((volatile Word *) SA1111_p2v (_WAKE_EN1)))
 #define WAKE_POL0	(*((volatile Word *) SA1111_p2v (_WAKE_POL0)))
 #define WAKE_POL1	(*((volatile Word *) SA1111_p2v (_WAKE_POL1)))
+
+#endif  /* LANGUAGE == C */
+
+/*
+ * PS/2 Trackpad and Mouse Interfaces
+ *
+ * Registers   (prefix kbd applies to trackpad interface, mse to mouse)
+ *    KBDCR     Control Register
+ *    KBDSTAT       Status Register
+ *    KBDDATA       Transmit/Receive Data register
+ *    KBDCLKDIV     Clock Division Register
+ *    KBDPRECNT     Clock Precount Register
+ *    KBDTEST1      Test register 1
+ *    KBDTEST2      Test register 2
+ *    KBDTEST3      Test register 3
+ *    KBDTEST4      Test register 4
+ *    MSECR
+ *    MSESTAT
+ *    MSEDATA
+ *    MSECLKDIV
+ *    MSEPRECNT
+ *    MSETEST1
+ *    MSETEST2
+ *    MSETEST3
+ *    MSETEST4
+ *
+ */
+
+#define _KBD( x )   _SA1111( 0x0A00 )
+#define _MSE( x )   _SA1111( 0x0C00 )
+
+#define _KBDCR      _SA1111( 0x0A00 )
+#define _KBDSTAT    _SA1111( 0x0A04 )
+#define _KBDDATA    _SA1111( 0x0A08 )
+#define _KBDCLKDIV  _SA1111( 0x0A0C )
+#define _KBDPRECNT  _SA1111( 0x0A10 )
+#define _MSECR      _SA1111( 0x0C00 )
+#define _MSESTAT    _SA1111( 0x0C04 )
+#define _MSEDATA    _SA1111( 0x0C08 )
+#define _MSECLKDIV  _SA1111( 0x0C10 )
+#define _MSEPRECNT  _SA1111( 0x0C14 )
+
+#if ( LANGUAGE == C )
+
+#define KBDCR       (*((volatile Word *) SA1111_p2v (_KBDCR)))
+#define KBDSTAT     (*((volatile Word *) SA1111_p2v (_KBDSTAT)))
+#define KBDDATA     (*((volatile Word *) SA1111_p2v (_KBDDATA)))
+#define KBDCLKDIV   (*((volatile Word *) SA1111_p2v (_KBDCLKDIV)))
+#define KBDPRECNT   (*((volatile Word *) SA1111_p2v (_KBDPRECNT)))
+#define KBDTEST1    (*((volatile Word *) SA1111_p2v (_KBDTEST1)))
+#define KBDTEST2    (*((volatile Word *) SA1111_p2v (_KBDTEST2)))
+#define KBDTEST3    (*((volatile Word *) SA1111_p2v (_KBDTEST3)))
+#define KBDTEST4    (*((volatile Word *) SA1111_p2v (_KBDTEST4)))
+#define MSECR       (*((volatile Word *) SA1111_p2v (_MSECR)))
+#define MSESTAT     (*((volatile Word *) SA1111_p2v (_MSESTAT)))
+#define MSEDATA     (*((volatile Word *) SA1111_p2v (_MSEDATA)))
+#define MSECLKDIV   (*((volatile Word *) SA1111_p2v (_MSECLKDIV)))
+#define MSEPRECNT   (*((volatile Word *) SA1111_p2v (_MSEPRECNT)))
+#define MSETEST1    (*((volatile Word *) SA1111_p2v (_MSETEST1)))
+#define MSETEST2    (*((volatile Word *) SA1111_p2v (_MSETEST2)))
+#define MSETEST3    (*((volatile Word *) SA1111_p2v (_MSETEST3)))
+#define MSETEST4    (*((volatile Word *) SA1111_p2v (_MSETEST4)))
+
+#define KBDCR_ENA        0x08
+#define KBDCR_FKD        0x02
+#define KBDCR_FKC        0x01
+
+#define KBDSTAT_TXE      0x80
+#define KBDSTAT_TXB      0x40
+#define KBDSTAT_RXF      0x20
+#define KBDSTAT_RXB      0x10
+#define KBDSTAT_ENA      0x08
+#define KBDSTAT_RXP      0x04
+#define KBDSTAT_KBD      0x02
+#define KBDSTAT_KBC      0x01
+
+#define KBDCLKDIV_DivVal     Fld(4,0)
+
+#define MSECR_ENA        0x08
+#define MSECR_FKD        0x02
+#define MSECR_FKC        0x01
+
+#define MSESTAT_TXE      0x80
+#define MSESTAT_TXB      0x40
+#define MSESTAT_RXF      0x20
+#define MSESTAT_RXB      0x10
+#define MSESTAT_ENA      0x08
+#define MSESTAT_RXP      0x04
+#define MSESTAT_MSD      0x02
+#define MSESTAT_MSC      0x01
+
+#define MSECLKDIV_DivVal     Fld(4,0)
+
+#define KBDTEST1_CD      0x80
+#define KBDTEST1_RC1         0x40
+#define KBDTEST1_MC      0x20
+#define KBDTEST1_C       Fld(2,3)
+#define KBDTEST1_T2      0x40
+#define KBDTEST1_T1      0x20
+#define KBDTEST1_T0      0x10
+#define KBDTEST2_TICBnRES    0x08
+#define KBDTEST2_RKC         0x04
+#define KBDTEST2_RKD         0x02
+#define KBDTEST2_SEL         0x01
+#define KBDTEST3_ms_16       0x80
+#define KBDTEST3_us_64       0x40
+#define KBDTEST3_us_16       0x20
+#define KBDTEST3_DIV8        0x10
+#define KBDTEST3_DIn         0x08
+#define KBDTEST3_CIn         0x04
+#define KBDTEST3_KD      0x02
+#define KBDTEST3_KC      0x01
+#define KBDTEST4_BC12        0x80
+#define KBDTEST4_BC11        0x40
+#define KBDTEST4_TRES        0x20
+#define KBDTEST4_CLKOE       0x10
+#define KBDTEST4_CRES        0x08
+#define KBDTEST4_RXB         0x04
+#define KBDTEST4_TXB         0x02
+#define KBDTEST4_SRX         0x01
+
+#define MSETEST1_CD      0x80
+#define MSETEST1_RC1         0x40
+#define MSETEST1_MC      0x20
+#define MSETEST1_C       Fld(2,3)
+#define MSETEST1_T2      0x40
+#define MSETEST1_T1      0x20
+#define MSETEST1_T0      0x10
+#define MSETEST2_TICBnRES    0x08
+#define MSETEST2_RKC         0x04
+#define MSETEST2_RKD         0x02
+#define MSETEST2_SEL         0x01
+#define MSETEST3_ms_16       0x80
+#define MSETEST3_us_64       0x40
+#define MSETEST3_us_16       0x20
+#define MSETEST3_DIV8        0x10
+#define MSETEST3_DIn         0x08
+#define MSETEST3_CIn         0x04
+#define MSETEST3_KD      0x02
+#define MSETEST3_KC      0x01
+#define MSETEST4_BC12        0x80
+#define MSETEST4_BC11        0x40
+#define MSETEST4_TRES        0x20
+#define MSETEST4_CLKOE       0x10
+#define MSETEST4_CRES        0x08
+#define MSETEST4_RXB         0x04
+#define MSETEST4_TXB         0x02
+#define MSETEST4_SRX         0x01
 
 #endif  /* LANGUAGE == C */
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/graphicsclient.h linux/include/asm-arm/arch-sa1100/graphicsclient.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/graphicsclient.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-sa1100/graphicsclient.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,88 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/graphicsclient.h
+ *
+ * Created 2000/06/11 by Nicolas Pitre <nico@cam.org>
+ * Modified 7/27/00 by Woojung <whuh@applieddata.net>
+ *
+ * This file contains the hardware specific definitions for the 
+ * ADS GraphicsClient/ThinClient boards.
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error "include <asm/hardware.h> instead"
+#endif
+
+
+#define ADS_CPLD_BASE		(0x10000000)
+#define ADS_p2v( x )		((x) - ADS_CPLD_BASE + 0xf0000000)
+#define ADS_v2p( x )		((x) - 0xf0000000 + ADS_CPLD_BASE)
+
+
+/* Parallel Port */
+
+#define _ADS_PPDR		0x10020000	/* parallel port data reg */
+#define _ADS_PPSR		0x10020004	/* parallel port status reg */
+
+
+/* PCMCIA */
+
+#define _ADS_CS_STATUS		0x10040000	/* PCMCIA status reg */
+#define ADS_CS_ST_A_READY	(1 << 0)	/* Socket A Card Ready */
+#define ADS_CS_ST_A_CD		(1 << 2)	/* Socket A Card Detect */
+#define ADS_CS_ST_A_BUSY	(1 << 4)	/* Socket A Card Busy */
+#define ADS_CS_ST_A_STS		(1 << 6)	/* Socket A Card STS */
+
+#define _ADS_CS_PR		0x10040004	/* PCMCIA Power/Reset */
+#define ADS_CS_PR_A_5V_POWER	(1 << 0)	/* Socket A Enable 5V Power */
+#define ADS_CS_PR_A_3V_POWER	(1 << 0)	/* Socket A Enable 3.3V Power */
+#define ADS_CS_PR_A_RESET		(1 << 2)	/* Socket A Reset */
+
+
+#define _ADS_SW_SWITCHES	0x10060000	/* Software Switches */
+
+
+/* Extra IRQ Controller */
+
+#define _ADS_INT_ST1		0x10080000	/* IRQ Status #1 */
+#define _ADS_INT_ST2		0x10080004	/* IRQ Status #2 */
+#define _ADS_INT_EN1		0x10080008	/* IRQ Enable #1 */
+#define _ADS_INT_EN2		0x1008000c	/* IRQ Enable #2 */
+
+/* Discrete Controller (AVR:Atmel AT90LS8535) */
+#define _ADS_AVR_REG		0x10080018
+
+/* On-Board Ethernet */
+
+#define _ADS_ETHERNET		0x100e0000	/* Ethernet */
+
+
+/* Extra UARTs */
+
+#define _ADS_UARTA		0x10100000	/* UART A */
+#define _ADS_UARTB		0x10120000	/* UART B */
+#define _ADS_UARTC		0x10140000	/* UART C */
+#define _ADS_UARTD		0x10160000	/* UART D */
+
+
+/* LEDs */
+
+#define ADS_LED0	GPIO_GPIO20		/* on-board D22 */
+#define ADS_LED1	GPIO_GPIO21		/* on-board D21 */
+#define ADS_LED2	GPIO_GPIO22		/* on-board D20 */
+#define ADS_LED3	GPIO_GPIO23		/* external */
+#define ADS_LED4	GPIO_GPIO24		/* external */
+#define ADS_LED5	GPIO_GPIO25		/* external */
+#define ADS_LED6	GPIO_GPIO26		/* external */
+#define ADS_LED7	GPIO_GPIO27		/* external */
+
+
+/* Virtual register addresses */
+
+#ifndef __ASSEMBLY__
+#define ADS_INT_ST1	(*((volatile u_char *) ADS_p2v(_ADS_INT_ST1)))
+#define ADS_INT_ST2	(*((volatile u_char *) ADS_p2v(_ADS_INT_ST2)))
+#define ADS_INT_EN1	(*((volatile u_char *) ADS_p2v(_ADS_INT_EN1)))
+#define ADS_INT_EN2	(*((volatile u_char *) ADS_p2v(_ADS_INT_EN2)))
+#define ADS_ETHERNET	((int) ADS_p2v(_ADS_ETHERNET))
+#define ADS_AVR_REG	(*((volatile u_char *) ADS_p2v(_ADS_AVR_REG)))
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/hardware.h linux/include/asm-arm/arch-sa1100/hardware.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/hardware.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-sa1100/hardware.h	Thu Feb  8 16:32:44 2001
@@ -80,6 +80,10 @@
  * Implementation specifics
  */
 
+#ifdef CONFIG_SA1100_PANGOLIN
+#include "pangolin.h"
+#endif
+
 #ifdef CONFIG_SA1100_ASSABET
 #include "assabet.h"
 #else
@@ -96,10 +100,6 @@
 
 #ifdef CONFIG_SA1100_BITSY
 #include "bitsy.h"
-#endif
-
-#if defined(CONFIG_SA1100_THINCLIENT)
-#include "thinclient.h"
 #endif
 
 #if defined(CONFIG_SA1100_GRAPHICSCLIENT)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/ide.h linux/include/asm-arm/arch-sa1100/ide.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/ide.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-sa1100/ide.h	Thu Feb  8 16:32:44 2001
@@ -15,10 +15,6 @@
 #include <asm/mach-types.h>
 
 
-#define PCMCIA_IO_0_BASE 0xe0000000
-#define PCMCIA_IO_1_BASE 0xe4000000
-
-
 /*
  * Set up a hw structure for a specified data port, control port and IRQ.
  * This should follow whatever the default interface uses.
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/io.h linux/include/asm-arm/arch-sa1100/io.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/io.h	Tue Jul 18 22:43:25 2000
+++ linux/include/asm-arm/arch-sa1100/io.h	Thu Feb  8 16:32:44 2001
@@ -16,45 +16,17 @@
  * We don't actually have real ISA nor PCI buses, but there is so many 
  * drivers out there that might just work if we fake them...
  */
-#define __io_pci(a)		(PCIO_BASE + (a))
+#define __io(a)			(PCIO_BASE + (a))
 #define __mem_pci(a)		((unsigned long)(a))
 #define __mem_isa(a)		((unsigned long)(a))
 
-#define __ioaddr(p)		__io_pci(p)
-
 /*
  * Generic virtual read/write
  */
-#define __arch_getb(a)		(*(volatile unsigned char *)(a))
-#define __arch_getl(a)		(*(volatile unsigned int  *)(a))
-
-extern __inline__ unsigned int __arch_getw(unsigned long a)
-{
-	unsigned int value;
-	__asm__ __volatile__("ldr%?h	%0, [%1, #0]	@ getw"
-		: "=&r" (value)
-		: "r" (a));
-	return value;
-}
-
-
-#define __arch_putb(v,a)	(*(volatile unsigned char *)(a) = (v))
-#define __arch_putl(v,a)	(*(volatile unsigned int  *)(a) = (v))
-
-extern __inline__ void __arch_putw(unsigned int value, unsigned long a)
-{
-	__asm__ __volatile__("str%?h	%0, [%1, #0]	@ putw"
-		: : "r" (value), "r" (a));
-}
-
-#define inb(p)			__arch_getb(__io_pci(p))
-#define inw(p)			__arch_getw(__io_pci(p))
-#define inl(p)			__arch_getl(__io_pci(p))
-
-#define outb(v,p)		__arch_putb(v,__io_pci(p))
-#define outw(v,p)		__arch_putw(v,__io_pci(p))
-#define outl(v,p)		__arch_putl(v,__io_pci(p))
+#define __arch_getw(a)		(*(volatile unsigned short *)(a))
+#define __arch_putw(v,a)	(*(volatile unsigned short *)(a) = (v))
 
-#define __arch_ioremap		__ioremap
+#define iomem_valid_addr(iomem,sz)	(1)
+#define iomem_to_phys(iomem)		(iomem)
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/irq.h linux/include/asm-arm/arch-sa1100/irq.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/irq.h	Sun Aug 13 09:54:15 2000
+++ linux/include/asm-arm/arch-sa1100/irq.h	Thu Feb  8 16:32:44 2001
@@ -11,11 +11,14 @@
  *   17-02-1999	NP	empeg henry ugly hacks now in a separate file ;)
  *   11-08-1999	PD	SA1101 support added
  *   25-09-1999	RMK	Merged into main ARM tree, cleaned up
- *   12-05-2000 NP	IRQ dispatcher handler for GPIO 11 to 27.
+ *   12-05-2000 NP	IRQ dispatcher handler for GPIOs 11 to 27.
  *   26-05-2000 JD	SA-1111 support added
+ *   01-06-2000 NP	GraphicsClient external IRQ dispatcher
+ *   09-10-2000 NP	Fixed lost interrupts on GPIOs 11 to 27.
  */
 #include <linux/config.h>
 #include <asm/irq.h>
+#include <asm/hardware.h>
 #include <asm/mach-types.h>
 
 #define fixup_irq(x)	(x)
@@ -85,7 +88,7 @@
 		 * unmasked.  However, such situation should happen only
 		 * during the loop below.  Thus all IRQs which aren't 
 		 * enabled at this point are considered spurious.  Those 
-		 * are cleared but only de-activated if they happened twice.
+		 * are cleared but only de-activated if they happen twice.
 		 */
 		spurious = irq & ~GPIO_11_27_enabled;
 		if (spurious) {
@@ -114,20 +117,35 @@
 static void sa1100_mask_and_ack_GPIO11_27_irq(unsigned int irq)
 {
 	int mask = (1 << GPIO_11_27_IRQ(irq));
+	GPIO_11_27_spurious &= ~mask;
 	GPIO_11_27_enabled &= ~mask;
 	GEDR = mask;
 }
 
 static void sa1100_mask_GPIO11_27_irq(unsigned int irq)
 {
-	GPIO_11_27_enabled &= ~(1 << GPIO_11_27_IRQ(irq));
+	int mask = (1 << GPIO_11_27_IRQ(irq));
+	GPIO_11_27_spurious &= ~mask;
+	GPIO_11_27_enabled &= ~mask;
 }
 
 static void sa1100_unmask_GPIO11_27_irq(unsigned int irq)
 {
 	int mask = (1 << GPIO_11_27_IRQ(irq));
+	if (GPIO_11_27_spurious & mask) {
+		/* 
+		 * We don't want to miss an interrupt that would have occured
+		 * while it was masked.  Simulate it if it is the case.
+		 */
+		int state = GPLR;
+		if (((state & GPIO_IRQ_rising_edge) | 
+		     (~state & GPIO_IRQ_falling_edge)) & mask) {
+			do_IRQ(irq, NULL);
+			/* we are being called again from do_IRQ() so ... */
+			return;
+		}
+	}
 	GPIO_11_27_enabled |= mask;
-	GPIO_11_27_spurious &= ~mask;
 	GRER = (GRER & ~mask) | (GPIO_IRQ_rising_edge & mask);
 	GFER = (GFER & ~mask) | (GPIO_IRQ_falling_edge & mask);
 }
@@ -245,7 +263,7 @@
 #endif
 
 
-#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_THINCLIENT)
+#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
 
 /*
  * IRQ handler for the ThinClient/GraphicsClient external IRQ controller
@@ -399,8 +417,8 @@
 	}
 #endif
 
-#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_THINCLIENT)
-	if( machine_is_graphicsclient()  || machine_is_thinclient() ){
+#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
+	if( machine_is_graphicsclient() ){
 		/* disable all IRQs */
 		ADS_INT_EN1 = 0;
 		ADS_INT_EN2 = 0;
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/irqs.h linux/include/asm-arm/arch-sa1100/irqs.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/irqs.h	Mon Jun 19 17:59:35 2000
+++ linux/include/asm-arm/arch-sa1100/irqs.h	Thu Feb  8 16:32:44 2001
@@ -72,7 +72,7 @@
 #define	NR_IRQS		(IRQ_GPIO27 + 1)
 
 
-#if defined(CONFIG_SA1100_GRAPHICSCLIENT) || defined(CONFIG_SA1100_THINCLIENT)
+#if defined(CONFIG_SA1100_GRAPHICSCLIENT)
 #define ADS_EXT_IRQ(x)	(IRQ_GPIO27 + 1 + (x))
 #undef NR_IRQS
 #define NR_IRQS		(ADS_EXT_IRQ(15) + 1)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/memory.h linux/include/asm-arm/arch-sa1100/memory.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/memory.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-sa1100/memory.h	Thu Feb  8 16:32:44 2001
@@ -15,6 +15,12 @@
 #define TASK_SIZE_26	(0x04000000UL)
 
 /*
+ * This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
+
+/*
  * Page offset: 3GB
  */
 #define PAGE_OFFSET	(0xc0000000UL)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/mmzone.h linux/include/asm-arm/arch-sa1100/mmzone.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/mmzone.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-sa1100/mmzone.h	Thu Feb  8 16:32:44 2001
@@ -41,11 +41,11 @@
  * Given a kernel address, find the home node of the underlying memory.
  */
 #define KVADDR_TO_NID(addr) \
-		(((unsigned long)(addr) & 0x18000000) >> 27)
+		(((unsigned long)(addr) - 0xc0000000) >> 27)
 
 /*
  * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
- * and returns the the mem_map of that node.
+ * and returns the mem_map of that node.
  */
 #define ADDR_TO_MAPBASE(kaddr) \
 			NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
@@ -66,7 +66,12 @@
 	(ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
 
 /*
- * Didn't find the best way to validate a page pointer yet...
+ * VALID_PAGE returns a non-zero value if given page pointer is valid.
+ * This assumes all node's mem_maps are stored within the node they refer to.
  */
+#define VALID_PAGE(page) \
+({ unsigned int node = KVADDR_TO_NID(page); \
+   ( (node < 4) && \
+     ((unsigned)((page) - NODE_MEM_MAP(node)) < NODE_DATA(node)->node_size) ); \
+})
 
-#define VALID_PAGE(page)	(1)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/pangolin.h linux/include/asm-arm/arch-sa1100/pangolin.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/pangolin.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/arch-sa1100/pangolin.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,22 @@
+/*
+ * linux/include/asm-arm/arch-sa1100/pangolin.h
+ *
+ * Created 2000/08/25 by Murphy Chen <murphy@mail.dialogue.com.tw>
+ *
+ * This file contains the hardware specific definitions for Pangolin
+ *
+ */
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#error "include <asm/hardware.h> instead"
+#endif
+
+
+/* GPIOs for which the generic definition doesn't say much */
+#define GPIO_CF_BUS_ON		GPIO_GPIO (3)
+#define GPIO_CF_RESET		GPIO_GPIO (2)
+#define GPIO_CF_CD		GPIO_GPIO (22)
+#define GPIO_CF_IRQ		GPIO_GPIO (21)
+
+#define IRQ_GPIO_CF_IRQ		IRQ_GPIO21
+#define IRQ_GPIO_CF_CD		IRQ_GPIO22
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/processor.h linux/include/asm-arm/arch-sa1100/processor.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/processor.h	Wed Oct 20 16:29:08 1999
+++ linux/include/asm-arm/arch-sa1100/processor.h	Wed Dec 31 16:00:00 1969
@@ -1,28 +0,0 @@
-/*
- * linux/include/asm-arm/arch-sa1100/processor.h
- *
- * Copyright (c) 1996 Russell King.
- *
- * Changelog:
- *  10-09-1996	RMK	Created
- *  05-01-1999  HBF     Mods for SA1100
- *  21-09-1999  NP	SWAPPER_PG_DIR readjusted for SA1100
- */
-
-#ifndef __ASM_ARCH_PROCESSOR_H
-#define __ASM_ARCH_PROCESSOR_H
-
-/*
- * Bus types
- */
-#define EISA_bus 0
-#define EISA_bus__is_a_macro /* for versions in ksyms.c */
-#define MCA_bus 0
-#define MCA_bus__is_a_macro /* for versions in ksyms.c */
-
-/* This decides where the kernel will search for a free chunk of vm
- * space during mmap's.
- */
-#define TASK_UNMAPPED_BASE (TASK_SIZE / 3)
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/system.h linux/include/asm-arm/arch-sa1100/system.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/system.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-sa1100/system.h	Thu Feb  8 16:32:44 2001
@@ -24,13 +24,9 @@
 		/* Jump into ROM at address 0 */
 		cpu_reset(0);
 	} else {
-		/* Activate SA1100 watchdog and wait for the trigger... */
-		OSMR3 = OSCR + 3686400/2;	/* in 1/2 sec */
-		OWER |= OWER_WME;
-		OIER |= OIER_E3;
+		/* Use on-chip reset capability */
+		RSRR = RSRR_SWR;
 	}
 }
-
-#define arch_power_off()	do { } while (0)
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/thinclient.h linux/include/asm-arm/arch-sa1100/thinclient.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/thinclient.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-sa1100/thinclient.h	Wed Dec 31 16:00:00 1969
@@ -1,89 +0,0 @@
-/*
- * linux/include/asm-arm/arch-sa1100/thinclient.h
- *
- * Created 2000/06/11 by Nicolas Pitre <nico@cam.org>
- *
- * This file contains the hardware specific definitions for the ADS
- * ThinClient/GraphicsClient boards.
- */
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#error "include <asm/hardware.h> instead"
-#endif
-
-
-#define ADS_CPLD_BASE		(0x10000000)
-#define ADS_p2v( x )		((x) - ADS_CPLD_BASE + 0xf0000000)
-#define ADS_v2p( x )		((x) - 0xf0000000 + ADS_CPLD_BASE)
-
-
-/* Parallel Port */
-
-#define _ADS_PPDR		0x10020000	/* parallel port data reg */
-#define _ADS_PPSR		0x10020004	/* parallel port status reg */
-
-
-/* PCMCIA */
-
-#define _ADS_CS_STATUS		0x10040000	/* PCMCIA status reg */
-#define ADS_CS_ST_A_READY	(1 << 0)	/* Socket A Card Ready */
-#define ADS_CS_ST_B_READY	(1 << 1)	/* Socket B Card Ready */
-#define ADS_CS_ST_A_CD		(1 << 2)	/* Socket A Card Detect */
-#define ADS_CS_ST_B_CD		(1 << 3)	/* Socket B Card Detect */
-#define ADS_CS_ST_A_BUSY	(1 << 4)	/* Socket A Card Busy */
-#define ADS_CS_ST_B_BUSY	(1 << 5)	/* Socket B Card Busy */
-#define ADS_CS_ST_A_STS		(1 << 6)	/* Socket A Card STS */
-#define ADS_CS_ST_B_STS		(1 << 7)	/* Socket B Card STS */
-
-#define _ADS_CS_PR		0x10040004	/* PCMCIA Power/Reset */
-#define ADS_CS_PR_A_POWER	(1 << 0)	/* Socket A Enable Power */
-#define ADS_CS_PR_B_POWER	(1 << 1)	/* Socket B Enable Power */
-#define ADS_CS_PR_A_RESET	(1 << 2)	/* Socket A Reset */
-#define ADS_CS_PR_B_RESET	(1 << 3)	/* Socket B Reset */
-
-
-#define _ADS_SW_SWITCHES	0x10060000	/* Software Switches */
-
-
-/* Extra IRQ Controller */
-
-#define _ADS_INT_ST1		0x10080000	/* IRQ Status #1 */
-#define _ADS_INT_ST2		0x10080004	/* IRQ Status #2 */
-#define _ADS_INT_EN1		0x10080008	/* IRQ Enable #1 */
-#define _ADS_INT_EN2		0x1008000c	/* IRQ Enable #2 */
-
-
-/* On-Board Ethernet */
-
-#define _ADS_ETHERNET		0x100e0000	/* Ethernet */
-
-
-/* Extra UARTs */
-
-#define _ADS_UARTA		0x10100000	/* UART A */
-#define _ADS_UARTB		0x10120000	/* UART B */
-#define _ADS_UARTC		0x10140000	/* UART C */
-#define _ADS_UARTD		0x10160000	/* UART D */
-
-
-/* LEDs */
-
-#define ADS_LED0	GPIO_GPIO20		/* on-board D22 */
-#define ADS_LED1	GPIO_GPIO21		/* on-board D21 */
-#define ADS_LED2	GPIO_GPIO22		/* on-board D20 */
-#define ADS_LED3	GPIO_GPIO23		/* external */
-#define ADS_LED4	GPIO_GPIO24		/* external */
-#define ADS_LED5	GPIO_GPIO25		/* external */
-#define ADS_LED6	GPIO_GPIO26		/* external */
-#define ADS_LED7	GPIO_GPIO27		/* external */
-
-
-/* Virtual register addresses */
-
-#ifndef __ASSEMBLY__
-#define ADS_INT_ST1	(*((volatile u_char *) ADS_p2v(_ADS_INT_ST1)))
-#define ADS_INT_ST2	(*((volatile u_char *) ADS_p2v(_ADS_INT_ST2)))
-#define ADS_INT_EN1	(*((volatile u_char *) ADS_p2v(_ADS_INT_EN1)))
-#define ADS_INT_EN2	(*((volatile u_char *) ADS_p2v(_ADS_INT_EN2)))
-#define ADS_ETHERNET	((int) ADS_p2v(_ADS_ETHERNET))
-#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-sa1100/uncompress.h linux/include/asm-arm/arch-sa1100/uncompress.h
--- v2.4.1/linux/include/asm-arm/arch-sa1100/uncompress.h	Sun Aug 13 09:54:15 2000
+++ linux/include/asm-arm/arch-sa1100/uncompress.h	Thu Feb  8 16:32:44 2001
@@ -31,10 +31,12 @@
 			serial_port = (unsigned long *)_Ser3UTCR0;
 		else
 			serial_port = (unsigned long *)_Ser1UTCR0;
-	} else if (machine_is_brutus()||machine_is_nanoengine())
+	} else if (machine_is_brutus()||machine_is_nanoengine() ||
+		machine_is_pangolin())
 		serial_port = (unsigned long *)_Ser1UTCR0;
 	else if (machine_is_empeg() || machine_is_bitsy() ||
-		 machine_is_victor() || machine_is_lart())
+		 machine_is_victor() || machine_is_lart() ||
+		 machine_is_sherman() )
 		serial_port = (unsigned long *)_Ser3UTCR0;
 	else
 		return;
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-shark/io.h linux/include/asm-arm/arch-shark/io.h
--- v2.4.1/linux/include/asm-arm/arch-shark/io.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-shark/io.h	Thu Feb  8 16:32:44 2001
@@ -35,7 +35,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"str" ##instr## "	%1, [%0, %2]	@ out"###fnsuffix	\
+	"str" instr "	%1, [%0, %2]	@ out" #fnsuffix			\
 	: "=&r" (temp)								\
 	: "r" (value), "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)	\
 	: "cc");								\
@@ -49,7 +49,7 @@
 	"tst	%2, #0x80000000\n\t"						\
 	"mov	%0, %4\n\t"							\
 	"addeq	%0, %0, %3\n\t"							\
-	"ldr" ##instr## "	%1, [%0, %2]	@ in"###fnsuffix	\
+	"ldr" instr "	%1, [%0, %2]	@ in" #fnsuffix				\
 	: "=&r" (temp), "=r" (value)						\
 	: "r" (port), "Ir" (PCIO_BASE - IO_BASE), "Ir" (IO_BASE)		\
 	: "cc");								\
@@ -181,13 +181,8 @@
 #define outw(v,p)	(__builtin_constant_p((p)) ? __outwc(v,p) : __outw(v,p))
 #define outl(v,p)	(__builtin_constant_p((p)) ? __outlc(v,p) : __outl(v,p))
 
-#define __arch_getb(addr)	(*(volatile unsigned char *)(addr))
 #define __arch_getw(addr)	(*(volatile unsigned short *)(addr))
-#define __arch_getl(addr)	(*(volatile unsigned long *)(addr))
-
-#define __arch_putb(b,addr)	(*(volatile unsigned char *)(addr) = (b))
 #define __arch_putw(b,addr)	(*(volatile unsigned short *)(addr) = (b))
-#define __arch_putl(b,addr)	(*(volatile unsigned long *)(addr) = (b))
 
 /*
  * Translated address IO functions
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/arch-tbox/io.h linux/include/asm-arm/arch-tbox/io.h
--- v2.4.1/linux/include/asm-arm/arch-tbox/io.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/arch-tbox/io.h	Thu Feb  8 16:32:44 2001
@@ -10,14 +10,11 @@
 
 #define IO_SPACE_LIMIT 0xffffffff
 
-#define __io_pc(_x)	((_x) << 2)
+#define __io(_x)		((_x) << 2)
 
 /*
  * Generic virtual read/write
  */
-#define __arch_getb(a)		(*(volatile unsigned char *)(a))
-#define __arch_getl(a)		(*(volatile unsigned long *)(a))
-
 extern __inline__ unsigned int __arch_getw(unsigned long a)
 {
 	unsigned int value;
@@ -27,23 +24,11 @@
 	return value;
 }
 
-
-#define __arch_putb(v,a)	(*(volatile unsigned char *)(a) = (v))
-#define __arch_putl(v,a)	(*(volatile unsigned long *)(a) = (v))
-
 extern __inline__ void __arch_putw(unsigned int value, unsigned long a)
 {
 	__asm__ __volatile__("str%?h	%0, [%1, #0]	@ putw"
 		: : "r" (value), "r" (a));
 }
-
-#define inb(p)			__arch_getb(__io_pc(p))
-#define inw(p)			__arch_getw(__io_pc(p))
-#define inl(p)			__arch_getl(__io_pc(p))
-
-#define outb(v,p)		__arch_putb(v,__io_pc(p))
-#define outw(v,p)		__arch_putw(v,__io_pc(p))
-#define outl(v,p)		__arch_putl(v,__io_pc(p))
 
 /* Idem, for devices on the upper byte lanes */
 #define inb_u(p)		__arch_getb(__io_pc(p) + 2)
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/ecard.h linux/include/asm-arm/ecard.h
--- v2.4.1/linux/include/asm-arm/ecard.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/ecard.h	Thu Feb  8 16:32:44 2001
@@ -41,8 +41,8 @@
 #define PROD_MORLEY_SCSI_UNCACHED	0x0067
 
 #define MANU_CUMANA		0x003a
-#define PROD_CUMANA_SCSI_1		0x00a0
 #define PROD_CUMANA_SCSI_2		0x003a
+#define PROD_CUMANA_SCSI_1		0x00a0
 
 #define MANU_ICS		0x003c
 #define PROD_ICS_IDE			0x00ae
@@ -59,6 +59,7 @@
 #define PROD_I3_ETHERLAN600A		0x011e
 
 #define MANU_ANT		0x0053
+#define PROD_ANT_ETHERM			0x00d8
 #define PROD_ANT_ETHERB			0x00e4
 
 #define MANU_ALSYSTEMS		0x005b
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/fiq.h linux/include/asm-arm/fiq.h
--- v2.4.1/linux/include/asm-arm/fiq.h	Sat May  8 11:06:57 1999
+++ linux/include/asm-arm/fiq.h	Thu Feb  8 16:32:44 2001
@@ -31,5 +31,7 @@
 extern void set_fiq_handler(void *start, unsigned int length);
 extern void set_fiq_regs(struct pt_regs *regs);
 extern void get_fiq_regs(struct pt_regs *regs);
+extern void enable_fiq(int fiq);
+extern void disable_fiq(int fiq);
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/io.h linux/include/asm-arm/io.h
--- v2.4.1/linux/include/asm-arm/io.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/io.h	Thu Feb  8 16:32:44 2001
@@ -20,10 +20,43 @@
 #ifndef __ASM_ARM_IO_H
 #define __ASM_ARM_IO_H
 
+#ifdef __KERNEL__
+
 #include <linux/types.h>
+#include <asm/memory.h>
 #include <asm/arch/hardware.h>
+
+/*
+ * Generic virtual read/write.  Note that we don't support half-word
+ * read/writes.  We define __arch_*[bl] here, and leave __arch_*w
+ * to the architecture specific code.
+ */
+#define __arch_getb(a)		(*(volatile unsigned char *)(a))
+#define __arch_getl(a)		(*(volatile unsigned int  *)(a))
+
+#define __arch_putb(v,a)	(*(volatile unsigned char *)(a) = (v))
+#define __arch_putl(v,a)	(*(volatile unsigned int  *)(a) = (v))
+
+/*
+ * Now, pick up the machine-defined IO definitions
+ */
 #include <asm/arch/io.h>
 
+/*
+ * IO definitions.  We define {out,in}[bwl] if __io is defined by
+ * the machine.  Otherwise, these definitions are left for the
+ * machine specific header files to pick up.
+ */
+#ifdef __io
+#define outb(v,p)			__arch_putb(v,__io(p))
+#define outw(v,p)			__arch_putw(v,__io(p))
+#define outl(v,p)			__arch_putl(v,__io(p))
+
+#define inb(p)				__arch_getb(__io(p))
+#define inw(p)				__arch_getw(__io(p))
+#define inl(p)				__arch_getl(__io(p))
+#endif
+
 #define outb_p(val,port)		outb((val),(port))
 #define outw_p(val,port)		outw((val),(port))
 #define outl_p(val,port)		outl((val),(port))
@@ -45,19 +78,34 @@
 #define insw_p(port,to,len)		insw(port,to,len)
 #define insl_p(port,to,len)		insl(port,to,len)
 
-#ifdef __KERNEL__
-
-#include <asm/memory.h>
-
-/* the following macro is depreciated */
-#define ioaddr(port)			__ioaddr((port))
-
 /*
- * ioremap and friends
+ * ioremap and friends.
+ *
+ * ioremap takes a PCI memory address, as specified in
+ * linux/Documentation/IO-mapping.txt.  If you want a
+ * physical address, use __ioremap instead.
  */
 extern void * __ioremap(unsigned long offset, size_t size, unsigned long flags);
 extern void __iounmap(void *addr);
 
+/*
+ * Generic ioremap support.
+ *
+ * Define:
+ *  iomem_valid_addr(off,size)
+ *  iomem_to_phys(off)
+ */
+#ifdef iomem_valid_addr
+#define __arch_ioremap(off,sz,nocache)				\
+ ({								\
+	unsigned long _off = (off), _size = (sz);		\
+	void *_ret = (void *)0;					\
+	if (iomem_valid_addr(_off, _size))			\
+		_ret = __ioremap(iomem_to_phys(_off),_size,0);	\
+	_ret;							\
+ })
+#endif
+
 #define ioremap(off,sz)			__arch_ioremap((off),(sz),0)
 #define ioremap_nocache(off,sz)		__arch_ioremap((off),(sz),1)
 #define iounmap(_addr)			__iounmap(_addr)
@@ -72,7 +120,26 @@
 extern void consistent_free(void *vaddr);
 extern void consistent_sync(void *vaddr, size_t size, int rw);
 
-extern void __readwrite_bug(const char *fn);
+#define __raw_writeb(v,a)		__arch_putb(v,a)
+#define __raw_writew(v,a)		__arch_putw(v,a)
+#define __raw_writel(v,a)		__arch_putl(v,a)
+
+#define __raw_readb(a)			__arch_getb(a)
+#define __raw_readw(a)			__arch_getw(a)
+#define __raw_readl(a)			__arch_getl(a)
+
+/*
+ * The compiler seems to be incapable of optimising constants
+ * properly.  Spell it out to the compiler in some cases.
+ * These are only valid for small values of "off" (< 1<<12)
+ */
+#define __raw_base_writeb(val,base,off)	__arch_base_putb(val,base,off)
+#define __raw_base_writew(val,base,off)	__arch_base_putw(val,base,off)
+#define __raw_base_writel(val,base,off)	__arch_base_putl(val,base,off)
+
+#define __raw_base_readb(base,off)	__arch_base_getb(base,off)
+#define __raw_base_readw(base,off)	__arch_base_getw(base,off)
+#define __raw_base_readl(base,off)	__arch_base_getl(base,off)
 
 /*
  * String version of IO memory access ops:
@@ -81,26 +148,21 @@
 extern void _memcpy_toio(unsigned long, const void *, size_t);
 extern void _memset_io(unsigned long, int, size_t);
 
-#define __raw_writeb(val,addr)		__arch_putb(val,addr)
-#define __raw_writew(val,addr)		__arch_putw(val,addr)
-#define __raw_writel(val,addr)		__arch_putl(val,addr)
-
-#define __raw_readb(addr)		__arch_getb(addr)
-#define __raw_readw(addr)		__arch_getw(addr)
-#define __raw_readl(addr)		__arch_getl(addr)
+extern void __readwrite_bug(const char *fn);
 
 /*
  * If this architecture has PCI memory IO, then define the read/write
- * macros.
+ * macros.  These should only be used with the cookie passed from
+ * ioremap.
  */
 #ifdef __mem_pci
 
-#define readb(addr)			__arch_getb(__mem_pci(addr))
-#define readw(addr)			__arch_getw(__mem_pci(addr))
-#define readl(addr)			__arch_getl(__mem_pci(addr))
-#define writeb(val,addr)		__arch_putb(val,__mem_pci(addr))
-#define writew(val,addr)		__arch_putw(val,__mem_pci(addr))
-#define writel(val,addr)		__arch_putl(val,__mem_pci(addr))
+#define readb(addr)			__raw_readb(__mem_pci(addr))
+#define readw(addr)			__raw_readw(__mem_pci(addr))
+#define readl(addr)			__raw_readl(__mem_pci(addr))
+#define writeb(val,addr)		__raw_writeb(val,__mem_pci(addr))
+#define writew(val,addr)		__raw_writew(val,__mem_pci(addr))
+#define writel(val,addr)		__raw_writel(val,__mem_pci(addr))
 
 #define memset_io(a,b,c)		_memset_io(__mem_pci(a),(b),(c))
 #define memcpy_fromio(a,b,c)		_memcpy_fromio((a),__mem_pci(b),(c))
@@ -142,17 +204,25 @@
 #endif	/* __mem_pci */
 
 /*
+ * remap a physical address `phys' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_page_range(from,phys,size,prot) \
+		remap_page_range(from,phys,size,prot)
+
+
+/*
  * If this architecture has ISA IO, then define the isa_read/isa_write
  * macros.
  */
 #ifdef __mem_isa
 
-#define isa_readb(addr)			__arch_getb(__mem_isa(addr))
-#define isa_readw(addr)			__arch_getw(__mem_isa(addr))
-#define isa_readl(addr)			__arch_getl(__mem_isa(addr))
-#define isa_writeb(val,addr)		__arch_putb(val,__mem_isa(addr))
-#define isa_writew(val,addr)		__arch_putw(val,__mem_isa(addr))
-#define isa_writel(val,addr)		__arch_putl(val,__mem_isa(addr))
+#define isa_readb(addr)			__raw_readb(__mem_isa(addr))
+#define isa_readw(addr)			__raw_readw(__mem_isa(addr))
+#define isa_readl(addr)			__raw_readl(__mem_isa(addr))
+#define isa_writeb(val,addr)		__raw_writeb(val,__mem_isa(addr))
+#define isa_writew(val,addr)		__raw_writew(val,__mem_isa(addr))
+#define isa_writel(val,addr)		__raw_writel(val,__mem_isa(addr))
 #define isa_memset_io(a,b,c)		_memset_io(__mem_isa(a),(b),(c))
 #define isa_memcpy_fromio(a,b,c)	_memcpy_fromio((a),__mem_isa(b),(c))
 #define isa_memcpy_toio(a,b,c)		_memcpy_toio(__mem_isa((a)),(b),(c))
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/ioctls.h linux/include/asm-arm/ioctls.h
--- v2.4.1/linux/include/asm-arm/ioctls.h	Thu Feb 12 16:25:04 1998
+++ linux/include/asm-arm/ioctls.h	Thu Feb  8 16:32:44 2001
@@ -65,6 +65,7 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define FIOQSIZE	0x545E
 
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/linux_logo.h linux/include/asm-arm/linux_logo.h
--- v2.4.1/linux/include/asm-arm/linux_logo.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/linux_logo.h	Thu Feb  8 16:32:44 2001
@@ -32,9 +32,6 @@
 extern unsigned char linux_logo_blue[];
 extern unsigned char linux_logo[];
 extern unsigned char linux_logo_bw[];
-extern unsigned char linux_logo16_red[];
-extern unsigned char linux_logo16_green[];
-extern unsigned char linux_logo16_blue[];
 extern unsigned char linux_logo16[];
 extern unsigned char *linux_serial_image;
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/mach/arch.h linux/include/asm-arm/mach/arch.h
--- v2.4.1/linux/include/asm-arm/mach/arch.h	Mon Sep 18 15:15:23 2000
+++ linux/include/asm-arm/mach/arch.h	Thu Feb  8 16:32:44 2001
@@ -12,35 +12,42 @@
  * The size of struct machine_desc
  *   (for assembler code)
  */
-#define SIZEOF_MACHINE_DESC	44
+#define SIZEOF_MACHINE_DESC	56
 
 #ifndef __ASSEMBLY__
 
+extern void setup_initrd(unsigned int start, unsigned int size);
+extern void setup_ramdisk(int doload, int prompt, int start, unsigned int rd_sz);
+
+struct tagtable;
+
 struct machine_desc {
 	/*
 	 * Note! The first four elements are used
 	 * by assembler code in head-armv.S
 	 */
-	unsigned int	nr;		/* architecture number	*/
-	unsigned int	phys_ram;	/* start of physical ram */
-	unsigned int	phys_io;	/* start of physical io	*/
-	unsigned int	virt_io;	/* start of virtual io	*/
-
-	const char	*name;		/* architecture name	*/
-	unsigned int	param_offset;	/* parameter page	*/
-
-	unsigned int	video_start;	/* start of video RAM	*/
-	unsigned int	video_end;	/* end of video RAM	*/
-
-	unsigned int	reserve_lp0 :1;	/* never has lp0	*/
-	unsigned int	reserve_lp1 :1;	/* never has lp1	*/
-	unsigned int	reserve_lp2 :1;	/* never has lp2	*/
-	unsigned int	broken_hlt  :1;	/* hlt is broken	*/
-	unsigned int	soft_reboot :1;	/* soft reboot		*/
-	void		(*fixup)(struct machine_desc *,
-				 struct param_struct *, char **,
-				 struct meminfo *);
-	void		(*map_io)(void);/* IO mapping function	*/
+	unsigned int		nr;		/* architecture number	*/
+	unsigned int		phys_ram;	/* start of physical ram */
+	unsigned int		phys_io;	/* start of physical io	*/
+	unsigned int		virt_io;	/* start of virtual io	*/
+
+	const char		*name;		/* architecture name	*/
+	unsigned int		param_offset;	/* parameter page	*/
+
+	unsigned int		video_start;	/* start of video RAM	*/
+	unsigned int		video_end;	/* end of video RAM	*/
+
+	unsigned int		reserve_lp0 :1;	/* never has lp0	*/
+	unsigned int		reserve_lp1 :1;	/* never has lp1	*/
+	unsigned int		reserve_lp2 :1;	/* never has lp2	*/
+	unsigned int		soft_reboot :1;	/* soft reboot		*/
+	const struct tagtable *	tagtable;	/* tag table		*/
+	int			tagsize;	/* tag table size	*/
+	void			(*fixup)(struct machine_desc *,
+					 struct param_struct *, char **,
+					 struct meminfo *);
+	void			(*map_io)(void);/* IO mapping function	*/
+	void			(*init_irq)(void);
 };
 
 /*
@@ -50,7 +57,7 @@
 #define MACHINE_START(_type,_name)		\
 const struct machine_desc __mach_desc_##_type	\
  __attribute__((__section__(".arch.info"))) = {	\
-	nr:		MACH_TYPE_##_type##,	\
+	nr:		MACH_TYPE_##_type,	\
 	name:		_name,
 
 #define MAINTAINER(n)
@@ -68,10 +75,9 @@
 	video_end:	_end,
 
 #define DISABLE_PARPORT(_n)			\
-	reserve_lp##_n##:	1,
+	reserve_lp##_n:	1,
 
-#define BROKEN_HLT				\
-	broken_hlt:	1,
+#define BROKEN_HLT /* unused */
 
 #define SOFT_REBOOT				\
 	soft_reboot:	1,
@@ -81,6 +87,9 @@
 
 #define MAPIO(_func)				\
 	map_io:		_func,
+
+#define INITIRQ(_func)				\
+	init_irq:	_func,
 
 #define MACHINE_END				\
 };
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/mach/irq.h linux/include/asm-arm/mach/irq.h
--- v2.4.1/linux/include/asm-arm/mach/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-arm/mach/irq.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,41 @@
+/*
+ *  linux/include/asm-arm/mach/irq.h
+ *
+ *  Copyright (C) 1995-2000 Russell King.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_ARM_MACH_IRQ_H
+#define __ASM_ARM_MACH_IRQ_H
+
+struct irqdesc {
+	unsigned int	 nomask   : 1;		/* IRQ does not mask in IRQ   */
+	unsigned int	 enabled  : 1;		/* IRQ is currently enabled   */
+	unsigned int	 triggered: 1;		/* IRQ has occurred	      */
+	unsigned int	 probing  : 1;		/* IRQ in use for a probe     */
+	unsigned int	 probe_ok : 1;		/* IRQ can be used for probe  */
+	unsigned int	 valid    : 1;		/* IRQ claimable	      */
+	unsigned int	 noautoenable : 1;	/* don't automatically enable IRQ */
+	unsigned int	 unused   :25;
+	void (*mask_ack)(unsigned int irq);	/* Mask and acknowledge IRQ   */
+	void (*mask)(unsigned int irq);		/* Mask IRQ		      */
+	void (*unmask)(unsigned int irq);	/* Unmask IRQ		      */
+	struct irqaction *action;
+	/*
+	 * IRQ lock detection
+	 */
+	unsigned int	 lck_cnt;
+	unsigned int	 lck_pc;
+	unsigned int	 lck_jif;
+};
+
+extern struct irqdesc irq_desc[];
+
+extern void (*init_arch_irq)(void);
+extern int setup_arm_irq(int, struct irqaction *);
+extern int get_fiq_list(char *);
+extern void init_FIQ(void);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/proc-armo/pgtable.h linux/include/asm-arm/proc-armo/pgtable.h
--- v2.4.1/linux/include/asm-arm/proc-armo/pgtable.h	Mon Sep 18 15:15:24 2000
+++ linux/include/asm-arm/proc-armo/pgtable.h	Thu Feb  8 16:32:44 2001
@@ -96,4 +96,9 @@
 
 #define pte_alloc_kernel        pte_alloc
 
+/*
+ * We don't store cache state bits in the page table here.
+ */
+#define pgprot_noncached(prot)	(prot)
+
 #endif /* __ASM_PROC_PGTABLE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/proc-armv/pgtable.h linux/include/asm-arm/proc-armv/pgtable.h
--- v2.4.1/linux/include/asm-arm/proc-armv/pgtable.h	Mon Sep 18 15:15:24 2000
+++ linux/include/asm-arm/proc-armv/pgtable.h	Thu Feb  8 16:32:44 2001
@@ -149,7 +149,7 @@
 #define pte_young(pte)			(pte_val(pte) & L_PTE_YOUNG)
 
 #define PTE_BIT_FUNC(fn,op)			\
-extern inline pte_t pte_##fn##(pte_t pte) { pte_val(pte) op##; return pte; }
+extern inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
 
 /*PTE_BIT_FUNC(rdprotect, &= ~L_PTE_USER);*/
 /*PTE_BIT_FUNC(mkread,    |= L_PTE_USER);*/
@@ -162,5 +162,10 @@
 PTE_BIT_FUNC(mkold,     &= ~L_PTE_YOUNG);
 PTE_BIT_FUNC(mkyoung,   |= L_PTE_YOUNG);
 PTE_BIT_FUNC(nocache,   &= ~L_PTE_CACHEABLE);
+
+/*
+ * Mark the prot value as uncacheable and unbufferable.
+ */
+#define pgprot_noncached(prot)	__pgprot(pgprot_val(prot) & ~(L_PTE_CACHEABLE | L_PTE_BUFFERABLE))
 
 #endif /* __ASM_PROC_PGTABLE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/setup.h linux/include/asm-arm/setup.h
--- v2.4.1/linux/include/asm-arm/setup.h	Mon Sep 18 15:15:24 2000
+++ linux/include/asm-arm/setup.h	Thu Feb  8 16:32:44 2001
@@ -68,6 +68,143 @@
 };
 
 /*
+ * New idea - a list of tagged entries
+ */
+#define ATAG_NONE	0x00000000
+
+struct tag_header {
+	u32 size;
+	u32 tag;
+};
+
+#define ATAG_CORE	0x54410001
+
+struct tag_core {
+	u32 flags;		/* bit 0 = read-only */
+	u32 pagesize;
+	u32 rootdev;
+};
+
+#define ATAG_MEM		0x54410002
+
+struct tag_mem32 {
+	u32	size;
+	u32	start;
+};
+
+#define ATAG_VIDEOTEXT	0x54410003
+
+struct tag_videotext {
+	u8		x;
+	u8		y;
+	u16		video_page;
+	u8		video_mode;
+	u8		video_cols;
+	u16		video_ega_bx;
+	u8		video_lines;
+	u8		video_isvga;
+	u16		video_points;
+};
+
+#define ATAG_RAMDISK	0x54410004
+
+struct tag_ramdisk {
+	u32 flags;		/* b0 = load, b1 = prompt */
+	u32 size;
+	u32 start;
+};
+
+#define ATAG_INITRD	0x54410005
+
+struct tag_initrd {
+	u32 start;
+	u32 size;
+};
+
+#define ATAG_SERIAL	0x54410006
+
+struct tag_serialnr {
+	u32 low;
+	u32 high;
+};
+
+#define ATAG_REVISION	0x54410007
+
+struct tag_revision {
+	u32 rev;
+};
+
+#define ATAG_VIDEOLFB	0x54410008
+
+struct tag_videolfb {
+	u16		lfb_width;
+	u16		lfb_height;
+	u16		lfb_depth;
+	u16		lfb_linelength;
+	u32		lfb_base;
+	u32		lfb_size;
+	u8		red_size;
+	u8		red_pos;
+	u8		green_size;
+	u8		green_pos;
+	u8		blue_size;
+	u8		blue_pos;
+	u8		rsvd_size;
+	u8		rsvd_pos;
+};
+
+#define ATAG_CMDLINE	0x54410009
+
+struct tag_cmdline {
+	char	cmdline[1];
+};
+
+#define ATAG_ACORN	0x41000101
+
+struct tag_acorn {
+	u32 memc_control_reg;
+	u32 vram_pages;
+	u8 sounddefault;
+	u8 adfsdrives;
+};
+
+#define ATAG_MEMCLK	0x41000402
+
+struct tag_memclk {
+	u32 fmemclk;
+};
+
+struct tag {
+	struct tag_header hdr;
+	union {
+		struct tag_core		core;
+		struct tag_mem32	mem;
+		struct tag_videotext	videotext;
+		struct tag_ramdisk	ramdisk;
+		struct tag_initrd	initrd;
+		struct tag_serialnr	serialnr;
+		struct tag_revision	revision;
+		struct tag_videolfb	videolfb;
+		struct tag_cmdline	cmdline;
+
+		/*
+		 * Acorn specific
+		 */
+		struct tag_acorn	acorn;
+
+		/*
+		 * DC21285 specific
+		 */
+		struct tag_memclk	memclk;
+	} u;
+};
+
+struct tagtable {
+	u32 tag;
+	int (*parse)(const struct tag *);
+};
+
+/*
  * Memory map description
  */
 #define NR_BANKS 4
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/socket.h linux/include/asm-arm/socket.h
--- v2.4.1/linux/include/asm-arm/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-arm/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-arm/termios.h linux/include/asm-arm/termios.h
--- v2.4.1/linux/include/asm-arm/termios.h	Sun Aug 13 09:54:15 2000
+++ linux/include/asm-arm/termios.h	Sat Feb  3 20:00:45 2001
@@ -61,7 +61,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/a.out.h linux/include/asm-cris/a.out.h
--- v2.4.1/linux/include/asm-cris/a.out.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/a.out.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,31 @@
+#ifndef __CRIS_A_OUT_H__
+#define __CRIS_A_OUT_H__
+
+/* we don't support a.out binaries on Linux/CRIS anyway, so this is
+ * not really used but still needed because binfmt_elf.c for some reason
+ * wants to know about a.out even if there is no interpreter available...
+ */
+
+/* grabbed from the intel stuff  */   
+#define STACK_TOP TASK_SIZE
+
+
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+};
+
+
+#define N_TRSIZE(a)	((a).a_trsize)
+#define N_DRSIZE(a)	((a).a_drsize)
+#define N_SYMSIZE(a)	((a).a_syms)
+
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/atomic.h linux/include/asm-cris/atomic.h
--- v2.4.1/linux/include/asm-cris/atomic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/atomic.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,142 @@
+/* $Id: atomic.h,v 1.2 2000/07/13 16:51:57 bjornw Exp $ */
+
+#ifndef __ASM_CRIS_ATOMIC__
+#define __ASM_CRIS_ATOMIC__
+
+#include <asm/system.h>
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ */
+
+/*
+ * Make sure gcc doesn't try to be clever and move things around
+ * on us. We need to use _exactly_ the address the user gave us,
+ * not some alias that contains the same information.
+ */
+
+#define __atomic_fool_gcc(x) (*(struct { int a[100]; } *)x)
+
+typedef struct { int counter; } atomic_t;
+
+#define ATOMIC_INIT(i)  { (i) }
+
+#define atomic_read(v) ((v)->counter)
+#define atomic_set(v,i) (((v)->counter) = (i))
+
+/* These should be written in asm but we do it in C for now. */
+
+static __inline__ void atomic_add(int i, volatile atomic_t *v)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	v->counter += i;
+	restore_flags(flags);
+}
+
+static __inline__ void atomic_sub(int i, volatile atomic_t *v)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	v->counter -= i;
+	restore_flags(flags);
+}
+
+static __inline__ int atomic_add_return(int i, volatile atomic_t *v)
+{
+	unsigned long flags;
+	int retval;
+	save_flags(flags);
+	cli();
+	retval = (v->counter += i);
+	restore_flags(flags);
+	return retval;
+}
+
+static __inline__ int atomic_sub_return(int i, volatile atomic_t *v)
+{
+	unsigned long flags;
+	int retval;
+	save_flags(flags);
+	cli();
+	retval = (v->counter -= i);
+	restore_flags(flags);
+	return retval;
+}
+
+static __inline__ int atomic_sub_and_test(int i, volatile atomic_t *v)
+{
+	int retval;
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	retval = (v->counter -= i) == 0;
+	restore_flags(flags);
+	return retval;
+}
+
+static __inline__ void atomic_inc(volatile atomic_t *v)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	(v->counter)++;
+	restore_flags(flags);
+}
+
+static __inline__ void atomic_dec(volatile atomic_t *v)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	(v->counter)--;
+	restore_flags(flags);
+}
+
+static __inline__ int atomic_inc_return(volatile atomic_t *v)
+{
+	unsigned long flags;
+	int retval;
+	save_flags(flags);
+	cli();
+	retval = (v->counter)++;
+	restore_flags(flags);
+	return retval;
+}
+
+static __inline__ int atomic_dec_return(volatile atomic_t *v)
+{
+	unsigned long flags;
+	int retval;
+	save_flags(flags);
+	cli();
+	retval = (v->counter)--;
+	restore_flags(flags);
+	return retval;
+}
+static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+{
+	int retval;
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	retval = --(v->counter) == 0;
+	restore_flags(flags);
+	return retval;
+}
+
+static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
+{
+	int retval;
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	retval = ++(v->counter) == 0;
+	restore_flags(flags);
+	return retval;
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/axisflashmap.h linux/include/asm-cris/axisflashmap.h
--- v2.4.1/linux/include/asm-cris/axisflashmap.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/axisflashmap.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,59 @@
+#ifndef __ASM_AXISFLASHMAP_H
+#define __ASM_AXISFLASHMAP_H
+
+/* Bootblock parameters are stored at 0xc000 and has the FLASH_BOOT_MAGIC 
+ * as start, it ends with 0xFFFFFFFF */
+#define FLASH_BOOT_MAGIC 0xbeefcace
+#define BOOTPARAM_OFFSET 0xc000
+/* apps/bootblocktool is used to read and write the parameters,
+ * and it has nothing to do with the partition table. 
+ */
+
+
+/* the partitiontable consists of some "jump over" code, a head and
+ * then the actual entries.
+ * tools/mkptable is used to generate the ptable. 
+ */
+
+/* The partition table start with kod to "jump over" it: */
+#define PARTITIONTABLE_CODE_START { \
+ 0x0f, 0x05, /* nop 0 */\
+ 0x25, 0xf0, /* di  2 */\
+ 0xed, 0xff  /* ba  4 */ }
+
+/* The actual offset depend on the number of entries */
+#define PARTITIONTABLE_CODE_END { \
+ 0x00, 0x00, /* ba offset 6 */\
+ 0x0f, 0x0f  /* nop 8 */}
+
+#define PARTITION_TABLE_OFFSET 10
+#define PARTITION_TABLE_MAGIC 0xbeef /* Not a good magic */
+
+/* The partitiontable_head is located at offset +10: */
+struct partitiontable_head {
+	__u16 magic; /* PARTITION_TABLE_MAGIC */ 
+	__u16 size;  /* Length of ptable block (not header) */
+	__u32 checksum; /* simple longword sum */
+};
+
+/* And followed by partition table entries */
+struct partitiontable_entry {
+	__u32 offset;   /* Offset is relative to the sector the ptable is in */
+	__u32 size;
+	__u32 checksum; /* simple longword sum */
+	__u16 type;
+	__u16 flags;   /* bit 0: ro/rw = 1/0 */
+	__u32 future0; /* 16 bytes reserved for future use */
+	__u32 future1;
+	__u32 future2;
+	__u32 future3;
+};
+/* ended by an end marker: */
+#define PARTITIONTABLE_END_MARKER 0xFFFFFFFF
+
+/*#define PARTITION_TYPE_RESCUE 0x0000?*/  /* Not used, maybe it should? */
+#define PARTITION_TYPE_PARAM  0x0001 /* Hmm.. */
+#define PARTITION_TYPE_KERNEL 0x0002
+#define PARTITION_TYPE_JFFS   0x0003
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/bitops.h linux/include/asm-cris/bitops.h
--- v2.4.1/linux/include/asm-cris/bitops.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/bitops.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,184 @@
+/* $Id: bitops.h,v 1.3 2000/10/17 14:56:27 bjornw Exp $ */
+/* all of these should probably be rewritten in assembler for speed. */
+
+#ifndef _CRIS_BITOPS_H
+#define _CRIS_BITOPS_H
+
+#include <asm/system.h>
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+/*
+ * Some hacks to defeat gcc over-optimizations..
+ */
+struct __dummy { unsigned long a[100]; };
+#define ADDR (*(struct __dummy *) addr)
+#define CONST_ADDR (*(const struct __dummy *) addr)
+
+#define set_bit(nr, addr)    (void)test_and_set_bit(nr, addr)
+#define clear_bit(nr, addr)  (void)test_and_clear_bit(nr, addr)
+#define change_bit(nr, addr) (void)test_and_change_bit(nr, addr)
+
+extern __inline__ int test_and_set_bit(int nr, void *addr)
+{
+	unsigned int mask, retval;
+	unsigned long flags;
+	unsigned int *adr = (unsigned int *)addr;
+	
+	adr += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	retval = (mask & *adr) != 0;
+	*adr |= mask;
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * clear_bit() doesn't provide any barrier for the compiler.
+ */
+#define smp_mb__before_clear_bit()      barrier()
+#define smp_mb__after_clear_bit()       barrier()
+
+extern __inline__ int test_and_clear_bit(int nr, void *addr)
+{
+	unsigned int mask, retval;
+	unsigned long flags;
+	unsigned int *adr = (unsigned int *)addr;
+	
+	adr += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	retval = (mask & *adr) != 0;
+	*adr &= ~mask;
+	restore_flags(flags);
+	return retval;
+}
+
+extern __inline__ int test_and_change_bit(int nr, void *addr)
+{
+	unsigned int mask, retval;
+	unsigned long flags;
+	unsigned int *adr = (unsigned int *)addr;
+	adr += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	save_flags(flags);
+	cli();
+	retval = (mask & *adr) != 0;
+	*adr ^= mask;
+	restore_flags(flags);
+	return retval;
+}
+
+/*
+ * This routine doesn't need to be atomic.
+ */
+extern __inline__ int test_bit(int nr, const void *addr)
+{
+	unsigned int mask;
+	unsigned int *adr = (unsigned int *)addr;
+	
+	adr += nr >> 5;
+	mask = 1 << (nr & 0x1f);
+	return ((mask & *adr) != 0);
+}
+
+/*
+ * Find-bit routines..
+ */
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+extern __inline__ unsigned long ffz(unsigned long word)
+{
+	unsigned long result = 0;
+	
+	while(word & 1) {
+		result++;
+		word >>= 1;
+	}
+	return result;
+}
+
+/*
+ * Find first one in word. Undefined if no one exists,
+ * so code should check against 0UL first..
+ */
+extern __inline__ unsigned long find_first_one(unsigned long word)
+{
+	unsigned long result = 0;
+	
+	while(!(word & 1)) {
+		result++;
+		word >>= 1;
+	}
+	return result;
+}
+
+extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+{
+	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
+	unsigned long result = offset & ~31UL;
+	unsigned long tmp;
+	
+	if (offset >= size)
+		return size;
+	size -= result;
+	offset &= 31UL;
+	if (offset) {
+		tmp = *(p++);
+		tmp |= ~0UL >> (32-offset);
+		if (size < 32)
+			goto found_first;
+		if (~tmp)
+			goto found_middle;
+		size -= 32;
+		result += 32;
+	}
+	while (size & ~31UL) {
+		if (~(tmp = *(p++)))
+			goto found_middle;
+		result += 32;
+		size -= 32;
+	}
+	if (!size)
+		return result;
+	tmp = *p;
+	
+ found_first:
+	tmp |= ~0UL >> size;
+ found_middle:
+	return result + ffz(tmp);
+}
+
+#define find_first_zero_bit(addr, size) \
+        find_next_zero_bit((addr), (size), 0)
+
+#ifdef __KERNEL__ 
+
+#define ext2_set_bit                 test_and_set_bit
+#define ext2_clear_bit               test_and_clear_bit
+#define ext2_test_bit                test_bit
+#define ext2_find_first_zero_bit     find_first_zero_bit
+#define ext2_find_next_zero_bit      find_next_zero_bit
+
+/* Bitmap functions for the minix filesystem.  */
+#define minix_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+
+#endif /* _CRIS_BITOPS_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/bugs.h linux/include/asm-cris/bugs.h
--- v2.4.1/linux/include/asm-cris/bugs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/bugs.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,21 @@
+/* $Id: bugs.h,v 1.2 2001/01/17 17:03:18 bjornw Exp $
+ *
+ *  include/asm-cris/bugs.h
+ *
+ *  Copyright (C) 2001 Axis Communications AB
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *	void check_bugs(void);
+ */
+
+static void check_bugs(void)
+{
+}
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/byteorder.h linux/include/asm-cris/byteorder.h
--- v2.4.1/linux/include/asm-cris/byteorder.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/byteorder.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,47 @@
+/* $Id: byteorder.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef _CRIS_BYTEORDER_H
+#define _CRIS_BYTEORDER_H
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+/* we just define these two (as we can do the swap in a single
+ * asm instruction in CRIS) and the arch-independent files will put
+ * them together into ntohl etc.
+ */
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+	__asm__ ("swapwb %0" : "=r" (x) : "0" (x));
+  
+	return(x);
+}
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+	__asm__ ("swapb %0" : "=r" (x) : "0" (x));
+	
+	return(x);
+}
+
+/* defines are necessary because the other files detect the presence
+ * of a defined __arch_swab32, not an inline
+ */
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+#  define __BYTEORDER_HAS_U64__
+#  define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __GNUC__ */
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/cache.h linux/include/asm-cris/cache.h
--- v2.4.1/linux/include/asm-cris/cache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/cache.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,10 @@
+#ifndef _ASM_CACHE_H
+#define _ASM_CACHE_H
+
+/* Etrax 100LX have 32-byte cache-lines. When we add support for future chips
+ * here should be a check for CPU type.
+ */
+
+#define L1_CACHE_BYTES 32
+
+#endif /* _ASM_CACHE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/checksum.h linux/include/asm-cris/checksum.h
--- v2.4.1/linux/include/asm-cris/checksum.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/checksum.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,119 @@
+/* $Id: checksum.h,v 1.3 2000/11/15 17:35:16 bjornw Exp $ */
+/* TODO: csum_tcpudp_magic could be speeded up, and csum_fold as well */
+
+#ifndef _CRIS_CHECKSUM_H
+#define _CRIS_CHECKSUM_H
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+unsigned int csum_partial_copy_nocheck(const char *src, char *dst,
+				       int len, unsigned int sum);
+
+/*
+ *	Fold a partial checksum into a word
+ */
+
+static inline unsigned int csum_fold(unsigned int sum)
+{
+	/* the while loop is unnecessary really, it's always enough with two
+	   iterations */
+	
+	while(sum >> 16)
+		sum = (sum & 0xffff) + (sum >> 16); /* add in end-around carry */
+	
+	return ~sum;
+}
+
+/* Checksum some values used in TCP/UDP headers.
+ *
+ * The gain by doing this in asm is that C will not generate carry-additions
+ * for the 32-bit components of the checksum, so otherwise we would have had
+ * to split all of those into 16-bit components, then add.
+ */
+
+static inline unsigned int
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr, unsigned short len,
+		   unsigned short proto, unsigned int sum)
+{
+	int res;
+	__asm__ ("add.d %2, %0\n\t"
+		 "ax\n\t"
+		 "add.d %3, %0\n\t"
+		 "ax\n\t"
+		 "add.d %4, %0\n\t"
+		 "ax\n\t"
+		 "addq 0, %0\n"
+	: "=r" (res)
+	: "0" (sum), "r" (daddr), "r" (saddr), "r" ((ntohs(len) << 16) + (proto << 8)));
+
+	return res;
+}	
+
+
+/* TODO we need to write this properly to handle userland VM exceptions!! */
+
+#define csum_partial_copy_from_user(a,b,c,d,errptr) csum_partial_copy_nocheck(a,b,c,d)
+
+#if 0
+unsigned int csum_partial_copy_from_user(const char *src, char *dst,
+					int len, unsigned int sum);
+#endif
+
+
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ */
+
+static inline unsigned short ip_fast_csum(unsigned char * iph,
+					  unsigned int ihl)
+{
+	return csum_fold(csum_partial(iph, ihl * 4, 0));
+}
+ 
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+
+static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
+						   unsigned long daddr,
+						   unsigned short len,
+						   unsigned short proto,
+						   unsigned int sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
+	return csum_fold (csum_partial(buff, len, 0));
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/current.h linux/include/asm-cris/current.h
--- v2.4.1/linux/include/asm-cris/current.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/current.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,15 @@
+#ifndef _CRIS_CURRENT_H
+#define _CRIS_CURRENT_H
+
+struct task_struct;
+
+static inline struct task_struct * get_current(void)
+{
+        struct task_struct *current;
+        __asm__("and.d sp,%0; ":"=r" (current) : "0" (~8191UL));
+        return current;
+ }
+ 
+#define current get_current()
+
+#endif /* !(_CRIS_CURRENT_H) */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/delay.h linux/include/asm-cris/delay.h
--- v2.4.1/linux/include/asm-cris/delay.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/delay.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,67 @@
+/* $Id: delay.h,v 1.2 2000/08/08 16:36:41 bjornw Exp $ */
+
+#ifndef _CRIS_DELAY_H
+#define _CRIS_DELAY_H
+
+/*
+ * Copyright (C) 1998, 1999, 2000 Axis Communications AB
+ *
+ * Delay routines, using a pre-computed "loops_per_second" value.
+ */
+
+#include <linux/config.h>
+#include <linux/linkage.h>
+
+#ifdef CONFIG_SMP
+#include <asm/smp.h>
+#endif 
+
+extern void __do_delay(void);	/* Special register call calling convention */
+
+extern __inline__ void __delay(int loops)
+{
+	/* need to be a great deal of nops, because Etrax shuts off IRQ's during a branch
+	   and we depend on the irq's to measure the time! */
+	
+	__asm__ __volatile__ (
+			      "move.d %0,r0\n"
+			      "1:\n\t"
+			      "nop\n\t"
+			      "nop\n\t"
+			      "nop\n\t"
+			      "nop\n\t"
+			      "nop\n\t"
+			      "nop\n\t"
+			      "nop\n\t"
+			      "subq 1,r0\n\t"
+			      "bne 1b\n\t"
+			      "nop\n\t"
+			      : : "r" (loops) : "r0", "cc");
+}
+
+
+/*
+ * Use only for very small delays ( < 1 msec).  Should probably use a
+ * lookup table, really, as the multiplications take much too long with
+ * short delays.  This is a "reasonable" implementation, though (and the
+ * first constant multiplications gets optimized away if the delay is
+ * a constant)
+ */
+
+extern unsigned long loops_per_usec; /* arch/cris/mm/init.c */
+
+extern __inline__ void udelay(unsigned long usecs)
+{
+	__delay(usecs * loops_per_usec);
+}
+
+extern __inline__ unsigned long muldiv(unsigned long a, unsigned long b, unsigned long c)
+{
+	printk("muldiv called!\n");
+	return 0;
+}
+
+#endif /* defined(_ETRAX_DELAY_H) */
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/div64.h linux/include/asm-cris/div64.h
--- v2.4.1/linux/include/asm-cris/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/div64.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,16 @@
+#ifndef __ASM_CRIS_DIV64
+#define __ASM_CRIS_DIV64
+
+/* copy from asm-arm */
+
+/* We're not 64-bit, but... */
+#define do_div(n,base)						\
+({								\
+	int __res;						\
+	__res = ((unsigned long)n) % (unsigned int)base;	\
+	n = ((unsigned long)n) / (unsigned int)base;		\
+	__res;							\
+})
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/dma.h linux/include/asm-cris/dma.h
--- v2.4.1/linux/include/asm-cris/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/dma.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,21 @@
+/* $Id: dma.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $
+ * linux/include/asm/dma.h: Defines for using and allocating dma channels.
+ */
+
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+/* it's useless on the Etrax, but unfortunately needed by the new
+   bootmem allocator (but this should do it for this) */
+
+#define MAX_DMA_ADDRESS PAGE_OFFSET
+
+/* TODO: check nbr of channels on Etrax-100LX */
+
+#define MAX_DMA_CHANNELS	10
+
+/* These are in kernel/dma.c: */
+extern int request_dma(unsigned int dmanr, const char * device_id); /* reserve a DMA channel */
+extern void free_dma(unsigned int dmanr);	                    /* release it */
+
+#endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/elf.h linux/include/asm-cris/elf.h
--- v2.4.1/linux/include/asm-cris/elf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/elf.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,68 @@
+#ifndef __ASMCRIS_ELF_H
+#define __ASMCRIS_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+
+typedef unsigned long elf_greg_t;
+
+/* These probably need fixing.  */
+#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* A placeholder; CRIS does not have any fp regs.  */
+typedef unsigned long elf_fpregset_t;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) ( (x)->e_machine == EM_CRIS )
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB;
+#define ELF_ARCH	EM_CRIS
+
+	/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
+	   starts (a register; assume first param register for CRIS)
+	   contains a pointer to a function which might be
+	   registered using `atexit'.  This provides a mean for the
+	   dynamic linker to call DT_FINI functions for shared libraries
+	   that have been loaded before the code runs.
+
+	   A value of 0 tells we have no such handler.  */
+#define ELF_PLAT_INIT(_r)	((_r)->r10 = 0)
+
+#undef USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	8192
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this CPU supports.  This could be done in user space,
+   but it's not easy, and we've already done it here.  */
+
+#define ELF_HWCAP       (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.
+*/
+
+#define ELF_PLATFORM  (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/errno.h linux/include/asm-cris/errno.h
--- v2.4.1/linux/include/asm-cris/errno.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/errno.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,134 @@
+/* verbatim copy of asm-i386/errno.h */
+
+#ifndef _CRIS_ERRNO_H
+#define _CRIS_ERRNO_H
+
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EDEADLK		35	/* Resource deadlock would occur */
+#define	ENAMETOOLONG	36	/* File name too long */
+#define	ENOLCK		37	/* No record locks available */
+#define	ENOSYS		38	/* Function not implemented */
+#define	ENOTEMPTY	39	/* Directory not empty */
+#define	ELOOP		40	/* Too many symbolic links encountered */
+#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
+#define	ENOMSG		42	/* No message of desired type */
+#define	EIDRM		43	/* Identifier removed */
+#define	ECHRNG		44	/* Channel number out of range */
+#define	EL2NSYNC	45	/* Level 2 not synchronized */
+#define	EL3HLT		46	/* Level 3 halted */
+#define	EL3RST		47	/* Level 3 reset */
+#define	ELNRNG		48	/* Link number out of range */
+#define	EUNATCH		49	/* Protocol driver not attached */
+#define	ENOCSI		50	/* No CSI structure available */
+#define	EL2HLT		51	/* Level 2 halted */
+#define	EBADE		52	/* Invalid exchange */
+#define	EBADR		53	/* Invalid request descriptor */
+#define	EXFULL		54	/* Exchange full */
+#define	ENOANO		55	/* No anode */
+#define	EBADRQC		56	/* Invalid request code */
+#define	EBADSLT		57	/* Invalid slot */
+
+#define	EDEADLOCK	EDEADLK
+
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EMULTIHOP	72	/* Multihop attempted */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EBADMSG		74	/* Not a data message */
+#define	EOVERFLOW	75	/* Value too large for defined data type */
+#define	ENOTUNIQ	76	/* Name not unique on network */
+#define	EBADFD		77	/* File descriptor in bad state */
+#define	EREMCHG		78	/* Remote address changed */
+#define	ELIBACC		79	/* Can not access a needed shared library */
+#define	ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	EILSEQ		84	/* Illegal byte sequence */
+#define	ERESTART	85	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	86	/* Streams pipe error */
+#define	EUSERS		87	/* Too many users */
+#define	ENOTSOCK	88	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	89	/* Destination address required */
+#define	EMSGSIZE	90	/* Message too long */
+#define	EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	92	/* Protocol not available */
+#define	EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	EADDRINUSE	98	/* Address already in use */
+#define	EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	ENETDOWN	100	/* Network is down */
+#define	ENETUNREACH	101	/* Network is unreachable */
+#define	ENETRESET	102	/* Network dropped connection because of reset */
+#define	ECONNABORTED	103	/* Software caused connection abort */
+#define	ECONNRESET	104	/* Connection reset by peer */
+#define	ENOBUFS		105	/* No buffer space available */
+#define	EISCONN		106	/* Transport endpoint is already connected */
+#define	ENOTCONN	107	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	ETIMEDOUT	110	/* Connection timed out */
+#define	ECONNREFUSED	111	/* Connection refused */
+#define	EHOSTDOWN	112	/* Host is down */
+#define	EHOSTUNREACH	113	/* No route to host */
+#define	EALREADY	114	/* Operation already in progress */
+#define	EINPROGRESS	115	/* Operation now in progress */
+#define	ESTALE		116	/* Stale NFS file handle */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+#define	EDQUOT		122	/* Quota exceeded */
+
+#define	ENOMEDIUM	123	/* No medium found */
+#define	EMEDIUMTYPE	124	/* Wrong medium type */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/eshlibld.h linux/include/asm-cris/eshlibld.h
--- v2.4.1/linux/include/asm-cris/eshlibld.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/eshlibld.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,114 @@
+/*!**************************************************************************
+*!
+*! FILE NAME  : eshlibld.h
+*!
+*! DESCRIPTION: Prototypes for exported shared library functions
+*!
+*! FUNCTIONS  : perform_cris_aout_relocations, shlibmod_fork, shlibmod_exit
+*! (EXPORTED)
+*!
+*!---------------------------------------------------------------------------
+*!
+*! (C) Copyright 1998, 1999 Axis Communications AB, LUND, SWEDEN
+*!
+*!**************************************************************************/
+/* $Id: eshlibld.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef _cris_relocate_h
+#define _cris_relocate_h
+
+/* Please note that this file is also compiled into the xsim simulator.
+   Try to avoid breaking its double use (only works on a little-endian
+   32-bit machine such as the i386 anyway).
+
+   Use __KERNEL__ when you're about to use kernel functions,
+       (which you should not do here anyway, since this file is
+       used by glibc).
+   Use defined(__KERNEL__) || defined(__elinux__) when doing
+       things that only makes sense on an elinux system.
+   Use __CRIS__ when you're about to do (really) CRIS-specific code.
+*/
+
+/* We have dependencies all over the place for the host system
+   for xsim being a linux system, so let's not pretend anything
+   else with #ifdef:s here until fixed.  */
+#include <linux/config.h>
+#include <linux/limits.h>
+
+/* Maybe do sanity checking if file input. */
+#undef SANITYCHECK_RELOC
+
+/* Maybe output debug messages. */
+#undef RELOC_DEBUG
+
+/* Maybe we want to share core as well as disk space.
+   Mainly depends on the config macro CONFIG_SHARE_SHLIB_CORE, but it is
+   assumed that we want to share code when debugging (exposes more
+   trouble). */
+#ifndef SHARE_LIB_CORE
+# if (defined(__KERNEL__) || !defined(RELOC_DEBUG)) \
+     && !defined(CONFIG_SHARE_SHLIB_CORE)
+#  define SHARE_LIB_CORE 0
+# else
+#  define SHARE_LIB_CORE 1
+# endif /* __KERNEL__ etc */
+#endif /* SHARE_LIB_CORE */
+
+
+/* Main exported function; supposed to be called when the program a.out
+   has been read in. */
+extern int
+perform_cris_aout_relocations(unsigned long text, unsigned long tlength,
+			      unsigned long data, unsigned long dlength,
+			      unsigned long baddr, unsigned long blength,
+
+			      /* These may be zero when there's "perfect"
+				 position-independent code. */
+			      unsigned char *trel, unsigned long tsrel,
+			      unsigned long dsrel,
+
+			      /* These will be zero at a first try, to see
+				 if code is statically linked.  Else a
+				 second try, with the symbol table and
+				 string table nonzero should be done. */
+			      unsigned char *symbols, unsigned long symlength,
+			      unsigned char *strings, unsigned long stringlength,
+
+			      /* These will only be used when symbol table
+			       information is present. */
+			      char **env, int envc,
+			      int euid, int is_suid);
+
+
+#ifdef RELOC_DEBUG
+/* Task-specific debug stuff. */
+struct task_reloc_debug {
+	struct memdebug *alloclast;
+	unsigned long alloc_total;
+	unsigned long export_total;
+};
+#endif /* RELOC_DEBUG */
+
+#if SHARE_LIB_CORE
+
+/* When code (and some very specific data) is shared and not just
+   dynamically linked, we need to export hooks for exec beginning and
+   end. */
+
+struct shlibdep;
+
+extern void
+shlibmod_exit(struct shlibdep **deps);
+
+/* Returns 0 if failure, nonzero for ok. */
+extern int
+shlibmod_fork(struct shlibdep **deps);
+
+#else  /* ! SHARE_LIB_CORE */
+# define shlibmod_exit(x)
+# define shlibmod_fork(x) 1
+#endif /* ! SHARE_LIB_CORE */
+
+#endif _cris_relocate_h
+/********************** END OF FILE eshlibld.h *****************************/
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/fcntl.h linux/include/asm-cris/fcntl.h
--- v2.4.1/linux/include/asm-cris/fcntl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/fcntl.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,89 @@
+#ifndef _CRIS_FCNTL_H
+#define _CRIS_FCNTL_H
+
+/* verbatim copy of i386 version */
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	 040000	/* direct disk access hint - currently ignored */
+#define O_LARGEFILE	0100000
+#define O_DIRECTORY	0200000	/* must be a directory */
+#define O_NOFOLLOW	0400000 /* don't follow links */
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get f_flags */
+#define F_SETFD		2	/* set f_flags */
+#define F_GETFL		3	/* more flags (cloexec) */
+#define F_SETFL		4
+#define F_GETLK		5
+#define F_SETLK		6
+#define F_SETLKW	7
+
+#define F_SETOWN	8	/*  for sockets. */
+#define F_GETOWN	9	/*  for sockets. */
+#define F_SETSIG	10	/*  for sockets. */
+#define F_GETSIG	11	/*  for sockets. */
+
+#define F_GETLK64      12      /*  using 'struct flock64' */
+#define F_SETLK64      13
+#define F_SETLKW64     14
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* for leases */
+#define F_INPROGRESS   16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#define LOCK_MAND      32      /* This is a mandatory flock */
+#define LOCK_READ      64      /* ... Which allows concurrent read operations */
+#define LOCK_WRITE     128     /* ... Which allows concurrent write operations */
+#define LOCK_RW        192     /* ... Which allows concurrent read & write ops */
+
+struct flock {
+	short l_type;
+	short l_whence;
+	off_t l_start;
+	off_t l_len;
+	pid_t l_pid;
+};
+
+struct flock64 {
+	short  l_type;
+	short  l_whence;
+	loff_t l_start;
+	loff_t l_len;
+	pid_t  l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE  1024
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/hardirq.h linux/include/asm-cris/hardirq.h
--- v2.4.1/linux/include/asm-cris/hardirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/hardirq.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,35 @@
+#ifndef __ASM_HARDIRQ_H
+#define __ASM_HARDIRQ_H
+
+/* only non-SMP supported */
+
+#include <linux/threads.h>
+
+/* entry.S is sensitive to the offsets of these fields */
+typedef struct {
+	unsigned int __softirq_active;
+	unsigned int __softirq_mask;
+	unsigned int __local_irq_count;
+	unsigned int __local_bh_count;
+	unsigned int __syscall_count;
+} ____cacheline_aligned irq_cpustat_t;
+
+#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
+
+/*
+ * Are we in an interrupt context? Either doing bottom half
+ * or hardware interrupt processing?
+ */
+#define in_interrupt()  ((local_irq_count(smp_processor_id()) + \
+			  local_bh_count(smp_processor_id())) != 0)
+#define in_irq()        (local_irq_count(smp_processor_id()) != 0)
+
+#define hardirq_trylock(cpu)    (local_irq_count(cpu) == 0)
+#define hardirq_endlock(cpu)    do { (void)(cpu); } while (0)
+
+#define irq_enter(cpu)      (local_irq_count(cpu)++)
+#define irq_exit(cpu)       (local_irq_count(cpu)--)
+
+#define synchronize_irq()       barrier()
+
+#endif /* __ASM_HARDIRQ_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/hdreg.h linux/include/asm-cris/hdreg.h
--- v2.4.1/linux/include/asm-cris/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/hdreg.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,11 @@
+/*
+ *  linux/include/asm-cris/hdreg.h
+ *
+ */
+
+#ifndef __ASMCRIS_HDREG_H
+#define __ASMCRIS_HDREG_H
+
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __ASMCRIS_HDREG_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ide.h linux/include/asm-cris/ide.h
--- v2.4.1/linux/include/asm-cris/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ide.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,142 @@
+/*
+ *  linux/include/asm-cris/ide.h
+ *
+ *  Copyright (C) 2000  Axis Communications AB
+ *
+ *  Authors:    Bjorn Wesen
+ *
+ */
+
+/*
+ *  This file contains the ETRAX 100LX specific IDE code.
+ */
+
+#ifndef __ASMCRIS_IDE_H
+#define __ASMCRIS_IDE_H
+
+#ifdef __KERNEL__
+
+#include <asm/svinto.h>
+
+/* ETRAX 100 can support 4 IDE busses on the same pins (serialized) */
+
+#define MAX_HWIFS	4
+
+#define ide__sti()	__sti()
+
+static __inline__ int ide_default_irq(ide_ioreg_t base)
+{
+	/* all IDE busses share the same IRQ, number 4.
+	 * this has the side-effect that ide-probe.c will cluster our 4 interfaces
+	 * together in a hwgroup, and will serialize accesses. this is good, because
+	 * we can't access more than one interface at the same time on ETRAX100.
+	 */
+	return 4; 
+}
+
+static __inline__ ide_ioreg_t ide_default_io_base(int index)
+{
+	/* we have no real I/O base address per interface, since all go through the
+	 * same register. but in a bitfield in that register, we have the i/f number.
+	 * so we can use the io_base to remember that bitfield.
+	 */
+	static const unsigned long io_bases[MAX_HWIFS] = {
+		IO_FIELD(R_ATA_CTRL_DATA, sel, 0),
+		IO_FIELD(R_ATA_CTRL_DATA, sel, 1),
+		IO_FIELD(R_ATA_CTRL_DATA, sel, 2),
+		IO_FIELD(R_ATA_CTRL_DATA, sel, 3)
+	};
+	return io_bases[index];
+}
+
+/* this is called once for each interface, to setup the port addresses. data_port is the result
+ * of the ide_default_io_base call above. ctrl_port will be 0, but that is don't care for us.
+ */
+
+static __inline__ void ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq)
+{
+	int i;
+
+	/* fill in ports for ATA addresses 0 to 7 */
+
+	for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
+		hw->io_ports[i] = data_port | 
+			IO_FIELD(R_ATA_CTRL_DATA, addr, i) | 
+			IO_STATE(R_ATA_CTRL_DATA, cs0, active);
+	}
+
+	/* the IDE control register is at ATA address 6, with CS1 active instead of CS0 */
+
+	hw->io_ports[IDE_CONTROL_OFFSET] = data_port |
+			IO_FIELD(R_ATA_CTRL_DATA, addr, 6) | 
+			IO_STATE(R_ATA_CTRL_DATA, cs1, active);
+
+	/* whats this for ? */
+
+	hw->io_ports[IDE_IRQ_OFFSET] = 0;
+}
+
+static __inline__ void ide_init_default_hwifs(void)
+{
+	hw_regs_t hw;
+	int index;
+
+	for(index = 0; index < MAX_HWIFS; index++) {
+		ide_init_hwif_ports(&hw, ide_default_io_base(index), 0, NULL);
+		hw.irq = ide_default_irq(ide_default_io_base(index));
+		ide_register_hw(&hw, NULL);
+	}
+}
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned head		: 4;	/* always zeros here */
+		unsigned unit		: 1;	/* drive select number, 0 or 1 */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* using LBA instead of CHS */
+		unsigned bit7		: 1;	/* always 1 */
+	} b;
+	} select_t;
+
+/* some configuration options we don't need */
+
+#undef SUPPORT_VLB_SYNC
+#define SUPPORT_VLB_SYNC 0
+
+#undef SUPPORT_SLOW_DATA_PORTS
+#define SUPPORT_SLOW_DATA_PORTS	0
+
+/* request and free a normal interrupt */
+
+#define ide_request_irq(irq,hand,flg,dev,id)	request_irq((irq),(hand),(flg),(dev),(id))
+#define ide_free_irq(irq,dev_id)		free_irq((irq), (dev_id))
+
+/* ide-probe.c calls ide_request_region and stuff on the io_ports defined,
+ * but since they are not actually memory-mapped in the ETRAX driver, we don't
+ * do anything.
+ */
+
+#define ide_check_region(from,extent)		(0)
+#define ide_request_region(from,extent,name)	do {} while(0)
+#define ide_release_region(from,extent)		do {} while(0)
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
+
+/* the drive addressing is done through a controller register on the Etrax CPU */
+void OUT_BYTE(unsigned char data, ide_ioreg_t reg);
+unsigned char IN_BYTE(ide_ioreg_t reg);
+
+/* this tells ide.h not to define the standard macros */
+#define HAVE_ARCH_OUT_BYTE
+#define HAVE_ARCH_IN_BYTE
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASMCRIS_IDE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/io.h linux/include/asm-cris/io.h
--- v2.4.1/linux/include/asm-cris/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/io.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,178 @@
+#ifndef _ASM_CRIS_IO_H
+#define _ASM_CRIS_IO_H
+
+#include <asm/page.h>   /* for __va, __pa */
+#include <asm/svinto.h>
+#include <linux/config.h>
+
+/* Console I/O for simulated etrax100.  Use #ifdef so erroneous
+   use will be evident. */
+#ifdef CONFIG_SVINTO_SIM
+  /* Let's use the ucsim interface since it lets us do write(2, ...) */
+#define SIMCOUT(s,len) asm ("moveq 4,r1\n\tmoveq 2,r10\n\tmove.d %0,r11\n\tmove.d %1,r12\
+\n\tpush irp\n\t.word 0xae3f\n\t.dword 0f\n\tjump -6809\n0:\n\tpop irp" \
+       : : "rm" (s), "rm" (len) : "r1","r10","r11","r12","memory")
+#define TRACE_ON() __extension__ \
+ ({ int _Foofoo; __asm__ volatile ("bmod [%0],%0" : "=r" (_Foofoo) : "0" \
+			       (255)); _Foofoo; })
+
+#define TRACE_OFF() do { __asm__ volatile ("bmod [%0],%0" :: "r" (254)); } while (0)
+#define SIM_END() do { __asm__ volatile ("bmod [%0],%0" :: "r" (28)); } while (0)
+#define CRIS_CYCLES() __extension__ \
+ ({ unsigned long c; asm ("bmod [%1],%0" : "=r" (c) : "r" (27)); c;})
+#else  /* ! defined CONFIG_SVINTO_SIM */
+/* FIXME: Is there a reliable cycle counter available in some chip?  Use
+   that then. */
+#define CRIS_CYCLES() 0
+#endif /* ! defined CONFIG_SVINTO_SIM */
+
+/* Etrax shadow registers - which live in arch/cris/kernel/shadows.c */
+
+extern unsigned long port_g_data_shadow;
+extern unsigned char port_pa_dir_shadow;
+extern unsigned char port_pa_data_shadow;
+extern unsigned char port_pb_i2c_shadow;
+extern unsigned char port_pb_config_shadow;
+extern unsigned char port_pb_dir_shadow;
+extern unsigned char port_pb_data_shadow;
+extern unsigned long r_timer_ctrl_shadow;
+extern unsigned long port_90000000_shadow;
+
+/* macro for setting regs through a shadow - 
+ * r = register name (like R_PORT_PA_DATA)
+ * s = shadow name (like port_pa_data_shadow)
+ * b = bit number
+ * v = value (0 or 1)
+ */
+
+#define REG_SHADOW_SET(r,s,b,v) *r = s = (s & ~(1 << b)) | ((v) << b) 
+
+/* The LED's on various Etrax-based products are set differently. */
+
+#if defined(CONFIG_ETRAX_NO_LEDS) || defined(CONFIG_SVINTO_SIM)
+#undef CONFIG_ETRAX_PA_LEDS
+#undef CONFIG_ETRAX_PB_LEDS
+#undef CONFIG_ETRAX_90000000_LEDS
+#define LED_NETWORK_RX_SET(x)
+#define LED_NETWORK_TX_SET(x)
+#define LED_ACTIVE_SET(x)
+#define LED_ACTIVE_SET_G(x)
+#define LED_ACTIVE_SET_R(x)
+#define LED_DISK_WRITE(x)
+#define LED_DISK_READ(x)
+#endif
+
+#ifdef CONFIG_ETRAX_PA_LEDS
+#define LED_NETWORK_RX_SET(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1G, !x)
+#define LED_NETWORK_TX_SET(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED1R, !x)
+#define LED_ACTIVE_SET(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_ACTIVE_SET_G(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_ACTIVE_SET_R(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED2R, !x)
+#define LED_DISK_WRITE(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !x)
+#define LED_DISK_READ(x) \
+         REG_SHADOW_SET(R_PORT_PA_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !x) 
+#endif
+
+#ifdef CONFIG_ETRAX_PB_LEDS
+#define LED_NETWORK_RX_SET(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1G, !x)
+#define LED_NETWORK_TX_SET(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED1R, !x)
+#define LED_ACTIVE_SET(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_ACTIVE_SET_G(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_ACTIVE_SET_R(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pb_data_shadow, CONFIG_ETRAX_LED2R, !x)
+#define LED_DISK_WRITE(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3R, !x)
+#define LED_DISK_READ(x) \
+         REG_SHADOW_SET(R_PORT_PB_DATA, port_pa_data_shadow, CONFIG_ETRAX_LED3G, !x)     
+#endif
+
+#ifdef CONFIG_ETRAX_90000000_LEDS
+/* TODO: this won't work, need a vremap into kernel virtual memory of 90000000 */
+#define LED_PORT_90 (volatile unsigned long*)0x90000000
+#define LED_ACTIVE_SET(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_NETWORK_RX_SET(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED1G, !x)
+#define LED_NETWORK_TX_SET(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED1R, !x)
+#define LED_ACTIVE_SET_G(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED2G, !x)
+#define LED_ACTIVE_SET_R(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED2R, !x)
+#define LED_DISK_WRITE(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED3R, !x)
+#define LED_DISK_READ(x) \
+         REG_SHADOW_SET(LED_PORT_90, port_90000000_shadow, CONFIG_ETRAX_LED3G, !x)           
+#endif
+
+/*
+ * Change virtual addresses to physical addresses and vv.
+ */
+
+static inline unsigned long virt_to_phys(volatile void * address)
+{
+	return __pa(address);
+}
+
+static inline void * phys_to_virt(unsigned long address)
+{
+	return __va(address);
+}
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the CRIS architecture, we just read/write the
+ * memory location directly.
+ */
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+
+#define writeb(b,addr) ((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b,addr) ((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b))
+
+#define memset_io(a,b,c)	memset((void *)(a),(b),(c))
+#define memcpy_fromio(a,b,c)	memcpy((a),(void *)(b),(c))
+#define memcpy_toio(a,b,c)	memcpy((void *)(a),(b),(c))
+
+/*
+ * Again, CRIS does not require mem IO specific function.
+ */
+
+#define eth_io_copy_and_sum(a,b,c,d)	eth_copy_and_sum((a),(void *)(b),(c),(d))
+
+/* The following is junk needed for the arch-independant code but which
+ * we never use in the CRIS port
+ */
+
+#define IO_SPACE_LIMIT 0xffff
+#define inb(x) (0)
+#define outb(x,y)
+#define outw(x,y)
+#define outl(x,y)
+#define insb(x,y,z)
+#define insw(x,y,z)
+#define insl(x,y,z)
+#define outsb(x,y,z)
+#define outsw(x,y,z)
+#define outsl(x,y,z)
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ioctl.h linux/include/asm-cris/ioctl.h
--- v2.4.1/linux/include/asm-cris/ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ioctl.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,76 @@
+/*
+ * linux/ioctl.h for Linux by H.H. Bergman.
+ *
+ * This is the same as the i386 version.
+ */
+
+#ifndef _ASMCRIS_IOCTL_H
+#define _ASMCRIS_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* _ASMCRIS_IOCTL_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ioctls.h linux/include/asm-cris/ioctls.h
--- v2.4.1/linux/include/asm-cris/ioctls.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ioctls.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,84 @@
+#ifndef __ARCH_CRIS_IOCTLS_H__
+#define __ARCH_CRIS_IOCTLS_H__
+
+/* verbatim copy of asm-i386/ioctls.h */
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS		0x5401
+#define TCSETS		0x5402
+#define TCSETSW		0x5403
+#define TCSETSF		0x5404
+#define TCGETA		0x5405
+#define TCSETA		0x5406
+#define TCSETAW		0x5407
+#define TCSETAF		0x5408
+#define TCSBRK		0x5409
+#define TCXONC		0x540A
+#define TCFLSH		0x540B
+#define TIOCEXCL	0x540C
+#define TIOCNXCL	0x540D
+#define TIOCSCTTY	0x540E
+#define TIOCGPGRP	0x540F
+#define TIOCSPGRP	0x5410
+#define TIOCOUTQ	0x5411
+#define TIOCSTI		0x5412
+#define TIOCGWINSZ	0x5413
+#define TIOCSWINSZ	0x5414
+#define TIOCMGET	0x5415
+#define TIOCMBIS	0x5416
+#define TIOCMBIC	0x5417
+#define TIOCMSET	0x5418
+#define TIOCGSOFTCAR	0x5419
+#define TIOCSSOFTCAR	0x541A
+#define FIONREAD	0x541B
+#define TIOCINQ		FIONREAD
+#define TIOCLINUX	0x541C
+#define TIOCCONS	0x541D
+#define TIOCGSERIAL	0x541E
+#define TIOCSSERIAL	0x541F
+#define TIOCPKT		0x5420
+#define FIONBIO		0x5421
+#define TIOCNOTTY	0x5422
+#define TIOCSETD	0x5423
+#define TIOCGETD	0x5424
+#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
+#define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
+#define FIOCLEX		0x5451
+#define FIOASYNC	0x5452
+#define TIOCSERCONFIG	0x5453
+#define TIOCSERGWILD	0x5454
+#define TIOCSERSWILD	0x5455
+#define TIOCGLCKTRMIOS	0x5456
+#define TIOCSLCKTRMIOS	0x5457
+#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
+#define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+
+/* Used for packet mode */
+#define TIOCPKT_DATA		 0
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_NOSTOP		16
+#define TIOCPKT_DOSTOP		32
+
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ipc.h linux/include/asm-cris/ipc.h
--- v2.4.1/linux/include/asm-cris/ipc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ipc.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,34 @@
+#ifndef __CRIS_IPC_H__
+#define __CRIS_IPC_H__
+
+/* 
+ * These are used to wrap system calls on CRIS.
+ *
+ * See arch/cris/kernel/sys_cris.c for ugly details..
+ *
+ * Same as x86 version.
+ *
+ */
+struct ipc_kludge {
+	struct msgbuf *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ipcbuf.h linux/include/asm-cris/ipcbuf.h
--- v2.4.1/linux/include/asm-cris/ipcbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ipcbuf.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,29 @@
+#ifndef __CRIS_IPCBUF_H__
+#define __CRIS_IPCBUF_H__
+
+/*
+ * The user_ipc_perm structure for CRIS architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned short		__pad2;
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+#endif /* __CRIS_IPCBUF_H__ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/irq.h linux/include/asm-cris/irq.h
--- v2.4.1/linux/include/asm-cris/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/irq.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,102 @@
+/*
+ * Interrupt handling assembler for Linux/CRIS
+ *
+ * Copyright (c) 2000 Axis Communications AB
+ *
+ * Authors:   Bjorn Wesen (bjornw@axis.com)
+ *
+ */
+
+#ifndef _ASM_IRQ_H
+#define _ASM_IRQ_H
+
+/*
+ *	linux/include/asm-cris/irq.h
+ */
+
+#include <linux/linkage.h>
+#include <asm/segment.h>
+
+#include <asm/sv_addr_ag.h>
+
+#define NR_IRQS 26     /* TODO: what is this for Etrax100/LX ? */
+
+extern void disable_irq(unsigned int);
+extern void enable_irq(unsigned int);
+
+#define disable_irq_nosync      disable_irq
+#define enable_irq_nosync       enable_irq
+
+/* our fine, global, etrax irq vector! the pointer lives in the head.S file. */
+
+typedef void (*irqvectptr)(void);
+
+struct etrax_interrupt_vector {
+	irqvectptr v[256];
+};
+
+extern struct etrax_interrupt_vector *etrax_irv;
+void set_int_vector(int n, irqvectptr addr, irqvectptr saddr);
+void set_break_vector(int n, irqvectptr addr);
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+ 
+/* SAVE_ALL saves registers so they match pt_regs */
+
+#define SAVE_ALL \
+  "push irp\n\t"       /* push instruction pointer */ \
+  "push srp\n\t"       /* push subroutine return pointer */ \
+  "push dccr\n\t"      /* push condition codes */ \
+  "push mof\n\t"       /* push multiply overflow reg */ \
+  "di\n\t"             /* need to disable irq's at this point */\
+  "subq 14*4,sp\n\t"   /* make room for r0-r13 */ \
+  "movem r13,[sp]\n\t" /* push the r0-r13 registers */ \
+  "push r10\n\t"       /* push orig_r10 */ \
+  "clear.d [sp=sp-4]\n\t"  /* frametype - this is a normal stackframe */
+
+  /* BLOCK_IRQ and UNBLOCK_IRQ do the same as mask_irq and unmask_irq in irq.c */
+
+#define BLOCK_IRQ(mask,nr) \
+  "move.d " #mask ",r0\n\t" \
+  "move.d r0,[0xb00000d8]\n\t" 
+  
+#define UNBLOCK_IRQ(mask) \
+  "move.d " #mask ",r0\n\t" \
+  "move.d r0,[0xb00000dc]\n\t" 
+
+#define IRQ_NAME2(nr) nr##_interrupt(void)
+#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
+#define sIRQ_NAME(nr) IRQ_NAME2(sIRQ##nr)
+#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr)
+
+  /* the asm IRQ handler makes sure the causing IRQ is blocked, then it calls
+   * do_IRQ (with irq disabled still). after that it unblocks and jumps to
+   * ret_from_intr (entry.S)
+   */
+
+#define BUILD_IRQ(nr,mask) \
+void IRQ_NAME(nr); \
+void sIRQ_NAME(nr); \
+void BAD_IRQ_NAME(nr); \
+__asm__ ( \
+          ".text\n\t" \
+          "_IRQ" #nr "_interrupt:\n\t" \
+	  SAVE_ALL \
+	  "_sIRQ" #nr "_interrupt:\n\t" /* shortcut for the multiple irq handler */ \
+	  BLOCK_IRQ(mask,nr) /* this must be done to prevent irq loops when we ei later */ \
+	  "moveq "#nr",r10\n\t" \
+	  "move.d sp,r11\n\t" \
+	  "jsr _do_IRQ\n\t" /* irq.c, r10 and r11 are arguments */ \
+	  UNBLOCK_IRQ(mask) \
+	  "moveq 0,r9\n\t" /* make ret_from_intr realise we came from an irq */ \
+	  "jump _ret_from_intr\n\t" \
+          "_bad_IRQ" #nr "_interrupt:\n\t" \
+	  "push r0\n\t" \
+	  BLOCK_IRQ(mask,nr) \
+	  "pop r0\n\t");
+
+
+#endif  /* _ASM_IRQ_H */
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/locks.h linux/include/asm-cris/locks.h
--- v2.4.1/linux/include/asm-cris/locks.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/locks.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,133 @@
+/*
+ *	SMP locks primitives for building ix86 locks
+ *	(not yet used).
+ *
+ *		Alan Cox, alan@cymru.net, 1995
+ */
+ 
+/*
+ *	This would be much easier but far less clear and easy
+ *	to borrow for other processors if it was just assembler.
+ */
+
+extern __inline__ void prim_spin_lock(struct spinlock *sp)
+{
+	int processor=smp_processor_id();
+	
+	/*
+	 *	Grab the lock bit
+	 */
+	 
+	while(lock_set_bit(0,&sp->lock))
+	{
+		/*
+		 *	Failed, but that's cos we own it!
+		 */
+		 
+		if(sp->cpu==processor)
+		{
+			sp->users++;
+			return 0;
+		}
+		/*
+		 *	Spin in the cache S state if possible
+		 */
+		while(sp->lock)
+		{
+			/*
+			 *	Wait for any invalidates to go off
+			 */
+			 
+			if(smp_invalidate_needed&(1<<processor))
+				while(lock_clear_bit(processor,&smp_invalidate_needed))
+					local_flush_tlb();
+			sp->spins++;
+		}
+		/*
+		 *	Someone wrote the line, we go 'I' and get
+		 *	the cache entry. Now try to regrab
+		 */
+	}
+	sp->users++;sp->cpu=processor;
+	return 1;
+}
+
+/*
+ *	Release a spin lock
+ */
+ 
+extern __inline__ int prim_spin_unlock(struct spinlock *sp)
+{
+	/* This is safe. The decrement is still guarded by the lock. A multilock would
+	   not be safe this way */
+	if(!--sp->users)
+	{
+		lock_clear_bit(0,&sp->lock);sp->cpu= NO_PROC_ID;
+		return 1;
+	}
+	return 0;
+}
+
+
+/*
+ *	Non blocking lock grab
+ */
+ 
+extern __inline__ int prim_spin_lock_nb(struct spinlock *sp)
+{
+	if(lock_set_bit(0,&sp->lock))
+		return 0;		/* Locked already */
+	sp->users++;
+	return 1;			/* We got the lock */
+}
+
+
+/*
+ *	These wrap the locking primitives up for usage
+ */
+ 
+extern __inline__ void spinlock(struct spinlock *sp)
+{
+	if(sp->priority<current->lock_order)
+		panic("lock order violation: %s (%d)\n", sp->name, current->lock_order);
+	if(prim_spin_lock(sp))
+	{
+		/*
+		 *	We got a new lock. Update the priority chain
+		 */
+		sp->oldpri=current->lock_order;
+		current->lock_order=sp->priority;
+	}
+}
+
+extern __inline__ void spinunlock(struct spinlock *sp)
+{
+	if(current->lock_order!=sp->priority)
+		panic("lock release order violation %s (%d)\n", sp->name, current->lock_order);
+	if(prim_spin_unlock(sp))
+	{
+		/*
+		 *	Update the debugging lock priority chain. We dumped
+		 *	our last right to the lock.
+		 */
+		current->lock_order=sp->oldpri;
+	}	
+}
+
+extern __inline__ void spintestlock(struct spinlock *sp)
+{
+	/*
+	 *	We do no sanity checks, it's legal to optimistically
+	 *	get a lower lock.
+	 */
+	prim_spin_lock_nb(sp);
+}
+
+extern __inline__ void spintestunlock(struct spinlock *sp)
+{
+	/*
+	 *	A testlock doesn't update the lock chain so we
+	 *	must not update it on free
+	 */
+	prim_spin_unlock(sp);
+}
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/mman.h linux/include/asm-cris/mman.h
--- v2.4.1/linux/include/asm-cris/mman.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/mman.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,40 @@
+#ifndef __CRIS_MMAN_H__
+#define __CRIS_MMAN_H__
+
+/* verbatim copy of asm-i386/ version */
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_NONE	0x0		/* page can not be accessed */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#define MAP_LOCKED	0x2000		/* pages are locked */
+#define MAP_NORESERVE	0x4000		/* don't check for reservations */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+#define MADV_NORMAL	0x0		/* default page-in behavior */
+#define MADV_RANDOM	0x1		/* page-in minimum required */
+#define MADV_SEQUENTIAL	0x2		/* read-ahead aggressively */
+#define MADV_WILLNEED	0x3		/* pre-fault pages */
+#define MADV_DONTNEED	0x4		/* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON	MAP_ANONYMOUS
+#define MAP_FILE	0
+
+#endif /* __CRIS_MMAN_H__ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/mmu.h linux/include/asm-cris/mmu.h
--- v2.4.1/linux/include/asm-cris/mmu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/mmu.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,62 @@
+/*
+ * CRIS MMU constants and PTE layout
+ */
+
+#ifndef _CRIS_MMU_H
+#define _CRIS_MMU_H
+
+/* type used in struct mm to couple an MMU context to an active mm */
+
+typedef unsigned int mm_context_t;
+
+/* kernel memory segments */
+
+#define KSEG_F 0xf0000000UL
+#define KSEG_E 0xe0000000UL
+#define KSEG_D 0xd0000000UL
+#define KSEG_C 0xc0000000UL
+#define KSEG_B 0xb0000000UL
+#define KSEG_A 0xa0000000UL
+#define KSEG_9 0x90000000UL
+#define KSEG_8 0x80000000UL
+#define KSEG_7 0x70000000UL
+#define KSEG_6 0x60000000UL
+#define KSEG_5 0x50000000UL
+#define KSEG_4 0x40000000UL
+#define KSEG_3 0x30000000UL
+#define KSEG_2 0x20000000UL
+#define KSEG_1 0x10000000UL
+#define KSEG_0 0x00000000UL
+
+/* CRIS PTE bits (see R_TLB_LO in the register description)
+ *
+ *   Bit:  31-13 12-------4    3        2       1       0  
+ *         ________________________________________________
+ *        | pfn | reserved | global | valid | kernel | we  |
+ *        |_____|__________|________|_______|________|_____|
+ *
+ * (pfn = physical frame number)
+ */
+
+/* Real HW-based PTE bits. We use some synonym names so that
+ * things become less confusing in combination with the SW-based
+ * bits further below.
+ *
+ */
+
+#define _PAGE_WE	   (1<<0) /* page is write-enabled */
+#define _PAGE_SILENT_WRITE (1<<0) /* synonym */
+#define _PAGE_KERNEL	   (1<<1) /* page is kernel only */
+#define _PAGE_VALID	   (1<<2) /* page is valid */
+#define _PAGE_SILENT_READ  (1<<2) /* synonym */
+#define _PAGE_GLOBAL       (1<<3) /* global page - context is ignored */
+
+/* Bits the HW doesn't care about but the kernel uses them in SW */
+
+#define _PAGE_PRESENT   (1<<4)  /* page present in memory */
+#define _PAGE_ACCESSED	(1<<5)  /* simulated in software using valid bit */
+#define _PAGE_MODIFIED	(1<<6)  /* simulated in software using we bit */
+#define _PAGE_READ      (1<<7)  /* read-enabled */
+#define _PAGE_WRITE     (1<<8)  /* write-enabled */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/mmu_context.h linux/include/asm-cris/mmu_context.h
--- v2.4.1/linux/include/asm-cris/mmu_context.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/mmu_context.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,16 @@
+#ifndef __CRIS_MMU_CONTEXT_H
+#define __CRIS_MMU_CONTEXT_H
+
+extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+extern void get_mmu_context(struct mm_struct *mm);
+extern void destroy_context(struct mm_struct *mm);
+extern void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+		      struct task_struct *tsk, int cpu);
+
+#define activate_mm(prev,next) switch_mm((prev),(next),NULL,smp_processor_id())
+
+static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+{
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/module.h linux/include/asm-cris/module.h
--- v2.4.1/linux/include/asm-cris/module.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/module.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,11 @@
+#ifndef _ASM_CRIS_MODULE_H
+#define _ASM_CRIS_MODULE_H
+/*
+ * This file contains the CRIS architecture specific module code.
+ */
+
+#define module_map(x)		vmalloc(x)
+#define module_unmap(x)		vfree(x)
+#define module_arch_init(x)	(0)
+
+#endif /* _ASM_CRIS_MODULE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/msgbuf.h linux/include/asm-cris/msgbuf.h
--- v2.4.1/linux/include/asm-cris/msgbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/msgbuf.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,33 @@
+#ifndef _CRIS_MSGBUF_H
+#define _CRIS_MSGBUF_H
+
+/* verbatim copy of asm-i386 version */
+
+/* 
+ * The msqid64_ds structure for CRIS architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	unsigned long	__unused1;
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	unsigned long	__unused2;
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long	__unused3;
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+#endif /* _CRIS_MSGBUF_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/namei.h linux/include/asm-cris/namei.h
--- v2.4.1/linux/include/asm-cris/namei.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/namei.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,17 @@
+/* $Id: namei.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $
+ * linux/include/asm-cris/namei.h
+ *
+ * Included from linux/fs/namei.c
+ */
+
+#ifndef __CRIS_NAMEI_H
+#define __CRIS_NAMEI_H
+
+/* used to find file-system prefixes for doing emulations
+ * see for example asm-sparc/namei.h
+ * we dont use it...
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* __CRIS_NAMEI_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/page.h linux/include/asm-cris/page.h
--- v2.4.1/linux/include/asm-cris/page.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/page.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,118 @@
+#ifndef _CRIS_PAGE_H
+#define _CRIS_PAGE_H
+
+#include <linux/config.h>
+#include <asm/mmu.h>
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT	13
+#define PAGE_SIZE	(1UL << PAGE_SHIFT)
+#define PAGE_MASK	(~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+
+#define clear_page(page)        memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from)      memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr)    clear_page(page)
+#define copy_user_page(to, from, vaddr) copy_page(to, from)
+
+#define STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pmd; } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)	((x).pte)
+#define pmd_val(x)	((x).pmd)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)	((x).pgprot)
+
+#define __pte(x)	((pte_t) { (x) } )
+#define __pmd(x)	((pmd_t) { (x) } )
+#define __pgd(x)	((pgd_t) { (x) } )
+#define __pgprot(x)	((pgprot_t) { (x) } )
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pmd_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)	(x)
+#define pmd_val(x)	(x)
+#define pgd_val(x)	(x)
+#define pgprot_val(x)	(x)
+
+#define __pte(x)	(x)
+#define __pmd(x)	(x)
+#define __pgd(x)	(x)
+#define __pgprot(x)	(x)
+
+#endif
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)	(((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/* This handles the memory map.. */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define PAGE_OFFSET		KSEG_6   /* kseg_6 is mapped to physical ram */
+#else
+#define PAGE_OFFSET		KSEG_C   /* kseg_c is mapped to physical ram */
+#endif
+
+#ifndef __ASSEMBLY__
+
+#define BUG() do { \
+  printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+} while (0)
+
+#define PAGE_BUG(page) do { \
+         BUG(); \
+} while (0)
+
+#endif /* __ASSEMBLY__ */
+
+/* macros to convert between really physical and virtual addresses
+ * by stripping a selected bit, we can convert between KSEG_x and 0x40000000 where
+ * the DRAM really resides
+ */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+/* we have DRAM virtually at 0x6 */
+#define __pa(x)                 ((unsigned long)(x) & 0xdfffffff)
+#define __va(x)                 ((void *)((unsigned long)(x) | 0x20000000))
+#else
+/* we have DRAM virtually at 0xc */
+#define __pa(x)                 ((unsigned long)(x) & 0x7fffffff)
+#define __va(x)                 ((void *)((unsigned long)(x) | 0x80000000))
+#endif
+
+/* to index into the page map. our pages all start at physical addr PAGE_OFFSET so
+ * we can let the map start there. notice that we subtract PAGE_OFFSET because
+ * we start our mem_map there - in other ports they map mem_map physically and
+ * use __pa instead. in our system both the physical and virtual address of DRAM
+ * is too high to let mem_map start at 0, so we do it this way instead (similar
+ * to arm and m68k I think)
+ */ 
+
+#define virt_to_page(kaddr)    (mem_map + (((unsigned long)kaddr - PAGE_OFFSET) >> PAGE_SHIFT))
+#define VALID_PAGE(page)       ((page - mem_map) < max_mapnr)
+
+/* from linker script */
+
+extern unsigned long dram_start, dram_end;
+
+#endif /* __KERNEL__ */
+
+#endif /* _CRIS_PAGE_H */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/param.h linux/include/asm-cris/param.h
--- v2.4.1/linux/include/asm-cris/param.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/param.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,24 @@
+#ifndef _ASMCRIS_PARAM_H
+#define _ASMCRIS_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE	8192
+
+#ifndef NGROUPS
+#define NGROUPS		32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC        100     /* frequency at which times() counts */
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/pci.h linux/include/asm-cris/pci.h
--- v2.4.1/linux/include/asm-cris/pci.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/pci.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,9 @@
+#ifndef __ASM_CRIS_PCI_H
+#define __ASM_CRIS_PCI_H
+
+/* ETRAX chips don't have a PCI bus. This file is just here because some stupid .c code
+ * includes it even if CONFIG_PCI is not set.
+ */
+
+#endif /* __ASM_CRIS_PCI_H */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/pgalloc.h linux/include/asm-cris/pgalloc.h
--- v2.4.1/linux/include/asm-cris/pgalloc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/pgalloc.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,200 @@
+#ifndef _CRIS_PGALLOC_H
+#define _CRIS_PGALLOC_H
+
+#include <linux/config.h>
+#include <asm/page.h>
+#include <linux/threads.h>
+
+/* bunch of protos */
+
+extern pgd_t *get_pgd_slow(void);
+extern void free_pgd_slow(pgd_t *pgd);
+extern __inline__ void free_pmd_slow(pmd_t *pmd) { }
+extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
+extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
+
+/* first the non-cached versions */
+
+extern __inline__ void free_pte_slow(pte_t *pte)
+{
+        free_page((unsigned long)pte);
+}
+
+extern __inline__ pgd_t *get_pgd_slow(void)
+{
+        pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+        if (ret) {
+                memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+                memcpy(ret + USER_PTRS_PER_PGD, swapper_pg_dir + USER_PTRS_PER_PGD,
+		       (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+        }
+        return ret;
+}
+
+extern __inline__ void free_pgd_slow(pgd_t *pgd)
+{
+        free_page((unsigned long)pgd);
+}
+
+/*
+ * Now for the page table cache versions
+ */
+
+#ifndef CONFIG_NO_PGT_CACHE
+
+#ifdef CONFIG_SMP
+#error Pgtable caches have to be per-CPU, so that no locking is needed.
+#endif  /* CONFIG_SMP */
+
+extern struct pgtable_cache_struct {
+        unsigned long *pgd_cache;
+        unsigned long *pte_cache;
+        unsigned long pgtable_cache_sz;
+} quicklists;
+
+#define pgd_quicklist           (quicklists.pgd_cache)
+#define pmd_quicklist           ((unsigned long *)0)
+#define pte_quicklist           (quicklists.pte_cache)
+#define pgtable_cache_size      (quicklists.pgtable_cache_sz)
+
+extern __inline__ pgd_t *get_pgd_fast(void)
+{
+        unsigned long *ret;
+
+        if ((ret = pgd_quicklist) != NULL) {
+                pgd_quicklist = (unsigned long *)(*ret);
+                ret[0] = 0;
+                pgtable_cache_size--;
+        } else
+                ret = (unsigned long *)get_pgd_slow();
+        return (pgd_t *)ret;
+}
+
+extern __inline__ void free_pgd_fast(pgd_t *pgd)
+{
+        *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
+        pgd_quicklist = (unsigned long *) pgd;
+        pgtable_cache_size++;
+}
+
+/* We don't use pmd cache, so this is a dummy routine */
+
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+        return (pmd_t *)0;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd) { }
+
+extern __inline__ pte_t *get_pte_fast(void)
+{
+        unsigned long *ret;
+
+        if((ret = (unsigned long *)pte_quicklist) != NULL) {
+                pte_quicklist = (unsigned long *)(*ret);
+                ret[0] = ret[1];
+                pgtable_cache_size--;
+        }
+        return (pte_t *)ret;
+}
+
+extern __inline__ void free_pte_fast(pte_t *pte)
+{
+        *(unsigned long *)pte = (unsigned long) pte_quicklist;
+        pte_quicklist = (unsigned long *) pte;
+        pgtable_cache_size++;
+}
+
+#else   /* CONFIG_NO_PGT_CACHE */
+
+#define pgd_quicklist           ((unsigned long *)0)
+#define pmd_quicklist           ((unsigned long *)0)
+#define pte_quicklist           ((unsigned long *)0)
+
+#define get_pgd_fast()          ((pgd_t *)0)
+#define get_pmd_fast()          ((pmd_t *)0)
+#define get_pte_fast()          ((pte_t *)0)
+
+#define free_pgd_fast(pgd)      free_pgd_slow(pgd)
+#define free_pmd_fast(pmd)      free_pmd_slow(pmd)
+#define free_pte_fast(pte)      free_pte_slow(pte)
+
+#endif  /* CONFIG_NO_PGT_CACHE */
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
+
+#define pte_free_kernel(pte)    free_pte_slow(pte)
+#define pte_free(pte)           free_pte_slow(pte)
+
+extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
+{
+        if (!pmd)
+                BUG();
+        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+        if (pmd_none(*pmd)) {
+                pte_t * page = (pte_t *) get_pte_fast();
+                if (!page)
+                        return get_pte_kernel_slow(pmd, address);
+		pmd_set_kernel(pmd, page);
+                return page + address;
+        }
+        if (pmd_bad(*pmd)) {
+                __handle_bad_pmd_kernel(pmd);
+                return NULL;
+        }
+        return (pte_t *) pmd_page(*pmd) + address;
+}
+
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+{
+        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+
+        if (pmd_none(*pmd))
+                goto getnew;
+        if (pmd_bad(*pmd))
+                goto fix;
+        return (pte_t *)pmd_page(*pmd) + address;
+ getnew:
+	{
+		pte_t * page = (pte_t *) get_pte_fast();
+		if (!page)
+			return get_pte_slow(pmd, address);
+		pmd_set(pmd, page);
+		return page + address;
+	}
+ fix:
+        __handle_bad_pmd(pmd);
+        return NULL;
+}
+
+/*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ */
+
+#define pmd_free(pmd)      free_pmd_slow(pmd)
+#define pmd_free_kernel    pmd_free
+#define pmd_alloc_kernel   pmd_alloc
+
+extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
+{
+        if (!pgd)
+                BUG();
+        return (pmd_t *) pgd;
+}
+
+/* pgd handling */
+
+#define pgd_free(pgd)      free_pgd_slow(pgd)
+#define pgd_alloc()        get_pgd_fast()
+
+/* other stuff */
+
+extern int do_check_pgt_cache(int, int);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/pgtable.h linux/include/asm-cris/pgtable.h
--- v2.4.1/linux/include/asm-cris/pgtable.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/pgtable.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,518 @@
+/* CRIS pgtable.h - macros and functions to manipulate page tables
+ *
+ * HISTORY:
+ *
+ * $Log: pgtable.h,v $
+ * Revision 1.9  2000/11/22 14:57:53  bjornw
+ * * extern inline -> static inline
+ * * include asm-generic/pgtable.h
+ *
+ * Revision 1.8  2000/11/21 13:56:16  bjornw
+ * Use CONFIG_CRIS_LOW_MAP for the low VM map instead of explicit CPU type
+ *
+ * Revision 1.7  2000/10/06 15:05:32  bjornw
+ * VMALLOC area changed in memory mapping change
+ *
+ * Revision 1.6  2000/10/04 16:59:14  bjornw
+ * Changed comments
+ *
+ * Revision 1.5  2000/09/13 14:39:53  bjornw
+ * New macros
+ *
+ * Revision 1.4  2000/08/17 15:38:48  bjornw
+ * 2.4.0-test6 modifications:
+ *   * flush_dcache_page added
+ *   * MAP_NR removed
+ *   * virt_to_page added
+ *
+ * Plus some comments and type-clarifications.
+ *
+ * Revision 1.3  2000/08/15 16:33:35  bjornw
+ * pmd_bad should recognize both kernel and user page-tables
+ *
+ * Revision 1.2  2000/07/10 17:06:01  bjornw
+ * Fixed warnings
+ *
+ * Revision 1.1.1.1  2000/07/10 16:32:31  bjornw
+ * CRIS architecture, working draft
+ *
+ *
+ * Revision 1.11  2000/05/29 14:55:56  bjornw
+ * Small tweaks of pte_mk routines
+ *
+ * Revision 1.10  2000/01/27 01:49:06  bjornw
+ * * Ooops. The physical frame number in a PTE entry needs to point to the
+ *   DRAM directly, not to what the kernel thinks is DRAM (due to KSEG mapping).
+ *   Hence we need to strip bit 31 so 0xcXXXXXXX -> 0x4XXXXXXX.
+ *
+ * Revision 1.9  2000/01/26 16:25:50  bjornw
+ * Fixed PAGE_KERNEL bits
+ *
+ * Revision 1.8  2000/01/23 22:53:22  bjornw
+ * Correct flush_tlb_* macros and externs
+ *
+ * Revision 1.7  2000/01/18 16:22:55  bjornw
+ * Use PAGE_MASK instead of PFN_MASK.
+ *
+ * Revision 1.6  2000/01/17 02:42:53  bjornw
+ * Added the pmd_set macro.
+ *
+ * Revision 1.5  2000/01/16 19:53:42  bjornw
+ * Removed VMALLOC_OFFSET. Changed definitions of swapper_pg_dir and zero_page.
+ *
+ * Revision 1.4  2000/01/14 16:38:20  bjornw
+ * PAGE_DIRTY -> PAGE_SILENT_WRITE, removed PAGE_COW from PAGE_COPY.
+ *
+ * Revision 1.3  1999/12/04 20:12:21  bjornw
+ * * PTE bits have moved to asm/mmu.h
+ * * Fixed definitions of the higher level page protection bits
+ * * Added the pte_* functions, including dirty/accessed SW simulation
+ *   (these are exactly the same as for the MIPS port)
+ *
+ * Revision 1.2  1999/12/04 00:41:54  bjornw
+ * * Fixed page table offsets, sizes and shifts
+ * * Removed reference to i386 SMP stuff
+ * * Added stray comments about Linux/CRIS mm design
+ * * Include asm/mmu.h which will contain MMU details
+ *
+ * Revision 1.1  1999/12/03 15:04:02  bjornw
+ * Copied from include/asm-etrax100. For the new CRIS architecture.
+ */
+
+#ifndef _CRIS_PGTABLE_H
+#define _CRIS_PGTABLE_H
+
+#include <linux/config.h>
+#include <asm/mmu.h>
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * CRIS, we use that, but "fold" the mid level into the top-level page
+ * table. Since the MMU TLB is software loaded through an interrupt, it
+ * supports any page table structure, so we could have used a three-level
+ * setup, but for the amounts of memory we normally use, a two-level is
+ * probably more efficient.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the CRIS page table tree.
+ */
+
+/* The cache doesn't need to be flushed when TLB entries change (I think!) */
+#define flush_cache_all()			do { } while (0)
+#define flush_cache_mm(mm)			do { } while (0)
+#define flush_cache_range(mm, start, end)	do { } while (0)
+#define flush_cache_page(vma, vmaddr)		do { } while (0)
+#define flush_page_to_ram(page)			do { } while (0)
+#define flush_dcache_page(page)                 do { } while (0)
+#define flush_icache_range(start, end)          do { } while (0)
+#define flush_icache_page(vma,pg)               do { } while (0)
+
+/*
+ * TLB flushing (implemented in arch/cris/mm/tlb.c):
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *
+ */
+
+extern void flush_tlb_all(void);
+extern void flush_tlb_mm(struct mm_struct *mm);
+extern void flush_tlb_page(struct vm_area_struct *vma, 
+			   unsigned long addr);
+extern void flush_tlb_range(struct mm_struct *mm,
+			    unsigned long start,
+			    unsigned long end);
+
+static inline void flush_tlb_pgtables(struct mm_struct *mm,
+                                      unsigned long start, unsigned long end)
+{
+        /* CRIS does not keep any page table caches in TLB */
+}
+
+
+static inline void flush_tlb(void) 
+{
+	flush_tlb_mm(current->mm);
+}
+
+/* Certain architectures need to do special things when pte's
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+/*
+ * (pmds are folded into pgds so this doesnt get actually called,
+ * but the define is needed for a generic inline function.)
+ */
+#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
+#define set_pgd(pgdptr, pgdval) (*(pgdptr) = pgdval)
+
+/* PMD_SHIFT determines the size of the area a second-level page table can
+ * map. It is equal to the page size times the number of PTE's that fit in
+ * a PMD page. A PTE is 4-bytes in CRIS. Hence the following number.
+ */
+
+#define PMD_SHIFT	(PAGE_SHIFT + (PAGE_SHIFT-2))
+#define PMD_SIZE	(1UL << PMD_SHIFT)
+#define PMD_MASK	(~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map.
+ * Since we fold into a two-level structure, this is the same as PMD_SHIFT.
+ */
+
+#define PGDIR_SHIFT	PMD_SHIFT
+#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK	(~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: we use a two-level, so
+ * we don't really have any PMD directory physically.
+ * pointers are 4 bytes so we can use the page size and 
+ * divide it by 4 (shift by 2).
+ */
+#define PTRS_PER_PTE	(1UL << (PAGE_SHIFT-2))
+#define PTRS_PER_PMD	1
+#define PTRS_PER_PGD	(1UL << (PAGE_SHIFT-2))
+
+/* calculate how many PGD entries a user-level program can use
+ * the first mappable virtual address is 0
+ * (TASK_SIZE is the maximum virtual address space)
+ */
+
+#define USER_PTRS_PER_PGD       (TASK_SIZE/PGDIR_SIZE)
+#define FIRST_USER_PGD_NR       0
+
+/*
+ * Kernels own virtual memory area. 
+ */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define VMALLOC_START     KSEG_7
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       KSEG_8
+#else
+#define VMALLOC_START     KSEG_D
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END       KSEG_E
+#endif
+
+/* Define some higher level generic page attributes. The PTE bits are
+ * defined in asm-cris/mmu.h, and these are just combinations of those.
+ */
+
+#define __READABLE      (_PAGE_READ | _PAGE_SILENT_READ | _PAGE_ACCESSED)
+#define __WRITEABLE     (_PAGE_WRITE | _PAGE_SILENT_WRITE | _PAGE_MODIFIED)
+
+#define _PAGE_TABLE     (_PAGE_PRESENT | __READABLE | __WRITEABLE)
+#define _PAGE_CHG_MASK  (PAGE_MASK | _PAGE_ACCESSED | _PAGE_SILENT_WRITE)
+
+#define PAGE_NONE       __pgprot(_PAGE_PRESENT | __READABLE)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | __READABLE | _PAGE_WRITE | \
+				 _PAGE_ACCESSED)
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | __READABLE)  // | _PAGE_COW
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | __READABLE)
+#define PAGE_KERNEL     __pgprot(_PAGE_GLOBAL | _PAGE_KERNEL | \
+				 _PAGE_PRESENT | __READABLE | __WRITEABLE)
+#define _KERNPG_TABLE   (_PAGE_TABLE | _PAGE_KERNEL)
+
+/*
+ * CRIS can't do page protection for execute, and considers read the same.
+ * Also, write permissions imply read permissions. This is the closest we can
+ * get..
+ */
+
+#define __P000	PAGE_NONE
+#define __P001	PAGE_READONLY
+#define __P010	PAGE_COPY
+#define __P011	PAGE_COPY
+#define __P100	PAGE_READONLY
+#define __P101	PAGE_READONLY
+#define __P110	PAGE_COPY
+#define __P111	PAGE_COPY
+
+#define __S000	PAGE_NONE
+#define __S001	PAGE_READONLY
+#define __S010	PAGE_SHARED
+#define __S011	PAGE_SHARED
+#define __S100	PAGE_READONLY
+#define __S101	PAGE_READONLY
+#define __S110	PAGE_SHARED
+#define __S111	PAGE_SHARED
+
+/* zero page used for uninitialized stuff */
+extern unsigned long empty_zero_page;
+
+/*
+ * BAD_PAGETABLE is used when we need a bogus page-table, while
+ * BAD_PAGE is used for a bogus page.
+ *
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern pte_t __bad_page(void);
+extern pte_t * __bad_pagetable(void);
+
+#define BAD_PAGETABLE    __bad_pagetable()
+#define BAD_PAGE         __bad_page()
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+/*
+ * Handling allocation failures during page table setup.
+ */
+extern void __handle_bad_pmd(pmd_t * pmd);
+extern void __handle_bad_pmd_kernel(pmd_t * pmd);
+
+/* number of bits that fit into a memory pointer */
+#define BITS_PER_PTR			(8*sizeof(unsigned long))
+
+/* to align the pointer to a pointer address */
+#define PTR_MASK			(~(sizeof(void*)-1))
+
+/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
+/* 64-bit machines, beware!  SRB. */
+#define SIZEOF_PTR_LOG2			2
+
+/* to find an entry in a page-table */
+#define PAGE_PTR(address) \
+((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
+
+/* to set the page-dir */
+#define SET_PAGE_DIR(tsk,pgdir)
+
+#define pte_none(x)	(!pte_val(x))
+#define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
+#define pte_clear(xp)	do { pte_val(*(xp)) = 0; } while (0)
+
+#define pmd_none(x)	(!pmd_val(x))
+/* by removing the _PAGE_KERNEL bit from the comparision, the same pmd_bad
+ * works for both _PAGE_TABLE and _KERNPG_TABLE pmd entries.
+ */
+#define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_KERNEL)) != _PAGE_TABLE)
+#define pmd_present(x)	(pmd_val(x) & _PAGE_PRESENT)
+#define pmd_clear(xp)	do { pmd_val(*(xp)) = 0; } while (0)
+
+/*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+static inline int pgd_none(pgd_t pgd)		{ return 0; }
+static inline int pgd_bad(pgd_t pgd)		{ return 0; }
+static inline int pgd_present(pgd_t pgd)	{ return 1; }
+static inline void pgd_clear(pgd_t * pgdp)	{ }
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+
+static inline int pte_read(pte_t pte)           { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_write(pte_t pte)          { return pte_val(pte) & _PAGE_WRITE; }
+static inline int pte_exec(pte_t pte)           { return pte_val(pte) & _PAGE_READ; }
+static inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_MODIFIED; }
+static inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
+
+static inline pte_t pte_wrprotect(pte_t pte)
+{
+        pte_val(pte) &= ~(_PAGE_WRITE | _PAGE_SILENT_WRITE);
+        return pte;
+}
+
+static inline pte_t pte_rdprotect(pte_t pte)
+{
+        pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	return pte;
+}
+
+static inline pte_t pte_exprotect(pte_t pte)
+{
+        pte_val(pte) &= ~(_PAGE_READ | _PAGE_SILENT_READ);
+	return pte;
+}
+
+static inline pte_t pte_mkclean(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_MODIFIED | _PAGE_SILENT_WRITE); 
+	return pte; 
+}
+
+static inline pte_t pte_mkold(pte_t pte)
+{
+	pte_val(pte) &= ~(_PAGE_ACCESSED | _PAGE_SILENT_READ);
+	return pte;
+}
+
+static inline pte_t pte_mkwrite(pte_t pte)
+{
+        pte_val(pte) |= _PAGE_WRITE;
+        if (pte_val(pte) & _PAGE_MODIFIED)
+                pte_val(pte) |= _PAGE_SILENT_WRITE;
+        return pte;
+}
+
+static inline pte_t pte_mkread(pte_t pte)
+{
+        pte_val(pte) |= _PAGE_READ;
+        if (pte_val(pte) & _PAGE_ACCESSED)
+                pte_val(pte) |= _PAGE_SILENT_READ;
+        return pte;
+}
+
+static inline pte_t pte_mkexec(pte_t pte)
+{
+        pte_val(pte) |= _PAGE_READ;
+        if (pte_val(pte) & _PAGE_ACCESSED)
+                pte_val(pte) |= _PAGE_SILENT_READ;
+        return pte;
+}
+
+static inline pte_t pte_mkdirty(pte_t pte)
+{
+        pte_val(pte) |= _PAGE_MODIFIED;
+        if (pte_val(pte) & _PAGE_WRITE)
+                pte_val(pte) |= _PAGE_SILENT_WRITE;
+        return pte;
+}
+
+static inline pte_t pte_mkyoung(pte_t pte)
+{
+        pte_val(pte) |= _PAGE_ACCESSED;
+        if (pte_val(pte) & _PAGE_READ)
+        {
+                pte_val(pte) |= _PAGE_SILENT_READ;
+                if ((pte_val(pte) & (_PAGE_WRITE | _PAGE_MODIFIED)) ==
+		    (_PAGE_WRITE | _PAGE_MODIFIED))
+                        pte_val(pte) |= _PAGE_SILENT_WRITE;
+        }
+        return pte;
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+/* What actually goes as arguments to the various functions is less than
+ * obvious, but a rule of thumb is that struct page's goes as struct page *,
+ * really physical DRAM addresses are unsigned long's, and DRAM "virtual"
+ * addresses (the 0xc0xxxxxx's) goes as void *'s.
+ */
+
+static inline pte_t __mk_pte(void * page, pgprot_t pgprot)
+{
+	pte_t pte;
+	/* the PTE needs a physical address */
+	pte_val(pte) = __pa(page) | pgprot_val(pgprot);
+	return pte;
+}
+
+#define mk_pte(page, pgprot) __mk_pte(page_address(page), (pgprot))
+
+#define mk_pte_phys(physpage, pgprot) \
+({                                                                      \
+        pte_t __pte;                                                    \
+                                                                        \
+        pte_val(__pte) = (physpage) + pgprot_val(pgprot);               \
+        __pte;                                                          \
+})
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte; }
+
+
+/* pte_val refers to a page in the 0x4xxxxxxx physical DRAM interval
+ * __pte_page(pte_val) refers to the "virtual" DRAM interval
+ * pte_pagenr refers to the page-number counted starting from the virtual DRAM start
+ */
+
+static inline unsigned long __pte_page(pte_t pte)
+{
+	/* the PTE contains a physical address */
+	return (unsigned long)__va(pte_val(pte) & PAGE_MASK);
+}
+
+#define pte_pagenr(pte)         ((__pte_page(pte) - PAGE_OFFSET) >> PAGE_SHIFT)
+
+/* permanent address of a page */
+
+#define page_address(page)      ((page)->virtual)
+#define __page_address(page)    (PAGE_OFFSET + (((page) - mem_map) << PAGE_SHIFT))
+#define pte_page(pte)           (mem_map+pte_pagenr(pte))
+
+/* only the pte's themselves need to point to physical DRAM (see above)
+ * the pagetable links are purely handled within the kernel SW and thus
+ * don't need the __pa and __va transformations.
+ */
+
+static inline unsigned long pmd_page(pmd_t pmd)
+{ return pmd_val(pmd) & PAGE_MASK; }
+
+static inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{ pmd_val(*pmdp) = _PAGE_TABLE | (unsigned long) ptep; }
+
+static inline void pmd_set_kernel(pmd_t * pmdp, pte_t * ptep)
+{ pmd_val(*pmdp) = _KERNPG_TABLE | (unsigned long) ptep; }
+
+/* to find an entry in a page-table-directory. */
+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+/* to find an entry in a page-table-directory */
+static inline pgd_t * pgd_offset(struct mm_struct * mm, unsigned long address)
+{
+	return mm->pgd + pgd_index(address);
+}
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level page table.. */
+static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+	return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */ 
+static inline pte_t * pte_offset(pmd_t * dir, unsigned long address)
+{
+	return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));
+}
+
+#define pte_ERROR(e) \
+        printk("%s:%d: bad pte %p(%08lx).\n", __FILE__, __LINE__, &(e), pte_val(e))
+#define pmd_ERROR(e) \
+        printk("%s:%d: bad pmd %p(%08lx).\n", __FILE__, __LINE__, &(e), pmd_val(e))
+#define pgd_ERROR(e) \
+        printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), pgd_val(e))
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; /* defined in head.S */
+
+/*
+ * CRIS doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ * 
+ * Actually I am not sure on what this could be used for.
+ */
+static inline void update_mmu_cache(struct vm_area_struct * vma,
+	unsigned long address, pte_t pte)
+{
+}
+
+/* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */
+/* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */
+
+#define SWP_TYPE(x)                     (((x).val >> 5) & 0x7f)
+#define SWP_OFFSET(x)                   ((x).val >> 12)
+#define SWP_ENTRY(type, offset)         ((swp_entry_t) { ((type) << 5) | ((offset) << 12) })
+#define pte_to_swp_entry(pte)           ((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)             ((pte_t) { (x).val })
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page)          (0)
+#define kern_addr_valid(addr)   (1)
+
+#include <asm-generic/pgtable.h>
+
+#endif /* _CRIS_PGTABLE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/poll.h linux/include/asm-cris/poll.h
--- v2.4.1/linux/include/asm-cris/poll.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/poll.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,24 @@
+#ifndef __ASM_CRIS_POLL_H
+#define __ASM_CRIS_POLL_H
+
+/* taken from asm-alpha */
+
+#define POLLIN		1
+#define POLLPRI		2
+#define POLLOUT		4
+#define POLLERR		8
+#define POLLHUP		16
+#define POLLNVAL	32
+#define POLLRDNORM	64
+#define POLLRDBAND	128
+#define POLLWRNORM	256
+#define POLLWRBAND	512
+#define POLLMSG		1024
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/posix_types.h linux/include/asm-cris/posix_types.h
--- v2.4.1/linux/include/asm-cris/posix_types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/posix_types.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,72 @@
+/* $Id: posix_types.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+/* We cheat a bit and use our C-coded bitops functions from asm/bitops.h */
+/* I guess we should write these in assembler because they are used often. */
+
+#ifndef __ARCH_CRIS_POSIX_TYPES_H
+#define __ARCH_CRIS_POSIX_TYPES_H
+
+#include <asm/bitops.h>
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short	__kernel_dev_t;
+typedef unsigned long	__kernel_ino_t;
+typedef unsigned short	__kernel_mode_t;
+typedef unsigned short	__kernel_nlink_t;
+typedef long		__kernel_off_t;
+typedef int		__kernel_pid_t;
+typedef unsigned short  __kernel_ipc_pid_t;
+typedef unsigned short	__kernel_uid_t;
+typedef unsigned short	__kernel_gid_t;
+typedef unsigned long	__kernel_size_t;
+typedef long		__kernel_ssize_t;
+typedef int		__kernel_ptrdiff_t;
+typedef long		__kernel_time_t;
+typedef long            __kernel_suseconds_t;
+typedef long		__kernel_clock_t;
+typedef int		__kernel_daddr_t;
+typedef char *		__kernel_caddr_t;
+typedef unsigned short  __kernel_uid16_t;
+typedef unsigned short  __kernel_gid16_t;
+typedef unsigned int    __kernel_uid32_t;
+typedef unsigned int    __kernel_gid32_t;
+
+typedef unsigned short  __kernel_old_uid_t;
+typedef unsigned short  __kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long	__kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+	int	val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+	int	__val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+/* should this ifdef be here ?  */
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef	__FD_SET
+#define __FD_SET(fd,fdsetp) set_bit(fd, (void *)(fdsetp))
+
+#undef	__FD_CLR
+#define __FD_CLR(fd,fdsetp) clear_bit(fd, (void *)(fdsetp))
+
+#undef	__FD_ISSET
+#define __FD_ISSET(fd,fdsetp) test_bit(fd, (void *)(fdsetp))
+
+#undef	__FD_ZERO
+#define __FD_ZERO(fdsetp) memset((void *)(fdsetp), 0, __FDSET_LONGS << 2)
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif /* __ARCH_CRIS_POSIX_TYPES_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/processor.h linux/include/asm-cris/processor.h
--- v2.4.1/linux/include/asm-cris/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/processor.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,147 @@
+/*
+ * include/asm-cris/processor.h
+ *
+ * Copyright (C) 2000 Axis Communications AB
+ *
+ * Authors:         Bjorn Wesen        Initial version
+ *
+ */
+
+#ifndef __ASM_CRIS_PROCESSOR_H
+#define __ASM_CRIS_PROCESSOR_H
+
+#include <linux/config.h>
+#include <asm/system.h>
+#include <asm/ptrace.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l;})
+
+/* CRIS has no problems with write protection */
+
+#define wp_works_ok 1
+
+/*
+ * User space process size. This is hardcoded into a few places,
+ * so don't change it unless you know what you are doing.
+ */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define TASK_SIZE       (0x50000000UL)   /* 1.25 GB */
+#else
+#define TASK_SIZE       (0xB0000000UL)   /* 2.75 GB */
+#endif
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE      (TASK_SIZE / 3)
+
+/* CRIS thread_struct. this really has nothing to do with the processor itself, since
+ * CRIS does not do any hardware task-switching, but it's here for legacy reasons.
+ * The thread_struct here is used when task-switching using _resume defined in entry.S.
+ * The offsets here are hardcoded into _resume - if you change this struct, you need to
+ * change them as well!!!
+*/
+
+struct thread_struct {
+	unsigned long ksp;     /* kernel stack pointer */
+	unsigned long usp;     /* user stack pointer */
+	unsigned long esp0;    /* points to start of saved stack frame, set in entry.S */  
+	unsigned long dccr;    /* saved flag register */
+};
+
+/* saved stack-frame upon syscall entry, points to registers */
+
+#define current_regs() (current->thread.esp0)
+
+/* this lives in process.c */
+asmlinkage void set_esp0(unsigned long ssp);
+
+/* INIT_MMAP is the kernels map of memory, between KSEG_C and KSEG_D */
+
+#ifdef CONFIG_CRIS_LOW_MAP
+#define INIT_MMAP { &init_mm, KSEG_6, KSEG_7, NULL, PAGE_SHARED, \
+			     VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+#else
+#define INIT_MMAP { &init_mm, KSEG_C, KSEG_D, NULL, PAGE_SHARED, \
+			     VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
+#endif
+
+#define INIT_THREAD  { \
+   0, 0, 0, 0x20 }  /* ccr = int enable, nothing else */
+
+/* TODO: REMOVE */
+#define alloc_kernel_stack()    __get_free_page(GFP_KERNEL)
+#define free_kernel_stack(page) free_page((page))
+
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* give the thread a program location
+ * set user-mode (The 'U' flag (User mode flag) is CCR/DCCR bit 8) 
+ * switch user-stackpointer
+ */
+
+#define start_thread(regs, ip, usp) do { \
+	set_fs(USER_DS);      \
+	regs->irp = ip;       \
+	regs->dccr |= 1 << 8; \
+	wrusp(usp);           \
+} while(0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define KSTK_EIP(tsk)   \
+    ({                  \
+        unsigned long eip = 0;   \
+        if ((tsk)->thread.esp0 > PAGE_SIZE && \
+            VALID_PAGE(virt_to_page((tsk)->thread.esp0))) \
+              eip = ((struct pt_regs *) (tsk)->thread.esp0)->irp; \
+        eip; })
+
+#define KSTK_ESP(tsk)   ((tsk) == current ? rdusp() : (tsk)->thread.usp)
+
+#define copy_segments(tsk, mm)          do { } while (0)
+#define release_segments(mm)            do { } while (0)
+#define forget_segments()               do { } while (0)
+ 
+/*
+ * Free current thread data structures etc..
+ */
+
+static inline void exit_thread(void)
+{
+}
+
+/* Free all resources held by a thread. */
+static inline void release_thread(struct task_struct *dead_task)
+{
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+	return (unsigned long)((struct pt_regs *)t->esp0)->irp;
+}
+
+/* THREAD_SIZE is the size of the task_struct/kernel_stack combo.
+ * normally, the stack is found by doing something like p + THREAD_SIZE
+ * in CRIS, a page is 8192 bytes, which seems like a sane size
+ */
+
+#define THREAD_SIZE     PAGE_SIZE
+#define KERNEL_STACK_SIZE PAGE_SIZE
+
+#define alloc_task_struct()  ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
+#define free_task_struct(p)  free_pages((unsigned long) (p), 1)
+#define get_task_struct(tsk) atomic_inc(&virt_to_page(tsk)->count)
+
+#define init_task       (init_task_union.task)
+#define init_stack      (init_task_union.stack)
+
+#endif /* __ASM_CRIS_PROCESSOR_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ptrace.h linux/include/asm-cris/ptrace.h
--- v2.4.1/linux/include/asm-cris/ptrace.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ptrace.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,99 @@
+#ifndef _CRIS_PTRACE_H
+#define _CRIS_PTRACE_H
+
+/* Register numbers in the ptrace system call interface */
+
+#define PT_FRAMETYPE 0
+#define PT_ORIG_R10  1
+#define PT_R13       2
+#define PT_R12       3
+#define PT_R11       4
+#define PT_R10       5
+#define PT_R9        6
+#define PT_R8        7
+#define PT_R7        8
+#define PT_R6        9
+#define PT_R5        10
+#define PT_R4        11
+#define PT_R3        12
+#define PT_R2        13
+#define PT_R1        14
+#define PT_R0        15
+#define PT_MOF       16
+#define PT_DCCR      17
+#define PT_SRP       18
+#define PT_IRP       19
+#define PT_MAX       19
+
+#define PT_USP       42    /* special case - USP is not in the pt_regs */
+
+/* Frame types */
+
+#define CRIS_FRAME_NORMAL   0  /* normal frame like pt_regs struct */
+#define CRIS_FRAME_BUSFAULT 1  /* SBFS frame of 4 longwords on top, including irp */
+#define CRIS_FRAME_FIXUP    2  /* SBFS frame which should do a normal return, not RBF */
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS            12
+#define PTRACE_SETREGS            13
+
+/* pt_regs not only specifices the format in the user-struct during
+ * ptrace but is also the frame format used in the kernel prologue/epilogues 
+ * themselves
+ */
+
+struct pt_regs {
+	unsigned long frametype;  /* type of stackframe */
+	unsigned long orig_r10;
+	/* pushed by movem r13, [sp] in SAVE_ALL, movem pushes backwards */
+	unsigned long r13; /* 8 */
+	unsigned long r12; /* 12 */
+	unsigned long r11; /* 16 */
+	unsigned long r10; /* 20 */
+	unsigned long r9;
+	unsigned long r8;
+	unsigned long r7;
+	unsigned long r6;
+	unsigned long r5;
+	unsigned long r4;
+	unsigned long r3;
+	unsigned long r2;
+	unsigned long r1;
+	unsigned long r0;
+	unsigned long mof;
+	unsigned long dccr;
+	unsigned long srp;
+	unsigned long irp;
+};
+
+/* switch_stack is the extra stuff pushed onto the stack in _resume (entry.S) when
+   doing a context-switch. it is used (apart from in resume) when a new thread is made 
+   and we need to make _resume (which is starting it for the first time) realise what
+   is going on. 
+
+   actually, the use is very close to the thread struct (TSS) in that both the switch_stack
+   and the TSS are used to keep thread stuff when switching in _resume.
+*/
+
+struct switch_stack {
+	unsigned long r9;
+	unsigned long r8;
+	unsigned long r7;
+	unsigned long r6;
+	unsigned long r5;
+	unsigned long r4;
+	unsigned long r3;
+	unsigned long r2;
+	unsigned long r1;
+	unsigned long r0;
+	unsigned long return_ip; /* ip that _resume will return to */
+};
+
+#ifdef __KERNEL__
+/* bit 8 is user-mode flag */
+#define user_mode(regs) ((regs)->dccr & 0x100)
+#define instruction_pointer(regs) ((regs)->irp)
+extern void show_regs(struct pt_regs *);
+#endif
+
+#endif /* _CRIS_PTRACE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/resource.h linux/include/asm-cris/resource.h
--- v2.4.1/linux/include/asm-cris/resource.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/resource.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,47 @@
+#ifndef _CRIS_RESOURCE_H
+#define _CRIS_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NPROC	6		/* max number of processes */
+#define RLIMIT_NOFILE	7		/* max number of open files */
+#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
+#define RLIMIT_AS	9		/* address space limit */
+#define RLIMIT_LOCKS   10              /* maximum file locks held */
+
+#define RLIM_NLIMITS	11
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY	(~0UL)
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{      _STK_LIM, RLIM_INFINITY },		\
+	{             0, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{             0,             0 },		\
+	{      INR_OPEN,     INR_OPEN  },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },               \
+        { RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+}
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/rtc.h linux/include/asm-cris/rtc.h
--- v2.4.1/linux/include/asm-cris/rtc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/rtc.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,59 @@
+/* $Id: rtc.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef RTC_H
+#define RTC_H
+
+#include <linux/config.h>
+
+/* Dallas DS1302 clock/calendar register numbers */
+
+#define RTC_SECONDS 0
+#define RTC_MINUTES 1
+#define RTC_HOURS 2
+#define RTC_DAY_OF_MONTH 3
+#define RTC_MONTH 4
+#define RTC_WEEKDAY 5
+#define RTC_YEAR 6
+
+#ifdef CONFIG_DS1302
+#define CMOS_READ(x) ds1302_readreg(x)
+#define CMOS_WRITE(val,reg) ds1302_writereg(reg,val)
+#define RTC_INIT() ds1302_init()
+#else
+/* no RTC configured so we shouldn't try to access any */
+#define CMOS_READ(x) 42
+#define CMOS_WRITE(x,y)
+#define RTC_INIT() (-1)
+#endif
+
+/* conversions to and from the stupid RTC internal format */
+
+#define BCD_TO_BIN(x) x = (((x & 0xf0) >> 3) * 5 + (x & 0xf))
+#define BIN_TO_BCD(x) x = (x % 10) | ((x / 10) << 4) 
+
+/*
+ * The struct used to pass data via the following ioctl. Similar to the
+ * struct tm in <time.h>, but it needs to be here so that the kernel 
+ * source is self contained, allowing cross-compiles, etc. etc.
+ */
+
+struct rtc_time {
+	int tm_sec;
+	int tm_min;
+	int tm_hour;
+	int tm_mday;
+	int tm_mon;
+	int tm_year;
+	int tm_wday;
+	int tm_yday;
+	int tm_isdst;
+};
+
+/*
+ * ioctl calls that are permitted to the /dev/rtc interface
+ */
+
+#define RTC_RD_TIME	_IOR('p', 0x09, struct rtc_time) /* Read RTC time   */
+#define RTC_SET_TIME	_IOW('p', 0x0a, struct rtc_time) /* Set RTC time    */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/segment.h linux/include/asm-cris/segment.h
--- v2.4.1/linux/include/asm-cris/segment.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/segment.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,16 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+/* argh. really legacy. totally misnomed. */
+
+#define __KERNEL_CS	0x10
+#define __KERNEL_DS	0x18
+
+#define __USER_CS	0x23
+#define __USER_DS	0x2B
+
+typedef struct {
+  unsigned long seg;
+} mm_segment_t;
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/semaphore-helper.h linux/include/asm-cris/semaphore-helper.h
--- v2.4.1/linux/include/asm-cris/semaphore-helper.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/semaphore-helper.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,77 @@
+/* $Id: semaphore-helper.h,v 1.1 2000/07/13 16:52:42 bjornw Exp $
+ *
+ * SMP- and interrupt-safe semaphores helper functions. Generic versions, no
+ * optimizations whatsoever... 
+ *
+ */
+
+#ifndef _ASM_SEMAPHORE_HELPER_H
+#define _ASM_SEMAPHORE_HELPER_H
+
+#include <asm/atomic.h>
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ */
+static inline void wake_one_more(struct semaphore * sem)
+{
+	atomic_inc(&sem->waking);
+}
+
+#define read(a) ((a)->counter)
+#define inc(a) (((a)->counter)++)
+#define dec(a) (((a)->counter)--)
+
+#define count_inc(a) ((*(a))++)
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	save_and_cli(flags);
+	if (read(&sem->waking) > 0) {
+		dec(&sem->waking);
+		ret = 1;
+	}
+	restore_flags(flags);
+	return ret;
+}
+
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+						struct task_struct *tsk)
+{
+	int ret = 0;
+	unsigned long flags;
+
+	save_and_cli(flags);
+	if (read(&sem->waking) > 0) {
+		dec(&sem->waking);
+		ret = 1;
+	} else if (signal_pending(tsk)) {
+		count_inc(&sem->count);
+		ret = -EINTR;
+	}
+	restore_flags(flags);
+	return ret;
+}
+
+static inline int waking_non_zero_trylock(struct semaphore *sem)
+{
+        int ret = 1;
+	unsigned long flags;
+
+	save_and_cli(flags);
+	if (read(&sem->waking) <= 0)
+		count_inc(&sem->count);
+	else {
+		dec(&sem->waking);
+		ret = 0;
+	}
+	restore_flags(flags);
+	return ret;
+}
+
+#endif /* _ASM_SEMAPHORE_HELPER_H */
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/semaphore.h linux/include/asm-cris/semaphore.h
--- v2.4.1/linux/include/asm-cris/semaphore.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/semaphore.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,321 @@
+/* $Id: semaphore.h,v 1.2 2000/07/13 16:52:46 bjornw Exp $ */
+
+/* On the i386 these are coded in asm, perhaps we should as well. Later.. */
+
+#ifndef _CRIS_SEMAPHORE_H
+#define _CRIS_SEMAPHORE_H
+
+#define RW_LOCK_BIAS             0x01000000
+
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+
+/*
+ * CRIS semaphores, implemented in C-only so far. 
+ */
+
+int printk(const char *fmt, ...);
+
+struct semaphore {
+	int count; /* not atomic_t since we do the atomicity here already */
+	atomic_t waking;
+	wait_queue_head_t wait;
+#if WAITQUEUE_DEBUG
+	long __magic;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+# define __SEM_DEBUG_INIT(name)         , (long)&(name).__magic
+#else
+# define __SEM_DEBUG_INIT(name)
+#endif
+
+#define __SEMAPHORE_INITIALIZER(name,count)             \
+        { count, ATOMIC_INIT(0),          \
+          __WAIT_QUEUE_HEAD_INITIALIZER((name).wait)    \
+          __SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+        __SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+        struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+extern inline void sema_init(struct semaphore *sem, int val)
+{
+	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+        sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+        sema_init(sem, 0);
+}
+
+extern void __down(struct semaphore * sem);
+extern int __down_interruptible(struct semaphore * sem);
+extern int __down_trylock(struct semaphore * sem);
+extern void __up(struct semaphore * sem);
+
+/* notice - we probably can do cli/sti here instead of saving */
+
+extern inline void down(struct semaphore * sem)
+{
+	unsigned long flags;
+	int failed;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	/* atomically decrement the semaphores count, and if its negative, we wait */
+	save_flags(flags);
+	cli();
+	failed = --(sem->count) < 0;
+	restore_flags(flags);
+	if(failed) {
+		__down(sem);
+	}
+}
+
+/*
+ * This version waits in interruptible state so that the waiting
+ * process can be killed.  The down_interruptible routine
+ * returns negative for signalled and zero for semaphore acquired.
+ */
+
+extern inline int down_interruptible(struct semaphore * sem)
+{
+	unsigned long flags;
+	int failed;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	/* atomically decrement the semaphores count, and if its negative, we wait */
+	save_flags(flags);
+	cli();
+	failed = --(sem->count) < 0;
+	restore_flags(flags);
+	if(failed)
+		failed = __down_interruptible(sem);
+	return(failed);
+}
+
+extern inline int down_trylock(struct semaphore * sem)
+{
+	unsigned long flags;
+	int failed;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	save_flags(flags);
+	cli();
+	failed = --(sem->count) < 0;
+	restore_flags(flags);
+	if(failed)
+		failed = __down_trylock(sem);
+	return(failed);
+}
+
+/*
+ * Note! This is subtle. We jump to wake people up only if
+ * the semaphore was negative (== somebody was waiting on it).
+ * The default case (no contention) will result in NO
+ * jumps for both down() and up().
+ */
+extern inline void up(struct semaphore * sem)
+{  
+	unsigned long flags;
+	int wakeup;
+
+#if WAITQUEUE_DEBUG
+	CHECK_MAGIC(sem->__magic);
+#endif
+
+	/* atomically increment the semaphores count, and if it was negative, we wake people */
+	save_flags(flags);
+	cli();
+	wakeup = ++(sem->count) <= 0;
+	restore_flags(flags);
+	if(wakeup) {
+		__up(sem);
+	}
+}
+
+/* rw mutexes (should that be mutices? =) -- throw rw
+ * spinlocks and semaphores together, and this is what we
+ * end up with...
+ *
+ * The lock is initialized to BIAS.  This way, a writer
+ * subtracts BIAS ands gets 0 for the case of an uncontended
+ * lock.  Readers decrement by 1 and see a positive value
+ * when uncontended, negative if there are writers waiting
+ * (in which case it goes to sleep).
+ *
+ * In terms of fairness, this should result in the lock
+ * flopping back and forth between readers and writers
+ * under heavy use.
+ *
+ *              -ben
+ */
+
+struct rw_semaphore {
+        atomic_t                count;
+	/* bit 0 means read bias granted;
+	   bit 1 means write bias granted.  */
+        unsigned granted;
+        wait_queue_head_t       wait;
+        wait_queue_head_t       write_bias_wait;
+#if WAITQUEUE_DEBUG
+        long                    __magic;
+        atomic_t                readers;
+        atomic_t                writers;
+#endif
+};
+
+#if WAITQUEUE_DEBUG
+#define __RWSEM_DEBUG_INIT      , ATOMIC_INIT(0), ATOMIC_INIT(0)
+#else
+#define __RWSEM_DEBUG_INIT      /* */
+#endif
+
+#define __RWSEM_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+        __WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
+        __SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
+
+#define __DECLARE_RWSEM_GENERIC(name,count) \
+        struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
+
+extern inline void init_rwsem(struct rw_semaphore *sem)
+{
+        atomic_set(&sem->count, RW_LOCK_BIAS);
+        sem->granted = 0;
+        init_waitqueue_head(&sem->wait);
+        init_waitqueue_head(&sem->write_bias_wait);
+#if WAITQUEUE_DEBUG
+        sem->__magic = (long)&sem->__magic;
+        atomic_set(&sem->readers, 0);
+        atomic_set(&sem->writers, 0);
+#endif
+}
+
+/* The expensive part is outlined.  */
+extern void __down_read(struct rw_semaphore *sem, int count);
+extern void __down_write(struct rw_semaphore *sem, int count);
+extern void __rwsem_wake(struct rw_semaphore *sem, unsigned long readers);
+
+extern inline void down_read(struct rw_semaphore *sem)
+{
+        int count;
+
+#if WAITQUEUE_DEBUG
+        CHECK_MAGIC(sem->__magic);
+#endif
+
+        count = atomic_dec_return(&sem->count);
+        if (count < 0) {
+                __down_read(sem, count);
+        }
+        mb();
+
+#if WAITQUEUE_DEBUG
+        if (sem->granted & 2)
+                BUG();
+        if (atomic_read(&sem->writers))
+                BUG();
+        atomic_inc(&sem->readers);
+#endif
+}
+
+extern inline void down_write(struct rw_semaphore *sem)
+{
+        int count;
+
+#if WAITQUEUE_DEBUG
+        CHECK_MAGIC(sem->__magic);
+#endif
+
+        count = atomic_sub_return(RW_LOCK_BIAS, &sem->count);
+        if (count) {
+                __down_write(sem, count);
+        }
+        mb();
+
+#if WAITQUEUE_DEBUG
+        if (atomic_read(&sem->writers))
+                BUG();
+        if (atomic_read(&sem->readers))
+                BUG();
+        if (sem->granted & 3)
+                BUG();
+        atomic_inc(&sem->writers);
+#endif
+}
+
+/* When a reader does a release, the only significant case is when
+   there was a writer waiting, and we've bumped the count to 0: we must
+   wake the writer up.  */
+
+extern inline void up_read(struct rw_semaphore *sem)
+{
+#if WAITQUEUE_DEBUG
+        CHECK_MAGIC(sem->__magic);
+        if (sem->granted & 2)
+                BUG();
+        if (atomic_read(&sem->writers))
+                BUG();
+        atomic_dec(&sem->readers);
+#endif
+
+        mb();
+        if (atomic_inc_return(&sem->count) == 0)
+                __rwsem_wake(sem, 0);
+}
+
+/*
+ * Releasing the writer is easy -- just release it and wake up any sleepers.
+ */
+extern inline void up_write(struct rw_semaphore *sem)
+{
+        int count;
+
+#if WAITQUEUE_DEBUG
+        CHECK_MAGIC(sem->__magic);
+        if (sem->granted & 3)
+                BUG();
+        if (atomic_read(&sem->readers))
+                BUG();
+        if (atomic_read(&sem->writers) != 1)
+                BUG();
+        atomic_dec(&sem->writers);
+#endif
+
+        mb();
+        count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
+        if (count - RW_LOCK_BIAS < 0 && count >= 0) {
+                /* Only do the wake if we're no longer negative.  */
+                __rwsem_wake(sem, count);
+        }
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/sembuf.h linux/include/asm-cris/sembuf.h
--- v2.4.1/linux/include/asm-cris/sembuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/sembuf.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,25 @@
+#ifndef _CRIS_SEMBUF_H
+#define _CRIS_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for CRIS architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	__kernel_time_t	sem_otime;		/* last semop time */
+	unsigned long	__unused1;
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	__unused2;
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _CRIS_SEMBUF_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/setup.h linux/include/asm-cris/setup.h
--- v2.4.1/linux/include/asm-cris/setup.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/setup.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,405 @@
+/*
+** asm/setup.h -- Definition of the Linux/m68k boot information structure
+**
+** Copyright 1992 by Greg Harp
+**
+** 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.
+**
+** Created 09/29/92 by Greg Harp
+**
+** 5/2/94 Roman Hodek:
+**   Added bi_atari part of the machine dependent union bi_un; for now it
+**   contains just a model field to distinguish between TT and Falcon.
+** 26/7/96 Roman Zippel:
+**   Renamed to setup.h; added some useful macros to allow gcc some
+**   optimizations if possible.
+*/
+
+#ifndef _M68K_SETUP_H
+#define _M68K_SETUP_H
+
+#include <linux/config.h>
+
+#define CL_SIZE	(256)
+
+#if 0
+
+#include <asm/zorro.h>
+
+/*
+ * Amiga specific part of bootinfo structure.
+ */
+
+#define NUM_AUTO    16
+
+#ifndef __ASSEMBLY__
+
+#define AMIGAHW_DECLARE(name)	unsigned name : 1
+#define AMIGAHW_SET(name)	(boot_info.bi_amiga.hw_present.name = 1)
+#define AMIGAHW_PRESENT(name)	(boot_info.bi_amiga.hw_present.name)
+
+struct bi_Amiga {
+	int model;				/* Amiga Model (3000?) */
+	int num_autocon;			/* # of autoconfig devices found */
+	struct ConfigDev autocon[NUM_AUTO];	/* up to 16 autoconfig devices */
+#ifdef HACKER_KERNEL
+	void (*exit_func)(void);		/* addr of function to exit kernel */
+	unsigned long chip_addr;		/* start of chip memory (bytes) */
+#endif
+	unsigned long chip_size;		/* size of chip memory (bytes) */
+	unsigned char vblank;	 		/* VBLANK frequency */
+	unsigned char psfreq; 			/* power supply frequency */
+	unsigned long eclock; 			/* EClock frequency */
+	unsigned long chipset;			/* native chipset present */
+	struct {
+		/* video hardware */
+		AMIGAHW_DECLARE(AMI_VIDEO);	/* Amiga Video */
+		AMIGAHW_DECLARE(AMI_BLITTER);	/* Amiga Blitter */
+		AMIGAHW_DECLARE(AMBER_FF);	/* Amber Flicker Fixer */
+		/* sound hardware */
+		AMIGAHW_DECLARE(AMI_AUDIO);	/* Amiga Audio */
+		/* disk storage interfaces */
+		AMIGAHW_DECLARE(AMI_FLOPPY);	/* Amiga Floppy */
+		AMIGAHW_DECLARE(A3000_SCSI);	/* SCSI (wd33c93, A3000 alike) */
+		AMIGAHW_DECLARE(A4000_SCSI);	/* SCSI (ncr53c710, A4000T alike) */
+		AMIGAHW_DECLARE(A1200_IDE);	/* IDE (A1200 alike) */
+		AMIGAHW_DECLARE(A4000_IDE);	/* IDE (A4000 alike) */
+		AMIGAHW_DECLARE(CD_ROM);	/* CD ROM drive */
+		/* other I/O hardware */
+		AMIGAHW_DECLARE(AMI_KEYBOARD);	/* Amiga Keyboard */
+		AMIGAHW_DECLARE(AMI_MOUSE);	/* Amiga Mouse */
+		AMIGAHW_DECLARE(AMI_SERIAL);	/* Amiga Serial */
+		AMIGAHW_DECLARE(AMI_PARALLEL);	/* Amiga Parallel */
+		/* real time clocks */
+		AMIGAHW_DECLARE(A2000_CLK);	/* Hardware Clock (A2000 alike) */
+		AMIGAHW_DECLARE(A3000_CLK);	/* Hardware Clock (A3000 alike) */
+		/* supporting hardware */
+		AMIGAHW_DECLARE(CHIP_RAM);	/* Chip RAM */
+		AMIGAHW_DECLARE(PAULA);		/* Paula (8364) */
+		AMIGAHW_DECLARE(DENISE);	/* Denise (8362) */
+		AMIGAHW_DECLARE(DENISE_HR);	/* Denise (8373) */
+		AMIGAHW_DECLARE(LISA);		/* Lisa (8375) */
+		AMIGAHW_DECLARE(AGNUS_PAL);	/* Normal/Fat PAL Agnus (8367/8371) */
+		AMIGAHW_DECLARE(AGNUS_NTSC);	/* Normal/Fat NTSC Agnus (8361/8370) */
+		AMIGAHW_DECLARE(AGNUS_HR_PAL);	/* Fat Hires PAL Agnus (8372) */
+		AMIGAHW_DECLARE(AGNUS_HR_NTSC);	/* Fat Hires NTSC Agnus (8372) */
+		AMIGAHW_DECLARE(ALICE_PAL);	/* PAL Alice (8374) */
+		AMIGAHW_DECLARE(ALICE_NTSC);	/* NTSC Alice (8374) */
+		AMIGAHW_DECLARE(MAGIC_REKICK);	/* A3000 Magic Hard Rekick */
+		AMIGAHW_DECLARE(ZORRO);		/* Zorro AutoConfig */
+	} hw_present;
+};
+
+#else	/* __ASSEMBLY__ */
+ 
+BI_amiga_model		= BI_un
+BI_amiga_num_autcon	= BI_amiga_model+4
+BI_amiga_autocon	= BI_amiga_num_autcon+4
+#ifdef HACKER_KERNEL
+BI_amiga_exit_func	= BI_amiga_autocon+(CD_sizeof*NUM_AUTO)
+BI_amiga_chip_addr	= BI_amiga_exit_func+4
+BI_amiga_chip_size	= BI_amiga_chip_addr+4
+#else
+BI_amiga_chip_size	= BI_amiga_autocon+(CD_sizeof*NUM_AUTO)
+#endif
+BI_amiga_vblank		= BI_amiga_chip_size+4
+BI_amiga_psfreq		= BI_amiga_vblank+1
+BI_amiga_eclock		= BI_amiga_psfreq+1
+BI_amiga_chipset	= BI_amiga_eclock+4
+BI_amiga_hw_present	= BI_amiga_chipset+4
+
+#endif	/* __ASSEMBLY__ */
+
+/* Atari specific part of bootinfo */
+
+/*
+ * Define several Hardware-Chips for indication so that for the ATARI we do
+ * no longer decide whether it is a Falcon or other machine . It's just
+ * important what hardware the machine uses
+ */
+
+/* ++roman 08/08/95: rewritten from ORing constants to a C bitfield */
+
+#ifndef __ASSEMBLY__
+
+#define ATARIHW_DECLARE(name)	unsigned name : 1
+#define ATARIHW_SET(name)	(boot_info.bi_atari.hw_present.name = 1)
+#define ATARIHW_PRESENT(name)	(boot_info.bi_atari.hw_present.name)
+
+struct bi_Atari {
+	struct {
+		/* video hardware */
+		ATARIHW_DECLARE(STND_SHIFTER);	/* ST-Shifter - no base low ! */
+		ATARIHW_DECLARE(EXTD_SHIFTER);	/* STe-Shifter - 24 bit address */
+		ATARIHW_DECLARE(TT_SHIFTER);	/* TT-Shifter */
+		ATARIHW_DECLARE(VIDEL_SHIFTER);	/* Falcon-Shifter */
+		/* sound hardware */
+		ATARIHW_DECLARE(YM_2149);	/* Yamaha YM 2149 */
+		ATARIHW_DECLARE(PCM_8BIT);	/* PCM-Sound in STe-ATARI */
+		ATARIHW_DECLARE(CODEC);		/* CODEC Sound (Falcon) */
+		/* disk storage interfaces */
+		ATARIHW_DECLARE(TT_SCSI);	/* Directly mapped NCR5380 */
+		ATARIHW_DECLARE(ST_SCSI);	/* NCR5380 via ST-DMA (Falcon) */
+		ATARIHW_DECLARE(ACSI);		/* Standard ACSI like in STs */
+		ATARIHW_DECLARE(IDE);		/* IDE Interface */
+		ATARIHW_DECLARE(FDCSPEED);	/* 8/16 MHz switch for FDC */
+		/* other I/O hardware */
+		ATARIHW_DECLARE(ST_MFP);	/* The ST-MFP (there should
+						   be no Atari without
+						   it... but who knows?) */
+		ATARIHW_DECLARE(TT_MFP);	/* 2nd MFP */
+		ATARIHW_DECLARE(SCC);		/* Serial Communications Contr. */
+		ATARIHW_DECLARE(ST_ESCC);	/* SCC Z83230 in an ST */
+		ATARIHW_DECLARE(ANALOG_JOY);	/* Paddle Interface for STe
+						   and Falcon */
+		ATARIHW_DECLARE(MICROWIRE);	/* Microwire Interface */
+		/* DMA */
+		ATARIHW_DECLARE(STND_DMA);	/* 24 Bit limited ST-DMA */
+		ATARIHW_DECLARE(EXTD_DMA);	/* 32 Bit ST-DMA */
+		ATARIHW_DECLARE(SCSI_DMA);	/* DMA for the NCR5380 */
+		ATARIHW_DECLARE(SCC_DMA);	/* DMA for the SCC */
+		/* real time clocks */
+		ATARIHW_DECLARE(TT_CLK);	/* TT compatible clock chip */
+		ATARIHW_DECLARE(MSTE_CLK);	/* Mega ST(E) clock chip */
+		/* supporting hardware */
+		ATARIHW_DECLARE(SCU);		/* System Control Unit */
+		ATARIHW_DECLARE(BLITTER);	/* Blitter */
+		ATARIHW_DECLARE(VME);		/* VME Bus */
+	} hw_present;
+	unsigned long mch_cookie;		/* _MCH cookie from TOS */
+};
+
+/* mch_cookie values (upper word) */
+#define	ATARI_MCH_ST		0
+#define	ATARI_MCH_STE		1
+#define	ATARI_MCH_TT		2
+#define	ATARI_MCH_FALCON	3
+
+struct mem_info {
+	unsigned long addr;			/* physical address of memory chunk */
+	unsigned long size;			/* length of memory chunk (in bytes) */
+};
+
+#else	/* __ASSEMBLY__ */
+
+MI_addr		= 0
+MI_size		= MI_addr+4
+MI_sizeof	= MI_size+4
+
+#endif /* __ASSEMBLY__ */
+
+#define NUM_MEMINFO  4
+
+#define MACH_AMIGA   1
+#define MACH_ATARI   2
+#define MACH_MAC     3
+
+/*
+ * CPU and FPU types
+ */
+
+#define CPUB_68020 0
+#define CPUB_68030 1
+#define CPUB_68040 2
+#define CPUB_68060 3
+#define FPUB_68881 5
+#define FPUB_68882 6
+#define FPUB_68040 7				/* Internal FPU */
+#define FPUB_68060 8				/* Internal FPU */
+
+#define CPU_68020    (1<<CPUB_68020)
+#define CPU_68030    (1<<CPUB_68030)
+#define CPU_68040    (1<<CPUB_68040)
+#define CPU_68060    (1<<CPUB_68060)
+#define CPU_MASK     (31)
+#define FPU_68881    (1<<FPUB_68881)
+#define FPU_68882    (1<<FPUB_68882)
+#define FPU_68040    (1<<FPUB_68040)		/* Internal FPU */
+#define FPU_68060    (1<<FPUB_68060)		/* Internal FPU */
+#define FPU_MASK     (0xfe0)
+
+#define CL_SIZE      (256)
+
+/*
+ * machine type definitions
+ */
+
+#if !defined(CONFIG_AMIGA)
+#  define MACH_IS_AMIGA (0)
+#elif defined(CONFIG_ATARI) || defined(CONFIG_MAC)
+#  define MACH_IS_AMIGA (boot_info.machtype == MACH_AMIGA)
+#else
+#  define CONFIG_AMIGA_ONLY
+#  define MACH_IS_AMIGA (1)
+#  define MACH_TYPE (MACH_AMIGA)
+#endif
+
+#if !defined(CONFIG_ATARI)
+#  define MACH_IS_ATARI (0)
+#elif defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
+#  define MACH_IS_ATARI (boot_info.machtype == MACH_ATARI)
+#else
+#  define CONFIG_ATARI_ONLY
+#  define MACH_IS_ATARI (1)
+#  define MACH_TYPE (MACH_ATARI)
+#endif
+
+#if defined(CONFIG_MAC)
+#  error Currently no Mac support!
+#endif
+
+#ifndef MACH_TYPE
+#  define MACH_TYPE (boot_info.machtype)
+#endif
+
+/*
+ * cpu type definitions
+ */
+
+#if !defined(CONFIG_M68020)
+#  define CPU_IS_020 (0)
+#elif defined(CONFIG_M68030) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
+#  define CPU_IS_020 (boot_info.cputype & CPU_68020)
+#else
+#  define CONFIG_M68020_ONLY
+#  define CPU_IS_020 (1)
+#endif
+
+#if !defined(CONFIG_M68030)
+#  define CPU_IS_030 (0)
+#elif defined(CONFIG_M68020) || defined(CONFIG_M68040) || defined(CONFIG_M68060)
+#  define CPU_IS_030 (boot_info.cputype & CPU_68030)
+#else
+#  define CONFIG_M68030_ONLY
+#  define CPU_IS_030 (1)
+#endif
+
+#if !defined(CONFIG_M68040)
+#  define CPU_IS_040 (0)
+#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68060)
+#  define CPU_IS_040 (boot_info.cputype & CPU_68040)
+#else
+#  define CONFIG_M68040_ONLY
+#  define CPU_IS_040 (1)
+#endif
+
+#if !defined(CONFIG_M68060)
+#  define CPU_IS_060 (0)
+#elif defined(CONFIG_M68020) || defined(CONFIG_M68030) || defined(CONFIG_M68040)
+#  define CPU_IS_060 (boot_info.cputype & CPU_68060)
+#else
+#  define CONFIG_M68060_ONLY
+#  define CPU_IS_060 (1)
+#endif
+
+#if !defined(CONFIG_M68020) && !defined(CONFIG_M68030)
+#  define CPU_IS_020_OR_030 (0)
+#else
+#  define CONFIG_M68020_OR_M68030
+#  if defined(CONFIG_M68040) || defined(CONFIG_M68060)
+#    define CPU_IS_020_OR_030 (!m68k_is040or060)
+#  else
+#    define CONFIG_M68020_OR_M68030_ONLY
+#    define CPU_IS_020_OR_030 (1)
+#  endif
+#endif
+
+#if !defined(CONFIG_M68040) && !defined(CONFIG_M68060)
+#  define CPU_IS_040_OR_060 (0)
+#else
+#  define CONFIG_M68040_OR_M68060
+#  if defined(CONFIG_M68020) || defined(CONFIG_M68030)
+#    define CPU_IS_040_OR_060 (m68k_is040or060)
+#  else
+#    define CONFIG_M68040_OR_M68060_ONLY
+#    define CPU_IS_040_OR_060 (1)
+#  endif
+#endif
+
+#define CPU_TYPE (boot_info.cputype)
+
+#ifndef __ASSEMBLY__
+#ifdef __KERNEL__
+	/*
+	 * m68k_is040or060 is != 0 for a '040 or higher;
+	 * used numbers are 4 for 68040 and 6 for 68060.
+	 */
+
+extern int m68k_is040or060;
+#endif
+
+struct bootinfo {
+	unsigned long machtype;			/* machine type */
+	unsigned long cputype;			/* system CPU & FPU */
+	struct mem_info memory[NUM_MEMINFO];	/* memory description */
+	int num_memory;				/* # of memory blocks found */
+	unsigned long ramdisk_size;		/* ramdisk size in 1024 byte blocks */
+	unsigned long ramdisk_addr;		/* address of the ram disk in mem */
+	char command_line[CL_SIZE];		/* kernel command line parameters */
+	union {
+		struct bi_Amiga bi_ami; 	/* Amiga specific information */
+		struct bi_Atari bi_ata; 	/* Atari specific information */
+	} bi_un;
+};
+#define bi_amiga bi_un.bi_ami
+#define bi_atari bi_un.bi_ata
+#define bi_mac	 bi_un.bi_mac
+
+extern struct bootinfo
+    boot_info;
+
+#else	/* __ASSEMBLY__ */
+
+BI_machtype	= 0
+BI_cputype	= BI_machtype+4
+BI_memory	= BI_cputype+4
+BI_num_memory	= BI_memory+(MI_sizeof*NUM_MEMINFO)
+BI_ramdisk_size	= BI_num_memory+4
+BI_ramdisk_addr	= BI_ramdisk_size+4
+BI_command_line	= BI_ramdisk_addr+4
+BI_un		= BI_command_line+CL_SIZE
+
+#endif /* __ASSEMBLY__ */
+
+
+/*
+ * Stuff for bootinfo interface versioning
+ *
+ * At the start of kernel code, a 'struct bootversion' is located. bootstrap
+ * checks for a matching version of the interface before booting a kernel, to
+ * avoid user confusion if kernel and bootstrap don't work together :-)
+ *
+ * If incompatible changes are made to the bootinfo interface, the major
+ * number below should be stepped (and the minor reset to 0) for the
+ * appropriate machine. If a change is backward-compatible, the minor should
+ * be stepped. "Backwards-compatible" means that booting will work, but
+ * certain features may not.
+ */
+
+#define BOOTINFOV_MAGIC			0x4249561A	/* 'BIV^Z' */
+#define MK_BI_VERSION(major,minor)	(((major)<<16)+(minor))
+#define BI_VERSION_MAJOR(v)		(((v) >> 16) & 0xffff)
+#define BI_VERSION_MINOR(v)		((v) & 0xffff)
+
+#ifndef __ASSEMBLY__
+
+struct bootversion {
+	unsigned short branch;
+	unsigned long magic;
+	struct {
+		unsigned long machtype;
+		unsigned long version;
+	} machversions[0];
+};
+
+#endif /* __ASSEMBLY__ */
+
+#define AMIGA_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
+#define ATARI_BOOTI_VERSION    MK_BI_VERSION( 1, 0 )
+
+#endif
+
+
+#endif /* _M68K_SETUP_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/shmbuf.h linux/include/asm-cris/shmbuf.h
--- v2.4.1/linux/include/asm-cris/shmbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/shmbuf.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,42 @@
+#ifndef _CRIS_SHMBUF_H
+#define _CRIS_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for CRIS architecture (same as for i386)
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 64-bit time_t to solve y2038 problem
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	unsigned long		__unused1;
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	unsigned long		__unused2;
+	__kernel_time_t		shm_ctime;	/* last change time */
+	unsigned long		__unused3;
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused4;
+	unsigned long		__unused5;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _CRIS_SHMBUF_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/shmparam.h linux/include/asm-cris/shmparam.h
--- v2.4.1/linux/include/asm-cris/shmparam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/shmparam.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,8 @@
+#ifndef _ASM_CRIS_SHMPARAM_H
+#define _ASM_CRIS_SHMPARAM_H
+
+/* same as asm-i386/ version.. */
+
+#define	SHMLBA PAGE_SIZE		 /* attach addr a multiple of this */
+
+#endif /* _ASM_CRIS_SHMPARAM_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/sigcontext.h linux/include/asm-cris/sigcontext.h
--- v2.4.1/linux/include/asm-cris/sigcontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/sigcontext.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,24 @@
+/* $Id: sigcontext.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef _ASM_CRIS_SIGCONTEXT_H
+#define _ASM_CRIS_SIGCONTEXT_H
+
+#include <asm/ptrace.h>
+
+/* This struct is saved by setup_frame in signal.c, to keep the current context while
+   a signal handler is executed. It's restored by sys_sigreturn.
+   
+   To keep things simple, we use pt_regs here even though normally you just specify
+   the list of regs to save. Then we can use copy_from_user on the entire regs instead
+   of a bunch of get_user's as well...
+
+*/
+
+struct sigcontext {
+	struct pt_regs regs;  /* needs to be first */
+	unsigned long oldmask;
+	unsigned long usp;    /* usp before stacking this gunk on it */
+};
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/siginfo.h linux/include/asm-cris/siginfo.h
--- v2.4.1/linux/include/asm-cris/siginfo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/siginfo.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,232 @@
+#ifndef _CRIS_SIGINFO_H
+#define _CRIS_SIGINFO_H
+
+#include <linux/types.h>
+
+/* This is copied from asm-m68k/siginfo.h.  */
+
+typedef union sigval {
+	int sival_int;
+	void *sival_ptr;
+} sigval_t;
+
+#define SI_MAX_SIZE	128
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			unsigned int _timer1;
+			unsigned int _timer2;
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+			sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			pid_t _pid;		/* which child */
+			uid_t _uid;		/* sender's uid */
+			int _status;		/* exit code */
+			clock_t _utime;
+			clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			void *_addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid		_sifields._kill._pid
+#define si_uid		_sifields._kill._uid
+#define si_status	_sifields._sigchld._status
+#define si_utime	_sifields._sigchld._utime
+#define si_stime	_sifields._sigchld._stime
+#define si_value	_sifields._rt._sigval
+#define si_int		_sifields._rt._sigval.sival_int
+#define si_ptr		_sifields._rt._sigval.sival_ptr
+#define si_addr		_sifields._sigfault._addr
+#define si_band		_sifields._sigpoll._band
+#define si_fd		_sifields._sigpoll._fd
+
+#ifdef __KERNEL__
+#define __SI_MASK	0xffff0000
+#define __SI_KILL	(0 << 16)
+#define __SI_TIMER	(1 << 16)
+#define __SI_POLL	(2 << 16)
+#define __SI_FAULT	(3 << 16)
+#define __SI_CHLD	(4 << 16)
+#define __SI_RT		(5 << 16)
+#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#else
+#define __SI_KILL	0
+#define __SI_TIMER	0
+#define __SI_POLL	0
+#define __SI_FAULT	0
+#define __SI_CHLD	0
+#define __SI_RT		0
+#define __SI_CODE(T,N)	(N)
+#endif
+
+/*
+ * si_code values
+ * Digital reserves positive values for kernel-generated signals.
+ */
+#define SI_USER		0		/* sent by kill, sigsend, raise */
+#define SI_KERNEL	0x80		/* sent by the kernel from somewhere */
+#define SI_QUEUE	-1		/* sent by sigqueue */
+#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */
+#define SI_MESGQ	-3		/* sent by real time mesq state change */
+#define SI_ASYNCIO	-4		/* sent by AIO completion */
+#define SI_SIGIO	-5		/* sent by queued SIGIO */
+
+#define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
+#define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
+
+/*
+ * SIGILL si_codes
+ */
+#define ILL_ILLOPC	(__SI_FAULT|1)	/* illegal opcode */
+#define ILL_ILLOPN	(__SI_FAULT|2)	/* illegal operand */
+#define ILL_ILLADR	(__SI_FAULT|3)	/* illegal addressing mode */
+#define ILL_ILLTRP	(__SI_FAULT|4)	/* illegal trap */
+#define ILL_PRVOPC	(__SI_FAULT|5)	/* privileged opcode */
+#define ILL_PRVREG	(__SI_FAULT|6)	/* privileged register */
+#define ILL_COPROC	(__SI_FAULT|7)	/* coprocessor error */
+#define ILL_BADSTK	(__SI_FAULT|8)	/* internal stack error */
+#define NSIGILL		8
+
+/*
+ * SIGFPE si_codes
+ */
+#define FPE_INTDIV	(__SI_FAULT|1)	/* integer divide by zero */
+#define FPE_INTOVF	(__SI_FAULT|2)	/* integer overflow */
+#define FPE_FLTDIV	(__SI_FAULT|3)	/* floating point divide by zero */
+#define FPE_FLTOVF	(__SI_FAULT|4)	/* floating point overflow */
+#define FPE_FLTUND	(__SI_FAULT|5)	/* floating point underflow */
+#define FPE_FLTRES	(__SI_FAULT|6)	/* floating point inexact result */
+#define FPE_FLTINV	(__SI_FAULT|7)	/* floating point invalid operation */
+#define FPE_FLTSUB	(__SI_FAULT|8)	/* subscript out of range */
+#define NSIGFPE		8
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_MAPERR	(__SI_FAULT|1)	/* address not mapped to object */
+#define SEGV_ACCERR	(__SI_FAULT|2)	/* invalid permissions for mapped object */
+#define NSIGSEGV	2
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_ADRALN	(__SI_FAULT|1)	/* invalid address alignment */
+#define BUS_ADRERR	(__SI_FAULT|2)	/* non-existant physical address */
+#define BUS_OBJERR	(__SI_FAULT|3)	/* object specific hardware error */
+#define NSIGBUS		3
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRKPT	(__SI_FAULT|1)	/* process breakpoint */
+#define TRAP_TRACE	(__SI_FAULT|2)	/* process trace trap */
+#define NSIGTRAP	2
+
+/*
+ * SIGCHLD si_codes
+ */
+#define CLD_EXITED	(__SI_CHLD|1)	/* child has exited */
+#define CLD_KILLED	(__SI_CHLD|2)	/* child was killed */
+#define CLD_DUMPED	(__SI_CHLD|3)	/* child terminated abnormally */
+#define CLD_TRAPPED	(__SI_CHLD|4)	/* traced child has trapped */
+#define CLD_STOPPED	(__SI_CHLD|5)	/* child has stopped */
+#define CLD_CONTINUED	(__SI_CHLD|6)	/* stopped child has continued */
+#define NSIGCHLD	6
+
+/*
+ * SIGPOLL si_codes
+ */
+#define POLL_IN		(__SI_POLL|1)	/* data input available */
+#define POLL_OUT	(__SI_POLL|2)	/* output buffers available */
+#define POLL_MSG	(__SI_POLL|3)	/* input message available */
+#define POLL_ERR	(__SI_POLL|4)	/* i/o error */
+#define POLL_PRI	(__SI_POLL|5)	/* high priority input available */
+#define POLL_HUP	(__SI_POLL|6)	/* device disconnected */
+#define NSIGPOLL	6
+
+/*
+ * sigevent definitions
+ * 
+ * It seems likely that SIGEV_THREAD will have to be handled from 
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+#define SIGEV_SIGNAL	0	/* notify via signal */
+#define SIGEV_NONE	1	/* other notification: meaningless */
+#define SIGEV_THREAD	2	/* deliver via thread creation */
+
+#define SIGEV_MAX_SIZE	64
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct sigevent {
+	sigval_t sigev_value;
+	int sigev_signo;
+	int sigev_notify;
+	union {
+		int _pad[SIGEV_PAD_SIZE];
+
+		struct {
+			void (*_function)(sigval_t);
+			void *_attribute;	/* really pthread_attr_t */
+		} _sigev_thread;
+	} _sigev_un;
+} sigevent_t;
+
+#define sigev_notify_function	_sigev_un._sigev_thread._function
+#define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+
+extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(siginfo_t));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+}
+
+extern int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from);
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/signal.h linux/include/asm-cris/signal.h
--- v2.4.1/linux/include/asm-cris/signal.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/signal.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,187 @@
+#ifndef _ASM_CRIS_SIGNAL_H
+#define _ASM_CRIS_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+#define _NSIG		64
+#define _NSIG_BPW	32
+#define _NSIG_WORDS	(_NSIG / _NSIG_BPW)
+
+typedef unsigned long old_sigset_t;		/* at least 32 bits */
+
+typedef struct {
+	unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG		32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP		 1
+#define SIGINT		 2
+#define SIGQUIT		 3
+#define SIGILL		 4
+#define SIGTRAP		 5
+#define SIGABRT		 6
+#define SIGIOT		 6
+#define SIGBUS		 7
+#define SIGFPE		 8
+#define SIGKILL		 9
+#define SIGUSR1		10
+#define SIGSEGV		11
+#define SIGUSR2		12
+#define SIGPIPE		13
+#define SIGALRM		14
+#define SIGTERM		15
+#define SIGSTKFLT	16
+#define SIGCHLD		17
+#define SIGCONT		18
+#define SIGSTOP		19
+#define SIGTSTP		20
+#define SIGTTIN		21
+#define SIGTTOU		22
+#define SIGURG		23
+#define SIGXCPU		24
+#define SIGXFSZ		25
+#define SIGVTALRM	26
+#define SIGPROF		27
+#define SIGWINCH	28
+#define SIGIO		29
+#define SIGPOLL		SIGIO
+/*
+#define SIGLOST		29
+*/
+#define SIGPWR		30
+#define SIGSYS          31
+#define	SIGUNUSED	31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN        32
+#define SIGRTMAX        (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+
+#define SA_NOCLDSTOP	0x00000001
+#define SA_NOCLDWAIT	0x00000002 /* not supported yet */
+#define SA_SIGINFO	0x00000004
+#define SA_ONSTACK	0x08000000
+#define SA_RESTART	0x10000000
+#define SA_NODEFER	0x40000000
+#define SA_RESETHAND	0x80000000
+
+#define SA_NOMASK	SA_NODEFER
+#define SA_ONESHOT	SA_RESETHAND
+#define SA_INTERRUPT	0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER	0x04000000
+
+/* 
+ * sigaltstack controls
+ */
+#define SS_ONSTACK	1
+#define SS_DISABLE	2
+
+#define MINSIGSTKSZ	2048
+#define SIGSTKSZ	8192
+
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support
+ */
+#define SA_PROBE		SA_ONESHOT
+#define SA_SAMPLE_RANDOM	SA_RESTART
+#define SA_SHIRQ		0x04000000
+#endif
+
+#define SIG_BLOCK          0	/* for blocking signals */
+#define SIG_UNBLOCK        1	/* for unblocking signals */
+#define SIG_SETMASK        2	/* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL	((__sighandler_t)0)	/* default signal handling */
+#define SIG_IGN	((__sighandler_t)1)	/* ignore signal */
+#define SIG_ERR	((__sighandler_t)-1)	/* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+	__sighandler_t sa_handler;
+	old_sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+struct sigaction {
+	__sighandler_t sa_handler;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+	sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+struct k_sigaction {
+	struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+	union {
+	  __sighandler_t _sa_handler;
+	  void (*_sa_sigaction)(int, struct siginfo *, void *);
+	} _u;
+	sigset_t sa_mask;
+	unsigned long sa_flags;
+	void (*sa_restorer)(void);
+};
+
+#define sa_handler	_u._sa_handler
+#define sa_sigaction	_u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+	void *ss_sp;
+	int ss_flags;
+	size_t ss_size;
+} stack_t;
+
+#ifdef __KERNEL__
+#include <asm/sigcontext.h>
+
+/* here we could define asm-optimized sigaddset, sigdelset etc. operations. 
+ * if we don't, generic ones are used from linux/signal.h
+ */
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/smp.h linux/include/asm-cris/smp.h
--- v2.4.1/linux/include/asm-cris/smp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/smp.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,4 @@
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/smp_lock.h linux/include/asm-cris/smp_lock.h
--- v2.4.1/linux/include/asm-cris/smp_lock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/smp_lock.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,73 @@
+#ifndef __CRIS_SMPLOCK_H
+#define __CRIS_SMPLOCK_H
+
+#include <linux/config.h>
+
+#ifdef CONFIG_SMP
+
+#error "SMP is not supported for CRIS"
+
+/*
+ *	Locking the kernel 
+ */
+ 
+extern __inline void lock_kernel(void)
+{
+	unsigned long flags;
+	int proc = smp_processor_id();
+
+	save_flags(flags);
+	cli();
+	/* set_bit works atomic in SMP machines */
+	while(set_bit(0, (void *)&kernel_flag)) 
+	{
+		/*
+		 *	We just start another level if we have the lock 
+		 */
+		if (proc == active_kernel_processor)
+			break;
+		do 
+		{
+#ifdef __SMP_PROF__		
+			smp_spins[smp_processor_id()]++;
+#endif			
+			/*
+			 *	Doing test_bit here doesn't lock the bus 
+			 */
+			if (test_bit(proc, (void *)&smp_invalidate_needed))
+				if (clear_bit(proc, (void *)&smp_invalidate_needed))
+					local_flush_tlb();
+		}
+		while(test_bit(0, (void *)&kernel_flag));
+	}
+	/* 
+	 *	We got the lock, so tell the world we are here and increment
+	 *	the level counter 
+	 */
+	active_kernel_processor = proc;
+	kernel_counter++;
+	restore_flags(flags);
+}
+
+extern __inline void unlock_kernel(void)
+{
+	unsigned long flags;
+	save_flags(flags);
+	cli();
+	/*
+	 *	If it's the last level we have in the kernel, then
+	 *	free the lock 
+	 */
+	if (kernel_counter == 0)
+		panic("Kernel counter wrong.\n"); /* FIXME: Why is kernel_counter sometimes 0 here? */
+	
+	if(! --kernel_counter) 
+	{
+		active_kernel_processor = NO_PROC_ID;
+		clear_bit(0, (void *)&kernel_flag);
+	}
+	restore_flags(flags);
+}
+
+#endif
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/smplock.h linux/include/asm-cris/smplock.h
--- v2.4.1/linux/include/asm-cris/smplock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/smplock.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,25 @@
+#ifndef __ASM_CRIS_SMPLOCK_H
+#define __ASM_CRIS_SMPLOCK_H
+
+/*
+ * 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.
+ */
+
+#include <linux/config.h>
+
+#ifndef CONFIG_SMP
+
+#define lock_kernel()                           do { } while(0)
+#define unlock_kernel()                         do { } while(0)
+#define release_kernel_lock(task, cpu, depth)   ((depth) = 1)
+#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
+
+#else
+
+#error "We do not support SMP on CRIS"
+
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/socket.h linux/include/asm-cris/socket.h
--- v2.4.1/linux/include/asm-cris/socket.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/socket.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,64 @@
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+/* almost the same as asm-i386/socket.h */
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME		28
+#define SO_TIMESTAMP           29
+#define SCM_TIMESTAMP          SO_TIMESTAMP
+
+#if defined(__KERNEL__)
+/* Socket types. */
+#define SOCK_STREAM     1               /* stream (connection) socket   */
+#define SOCK_DGRAM      2               /* datagram (conn.less) socket  */
+#define SOCK_RAW        3               /* raw socket                   */
+#define SOCK_RDM        4               /* reliably-delivered message   */
+#define SOCK_SEQPACKET  5               /* sequential packet socket     */
+#define SOCK_PACKET     10              /* linux specific way of        */
+                                        /* getting packets at the dev   */
+                                        /* level.  For writing rarp and */
+                                        /* other similar things on the  */
+                                        /* user level.                  */
+#endif
+
+#endif /* _ASM_SOCKET_H */
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/sockios.h linux/include/asm-cris/sockios.h
--- v2.4.1/linux/include/asm-cris/sockios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/sockios.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,12 @@
+#ifndef __ARCH_CRIS_SOCKIOS__
+#define __ARCH_CRIS_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/softirq.h linux/include/asm-cris/softirq.h
--- v2.4.1/linux/include/asm-cris/softirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/softirq.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,12 @@
+#ifndef __ASM_SOFTIRQ_H
+#define __ASM_SOFTIRQ_H
+
+#include <asm/atomic.h>
+#include <asm/hardirq.h>
+
+#define local_bh_disable()      (local_bh_count(smp_processor_id())++)
+#define local_bh_enable()       (local_bh_count(smp_processor_id())--)
+
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
+
+#endif	/* __ASM_SOFTIRQ_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/stat.h linux/include/asm-cris/stat.h
--- v2.4.1/linux/include/asm-cris/stat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/stat.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,79 @@
+#ifndef _CRIS_STAT_H
+#define _CRIS_STAT_H
+
+/* verbatim copy of i386 version */
+
+struct __old_kernel_stat {
+	unsigned short st_dev;
+	unsigned short st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned long  st_size;
+	unsigned long  st_atime;
+	unsigned long  st_mtime;
+	unsigned long  st_ctime;
+};
+
+struct stat {
+	unsigned short st_dev;
+	unsigned short __pad1;
+	unsigned long st_ino;
+	unsigned short st_mode;
+	unsigned short st_nlink;
+	unsigned short st_uid;
+	unsigned short st_gid;
+	unsigned short st_rdev;
+	unsigned short __pad2;
+	unsigned long  st_size;
+	unsigned long  st_blksize;
+	unsigned long  st_blocks;
+	unsigned long  st_atime;
+	unsigned long  __unused1;
+	unsigned long  st_mtime;
+	unsigned long  __unused2;
+	unsigned long  st_ctime;
+	unsigned long  __unused3;
+	unsigned long  __unused4;
+	unsigned long  __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct stat64 {
+	unsigned short	st_dev;
+	unsigned char	__pad0[10];
+
+	unsigned long	st_ino;
+	unsigned int	st_mode;
+	unsigned int	st_nlink;
+
+	unsigned long	st_uid;
+	unsigned long	st_gid;
+
+	unsigned short	st_rdev;
+	unsigned char	__pad3[10];
+
+	long long	st_size;
+	unsigned long	st_blksize;
+
+	unsigned long	st_blocks;	/* Number 512-byte blocks allocated. */
+	unsigned long	__pad4;		/* future possible st_blocks high bits */
+
+	unsigned long	st_atime;
+	unsigned long	__pad5;
+
+	unsigned long	st_mtime;
+	unsigned long	__pad6;
+
+	unsigned long	st_ctime;
+	unsigned long	__pad7;		/* will be high 32 bits of ctime someday */
+
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/statfs.h linux/include/asm-cris/statfs.h
--- v2.4.1/linux/include/asm-cris/statfs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/statfs.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,25 @@
+#ifndef _CRIS_STATFS_H
+#define _CRIS_STATFS_H
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t	fsid_t;
+
+#endif
+
+struct statfs {
+	long f_type;
+	long f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	__kernel_fsid_t f_fsid;
+	long f_namelen;
+	long f_spare[6];
+};
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/string.h linux/include/asm-cris/string.h
--- v2.4.1/linux/include/asm-cris/string.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/string.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,14 @@
+#ifndef _ASM_CRIS_STRING_H
+#define _ASM_CRIS_STRING_H
+
+/* the optimized memcpy is in arch/cris/lib/string.c */
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, size_t);
+
+/* New and improved.  In arch/cris/lib/memset.c */
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, size_t);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/sv_addr.agh linux/include/asm-cris/sv_addr.agh
--- v2.4.1/linux/include/asm-cris/sv_addr.agh	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/sv_addr.agh	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,7008 @@
+/*
+!* This file was automatically generated by /n/asic/bin/reg_macro_gen
+!* from the file `etrax_ng_regs.rd'.
+!* Editing within this file is thus not recommended,
+!* make the changes in `etrax_ng_regs.rd' instead.
+!*/
+
+
+/*
+!* Bus interface configuration registers
+!*/
+
+#define R_WAITSTATES (IO_TYPECAST_UDWORD 0xb0000000)
+#define R_WAITSTATES__pcs4_7_zw__BITNR 30
+#define R_WAITSTATES__pcs4_7_zw__WIDTH 2
+#define R_WAITSTATES__pcs4_7_ew__BITNR 28
+#define R_WAITSTATES__pcs4_7_ew__WIDTH 2
+#define R_WAITSTATES__pcs4_7_lw__BITNR 24
+#define R_WAITSTATES__pcs4_7_lw__WIDTH 4
+#define R_WAITSTATES__pcs0_3_zw__BITNR 22
+#define R_WAITSTATES__pcs0_3_zw__WIDTH 2
+#define R_WAITSTATES__pcs0_3_ew__BITNR 20
+#define R_WAITSTATES__pcs0_3_ew__WIDTH 2
+#define R_WAITSTATES__pcs0_3_lw__BITNR 16
+#define R_WAITSTATES__pcs0_3_lw__WIDTH 4
+#define R_WAITSTATES__sram_zw__BITNR 14
+#define R_WAITSTATES__sram_zw__WIDTH 2
+#define R_WAITSTATES__sram_ew__BITNR 12
+#define R_WAITSTATES__sram_ew__WIDTH 2
+#define R_WAITSTATES__sram_lw__BITNR 8
+#define R_WAITSTATES__sram_lw__WIDTH 4
+#define R_WAITSTATES__flash_zw__BITNR 6
+#define R_WAITSTATES__flash_zw__WIDTH 2
+#define R_WAITSTATES__flash_ew__BITNR 4
+#define R_WAITSTATES__flash_ew__WIDTH 2
+#define R_WAITSTATES__flash_lw__BITNR 0
+#define R_WAITSTATES__flash_lw__WIDTH 4
+
+#define R_BUS_CONFIG (IO_TYPECAST_UDWORD 0xb0000004)
+#define R_BUS_CONFIG__sram_type__BITNR 9
+#define R_BUS_CONFIG__sram_type__WIDTH 1
+#define R_BUS_CONFIG__sram_type__cwe 1
+#define R_BUS_CONFIG__sram_type__bwe 0
+#define R_BUS_CONFIG__dma_burst__BITNR 8
+#define R_BUS_CONFIG__dma_burst__WIDTH 1
+#define R_BUS_CONFIG__dma_burst__burst16 1
+#define R_BUS_CONFIG__dma_burst__burst32 0
+#define R_BUS_CONFIG__pcs4_7_wr__BITNR 7
+#define R_BUS_CONFIG__pcs4_7_wr__WIDTH 1
+#define R_BUS_CONFIG__pcs4_7_wr__ext 1
+#define R_BUS_CONFIG__pcs4_7_wr__norm 0
+#define R_BUS_CONFIG__pcs0_3_wr__BITNR 6
+#define R_BUS_CONFIG__pcs0_3_wr__WIDTH 1
+#define R_BUS_CONFIG__pcs0_3_wr__ext 1
+#define R_BUS_CONFIG__pcs0_3_wr__norm 0
+#define R_BUS_CONFIG__sram_wr__BITNR 5
+#define R_BUS_CONFIG__sram_wr__WIDTH 1
+#define R_BUS_CONFIG__sram_wr__ext 1
+#define R_BUS_CONFIG__sram_wr__norm 0
+#define R_BUS_CONFIG__flash_wr__BITNR 4
+#define R_BUS_CONFIG__flash_wr__WIDTH 1
+#define R_BUS_CONFIG__flash_wr__ext 1
+#define R_BUS_CONFIG__flash_wr__norm 0
+#define R_BUS_CONFIG__pcs4_7_bw__BITNR 3
+#define R_BUS_CONFIG__pcs4_7_bw__WIDTH 1
+#define R_BUS_CONFIG__pcs4_7_bw__bw32 1
+#define R_BUS_CONFIG__pcs4_7_bw__bw16 0
+#define R_BUS_CONFIG__pcs0_3_bw__BITNR 2
+#define R_BUS_CONFIG__pcs0_3_bw__WIDTH 1
+#define R_BUS_CONFIG__pcs0_3_bw__bw32 1
+#define R_BUS_CONFIG__pcs0_3_bw__bw16 0
+#define R_BUS_CONFIG__sram_bw__BITNR 1
+#define R_BUS_CONFIG__sram_bw__WIDTH 1
+#define R_BUS_CONFIG__sram_bw__bw32 1
+#define R_BUS_CONFIG__sram_bw__bw16 0
+#define R_BUS_CONFIG__flash_bw__BITNR 0
+#define R_BUS_CONFIG__flash_bw__WIDTH 1
+#define R_BUS_CONFIG__flash_bw__bw32 1
+#define R_BUS_CONFIG__flash_bw__bw16 0
+
+#define R_BUS_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000004)
+#define R_BUS_STATUS__pll_lock_tm__BITNR 5
+#define R_BUS_STATUS__pll_lock_tm__WIDTH 1
+#define R_BUS_STATUS__pll_lock_tm__expired 0
+#define R_BUS_STATUS__pll_lock_tm__counting 1
+#define R_BUS_STATUS__both_faults__BITNR 4
+#define R_BUS_STATUS__both_faults__WIDTH 1
+#define R_BUS_STATUS__both_faults__no 0
+#define R_BUS_STATUS__both_faults__yes 1
+#define R_BUS_STATUS__bsen___BITNR 3
+#define R_BUS_STATUS__bsen___WIDTH 1
+#define R_BUS_STATUS__bsen___enable 0
+#define R_BUS_STATUS__bsen___disable 1
+#define R_BUS_STATUS__boot__BITNR 1
+#define R_BUS_STATUS__boot__WIDTH 2
+#define R_BUS_STATUS__boot__uncached 0
+#define R_BUS_STATUS__boot__serial 1
+#define R_BUS_STATUS__boot__network 2
+#define R_BUS_STATUS__boot__parallel 3
+#define R_BUS_STATUS__flashw__BITNR 0
+#define R_BUS_STATUS__flashw__WIDTH 1
+#define R_BUS_STATUS__flashw__bw32 1
+#define R_BUS_STATUS__flashw__bw16 0
+
+#define R_DRAM_TIMING (IO_TYPECAST_UDWORD 0xb0000008)
+#define R_DRAM_TIMING__ref__BITNR 14
+#define R_DRAM_TIMING__ref__WIDTH 2
+#define R_DRAM_TIMING__ref__e52us 0
+#define R_DRAM_TIMING__ref__e13us 1
+#define R_DRAM_TIMING__ref__e8700ns 2
+#define R_DRAM_TIMING__ref__disable 3
+#define R_DRAM_TIMING__rp__BITNR 12
+#define R_DRAM_TIMING__rp__WIDTH 2
+#define R_DRAM_TIMING__rs__BITNR 10
+#define R_DRAM_TIMING__rs__WIDTH 2
+#define R_DRAM_TIMING__rh__BITNR 8
+#define R_DRAM_TIMING__rh__WIDTH 2
+#define R_DRAM_TIMING__w__BITNR 7
+#define R_DRAM_TIMING__w__WIDTH 1
+#define R_DRAM_TIMING__w__norm 0
+#define R_DRAM_TIMING__w__ext 1
+#define R_DRAM_TIMING__c__BITNR 6
+#define R_DRAM_TIMING__c__WIDTH 1
+#define R_DRAM_TIMING__c__norm 0
+#define R_DRAM_TIMING__c__ext 1
+#define R_DRAM_TIMING__cz__BITNR 4
+#define R_DRAM_TIMING__cz__WIDTH 2
+#define R_DRAM_TIMING__cp__BITNR 2
+#define R_DRAM_TIMING__cp__WIDTH 2
+#define R_DRAM_TIMING__cw__BITNR 0
+#define R_DRAM_TIMING__cw__WIDTH 2
+
+#define R_SDRAM_TIMING (IO_TYPECAST_UDWORD 0xb0000008)
+#define R_SDRAM_TIMING__sdram__BITNR 31
+#define R_SDRAM_TIMING__sdram__WIDTH 1
+#define R_SDRAM_TIMING__sdram__enable 1
+#define R_SDRAM_TIMING__sdram__disable 0
+#define R_SDRAM_TIMING__mrs_data__BITNR 16
+#define R_SDRAM_TIMING__mrs_data__WIDTH 15
+#define R_SDRAM_TIMING__ref__BITNR 14
+#define R_SDRAM_TIMING__ref__WIDTH 2
+#define R_SDRAM_TIMING__ref__e52us 0
+#define R_SDRAM_TIMING__ref__e13us 1
+#define R_SDRAM_TIMING__ref__e6500ns 2
+#define R_SDRAM_TIMING__ref__disable 3
+#define R_SDRAM_TIMING__ddr__BITNR 13
+#define R_SDRAM_TIMING__ddr__WIDTH 1
+#define R_SDRAM_TIMING__ddr__on 1
+#define R_SDRAM_TIMING__ddr__off 0
+#define R_SDRAM_TIMING__clk100__BITNR 12
+#define R_SDRAM_TIMING__clk100__WIDTH 1
+#define R_SDRAM_TIMING__clk100__on 1
+#define R_SDRAM_TIMING__clk100__off 0
+#define R_SDRAM_TIMING__ps__BITNR 11
+#define R_SDRAM_TIMING__ps__WIDTH 1
+#define R_SDRAM_TIMING__ps__on 1
+#define R_SDRAM_TIMING__ps__off 0
+#define R_SDRAM_TIMING__cmd__BITNR 9
+#define R_SDRAM_TIMING__cmd__WIDTH 2
+#define R_SDRAM_TIMING__cmd__pre 3
+#define R_SDRAM_TIMING__cmd__ref 2
+#define R_SDRAM_TIMING__cmd__mrs 1
+#define R_SDRAM_TIMING__cmd__nop 0
+#define R_SDRAM_TIMING__pde__BITNR 8
+#define R_SDRAM_TIMING__pde__WIDTH 1
+#define R_SDRAM_TIMING__rc__BITNR 6
+#define R_SDRAM_TIMING__rc__WIDTH 2
+#define R_SDRAM_TIMING__rp__BITNR 4
+#define R_SDRAM_TIMING__rp__WIDTH 2
+#define R_SDRAM_TIMING__rcd__BITNR 2
+#define R_SDRAM_TIMING__rcd__WIDTH 2
+#define R_SDRAM_TIMING__cl__BITNR 0
+#define R_SDRAM_TIMING__cl__WIDTH 2
+
+#define R_DRAM_CONFIG (IO_TYPECAST_UDWORD 0xb000000c)
+#define R_DRAM_CONFIG__wmm1__BITNR 31
+#define R_DRAM_CONFIG__wmm1__WIDTH 1
+#define R_DRAM_CONFIG__wmm1__wmm 1
+#define R_DRAM_CONFIG__wmm1__norm 0
+#define R_DRAM_CONFIG__wmm0__BITNR 30
+#define R_DRAM_CONFIG__wmm0__WIDTH 1
+#define R_DRAM_CONFIG__wmm0__wmm 1
+#define R_DRAM_CONFIG__wmm0__norm 0
+#define R_DRAM_CONFIG__sh1__BITNR 27
+#define R_DRAM_CONFIG__sh1__WIDTH 3
+#define R_DRAM_CONFIG__sh0__BITNR 24
+#define R_DRAM_CONFIG__sh0__WIDTH 3
+#define R_DRAM_CONFIG__w__BITNR 23
+#define R_DRAM_CONFIG__w__WIDTH 1
+#define R_DRAM_CONFIG__w__bw16 0
+#define R_DRAM_CONFIG__w__bw32 1
+#define R_DRAM_CONFIG__c__BITNR 22
+#define R_DRAM_CONFIG__c__WIDTH 1
+#define R_DRAM_CONFIG__c__byte 0
+#define R_DRAM_CONFIG__c__bank 1
+#define R_DRAM_CONFIG__e__BITNR 21
+#define R_DRAM_CONFIG__e__WIDTH 1
+#define R_DRAM_CONFIG__e__fast 0
+#define R_DRAM_CONFIG__e__edo 1
+#define R_DRAM_CONFIG__group_sel__BITNR 16
+#define R_DRAM_CONFIG__group_sel__WIDTH 5
+#define R_DRAM_CONFIG__group_sel__grp0 0
+#define R_DRAM_CONFIG__group_sel__grp1 1
+#define R_DRAM_CONFIG__group_sel__bit9 9
+#define R_DRAM_CONFIG__group_sel__bit10 10
+#define R_DRAM_CONFIG__group_sel__bit11 11
+#define R_DRAM_CONFIG__group_sel__bit12 12
+#define R_DRAM_CONFIG__group_sel__bit13 13
+#define R_DRAM_CONFIG__group_sel__bit14 14
+#define R_DRAM_CONFIG__group_sel__bit15 15
+#define R_DRAM_CONFIG__group_sel__bit16 16
+#define R_DRAM_CONFIG__group_sel__bit17 17
+#define R_DRAM_CONFIG__group_sel__bit18 18
+#define R_DRAM_CONFIG__group_sel__bit19 19
+#define R_DRAM_CONFIG__group_sel__bit20 20
+#define R_DRAM_CONFIG__group_sel__bit21 21
+#define R_DRAM_CONFIG__group_sel__bit22 22
+#define R_DRAM_CONFIG__group_sel__bit23 23
+#define R_DRAM_CONFIG__group_sel__bit24 24
+#define R_DRAM_CONFIG__group_sel__bit25 25
+#define R_DRAM_CONFIG__group_sel__bit26 26
+#define R_DRAM_CONFIG__group_sel__bit27 27
+#define R_DRAM_CONFIG__group_sel__bit28 28
+#define R_DRAM_CONFIG__group_sel__bit29 29
+#define R_DRAM_CONFIG__ca1__BITNR 13
+#define R_DRAM_CONFIG__ca1__WIDTH 3
+#define R_DRAM_CONFIG__bank23sel__BITNR 8
+#define R_DRAM_CONFIG__bank23sel__WIDTH 5
+#define R_DRAM_CONFIG__bank23sel__bank0 0
+#define R_DRAM_CONFIG__bank23sel__bank1 1
+#define R_DRAM_CONFIG__bank23sel__bit9 9
+#define R_DRAM_CONFIG__bank23sel__bit10 10
+#define R_DRAM_CONFIG__bank23sel__bit11 11
+#define R_DRAM_CONFIG__bank23sel__bit12 12
+#define R_DRAM_CONFIG__bank23sel__bit13 13
+#define R_DRAM_CONFIG__bank23sel__bit14 14
+#define R_DRAM_CONFIG__bank23sel__bit15 15
+#define R_DRAM_CONFIG__bank23sel__bit16 16
+#define R_DRAM_CONFIG__bank23sel__bit17 17
+#define R_DRAM_CONFIG__bank23sel__bit18 18
+#define R_DRAM_CONFIG__bank23sel__bit19 19
+#define R_DRAM_CONFIG__bank23sel__bit20 20
+#define R_DRAM_CONFIG__bank23sel__bit21 21
+#define R_DRAM_CONFIG__bank23sel__bit22 22
+#define R_DRAM_CONFIG__bank23sel__bit23 23
+#define R_DRAM_CONFIG__bank23sel__bit24 24
+#define R_DRAM_CONFIG__bank23sel__bit25 25
+#define R_DRAM_CONFIG__bank23sel__bit26 26
+#define R_DRAM_CONFIG__bank23sel__bit27 27
+#define R_DRAM_CONFIG__bank23sel__bit28 28
+#define R_DRAM_CONFIG__bank23sel__bit29 29
+#define R_DRAM_CONFIG__ca0__BITNR 5
+#define R_DRAM_CONFIG__ca0__WIDTH 3
+#define R_DRAM_CONFIG__bank01sel__BITNR 0
+#define R_DRAM_CONFIG__bank01sel__WIDTH 5
+#define R_DRAM_CONFIG__bank01sel__bank0 0
+#define R_DRAM_CONFIG__bank01sel__bank1 1
+#define R_DRAM_CONFIG__bank01sel__bit9 9
+#define R_DRAM_CONFIG__bank01sel__bit10 10
+#define R_DRAM_CONFIG__bank01sel__bit11 11
+#define R_DRAM_CONFIG__bank01sel__bit12 12
+#define R_DRAM_CONFIG__bank01sel__bit13 13
+#define R_DRAM_CONFIG__bank01sel__bit14 14
+#define R_DRAM_CONFIG__bank01sel__bit15 15
+#define R_DRAM_CONFIG__bank01sel__bit16 16
+#define R_DRAM_CONFIG__bank01sel__bit17 17
+#define R_DRAM_CONFIG__bank01sel__bit18 18
+#define R_DRAM_CONFIG__bank01sel__bit19 19
+#define R_DRAM_CONFIG__bank01sel__bit20 20
+#define R_DRAM_CONFIG__bank01sel__bit21 21
+#define R_DRAM_CONFIG__bank01sel__bit22 22
+#define R_DRAM_CONFIG__bank01sel__bit23 23
+#define R_DRAM_CONFIG__bank01sel__bit24 24
+#define R_DRAM_CONFIG__bank01sel__bit25 25
+#define R_DRAM_CONFIG__bank01sel__bit26 26
+#define R_DRAM_CONFIG__bank01sel__bit27 27
+#define R_DRAM_CONFIG__bank01sel__bit28 28
+#define R_DRAM_CONFIG__bank01sel__bit29 29
+
+#define R_SDRAM_CONFIG (IO_TYPECAST_UDWORD 0xb000000c)
+#define R_SDRAM_CONFIG__wmm1__BITNR 31
+#define R_SDRAM_CONFIG__wmm1__WIDTH 1
+#define R_SDRAM_CONFIG__wmm1__wmm 1
+#define R_SDRAM_CONFIG__wmm1__norm 0
+#define R_SDRAM_CONFIG__wmm0__BITNR 30
+#define R_SDRAM_CONFIG__wmm0__WIDTH 1
+#define R_SDRAM_CONFIG__wmm0__wmm 1
+#define R_SDRAM_CONFIG__wmm0__norm 0
+#define R_SDRAM_CONFIG__sh1__BITNR 27
+#define R_SDRAM_CONFIG__sh1__WIDTH 3
+#define R_SDRAM_CONFIG__sh0__BITNR 24
+#define R_SDRAM_CONFIG__sh0__WIDTH 3
+#define R_SDRAM_CONFIG__w__BITNR 23
+#define R_SDRAM_CONFIG__w__WIDTH 1
+#define R_SDRAM_CONFIG__w__bw16 0
+#define R_SDRAM_CONFIG__w__bw32 1
+#define R_SDRAM_CONFIG__type1__BITNR 22
+#define R_SDRAM_CONFIG__type1__WIDTH 1
+#define R_SDRAM_CONFIG__type1__bank2 0
+#define R_SDRAM_CONFIG__type1__bank4 1
+#define R_SDRAM_CONFIG__type0__BITNR 21
+#define R_SDRAM_CONFIG__type0__WIDTH 1
+#define R_SDRAM_CONFIG__type0__bank2 0
+#define R_SDRAM_CONFIG__type0__bank4 1
+#define R_SDRAM_CONFIG__group_sel__BITNR 16
+#define R_SDRAM_CONFIG__group_sel__WIDTH 5
+#define R_SDRAM_CONFIG__group_sel__grp0 0
+#define R_SDRAM_CONFIG__group_sel__grp1 1
+#define R_SDRAM_CONFIG__group_sel__bit9 9
+#define R_SDRAM_CONFIG__group_sel__bit10 10
+#define R_SDRAM_CONFIG__group_sel__bit11 11
+#define R_SDRAM_CONFIG__group_sel__bit12 12
+#define R_SDRAM_CONFIG__group_sel__bit13 13
+#define R_SDRAM_CONFIG__group_sel__bit14 14
+#define R_SDRAM_CONFIG__group_sel__bit15 15
+#define R_SDRAM_CONFIG__group_sel__bit16 16
+#define R_SDRAM_CONFIG__group_sel__bit17 17
+#define R_SDRAM_CONFIG__group_sel__bit18 18
+#define R_SDRAM_CONFIG__group_sel__bit19 19
+#define R_SDRAM_CONFIG__group_sel__bit20 20
+#define R_SDRAM_CONFIG__group_sel__bit21 21
+#define R_SDRAM_CONFIG__group_sel__bit22 22
+#define R_SDRAM_CONFIG__group_sel__bit23 23
+#define R_SDRAM_CONFIG__group_sel__bit24 24
+#define R_SDRAM_CONFIG__group_sel__bit25 25
+#define R_SDRAM_CONFIG__group_sel__bit26 26
+#define R_SDRAM_CONFIG__group_sel__bit27 27
+#define R_SDRAM_CONFIG__group_sel__bit28 28
+#define R_SDRAM_CONFIG__group_sel__bit29 29
+#define R_SDRAM_CONFIG__ca1__BITNR 13
+#define R_SDRAM_CONFIG__ca1__WIDTH 3
+#define R_SDRAM_CONFIG__bank_sel1__BITNR 8
+#define R_SDRAM_CONFIG__bank_sel1__WIDTH 5
+#define R_SDRAM_CONFIG__bank_sel1__bit9 9
+#define R_SDRAM_CONFIG__bank_sel1__bit10 10
+#define R_SDRAM_CONFIG__bank_sel1__bit11 11
+#define R_SDRAM_CONFIG__bank_sel1__bit12 12
+#define R_SDRAM_CONFIG__bank_sel1__bit13 13
+#define R_SDRAM_CONFIG__bank_sel1__bit14 14
+#define R_SDRAM_CONFIG__bank_sel1__bit15 15
+#define R_SDRAM_CONFIG__bank_sel1__bit16 16
+#define R_SDRAM_CONFIG__bank_sel1__bit17 17
+#define R_SDRAM_CONFIG__bank_sel1__bit18 18
+#define R_SDRAM_CONFIG__bank_sel1__bit19 19
+#define R_SDRAM_CONFIG__bank_sel1__bit20 20
+#define R_SDRAM_CONFIG__bank_sel1__bit21 21
+#define R_SDRAM_CONFIG__bank_sel1__bit22 22
+#define R_SDRAM_CONFIG__bank_sel1__bit23 23
+#define R_SDRAM_CONFIG__bank_sel1__bit24 24
+#define R_SDRAM_CONFIG__bank_sel1__bit25 25
+#define R_SDRAM_CONFIG__bank_sel1__bit26 26
+#define R_SDRAM_CONFIG__bank_sel1__bit27 27
+#define R_SDRAM_CONFIG__bank_sel1__bit28 28
+#define R_SDRAM_CONFIG__bank_sel1__bit29 29
+#define R_SDRAM_CONFIG__ca0__BITNR 5
+#define R_SDRAM_CONFIG__ca0__WIDTH 3
+#define R_SDRAM_CONFIG__bank_sel0__BITNR 0
+#define R_SDRAM_CONFIG__bank_sel0__WIDTH 5
+#define R_SDRAM_CONFIG__bank_sel0__bit9 9
+#define R_SDRAM_CONFIG__bank_sel0__bit10 10
+#define R_SDRAM_CONFIG__bank_sel0__bit11 11
+#define R_SDRAM_CONFIG__bank_sel0__bit12 12
+#define R_SDRAM_CONFIG__bank_sel0__bit13 13
+#define R_SDRAM_CONFIG__bank_sel0__bit14 14
+#define R_SDRAM_CONFIG__bank_sel0__bit15 15
+#define R_SDRAM_CONFIG__bank_sel0__bit16 16
+#define R_SDRAM_CONFIG__bank_sel0__bit17 17
+#define R_SDRAM_CONFIG__bank_sel0__bit18 18
+#define R_SDRAM_CONFIG__bank_sel0__bit19 19
+#define R_SDRAM_CONFIG__bank_sel0__bit20 20
+#define R_SDRAM_CONFIG__bank_sel0__bit21 21
+#define R_SDRAM_CONFIG__bank_sel0__bit22 22
+#define R_SDRAM_CONFIG__bank_sel0__bit23 23
+#define R_SDRAM_CONFIG__bank_sel0__bit24 24
+#define R_SDRAM_CONFIG__bank_sel0__bit25 25
+#define R_SDRAM_CONFIG__bank_sel0__bit26 26
+#define R_SDRAM_CONFIG__bank_sel0__bit27 27
+#define R_SDRAM_CONFIG__bank_sel0__bit28 28
+#define R_SDRAM_CONFIG__bank_sel0__bit29 29
+
+/*
+!* External DMA registers
+!*/
+
+#define R_EXT_DMA_0_CMD (IO_TYPECAST_UDWORD 0xb0000010)
+#define R_EXT_DMA_0_CMD__cnt__BITNR 23
+#define R_EXT_DMA_0_CMD__cnt__WIDTH 1
+#define R_EXT_DMA_0_CMD__cnt__enable 1
+#define R_EXT_DMA_0_CMD__cnt__disable 0
+#define R_EXT_DMA_0_CMD__rqpol__BITNR 22
+#define R_EXT_DMA_0_CMD__rqpol__WIDTH 1
+#define R_EXT_DMA_0_CMD__rqpol__ahigh 0
+#define R_EXT_DMA_0_CMD__rqpol__alow 1
+#define R_EXT_DMA_0_CMD__apol__BITNR 21
+#define R_EXT_DMA_0_CMD__apol__WIDTH 1
+#define R_EXT_DMA_0_CMD__apol__ahigh 0
+#define R_EXT_DMA_0_CMD__apol__alow 1
+#define R_EXT_DMA_0_CMD__rq_ack__BITNR 20
+#define R_EXT_DMA_0_CMD__rq_ack__WIDTH 1
+#define R_EXT_DMA_0_CMD__rq_ack__burst 0
+#define R_EXT_DMA_0_CMD__rq_ack__handsh 1
+#define R_EXT_DMA_0_CMD__wid__BITNR 18
+#define R_EXT_DMA_0_CMD__wid__WIDTH 2
+#define R_EXT_DMA_0_CMD__wid__byte 0
+#define R_EXT_DMA_0_CMD__wid__word 1
+#define R_EXT_DMA_0_CMD__wid__dword 2
+#define R_EXT_DMA_0_CMD__dir__BITNR 17
+#define R_EXT_DMA_0_CMD__dir__WIDTH 1
+#define R_EXT_DMA_0_CMD__dir__input 0
+#define R_EXT_DMA_0_CMD__dir__output 1
+#define R_EXT_DMA_0_CMD__run__BITNR 16
+#define R_EXT_DMA_0_CMD__run__WIDTH 1
+#define R_EXT_DMA_0_CMD__run__start 1
+#define R_EXT_DMA_0_CMD__run__stop 0
+#define R_EXT_DMA_0_CMD__trf_count__BITNR 0
+#define R_EXT_DMA_0_CMD__trf_count__WIDTH 16
+
+#define R_EXT_DMA_0_STAT (IO_TYPECAST_RO_UDWORD 0xb0000010)
+#define R_EXT_DMA_0_STAT__run__BITNR 16
+#define R_EXT_DMA_0_STAT__run__WIDTH 1
+#define R_EXT_DMA_0_STAT__run__start 1
+#define R_EXT_DMA_0_STAT__run__stop 0
+#define R_EXT_DMA_0_STAT__trf_count__BITNR 0
+#define R_EXT_DMA_0_STAT__trf_count__WIDTH 16
+
+#define R_EXT_DMA_0_ADDR (IO_TYPECAST_UDWORD 0xb0000014)
+#define R_EXT_DMA_0_ADDR__ext0_addr__BITNR 2
+#define R_EXT_DMA_0_ADDR__ext0_addr__WIDTH 28
+
+#define R_EXT_DMA_1_CMD (IO_TYPECAST_UDWORD 0xb0000018)
+#define R_EXT_DMA_1_CMD__cnt__BITNR 23
+#define R_EXT_DMA_1_CMD__cnt__WIDTH 1
+#define R_EXT_DMA_1_CMD__cnt__enable 1
+#define R_EXT_DMA_1_CMD__cnt__disable 0
+#define R_EXT_DMA_1_CMD__rqpol__BITNR 22
+#define R_EXT_DMA_1_CMD__rqpol__WIDTH 1
+#define R_EXT_DMA_1_CMD__rqpol__ahigh 0
+#define R_EXT_DMA_1_CMD__rqpol__alow 1
+#define R_EXT_DMA_1_CMD__apol__BITNR 21
+#define R_EXT_DMA_1_CMD__apol__WIDTH 1
+#define R_EXT_DMA_1_CMD__apol__ahigh 0
+#define R_EXT_DMA_1_CMD__apol__alow 1
+#define R_EXT_DMA_1_CMD__rq_ack__BITNR 20
+#define R_EXT_DMA_1_CMD__rq_ack__WIDTH 1
+#define R_EXT_DMA_1_CMD__rq_ack__burst 0
+#define R_EXT_DMA_1_CMD__rq_ack__handsh 1
+#define R_EXT_DMA_1_CMD__wid__BITNR 18
+#define R_EXT_DMA_1_CMD__wid__WIDTH 2
+#define R_EXT_DMA_1_CMD__wid__byte 0
+#define R_EXT_DMA_1_CMD__wid__word 1
+#define R_EXT_DMA_1_CMD__wid__dword 2
+#define R_EXT_DMA_1_CMD__dir__BITNR 17
+#define R_EXT_DMA_1_CMD__dir__WIDTH 1
+#define R_EXT_DMA_1_CMD__dir__input 0
+#define R_EXT_DMA_1_CMD__dir__output 1
+#define R_EXT_DMA_1_CMD__run__BITNR 16
+#define R_EXT_DMA_1_CMD__run__WIDTH 1
+#define R_EXT_DMA_1_CMD__run__start 1
+#define R_EXT_DMA_1_CMD__run__stop 0
+#define R_EXT_DMA_1_CMD__trf_count__BITNR 0
+#define R_EXT_DMA_1_CMD__trf_count__WIDTH 16
+
+#define R_EXT_DMA_1_STAT (IO_TYPECAST_RO_UDWORD 0xb0000018)
+#define R_EXT_DMA_1_STAT__run__BITNR 16
+#define R_EXT_DMA_1_STAT__run__WIDTH 1
+#define R_EXT_DMA_1_STAT__run__start 1
+#define R_EXT_DMA_1_STAT__run__stop 0
+#define R_EXT_DMA_1_STAT__trf_count__BITNR 0
+#define R_EXT_DMA_1_STAT__trf_count__WIDTH 16
+
+#define R_EXT_DMA_1_ADDR (IO_TYPECAST_UDWORD 0xb000001c)
+#define R_EXT_DMA_1_ADDR__ext0_addr__BITNR 2
+#define R_EXT_DMA_1_ADDR__ext0_addr__WIDTH 28
+
+/*
+!* Timer registers
+!*/
+
+#define R_TIMER_CTRL (IO_TYPECAST_UDWORD 0xb0000020)
+#define R_TIMER_CTRL__timerdiv1__BITNR 24
+#define R_TIMER_CTRL__timerdiv1__WIDTH 8
+#define R_TIMER_CTRL__timerdiv0__BITNR 16
+#define R_TIMER_CTRL__timerdiv0__WIDTH 8
+#define R_TIMER_CTRL__presc_timer1__BITNR 15
+#define R_TIMER_CTRL__presc_timer1__WIDTH 1
+#define R_TIMER_CTRL__presc_timer1__normal 0
+#define R_TIMER_CTRL__presc_timer1__prescale 1
+#define R_TIMER_CTRL__i1__BITNR 14
+#define R_TIMER_CTRL__i1__WIDTH 1
+#define R_TIMER_CTRL__i1__clr 1
+#define R_TIMER_CTRL__i1__nop 0
+#define R_TIMER_CTRL__tm1__BITNR 12
+#define R_TIMER_CTRL__tm1__WIDTH 2
+#define R_TIMER_CTRL__tm1__stop_ld 0
+#define R_TIMER_CTRL__tm1__freeze 1
+#define R_TIMER_CTRL__tm1__run 2
+#define R_TIMER_CTRL__tm1__reserved 3
+#define R_TIMER_CTRL__clksel1__BITNR 8
+#define R_TIMER_CTRL__clksel1__WIDTH 4
+#define R_TIMER_CTRL__clksel1__c300Hz 0
+#define R_TIMER_CTRL__clksel1__c600Hz 1
+#define R_TIMER_CTRL__clksel1__c1200Hz 2
+#define R_TIMER_CTRL__clksel1__c2400Hz 3
+#define R_TIMER_CTRL__clksel1__c4800Hz 4
+#define R_TIMER_CTRL__clksel1__c9600Hz 5
+#define R_TIMER_CTRL__clksel1__c19k2Hz 6
+#define R_TIMER_CTRL__clksel1__c38k4Hz 7
+#define R_TIMER_CTRL__clksel1__c57k6Hz 8
+#define R_TIMER_CTRL__clksel1__c115k2Hz 9
+#define R_TIMER_CTRL__clksel1__c230k4Hz 10
+#define R_TIMER_CTRL__clksel1__c460k8Hz 11
+#define R_TIMER_CTRL__clksel1__c921k6Hz 12
+#define R_TIMER_CTRL__clksel1__c1843k2Hz 13
+#define R_TIMER_CTRL__clksel1__c6250kHz 14
+#define R_TIMER_CTRL__clksel1__cascade0 15
+#define R_TIMER_CTRL__presc_ext__BITNR 7
+#define R_TIMER_CTRL__presc_ext__WIDTH 1
+#define R_TIMER_CTRL__presc_ext__prescale 0
+#define R_TIMER_CTRL__presc_ext__external 1
+#define R_TIMER_CTRL__i0__BITNR 6
+#define R_TIMER_CTRL__i0__WIDTH 1
+#define R_TIMER_CTRL__i0__clr 1
+#define R_TIMER_CTRL__i0__nop 0
+#define R_TIMER_CTRL__tm0__BITNR 4
+#define R_TIMER_CTRL__tm0__WIDTH 2
+#define R_TIMER_CTRL__tm0__stop_ld 0
+#define R_TIMER_CTRL__tm0__freeze 1
+#define R_TIMER_CTRL__tm0__run 2
+#define R_TIMER_CTRL__tm0__reserved 3
+#define R_TIMER_CTRL__clksel0__BITNR 0
+#define R_TIMER_CTRL__clksel0__WIDTH 4
+#define R_TIMER_CTRL__clksel0__c300Hz 0
+#define R_TIMER_CTRL__clksel0__c600Hz 1
+#define R_TIMER_CTRL__clksel0__c1200Hz 2
+#define R_TIMER_CTRL__clksel0__c2400Hz 3
+#define R_TIMER_CTRL__clksel0__c4800Hz 4
+#define R_TIMER_CTRL__clksel0__c9600Hz 5
+#define R_TIMER_CTRL__clksel0__c19k2Hz 6
+#define R_TIMER_CTRL__clksel0__c38k4Hz 7
+#define R_TIMER_CTRL__clksel0__c57k6Hz 8
+#define R_TIMER_CTRL__clksel0__c115k2Hz 9
+#define R_TIMER_CTRL__clksel0__c230k4Hz 10
+#define R_TIMER_CTRL__clksel0__c460k8Hz 11
+#define R_TIMER_CTRL__clksel0__c921k6Hz 12
+#define R_TIMER_CTRL__clksel0__c1843k2Hz 13
+#define R_TIMER_CTRL__clksel0__c6250kHz 14
+#define R_TIMER_CTRL__clksel0__flexible 15
+
+#define R_TIMER_DATA (IO_TYPECAST_RO_UDWORD 0xb0000020)
+#define R_TIMER_DATA__timer1__BITNR 24
+#define R_TIMER_DATA__timer1__WIDTH 8
+#define R_TIMER_DATA__timer0__BITNR 16
+#define R_TIMER_DATA__timer0__WIDTH 8
+#define R_TIMER_DATA__clkdiv_high__BITNR 8
+#define R_TIMER_DATA__clkdiv_high__WIDTH 8
+#define R_TIMER_DATA__clkdiv_low__BITNR 0
+#define R_TIMER_DATA__clkdiv_low__WIDTH 8
+
+#define R_TIMER01_DATA (IO_TYPECAST_RO_UWORD 0xb0000022)
+#define R_TIMER01_DATA__count__BITNR 0
+#define R_TIMER01_DATA__count__WIDTH 16
+
+#define R_TIMER0_DATA (IO_TYPECAST_RO_BYTE 0xb0000022)
+#define R_TIMER0_DATA__count__BITNR 0
+#define R_TIMER0_DATA__count__WIDTH 8
+
+#define R_TIMER1_DATA (IO_TYPECAST_RO_BYTE 0xb0000023)
+#define R_TIMER1_DATA__count__BITNR 0
+#define R_TIMER1_DATA__count__WIDTH 8
+
+#define R_WATCHDOG (IO_TYPECAST_UDWORD 0xb0000024)
+#define R_WATCHDOG__key__BITNR 1
+#define R_WATCHDOG__key__WIDTH 3
+#define R_WATCHDOG__enable__BITNR 0
+#define R_WATCHDOG__enable__WIDTH 1
+#define R_WATCHDOG__enable__stop 0
+#define R_WATCHDOG__enable__start 1
+
+#define R_CLOCK_PRESCALE (IO_TYPECAST_UDWORD 0xb00000f0)
+#define R_CLOCK_PRESCALE__ser_presc__BITNR 16
+#define R_CLOCK_PRESCALE__ser_presc__WIDTH 16
+#define R_CLOCK_PRESCALE__tim_presc__BITNR 0
+#define R_CLOCK_PRESCALE__tim_presc__WIDTH 16
+
+#define R_SERIAL_PRESCALE (IO_TYPECAST_UWORD 0xb00000f2)
+#define R_SERIAL_PRESCALE__ser_presc__BITNR 0
+#define R_SERIAL_PRESCALE__ser_presc__WIDTH 16
+
+#define R_TIMER_PRESCALE (IO_TYPECAST_UWORD 0xb00000f0)
+#define R_TIMER_PRESCALE__tim_presc__BITNR 0
+#define R_TIMER_PRESCALE__tim_presc__WIDTH 16
+
+#define R_PRESCALE_STATUS (IO_TYPECAST_RO_UDWORD 0xb00000f0)
+#define R_PRESCALE_STATUS__ser_status__BITNR 16
+#define R_PRESCALE_STATUS__ser_status__WIDTH 16
+#define R_PRESCALE_STATUS__tim_status__BITNR 0
+#define R_PRESCALE_STATUS__tim_status__WIDTH 16
+
+#define R_SER_PRESC_STATUS (IO_TYPECAST_RO_UWORD 0xb00000f2)
+#define R_SER_PRESC_STATUS__ser_status__BITNR 0
+#define R_SER_PRESC_STATUS__ser_status__WIDTH 16
+
+#define R_TIM_PRESC_STATUS (IO_TYPECAST_RO_UWORD 0xb00000f0)
+#define R_TIM_PRESC_STATUS__tim_status__BITNR 0
+#define R_TIM_PRESC_STATUS__tim_status__WIDTH 16
+
+#define R_SYNC_SERIAL_PRESCALE (IO_TYPECAST_UDWORD 0xb00000f4)
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__BITNR 23
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__codec 0
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u3__baudrate 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__BITNR 22
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__external 0
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u3__internal 1
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__BITNR 21
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__codec 0
+#define R_SYNC_SERIAL_PRESCALE__clk_sel_u1__baudrate 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__BITNR 20
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__external 0
+#define R_SYNC_SERIAL_PRESCALE__word_stb_sel_u1__internal 1
+#define R_SYNC_SERIAL_PRESCALE__prescaler__BITNR 16
+#define R_SYNC_SERIAL_PRESCALE__prescaler__WIDTH 3
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div1 0
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div2 1
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div4 2
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div8 3
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div16 4
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div32 5
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div64 6
+#define R_SYNC_SERIAL_PRESCALE__prescaler__div128 7
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__BITNR 15
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__WIDTH 1
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__normal 0
+#define R_SYNC_SERIAL_PRESCALE__warp_mode__enabled 1
+#define R_SYNC_SERIAL_PRESCALE__frame_rate__BITNR 11
+#define R_SYNC_SERIAL_PRESCALE__frame_rate__WIDTH 4
+#define R_SYNC_SERIAL_PRESCALE__word_rate__BITNR 0
+#define R_SYNC_SERIAL_PRESCALE__word_rate__WIDTH 10
+
+/*
+!* Shared RAM interface registers
+!*/
+
+#define R_SHARED_RAM_CONFIG (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_SHARED_RAM_CONFIG__width__BITNR 3
+#define R_SHARED_RAM_CONFIG__width__WIDTH 1
+#define R_SHARED_RAM_CONFIG__width__byte 0
+#define R_SHARED_RAM_CONFIG__width__word 1
+#define R_SHARED_RAM_CONFIG__enable__BITNR 2
+#define R_SHARED_RAM_CONFIG__enable__WIDTH 1
+#define R_SHARED_RAM_CONFIG__enable__yes 1
+#define R_SHARED_RAM_CONFIG__enable__no 0
+#define R_SHARED_RAM_CONFIG__pint__BITNR 1
+#define R_SHARED_RAM_CONFIG__pint__WIDTH 1
+#define R_SHARED_RAM_CONFIG__pint__int 1
+#define R_SHARED_RAM_CONFIG__pint__nop 0
+#define R_SHARED_RAM_CONFIG__clri__BITNR 0
+#define R_SHARED_RAM_CONFIG__clri__WIDTH 1
+#define R_SHARED_RAM_CONFIG__clri__clr 1
+#define R_SHARED_RAM_CONFIG__clri__nop 0
+
+#define R_SHARED_RAM_ADDR (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_SHARED_RAM_ADDR__base_addr__BITNR 8
+#define R_SHARED_RAM_ADDR__base_addr__WIDTH 22
+
+/*
+!* General config registers
+!*/
+
+#define R_GEN_CONFIG (IO_TYPECAST_UDWORD 0xb000002c)
+#define R_GEN_CONFIG__par_w__BITNR 31
+#define R_GEN_CONFIG__par_w__WIDTH 1
+#define R_GEN_CONFIG__par_w__select 1
+#define R_GEN_CONFIG__par_w__disable 0
+#define R_GEN_CONFIG__usb2__BITNR 30
+#define R_GEN_CONFIG__usb2__WIDTH 1
+#define R_GEN_CONFIG__usb2__select 1
+#define R_GEN_CONFIG__usb2__disable 0
+#define R_GEN_CONFIG__usb1__BITNR 29
+#define R_GEN_CONFIG__usb1__WIDTH 1
+#define R_GEN_CONFIG__usb1__select 1
+#define R_GEN_CONFIG__usb1__disable 0
+#define R_GEN_CONFIG__p21__BITNR 28
+#define R_GEN_CONFIG__p21__WIDTH 1
+#define R_GEN_CONFIG__p21__select 1
+#define R_GEN_CONFIG__p21__disable 0
+#define R_GEN_CONFIG__g24dir__BITNR 27
+#define R_GEN_CONFIG__g24dir__WIDTH 1
+#define R_GEN_CONFIG__g24dir__in 0
+#define R_GEN_CONFIG__g24dir__out 1
+#define R_GEN_CONFIG__g16_20dir__BITNR 26
+#define R_GEN_CONFIG__g16_20dir__WIDTH 1
+#define R_GEN_CONFIG__g16_20dir__in 0
+#define R_GEN_CONFIG__g16_20dir__out 1
+#define R_GEN_CONFIG__g8_15dir__BITNR 25
+#define R_GEN_CONFIG__g8_15dir__WIDTH 1
+#define R_GEN_CONFIG__g8_15dir__in 0
+#define R_GEN_CONFIG__g8_15dir__out 1
+#define R_GEN_CONFIG__g0dir__BITNR 24
+#define R_GEN_CONFIG__g0dir__WIDTH 1
+#define R_GEN_CONFIG__g0dir__in 0
+#define R_GEN_CONFIG__g0dir__out 1
+#define R_GEN_CONFIG__dma9__BITNR 23
+#define R_GEN_CONFIG__dma9__WIDTH 1
+#define R_GEN_CONFIG__dma9__usb 0
+#define R_GEN_CONFIG__dma9__serial1 1
+#define R_GEN_CONFIG__dma8__BITNR 22
+#define R_GEN_CONFIG__dma8__WIDTH 1
+#define R_GEN_CONFIG__dma8__usb 0
+#define R_GEN_CONFIG__dma8__serial1 1
+#define R_GEN_CONFIG__dma7__BITNR 20
+#define R_GEN_CONFIG__dma7__WIDTH 2
+#define R_GEN_CONFIG__dma7__unused 0
+#define R_GEN_CONFIG__dma7__serial0 1
+#define R_GEN_CONFIG__dma7__extdma1 2
+#define R_GEN_CONFIG__dma7__intdma6 3
+#define R_GEN_CONFIG__dma6__BITNR 18
+#define R_GEN_CONFIG__dma6__WIDTH 2
+#define R_GEN_CONFIG__dma6__unused 0
+#define R_GEN_CONFIG__dma6__serial0 1
+#define R_GEN_CONFIG__dma6__extdma1 2
+#define R_GEN_CONFIG__dma6__intdma7 3
+#define R_GEN_CONFIG__dma5__BITNR 16
+#define R_GEN_CONFIG__dma5__WIDTH 2
+#define R_GEN_CONFIG__dma5__par1 0
+#define R_GEN_CONFIG__dma5__scsi1 1
+#define R_GEN_CONFIG__dma5__serial3 2
+#define R_GEN_CONFIG__dma5__extdma0 3
+#define R_GEN_CONFIG__dma4__BITNR 14
+#define R_GEN_CONFIG__dma4__WIDTH 2
+#define R_GEN_CONFIG__dma4__par1 0
+#define R_GEN_CONFIG__dma4__scsi1 1
+#define R_GEN_CONFIG__dma4__serial3 2
+#define R_GEN_CONFIG__dma4__extdma0 3
+#define R_GEN_CONFIG__dma3__BITNR 12
+#define R_GEN_CONFIG__dma3__WIDTH 2
+#define R_GEN_CONFIG__dma3__par0 0
+#define R_GEN_CONFIG__dma3__scsi0 1
+#define R_GEN_CONFIG__dma3__serial2 2
+#define R_GEN_CONFIG__dma3__ata 3
+#define R_GEN_CONFIG__dma2__BITNR 10
+#define R_GEN_CONFIG__dma2__WIDTH 2
+#define R_GEN_CONFIG__dma2__par0 0
+#define R_GEN_CONFIG__dma2__scsi0 1
+#define R_GEN_CONFIG__dma2__serial2 2
+#define R_GEN_CONFIG__dma2__ata 3
+#define R_GEN_CONFIG__mio_w__BITNR 9
+#define R_GEN_CONFIG__mio_w__WIDTH 1
+#define R_GEN_CONFIG__mio_w__select 1
+#define R_GEN_CONFIG__mio_w__disable 0
+#define R_GEN_CONFIG__ser3__BITNR 8
+#define R_GEN_CONFIG__ser3__WIDTH 1
+#define R_GEN_CONFIG__ser3__select 1
+#define R_GEN_CONFIG__ser3__disable 0
+#define R_GEN_CONFIG__par1__BITNR 7
+#define R_GEN_CONFIG__par1__WIDTH 1
+#define R_GEN_CONFIG__par1__select 1
+#define R_GEN_CONFIG__par1__disable 0
+#define R_GEN_CONFIG__scsi0w__BITNR 6
+#define R_GEN_CONFIG__scsi0w__WIDTH 1
+#define R_GEN_CONFIG__scsi0w__select 1
+#define R_GEN_CONFIG__scsi0w__disable 0
+#define R_GEN_CONFIG__scsi1__BITNR 5
+#define R_GEN_CONFIG__scsi1__WIDTH 1
+#define R_GEN_CONFIG__scsi1__select 1
+#define R_GEN_CONFIG__scsi1__disable 0
+#define R_GEN_CONFIG__mio__BITNR 4
+#define R_GEN_CONFIG__mio__WIDTH 1
+#define R_GEN_CONFIG__mio__select 1
+#define R_GEN_CONFIG__mio__disable 0
+#define R_GEN_CONFIG__ser2__BITNR 3
+#define R_GEN_CONFIG__ser2__WIDTH 1
+#define R_GEN_CONFIG__ser2__select 1
+#define R_GEN_CONFIG__ser2__disable 0
+#define R_GEN_CONFIG__par0__BITNR 2
+#define R_GEN_CONFIG__par0__WIDTH 1
+#define R_GEN_CONFIG__par0__select 1
+#define R_GEN_CONFIG__par0__disable 0
+#define R_GEN_CONFIG__ata__BITNR 1
+#define R_GEN_CONFIG__ata__WIDTH 1
+#define R_GEN_CONFIG__ata__select 1
+#define R_GEN_CONFIG__ata__disable 0
+#define R_GEN_CONFIG__scsi0__BITNR 0
+#define R_GEN_CONFIG__scsi0__WIDTH 1
+#define R_GEN_CONFIG__scsi0__select 1
+#define R_GEN_CONFIG__scsi0__disable 0
+
+#define R_GEN_CONFIG_II (IO_TYPECAST_UDWORD 0xb0000034)
+#define R_GEN_CONFIG_II__sermode3__BITNR 6
+#define R_GEN_CONFIG_II__sermode3__WIDTH 1
+#define R_GEN_CONFIG_II__sermode3__async 0
+#define R_GEN_CONFIG_II__sermode3__sync 1
+#define R_GEN_CONFIG_II__sermode1__BITNR 4
+#define R_GEN_CONFIG_II__sermode1__WIDTH 1
+#define R_GEN_CONFIG_II__sermode1__async 0
+#define R_GEN_CONFIG_II__sermode1__sync 1
+#define R_GEN_CONFIG_II__ext_clk__BITNR 2
+#define R_GEN_CONFIG_II__ext_clk__WIDTH 1
+#define R_GEN_CONFIG_II__ext_clk__select 1
+#define R_GEN_CONFIG_II__ext_clk__disable 0
+#define R_GEN_CONFIG_II__ser2__BITNR 1
+#define R_GEN_CONFIG_II__ser2__WIDTH 1
+#define R_GEN_CONFIG_II__ser2__select 1
+#define R_GEN_CONFIG_II__ser2__disable 0
+#define R_GEN_CONFIG_II__ser3__BITNR 0
+#define R_GEN_CONFIG_II__ser3__WIDTH 1
+#define R_GEN_CONFIG_II__ser3__select 1
+#define R_GEN_CONFIG_II__ser3__disable 0
+
+#define R_PORT_G_DATA (IO_TYPECAST_UDWORD 0xb0000028)
+#define R_PORT_G_DATA__data__BITNR 0
+#define R_PORT_G_DATA__data__WIDTH 32
+
+/*
+!* General port configuration registers
+!*/
+
+#define R_PORT_PA_SET (IO_TYPECAST_UDWORD 0xb0000030)
+#define R_PORT_PA_SET__dir7__BITNR 15
+#define R_PORT_PA_SET__dir7__WIDTH 1
+#define R_PORT_PA_SET__dir7__input 0
+#define R_PORT_PA_SET__dir7__output 1
+#define R_PORT_PA_SET__dir6__BITNR 14
+#define R_PORT_PA_SET__dir6__WIDTH 1
+#define R_PORT_PA_SET__dir6__input 0
+#define R_PORT_PA_SET__dir6__output 1
+#define R_PORT_PA_SET__dir5__BITNR 13
+#define R_PORT_PA_SET__dir5__WIDTH 1
+#define R_PORT_PA_SET__dir5__input 0
+#define R_PORT_PA_SET__dir5__output 1
+#define R_PORT_PA_SET__dir4__BITNR 12
+#define R_PORT_PA_SET__dir4__WIDTH 1
+#define R_PORT_PA_SET__dir4__input 0
+#define R_PORT_PA_SET__dir4__output 1
+#define R_PORT_PA_SET__dir3__BITNR 11
+#define R_PORT_PA_SET__dir3__WIDTH 1
+#define R_PORT_PA_SET__dir3__input 0
+#define R_PORT_PA_SET__dir3__output 1
+#define R_PORT_PA_SET__dir2__BITNR 10
+#define R_PORT_PA_SET__dir2__WIDTH 1
+#define R_PORT_PA_SET__dir2__input 0
+#define R_PORT_PA_SET__dir2__output 1
+#define R_PORT_PA_SET__dir1__BITNR 9
+#define R_PORT_PA_SET__dir1__WIDTH 1
+#define R_PORT_PA_SET__dir1__input 0
+#define R_PORT_PA_SET__dir1__output 1
+#define R_PORT_PA_SET__dir0__BITNR 8
+#define R_PORT_PA_SET__dir0__WIDTH 1
+#define R_PORT_PA_SET__dir0__input 0
+#define R_PORT_PA_SET__dir0__output 1
+#define R_PORT_PA_SET__data_out__BITNR 0
+#define R_PORT_PA_SET__data_out__WIDTH 8
+
+#define R_PORT_PA_DATA (IO_TYPECAST_BYTE 0xb0000030)
+#define R_PORT_PA_DATA__data_out__BITNR 0
+#define R_PORT_PA_DATA__data_out__WIDTH 8
+
+#define R_PORT_PA_DIR (IO_TYPECAST_BYTE 0xb0000031)
+#define R_PORT_PA_DIR__dir7__BITNR 7
+#define R_PORT_PA_DIR__dir7__WIDTH 1
+#define R_PORT_PA_DIR__dir7__input 0
+#define R_PORT_PA_DIR__dir7__output 1
+#define R_PORT_PA_DIR__dir6__BITNR 6
+#define R_PORT_PA_DIR__dir6__WIDTH 1
+#define R_PORT_PA_DIR__dir6__input 0
+#define R_PORT_PA_DIR__dir6__output 1
+#define R_PORT_PA_DIR__dir5__BITNR 5
+#define R_PORT_PA_DIR__dir5__WIDTH 1
+#define R_PORT_PA_DIR__dir5__input 0
+#define R_PORT_PA_DIR__dir5__output 1
+#define R_PORT_PA_DIR__dir4__BITNR 4
+#define R_PORT_PA_DIR__dir4__WIDTH 1
+#define R_PORT_PA_DIR__dir4__input 0
+#define R_PORT_PA_DIR__dir4__output 1
+#define R_PORT_PA_DIR__dir3__BITNR 3
+#define R_PORT_PA_DIR__dir3__WIDTH 1
+#define R_PORT_PA_DIR__dir3__input 0
+#define R_PORT_PA_DIR__dir3__output 1
+#define R_PORT_PA_DIR__dir2__BITNR 2
+#define R_PORT_PA_DIR__dir2__WIDTH 1
+#define R_PORT_PA_DIR__dir2__input 0
+#define R_PORT_PA_DIR__dir2__output 1
+#define R_PORT_PA_DIR__dir1__BITNR 1
+#define R_PORT_PA_DIR__dir1__WIDTH 1
+#define R_PORT_PA_DIR__dir1__input 0
+#define R_PORT_PA_DIR__dir1__output 1
+#define R_PORT_PA_DIR__dir0__BITNR 0
+#define R_PORT_PA_DIR__dir0__WIDTH 1
+#define R_PORT_PA_DIR__dir0__input 0
+#define R_PORT_PA_DIR__dir0__output 1
+
+#define R_PORT_PA_READ (IO_TYPECAST_RO_UDWORD 0xb0000030)
+#define R_PORT_PA_READ__data_in__BITNR 0
+#define R_PORT_PA_READ__data_in__WIDTH 8
+
+#define R_PORT_PB_SET (IO_TYPECAST_UDWORD 0xb0000038)
+#define R_PORT_PB_SET__syncser3__BITNR 29
+#define R_PORT_PB_SET__syncser3__WIDTH 1
+#define R_PORT_PB_SET__syncser3__port_cs 0
+#define R_PORT_PB_SET__syncser3__ss3extra 1
+#define R_PORT_PB_SET__syncser1__BITNR 28
+#define R_PORT_PB_SET__syncser1__WIDTH 1
+#define R_PORT_PB_SET__syncser1__port_cs 0
+#define R_PORT_PB_SET__syncser1__ss1extra 1
+#define R_PORT_PB_SET__i2c_en__BITNR 27
+#define R_PORT_PB_SET__i2c_en__WIDTH 1
+#define R_PORT_PB_SET__i2c_en__off 0
+#define R_PORT_PB_SET__i2c_en__on 1
+#define R_PORT_PB_SET__i2c_d__BITNR 26
+#define R_PORT_PB_SET__i2c_d__WIDTH 1
+#define R_PORT_PB_SET__i2c_clk__BITNR 25
+#define R_PORT_PB_SET__i2c_clk__WIDTH 1
+#define R_PORT_PB_SET__i2c_oe___BITNR 24
+#define R_PORT_PB_SET__i2c_oe___WIDTH 1
+#define R_PORT_PB_SET__i2c_oe___enable 0
+#define R_PORT_PB_SET__i2c_oe___disable 1
+#define R_PORT_PB_SET__cs7__BITNR 23
+#define R_PORT_PB_SET__cs7__WIDTH 1
+#define R_PORT_PB_SET__cs7__port 0
+#define R_PORT_PB_SET__cs7__cs 1
+#define R_PORT_PB_SET__cs6__BITNR 22
+#define R_PORT_PB_SET__cs6__WIDTH 1
+#define R_PORT_PB_SET__cs6__port 0
+#define R_PORT_PB_SET__cs6__cs 1
+#define R_PORT_PB_SET__cs5__BITNR 21
+#define R_PORT_PB_SET__cs5__WIDTH 1
+#define R_PORT_PB_SET__cs5__port 0
+#define R_PORT_PB_SET__cs5__cs 1
+#define R_PORT_PB_SET__cs4__BITNR 20
+#define R_PORT_PB_SET__cs4__WIDTH 1
+#define R_PORT_PB_SET__cs4__port 0
+#define R_PORT_PB_SET__cs4__cs 1
+#define R_PORT_PB_SET__cs3__BITNR 19
+#define R_PORT_PB_SET__cs3__WIDTH 1
+#define R_PORT_PB_SET__cs3__port 0
+#define R_PORT_PB_SET__cs3__cs 1
+#define R_PORT_PB_SET__cs2__BITNR 18
+#define R_PORT_PB_SET__cs2__WIDTH 1
+#define R_PORT_PB_SET__cs2__port 0
+#define R_PORT_PB_SET__cs2__cs 1
+#define R_PORT_PB_SET__scsi1__BITNR 17
+#define R_PORT_PB_SET__scsi1__WIDTH 1
+#define R_PORT_PB_SET__scsi1__port_cs 0
+#define R_PORT_PB_SET__scsi1__enph 1
+#define R_PORT_PB_SET__scsi0__BITNR 16
+#define R_PORT_PB_SET__scsi0__WIDTH 1
+#define R_PORT_PB_SET__scsi0__port_cs 0
+#define R_PORT_PB_SET__scsi0__enph 1
+#define R_PORT_PB_SET__dir7__BITNR 15
+#define R_PORT_PB_SET__dir7__WIDTH 1
+#define R_PORT_PB_SET__dir7__input 0
+#define R_PORT_PB_SET__dir7__output 1
+#define R_PORT_PB_SET__dir6__BITNR 14
+#define R_PORT_PB_SET__dir6__WIDTH 1
+#define R_PORT_PB_SET__dir6__input 0
+#define R_PORT_PB_SET__dir6__output 1
+#define R_PORT_PB_SET__dir5__BITNR 13
+#define R_PORT_PB_SET__dir5__WIDTH 1
+#define R_PORT_PB_SET__dir5__input 0
+#define R_PORT_PB_SET__dir5__output 1
+#define R_PORT_PB_SET__dir4__BITNR 12
+#define R_PORT_PB_SET__dir4__WIDTH 1
+#define R_PORT_PB_SET__dir4__input 0
+#define R_PORT_PB_SET__dir4__output 1
+#define R_PORT_PB_SET__dir3__BITNR 11
+#define R_PORT_PB_SET__dir3__WIDTH 1
+#define R_PORT_PB_SET__dir3__input 0
+#define R_PORT_PB_SET__dir3__output 1
+#define R_PORT_PB_SET__dir2__BITNR 10
+#define R_PORT_PB_SET__dir2__WIDTH 1
+#define R_PORT_PB_SET__dir2__input 0
+#define R_PORT_PB_SET__dir2__output 1
+#define R_PORT_PB_SET__dir1__BITNR 9
+#define R_PORT_PB_SET__dir1__WIDTH 1
+#define R_PORT_PB_SET__dir1__input 0
+#define R_PORT_PB_SET__dir1__output 1
+#define R_PORT_PB_SET__dir0__BITNR 8
+#define R_PORT_PB_SET__dir0__WIDTH 1
+#define R_PORT_PB_SET__dir0__input 0
+#define R_PORT_PB_SET__dir0__output 1
+#define R_PORT_PB_SET__data_out__BITNR 0
+#define R_PORT_PB_SET__data_out__WIDTH 8
+
+#define R_PORT_PB_DATA (IO_TYPECAST_BYTE 0xb0000038)
+#define R_PORT_PB_DATA__data_out__BITNR 0
+#define R_PORT_PB_DATA__data_out__WIDTH 8
+
+#define R_PORT_PB_DIR (IO_TYPECAST_BYTE 0xb0000039)
+#define R_PORT_PB_DIR__dir7__BITNR 7
+#define R_PORT_PB_DIR__dir7__WIDTH 1
+#define R_PORT_PB_DIR__dir7__input 0
+#define R_PORT_PB_DIR__dir7__output 1
+#define R_PORT_PB_DIR__dir6__BITNR 6
+#define R_PORT_PB_DIR__dir6__WIDTH 1
+#define R_PORT_PB_DIR__dir6__input 0
+#define R_PORT_PB_DIR__dir6__output 1
+#define R_PORT_PB_DIR__dir5__BITNR 5
+#define R_PORT_PB_DIR__dir5__WIDTH 1
+#define R_PORT_PB_DIR__dir5__input 0
+#define R_PORT_PB_DIR__dir5__output 1
+#define R_PORT_PB_DIR__dir4__BITNR 4
+#define R_PORT_PB_DIR__dir4__WIDTH 1
+#define R_PORT_PB_DIR__dir4__input 0
+#define R_PORT_PB_DIR__dir4__output 1
+#define R_PORT_PB_DIR__dir3__BITNR 3
+#define R_PORT_PB_DIR__dir3__WIDTH 1
+#define R_PORT_PB_DIR__dir3__input 0
+#define R_PORT_PB_DIR__dir3__output 1
+#define R_PORT_PB_DIR__dir2__BITNR 2
+#define R_PORT_PB_DIR__dir2__WIDTH 1
+#define R_PORT_PB_DIR__dir2__input 0
+#define R_PORT_PB_DIR__dir2__output 1
+#define R_PORT_PB_DIR__dir1__BITNR 1
+#define R_PORT_PB_DIR__dir1__WIDTH 1
+#define R_PORT_PB_DIR__dir1__input 0
+#define R_PORT_PB_DIR__dir1__output 1
+#define R_PORT_PB_DIR__dir0__BITNR 0
+#define R_PORT_PB_DIR__dir0__WIDTH 1
+#define R_PORT_PB_DIR__dir0__input 0
+#define R_PORT_PB_DIR__dir0__output 1
+
+#define R_PORT_PB_CONFIG (IO_TYPECAST_BYTE 0xb000003a)
+#define R_PORT_PB_CONFIG__cs7__BITNR 7
+#define R_PORT_PB_CONFIG__cs7__WIDTH 1
+#define R_PORT_PB_CONFIG__cs7__port 0
+#define R_PORT_PB_CONFIG__cs7__cs 1
+#define R_PORT_PB_CONFIG__cs6__BITNR 6
+#define R_PORT_PB_CONFIG__cs6__WIDTH 1
+#define R_PORT_PB_CONFIG__cs6__port 0
+#define R_PORT_PB_CONFIG__cs6__cs 1
+#define R_PORT_PB_CONFIG__cs5__BITNR 5
+#define R_PORT_PB_CONFIG__cs5__WIDTH 1
+#define R_PORT_PB_CONFIG__cs5__port 0
+#define R_PORT_PB_CONFIG__cs5__cs 1
+#define R_PORT_PB_CONFIG__cs4__BITNR 4
+#define R_PORT_PB_CONFIG__cs4__WIDTH 1
+#define R_PORT_PB_CONFIG__cs4__port 0
+#define R_PORT_PB_CONFIG__cs4__cs 1
+#define R_PORT_PB_CONFIG__cs3__BITNR 3
+#define R_PORT_PB_CONFIG__cs3__WIDTH 1
+#define R_PORT_PB_CONFIG__cs3__port 0
+#define R_PORT_PB_CONFIG__cs3__cs 1
+#define R_PORT_PB_CONFIG__cs2__BITNR 2
+#define R_PORT_PB_CONFIG__cs2__WIDTH 1
+#define R_PORT_PB_CONFIG__cs2__port 0
+#define R_PORT_PB_CONFIG__cs2__cs 1
+#define R_PORT_PB_CONFIG__scsi1__BITNR 1
+#define R_PORT_PB_CONFIG__scsi1__WIDTH 1
+#define R_PORT_PB_CONFIG__scsi1__port_cs 0
+#define R_PORT_PB_CONFIG__scsi1__enph 1
+#define R_PORT_PB_CONFIG__scsi0__BITNR 0
+#define R_PORT_PB_CONFIG__scsi0__WIDTH 1
+#define R_PORT_PB_CONFIG__scsi0__port_cs 0
+#define R_PORT_PB_CONFIG__scsi0__enph 1
+
+#define R_PORT_PB_I2C (IO_TYPECAST_BYTE 0xb000003b)
+#define R_PORT_PB_I2C__syncser3__BITNR 5
+#define R_PORT_PB_I2C__syncser3__WIDTH 1
+#define R_PORT_PB_I2C__syncser3__port_cs 0
+#define R_PORT_PB_I2C__syncser3__ss3extra 1
+#define R_PORT_PB_I2C__syncser1__BITNR 4
+#define R_PORT_PB_I2C__syncser1__WIDTH 1
+#define R_PORT_PB_I2C__syncser1__port_cs 0
+#define R_PORT_PB_I2C__syncser1__ss1extra 1
+#define R_PORT_PB_I2C__i2c_en__BITNR 3
+#define R_PORT_PB_I2C__i2c_en__WIDTH 1
+#define R_PORT_PB_I2C__i2c_en__off 0
+#define R_PORT_PB_I2C__i2c_en__on 1
+#define R_PORT_PB_I2C__i2c_d__BITNR 2
+#define R_PORT_PB_I2C__i2c_d__WIDTH 1
+#define R_PORT_PB_I2C__i2c_clk__BITNR 1
+#define R_PORT_PB_I2C__i2c_clk__WIDTH 1
+#define R_PORT_PB_I2C__i2c_oe___BITNR 0
+#define R_PORT_PB_I2C__i2c_oe___WIDTH 1
+#define R_PORT_PB_I2C__i2c_oe___enable 0
+#define R_PORT_PB_I2C__i2c_oe___disable 1
+
+#define R_PORT_PB_READ (IO_TYPECAST_RO_UDWORD 0xb0000038)
+#define R_PORT_PB_READ__data_in__BITNR 0
+#define R_PORT_PB_READ__data_in__WIDTH 8
+
+/*
+!* Serial port registers
+!*/
+
+#define R_SERIAL0_CTRL (IO_TYPECAST_UDWORD 0xb0000060)
+#define R_SERIAL0_CTRL__tr_baud__BITNR 28
+#define R_SERIAL0_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL0_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL0_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL0_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL0_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL0_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL0_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL0_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL0_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL0_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL0_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL0_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL0_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL0_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL0_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL0_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL0_CTRL__tr_baud__reserved 15
+#define R_SERIAL0_CTRL__rec_baud__BITNR 24
+#define R_SERIAL0_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL0_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL0_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL0_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL0_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL0_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL0_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL0_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL0_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL0_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL0_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL0_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL0_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL0_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL0_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL0_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL0_CTRL__rec_baud__reserved 15
+#define R_SERIAL0_CTRL__dma_err__BITNR 23
+#define R_SERIAL0_CTRL__dma_err__WIDTH 1
+#define R_SERIAL0_CTRL__dma_err__stop 0
+#define R_SERIAL0_CTRL__dma_err__ignore 1
+#define R_SERIAL0_CTRL__rec_enable__BITNR 22
+#define R_SERIAL0_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL0_CTRL__rec_enable__disable 0
+#define R_SERIAL0_CTRL__rec_enable__enable 1
+#define R_SERIAL0_CTRL__rts___BITNR 21
+#define R_SERIAL0_CTRL__rts___WIDTH 1
+#define R_SERIAL0_CTRL__rts___active 0
+#define R_SERIAL0_CTRL__rts___inactive 1
+#define R_SERIAL0_CTRL__sampling__BITNR 20
+#define R_SERIAL0_CTRL__sampling__WIDTH 1
+#define R_SERIAL0_CTRL__sampling__middle 0
+#define R_SERIAL0_CTRL__sampling__majority 1
+#define R_SERIAL0_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL0_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL0_CTRL__rec_stick_par__normal 0
+#define R_SERIAL0_CTRL__rec_stick_par__stick 1
+#define R_SERIAL0_CTRL__rec_par__BITNR 18
+#define R_SERIAL0_CTRL__rec_par__WIDTH 1
+#define R_SERIAL0_CTRL__rec_par__even 0
+#define R_SERIAL0_CTRL__rec_par__odd 1
+#define R_SERIAL0_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL0_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL0_CTRL__rec_par_en__disable 0
+#define R_SERIAL0_CTRL__rec_par_en__enable 1
+#define R_SERIAL0_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL0_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL0_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL0_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL0_CTRL__txd__BITNR 15
+#define R_SERIAL0_CTRL__txd__WIDTH 1
+#define R_SERIAL0_CTRL__tr_enable__BITNR 14
+#define R_SERIAL0_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL0_CTRL__tr_enable__disable 0
+#define R_SERIAL0_CTRL__tr_enable__enable 1
+#define R_SERIAL0_CTRL__auto_cts__BITNR 13
+#define R_SERIAL0_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL0_CTRL__auto_cts__disabled 0
+#define R_SERIAL0_CTRL__auto_cts__active 1
+#define R_SERIAL0_CTRL__stop_bits__BITNR 12
+#define R_SERIAL0_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL0_CTRL__stop_bits__one_bit 0
+#define R_SERIAL0_CTRL__stop_bits__two_bits 1
+#define R_SERIAL0_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL0_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL0_CTRL__tr_stick_par__normal 0
+#define R_SERIAL0_CTRL__tr_stick_par__stick 1
+#define R_SERIAL0_CTRL__tr_par__BITNR 10
+#define R_SERIAL0_CTRL__tr_par__WIDTH 1
+#define R_SERIAL0_CTRL__tr_par__even 0
+#define R_SERIAL0_CTRL__tr_par__odd 1
+#define R_SERIAL0_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL0_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL0_CTRL__tr_par_en__disable 0
+#define R_SERIAL0_CTRL__tr_par_en__enable 1
+#define R_SERIAL0_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL0_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL0_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL0_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL0_CTRL__data_out__BITNR 0
+#define R_SERIAL0_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL0_BAUD (IO_TYPECAST_BYTE 0xb0000063)
+#define R_SERIAL0_BAUD__tr_baud__BITNR 4
+#define R_SERIAL0_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL0_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL0_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL0_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL0_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL0_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL0_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL0_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL0_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL0_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL0_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL0_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL0_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL0_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL0_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL0_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL0_BAUD__tr_baud__reserved 15
+#define R_SERIAL0_BAUD__rec_baud__BITNR 0
+#define R_SERIAL0_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL0_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL0_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL0_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL0_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL0_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL0_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL0_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL0_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL0_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL0_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL0_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL0_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL0_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL0_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL0_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL0_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL0_REC_CTRL (IO_TYPECAST_BYTE 0xb0000062)
+#define R_SERIAL0_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL0_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL0_REC_CTRL__dma_err__stop 0
+#define R_SERIAL0_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL0_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL0_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL0_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL0_REC_CTRL__rts___BITNR 5
+#define R_SERIAL0_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL0_REC_CTRL__rts___active 0
+#define R_SERIAL0_REC_CTRL__rts___inactive 1
+#define R_SERIAL0_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL0_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL0_REC_CTRL__sampling__middle 0
+#define R_SERIAL0_REC_CTRL__sampling__majority 1
+#define R_SERIAL0_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL0_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL0_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL0_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL0_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_par__even 0
+#define R_SERIAL0_REC_CTRL__rec_par__odd 1
+#define R_SERIAL0_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL0_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL0_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL0_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL0_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL0_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL0_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL0_TR_CTRL (IO_TYPECAST_BYTE 0xb0000061)
+#define R_SERIAL0_TR_CTRL__txd__BITNR 7
+#define R_SERIAL0_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL0_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL0_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL0_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL0_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL0_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL0_TR_CTRL__auto_cts__active 1
+#define R_SERIAL0_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL0_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL0_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL0_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL0_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL0_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL0_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL0_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL0_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_par__even 0
+#define R_SERIAL0_TR_CTRL__tr_par__odd 1
+#define R_SERIAL0_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL0_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL0_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL0_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL0_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL0_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL0_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL0_TR_DATA (IO_TYPECAST_BYTE 0xb0000060)
+#define R_SERIAL0_TR_DATA__data_out__BITNR 0
+#define R_SERIAL0_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL0_READ (IO_TYPECAST_RO_UDWORD 0xb0000060)
+#define R_SERIAL0_READ__xoff_detect__BITNR 15
+#define R_SERIAL0_READ__xoff_detect__WIDTH 1
+#define R_SERIAL0_READ__xoff_detect__no_xoff 0
+#define R_SERIAL0_READ__xoff_detect__xoff 1
+#define R_SERIAL0_READ__cts___BITNR 14
+#define R_SERIAL0_READ__cts___WIDTH 1
+#define R_SERIAL0_READ__cts___active 0
+#define R_SERIAL0_READ__cts___inactive 1
+#define R_SERIAL0_READ__tr_ready__BITNR 13
+#define R_SERIAL0_READ__tr_ready__WIDTH 1
+#define R_SERIAL0_READ__tr_ready__full 0
+#define R_SERIAL0_READ__tr_ready__ready 1
+#define R_SERIAL0_READ__rxd__BITNR 12
+#define R_SERIAL0_READ__rxd__WIDTH 1
+#define R_SERIAL0_READ__overrun__BITNR 11
+#define R_SERIAL0_READ__overrun__WIDTH 1
+#define R_SERIAL0_READ__overrun__no 0
+#define R_SERIAL0_READ__overrun__yes 1
+#define R_SERIAL0_READ__par_err__BITNR 10
+#define R_SERIAL0_READ__par_err__WIDTH 1
+#define R_SERIAL0_READ__par_err__no 0
+#define R_SERIAL0_READ__par_err__yes 1
+#define R_SERIAL0_READ__framing_err__BITNR 9
+#define R_SERIAL0_READ__framing_err__WIDTH 1
+#define R_SERIAL0_READ__framing_err__no 0
+#define R_SERIAL0_READ__framing_err__yes 1
+#define R_SERIAL0_READ__data_avail__BITNR 8
+#define R_SERIAL0_READ__data_avail__WIDTH 1
+#define R_SERIAL0_READ__data_avail__no 0
+#define R_SERIAL0_READ__data_avail__yes 1
+#define R_SERIAL0_READ__data_in__BITNR 0
+#define R_SERIAL0_READ__data_in__WIDTH 8
+
+#define R_SERIAL0_STATUS (IO_TYPECAST_RO_BYTE 0xb0000061)
+#define R_SERIAL0_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL0_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL0_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL0_STATUS__xoff_detect__xoff 1
+#define R_SERIAL0_STATUS__cts___BITNR 6
+#define R_SERIAL0_STATUS__cts___WIDTH 1
+#define R_SERIAL0_STATUS__cts___active 0
+#define R_SERIAL0_STATUS__cts___inactive 1
+#define R_SERIAL0_STATUS__tr_ready__BITNR 5
+#define R_SERIAL0_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL0_STATUS__tr_ready__full 0
+#define R_SERIAL0_STATUS__tr_ready__ready 1
+#define R_SERIAL0_STATUS__rxd__BITNR 4
+#define R_SERIAL0_STATUS__rxd__WIDTH 1
+#define R_SERIAL0_STATUS__overrun__BITNR 3
+#define R_SERIAL0_STATUS__overrun__WIDTH 1
+#define R_SERIAL0_STATUS__overrun__no 0
+#define R_SERIAL0_STATUS__overrun__yes 1
+#define R_SERIAL0_STATUS__par_err__BITNR 2
+#define R_SERIAL0_STATUS__par_err__WIDTH 1
+#define R_SERIAL0_STATUS__par_err__no 0
+#define R_SERIAL0_STATUS__par_err__yes 1
+#define R_SERIAL0_STATUS__framing_err__BITNR 1
+#define R_SERIAL0_STATUS__framing_err__WIDTH 1
+#define R_SERIAL0_STATUS__framing_err__no 0
+#define R_SERIAL0_STATUS__framing_err__yes 1
+#define R_SERIAL0_STATUS__data_avail__BITNR 0
+#define R_SERIAL0_STATUS__data_avail__WIDTH 1
+#define R_SERIAL0_STATUS__data_avail__no 0
+#define R_SERIAL0_STATUS__data_avail__yes 1
+
+#define R_SERIAL0_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000060)
+#define R_SERIAL0_REC_DATA__data_in__BITNR 0
+#define R_SERIAL0_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL0_XOFF (IO_TYPECAST_UDWORD 0xb0000064)
+#define R_SERIAL0_XOFF__tx_stop__BITNR 9
+#define R_SERIAL0_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL0_XOFF__tx_stop__enable 0
+#define R_SERIAL0_XOFF__tx_stop__stop 1
+#define R_SERIAL0_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL0_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL0_XOFF__auto_xoff__disable 0
+#define R_SERIAL0_XOFF__auto_xoff__enable 1
+#define R_SERIAL0_XOFF__xoff_char__BITNR 0
+#define R_SERIAL0_XOFF__xoff_char__WIDTH 8
+
+#define R_SERIAL1_CTRL (IO_TYPECAST_UDWORD 0xb0000068)
+#define R_SERIAL1_CTRL__tr_baud__BITNR 28
+#define R_SERIAL1_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL1_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL1_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL1_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL1_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL1_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL1_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL1_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL1_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL1_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL1_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL1_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL1_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL1_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL1_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL1_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL1_CTRL__tr_baud__reserved 15
+#define R_SERIAL1_CTRL__rec_baud__BITNR 24
+#define R_SERIAL1_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL1_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL1_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL1_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL1_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL1_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL1_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL1_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL1_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL1_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL1_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL1_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL1_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL1_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL1_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL1_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL1_CTRL__rec_baud__reserved 15
+#define R_SERIAL1_CTRL__dma_err__BITNR 23
+#define R_SERIAL1_CTRL__dma_err__WIDTH 1
+#define R_SERIAL1_CTRL__dma_err__stop 0
+#define R_SERIAL1_CTRL__dma_err__ignore 1
+#define R_SERIAL1_CTRL__rec_enable__BITNR 22
+#define R_SERIAL1_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL1_CTRL__rec_enable__disable 0
+#define R_SERIAL1_CTRL__rec_enable__enable 1
+#define R_SERIAL1_CTRL__rts___BITNR 21
+#define R_SERIAL1_CTRL__rts___WIDTH 1
+#define R_SERIAL1_CTRL__rts___active 0
+#define R_SERIAL1_CTRL__rts___inactive 1
+#define R_SERIAL1_CTRL__sampling__BITNR 20
+#define R_SERIAL1_CTRL__sampling__WIDTH 1
+#define R_SERIAL1_CTRL__sampling__middle 0
+#define R_SERIAL1_CTRL__sampling__majority 1
+#define R_SERIAL1_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL1_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL1_CTRL__rec_stick_par__normal 0
+#define R_SERIAL1_CTRL__rec_stick_par__stick 1
+#define R_SERIAL1_CTRL__rec_par__BITNR 18
+#define R_SERIAL1_CTRL__rec_par__WIDTH 1
+#define R_SERIAL1_CTRL__rec_par__even 0
+#define R_SERIAL1_CTRL__rec_par__odd 1
+#define R_SERIAL1_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL1_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL1_CTRL__rec_par_en__disable 0
+#define R_SERIAL1_CTRL__rec_par_en__enable 1
+#define R_SERIAL1_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL1_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL1_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL1_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL1_CTRL__txd__BITNR 15
+#define R_SERIAL1_CTRL__txd__WIDTH 1
+#define R_SERIAL1_CTRL__tr_enable__BITNR 14
+#define R_SERIAL1_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL1_CTRL__tr_enable__disable 0
+#define R_SERIAL1_CTRL__tr_enable__enable 1
+#define R_SERIAL1_CTRL__auto_cts__BITNR 13
+#define R_SERIAL1_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL1_CTRL__auto_cts__disabled 0
+#define R_SERIAL1_CTRL__auto_cts__active 1
+#define R_SERIAL1_CTRL__stop_bits__BITNR 12
+#define R_SERIAL1_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL1_CTRL__stop_bits__one_bit 0
+#define R_SERIAL1_CTRL__stop_bits__two_bits 1
+#define R_SERIAL1_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL1_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL1_CTRL__tr_stick_par__normal 0
+#define R_SERIAL1_CTRL__tr_stick_par__stick 1
+#define R_SERIAL1_CTRL__tr_par__BITNR 10
+#define R_SERIAL1_CTRL__tr_par__WIDTH 1
+#define R_SERIAL1_CTRL__tr_par__even 0
+#define R_SERIAL1_CTRL__tr_par__odd 1
+#define R_SERIAL1_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL1_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL1_CTRL__tr_par_en__disable 0
+#define R_SERIAL1_CTRL__tr_par_en__enable 1
+#define R_SERIAL1_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL1_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL1_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL1_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL1_CTRL__data_out__BITNR 0
+#define R_SERIAL1_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL1_BAUD (IO_TYPECAST_BYTE 0xb000006b)
+#define R_SERIAL1_BAUD__tr_baud__BITNR 4
+#define R_SERIAL1_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL1_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL1_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL1_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL1_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL1_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL1_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL1_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL1_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL1_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL1_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL1_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL1_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL1_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL1_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL1_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL1_BAUD__tr_baud__reserved 15
+#define R_SERIAL1_BAUD__rec_baud__BITNR 0
+#define R_SERIAL1_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL1_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL1_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL1_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL1_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL1_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL1_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL1_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL1_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL1_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL1_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL1_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL1_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL1_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL1_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL1_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL1_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL1_REC_CTRL (IO_TYPECAST_BYTE 0xb000006a)
+#define R_SERIAL1_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL1_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL1_REC_CTRL__dma_err__stop 0
+#define R_SERIAL1_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL1_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL1_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL1_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL1_REC_CTRL__rts___BITNR 5
+#define R_SERIAL1_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL1_REC_CTRL__rts___active 0
+#define R_SERIAL1_REC_CTRL__rts___inactive 1
+#define R_SERIAL1_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL1_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL1_REC_CTRL__sampling__middle 0
+#define R_SERIAL1_REC_CTRL__sampling__majority 1
+#define R_SERIAL1_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL1_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL1_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL1_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL1_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_par__even 0
+#define R_SERIAL1_REC_CTRL__rec_par__odd 1
+#define R_SERIAL1_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL1_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL1_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL1_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL1_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL1_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL1_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL1_TR_CTRL (IO_TYPECAST_BYTE 0xb0000069)
+#define R_SERIAL1_TR_CTRL__txd__BITNR 7
+#define R_SERIAL1_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL1_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL1_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL1_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL1_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL1_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL1_TR_CTRL__auto_cts__active 1
+#define R_SERIAL1_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL1_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL1_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL1_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL1_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL1_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL1_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL1_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL1_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_par__even 0
+#define R_SERIAL1_TR_CTRL__tr_par__odd 1
+#define R_SERIAL1_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL1_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL1_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL1_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL1_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL1_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL1_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL1_TR_DATA (IO_TYPECAST_BYTE 0xb0000068)
+#define R_SERIAL1_TR_DATA__data_out__BITNR 0
+#define R_SERIAL1_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL1_READ (IO_TYPECAST_RO_UDWORD 0xb0000068)
+#define R_SERIAL1_READ__xoff_detect__BITNR 15
+#define R_SERIAL1_READ__xoff_detect__WIDTH 1
+#define R_SERIAL1_READ__xoff_detect__no_xoff 0
+#define R_SERIAL1_READ__xoff_detect__xoff 1
+#define R_SERIAL1_READ__cts___BITNR 14
+#define R_SERIAL1_READ__cts___WIDTH 1
+#define R_SERIAL1_READ__cts___active 0
+#define R_SERIAL1_READ__cts___inactive 1
+#define R_SERIAL1_READ__tr_ready__BITNR 13
+#define R_SERIAL1_READ__tr_ready__WIDTH 1
+#define R_SERIAL1_READ__tr_ready__full 0
+#define R_SERIAL1_READ__tr_ready__ready 1
+#define R_SERIAL1_READ__rxd__BITNR 12
+#define R_SERIAL1_READ__rxd__WIDTH 1
+#define R_SERIAL1_READ__overrun__BITNR 11
+#define R_SERIAL1_READ__overrun__WIDTH 1
+#define R_SERIAL1_READ__overrun__no 0
+#define R_SERIAL1_READ__overrun__yes 1
+#define R_SERIAL1_READ__par_err__BITNR 10
+#define R_SERIAL1_READ__par_err__WIDTH 1
+#define R_SERIAL1_READ__par_err__no 0
+#define R_SERIAL1_READ__par_err__yes 1
+#define R_SERIAL1_READ__framing_err__BITNR 9
+#define R_SERIAL1_READ__framing_err__WIDTH 1
+#define R_SERIAL1_READ__framing_err__no 0
+#define R_SERIAL1_READ__framing_err__yes 1
+#define R_SERIAL1_READ__data_avail__BITNR 8
+#define R_SERIAL1_READ__data_avail__WIDTH 1
+#define R_SERIAL1_READ__data_avail__no 0
+#define R_SERIAL1_READ__data_avail__yes 1
+#define R_SERIAL1_READ__data_in__BITNR 0
+#define R_SERIAL1_READ__data_in__WIDTH 8
+
+#define R_SERIAL1_STATUS (IO_TYPECAST_RO_BYTE 0xb0000069)
+#define R_SERIAL1_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL1_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL1_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL1_STATUS__xoff_detect__xoff 1
+#define R_SERIAL1_STATUS__cts___BITNR 6
+#define R_SERIAL1_STATUS__cts___WIDTH 1
+#define R_SERIAL1_STATUS__cts___active 0
+#define R_SERIAL1_STATUS__cts___inactive 1
+#define R_SERIAL1_STATUS__tr_ready__BITNR 5
+#define R_SERIAL1_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL1_STATUS__tr_ready__full 0
+#define R_SERIAL1_STATUS__tr_ready__ready 1
+#define R_SERIAL1_STATUS__rxd__BITNR 4
+#define R_SERIAL1_STATUS__rxd__WIDTH 1
+#define R_SERIAL1_STATUS__overrun__BITNR 3
+#define R_SERIAL1_STATUS__overrun__WIDTH 1
+#define R_SERIAL1_STATUS__overrun__no 0
+#define R_SERIAL1_STATUS__overrun__yes 1
+#define R_SERIAL1_STATUS__par_err__BITNR 2
+#define R_SERIAL1_STATUS__par_err__WIDTH 1
+#define R_SERIAL1_STATUS__par_err__no 0
+#define R_SERIAL1_STATUS__par_err__yes 1
+#define R_SERIAL1_STATUS__framing_err__BITNR 1
+#define R_SERIAL1_STATUS__framing_err__WIDTH 1
+#define R_SERIAL1_STATUS__framing_err__no 0
+#define R_SERIAL1_STATUS__framing_err__yes 1
+#define R_SERIAL1_STATUS__data_avail__BITNR 0
+#define R_SERIAL1_STATUS__data_avail__WIDTH 1
+#define R_SERIAL1_STATUS__data_avail__no 0
+#define R_SERIAL1_STATUS__data_avail__yes 1
+
+#define R_SERIAL1_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000068)
+#define R_SERIAL1_REC_DATA__data_in__BITNR 0
+#define R_SERIAL1_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL1_XOFF (IO_TYPECAST_UDWORD 0xb000006c)
+#define R_SERIAL1_XOFF__tx_stop__BITNR 9
+#define R_SERIAL1_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL1_XOFF__tx_stop__enable 0
+#define R_SERIAL1_XOFF__tx_stop__stop 1
+#define R_SERIAL1_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL1_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL1_XOFF__auto_xoff__disable 0
+#define R_SERIAL1_XOFF__auto_xoff__enable 1
+#define R_SERIAL1_XOFF__xoff_char__BITNR 0
+#define R_SERIAL1_XOFF__xoff_char__WIDTH 8
+
+#define R_SERIAL2_CTRL (IO_TYPECAST_UDWORD 0xb0000070)
+#define R_SERIAL2_CTRL__tr_baud__BITNR 28
+#define R_SERIAL2_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL2_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL2_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL2_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL2_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL2_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL2_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL2_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL2_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL2_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL2_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL2_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL2_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL2_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL2_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL2_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL2_CTRL__tr_baud__reserved 15
+#define R_SERIAL2_CTRL__rec_baud__BITNR 24
+#define R_SERIAL2_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL2_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL2_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL2_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL2_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL2_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL2_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL2_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL2_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL2_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL2_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL2_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL2_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL2_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL2_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL2_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL2_CTRL__rec_baud__reserved 15
+#define R_SERIAL2_CTRL__dma_err__BITNR 23
+#define R_SERIAL2_CTRL__dma_err__WIDTH 1
+#define R_SERIAL2_CTRL__dma_err__stop 0
+#define R_SERIAL2_CTRL__dma_err__ignore 1
+#define R_SERIAL2_CTRL__rec_enable__BITNR 22
+#define R_SERIAL2_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL2_CTRL__rec_enable__disable 0
+#define R_SERIAL2_CTRL__rec_enable__enable 1
+#define R_SERIAL2_CTRL__rts___BITNR 21
+#define R_SERIAL2_CTRL__rts___WIDTH 1
+#define R_SERIAL2_CTRL__rts___active 0
+#define R_SERIAL2_CTRL__rts___inactive 1
+#define R_SERIAL2_CTRL__sampling__BITNR 20
+#define R_SERIAL2_CTRL__sampling__WIDTH 1
+#define R_SERIAL2_CTRL__sampling__middle 0
+#define R_SERIAL2_CTRL__sampling__majority 1
+#define R_SERIAL2_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL2_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL2_CTRL__rec_stick_par__normal 0
+#define R_SERIAL2_CTRL__rec_stick_par__stick 1
+#define R_SERIAL2_CTRL__rec_par__BITNR 18
+#define R_SERIAL2_CTRL__rec_par__WIDTH 1
+#define R_SERIAL2_CTRL__rec_par__even 0
+#define R_SERIAL2_CTRL__rec_par__odd 1
+#define R_SERIAL2_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL2_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL2_CTRL__rec_par_en__disable 0
+#define R_SERIAL2_CTRL__rec_par_en__enable 1
+#define R_SERIAL2_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL2_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL2_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL2_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL2_CTRL__txd__BITNR 15
+#define R_SERIAL2_CTRL__txd__WIDTH 1
+#define R_SERIAL2_CTRL__tr_enable__BITNR 14
+#define R_SERIAL2_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL2_CTRL__tr_enable__disable 0
+#define R_SERIAL2_CTRL__tr_enable__enable 1
+#define R_SERIAL2_CTRL__auto_cts__BITNR 13
+#define R_SERIAL2_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL2_CTRL__auto_cts__disabled 0
+#define R_SERIAL2_CTRL__auto_cts__active 1
+#define R_SERIAL2_CTRL__stop_bits__BITNR 12
+#define R_SERIAL2_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL2_CTRL__stop_bits__one_bit 0
+#define R_SERIAL2_CTRL__stop_bits__two_bits 1
+#define R_SERIAL2_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL2_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL2_CTRL__tr_stick_par__normal 0
+#define R_SERIAL2_CTRL__tr_stick_par__stick 1
+#define R_SERIAL2_CTRL__tr_par__BITNR 10
+#define R_SERIAL2_CTRL__tr_par__WIDTH 1
+#define R_SERIAL2_CTRL__tr_par__even 0
+#define R_SERIAL2_CTRL__tr_par__odd 1
+#define R_SERIAL2_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL2_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL2_CTRL__tr_par_en__disable 0
+#define R_SERIAL2_CTRL__tr_par_en__enable 1
+#define R_SERIAL2_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL2_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL2_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL2_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL2_CTRL__data_out__BITNR 0
+#define R_SERIAL2_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL2_BAUD (IO_TYPECAST_BYTE 0xb0000073)
+#define R_SERIAL2_BAUD__tr_baud__BITNR 4
+#define R_SERIAL2_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL2_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL2_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL2_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL2_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL2_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL2_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL2_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL2_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL2_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL2_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL2_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL2_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL2_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL2_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL2_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL2_BAUD__tr_baud__reserved 15
+#define R_SERIAL2_BAUD__rec_baud__BITNR 0
+#define R_SERIAL2_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL2_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL2_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL2_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL2_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL2_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL2_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL2_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL2_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL2_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL2_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL2_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL2_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL2_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL2_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL2_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL2_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL2_REC_CTRL (IO_TYPECAST_BYTE 0xb0000072)
+#define R_SERIAL2_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL2_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL2_REC_CTRL__dma_err__stop 0
+#define R_SERIAL2_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL2_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL2_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL2_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL2_REC_CTRL__rts___BITNR 5
+#define R_SERIAL2_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL2_REC_CTRL__rts___active 0
+#define R_SERIAL2_REC_CTRL__rts___inactive 1
+#define R_SERIAL2_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL2_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL2_REC_CTRL__sampling__middle 0
+#define R_SERIAL2_REC_CTRL__sampling__majority 1
+#define R_SERIAL2_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL2_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL2_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL2_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL2_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_par__even 0
+#define R_SERIAL2_REC_CTRL__rec_par__odd 1
+#define R_SERIAL2_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL2_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL2_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL2_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL2_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL2_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL2_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL2_TR_CTRL (IO_TYPECAST_BYTE 0xb0000071)
+#define R_SERIAL2_TR_CTRL__txd__BITNR 7
+#define R_SERIAL2_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL2_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL2_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL2_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL2_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL2_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL2_TR_CTRL__auto_cts__active 1
+#define R_SERIAL2_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL2_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL2_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL2_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL2_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL2_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL2_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL2_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL2_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_par__even 0
+#define R_SERIAL2_TR_CTRL__tr_par__odd 1
+#define R_SERIAL2_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL2_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL2_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL2_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL2_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL2_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL2_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL2_TR_DATA (IO_TYPECAST_BYTE 0xb0000070)
+#define R_SERIAL2_TR_DATA__data_out__BITNR 0
+#define R_SERIAL2_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL2_READ (IO_TYPECAST_RO_UDWORD 0xb0000070)
+#define R_SERIAL2_READ__xoff_detect__BITNR 15
+#define R_SERIAL2_READ__xoff_detect__WIDTH 1
+#define R_SERIAL2_READ__xoff_detect__no_xoff 0
+#define R_SERIAL2_READ__xoff_detect__xoff 1
+#define R_SERIAL2_READ__cts___BITNR 14
+#define R_SERIAL2_READ__cts___WIDTH 1
+#define R_SERIAL2_READ__cts___active 0
+#define R_SERIAL2_READ__cts___inactive 1
+#define R_SERIAL2_READ__tr_ready__BITNR 13
+#define R_SERIAL2_READ__tr_ready__WIDTH 1
+#define R_SERIAL2_READ__tr_ready__full 0
+#define R_SERIAL2_READ__tr_ready__ready 1
+#define R_SERIAL2_READ__rxd__BITNR 12
+#define R_SERIAL2_READ__rxd__WIDTH 1
+#define R_SERIAL2_READ__overrun__BITNR 11
+#define R_SERIAL2_READ__overrun__WIDTH 1
+#define R_SERIAL2_READ__overrun__no 0
+#define R_SERIAL2_READ__overrun__yes 1
+#define R_SERIAL2_READ__par_err__BITNR 10
+#define R_SERIAL2_READ__par_err__WIDTH 1
+#define R_SERIAL2_READ__par_err__no 0
+#define R_SERIAL2_READ__par_err__yes 1
+#define R_SERIAL2_READ__framing_err__BITNR 9
+#define R_SERIAL2_READ__framing_err__WIDTH 1
+#define R_SERIAL2_READ__framing_err__no 0
+#define R_SERIAL2_READ__framing_err__yes 1
+#define R_SERIAL2_READ__data_avail__BITNR 8
+#define R_SERIAL2_READ__data_avail__WIDTH 1
+#define R_SERIAL2_READ__data_avail__no 0
+#define R_SERIAL2_READ__data_avail__yes 1
+#define R_SERIAL2_READ__data_in__BITNR 0
+#define R_SERIAL2_READ__data_in__WIDTH 8
+
+#define R_SERIAL2_STATUS (IO_TYPECAST_RO_BYTE 0xb0000071)
+#define R_SERIAL2_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL2_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL2_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL2_STATUS__xoff_detect__xoff 1
+#define R_SERIAL2_STATUS__cts___BITNR 6
+#define R_SERIAL2_STATUS__cts___WIDTH 1
+#define R_SERIAL2_STATUS__cts___active 0
+#define R_SERIAL2_STATUS__cts___inactive 1
+#define R_SERIAL2_STATUS__tr_ready__BITNR 5
+#define R_SERIAL2_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL2_STATUS__tr_ready__full 0
+#define R_SERIAL2_STATUS__tr_ready__ready 1
+#define R_SERIAL2_STATUS__rxd__BITNR 4
+#define R_SERIAL2_STATUS__rxd__WIDTH 1
+#define R_SERIAL2_STATUS__overrun__BITNR 3
+#define R_SERIAL2_STATUS__overrun__WIDTH 1
+#define R_SERIAL2_STATUS__overrun__no 0
+#define R_SERIAL2_STATUS__overrun__yes 1
+#define R_SERIAL2_STATUS__par_err__BITNR 2
+#define R_SERIAL2_STATUS__par_err__WIDTH 1
+#define R_SERIAL2_STATUS__par_err__no 0
+#define R_SERIAL2_STATUS__par_err__yes 1
+#define R_SERIAL2_STATUS__framing_err__BITNR 1
+#define R_SERIAL2_STATUS__framing_err__WIDTH 1
+#define R_SERIAL2_STATUS__framing_err__no 0
+#define R_SERIAL2_STATUS__framing_err__yes 1
+#define R_SERIAL2_STATUS__data_avail__BITNR 0
+#define R_SERIAL2_STATUS__data_avail__WIDTH 1
+#define R_SERIAL2_STATUS__data_avail__no 0
+#define R_SERIAL2_STATUS__data_avail__yes 1
+
+#define R_SERIAL2_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000070)
+#define R_SERIAL2_REC_DATA__data_in__BITNR 0
+#define R_SERIAL2_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL2_XOFF (IO_TYPECAST_UDWORD 0xb0000074)
+#define R_SERIAL2_XOFF__tx_stop__BITNR 9
+#define R_SERIAL2_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL2_XOFF__tx_stop__enable 0
+#define R_SERIAL2_XOFF__tx_stop__stop 1
+#define R_SERIAL2_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL2_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL2_XOFF__auto_xoff__disable 0
+#define R_SERIAL2_XOFF__auto_xoff__enable 1
+#define R_SERIAL2_XOFF__xoff_char__BITNR 0
+#define R_SERIAL2_XOFF__xoff_char__WIDTH 8
+
+#define R_SERIAL3_CTRL (IO_TYPECAST_UDWORD 0xb0000078)
+#define R_SERIAL3_CTRL__tr_baud__BITNR 28
+#define R_SERIAL3_CTRL__tr_baud__WIDTH 4
+#define R_SERIAL3_CTRL__tr_baud__c300Hz 0
+#define R_SERIAL3_CTRL__tr_baud__c600Hz 1
+#define R_SERIAL3_CTRL__tr_baud__c1200Hz 2
+#define R_SERIAL3_CTRL__tr_baud__c2400Hz 3
+#define R_SERIAL3_CTRL__tr_baud__c4800Hz 4
+#define R_SERIAL3_CTRL__tr_baud__c9600Hz 5
+#define R_SERIAL3_CTRL__tr_baud__c19k2Hz 6
+#define R_SERIAL3_CTRL__tr_baud__c38k4Hz 7
+#define R_SERIAL3_CTRL__tr_baud__c57k6Hz 8
+#define R_SERIAL3_CTRL__tr_baud__c115k2Hz 9
+#define R_SERIAL3_CTRL__tr_baud__c230k4Hz 10
+#define R_SERIAL3_CTRL__tr_baud__c460k8Hz 11
+#define R_SERIAL3_CTRL__tr_baud__c921k6Hz 12
+#define R_SERIAL3_CTRL__tr_baud__c1843k2Hz 13
+#define R_SERIAL3_CTRL__tr_baud__c6250kHz 14
+#define R_SERIAL3_CTRL__tr_baud__reserved 15
+#define R_SERIAL3_CTRL__rec_baud__BITNR 24
+#define R_SERIAL3_CTRL__rec_baud__WIDTH 4
+#define R_SERIAL3_CTRL__rec_baud__c300Hz 0
+#define R_SERIAL3_CTRL__rec_baud__c600Hz 1
+#define R_SERIAL3_CTRL__rec_baud__c1200Hz 2
+#define R_SERIAL3_CTRL__rec_baud__c2400Hz 3
+#define R_SERIAL3_CTRL__rec_baud__c4800Hz 4
+#define R_SERIAL3_CTRL__rec_baud__c9600Hz 5
+#define R_SERIAL3_CTRL__rec_baud__c19k2Hz 6
+#define R_SERIAL3_CTRL__rec_baud__c38k4Hz 7
+#define R_SERIAL3_CTRL__rec_baud__c57k6Hz 8
+#define R_SERIAL3_CTRL__rec_baud__c115k2Hz 9
+#define R_SERIAL3_CTRL__rec_baud__c230k4Hz 10
+#define R_SERIAL3_CTRL__rec_baud__c460k8Hz 11
+#define R_SERIAL3_CTRL__rec_baud__c921k6Hz 12
+#define R_SERIAL3_CTRL__rec_baud__c1843k2Hz 13
+#define R_SERIAL3_CTRL__rec_baud__c6250kHz 14
+#define R_SERIAL3_CTRL__rec_baud__reserved 15
+#define R_SERIAL3_CTRL__dma_err__BITNR 23
+#define R_SERIAL3_CTRL__dma_err__WIDTH 1
+#define R_SERIAL3_CTRL__dma_err__stop 0
+#define R_SERIAL3_CTRL__dma_err__ignore 1
+#define R_SERIAL3_CTRL__rec_enable__BITNR 22
+#define R_SERIAL3_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL3_CTRL__rec_enable__disable 0
+#define R_SERIAL3_CTRL__rec_enable__enable 1
+#define R_SERIAL3_CTRL__rts___BITNR 21
+#define R_SERIAL3_CTRL__rts___WIDTH 1
+#define R_SERIAL3_CTRL__rts___active 0
+#define R_SERIAL3_CTRL__rts___inactive 1
+#define R_SERIAL3_CTRL__sampling__BITNR 20
+#define R_SERIAL3_CTRL__sampling__WIDTH 1
+#define R_SERIAL3_CTRL__sampling__middle 0
+#define R_SERIAL3_CTRL__sampling__majority 1
+#define R_SERIAL3_CTRL__rec_stick_par__BITNR 19
+#define R_SERIAL3_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL3_CTRL__rec_stick_par__normal 0
+#define R_SERIAL3_CTRL__rec_stick_par__stick 1
+#define R_SERIAL3_CTRL__rec_par__BITNR 18
+#define R_SERIAL3_CTRL__rec_par__WIDTH 1
+#define R_SERIAL3_CTRL__rec_par__even 0
+#define R_SERIAL3_CTRL__rec_par__odd 1
+#define R_SERIAL3_CTRL__rec_par_en__BITNR 17
+#define R_SERIAL3_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL3_CTRL__rec_par_en__disable 0
+#define R_SERIAL3_CTRL__rec_par_en__enable 1
+#define R_SERIAL3_CTRL__rec_bitnr__BITNR 16
+#define R_SERIAL3_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL3_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL3_CTRL__rec_bitnr__rec_7bit 1
+#define R_SERIAL3_CTRL__txd__BITNR 15
+#define R_SERIAL3_CTRL__txd__WIDTH 1
+#define R_SERIAL3_CTRL__tr_enable__BITNR 14
+#define R_SERIAL3_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL3_CTRL__tr_enable__disable 0
+#define R_SERIAL3_CTRL__tr_enable__enable 1
+#define R_SERIAL3_CTRL__auto_cts__BITNR 13
+#define R_SERIAL3_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL3_CTRL__auto_cts__disabled 0
+#define R_SERIAL3_CTRL__auto_cts__active 1
+#define R_SERIAL3_CTRL__stop_bits__BITNR 12
+#define R_SERIAL3_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL3_CTRL__stop_bits__one_bit 0
+#define R_SERIAL3_CTRL__stop_bits__two_bits 1
+#define R_SERIAL3_CTRL__tr_stick_par__BITNR 11
+#define R_SERIAL3_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL3_CTRL__tr_stick_par__normal 0
+#define R_SERIAL3_CTRL__tr_stick_par__stick 1
+#define R_SERIAL3_CTRL__tr_par__BITNR 10
+#define R_SERIAL3_CTRL__tr_par__WIDTH 1
+#define R_SERIAL3_CTRL__tr_par__even 0
+#define R_SERIAL3_CTRL__tr_par__odd 1
+#define R_SERIAL3_CTRL__tr_par_en__BITNR 9
+#define R_SERIAL3_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL3_CTRL__tr_par_en__disable 0
+#define R_SERIAL3_CTRL__tr_par_en__enable 1
+#define R_SERIAL3_CTRL__tr_bitnr__BITNR 8
+#define R_SERIAL3_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL3_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL3_CTRL__tr_bitnr__tr_7bit 1
+#define R_SERIAL3_CTRL__data_out__BITNR 0
+#define R_SERIAL3_CTRL__data_out__WIDTH 8
+
+#define R_SERIAL3_BAUD (IO_TYPECAST_BYTE 0xb000007b)
+#define R_SERIAL3_BAUD__tr_baud__BITNR 4
+#define R_SERIAL3_BAUD__tr_baud__WIDTH 4
+#define R_SERIAL3_BAUD__tr_baud__c300Hz 0
+#define R_SERIAL3_BAUD__tr_baud__c600Hz 1
+#define R_SERIAL3_BAUD__tr_baud__c1200Hz 2
+#define R_SERIAL3_BAUD__tr_baud__c2400Hz 3
+#define R_SERIAL3_BAUD__tr_baud__c4800Hz 4
+#define R_SERIAL3_BAUD__tr_baud__c9600Hz 5
+#define R_SERIAL3_BAUD__tr_baud__c19k2Hz 6
+#define R_SERIAL3_BAUD__tr_baud__c38k4Hz 7
+#define R_SERIAL3_BAUD__tr_baud__c57k6Hz 8
+#define R_SERIAL3_BAUD__tr_baud__c115k2Hz 9
+#define R_SERIAL3_BAUD__tr_baud__c230k4Hz 10
+#define R_SERIAL3_BAUD__tr_baud__c460k8Hz 11
+#define R_SERIAL3_BAUD__tr_baud__c921k6Hz 12
+#define R_SERIAL3_BAUD__tr_baud__c1843k2Hz 13
+#define R_SERIAL3_BAUD__tr_baud__c6250kHz 14
+#define R_SERIAL3_BAUD__tr_baud__reserved 15
+#define R_SERIAL3_BAUD__rec_baud__BITNR 0
+#define R_SERIAL3_BAUD__rec_baud__WIDTH 4
+#define R_SERIAL3_BAUD__rec_baud__c300Hz 0
+#define R_SERIAL3_BAUD__rec_baud__c600Hz 1
+#define R_SERIAL3_BAUD__rec_baud__c1200Hz 2
+#define R_SERIAL3_BAUD__rec_baud__c2400Hz 3
+#define R_SERIAL3_BAUD__rec_baud__c4800Hz 4
+#define R_SERIAL3_BAUD__rec_baud__c9600Hz 5
+#define R_SERIAL3_BAUD__rec_baud__c19k2Hz 6
+#define R_SERIAL3_BAUD__rec_baud__c38k4Hz 7
+#define R_SERIAL3_BAUD__rec_baud__c57k6Hz 8
+#define R_SERIAL3_BAUD__rec_baud__c115k2Hz 9
+#define R_SERIAL3_BAUD__rec_baud__c230k4Hz 10
+#define R_SERIAL3_BAUD__rec_baud__c460k8Hz 11
+#define R_SERIAL3_BAUD__rec_baud__c921k6Hz 12
+#define R_SERIAL3_BAUD__rec_baud__c1843k2Hz 13
+#define R_SERIAL3_BAUD__rec_baud__c6250kHz 14
+#define R_SERIAL3_BAUD__rec_baud__reserved 15
+
+#define R_SERIAL3_REC_CTRL (IO_TYPECAST_BYTE 0xb000007a)
+#define R_SERIAL3_REC_CTRL__dma_err__BITNR 7
+#define R_SERIAL3_REC_CTRL__dma_err__WIDTH 1
+#define R_SERIAL3_REC_CTRL__dma_err__stop 0
+#define R_SERIAL3_REC_CTRL__dma_err__ignore 1
+#define R_SERIAL3_REC_CTRL__rec_enable__BITNR 6
+#define R_SERIAL3_REC_CTRL__rec_enable__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_enable__disable 0
+#define R_SERIAL3_REC_CTRL__rec_enable__enable 1
+#define R_SERIAL3_REC_CTRL__rts___BITNR 5
+#define R_SERIAL3_REC_CTRL__rts___WIDTH 1
+#define R_SERIAL3_REC_CTRL__rts___active 0
+#define R_SERIAL3_REC_CTRL__rts___inactive 1
+#define R_SERIAL3_REC_CTRL__sampling__BITNR 4
+#define R_SERIAL3_REC_CTRL__sampling__WIDTH 1
+#define R_SERIAL3_REC_CTRL__sampling__middle 0
+#define R_SERIAL3_REC_CTRL__sampling__majority 1
+#define R_SERIAL3_REC_CTRL__rec_stick_par__BITNR 3
+#define R_SERIAL3_REC_CTRL__rec_stick_par__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_stick_par__normal 0
+#define R_SERIAL3_REC_CTRL__rec_stick_par__stick 1
+#define R_SERIAL3_REC_CTRL__rec_par__BITNR 2
+#define R_SERIAL3_REC_CTRL__rec_par__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_par__even 0
+#define R_SERIAL3_REC_CTRL__rec_par__odd 1
+#define R_SERIAL3_REC_CTRL__rec_par_en__BITNR 1
+#define R_SERIAL3_REC_CTRL__rec_par_en__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_par_en__disable 0
+#define R_SERIAL3_REC_CTRL__rec_par_en__enable 1
+#define R_SERIAL3_REC_CTRL__rec_bitnr__BITNR 0
+#define R_SERIAL3_REC_CTRL__rec_bitnr__WIDTH 1
+#define R_SERIAL3_REC_CTRL__rec_bitnr__rec_8bit 0
+#define R_SERIAL3_REC_CTRL__rec_bitnr__rec_7bit 1
+
+#define R_SERIAL3_TR_CTRL (IO_TYPECAST_BYTE 0xb0000079)
+#define R_SERIAL3_TR_CTRL__txd__BITNR 7
+#define R_SERIAL3_TR_CTRL__txd__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_enable__BITNR 6
+#define R_SERIAL3_TR_CTRL__tr_enable__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_enable__disable 0
+#define R_SERIAL3_TR_CTRL__tr_enable__enable 1
+#define R_SERIAL3_TR_CTRL__auto_cts__BITNR 5
+#define R_SERIAL3_TR_CTRL__auto_cts__WIDTH 1
+#define R_SERIAL3_TR_CTRL__auto_cts__disabled 0
+#define R_SERIAL3_TR_CTRL__auto_cts__active 1
+#define R_SERIAL3_TR_CTRL__stop_bits__BITNR 4
+#define R_SERIAL3_TR_CTRL__stop_bits__WIDTH 1
+#define R_SERIAL3_TR_CTRL__stop_bits__one_bit 0
+#define R_SERIAL3_TR_CTRL__stop_bits__two_bits 1
+#define R_SERIAL3_TR_CTRL__tr_stick_par__BITNR 3
+#define R_SERIAL3_TR_CTRL__tr_stick_par__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_stick_par__normal 0
+#define R_SERIAL3_TR_CTRL__tr_stick_par__stick 1
+#define R_SERIAL3_TR_CTRL__tr_par__BITNR 2
+#define R_SERIAL3_TR_CTRL__tr_par__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_par__even 0
+#define R_SERIAL3_TR_CTRL__tr_par__odd 1
+#define R_SERIAL3_TR_CTRL__tr_par_en__BITNR 1
+#define R_SERIAL3_TR_CTRL__tr_par_en__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_par_en__disable 0
+#define R_SERIAL3_TR_CTRL__tr_par_en__enable 1
+#define R_SERIAL3_TR_CTRL__tr_bitnr__BITNR 0
+#define R_SERIAL3_TR_CTRL__tr_bitnr__WIDTH 1
+#define R_SERIAL3_TR_CTRL__tr_bitnr__tr_8bit 0
+#define R_SERIAL3_TR_CTRL__tr_bitnr__tr_7bit 1
+
+#define R_SERIAL3_TR_DATA (IO_TYPECAST_BYTE 0xb0000078)
+#define R_SERIAL3_TR_DATA__data_out__BITNR 0
+#define R_SERIAL3_TR_DATA__data_out__WIDTH 8
+
+#define R_SERIAL3_READ (IO_TYPECAST_RO_UDWORD 0xb0000078)
+#define R_SERIAL3_READ__xoff_detect__BITNR 15
+#define R_SERIAL3_READ__xoff_detect__WIDTH 1
+#define R_SERIAL3_READ__xoff_detect__no_xoff 0
+#define R_SERIAL3_READ__xoff_detect__xoff 1
+#define R_SERIAL3_READ__cts___BITNR 14
+#define R_SERIAL3_READ__cts___WIDTH 1
+#define R_SERIAL3_READ__cts___active 0
+#define R_SERIAL3_READ__cts___inactive 1
+#define R_SERIAL3_READ__tr_ready__BITNR 13
+#define R_SERIAL3_READ__tr_ready__WIDTH 1
+#define R_SERIAL3_READ__tr_ready__full 0
+#define R_SERIAL3_READ__tr_ready__ready 1
+#define R_SERIAL3_READ__rxd__BITNR 12
+#define R_SERIAL3_READ__rxd__WIDTH 1
+#define R_SERIAL3_READ__overrun__BITNR 11
+#define R_SERIAL3_READ__overrun__WIDTH 1
+#define R_SERIAL3_READ__overrun__no 0
+#define R_SERIAL3_READ__overrun__yes 1
+#define R_SERIAL3_READ__par_err__BITNR 10
+#define R_SERIAL3_READ__par_err__WIDTH 1
+#define R_SERIAL3_READ__par_err__no 0
+#define R_SERIAL3_READ__par_err__yes 1
+#define R_SERIAL3_READ__framing_err__BITNR 9
+#define R_SERIAL3_READ__framing_err__WIDTH 1
+#define R_SERIAL3_READ__framing_err__no 0
+#define R_SERIAL3_READ__framing_err__yes 1
+#define R_SERIAL3_READ__data_avail__BITNR 8
+#define R_SERIAL3_READ__data_avail__WIDTH 1
+#define R_SERIAL3_READ__data_avail__no 0
+#define R_SERIAL3_READ__data_avail__yes 1
+#define R_SERIAL3_READ__data_in__BITNR 0
+#define R_SERIAL3_READ__data_in__WIDTH 8
+
+#define R_SERIAL3_STATUS (IO_TYPECAST_RO_BYTE 0xb0000079)
+#define R_SERIAL3_STATUS__xoff_detect__BITNR 7
+#define R_SERIAL3_STATUS__xoff_detect__WIDTH 1
+#define R_SERIAL3_STATUS__xoff_detect__no_xoff 0
+#define R_SERIAL3_STATUS__xoff_detect__xoff 1
+#define R_SERIAL3_STATUS__cts___BITNR 6
+#define R_SERIAL3_STATUS__cts___WIDTH 1
+#define R_SERIAL3_STATUS__cts___active 0
+#define R_SERIAL3_STATUS__cts___inactive 1
+#define R_SERIAL3_STATUS__tr_ready__BITNR 5
+#define R_SERIAL3_STATUS__tr_ready__WIDTH 1
+#define R_SERIAL3_STATUS__tr_ready__full 0
+#define R_SERIAL3_STATUS__tr_ready__ready 1
+#define R_SERIAL3_STATUS__rxd__BITNR 4
+#define R_SERIAL3_STATUS__rxd__WIDTH 1
+#define R_SERIAL3_STATUS__overrun__BITNR 3
+#define R_SERIAL3_STATUS__overrun__WIDTH 1
+#define R_SERIAL3_STATUS__overrun__no 0
+#define R_SERIAL3_STATUS__overrun__yes 1
+#define R_SERIAL3_STATUS__par_err__BITNR 2
+#define R_SERIAL3_STATUS__par_err__WIDTH 1
+#define R_SERIAL3_STATUS__par_err__no 0
+#define R_SERIAL3_STATUS__par_err__yes 1
+#define R_SERIAL3_STATUS__framing_err__BITNR 1
+#define R_SERIAL3_STATUS__framing_err__WIDTH 1
+#define R_SERIAL3_STATUS__framing_err__no 0
+#define R_SERIAL3_STATUS__framing_err__yes 1
+#define R_SERIAL3_STATUS__data_avail__BITNR 0
+#define R_SERIAL3_STATUS__data_avail__WIDTH 1
+#define R_SERIAL3_STATUS__data_avail__no 0
+#define R_SERIAL3_STATUS__data_avail__yes 1
+
+#define R_SERIAL3_REC_DATA (IO_TYPECAST_RO_BYTE 0xb0000078)
+#define R_SERIAL3_REC_DATA__data_in__BITNR 0
+#define R_SERIAL3_REC_DATA__data_in__WIDTH 8
+
+#define R_SERIAL3_XOFF (IO_TYPECAST_UDWORD 0xb000007c)
+#define R_SERIAL3_XOFF__tx_stop__BITNR 9
+#define R_SERIAL3_XOFF__tx_stop__WIDTH 1
+#define R_SERIAL3_XOFF__tx_stop__enable 0
+#define R_SERIAL3_XOFF__tx_stop__stop 1
+#define R_SERIAL3_XOFF__auto_xoff__BITNR 8
+#define R_SERIAL3_XOFF__auto_xoff__WIDTH 1
+#define R_SERIAL3_XOFF__auto_xoff__disable 0
+#define R_SERIAL3_XOFF__auto_xoff__enable 1
+#define R_SERIAL3_XOFF__xoff_char__BITNR 0
+#define R_SERIAL3_XOFF__xoff_char__WIDTH 8
+
+#define R_ALT_SER_BAUDRATE (IO_TYPECAST_UDWORD 0xb000005c)
+#define R_ALT_SER_BAUDRATE__ser3_tr__BITNR 28
+#define R_ALT_SER_BAUDRATE__ser3_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser3_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser3_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser3_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser3_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser3_rec__BITNR 24
+#define R_ALT_SER_BAUDRATE__ser3_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser3_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser3_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser3_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser3_rec__timer 3
+#define R_ALT_SER_BAUDRATE__ser2_tr__BITNR 20
+#define R_ALT_SER_BAUDRATE__ser2_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser2_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser2_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser2_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser2_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser2_rec__BITNR 16
+#define R_ALT_SER_BAUDRATE__ser2_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser2_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser2_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser2_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser2_rec__timer 3
+#define R_ALT_SER_BAUDRATE__ser1_tr__BITNR 12
+#define R_ALT_SER_BAUDRATE__ser1_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser1_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser1_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser1_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser1_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser1_rec__BITNR 8
+#define R_ALT_SER_BAUDRATE__ser1_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser1_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser1_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser1_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser1_rec__timer 3
+#define R_ALT_SER_BAUDRATE__ser0_tr__BITNR 4
+#define R_ALT_SER_BAUDRATE__ser0_tr__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser0_tr__normal 0
+#define R_ALT_SER_BAUDRATE__ser0_tr__prescale 1
+#define R_ALT_SER_BAUDRATE__ser0_tr__extern 2
+#define R_ALT_SER_BAUDRATE__ser0_tr__timer 3
+#define R_ALT_SER_BAUDRATE__ser0_rec__BITNR 0
+#define R_ALT_SER_BAUDRATE__ser0_rec__WIDTH 2
+#define R_ALT_SER_BAUDRATE__ser0_rec__normal 0
+#define R_ALT_SER_BAUDRATE__ser0_rec__prescale 1
+#define R_ALT_SER_BAUDRATE__ser0_rec__extern 2
+#define R_ALT_SER_BAUDRATE__ser0_rec__timer 3
+
+/*
+!* Network interface registers
+!*/
+
+#define R_NETWORK_SA_0 (IO_TYPECAST_UDWORD 0xb0000080)
+#define R_NETWORK_SA_0__ma0_low__BITNR 0
+#define R_NETWORK_SA_0__ma0_low__WIDTH 32
+
+#define R_NETWORK_SA_1 (IO_TYPECAST_UDWORD 0xb0000084)
+#define R_NETWORK_SA_1__ma1_low__BITNR 16
+#define R_NETWORK_SA_1__ma1_low__WIDTH 16
+#define R_NETWORK_SA_1__ma0_high__BITNR 0
+#define R_NETWORK_SA_1__ma0_high__WIDTH 16
+
+#define R_NETWORK_SA_2 (IO_TYPECAST_UDWORD 0xb0000088)
+#define R_NETWORK_SA_2__ma1_high__BITNR 0
+#define R_NETWORK_SA_2__ma1_high__WIDTH 32
+
+#define R_NETWORK_GA_0 (IO_TYPECAST_UDWORD 0xb000008c)
+#define R_NETWORK_GA_0__ga_low__BITNR 0
+#define R_NETWORK_GA_0__ga_low__WIDTH 32
+
+#define R_NETWORK_GA_1 (IO_TYPECAST_UDWORD 0xb0000090)
+#define R_NETWORK_GA_1__ga_high__BITNR 0
+#define R_NETWORK_GA_1__ga_high__WIDTH 32
+
+#define R_NETWORK_REC_CONFIG (IO_TYPECAST_UDWORD 0xb0000094)
+#define R_NETWORK_REC_CONFIG__duplex__BITNR 9
+#define R_NETWORK_REC_CONFIG__duplex__WIDTH 1
+#define R_NETWORK_REC_CONFIG__duplex__full 1
+#define R_NETWORK_REC_CONFIG__duplex__half 0
+#define R_NETWORK_REC_CONFIG__bad_crc__BITNR 8
+#define R_NETWORK_REC_CONFIG__bad_crc__WIDTH 1
+#define R_NETWORK_REC_CONFIG__bad_crc__receive 1
+#define R_NETWORK_REC_CONFIG__bad_crc__discard 0
+#define R_NETWORK_REC_CONFIG__oversize__BITNR 7
+#define R_NETWORK_REC_CONFIG__oversize__WIDTH 1
+#define R_NETWORK_REC_CONFIG__oversize__receive 1
+#define R_NETWORK_REC_CONFIG__oversize__discard 0
+#define R_NETWORK_REC_CONFIG__undersize__BITNR 6
+#define R_NETWORK_REC_CONFIG__undersize__WIDTH 1
+#define R_NETWORK_REC_CONFIG__undersize__receive 1
+#define R_NETWORK_REC_CONFIG__undersize__discard 0
+#define R_NETWORK_REC_CONFIG__all_roots__BITNR 5
+#define R_NETWORK_REC_CONFIG__all_roots__WIDTH 1
+#define R_NETWORK_REC_CONFIG__all_roots__receive 1
+#define R_NETWORK_REC_CONFIG__all_roots__discard 0
+#define R_NETWORK_REC_CONFIG__tr_broadcast__BITNR 4
+#define R_NETWORK_REC_CONFIG__tr_broadcast__WIDTH 1
+#define R_NETWORK_REC_CONFIG__tr_broadcast__receive 1
+#define R_NETWORK_REC_CONFIG__tr_broadcast__discard 0
+#define R_NETWORK_REC_CONFIG__broadcast__BITNR 3
+#define R_NETWORK_REC_CONFIG__broadcast__WIDTH 1
+#define R_NETWORK_REC_CONFIG__broadcast__receive 1
+#define R_NETWORK_REC_CONFIG__broadcast__discard 0
+#define R_NETWORK_REC_CONFIG__individual__BITNR 2
+#define R_NETWORK_REC_CONFIG__individual__WIDTH 1
+#define R_NETWORK_REC_CONFIG__individual__receive 1
+#define R_NETWORK_REC_CONFIG__individual__discard 0
+#define R_NETWORK_REC_CONFIG__ma1__BITNR 1
+#define R_NETWORK_REC_CONFIG__ma1__WIDTH 1
+#define R_NETWORK_REC_CONFIG__ma1__enable 1
+#define R_NETWORK_REC_CONFIG__ma1__disable 0
+#define R_NETWORK_REC_CONFIG__ma0__BITNR 0
+#define R_NETWORK_REC_CONFIG__ma0__WIDTH 1
+#define R_NETWORK_REC_CONFIG__ma0__enable 1
+#define R_NETWORK_REC_CONFIG__ma0__disable 0
+
+#define R_NETWORK_GEN_CONFIG (IO_TYPECAST_UDWORD 0xb0000098)
+#define R_NETWORK_GEN_CONFIG__loopback__BITNR 5
+#define R_NETWORK_GEN_CONFIG__loopback__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__loopback__on 1
+#define R_NETWORK_GEN_CONFIG__loopback__off 0
+#define R_NETWORK_GEN_CONFIG__frame__BITNR 4
+#define R_NETWORK_GEN_CONFIG__frame__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__frame__tokenr 1
+#define R_NETWORK_GEN_CONFIG__frame__ether 0
+#define R_NETWORK_GEN_CONFIG__vg__BITNR 3
+#define R_NETWORK_GEN_CONFIG__vg__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__vg__on 1
+#define R_NETWORK_GEN_CONFIG__vg__off 0
+#define R_NETWORK_GEN_CONFIG__phy__BITNR 1
+#define R_NETWORK_GEN_CONFIG__phy__WIDTH 2
+#define R_NETWORK_GEN_CONFIG__phy__sni 0
+#define R_NETWORK_GEN_CONFIG__phy__mii_clk 1
+#define R_NETWORK_GEN_CONFIG__phy__mii_err 2
+#define R_NETWORK_GEN_CONFIG__phy__mii_req 3
+#define R_NETWORK_GEN_CONFIG__enable__BITNR 0
+#define R_NETWORK_GEN_CONFIG__enable__WIDTH 1
+#define R_NETWORK_GEN_CONFIG__enable__on 1
+#define R_NETWORK_GEN_CONFIG__enable__off 0
+
+#define R_NETWORK_TR_CTRL (IO_TYPECAST_UDWORD 0xb000009c)
+#define R_NETWORK_TR_CTRL__clr_error__BITNR 8
+#define R_NETWORK_TR_CTRL__clr_error__WIDTH 1
+#define R_NETWORK_TR_CTRL__clr_error__clr 1
+#define R_NETWORK_TR_CTRL__clr_error__nop 0
+#define R_NETWORK_TR_CTRL__delay__BITNR 5
+#define R_NETWORK_TR_CTRL__delay__WIDTH 1
+#define R_NETWORK_TR_CTRL__delay__d2us 1
+#define R_NETWORK_TR_CTRL__delay__none 0
+#define R_NETWORK_TR_CTRL__cancel__BITNR 4
+#define R_NETWORK_TR_CTRL__cancel__WIDTH 1
+#define R_NETWORK_TR_CTRL__cancel__do 1
+#define R_NETWORK_TR_CTRL__cancel__dont 0
+#define R_NETWORK_TR_CTRL__cd__BITNR 3
+#define R_NETWORK_TR_CTRL__cd__WIDTH 1
+#define R_NETWORK_TR_CTRL__cd__enable 0
+#define R_NETWORK_TR_CTRL__cd__disable 1
+#define R_NETWORK_TR_CTRL__cd__ack_col 0
+#define R_NETWORK_TR_CTRL__cd__ack_crs 1
+#define R_NETWORK_TR_CTRL__retry__BITNR 2
+#define R_NETWORK_TR_CTRL__retry__WIDTH 1
+#define R_NETWORK_TR_CTRL__retry__enable 0
+#define R_NETWORK_TR_CTRL__retry__disable 1
+#define R_NETWORK_TR_CTRL__pad__BITNR 1
+#define R_NETWORK_TR_CTRL__pad__WIDTH 1
+#define R_NETWORK_TR_CTRL__pad__enable 1
+#define R_NETWORK_TR_CTRL__pad__disable 0
+#define R_NETWORK_TR_CTRL__crc__BITNR 0
+#define R_NETWORK_TR_CTRL__crc__WIDTH 1
+#define R_NETWORK_TR_CTRL__crc__enable 0
+#define R_NETWORK_TR_CTRL__crc__disable 1
+
+#define R_NETWORK_MGM_CTRL (IO_TYPECAST_UDWORD 0xb00000a0)
+#define R_NETWORK_MGM_CTRL__txd_pins__BITNR 4
+#define R_NETWORK_MGM_CTRL__txd_pins__WIDTH 4
+#define R_NETWORK_MGM_CTRL__txer_pin__BITNR 3
+#define R_NETWORK_MGM_CTRL__txer_pin__WIDTH 1
+#define R_NETWORK_MGM_CTRL__mdck__BITNR 2
+#define R_NETWORK_MGM_CTRL__mdck__WIDTH 1
+#define R_NETWORK_MGM_CTRL__mdoe__BITNR 1
+#define R_NETWORK_MGM_CTRL__mdoe__WIDTH 1
+#define R_NETWORK_MGM_CTRL__mdoe__enable 1
+#define R_NETWORK_MGM_CTRL__mdoe__disable 0
+#define R_NETWORK_MGM_CTRL__mdio__BITNR 0
+#define R_NETWORK_MGM_CTRL__mdio__WIDTH 1
+
+#define R_NETWORK_STAT (IO_TYPECAST_RO_UDWORD 0xb00000a0)
+#define R_NETWORK_STAT__rxd_pins__BITNR 4
+#define R_NETWORK_STAT__rxd_pins__WIDTH 4
+#define R_NETWORK_STAT__rxer__BITNR 3
+#define R_NETWORK_STAT__rxer__WIDTH 1
+#define R_NETWORK_STAT__underrun__BITNR 2
+#define R_NETWORK_STAT__underrun__WIDTH 1
+#define R_NETWORK_STAT__underrun__yes 1
+#define R_NETWORK_STAT__underrun__no 0
+#define R_NETWORK_STAT__exc_col__BITNR 1
+#define R_NETWORK_STAT__exc_col__WIDTH 1
+#define R_NETWORK_STAT__exc_col__yes 1
+#define R_NETWORK_STAT__exc_col__no 0
+#define R_NETWORK_STAT__mdio__BITNR 0
+#define R_NETWORK_STAT__mdio__WIDTH 1
+
+#define R_REC_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000a4)
+#define R_REC_COUNTERS__congestion__BITNR 24
+#define R_REC_COUNTERS__congestion__WIDTH 8
+#define R_REC_COUNTERS__oversize__BITNR 16
+#define R_REC_COUNTERS__oversize__WIDTH 8
+#define R_REC_COUNTERS__alignment_error__BITNR 8
+#define R_REC_COUNTERS__alignment_error__WIDTH 8
+#define R_REC_COUNTERS__crc_error__BITNR 0
+#define R_REC_COUNTERS__crc_error__WIDTH 8
+
+#define R_TR_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000a8)
+#define R_TR_COUNTERS__deferred__BITNR 24
+#define R_TR_COUNTERS__deferred__WIDTH 8
+#define R_TR_COUNTERS__late_col__BITNR 16
+#define R_TR_COUNTERS__late_col__WIDTH 8
+#define R_TR_COUNTERS__multiple_col__BITNR 8
+#define R_TR_COUNTERS__multiple_col__WIDTH 8
+#define R_TR_COUNTERS__single_col__BITNR 0
+#define R_TR_COUNTERS__single_col__WIDTH 8
+
+#define R_PHY_COUNTERS (IO_TYPECAST_RO_UDWORD 0xb00000ac)
+#define R_PHY_COUNTERS__sqe_test_error__BITNR 8
+#define R_PHY_COUNTERS__sqe_test_error__WIDTH 8
+#define R_PHY_COUNTERS__carrier_loss__BITNR 0
+#define R_PHY_COUNTERS__carrier_loss__WIDTH 8
+
+/*
+!* Parallel printer port registers
+!*/
+
+#define R_PAR0_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_PAR0_CTRL_DATA__peri_int__BITNR 24
+#define R_PAR0_CTRL_DATA__peri_int__WIDTH 1
+#define R_PAR0_CTRL_DATA__peri_int__ack 1
+#define R_PAR0_CTRL_DATA__peri_int__nop 0
+#define R_PAR0_CTRL_DATA__oe__BITNR 20
+#define R_PAR0_CTRL_DATA__oe__WIDTH 1
+#define R_PAR0_CTRL_DATA__oe__enable 1
+#define R_PAR0_CTRL_DATA__oe__disable 0
+#define R_PAR0_CTRL_DATA__seli__BITNR 19
+#define R_PAR0_CTRL_DATA__seli__WIDTH 1
+#define R_PAR0_CTRL_DATA__seli__active 1
+#define R_PAR0_CTRL_DATA__seli__inactive 0
+#define R_PAR0_CTRL_DATA__autofd__BITNR 18
+#define R_PAR0_CTRL_DATA__autofd__WIDTH 1
+#define R_PAR0_CTRL_DATA__autofd__active 1
+#define R_PAR0_CTRL_DATA__autofd__inactive 0
+#define R_PAR0_CTRL_DATA__strb__BITNR 17
+#define R_PAR0_CTRL_DATA__strb__WIDTH 1
+#define R_PAR0_CTRL_DATA__strb__active 1
+#define R_PAR0_CTRL_DATA__strb__inactive 0
+#define R_PAR0_CTRL_DATA__init__BITNR 16
+#define R_PAR0_CTRL_DATA__init__WIDTH 1
+#define R_PAR0_CTRL_DATA__init__active 1
+#define R_PAR0_CTRL_DATA__init__inactive 0
+#define R_PAR0_CTRL_DATA__ecp_cmd__BITNR 8
+#define R_PAR0_CTRL_DATA__ecp_cmd__WIDTH 1
+#define R_PAR0_CTRL_DATA__ecp_cmd__command 1
+#define R_PAR0_CTRL_DATA__ecp_cmd__data 0
+#define R_PAR0_CTRL_DATA__data__BITNR 0
+#define R_PAR0_CTRL_DATA__data__WIDTH 8
+
+#define R_PAR0_CTRL (IO_TYPECAST_BYTE 0xb0000042)
+#define R_PAR0_CTRL__ctrl__BITNR 0
+#define R_PAR0_CTRL__ctrl__WIDTH 5
+
+#define R_PAR0_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000040)
+#define R_PAR0_STATUS_DATA__mode__BITNR 29
+#define R_PAR0_STATUS_DATA__mode__WIDTH 3
+#define R_PAR0_STATUS_DATA__mode__manual 0
+#define R_PAR0_STATUS_DATA__mode__centronics 1
+#define R_PAR0_STATUS_DATA__mode__fastbyte 2
+#define R_PAR0_STATUS_DATA__mode__nibble 3
+#define R_PAR0_STATUS_DATA__mode__byte 4
+#define R_PAR0_STATUS_DATA__mode__ecp_fwd 5
+#define R_PAR0_STATUS_DATA__mode__ecp_rev 6
+#define R_PAR0_STATUS_DATA__mode__off 7
+#define R_PAR0_STATUS_DATA__perr__BITNR 28
+#define R_PAR0_STATUS_DATA__perr__WIDTH 1
+#define R_PAR0_STATUS_DATA__perr__active 1
+#define R_PAR0_STATUS_DATA__perr__inactive 0
+#define R_PAR0_STATUS_DATA__ack__BITNR 27
+#define R_PAR0_STATUS_DATA__ack__WIDTH 1
+#define R_PAR0_STATUS_DATA__ack__active 0
+#define R_PAR0_STATUS_DATA__ack__inactive 1
+#define R_PAR0_STATUS_DATA__busy__BITNR 26
+#define R_PAR0_STATUS_DATA__busy__WIDTH 1
+#define R_PAR0_STATUS_DATA__busy__active 1
+#define R_PAR0_STATUS_DATA__busy__inactive 0
+#define R_PAR0_STATUS_DATA__fault__BITNR 25
+#define R_PAR0_STATUS_DATA__fault__WIDTH 1
+#define R_PAR0_STATUS_DATA__fault__active 0
+#define R_PAR0_STATUS_DATA__fault__inactive 1
+#define R_PAR0_STATUS_DATA__sel__BITNR 24
+#define R_PAR0_STATUS_DATA__sel__WIDTH 1
+#define R_PAR0_STATUS_DATA__sel__active 1
+#define R_PAR0_STATUS_DATA__sel__inactive 0
+#define R_PAR0_STATUS_DATA__tr_rdy__BITNR 17
+#define R_PAR0_STATUS_DATA__tr_rdy__WIDTH 1
+#define R_PAR0_STATUS_DATA__tr_rdy__ready 1
+#define R_PAR0_STATUS_DATA__tr_rdy__busy 0
+#define R_PAR0_STATUS_DATA__dav__BITNR 16
+#define R_PAR0_STATUS_DATA__dav__WIDTH 1
+#define R_PAR0_STATUS_DATA__dav__data 1
+#define R_PAR0_STATUS_DATA__dav__nodata 0
+#define R_PAR0_STATUS_DATA__ecp_cmd__BITNR 8
+#define R_PAR0_STATUS_DATA__ecp_cmd__WIDTH 1
+#define R_PAR0_STATUS_DATA__ecp_cmd__command 1
+#define R_PAR0_STATUS_DATA__ecp_cmd__data 0
+#define R_PAR0_STATUS_DATA__data__BITNR 0
+#define R_PAR0_STATUS_DATA__data__WIDTH 8
+
+#define R_PAR_ECP16_DATA (IO_TYPECAST_RO_UWORD 0xb0000040)
+#define R_PAR_ECP16_DATA__data__BITNR 0
+#define R_PAR_ECP16_DATA__data__WIDTH 16
+
+#define R_PAR0_CONFIG (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_PAR0_CONFIG__ioe__BITNR 25
+#define R_PAR0_CONFIG__ioe__WIDTH 1
+#define R_PAR0_CONFIG__ioe__inv 1
+#define R_PAR0_CONFIG__ioe__noninv 0
+#define R_PAR0_CONFIG__iseli__BITNR 24
+#define R_PAR0_CONFIG__iseli__WIDTH 1
+#define R_PAR0_CONFIG__iseli__inv 1
+#define R_PAR0_CONFIG__iseli__noninv 0
+#define R_PAR0_CONFIG__iautofd__BITNR 23
+#define R_PAR0_CONFIG__iautofd__WIDTH 1
+#define R_PAR0_CONFIG__iautofd__inv 1
+#define R_PAR0_CONFIG__iautofd__noninv 0
+#define R_PAR0_CONFIG__istrb__BITNR 22
+#define R_PAR0_CONFIG__istrb__WIDTH 1
+#define R_PAR0_CONFIG__istrb__inv 1
+#define R_PAR0_CONFIG__istrb__noninv 0
+#define R_PAR0_CONFIG__iinit__BITNR 21
+#define R_PAR0_CONFIG__iinit__WIDTH 1
+#define R_PAR0_CONFIG__iinit__inv 1
+#define R_PAR0_CONFIG__iinit__noninv 0
+#define R_PAR0_CONFIG__iperr__BITNR 20
+#define R_PAR0_CONFIG__iperr__WIDTH 1
+#define R_PAR0_CONFIG__iperr__inv 1
+#define R_PAR0_CONFIG__iperr__noninv 0
+#define R_PAR0_CONFIG__iack__BITNR 19
+#define R_PAR0_CONFIG__iack__WIDTH 1
+#define R_PAR0_CONFIG__iack__inv 1
+#define R_PAR0_CONFIG__iack__noninv 0
+#define R_PAR0_CONFIG__ibusy__BITNR 18
+#define R_PAR0_CONFIG__ibusy__WIDTH 1
+#define R_PAR0_CONFIG__ibusy__inv 1
+#define R_PAR0_CONFIG__ibusy__noninv 0
+#define R_PAR0_CONFIG__ifault__BITNR 17
+#define R_PAR0_CONFIG__ifault__WIDTH 1
+#define R_PAR0_CONFIG__ifault__inv 1
+#define R_PAR0_CONFIG__ifault__noninv 0
+#define R_PAR0_CONFIG__isel__BITNR 16
+#define R_PAR0_CONFIG__isel__WIDTH 1
+#define R_PAR0_CONFIG__isel__inv 1
+#define R_PAR0_CONFIG__isel__noninv 0
+#define R_PAR0_CONFIG__ext_mode__BITNR 11
+#define R_PAR0_CONFIG__ext_mode__WIDTH 1
+#define R_PAR0_CONFIG__ext_mode__enable 1
+#define R_PAR0_CONFIG__ext_mode__disable 0
+#define R_PAR0_CONFIG__wide__BITNR 10
+#define R_PAR0_CONFIG__wide__WIDTH 1
+#define R_PAR0_CONFIG__wide__enable 1
+#define R_PAR0_CONFIG__wide__disable 0
+#define R_PAR0_CONFIG__dma__BITNR 9
+#define R_PAR0_CONFIG__dma__WIDTH 1
+#define R_PAR0_CONFIG__dma__enable 1
+#define R_PAR0_CONFIG__dma__disable 0
+#define R_PAR0_CONFIG__rle_in__BITNR 8
+#define R_PAR0_CONFIG__rle_in__WIDTH 1
+#define R_PAR0_CONFIG__rle_in__enable 1
+#define R_PAR0_CONFIG__rle_in__disable 0
+#define R_PAR0_CONFIG__rle_out__BITNR 7
+#define R_PAR0_CONFIG__rle_out__WIDTH 1
+#define R_PAR0_CONFIG__rle_out__enable 1
+#define R_PAR0_CONFIG__rle_out__disable 0
+#define R_PAR0_CONFIG__enable__BITNR 6
+#define R_PAR0_CONFIG__enable__WIDTH 1
+#define R_PAR0_CONFIG__enable__on 1
+#define R_PAR0_CONFIG__enable__reset 0
+#define R_PAR0_CONFIG__force__BITNR 5
+#define R_PAR0_CONFIG__force__WIDTH 1
+#define R_PAR0_CONFIG__force__on 1
+#define R_PAR0_CONFIG__force__off 0
+#define R_PAR0_CONFIG__ign_ack__BITNR 4
+#define R_PAR0_CONFIG__ign_ack__WIDTH 1
+#define R_PAR0_CONFIG__ign_ack__ignore 1
+#define R_PAR0_CONFIG__ign_ack__wait 0
+#define R_PAR0_CONFIG__oe_ack__BITNR 3
+#define R_PAR0_CONFIG__oe_ack__WIDTH 1
+#define R_PAR0_CONFIG__oe_ack__wait_oe 1
+#define R_PAR0_CONFIG__oe_ack__dont_wait 0
+#define R_PAR0_CONFIG__oe_ack__epp_addr 1
+#define R_PAR0_CONFIG__oe_ack__epp_data 0
+#define R_PAR0_CONFIG__epp_addr_data__BITNR 3
+#define R_PAR0_CONFIG__epp_addr_data__WIDTH 1
+#define R_PAR0_CONFIG__epp_addr_data__wait_oe 1
+#define R_PAR0_CONFIG__epp_addr_data__dont_wait 0
+#define R_PAR0_CONFIG__epp_addr_data__epp_addr 1
+#define R_PAR0_CONFIG__epp_addr_data__epp_data 0
+#define R_PAR0_CONFIG__mode__BITNR 0
+#define R_PAR0_CONFIG__mode__WIDTH 3
+#define R_PAR0_CONFIG__mode__manual 0
+#define R_PAR0_CONFIG__mode__centronics 1
+#define R_PAR0_CONFIG__mode__fastbyte 2
+#define R_PAR0_CONFIG__mode__nibble 3
+#define R_PAR0_CONFIG__mode__byte 4
+#define R_PAR0_CONFIG__mode__ecp_fwd 5
+#define R_PAR0_CONFIG__mode__ecp_rev 6
+#define R_PAR0_CONFIG__mode__off 7
+
+#define R_PAR0_DELAY (IO_TYPECAST_UDWORD 0xb0000048)
+#define R_PAR0_DELAY__fine_hold__BITNR 21
+#define R_PAR0_DELAY__fine_hold__WIDTH 3
+#define R_PAR0_DELAY__hold__BITNR 16
+#define R_PAR0_DELAY__hold__WIDTH 5
+#define R_PAR0_DELAY__fine_strb__BITNR 13
+#define R_PAR0_DELAY__fine_strb__WIDTH 3
+#define R_PAR0_DELAY__strobe__BITNR 8
+#define R_PAR0_DELAY__strobe__WIDTH 5
+#define R_PAR0_DELAY__fine_setup__BITNR 5
+#define R_PAR0_DELAY__fine_setup__WIDTH 3
+#define R_PAR0_DELAY__setup__BITNR 0
+#define R_PAR0_DELAY__setup__WIDTH 5
+
+#define R_PAR1_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000050)
+#define R_PAR1_CTRL_DATA__peri_int__BITNR 24
+#define R_PAR1_CTRL_DATA__peri_int__WIDTH 1
+#define R_PAR1_CTRL_DATA__peri_int__ack 1
+#define R_PAR1_CTRL_DATA__peri_int__nop 0
+#define R_PAR1_CTRL_DATA__oe__BITNR 20
+#define R_PAR1_CTRL_DATA__oe__WIDTH 1
+#define R_PAR1_CTRL_DATA__oe__enable 1
+#define R_PAR1_CTRL_DATA__oe__disable 0
+#define R_PAR1_CTRL_DATA__seli__BITNR 19
+#define R_PAR1_CTRL_DATA__seli__WIDTH 1
+#define R_PAR1_CTRL_DATA__seli__active 1
+#define R_PAR1_CTRL_DATA__seli__inactive 0
+#define R_PAR1_CTRL_DATA__autofd__BITNR 18
+#define R_PAR1_CTRL_DATA__autofd__WIDTH 1
+#define R_PAR1_CTRL_DATA__autofd__active 1
+#define R_PAR1_CTRL_DATA__autofd__inactive 0
+#define R_PAR1_CTRL_DATA__strb__BITNR 17
+#define R_PAR1_CTRL_DATA__strb__WIDTH 1
+#define R_PAR1_CTRL_DATA__strb__active 1
+#define R_PAR1_CTRL_DATA__strb__inactive 0
+#define R_PAR1_CTRL_DATA__init__BITNR 16
+#define R_PAR1_CTRL_DATA__init__WIDTH 1
+#define R_PAR1_CTRL_DATA__init__active 1
+#define R_PAR1_CTRL_DATA__init__inactive 0
+#define R_PAR1_CTRL_DATA__ecp_cmd__BITNR 8
+#define R_PAR1_CTRL_DATA__ecp_cmd__WIDTH 1
+#define R_PAR1_CTRL_DATA__ecp_cmd__command 1
+#define R_PAR1_CTRL_DATA__ecp_cmd__data 0
+#define R_PAR1_CTRL_DATA__data__BITNR 0
+#define R_PAR1_CTRL_DATA__data__WIDTH 8
+
+#define R_PAR1_CTRL (IO_TYPECAST_BYTE 0xb0000052)
+#define R_PAR1_CTRL__ctrl__BITNR 0
+#define R_PAR1_CTRL__ctrl__WIDTH 5
+
+#define R_PAR1_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000050)
+#define R_PAR1_STATUS_DATA__mode__BITNR 29
+#define R_PAR1_STATUS_DATA__mode__WIDTH 3
+#define R_PAR1_STATUS_DATA__mode__manual 0
+#define R_PAR1_STATUS_DATA__mode__centronics 1
+#define R_PAR1_STATUS_DATA__mode__fastbyte 2
+#define R_PAR1_STATUS_DATA__mode__nibble 3
+#define R_PAR1_STATUS_DATA__mode__byte 4
+#define R_PAR1_STATUS_DATA__mode__ecp_fwd 5
+#define R_PAR1_STATUS_DATA__mode__ecp_rev 6
+#define R_PAR1_STATUS_DATA__mode__off 7
+#define R_PAR1_STATUS_DATA__perr__BITNR 28
+#define R_PAR1_STATUS_DATA__perr__WIDTH 1
+#define R_PAR1_STATUS_DATA__perr__active 1
+#define R_PAR1_STATUS_DATA__perr__inactive 0
+#define R_PAR1_STATUS_DATA__ack__BITNR 27
+#define R_PAR1_STATUS_DATA__ack__WIDTH 1
+#define R_PAR1_STATUS_DATA__ack__active 0
+#define R_PAR1_STATUS_DATA__ack__inactive 1
+#define R_PAR1_STATUS_DATA__busy__BITNR 26
+#define R_PAR1_STATUS_DATA__busy__WIDTH 1
+#define R_PAR1_STATUS_DATA__busy__active 1
+#define R_PAR1_STATUS_DATA__busy__inactive 0
+#define R_PAR1_STATUS_DATA__fault__BITNR 25
+#define R_PAR1_STATUS_DATA__fault__WIDTH 1
+#define R_PAR1_STATUS_DATA__fault__active 0
+#define R_PAR1_STATUS_DATA__fault__inactive 1
+#define R_PAR1_STATUS_DATA__sel__BITNR 24
+#define R_PAR1_STATUS_DATA__sel__WIDTH 1
+#define R_PAR1_STATUS_DATA__sel__active 1
+#define R_PAR1_STATUS_DATA__sel__inactive 0
+#define R_PAR1_STATUS_DATA__tr_rdy__BITNR 17
+#define R_PAR1_STATUS_DATA__tr_rdy__WIDTH 1
+#define R_PAR1_STATUS_DATA__tr_rdy__ready 1
+#define R_PAR1_STATUS_DATA__tr_rdy__busy 0
+#define R_PAR1_STATUS_DATA__dav__BITNR 16
+#define R_PAR1_STATUS_DATA__dav__WIDTH 1
+#define R_PAR1_STATUS_DATA__dav__data 1
+#define R_PAR1_STATUS_DATA__dav__nodata 0
+#define R_PAR1_STATUS_DATA__ecp_cmd__BITNR 8
+#define R_PAR1_STATUS_DATA__ecp_cmd__WIDTH 1
+#define R_PAR1_STATUS_DATA__ecp_cmd__command 1
+#define R_PAR1_STATUS_DATA__ecp_cmd__data 0
+#define R_PAR1_STATUS_DATA__data__BITNR 0
+#define R_PAR1_STATUS_DATA__data__WIDTH 8
+
+#define R_PAR1_CONFIG (IO_TYPECAST_UDWORD 0xb0000054)
+#define R_PAR1_CONFIG__ioe__BITNR 25
+#define R_PAR1_CONFIG__ioe__WIDTH 1
+#define R_PAR1_CONFIG__ioe__inv 1
+#define R_PAR1_CONFIG__ioe__noninv 0
+#define R_PAR1_CONFIG__iseli__BITNR 24
+#define R_PAR1_CONFIG__iseli__WIDTH 1
+#define R_PAR1_CONFIG__iseli__inv 1
+#define R_PAR1_CONFIG__iseli__noninv 0
+#define R_PAR1_CONFIG__iautofd__BITNR 23
+#define R_PAR1_CONFIG__iautofd__WIDTH 1
+#define R_PAR1_CONFIG__iautofd__inv 1
+#define R_PAR1_CONFIG__iautofd__noninv 0
+#define R_PAR1_CONFIG__istrb__BITNR 22
+#define R_PAR1_CONFIG__istrb__WIDTH 1
+#define R_PAR1_CONFIG__istrb__inv 1
+#define R_PAR1_CONFIG__istrb__noninv 0
+#define R_PAR1_CONFIG__iinit__BITNR 21
+#define R_PAR1_CONFIG__iinit__WIDTH 1
+#define R_PAR1_CONFIG__iinit__inv 1
+#define R_PAR1_CONFIG__iinit__noninv 0
+#define R_PAR1_CONFIG__iperr__BITNR 20
+#define R_PAR1_CONFIG__iperr__WIDTH 1
+#define R_PAR1_CONFIG__iperr__inv 1
+#define R_PAR1_CONFIG__iperr__noninv 0
+#define R_PAR1_CONFIG__iack__BITNR 19
+#define R_PAR1_CONFIG__iack__WIDTH 1
+#define R_PAR1_CONFIG__iack__inv 1
+#define R_PAR1_CONFIG__iack__noninv 0
+#define R_PAR1_CONFIG__ibusy__BITNR 18
+#define R_PAR1_CONFIG__ibusy__WIDTH 1
+#define R_PAR1_CONFIG__ibusy__inv 1
+#define R_PAR1_CONFIG__ibusy__noninv 0
+#define R_PAR1_CONFIG__ifault__BITNR 17
+#define R_PAR1_CONFIG__ifault__WIDTH 1
+#define R_PAR1_CONFIG__ifault__inv 1
+#define R_PAR1_CONFIG__ifault__noninv 0
+#define R_PAR1_CONFIG__isel__BITNR 16
+#define R_PAR1_CONFIG__isel__WIDTH 1
+#define R_PAR1_CONFIG__isel__inv 1
+#define R_PAR1_CONFIG__isel__noninv 0
+#define R_PAR1_CONFIG__ext_mode__BITNR 11
+#define R_PAR1_CONFIG__ext_mode__WIDTH 1
+#define R_PAR1_CONFIG__ext_mode__enable 1
+#define R_PAR1_CONFIG__ext_mode__disable 0
+#define R_PAR1_CONFIG__dma__BITNR 9
+#define R_PAR1_CONFIG__dma__WIDTH 1
+#define R_PAR1_CONFIG__dma__enable 1
+#define R_PAR1_CONFIG__dma__disable 0
+#define R_PAR1_CONFIG__rle_in__BITNR 8
+#define R_PAR1_CONFIG__rle_in__WIDTH 1
+#define R_PAR1_CONFIG__rle_in__enable 1
+#define R_PAR1_CONFIG__rle_in__disable 0
+#define R_PAR1_CONFIG__rle_out__BITNR 7
+#define R_PAR1_CONFIG__rle_out__WIDTH 1
+#define R_PAR1_CONFIG__rle_out__enable 1
+#define R_PAR1_CONFIG__rle_out__disable 0
+#define R_PAR1_CONFIG__enable__BITNR 6
+#define R_PAR1_CONFIG__enable__WIDTH 1
+#define R_PAR1_CONFIG__enable__on 1
+#define R_PAR1_CONFIG__enable__reset 0
+#define R_PAR1_CONFIG__force__BITNR 5
+#define R_PAR1_CONFIG__force__WIDTH 1
+#define R_PAR1_CONFIG__force__on 1
+#define R_PAR1_CONFIG__force__off 0
+#define R_PAR1_CONFIG__ign_ack__BITNR 4
+#define R_PAR1_CONFIG__ign_ack__WIDTH 1
+#define R_PAR1_CONFIG__ign_ack__ignore 1
+#define R_PAR1_CONFIG__ign_ack__wait 0
+#define R_PAR1_CONFIG__oe_ack__BITNR 3
+#define R_PAR1_CONFIG__oe_ack__WIDTH 1
+#define R_PAR1_CONFIG__oe_ack__wait_oe 1
+#define R_PAR1_CONFIG__oe_ack__dont_wait 0
+#define R_PAR1_CONFIG__oe_ack__epp_addr 1
+#define R_PAR1_CONFIG__oe_ack__epp_data 0
+#define R_PAR1_CONFIG__epp_addr_data__BITNR 3
+#define R_PAR1_CONFIG__epp_addr_data__WIDTH 1
+#define R_PAR1_CONFIG__epp_addr_data__wait_oe 1
+#define R_PAR1_CONFIG__epp_addr_data__dont_wait 0
+#define R_PAR1_CONFIG__epp_addr_data__epp_addr 1
+#define R_PAR1_CONFIG__epp_addr_data__epp_data 0
+#define R_PAR1_CONFIG__mode__BITNR 0
+#define R_PAR1_CONFIG__mode__WIDTH 3
+#define R_PAR1_CONFIG__mode__manual 0
+#define R_PAR1_CONFIG__mode__centronics 1
+#define R_PAR1_CONFIG__mode__fastbyte 2
+#define R_PAR1_CONFIG__mode__nibble 3
+#define R_PAR1_CONFIG__mode__byte 4
+#define R_PAR1_CONFIG__mode__ecp_fwd 5
+#define R_PAR1_CONFIG__mode__ecp_rev 6
+#define R_PAR1_CONFIG__mode__off 7
+
+#define R_PAR1_DELAY (IO_TYPECAST_UDWORD 0xb0000058)
+#define R_PAR1_DELAY__fine_hold__BITNR 21
+#define R_PAR1_DELAY__fine_hold__WIDTH 3
+#define R_PAR1_DELAY__hold__BITNR 16
+#define R_PAR1_DELAY__hold__WIDTH 5
+#define R_PAR1_DELAY__fine_strb__BITNR 13
+#define R_PAR1_DELAY__fine_strb__WIDTH 3
+#define R_PAR1_DELAY__strobe__BITNR 8
+#define R_PAR1_DELAY__strobe__WIDTH 5
+#define R_PAR1_DELAY__fine_setup__BITNR 5
+#define R_PAR1_DELAY__fine_setup__WIDTH 3
+#define R_PAR1_DELAY__setup__BITNR 0
+#define R_PAR1_DELAY__setup__WIDTH 5
+
+/*
+!* ATA interface registers
+!*/
+
+#define R_ATA_CTRL_DATA (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_ATA_CTRL_DATA__sel__BITNR 30
+#define R_ATA_CTRL_DATA__sel__WIDTH 2
+#define R_ATA_CTRL_DATA__cs1__BITNR 29
+#define R_ATA_CTRL_DATA__cs1__WIDTH 1
+#define R_ATA_CTRL_DATA__cs1__active 1
+#define R_ATA_CTRL_DATA__cs1__inactive 0
+#define R_ATA_CTRL_DATA__cs0__BITNR 28
+#define R_ATA_CTRL_DATA__cs0__WIDTH 1
+#define R_ATA_CTRL_DATA__cs0__active 1
+#define R_ATA_CTRL_DATA__cs0__inactive 0
+#define R_ATA_CTRL_DATA__addr__BITNR 25
+#define R_ATA_CTRL_DATA__addr__WIDTH 3
+#define R_ATA_CTRL_DATA__rw__BITNR 24
+#define R_ATA_CTRL_DATA__rw__WIDTH 1
+#define R_ATA_CTRL_DATA__rw__read 1
+#define R_ATA_CTRL_DATA__rw__write 0
+#define R_ATA_CTRL_DATA__src_dst__BITNR 23
+#define R_ATA_CTRL_DATA__src_dst__WIDTH 1
+#define R_ATA_CTRL_DATA__src_dst__dma 1
+#define R_ATA_CTRL_DATA__src_dst__register 0
+#define R_ATA_CTRL_DATA__handsh__BITNR 22
+#define R_ATA_CTRL_DATA__handsh__WIDTH 1
+#define R_ATA_CTRL_DATA__handsh__dma 1
+#define R_ATA_CTRL_DATA__handsh__pio 0
+#define R_ATA_CTRL_DATA__multi__BITNR 21
+#define R_ATA_CTRL_DATA__multi__WIDTH 1
+#define R_ATA_CTRL_DATA__multi__on 1
+#define R_ATA_CTRL_DATA__multi__off 0
+#define R_ATA_CTRL_DATA__dma_size__BITNR 20
+#define R_ATA_CTRL_DATA__dma_size__WIDTH 1
+#define R_ATA_CTRL_DATA__dma_size__byte 1
+#define R_ATA_CTRL_DATA__dma_size__word 0
+#define R_ATA_CTRL_DATA__data__BITNR 0
+#define R_ATA_CTRL_DATA__data__WIDTH 16
+
+#define R_ATA_STATUS_DATA (IO_TYPECAST_RO_UDWORD 0xb0000040)
+#define R_ATA_STATUS_DATA__busy__BITNR 18
+#define R_ATA_STATUS_DATA__busy__WIDTH 1
+#define R_ATA_STATUS_DATA__busy__yes 1
+#define R_ATA_STATUS_DATA__busy__no 0
+#define R_ATA_STATUS_DATA__tr_rdy__BITNR 17
+#define R_ATA_STATUS_DATA__tr_rdy__WIDTH 1
+#define R_ATA_STATUS_DATA__tr_rdy__ready 1
+#define R_ATA_STATUS_DATA__tr_rdy__busy 0
+#define R_ATA_STATUS_DATA__dav__BITNR 16
+#define R_ATA_STATUS_DATA__dav__WIDTH 1
+#define R_ATA_STATUS_DATA__dav__data 1
+#define R_ATA_STATUS_DATA__dav__nodata 0
+#define R_ATA_STATUS_DATA__data__BITNR 0
+#define R_ATA_STATUS_DATA__data__WIDTH 16
+
+#define R_ATA_CONFIG (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_ATA_CONFIG__enable__BITNR 25
+#define R_ATA_CONFIG__enable__WIDTH 1
+#define R_ATA_CONFIG__enable__on 1
+#define R_ATA_CONFIG__enable__off 0
+#define R_ATA_CONFIG__dma_strobe__BITNR 20
+#define R_ATA_CONFIG__dma_strobe__WIDTH 5
+#define R_ATA_CONFIG__dma_hold__BITNR 15
+#define R_ATA_CONFIG__dma_hold__WIDTH 5
+#define R_ATA_CONFIG__pio_setup__BITNR 10
+#define R_ATA_CONFIG__pio_setup__WIDTH 5
+#define R_ATA_CONFIG__pio_strobe__BITNR 5
+#define R_ATA_CONFIG__pio_strobe__WIDTH 5
+#define R_ATA_CONFIG__pio_hold__BITNR 0
+#define R_ATA_CONFIG__pio_hold__WIDTH 5
+
+#define R_ATA_TRANSFER_CNT (IO_TYPECAST_UDWORD 0xb0000048)
+#define R_ATA_TRANSFER_CNT__count__BITNR 0
+#define R_ATA_TRANSFER_CNT__count__WIDTH 17
+
+/*
+!* SCSI registers
+!*/
+
+#define R_SCSI0_CTRL (IO_TYPECAST_UDWORD 0xb0000044)
+#define R_SCSI0_CTRL__id_type__BITNR 31
+#define R_SCSI0_CTRL__id_type__WIDTH 1
+#define R_SCSI0_CTRL__id_type__software 1
+#define R_SCSI0_CTRL__id_type__hardware 0
+#define R_SCSI0_CTRL__sel_timeout__BITNR 24
+#define R_SCSI0_CTRL__sel_timeout__WIDTH 7
+#define R_SCSI0_CTRL__synch_per__BITNR 16
+#define R_SCSI0_CTRL__synch_per__WIDTH 8
+#define R_SCSI0_CTRL__rst__BITNR 15
+#define R_SCSI0_CTRL__rst__WIDTH 1
+#define R_SCSI0_CTRL__rst__yes 1
+#define R_SCSI0_CTRL__rst__no 0
+#define R_SCSI0_CTRL__atn__BITNR 14
+#define R_SCSI0_CTRL__atn__WIDTH 1
+#define R_SCSI0_CTRL__atn__yes 1
+#define R_SCSI0_CTRL__atn__no 0
+#define R_SCSI0_CTRL__my_id__BITNR 9
+#define R_SCSI0_CTRL__my_id__WIDTH 4
+#define R_SCSI0_CTRL__target_id__BITNR 4
+#define R_SCSI0_CTRL__target_id__WIDTH 4
+#define R_SCSI0_CTRL__fast_20__BITNR 3
+#define R_SCSI0_CTRL__fast_20__WIDTH 1
+#define R_SCSI0_CTRL__fast_20__yes 1
+#define R_SCSI0_CTRL__fast_20__no 0
+#define R_SCSI0_CTRL__bus_width__BITNR 2
+#define R_SCSI0_CTRL__bus_width__WIDTH 1
+#define R_SCSI0_CTRL__bus_width__wide 1
+#define R_SCSI0_CTRL__bus_width__narrow 0
+#define R_SCSI0_CTRL__synch__BITNR 1
+#define R_SCSI0_CTRL__synch__WIDTH 1
+#define R_SCSI0_CTRL__synch__synch 1
+#define R_SCSI0_CTRL__synch__asynch 0
+#define R_SCSI0_CTRL__enable__BITNR 0
+#define R_SCSI0_CTRL__enable__WIDTH 1
+#define R_SCSI0_CTRL__enable__on 1
+#define R_SCSI0_CTRL__enable__off 0
+
+#define R_SCSI0_CMD_DATA (IO_TYPECAST_UDWORD 0xb0000040)
+#define R_SCSI0_CMD_DATA__parity_in__BITNR 26
+#define R_SCSI0_CMD_DATA__parity_in__WIDTH 1
+#define R_SCSI0_CMD_DATA__parity_in__on 0
+#define R_SCSI0_CMD_DATA__parity_in__off 1
+#define R_SCSI0_CMD_DATA__skip__BITNR 25
+#define R_SCSI0_CMD_DATA__skip__WIDTH 1
+#define R_SCSI0_CMD_DATA__skip__on 1
+#define R_SCSI0_CMD_DATA__skip__off 0
+#define R_SCSI0_CMD_DATA__clr_status__BITNR 24
+#define R_SCSI0_CMD_DATA__clr_status__WIDTH 1
+#define R_SCSI0_CMD_DATA__clr_status__yes 1
+#define R_SCSI0_CMD_DATA__clr_status__nop 0
+#define R_SCSI0_CMD_DATA__asynch_setup__BITNR 20
+#define R_SCSI0_CMD_DATA__asynch_setup__WIDTH 4
+#define R_SCSI0_CMD_DATA__command__BITNR 16
+#define R_SCSI0_CMD_DATA__command__WIDTH 4
+#define R_SCSI0_CMD_DATA__command__full_din_1 0
+#define R_SCSI0_CMD_DATA__command__full_dout_1 1
+#define R_SCSI0_CMD_DATA__command__full_stat_1 2
+#define R_SCSI0_CMD_DATA__command__resel_din 3
+#define R_SCSI0_CMD_DATA__command__resel_dout 4
+#define R_SCSI0_CMD_DATA__command__resel_stat 5
+#define R_SCSI0_CMD_DATA__command__arb_only 6
+#define R_SCSI0_CMD_DATA__command__full_din_3 8
+#define R_SCSI0_CMD_DATA__command__full_dout_3 9
+#define R_SCSI0_CMD_DATA__command__full_stat_3 10
+#define R_SCSI0_CMD_DATA__command__man_data_in 11
+#define R_SCSI0_CMD_DATA__command__man_data_out 12
+#define R_SCSI0_CMD_DATA__command__man_rat 13
+#define R_SCSI0_CMD_DATA__data_out__BITNR 0
+#define R_SCSI0_CMD_DATA__data_out__WIDTH 16
+
+#define R_SCSI0_DATA (IO_TYPECAST_UWORD 0xb0000040)
+#define R_SCSI0_DATA__data_out__BITNR 0
+#define R_SCSI0_DATA__data_out__WIDTH 16
+
+#define R_SCSI0_CMD (IO_TYPECAST_BYTE 0xb0000042)
+#define R_SCSI0_CMD__asynch_setup__BITNR 4
+#define R_SCSI0_CMD__asynch_setup__WIDTH 4
+#define R_SCSI0_CMD__command__BITNR 0
+#define R_SCSI0_CMD__command__WIDTH 4
+#define R_SCSI0_CMD__command__full_din_1 0
+#define R_SCSI0_CMD__command__full_dout_1 1
+#define R_SCSI0_CMD__command__full_stat_1 2
+#define R_SCSI0_CMD__command__resel_din 3
+#define R_SCSI0_CMD__command__resel_dout 4
+#define R_SCSI0_CMD__command__resel_stat 5
+#define R_SCSI0_CMD__command__arb_only 6
+#define R_SCSI0_CMD__command__full_din_3 8
+#define R_SCSI0_CMD__command__full_dout_3 9
+#define R_SCSI0_CMD__command__full_stat_3 10
+#define R_SCSI0_CMD__command__man_data_in 11
+#define R_SCSI0_CMD__command__man_data_out 12
+#define R_SCSI0_CMD__command__man_rat 13
+
+#define R_SCSI0_STATUS_CTRL (IO_TYPECAST_BYTE 0xb0000043)
+#define R_SCSI0_STATUS_CTRL__parity_in__BITNR 2
+#define R_SCSI0_STATUS_CTRL__parity_in__WIDTH 1
+#define R_SCSI0_STATUS_CTRL__parity_in__on 0
+#define R_SCSI0_STATUS_CTRL__parity_in__off 1
+#define R_SCSI0_STATUS_CTRL__skip__BITNR 1
+#define R_SCSI0_STATUS_CTRL__skip__WIDTH 1
+#define R_SCSI0_STATUS_CTRL__skip__on 1
+#define R_SCSI0_STATUS_CTRL__skip__off 0
+#define R_SCSI0_STATUS_CTRL__clr_status__BITNR 0
+#define R_SCSI0_STATUS_CTRL__clr_status__WIDTH 1
+#define R_SCSI0_STATUS_CTRL__clr_status__yes 1
+#define R_SCSI0_STATUS_CTRL__clr_status__nop 0
+
+#define R_SCSI0_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000048)
+#define R_SCSI0_STATUS__tst_arb_won__BITNR 23
+#define R_SCSI0_STATUS__tst_arb_won__WIDTH 1
+#define R_SCSI0_STATUS__tst_resel__BITNR 22
+#define R_SCSI0_STATUS__tst_resel__WIDTH 1
+#define R_SCSI0_STATUS__parity_error__BITNR 21
+#define R_SCSI0_STATUS__parity_error__WIDTH 1
+#define R_SCSI0_STATUS__bus_reset__BITNR 20
+#define R_SCSI0_STATUS__bus_reset__WIDTH 1
+#define R_SCSI0_STATUS__bus_reset__yes 1
+#define R_SCSI0_STATUS__bus_reset__no 0
+#define R_SCSI0_STATUS__resel_target__BITNR 15
+#define R_SCSI0_STATUS__resel_target__WIDTH 4
+#define R_SCSI0_STATUS__resel__BITNR 14
+#define R_SCSI0_STATUS__resel__WIDTH 1
+#define R_SCSI0_STATUS__resel__yes 1
+#define R_SCSI0_STATUS__resel__no 0
+#define R_SCSI0_STATUS__curr_phase__BITNR 11
+#define R_SCSI0_STATUS__curr_phase__WIDTH 3
+#define R_SCSI0_STATUS__curr_phase__ph_undef 0
+#define R_SCSI0_STATUS__curr_phase__ph_msg_in 7
+#define R_SCSI0_STATUS__curr_phase__ph_msg_out 6
+#define R_SCSI0_STATUS__curr_phase__ph_status 3
+#define R_SCSI0_STATUS__curr_phase__ph_command 2
+#define R_SCSI0_STATUS__curr_phase__ph_data_in 5
+#define R_SCSI0_STATUS__curr_phase__ph_data_out 4
+#define R_SCSI0_STATUS__curr_phase__ph_resel 1
+#define R_SCSI0_STATUS__last_seq_step__BITNR 6
+#define R_SCSI0_STATUS__last_seq_step__WIDTH 5
+#define R_SCSI0_STATUS__last_seq_step__st_bus_free 24
+#define R_SCSI0_STATUS__last_seq_step__st_arbitrate 8
+#define R_SCSI0_STATUS__last_seq_step__st_resel_req 29
+#define R_SCSI0_STATUS__last_seq_step__st_msg_1 2
+#define R_SCSI0_STATUS__last_seq_step__st_manual 28
+#define R_SCSI0_STATUS__last_seq_step__st_transf_cmd 30
+#define R_SCSI0_STATUS__last_seq_step__st_msg_2 6
+#define R_SCSI0_STATUS__last_seq_step__st_msg_3 22
+#define R_SCSI0_STATUS__last_seq_step__st_answer 3
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din_perr 1
+#define R_SCSI0_STATUS__last_seq_step__st_transfer_done 15
+#define R_SCSI0_STATUS__last_seq_step__st_synch_dout 0
+#define R_SCSI0_STATUS__last_seq_step__st_asynch_dout 25
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din 13
+#define R_SCSI0_STATUS__last_seq_step__st_asynch_din 9
+#define R_SCSI0_STATUS__last_seq_step__st_synch_dout_ack 4
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din_ack 12
+#define R_SCSI0_STATUS__last_seq_step__st_synch_din_ack_perr 5
+#define R_SCSI0_STATUS__last_seq_step__st_asynch_dout_end 11
+#define R_SCSI0_STATUS__last_seq_step__st_iwr 27
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_disc 21
+#define R_SCSI0_STATUS__last_seq_step__st_sdp_disc 7
+#define R_SCSI0_STATUS__last_seq_step__st_cc 31
+#define R_SCSI0_STATUS__last_seq_step__st_iwr_good 14
+#define R_SCSI0_STATUS__last_seq_step__st_iwr_cc 23
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_iwr_cc 17
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_cc 20
+#define R_SCSI0_STATUS__last_seq_step__st_wait_free_sdp_disc 16
+#define R_SCSI0_STATUS__last_seq_step__st_manual_req 10
+#define R_SCSI0_STATUS__last_seq_step__st_manual_din_prot 18
+#define R_SCSI0_STATUS__valid_status__BITNR 5
+#define R_SCSI0_STATUS__valid_status__WIDTH 1
+#define R_SCSI0_STATUS__valid_status__yes 1
+#define R_SCSI0_STATUS__valid_status__no 0
+#define R_SCSI0_STATUS__seq_status__BITNR 0
+#define R_SCSI0_STATUS__seq_status__WIDTH 5
+#define R_SCSI0_STATUS__seq_status__info_seq_complete 0
+#define R_SCSI0_STATUS__seq_status__info_parity_error 1
+#define R_SCSI0_STATUS__seq_status__info_unhandled_msg_in 2
+#define R_SCSI0_STATUS__seq_status__info_unexp_ph_change 3
+#define R_SCSI0_STATUS__seq_status__info_arb_lost 4
+#define R_SCSI0_STATUS__seq_status__info_sel_timeout 5
+#define R_SCSI0_STATUS__seq_status__info_unexp_bf 6
+#define R_SCSI0_STATUS__seq_status__info_illegal_op 7
+#define R_SCSI0_STATUS__seq_status__info_rec_recvd 8
+#define R_SCSI0_STATUS__seq_status__info_reselected 9
+#define R_SCSI0_STATUS__seq_status__info_unhandled_status 10
+#define R_SCSI0_STATUS__seq_status__info_bus_reset 11
+#define R_SCSI0_STATUS__seq_status__info_illegal_bf 12
+#define R_SCSI0_STATUS__seq_status__info_bus_free 13
+
+#define R_SCSI0_DATA_IN (IO_TYPECAST_RO_UWORD 0xb0000040)
+#define R_SCSI0_DATA_IN__data_in__BITNR 0
+#define R_SCSI0_DATA_IN__data_in__WIDTH 16
+
+#define R_SCSI1_CTRL (IO_TYPECAST_UDWORD 0xb0000054)
+#define R_SCSI1_CTRL__id_type__BITNR 31
+#define R_SCSI1_CTRL__id_type__WIDTH 1
+#define R_SCSI1_CTRL__id_type__software 1
+#define R_SCSI1_CTRL__id_type__hardware 0
+#define R_SCSI1_CTRL__sel_timeout__BITNR 24
+#define R_SCSI1_CTRL__sel_timeout__WIDTH 7
+#define R_SCSI1_CTRL__synch_per__BITNR 16
+#define R_SCSI1_CTRL__synch_per__WIDTH 8
+#define R_SCSI1_CTRL__rst__BITNR 15
+#define R_SCSI1_CTRL__rst__WIDTH 1
+#define R_SCSI1_CTRL__rst__yes 1
+#define R_SCSI1_CTRL__rst__no 0
+#define R_SCSI1_CTRL__atn__BITNR 14
+#define R_SCSI1_CTRL__atn__WIDTH 1
+#define R_SCSI1_CTRL__atn__yes 1
+#define R_SCSI1_CTRL__atn__no 0
+#define R_SCSI1_CTRL__my_id__BITNR 9
+#define R_SCSI1_CTRL__my_id__WIDTH 4
+#define R_SCSI1_CTRL__target_id__BITNR 4
+#define R_SCSI1_CTRL__target_id__WIDTH 4
+#define R_SCSI1_CTRL__fast_20__BITNR 3
+#define R_SCSI1_CTRL__fast_20__WIDTH 1
+#define R_SCSI1_CTRL__fast_20__yes 1
+#define R_SCSI1_CTRL__fast_20__no 0
+#define R_SCSI1_CTRL__bus_width__BITNR 2
+#define R_SCSI1_CTRL__bus_width__WIDTH 1
+#define R_SCSI1_CTRL__bus_width__wide 1
+#define R_SCSI1_CTRL__bus_width__narrow 0
+#define R_SCSI1_CTRL__synch__BITNR 1
+#define R_SCSI1_CTRL__synch__WIDTH 1
+#define R_SCSI1_CTRL__synch__synch 1
+#define R_SCSI1_CTRL__synch__asynch 0
+#define R_SCSI1_CTRL__enable__BITNR 0
+#define R_SCSI1_CTRL__enable__WIDTH 1
+#define R_SCSI1_CTRL__enable__on 1
+#define R_SCSI1_CTRL__enable__off 0
+
+#define R_SCSI1_CMD_DATA (IO_TYPECAST_UDWORD 0xb0000050)
+#define R_SCSI1_CMD_DATA__parity_in__BITNR 26
+#define R_SCSI1_CMD_DATA__parity_in__WIDTH 1
+#define R_SCSI1_CMD_DATA__parity_in__on 0
+#define R_SCSI1_CMD_DATA__parity_in__off 1
+#define R_SCSI1_CMD_DATA__skip__BITNR 25
+#define R_SCSI1_CMD_DATA__skip__WIDTH 1
+#define R_SCSI1_CMD_DATA__skip__on 1
+#define R_SCSI1_CMD_DATA__skip__off 0
+#define R_SCSI1_CMD_DATA__clr_status__BITNR 24
+#define R_SCSI1_CMD_DATA__clr_status__WIDTH 1
+#define R_SCSI1_CMD_DATA__clr_status__yes 1
+#define R_SCSI1_CMD_DATA__clr_status__nop 0
+#define R_SCSI1_CMD_DATA__asynch_setup__BITNR 20
+#define R_SCSI1_CMD_DATA__asynch_setup__WIDTH 4
+#define R_SCSI1_CMD_DATA__command__BITNR 16
+#define R_SCSI1_CMD_DATA__command__WIDTH 4
+#define R_SCSI1_CMD_DATA__command__full_din_1 0
+#define R_SCSI1_CMD_DATA__command__full_dout_1 1
+#define R_SCSI1_CMD_DATA__command__full_stat_1 2
+#define R_SCSI1_CMD_DATA__command__resel_din 3
+#define R_SCSI1_CMD_DATA__command__resel_dout 4
+#define R_SCSI1_CMD_DATA__command__resel_stat 5
+#define R_SCSI1_CMD_DATA__command__arb_only 6
+#define R_SCSI1_CMD_DATA__command__full_din_3 8
+#define R_SCSI1_CMD_DATA__command__full_dout_3 9
+#define R_SCSI1_CMD_DATA__command__full_stat_3 10
+#define R_SCSI1_CMD_DATA__command__man_data_in 11
+#define R_SCSI1_CMD_DATA__command__man_data_out 12
+#define R_SCSI1_CMD_DATA__command__man_rat 13
+#define R_SCSI1_CMD_DATA__data_out__BITNR 0
+#define R_SCSI1_CMD_DATA__data_out__WIDTH 16
+
+#define R_SCSI1_DATA (IO_TYPECAST_UWORD 0xb0000050)
+#define R_SCSI1_DATA__data_out__BITNR 0
+#define R_SCSI1_DATA__data_out__WIDTH 16
+
+#define R_SCSI1_CMD (IO_TYPECAST_BYTE 0xb0000052)
+#define R_SCSI1_CMD__asynch_setup__BITNR 4
+#define R_SCSI1_CMD__asynch_setup__WIDTH 4
+#define R_SCSI1_CMD__command__BITNR 0
+#define R_SCSI1_CMD__command__WIDTH 4
+#define R_SCSI1_CMD__command__full_din_1 0
+#define R_SCSI1_CMD__command__full_dout_1 1
+#define R_SCSI1_CMD__command__full_stat_1 2
+#define R_SCSI1_CMD__command__resel_din 3
+#define R_SCSI1_CMD__command__resel_dout 4
+#define R_SCSI1_CMD__command__resel_stat 5
+#define R_SCSI1_CMD__command__arb_only 6
+#define R_SCSI1_CMD__command__full_din_3 8
+#define R_SCSI1_CMD__command__full_dout_3 9
+#define R_SCSI1_CMD__command__full_stat_3 10
+#define R_SCSI1_CMD__command__man_data_in 11
+#define R_SCSI1_CMD__command__man_data_out 12
+#define R_SCSI1_CMD__command__man_rat 13
+
+#define R_SCSI1_STATUS_CTRL (IO_TYPECAST_BYTE 0xb0000053)
+#define R_SCSI1_STATUS_CTRL__parity_in__BITNR 2
+#define R_SCSI1_STATUS_CTRL__parity_in__WIDTH 1
+#define R_SCSI1_STATUS_CTRL__parity_in__on 0
+#define R_SCSI1_STATUS_CTRL__parity_in__off 1
+#define R_SCSI1_STATUS_CTRL__skip__BITNR 1
+#define R_SCSI1_STATUS_CTRL__skip__WIDTH 1
+#define R_SCSI1_STATUS_CTRL__skip__on 1
+#define R_SCSI1_STATUS_CTRL__skip__off 0
+#define R_SCSI1_STATUS_CTRL__clr_status__BITNR 0
+#define R_SCSI1_STATUS_CTRL__clr_status__WIDTH 1
+#define R_SCSI1_STATUS_CTRL__clr_status__yes 1
+#define R_SCSI1_STATUS_CTRL__clr_status__nop 0
+
+#define R_SCSI1_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000058)
+#define R_SCSI1_STATUS__tst_arb_won__BITNR 23
+#define R_SCSI1_STATUS__tst_arb_won__WIDTH 1
+#define R_SCSI1_STATUS__tst_resel__BITNR 22
+#define R_SCSI1_STATUS__tst_resel__WIDTH 1
+#define R_SCSI1_STATUS__parity_error__BITNR 21
+#define R_SCSI1_STATUS__parity_error__WIDTH 1
+#define R_SCSI1_STATUS__bus_reset__BITNR 20
+#define R_SCSI1_STATUS__bus_reset__WIDTH 1
+#define R_SCSI1_STATUS__bus_reset__yes 1
+#define R_SCSI1_STATUS__bus_reset__no 0
+#define R_SCSI1_STATUS__resel_target__BITNR 15
+#define R_SCSI1_STATUS__resel_target__WIDTH 4
+#define R_SCSI1_STATUS__resel__BITNR 14
+#define R_SCSI1_STATUS__resel__WIDTH 1
+#define R_SCSI1_STATUS__resel__yes 1
+#define R_SCSI1_STATUS__resel__no 0
+#define R_SCSI1_STATUS__curr_phase__BITNR 11
+#define R_SCSI1_STATUS__curr_phase__WIDTH 3
+#define R_SCSI1_STATUS__curr_phase__ph_undef 0
+#define R_SCSI1_STATUS__curr_phase__ph_msg_in 7
+#define R_SCSI1_STATUS__curr_phase__ph_msg_out 6
+#define R_SCSI1_STATUS__curr_phase__ph_status 3
+#define R_SCSI1_STATUS__curr_phase__ph_command 2
+#define R_SCSI1_STATUS__curr_phase__ph_data_in 5
+#define R_SCSI1_STATUS__curr_phase__ph_data_out 4
+#define R_SCSI1_STATUS__curr_phase__ph_resel 1
+#define R_SCSI1_STATUS__last_seq_step__BITNR 6
+#define R_SCSI1_STATUS__last_seq_step__WIDTH 5
+#define R_SCSI1_STATUS__last_seq_step__st_bus_free 24
+#define R_SCSI1_STATUS__last_seq_step__st_arbitrate 8
+#define R_SCSI1_STATUS__last_seq_step__st_resel_req 29
+#define R_SCSI1_STATUS__last_seq_step__st_msg_1 2
+#define R_SCSI1_STATUS__last_seq_step__st_manual 28
+#define R_SCSI1_STATUS__last_seq_step__st_transf_cmd 30
+#define R_SCSI1_STATUS__last_seq_step__st_msg_2 6
+#define R_SCSI1_STATUS__last_seq_step__st_msg_3 22
+#define R_SCSI1_STATUS__last_seq_step__st_answer 3
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din_perr 1
+#define R_SCSI1_STATUS__last_seq_step__st_transfer_done 15
+#define R_SCSI1_STATUS__last_seq_step__st_synch_dout 0
+#define R_SCSI1_STATUS__last_seq_step__st_asynch_dout 25
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din 13
+#define R_SCSI1_STATUS__last_seq_step__st_asynch_din 9
+#define R_SCSI1_STATUS__last_seq_step__st_synch_dout_ack 4
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din_ack 12
+#define R_SCSI1_STATUS__last_seq_step__st_synch_din_ack_perr 5
+#define R_SCSI1_STATUS__last_seq_step__st_asynch_dout_end 11
+#define R_SCSI1_STATUS__last_seq_step__st_iwr 27
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_disc 21
+#define R_SCSI1_STATUS__last_seq_step__st_sdp_disc 7
+#define R_SCSI1_STATUS__last_seq_step__st_cc 31
+#define R_SCSI1_STATUS__last_seq_step__st_iwr_good 14
+#define R_SCSI1_STATUS__last_seq_step__st_iwr_cc 23
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_iwr_cc 17
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_cc 20
+#define R_SCSI1_STATUS__last_seq_step__st_wait_free_sdp_disc 16
+#define R_SCSI1_STATUS__last_seq_step__st_manual_req 10
+#define R_SCSI1_STATUS__last_seq_step__st_manual_din_prot 18
+#define R_SCSI1_STATUS__valid_status__BITNR 5
+#define R_SCSI1_STATUS__valid_status__WIDTH 1
+#define R_SCSI1_STATUS__valid_status__yes 1
+#define R_SCSI1_STATUS__valid_status__no 0
+#define R_SCSI1_STATUS__seq_status__BITNR 0
+#define R_SCSI1_STATUS__seq_status__WIDTH 5
+#define R_SCSI1_STATUS__seq_status__info_seq_complete 0
+#define R_SCSI1_STATUS__seq_status__info_parity_error 1
+#define R_SCSI1_STATUS__seq_status__info_unhandled_msg_in 2
+#define R_SCSI1_STATUS__seq_status__info_unexp_ph_change 3
+#define R_SCSI1_STATUS__seq_status__info_arb_lost 4
+#define R_SCSI1_STATUS__seq_status__info_sel_timeout 5
+#define R_SCSI1_STATUS__seq_status__info_unexp_bf 6
+#define R_SCSI1_STATUS__seq_status__info_illegal_op 7
+#define R_SCSI1_STATUS__seq_status__info_rec_recvd 8
+#define R_SCSI1_STATUS__seq_status__info_reselected 9
+#define R_SCSI1_STATUS__seq_status__info_unhandled_status 10
+#define R_SCSI1_STATUS__seq_status__info_bus_reset 11
+#define R_SCSI1_STATUS__seq_status__info_illegal_bf 12
+#define R_SCSI1_STATUS__seq_status__info_bus_free 13
+
+#define R_SCSI1_DATA_IN (IO_TYPECAST_RO_UWORD 0xb0000050)
+#define R_SCSI1_DATA_IN__data_in__BITNR 0
+#define R_SCSI1_DATA_IN__data_in__WIDTH 16
+
+/*
+!* Interrupt mask and status registers
+!*/
+
+#define R_IRQ_MASK0_RD (IO_TYPECAST_RO_UDWORD 0xb00000c0)
+#define R_IRQ_MASK0_RD__nmi_pin__BITNR 31
+#define R_IRQ_MASK0_RD__nmi_pin__WIDTH 1
+#define R_IRQ_MASK0_RD__nmi_pin__active 1
+#define R_IRQ_MASK0_RD__nmi_pin__inactive 0
+#define R_IRQ_MASK0_RD__watchdog_nmi__BITNR 30
+#define R_IRQ_MASK0_RD__watchdog_nmi__WIDTH 1
+#define R_IRQ_MASK0_RD__watchdog_nmi__active 1
+#define R_IRQ_MASK0_RD__watchdog_nmi__inactive 0
+#define R_IRQ_MASK0_RD__sqe_test_error__BITNR 29
+#define R_IRQ_MASK0_RD__sqe_test_error__WIDTH 1
+#define R_IRQ_MASK0_RD__sqe_test_error__active 1
+#define R_IRQ_MASK0_RD__sqe_test_error__inactive 0
+#define R_IRQ_MASK0_RD__carrier_loss__BITNR 28
+#define R_IRQ_MASK0_RD__carrier_loss__WIDTH 1
+#define R_IRQ_MASK0_RD__carrier_loss__active 1
+#define R_IRQ_MASK0_RD__carrier_loss__inactive 0
+#define R_IRQ_MASK0_RD__deferred__BITNR 27
+#define R_IRQ_MASK0_RD__deferred__WIDTH 1
+#define R_IRQ_MASK0_RD__deferred__active 1
+#define R_IRQ_MASK0_RD__deferred__inactive 0
+#define R_IRQ_MASK0_RD__late_col__BITNR 26
+#define R_IRQ_MASK0_RD__late_col__WIDTH 1
+#define R_IRQ_MASK0_RD__late_col__active 1
+#define R_IRQ_MASK0_RD__late_col__inactive 0
+#define R_IRQ_MASK0_RD__multiple_col__BITNR 25
+#define R_IRQ_MASK0_RD__multiple_col__WIDTH 1
+#define R_IRQ_MASK0_RD__multiple_col__active 1
+#define R_IRQ_MASK0_RD__multiple_col__inactive 0
+#define R_IRQ_MASK0_RD__single_col__BITNR 24
+#define R_IRQ_MASK0_RD__single_col__WIDTH 1
+#define R_IRQ_MASK0_RD__single_col__active 1
+#define R_IRQ_MASK0_RD__single_col__inactive 0
+#define R_IRQ_MASK0_RD__congestion__BITNR 23
+#define R_IRQ_MASK0_RD__congestion__WIDTH 1
+#define R_IRQ_MASK0_RD__congestion__active 1
+#define R_IRQ_MASK0_RD__congestion__inactive 0
+#define R_IRQ_MASK0_RD__oversize__BITNR 22
+#define R_IRQ_MASK0_RD__oversize__WIDTH 1
+#define R_IRQ_MASK0_RD__oversize__active 1
+#define R_IRQ_MASK0_RD__oversize__inactive 0
+#define R_IRQ_MASK0_RD__alignment_error__BITNR 21
+#define R_IRQ_MASK0_RD__alignment_error__WIDTH 1
+#define R_IRQ_MASK0_RD__alignment_error__active 1
+#define R_IRQ_MASK0_RD__alignment_error__inactive 0
+#define R_IRQ_MASK0_RD__crc_error__BITNR 20
+#define R_IRQ_MASK0_RD__crc_error__WIDTH 1
+#define R_IRQ_MASK0_RD__crc_error__active 1
+#define R_IRQ_MASK0_RD__crc_error__inactive 0
+#define R_IRQ_MASK0_RD__overrun__BITNR 19
+#define R_IRQ_MASK0_RD__overrun__WIDTH 1
+#define R_IRQ_MASK0_RD__overrun__active 1
+#define R_IRQ_MASK0_RD__overrun__inactive 0
+#define R_IRQ_MASK0_RD__underrun__BITNR 18
+#define R_IRQ_MASK0_RD__underrun__WIDTH 1
+#define R_IRQ_MASK0_RD__underrun__active 1
+#define R_IRQ_MASK0_RD__underrun__inactive 0
+#define R_IRQ_MASK0_RD__excessive_col__BITNR 17
+#define R_IRQ_MASK0_RD__excessive_col__WIDTH 1
+#define R_IRQ_MASK0_RD__excessive_col__active 1
+#define R_IRQ_MASK0_RD__excessive_col__inactive 0
+#define R_IRQ_MASK0_RD__mdio__BITNR 16
+#define R_IRQ_MASK0_RD__mdio__WIDTH 1
+#define R_IRQ_MASK0_RD__mdio__active 1
+#define R_IRQ_MASK0_RD__mdio__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq3__BITNR 15
+#define R_IRQ_MASK0_RD__ata_drq3__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq3__active 1
+#define R_IRQ_MASK0_RD__ata_drq3__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq2__BITNR 14
+#define R_IRQ_MASK0_RD__ata_drq2__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq2__active 1
+#define R_IRQ_MASK0_RD__ata_drq2__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq1__BITNR 13
+#define R_IRQ_MASK0_RD__ata_drq1__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq1__active 1
+#define R_IRQ_MASK0_RD__ata_drq1__inactive 0
+#define R_IRQ_MASK0_RD__ata_drq0__BITNR 12
+#define R_IRQ_MASK0_RD__ata_drq0__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_drq0__active 1
+#define R_IRQ_MASK0_RD__ata_drq0__inactive 0
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__BITNR 11
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__active 1
+#define R_IRQ_MASK0_RD__par0_ecp_cmd__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq3__BITNR 11
+#define R_IRQ_MASK0_RD__ata_irq3__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq3__active 1
+#define R_IRQ_MASK0_RD__ata_irq3__inactive 0
+#define R_IRQ_MASK0_RD__par0_peri__BITNR 10
+#define R_IRQ_MASK0_RD__par0_peri__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_peri__active 1
+#define R_IRQ_MASK0_RD__par0_peri__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq2__BITNR 10
+#define R_IRQ_MASK0_RD__ata_irq2__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq2__active 1
+#define R_IRQ_MASK0_RD__ata_irq2__inactive 0
+#define R_IRQ_MASK0_RD__p21_irq2__BITNR 10
+#define R_IRQ_MASK0_RD__p21_irq2__WIDTH 1
+#define R_IRQ_MASK0_RD__p21_irq2__active 1
+#define R_IRQ_MASK0_RD__p21_irq2__inactive 0
+#define R_IRQ_MASK0_RD__par0_data__BITNR 9
+#define R_IRQ_MASK0_RD__par0_data__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_data__active 1
+#define R_IRQ_MASK0_RD__par0_data__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq1__BITNR 9
+#define R_IRQ_MASK0_RD__ata_irq1__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq1__active 1
+#define R_IRQ_MASK0_RD__ata_irq1__inactive 0
+#define R_IRQ_MASK0_RD__p21_irq1__BITNR 9
+#define R_IRQ_MASK0_RD__p21_irq1__WIDTH 1
+#define R_IRQ_MASK0_RD__p21_irq1__active 1
+#define R_IRQ_MASK0_RD__p21_irq1__inactive 0
+#define R_IRQ_MASK0_RD__par0_ready__BITNR 8
+#define R_IRQ_MASK0_RD__par0_ready__WIDTH 1
+#define R_IRQ_MASK0_RD__par0_ready__active 1
+#define R_IRQ_MASK0_RD__par0_ready__inactive 0
+#define R_IRQ_MASK0_RD__ata_irq0__BITNR 8
+#define R_IRQ_MASK0_RD__ata_irq0__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_irq0__active 1
+#define R_IRQ_MASK0_RD__ata_irq0__inactive 0
+#define R_IRQ_MASK0_RD__mio__BITNR 8
+#define R_IRQ_MASK0_RD__mio__WIDTH 1
+#define R_IRQ_MASK0_RD__mio__active 1
+#define R_IRQ_MASK0_RD__mio__inactive 0
+#define R_IRQ_MASK0_RD__scsi0__BITNR 8
+#define R_IRQ_MASK0_RD__scsi0__WIDTH 1
+#define R_IRQ_MASK0_RD__scsi0__active 1
+#define R_IRQ_MASK0_RD__scsi0__inactive 0
+#define R_IRQ_MASK0_RD__p21_irq0__BITNR 8
+#define R_IRQ_MASK0_RD__p21_irq0__WIDTH 1
+#define R_IRQ_MASK0_RD__p21_irq0__active 1
+#define R_IRQ_MASK0_RD__p21_irq0__inactive 0
+#define R_IRQ_MASK0_RD__ata_dmaend__BITNR 7
+#define R_IRQ_MASK0_RD__ata_dmaend__WIDTH 1
+#define R_IRQ_MASK0_RD__ata_dmaend__active 1
+#define R_IRQ_MASK0_RD__ata_dmaend__inactive 0
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__active 1
+#define R_IRQ_MASK0_RD__irq_ext_vector_nr__inactive 0
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__BITNR 4
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__active 1
+#define R_IRQ_MASK0_RD__irq_int_vector_nr__inactive 0
+#define R_IRQ_MASK0_RD__ext_dma1__BITNR 3
+#define R_IRQ_MASK0_RD__ext_dma1__WIDTH 1
+#define R_IRQ_MASK0_RD__ext_dma1__active 1
+#define R_IRQ_MASK0_RD__ext_dma1__inactive 0
+#define R_IRQ_MASK0_RD__ext_dma0__BITNR 2
+#define R_IRQ_MASK0_RD__ext_dma0__WIDTH 1
+#define R_IRQ_MASK0_RD__ext_dma0__active 1
+#define R_IRQ_MASK0_RD__ext_dma0__inactive 0
+#define R_IRQ_MASK0_RD__timer1__BITNR 1
+#define R_IRQ_MASK0_RD__timer1__WIDTH 1
+#define R_IRQ_MASK0_RD__timer1__active 1
+#define R_IRQ_MASK0_RD__timer1__inactive 0
+#define R_IRQ_MASK0_RD__timer0__BITNR 0
+#define R_IRQ_MASK0_RD__timer0__WIDTH 1
+#define R_IRQ_MASK0_RD__timer0__active 1
+#define R_IRQ_MASK0_RD__timer0__inactive 0
+
+#define R_IRQ_MASK0_CLR (IO_TYPECAST_UDWORD 0xb00000c0)
+#define R_IRQ_MASK0_CLR__nmi_pin__BITNR 31
+#define R_IRQ_MASK0_CLR__nmi_pin__WIDTH 1
+#define R_IRQ_MASK0_CLR__nmi_pin__clr 1
+#define R_IRQ_MASK0_CLR__nmi_pin__nop 0
+#define R_IRQ_MASK0_CLR__watchdog_nmi__BITNR 30
+#define R_IRQ_MASK0_CLR__watchdog_nmi__WIDTH 1
+#define R_IRQ_MASK0_CLR__watchdog_nmi__clr 1
+#define R_IRQ_MASK0_CLR__watchdog_nmi__nop 0
+#define R_IRQ_MASK0_CLR__sqe_test_error__BITNR 29
+#define R_IRQ_MASK0_CLR__sqe_test_error__WIDTH 1
+#define R_IRQ_MASK0_CLR__sqe_test_error__clr 1
+#define R_IRQ_MASK0_CLR__sqe_test_error__nop 0
+#define R_IRQ_MASK0_CLR__carrier_loss__BITNR 28
+#define R_IRQ_MASK0_CLR__carrier_loss__WIDTH 1
+#define R_IRQ_MASK0_CLR__carrier_loss__clr 1
+#define R_IRQ_MASK0_CLR__carrier_loss__nop 0
+#define R_IRQ_MASK0_CLR__deferred__BITNR 27
+#define R_IRQ_MASK0_CLR__deferred__WIDTH 1
+#define R_IRQ_MASK0_CLR__deferred__clr 1
+#define R_IRQ_MASK0_CLR__deferred__nop 0
+#define R_IRQ_MASK0_CLR__late_col__BITNR 26
+#define R_IRQ_MASK0_CLR__late_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__late_col__clr 1
+#define R_IRQ_MASK0_CLR__late_col__nop 0
+#define R_IRQ_MASK0_CLR__multiple_col__BITNR 25
+#define R_IRQ_MASK0_CLR__multiple_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__multiple_col__clr 1
+#define R_IRQ_MASK0_CLR__multiple_col__nop 0
+#define R_IRQ_MASK0_CLR__single_col__BITNR 24
+#define R_IRQ_MASK0_CLR__single_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__single_col__clr 1
+#define R_IRQ_MASK0_CLR__single_col__nop 0
+#define R_IRQ_MASK0_CLR__congestion__BITNR 23
+#define R_IRQ_MASK0_CLR__congestion__WIDTH 1
+#define R_IRQ_MASK0_CLR__congestion__clr 1
+#define R_IRQ_MASK0_CLR__congestion__nop 0
+#define R_IRQ_MASK0_CLR__oversize__BITNR 22
+#define R_IRQ_MASK0_CLR__oversize__WIDTH 1
+#define R_IRQ_MASK0_CLR__oversize__clr 1
+#define R_IRQ_MASK0_CLR__oversize__nop 0
+#define R_IRQ_MASK0_CLR__alignment_error__BITNR 21
+#define R_IRQ_MASK0_CLR__alignment_error__WIDTH 1
+#define R_IRQ_MASK0_CLR__alignment_error__clr 1
+#define R_IRQ_MASK0_CLR__alignment_error__nop 0
+#define R_IRQ_MASK0_CLR__crc_error__BITNR 20
+#define R_IRQ_MASK0_CLR__crc_error__WIDTH 1
+#define R_IRQ_MASK0_CLR__crc_error__clr 1
+#define R_IRQ_MASK0_CLR__crc_error__nop 0
+#define R_IRQ_MASK0_CLR__overrun__BITNR 19
+#define R_IRQ_MASK0_CLR__overrun__WIDTH 1
+#define R_IRQ_MASK0_CLR__overrun__clr 1
+#define R_IRQ_MASK0_CLR__overrun__nop 0
+#define R_IRQ_MASK0_CLR__underrun__BITNR 18
+#define R_IRQ_MASK0_CLR__underrun__WIDTH 1
+#define R_IRQ_MASK0_CLR__underrun__clr 1
+#define R_IRQ_MASK0_CLR__underrun__nop 0
+#define R_IRQ_MASK0_CLR__excessive_col__BITNR 17
+#define R_IRQ_MASK0_CLR__excessive_col__WIDTH 1
+#define R_IRQ_MASK0_CLR__excessive_col__clr 1
+#define R_IRQ_MASK0_CLR__excessive_col__nop 0
+#define R_IRQ_MASK0_CLR__mdio__BITNR 16
+#define R_IRQ_MASK0_CLR__mdio__WIDTH 1
+#define R_IRQ_MASK0_CLR__mdio__clr 1
+#define R_IRQ_MASK0_CLR__mdio__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq3__BITNR 15
+#define R_IRQ_MASK0_CLR__ata_drq3__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq3__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq3__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq2__BITNR 14
+#define R_IRQ_MASK0_CLR__ata_drq2__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq2__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq2__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq1__BITNR 13
+#define R_IRQ_MASK0_CLR__ata_drq1__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq1__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq1__nop 0
+#define R_IRQ_MASK0_CLR__ata_drq0__BITNR 12
+#define R_IRQ_MASK0_CLR__ata_drq0__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_drq0__clr 1
+#define R_IRQ_MASK0_CLR__ata_drq0__nop 0
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__BITNR 11
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__clr 1
+#define R_IRQ_MASK0_CLR__par0_ecp_cmd__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq3__BITNR 11
+#define R_IRQ_MASK0_CLR__ata_irq3__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq3__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq3__nop 0
+#define R_IRQ_MASK0_CLR__par0_peri__BITNR 10
+#define R_IRQ_MASK0_CLR__par0_peri__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_peri__clr 1
+#define R_IRQ_MASK0_CLR__par0_peri__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq2__BITNR 10
+#define R_IRQ_MASK0_CLR__ata_irq2__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq2__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq2__nop 0
+#define R_IRQ_MASK0_CLR__p21_irq2__BITNR 10
+#define R_IRQ_MASK0_CLR__p21_irq2__WIDTH 1
+#define R_IRQ_MASK0_CLR__p21_irq2__clr 1
+#define R_IRQ_MASK0_CLR__p21_irq2__nop 0
+#define R_IRQ_MASK0_CLR__par0_data__BITNR 9
+#define R_IRQ_MASK0_CLR__par0_data__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_data__clr 1
+#define R_IRQ_MASK0_CLR__par0_data__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq1__BITNR 9
+#define R_IRQ_MASK0_CLR__ata_irq1__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq1__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq1__nop 0
+#define R_IRQ_MASK0_CLR__p21_irq1__BITNR 9
+#define R_IRQ_MASK0_CLR__p21_irq1__WIDTH 1
+#define R_IRQ_MASK0_CLR__p21_irq1__clr 1
+#define R_IRQ_MASK0_CLR__p21_irq1__nop 0
+#define R_IRQ_MASK0_CLR__par0_ready__BITNR 8
+#define R_IRQ_MASK0_CLR__par0_ready__WIDTH 1
+#define R_IRQ_MASK0_CLR__par0_ready__clr 1
+#define R_IRQ_MASK0_CLR__par0_ready__nop 0
+#define R_IRQ_MASK0_CLR__ata_irq0__BITNR 8
+#define R_IRQ_MASK0_CLR__ata_irq0__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_irq0__clr 1
+#define R_IRQ_MASK0_CLR__ata_irq0__nop 0
+#define R_IRQ_MASK0_CLR__mio__BITNR 8
+#define R_IRQ_MASK0_CLR__mio__WIDTH 1
+#define R_IRQ_MASK0_CLR__mio__clr 1
+#define R_IRQ_MASK0_CLR__mio__nop 0
+#define R_IRQ_MASK0_CLR__scsi0__BITNR 8
+#define R_IRQ_MASK0_CLR__scsi0__WIDTH 1
+#define R_IRQ_MASK0_CLR__scsi0__clr 1
+#define R_IRQ_MASK0_CLR__scsi0__nop 0
+#define R_IRQ_MASK0_CLR__p21_irq0__BITNR 8
+#define R_IRQ_MASK0_CLR__p21_irq0__WIDTH 1
+#define R_IRQ_MASK0_CLR__p21_irq0__clr 1
+#define R_IRQ_MASK0_CLR__p21_irq0__nop 0
+#define R_IRQ_MASK0_CLR__ata_dmaend__BITNR 7
+#define R_IRQ_MASK0_CLR__ata_dmaend__WIDTH 1
+#define R_IRQ_MASK0_CLR__ata_dmaend__clr 1
+#define R_IRQ_MASK0_CLR__ata_dmaend__nop 0
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__clr 1
+#define R_IRQ_MASK0_CLR__irq_ext_vector_nr__nop 0
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__BITNR 4
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__clr 1
+#define R_IRQ_MASK0_CLR__irq_int_vector_nr__nop 0
+#define R_IRQ_MASK0_CLR__ext_dma1__BITNR 3
+#define R_IRQ_MASK0_CLR__ext_dma1__WIDTH 1
+#define R_IRQ_MASK0_CLR__ext_dma1__clr 1
+#define R_IRQ_MASK0_CLR__ext_dma1__nop 0
+#define R_IRQ_MASK0_CLR__ext_dma0__BITNR 2
+#define R_IRQ_MASK0_CLR__ext_dma0__WIDTH 1
+#define R_IRQ_MASK0_CLR__ext_dma0__clr 1
+#define R_IRQ_MASK0_CLR__ext_dma0__nop 0
+#define R_IRQ_MASK0_CLR__timer1__BITNR 1
+#define R_IRQ_MASK0_CLR__timer1__WIDTH 1
+#define R_IRQ_MASK0_CLR__timer1__clr 1
+#define R_IRQ_MASK0_CLR__timer1__nop 0
+#define R_IRQ_MASK0_CLR__timer0__BITNR 0
+#define R_IRQ_MASK0_CLR__timer0__WIDTH 1
+#define R_IRQ_MASK0_CLR__timer0__clr 1
+#define R_IRQ_MASK0_CLR__timer0__nop 0
+
+#define R_IRQ_READ0 (IO_TYPECAST_RO_UDWORD 0xb00000c4)
+#define R_IRQ_READ0__nmi_pin__BITNR 31
+#define R_IRQ_READ0__nmi_pin__WIDTH 1
+#define R_IRQ_READ0__nmi_pin__active 1
+#define R_IRQ_READ0__nmi_pin__inactive 0
+#define R_IRQ_READ0__watchdog_nmi__BITNR 30
+#define R_IRQ_READ0__watchdog_nmi__WIDTH 1
+#define R_IRQ_READ0__watchdog_nmi__active 1
+#define R_IRQ_READ0__watchdog_nmi__inactive 0
+#define R_IRQ_READ0__sqe_test_error__BITNR 29
+#define R_IRQ_READ0__sqe_test_error__WIDTH 1
+#define R_IRQ_READ0__sqe_test_error__active 1
+#define R_IRQ_READ0__sqe_test_error__inactive 0
+#define R_IRQ_READ0__carrier_loss__BITNR 28
+#define R_IRQ_READ0__carrier_loss__WIDTH 1
+#define R_IRQ_READ0__carrier_loss__active 1
+#define R_IRQ_READ0__carrier_loss__inactive 0
+#define R_IRQ_READ0__deferred__BITNR 27
+#define R_IRQ_READ0__deferred__WIDTH 1
+#define R_IRQ_READ0__deferred__active 1
+#define R_IRQ_READ0__deferred__inactive 0
+#define R_IRQ_READ0__late_col__BITNR 26
+#define R_IRQ_READ0__late_col__WIDTH 1
+#define R_IRQ_READ0__late_col__active 1
+#define R_IRQ_READ0__late_col__inactive 0
+#define R_IRQ_READ0__multiple_col__BITNR 25
+#define R_IRQ_READ0__multiple_col__WIDTH 1
+#define R_IRQ_READ0__multiple_col__active 1
+#define R_IRQ_READ0__multiple_col__inactive 0
+#define R_IRQ_READ0__single_col__BITNR 24
+#define R_IRQ_READ0__single_col__WIDTH 1
+#define R_IRQ_READ0__single_col__active 1
+#define R_IRQ_READ0__single_col__inactive 0
+#define R_IRQ_READ0__congestion__BITNR 23
+#define R_IRQ_READ0__congestion__WIDTH 1
+#define R_IRQ_READ0__congestion__active 1
+#define R_IRQ_READ0__congestion__inactive 0
+#define R_IRQ_READ0__oversize__BITNR 22
+#define R_IRQ_READ0__oversize__WIDTH 1
+#define R_IRQ_READ0__oversize__active 1
+#define R_IRQ_READ0__oversize__inactive 0
+#define R_IRQ_READ0__alignment_error__BITNR 21
+#define R_IRQ_READ0__alignment_error__WIDTH 1
+#define R_IRQ_READ0__alignment_error__active 1
+#define R_IRQ_READ0__alignment_error__inactive 0
+#define R_IRQ_READ0__crc_error__BITNR 20
+#define R_IRQ_READ0__crc_error__WIDTH 1
+#define R_IRQ_READ0__crc_error__active 1
+#define R_IRQ_READ0__crc_error__inactive 0
+#define R_IRQ_READ0__overrun__BITNR 19
+#define R_IRQ_READ0__overrun__WIDTH 1
+#define R_IRQ_READ0__overrun__active 1
+#define R_IRQ_READ0__overrun__inactive 0
+#define R_IRQ_READ0__underrun__BITNR 18
+#define R_IRQ_READ0__underrun__WIDTH 1
+#define R_IRQ_READ0__underrun__active 1
+#define R_IRQ_READ0__underrun__inactive 0
+#define R_IRQ_READ0__excessive_col__BITNR 17
+#define R_IRQ_READ0__excessive_col__WIDTH 1
+#define R_IRQ_READ0__excessive_col__active 1
+#define R_IRQ_READ0__excessive_col__inactive 0
+#define R_IRQ_READ0__mdio__BITNR 16
+#define R_IRQ_READ0__mdio__WIDTH 1
+#define R_IRQ_READ0__mdio__active 1
+#define R_IRQ_READ0__mdio__inactive 0
+#define R_IRQ_READ0__ata_drq3__BITNR 15
+#define R_IRQ_READ0__ata_drq3__WIDTH 1
+#define R_IRQ_READ0__ata_drq3__active 1
+#define R_IRQ_READ0__ata_drq3__inactive 0
+#define R_IRQ_READ0__ata_drq2__BITNR 14
+#define R_IRQ_READ0__ata_drq2__WIDTH 1
+#define R_IRQ_READ0__ata_drq2__active 1
+#define R_IRQ_READ0__ata_drq2__inactive 0
+#define R_IRQ_READ0__ata_drq1__BITNR 13
+#define R_IRQ_READ0__ata_drq1__WIDTH 1
+#define R_IRQ_READ0__ata_drq1__active 1
+#define R_IRQ_READ0__ata_drq1__inactive 0
+#define R_IRQ_READ0__ata_drq0__BITNR 12
+#define R_IRQ_READ0__ata_drq0__WIDTH 1
+#define R_IRQ_READ0__ata_drq0__active 1
+#define R_IRQ_READ0__ata_drq0__inactive 0
+#define R_IRQ_READ0__par0_ecp_cmd__BITNR 11
+#define R_IRQ_READ0__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_READ0__par0_ecp_cmd__active 1
+#define R_IRQ_READ0__par0_ecp_cmd__inactive 0
+#define R_IRQ_READ0__ata_irq3__BITNR 11
+#define R_IRQ_READ0__ata_irq3__WIDTH 1
+#define R_IRQ_READ0__ata_irq3__active 1
+#define R_IRQ_READ0__ata_irq3__inactive 0
+#define R_IRQ_READ0__par0_peri__BITNR 10
+#define R_IRQ_READ0__par0_peri__WIDTH 1
+#define R_IRQ_READ0__par0_peri__active 1
+#define R_IRQ_READ0__par0_peri__inactive 0
+#define R_IRQ_READ0__ata_irq2__BITNR 10
+#define R_IRQ_READ0__ata_irq2__WIDTH 1
+#define R_IRQ_READ0__ata_irq2__active 1
+#define R_IRQ_READ0__ata_irq2__inactive 0
+#define R_IRQ_READ0__p21_irq2__BITNR 10
+#define R_IRQ_READ0__p21_irq2__WIDTH 1
+#define R_IRQ_READ0__p21_irq2__active 1
+#define R_IRQ_READ0__p21_irq2__inactive 0
+#define R_IRQ_READ0__par0_data__BITNR 9
+#define R_IRQ_READ0__par0_data__WIDTH 1
+#define R_IRQ_READ0__par0_data__active 1
+#define R_IRQ_READ0__par0_data__inactive 0
+#define R_IRQ_READ0__ata_irq1__BITNR 9
+#define R_IRQ_READ0__ata_irq1__WIDTH 1
+#define R_IRQ_READ0__ata_irq1__active 1
+#define R_IRQ_READ0__ata_irq1__inactive 0
+#define R_IRQ_READ0__p21_irq1__BITNR 9
+#define R_IRQ_READ0__p21_irq1__WIDTH 1
+#define R_IRQ_READ0__p21_irq1__active 1
+#define R_IRQ_READ0__p21_irq1__inactive 0
+#define R_IRQ_READ0__par0_ready__BITNR 8
+#define R_IRQ_READ0__par0_ready__WIDTH 1
+#define R_IRQ_READ0__par0_ready__active 1
+#define R_IRQ_READ0__par0_ready__inactive 0
+#define R_IRQ_READ0__ata_irq0__BITNR 8
+#define R_IRQ_READ0__ata_irq0__WIDTH 1
+#define R_IRQ_READ0__ata_irq0__active 1
+#define R_IRQ_READ0__ata_irq0__inactive 0
+#define R_IRQ_READ0__mio__BITNR 8
+#define R_IRQ_READ0__mio__WIDTH 1
+#define R_IRQ_READ0__mio__active 1
+#define R_IRQ_READ0__mio__inactive 0
+#define R_IRQ_READ0__scsi0__BITNR 8
+#define R_IRQ_READ0__scsi0__WIDTH 1
+#define R_IRQ_READ0__scsi0__active 1
+#define R_IRQ_READ0__scsi0__inactive 0
+#define R_IRQ_READ0__p21_irq0__BITNR 8
+#define R_IRQ_READ0__p21_irq0__WIDTH 1
+#define R_IRQ_READ0__p21_irq0__active 1
+#define R_IRQ_READ0__p21_irq0__inactive 0
+#define R_IRQ_READ0__ata_dmaend__BITNR 7
+#define R_IRQ_READ0__ata_dmaend__WIDTH 1
+#define R_IRQ_READ0__ata_dmaend__active 1
+#define R_IRQ_READ0__ata_dmaend__inactive 0
+#define R_IRQ_READ0__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_READ0__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_READ0__irq_ext_vector_nr__active 1
+#define R_IRQ_READ0__irq_ext_vector_nr__inactive 0
+#define R_IRQ_READ0__irq_int_vector_nr__BITNR 4
+#define R_IRQ_READ0__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_READ0__irq_int_vector_nr__active 1
+#define R_IRQ_READ0__irq_int_vector_nr__inactive 0
+#define R_IRQ_READ0__ext_dma1__BITNR 3
+#define R_IRQ_READ0__ext_dma1__WIDTH 1
+#define R_IRQ_READ0__ext_dma1__active 1
+#define R_IRQ_READ0__ext_dma1__inactive 0
+#define R_IRQ_READ0__ext_dma0__BITNR 2
+#define R_IRQ_READ0__ext_dma0__WIDTH 1
+#define R_IRQ_READ0__ext_dma0__active 1
+#define R_IRQ_READ0__ext_dma0__inactive 0
+#define R_IRQ_READ0__timer1__BITNR 1
+#define R_IRQ_READ0__timer1__WIDTH 1
+#define R_IRQ_READ0__timer1__active 1
+#define R_IRQ_READ0__timer1__inactive 0
+#define R_IRQ_READ0__timer0__BITNR 0
+#define R_IRQ_READ0__timer0__WIDTH 1
+#define R_IRQ_READ0__timer0__active 1
+#define R_IRQ_READ0__timer0__inactive 0
+
+#define R_IRQ_MASK0_SET (IO_TYPECAST_UDWORD 0xb00000c4)
+#define R_IRQ_MASK0_SET__nmi_pin__BITNR 31
+#define R_IRQ_MASK0_SET__nmi_pin__WIDTH 1
+#define R_IRQ_MASK0_SET__nmi_pin__set 1
+#define R_IRQ_MASK0_SET__nmi_pin__nop 0
+#define R_IRQ_MASK0_SET__watchdog_nmi__BITNR 30
+#define R_IRQ_MASK0_SET__watchdog_nmi__WIDTH 1
+#define R_IRQ_MASK0_SET__watchdog_nmi__set 1
+#define R_IRQ_MASK0_SET__watchdog_nmi__nop 0
+#define R_IRQ_MASK0_SET__sqe_test_error__BITNR 29
+#define R_IRQ_MASK0_SET__sqe_test_error__WIDTH 1
+#define R_IRQ_MASK0_SET__sqe_test_error__set 1
+#define R_IRQ_MASK0_SET__sqe_test_error__nop 0
+#define R_IRQ_MASK0_SET__carrier_loss__BITNR 28
+#define R_IRQ_MASK0_SET__carrier_loss__WIDTH 1
+#define R_IRQ_MASK0_SET__carrier_loss__set 1
+#define R_IRQ_MASK0_SET__carrier_loss__nop 0
+#define R_IRQ_MASK0_SET__deferred__BITNR 27
+#define R_IRQ_MASK0_SET__deferred__WIDTH 1
+#define R_IRQ_MASK0_SET__deferred__set 1
+#define R_IRQ_MASK0_SET__deferred__nop 0
+#define R_IRQ_MASK0_SET__late_col__BITNR 26
+#define R_IRQ_MASK0_SET__late_col__WIDTH 1
+#define R_IRQ_MASK0_SET__late_col__set 1
+#define R_IRQ_MASK0_SET__late_col__nop 0
+#define R_IRQ_MASK0_SET__multiple_col__BITNR 25
+#define R_IRQ_MASK0_SET__multiple_col__WIDTH 1
+#define R_IRQ_MASK0_SET__multiple_col__set 1
+#define R_IRQ_MASK0_SET__multiple_col__nop 0
+#define R_IRQ_MASK0_SET__single_col__BITNR 24
+#define R_IRQ_MASK0_SET__single_col__WIDTH 1
+#define R_IRQ_MASK0_SET__single_col__set 1
+#define R_IRQ_MASK0_SET__single_col__nop 0
+#define R_IRQ_MASK0_SET__congestion__BITNR 23
+#define R_IRQ_MASK0_SET__congestion__WIDTH 1
+#define R_IRQ_MASK0_SET__congestion__set 1
+#define R_IRQ_MASK0_SET__congestion__nop 0
+#define R_IRQ_MASK0_SET__oversize__BITNR 22
+#define R_IRQ_MASK0_SET__oversize__WIDTH 1
+#define R_IRQ_MASK0_SET__oversize__set 1
+#define R_IRQ_MASK0_SET__oversize__nop 0
+#define R_IRQ_MASK0_SET__alignment_error__BITNR 21
+#define R_IRQ_MASK0_SET__alignment_error__WIDTH 1
+#define R_IRQ_MASK0_SET__alignment_error__set 1
+#define R_IRQ_MASK0_SET__alignment_error__nop 0
+#define R_IRQ_MASK0_SET__crc_error__BITNR 20
+#define R_IRQ_MASK0_SET__crc_error__WIDTH 1
+#define R_IRQ_MASK0_SET__crc_error__set 1
+#define R_IRQ_MASK0_SET__crc_error__nop 0
+#define R_IRQ_MASK0_SET__overrun__BITNR 19
+#define R_IRQ_MASK0_SET__overrun__WIDTH 1
+#define R_IRQ_MASK0_SET__overrun__set 1
+#define R_IRQ_MASK0_SET__overrun__nop 0
+#define R_IRQ_MASK0_SET__underrun__BITNR 18
+#define R_IRQ_MASK0_SET__underrun__WIDTH 1
+#define R_IRQ_MASK0_SET__underrun__set 1
+#define R_IRQ_MASK0_SET__underrun__nop 0
+#define R_IRQ_MASK0_SET__excessive_col__BITNR 17
+#define R_IRQ_MASK0_SET__excessive_col__WIDTH 1
+#define R_IRQ_MASK0_SET__excessive_col__set 1
+#define R_IRQ_MASK0_SET__excessive_col__nop 0
+#define R_IRQ_MASK0_SET__mdio__BITNR 16
+#define R_IRQ_MASK0_SET__mdio__WIDTH 1
+#define R_IRQ_MASK0_SET__mdio__set 1
+#define R_IRQ_MASK0_SET__mdio__nop 0
+#define R_IRQ_MASK0_SET__ata_drq3__BITNR 15
+#define R_IRQ_MASK0_SET__ata_drq3__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq3__set 1
+#define R_IRQ_MASK0_SET__ata_drq3__nop 0
+#define R_IRQ_MASK0_SET__ata_drq2__BITNR 14
+#define R_IRQ_MASK0_SET__ata_drq2__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq2__set 1
+#define R_IRQ_MASK0_SET__ata_drq2__nop 0
+#define R_IRQ_MASK0_SET__ata_drq1__BITNR 13
+#define R_IRQ_MASK0_SET__ata_drq1__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq1__set 1
+#define R_IRQ_MASK0_SET__ata_drq1__nop 0
+#define R_IRQ_MASK0_SET__ata_drq0__BITNR 12
+#define R_IRQ_MASK0_SET__ata_drq0__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_drq0__set 1
+#define R_IRQ_MASK0_SET__ata_drq0__nop 0
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__BITNR 11
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__set 1
+#define R_IRQ_MASK0_SET__par0_ecp_cmd__nop 0
+#define R_IRQ_MASK0_SET__ata_irq3__BITNR 11
+#define R_IRQ_MASK0_SET__ata_irq3__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq3__set 1
+#define R_IRQ_MASK0_SET__ata_irq3__nop 0
+#define R_IRQ_MASK0_SET__par0_peri__BITNR 10
+#define R_IRQ_MASK0_SET__par0_peri__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_peri__set 1
+#define R_IRQ_MASK0_SET__par0_peri__nop 0
+#define R_IRQ_MASK0_SET__ata_irq2__BITNR 10
+#define R_IRQ_MASK0_SET__ata_irq2__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq2__set 1
+#define R_IRQ_MASK0_SET__ata_irq2__nop 0
+#define R_IRQ_MASK0_SET__p21_irq2__BITNR 10
+#define R_IRQ_MASK0_SET__p21_irq2__WIDTH 1
+#define R_IRQ_MASK0_SET__p21_irq2__set 1
+#define R_IRQ_MASK0_SET__p21_irq2__nop 0
+#define R_IRQ_MASK0_SET__par0_data__BITNR 9
+#define R_IRQ_MASK0_SET__par0_data__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_data__set 1
+#define R_IRQ_MASK0_SET__par0_data__nop 0
+#define R_IRQ_MASK0_SET__ata_irq1__BITNR 9
+#define R_IRQ_MASK0_SET__ata_irq1__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq1__set 1
+#define R_IRQ_MASK0_SET__ata_irq1__nop 0
+#define R_IRQ_MASK0_SET__p21_irq1__BITNR 9
+#define R_IRQ_MASK0_SET__p21_irq1__WIDTH 1
+#define R_IRQ_MASK0_SET__p21_irq1__set 1
+#define R_IRQ_MASK0_SET__p21_irq1__nop 0
+#define R_IRQ_MASK0_SET__par0_ready__BITNR 8
+#define R_IRQ_MASK0_SET__par0_ready__WIDTH 1
+#define R_IRQ_MASK0_SET__par0_ready__set 1
+#define R_IRQ_MASK0_SET__par0_ready__nop 0
+#define R_IRQ_MASK0_SET__ata_irq0__BITNR 8
+#define R_IRQ_MASK0_SET__ata_irq0__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_irq0__set 1
+#define R_IRQ_MASK0_SET__ata_irq0__nop 0
+#define R_IRQ_MASK0_SET__mio__BITNR 8
+#define R_IRQ_MASK0_SET__mio__WIDTH 1
+#define R_IRQ_MASK0_SET__mio__set 1
+#define R_IRQ_MASK0_SET__mio__nop 0
+#define R_IRQ_MASK0_SET__scsi0__BITNR 8
+#define R_IRQ_MASK0_SET__scsi0__WIDTH 1
+#define R_IRQ_MASK0_SET__scsi0__set 1
+#define R_IRQ_MASK0_SET__scsi0__nop 0
+#define R_IRQ_MASK0_SET__p21_irq0__BITNR 8
+#define R_IRQ_MASK0_SET__p21_irq0__WIDTH 1
+#define R_IRQ_MASK0_SET__p21_irq0__set 1
+#define R_IRQ_MASK0_SET__p21_irq0__nop 0
+#define R_IRQ_MASK0_SET__ata_dmaend__BITNR 7
+#define R_IRQ_MASK0_SET__ata_dmaend__WIDTH 1
+#define R_IRQ_MASK0_SET__ata_dmaend__set 1
+#define R_IRQ_MASK0_SET__ata_dmaend__nop 0
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__BITNR 5
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__set 1
+#define R_IRQ_MASK0_SET__irq_ext_vector_nr__nop 0
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__BITNR 4
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__WIDTH 1
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__set 1
+#define R_IRQ_MASK0_SET__irq_int_vector_nr__nop 0
+#define R_IRQ_MASK0_SET__ext_dma1__BITNR 3
+#define R_IRQ_MASK0_SET__ext_dma1__WIDTH 1
+#define R_IRQ_MASK0_SET__ext_dma1__set 1
+#define R_IRQ_MASK0_SET__ext_dma1__nop 0
+#define R_IRQ_MASK0_SET__ext_dma0__BITNR 2
+#define R_IRQ_MASK0_SET__ext_dma0__WIDTH 1
+#define R_IRQ_MASK0_SET__ext_dma0__set 1
+#define R_IRQ_MASK0_SET__ext_dma0__nop 0
+#define R_IRQ_MASK0_SET__timer1__BITNR 1
+#define R_IRQ_MASK0_SET__timer1__WIDTH 1
+#define R_IRQ_MASK0_SET__timer1__set 1
+#define R_IRQ_MASK0_SET__timer1__nop 0
+#define R_IRQ_MASK0_SET__timer0__BITNR 0
+#define R_IRQ_MASK0_SET__timer0__WIDTH 1
+#define R_IRQ_MASK0_SET__timer0__set 1
+#define R_IRQ_MASK0_SET__timer0__nop 0
+
+#define R_IRQ_MASK1_RD (IO_TYPECAST_RO_UDWORD 0xb00000c8)
+#define R_IRQ_MASK1_RD__sw_int7__BITNR 31
+#define R_IRQ_MASK1_RD__sw_int7__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int7__active 1
+#define R_IRQ_MASK1_RD__sw_int7__inactive 0
+#define R_IRQ_MASK1_RD__sw_int6__BITNR 30
+#define R_IRQ_MASK1_RD__sw_int6__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int6__active 1
+#define R_IRQ_MASK1_RD__sw_int6__inactive 0
+#define R_IRQ_MASK1_RD__sw_int5__BITNR 29
+#define R_IRQ_MASK1_RD__sw_int5__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int5__active 1
+#define R_IRQ_MASK1_RD__sw_int5__inactive 0
+#define R_IRQ_MASK1_RD__sw_int4__BITNR 28
+#define R_IRQ_MASK1_RD__sw_int4__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int4__active 1
+#define R_IRQ_MASK1_RD__sw_int4__inactive 0
+#define R_IRQ_MASK1_RD__sw_int3__BITNR 27
+#define R_IRQ_MASK1_RD__sw_int3__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int3__active 1
+#define R_IRQ_MASK1_RD__sw_int3__inactive 0
+#define R_IRQ_MASK1_RD__sw_int2__BITNR 26
+#define R_IRQ_MASK1_RD__sw_int2__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int2__active 1
+#define R_IRQ_MASK1_RD__sw_int2__inactive 0
+#define R_IRQ_MASK1_RD__sw_int1__BITNR 25
+#define R_IRQ_MASK1_RD__sw_int1__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int1__active 1
+#define R_IRQ_MASK1_RD__sw_int1__inactive 0
+#define R_IRQ_MASK1_RD__sw_int0__BITNR 24
+#define R_IRQ_MASK1_RD__sw_int0__WIDTH 1
+#define R_IRQ_MASK1_RD__sw_int0__active 1
+#define R_IRQ_MASK1_RD__sw_int0__inactive 0
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__BITNR 19
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__active 1
+#define R_IRQ_MASK1_RD__par1_ecp_cmd__inactive 0
+#define R_IRQ_MASK1_RD__par1_peri__BITNR 18
+#define R_IRQ_MASK1_RD__par1_peri__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_peri__active 1
+#define R_IRQ_MASK1_RD__par1_peri__inactive 0
+#define R_IRQ_MASK1_RD__par1_data__BITNR 17
+#define R_IRQ_MASK1_RD__par1_data__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_data__active 1
+#define R_IRQ_MASK1_RD__par1_data__inactive 0
+#define R_IRQ_MASK1_RD__par1_ready__BITNR 16
+#define R_IRQ_MASK1_RD__par1_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__par1_ready__active 1
+#define R_IRQ_MASK1_RD__par1_ready__inactive 0
+#define R_IRQ_MASK1_RD__scsi1__BITNR 16
+#define R_IRQ_MASK1_RD__scsi1__WIDTH 1
+#define R_IRQ_MASK1_RD__scsi1__active 1
+#define R_IRQ_MASK1_RD__scsi1__inactive 0
+#define R_IRQ_MASK1_RD__ser3_ready__BITNR 15
+#define R_IRQ_MASK1_RD__ser3_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser3_ready__active 1
+#define R_IRQ_MASK1_RD__ser3_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser3_data__BITNR 14
+#define R_IRQ_MASK1_RD__ser3_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser3_data__active 1
+#define R_IRQ_MASK1_RD__ser3_data__inactive 0
+#define R_IRQ_MASK1_RD__ser2_ready__BITNR 13
+#define R_IRQ_MASK1_RD__ser2_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser2_ready__active 1
+#define R_IRQ_MASK1_RD__ser2_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser2_data__BITNR 12
+#define R_IRQ_MASK1_RD__ser2_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser2_data__active 1
+#define R_IRQ_MASK1_RD__ser2_data__inactive 0
+#define R_IRQ_MASK1_RD__ser1_ready__BITNR 11
+#define R_IRQ_MASK1_RD__ser1_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser1_ready__active 1
+#define R_IRQ_MASK1_RD__ser1_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser1_data__BITNR 10
+#define R_IRQ_MASK1_RD__ser1_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser1_data__active 1
+#define R_IRQ_MASK1_RD__ser1_data__inactive 0
+#define R_IRQ_MASK1_RD__ser0_ready__BITNR 9
+#define R_IRQ_MASK1_RD__ser0_ready__WIDTH 1
+#define R_IRQ_MASK1_RD__ser0_ready__active 1
+#define R_IRQ_MASK1_RD__ser0_ready__inactive 0
+#define R_IRQ_MASK1_RD__ser0_data__BITNR 8
+#define R_IRQ_MASK1_RD__ser0_data__WIDTH 1
+#define R_IRQ_MASK1_RD__ser0_data__active 1
+#define R_IRQ_MASK1_RD__ser0_data__inactive 0
+#define R_IRQ_MASK1_RD__pa7__BITNR 7
+#define R_IRQ_MASK1_RD__pa7__WIDTH 1
+#define R_IRQ_MASK1_RD__pa7__active 1
+#define R_IRQ_MASK1_RD__pa7__inactive 0
+#define R_IRQ_MASK1_RD__pa6__BITNR 6
+#define R_IRQ_MASK1_RD__pa6__WIDTH 1
+#define R_IRQ_MASK1_RD__pa6__active 1
+#define R_IRQ_MASK1_RD__pa6__inactive 0
+#define R_IRQ_MASK1_RD__pa5__BITNR 5
+#define R_IRQ_MASK1_RD__pa5__WIDTH 1
+#define R_IRQ_MASK1_RD__pa5__active 1
+#define R_IRQ_MASK1_RD__pa5__inactive 0
+#define R_IRQ_MASK1_RD__pa4__BITNR 4
+#define R_IRQ_MASK1_RD__pa4__WIDTH 1
+#define R_IRQ_MASK1_RD__pa4__active 1
+#define R_IRQ_MASK1_RD__pa4__inactive 0
+#define R_IRQ_MASK1_RD__pa3__BITNR 3
+#define R_IRQ_MASK1_RD__pa3__WIDTH 1
+#define R_IRQ_MASK1_RD__pa3__active 1
+#define R_IRQ_MASK1_RD__pa3__inactive 0
+#define R_IRQ_MASK1_RD__pa2__BITNR 2
+#define R_IRQ_MASK1_RD__pa2__WIDTH 1
+#define R_IRQ_MASK1_RD__pa2__active 1
+#define R_IRQ_MASK1_RD__pa2__inactive 0
+#define R_IRQ_MASK1_RD__pa1__BITNR 1
+#define R_IRQ_MASK1_RD__pa1__WIDTH 1
+#define R_IRQ_MASK1_RD__pa1__active 1
+#define R_IRQ_MASK1_RD__pa1__inactive 0
+#define R_IRQ_MASK1_RD__pa0__BITNR 0
+#define R_IRQ_MASK1_RD__pa0__WIDTH 1
+#define R_IRQ_MASK1_RD__pa0__active 1
+#define R_IRQ_MASK1_RD__pa0__inactive 0
+
+#define R_IRQ_MASK1_CLR (IO_TYPECAST_UDWORD 0xb00000c8)
+#define R_IRQ_MASK1_CLR__sw_int7__BITNR 31
+#define R_IRQ_MASK1_CLR__sw_int7__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int7__clr 1
+#define R_IRQ_MASK1_CLR__sw_int7__nop 0
+#define R_IRQ_MASK1_CLR__sw_int6__BITNR 30
+#define R_IRQ_MASK1_CLR__sw_int6__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int6__clr 1
+#define R_IRQ_MASK1_CLR__sw_int6__nop 0
+#define R_IRQ_MASK1_CLR__sw_int5__BITNR 29
+#define R_IRQ_MASK1_CLR__sw_int5__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int5__clr 1
+#define R_IRQ_MASK1_CLR__sw_int5__nop 0
+#define R_IRQ_MASK1_CLR__sw_int4__BITNR 28
+#define R_IRQ_MASK1_CLR__sw_int4__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int4__clr 1
+#define R_IRQ_MASK1_CLR__sw_int4__nop 0
+#define R_IRQ_MASK1_CLR__sw_int3__BITNR 27
+#define R_IRQ_MASK1_CLR__sw_int3__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int3__clr 1
+#define R_IRQ_MASK1_CLR__sw_int3__nop 0
+#define R_IRQ_MASK1_CLR__sw_int2__BITNR 26
+#define R_IRQ_MASK1_CLR__sw_int2__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int2__clr 1
+#define R_IRQ_MASK1_CLR__sw_int2__nop 0
+#define R_IRQ_MASK1_CLR__sw_int1__BITNR 25
+#define R_IRQ_MASK1_CLR__sw_int1__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int1__clr 1
+#define R_IRQ_MASK1_CLR__sw_int1__nop 0
+#define R_IRQ_MASK1_CLR__sw_int0__BITNR 24
+#define R_IRQ_MASK1_CLR__sw_int0__WIDTH 1
+#define R_IRQ_MASK1_CLR__sw_int0__clr 1
+#define R_IRQ_MASK1_CLR__sw_int0__nop 0
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__BITNR 19
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__clr 1
+#define R_IRQ_MASK1_CLR__par1_ecp_cmd__nop 0
+#define R_IRQ_MASK1_CLR__par1_peri__BITNR 18
+#define R_IRQ_MASK1_CLR__par1_peri__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_peri__clr 1
+#define R_IRQ_MASK1_CLR__par1_peri__nop 0
+#define R_IRQ_MASK1_CLR__par1_data__BITNR 17
+#define R_IRQ_MASK1_CLR__par1_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_data__clr 1
+#define R_IRQ_MASK1_CLR__par1_data__nop 0
+#define R_IRQ_MASK1_CLR__par1_ready__BITNR 16
+#define R_IRQ_MASK1_CLR__par1_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__par1_ready__clr 1
+#define R_IRQ_MASK1_CLR__par1_ready__nop 0
+#define R_IRQ_MASK1_CLR__scsi1__BITNR 16
+#define R_IRQ_MASK1_CLR__scsi1__WIDTH 1
+#define R_IRQ_MASK1_CLR__scsi1__clr 1
+#define R_IRQ_MASK1_CLR__scsi1__nop 0
+#define R_IRQ_MASK1_CLR__ser3_ready__BITNR 15
+#define R_IRQ_MASK1_CLR__ser3_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser3_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser3_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser3_data__BITNR 14
+#define R_IRQ_MASK1_CLR__ser3_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser3_data__clr 1
+#define R_IRQ_MASK1_CLR__ser3_data__nop 0
+#define R_IRQ_MASK1_CLR__ser2_ready__BITNR 13
+#define R_IRQ_MASK1_CLR__ser2_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser2_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser2_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser2_data__BITNR 12
+#define R_IRQ_MASK1_CLR__ser2_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser2_data__clr 1
+#define R_IRQ_MASK1_CLR__ser2_data__nop 0
+#define R_IRQ_MASK1_CLR__ser1_ready__BITNR 11
+#define R_IRQ_MASK1_CLR__ser1_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser1_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser1_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser1_data__BITNR 10
+#define R_IRQ_MASK1_CLR__ser1_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser1_data__clr 1
+#define R_IRQ_MASK1_CLR__ser1_data__nop 0
+#define R_IRQ_MASK1_CLR__ser0_ready__BITNR 9
+#define R_IRQ_MASK1_CLR__ser0_ready__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser0_ready__clr 1
+#define R_IRQ_MASK1_CLR__ser0_ready__nop 0
+#define R_IRQ_MASK1_CLR__ser0_data__BITNR 8
+#define R_IRQ_MASK1_CLR__ser0_data__WIDTH 1
+#define R_IRQ_MASK1_CLR__ser0_data__clr 1
+#define R_IRQ_MASK1_CLR__ser0_data__nop 0
+#define R_IRQ_MASK1_CLR__pa7__BITNR 7
+#define R_IRQ_MASK1_CLR__pa7__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa7__clr 1
+#define R_IRQ_MASK1_CLR__pa7__nop 0
+#define R_IRQ_MASK1_CLR__pa6__BITNR 6
+#define R_IRQ_MASK1_CLR__pa6__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa6__clr 1
+#define R_IRQ_MASK1_CLR__pa6__nop 0
+#define R_IRQ_MASK1_CLR__pa5__BITNR 5
+#define R_IRQ_MASK1_CLR__pa5__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa5__clr 1
+#define R_IRQ_MASK1_CLR__pa5__nop 0
+#define R_IRQ_MASK1_CLR__pa4__BITNR 4
+#define R_IRQ_MASK1_CLR__pa4__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa4__clr 1
+#define R_IRQ_MASK1_CLR__pa4__nop 0
+#define R_IRQ_MASK1_CLR__pa3__BITNR 3
+#define R_IRQ_MASK1_CLR__pa3__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa3__clr 1
+#define R_IRQ_MASK1_CLR__pa3__nop 0
+#define R_IRQ_MASK1_CLR__pa2__BITNR 2
+#define R_IRQ_MASK1_CLR__pa2__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa2__clr 1
+#define R_IRQ_MASK1_CLR__pa2__nop 0
+#define R_IRQ_MASK1_CLR__pa1__BITNR 1
+#define R_IRQ_MASK1_CLR__pa1__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa1__clr 1
+#define R_IRQ_MASK1_CLR__pa1__nop 0
+#define R_IRQ_MASK1_CLR__pa0__BITNR 0
+#define R_IRQ_MASK1_CLR__pa0__WIDTH 1
+#define R_IRQ_MASK1_CLR__pa0__clr 1
+#define R_IRQ_MASK1_CLR__pa0__nop 0
+
+#define R_IRQ_READ1 (IO_TYPECAST_RO_UDWORD 0xb00000cc)
+#define R_IRQ_READ1__sw_int7__BITNR 31
+#define R_IRQ_READ1__sw_int7__WIDTH 1
+#define R_IRQ_READ1__sw_int7__active 1
+#define R_IRQ_READ1__sw_int7__inactive 0
+#define R_IRQ_READ1__sw_int6__BITNR 30
+#define R_IRQ_READ1__sw_int6__WIDTH 1
+#define R_IRQ_READ1__sw_int6__active 1
+#define R_IRQ_READ1__sw_int6__inactive 0
+#define R_IRQ_READ1__sw_int5__BITNR 29
+#define R_IRQ_READ1__sw_int5__WIDTH 1
+#define R_IRQ_READ1__sw_int5__active 1
+#define R_IRQ_READ1__sw_int5__inactive 0
+#define R_IRQ_READ1__sw_int4__BITNR 28
+#define R_IRQ_READ1__sw_int4__WIDTH 1
+#define R_IRQ_READ1__sw_int4__active 1
+#define R_IRQ_READ1__sw_int4__inactive 0
+#define R_IRQ_READ1__sw_int3__BITNR 27
+#define R_IRQ_READ1__sw_int3__WIDTH 1
+#define R_IRQ_READ1__sw_int3__active 1
+#define R_IRQ_READ1__sw_int3__inactive 0
+#define R_IRQ_READ1__sw_int2__BITNR 26
+#define R_IRQ_READ1__sw_int2__WIDTH 1
+#define R_IRQ_READ1__sw_int2__active 1
+#define R_IRQ_READ1__sw_int2__inactive 0
+#define R_IRQ_READ1__sw_int1__BITNR 25
+#define R_IRQ_READ1__sw_int1__WIDTH 1
+#define R_IRQ_READ1__sw_int1__active 1
+#define R_IRQ_READ1__sw_int1__inactive 0
+#define R_IRQ_READ1__sw_int0__BITNR 24
+#define R_IRQ_READ1__sw_int0__WIDTH 1
+#define R_IRQ_READ1__sw_int0__active 1
+#define R_IRQ_READ1__sw_int0__inactive 0
+#define R_IRQ_READ1__par1_ecp_cmd__BITNR 19
+#define R_IRQ_READ1__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_READ1__par1_ecp_cmd__active 1
+#define R_IRQ_READ1__par1_ecp_cmd__inactive 0
+#define R_IRQ_READ1__par1_peri__BITNR 18
+#define R_IRQ_READ1__par1_peri__WIDTH 1
+#define R_IRQ_READ1__par1_peri__active 1
+#define R_IRQ_READ1__par1_peri__inactive 0
+#define R_IRQ_READ1__par1_data__BITNR 17
+#define R_IRQ_READ1__par1_data__WIDTH 1
+#define R_IRQ_READ1__par1_data__active 1
+#define R_IRQ_READ1__par1_data__inactive 0
+#define R_IRQ_READ1__par1_ready__BITNR 16
+#define R_IRQ_READ1__par1_ready__WIDTH 1
+#define R_IRQ_READ1__par1_ready__active 1
+#define R_IRQ_READ1__par1_ready__inactive 0
+#define R_IRQ_READ1__scsi1__BITNR 16
+#define R_IRQ_READ1__scsi1__WIDTH 1
+#define R_IRQ_READ1__scsi1__active 1
+#define R_IRQ_READ1__scsi1__inactive 0
+#define R_IRQ_READ1__ser3_ready__BITNR 15
+#define R_IRQ_READ1__ser3_ready__WIDTH 1
+#define R_IRQ_READ1__ser3_ready__active 1
+#define R_IRQ_READ1__ser3_ready__inactive 0
+#define R_IRQ_READ1__ser3_data__BITNR 14
+#define R_IRQ_READ1__ser3_data__WIDTH 1
+#define R_IRQ_READ1__ser3_data__active 1
+#define R_IRQ_READ1__ser3_data__inactive 0
+#define R_IRQ_READ1__ser2_ready__BITNR 13
+#define R_IRQ_READ1__ser2_ready__WIDTH 1
+#define R_IRQ_READ1__ser2_ready__active 1
+#define R_IRQ_READ1__ser2_ready__inactive 0
+#define R_IRQ_READ1__ser2_data__BITNR 12
+#define R_IRQ_READ1__ser2_data__WIDTH 1
+#define R_IRQ_READ1__ser2_data__active 1
+#define R_IRQ_READ1__ser2_data__inactive 0
+#define R_IRQ_READ1__ser1_ready__BITNR 11
+#define R_IRQ_READ1__ser1_ready__WIDTH 1
+#define R_IRQ_READ1__ser1_ready__active 1
+#define R_IRQ_READ1__ser1_ready__inactive 0
+#define R_IRQ_READ1__ser1_data__BITNR 10
+#define R_IRQ_READ1__ser1_data__WIDTH 1
+#define R_IRQ_READ1__ser1_data__active 1
+#define R_IRQ_READ1__ser1_data__inactive 0
+#define R_IRQ_READ1__ser0_ready__BITNR 9
+#define R_IRQ_READ1__ser0_ready__WIDTH 1
+#define R_IRQ_READ1__ser0_ready__active 1
+#define R_IRQ_READ1__ser0_ready__inactive 0
+#define R_IRQ_READ1__ser0_data__BITNR 8
+#define R_IRQ_READ1__ser0_data__WIDTH 1
+#define R_IRQ_READ1__ser0_data__active 1
+#define R_IRQ_READ1__ser0_data__inactive 0
+#define R_IRQ_READ1__pa7__BITNR 7
+#define R_IRQ_READ1__pa7__WIDTH 1
+#define R_IRQ_READ1__pa7__active 1
+#define R_IRQ_READ1__pa7__inactive 0
+#define R_IRQ_READ1__pa6__BITNR 6
+#define R_IRQ_READ1__pa6__WIDTH 1
+#define R_IRQ_READ1__pa6__active 1
+#define R_IRQ_READ1__pa6__inactive 0
+#define R_IRQ_READ1__pa5__BITNR 5
+#define R_IRQ_READ1__pa5__WIDTH 1
+#define R_IRQ_READ1__pa5__active 1
+#define R_IRQ_READ1__pa5__inactive 0
+#define R_IRQ_READ1__pa4__BITNR 4
+#define R_IRQ_READ1__pa4__WIDTH 1
+#define R_IRQ_READ1__pa4__active 1
+#define R_IRQ_READ1__pa4__inactive 0
+#define R_IRQ_READ1__pa3__BITNR 3
+#define R_IRQ_READ1__pa3__WIDTH 1
+#define R_IRQ_READ1__pa3__active 1
+#define R_IRQ_READ1__pa3__inactive 0
+#define R_IRQ_READ1__pa2__BITNR 2
+#define R_IRQ_READ1__pa2__WIDTH 1
+#define R_IRQ_READ1__pa2__active 1
+#define R_IRQ_READ1__pa2__inactive 0
+#define R_IRQ_READ1__pa1__BITNR 1
+#define R_IRQ_READ1__pa1__WIDTH 1
+#define R_IRQ_READ1__pa1__active 1
+#define R_IRQ_READ1__pa1__inactive 0
+#define R_IRQ_READ1__pa0__BITNR 0
+#define R_IRQ_READ1__pa0__WIDTH 1
+#define R_IRQ_READ1__pa0__active 1
+#define R_IRQ_READ1__pa0__inactive 0
+
+#define R_IRQ_MASK1_SET (IO_TYPECAST_UDWORD 0xb00000cc)
+#define R_IRQ_MASK1_SET__sw_int7__BITNR 31
+#define R_IRQ_MASK1_SET__sw_int7__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int7__set 1
+#define R_IRQ_MASK1_SET__sw_int7__nop 0
+#define R_IRQ_MASK1_SET__sw_int6__BITNR 30
+#define R_IRQ_MASK1_SET__sw_int6__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int6__set 1
+#define R_IRQ_MASK1_SET__sw_int6__nop 0
+#define R_IRQ_MASK1_SET__sw_int5__BITNR 29
+#define R_IRQ_MASK1_SET__sw_int5__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int5__set 1
+#define R_IRQ_MASK1_SET__sw_int5__nop 0
+#define R_IRQ_MASK1_SET__sw_int4__BITNR 28
+#define R_IRQ_MASK1_SET__sw_int4__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int4__set 1
+#define R_IRQ_MASK1_SET__sw_int4__nop 0
+#define R_IRQ_MASK1_SET__sw_int3__BITNR 27
+#define R_IRQ_MASK1_SET__sw_int3__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int3__set 1
+#define R_IRQ_MASK1_SET__sw_int3__nop 0
+#define R_IRQ_MASK1_SET__sw_int2__BITNR 26
+#define R_IRQ_MASK1_SET__sw_int2__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int2__set 1
+#define R_IRQ_MASK1_SET__sw_int2__nop 0
+#define R_IRQ_MASK1_SET__sw_int1__BITNR 25
+#define R_IRQ_MASK1_SET__sw_int1__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int1__set 1
+#define R_IRQ_MASK1_SET__sw_int1__nop 0
+#define R_IRQ_MASK1_SET__sw_int0__BITNR 24
+#define R_IRQ_MASK1_SET__sw_int0__WIDTH 1
+#define R_IRQ_MASK1_SET__sw_int0__set 1
+#define R_IRQ_MASK1_SET__sw_int0__nop 0
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__BITNR 19
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__set 1
+#define R_IRQ_MASK1_SET__par1_ecp_cmd__nop 0
+#define R_IRQ_MASK1_SET__par1_peri__BITNR 18
+#define R_IRQ_MASK1_SET__par1_peri__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_peri__set 1
+#define R_IRQ_MASK1_SET__par1_peri__nop 0
+#define R_IRQ_MASK1_SET__par1_data__BITNR 17
+#define R_IRQ_MASK1_SET__par1_data__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_data__set 1
+#define R_IRQ_MASK1_SET__par1_data__nop 0
+#define R_IRQ_MASK1_SET__par1_ready__BITNR 16
+#define R_IRQ_MASK1_SET__par1_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__par1_ready__set 1
+#define R_IRQ_MASK1_SET__par1_ready__nop 0
+#define R_IRQ_MASK1_SET__scsi1__BITNR 16
+#define R_IRQ_MASK1_SET__scsi1__WIDTH 1
+#define R_IRQ_MASK1_SET__scsi1__set 1
+#define R_IRQ_MASK1_SET__scsi1__nop 0
+#define R_IRQ_MASK1_SET__ser3_ready__BITNR 15
+#define R_IRQ_MASK1_SET__ser3_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser3_ready__set 1
+#define R_IRQ_MASK1_SET__ser3_ready__nop 0
+#define R_IRQ_MASK1_SET__ser3_data__BITNR 14
+#define R_IRQ_MASK1_SET__ser3_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser3_data__set 1
+#define R_IRQ_MASK1_SET__ser3_data__nop 0
+#define R_IRQ_MASK1_SET__ser2_ready__BITNR 13
+#define R_IRQ_MASK1_SET__ser2_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser2_ready__set 1
+#define R_IRQ_MASK1_SET__ser2_ready__nop 0
+#define R_IRQ_MASK1_SET__ser2_data__BITNR 12
+#define R_IRQ_MASK1_SET__ser2_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser2_data__set 1
+#define R_IRQ_MASK1_SET__ser2_data__nop 0
+#define R_IRQ_MASK1_SET__ser1_ready__BITNR 11
+#define R_IRQ_MASK1_SET__ser1_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser1_ready__set 1
+#define R_IRQ_MASK1_SET__ser1_ready__nop 0
+#define R_IRQ_MASK1_SET__ser1_data__BITNR 10
+#define R_IRQ_MASK1_SET__ser1_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser1_data__set 1
+#define R_IRQ_MASK1_SET__ser1_data__nop 0
+#define R_IRQ_MASK1_SET__ser0_ready__BITNR 9
+#define R_IRQ_MASK1_SET__ser0_ready__WIDTH 1
+#define R_IRQ_MASK1_SET__ser0_ready__set 1
+#define R_IRQ_MASK1_SET__ser0_ready__nop 0
+#define R_IRQ_MASK1_SET__ser0_data__BITNR 8
+#define R_IRQ_MASK1_SET__ser0_data__WIDTH 1
+#define R_IRQ_MASK1_SET__ser0_data__set 1
+#define R_IRQ_MASK1_SET__ser0_data__nop 0
+#define R_IRQ_MASK1_SET__pa7__BITNR 7
+#define R_IRQ_MASK1_SET__pa7__WIDTH 1
+#define R_IRQ_MASK1_SET__pa7__set 1
+#define R_IRQ_MASK1_SET__pa7__nop 0
+#define R_IRQ_MASK1_SET__pa6__BITNR 6
+#define R_IRQ_MASK1_SET__pa6__WIDTH 1
+#define R_IRQ_MASK1_SET__pa6__set 1
+#define R_IRQ_MASK1_SET__pa6__nop 0
+#define R_IRQ_MASK1_SET__pa5__BITNR 5
+#define R_IRQ_MASK1_SET__pa5__WIDTH 1
+#define R_IRQ_MASK1_SET__pa5__set 1
+#define R_IRQ_MASK1_SET__pa5__nop 0
+#define R_IRQ_MASK1_SET__pa4__BITNR 4
+#define R_IRQ_MASK1_SET__pa4__WIDTH 1
+#define R_IRQ_MASK1_SET__pa4__set 1
+#define R_IRQ_MASK1_SET__pa4__nop 0
+#define R_IRQ_MASK1_SET__pa3__BITNR 3
+#define R_IRQ_MASK1_SET__pa3__WIDTH 1
+#define R_IRQ_MASK1_SET__pa3__set 1
+#define R_IRQ_MASK1_SET__pa3__nop 0
+#define R_IRQ_MASK1_SET__pa2__BITNR 2
+#define R_IRQ_MASK1_SET__pa2__WIDTH 1
+#define R_IRQ_MASK1_SET__pa2__set 1
+#define R_IRQ_MASK1_SET__pa2__nop 0
+#define R_IRQ_MASK1_SET__pa1__BITNR 1
+#define R_IRQ_MASK1_SET__pa1__WIDTH 1
+#define R_IRQ_MASK1_SET__pa1__set 1
+#define R_IRQ_MASK1_SET__pa1__nop 0
+#define R_IRQ_MASK1_SET__pa0__BITNR 0
+#define R_IRQ_MASK1_SET__pa0__WIDTH 1
+#define R_IRQ_MASK1_SET__pa0__set 1
+#define R_IRQ_MASK1_SET__pa0__nop 0
+
+#define R_IRQ_MASK2_RD (IO_TYPECAST_RO_UDWORD 0xb00000d0)
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__BITNR 23
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub3_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__BITNR 22
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub2_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__BITNR 21
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub1_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__BITNR 20
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_sub0_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma9_eop__BITNR 19
+#define R_IRQ_MASK2_RD__dma9_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma9_eop__active 1
+#define R_IRQ_MASK2_RD__dma9_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma9_descr__BITNR 18
+#define R_IRQ_MASK2_RD__dma9_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma9_descr__active 1
+#define R_IRQ_MASK2_RD__dma9_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma8_eop__BITNR 17
+#define R_IRQ_MASK2_RD__dma8_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_eop__active 1
+#define R_IRQ_MASK2_RD__dma8_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma8_descr__BITNR 16
+#define R_IRQ_MASK2_RD__dma8_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma8_descr__active 1
+#define R_IRQ_MASK2_RD__dma8_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma7_eop__BITNR 15
+#define R_IRQ_MASK2_RD__dma7_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma7_eop__active 1
+#define R_IRQ_MASK2_RD__dma7_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma7_descr__BITNR 14
+#define R_IRQ_MASK2_RD__dma7_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma7_descr__active 1
+#define R_IRQ_MASK2_RD__dma7_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma6_eop__BITNR 13
+#define R_IRQ_MASK2_RD__dma6_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma6_eop__active 1
+#define R_IRQ_MASK2_RD__dma6_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma6_descr__BITNR 12
+#define R_IRQ_MASK2_RD__dma6_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma6_descr__active 1
+#define R_IRQ_MASK2_RD__dma6_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma5_eop__BITNR 11
+#define R_IRQ_MASK2_RD__dma5_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma5_eop__active 1
+#define R_IRQ_MASK2_RD__dma5_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma5_descr__BITNR 10
+#define R_IRQ_MASK2_RD__dma5_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma5_descr__active 1
+#define R_IRQ_MASK2_RD__dma5_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma4_eop__BITNR 9
+#define R_IRQ_MASK2_RD__dma4_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma4_eop__active 1
+#define R_IRQ_MASK2_RD__dma4_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma4_descr__BITNR 8
+#define R_IRQ_MASK2_RD__dma4_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma4_descr__active 1
+#define R_IRQ_MASK2_RD__dma4_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma3_eop__BITNR 7
+#define R_IRQ_MASK2_RD__dma3_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma3_eop__active 1
+#define R_IRQ_MASK2_RD__dma3_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma3_descr__BITNR 6
+#define R_IRQ_MASK2_RD__dma3_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma3_descr__active 1
+#define R_IRQ_MASK2_RD__dma3_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma2_eop__BITNR 5
+#define R_IRQ_MASK2_RD__dma2_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma2_eop__active 1
+#define R_IRQ_MASK2_RD__dma2_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma2_descr__BITNR 4
+#define R_IRQ_MASK2_RD__dma2_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma2_descr__active 1
+#define R_IRQ_MASK2_RD__dma2_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma1_eop__BITNR 3
+#define R_IRQ_MASK2_RD__dma1_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma1_eop__active 1
+#define R_IRQ_MASK2_RD__dma1_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma1_descr__BITNR 2
+#define R_IRQ_MASK2_RD__dma1_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma1_descr__active 1
+#define R_IRQ_MASK2_RD__dma1_descr__inactive 0
+#define R_IRQ_MASK2_RD__dma0_eop__BITNR 1
+#define R_IRQ_MASK2_RD__dma0_eop__WIDTH 1
+#define R_IRQ_MASK2_RD__dma0_eop__active 1
+#define R_IRQ_MASK2_RD__dma0_eop__inactive 0
+#define R_IRQ_MASK2_RD__dma0_descr__BITNR 0
+#define R_IRQ_MASK2_RD__dma0_descr__WIDTH 1
+#define R_IRQ_MASK2_RD__dma0_descr__active 1
+#define R_IRQ_MASK2_RD__dma0_descr__inactive 0
+
+#define R_IRQ_MASK2_CLR (IO_TYPECAST_UDWORD 0xb00000d0)
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__BITNR 23
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub3_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__BITNR 22
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub2_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__BITNR 21
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub1_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__BITNR 20
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_sub0_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma9_eop__BITNR 19
+#define R_IRQ_MASK2_CLR__dma9_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma9_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma9_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma9_descr__BITNR 18
+#define R_IRQ_MASK2_CLR__dma9_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma9_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma9_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma8_eop__BITNR 17
+#define R_IRQ_MASK2_CLR__dma8_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma8_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma8_descr__BITNR 16
+#define R_IRQ_MASK2_CLR__dma8_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma8_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma8_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma7_eop__BITNR 15
+#define R_IRQ_MASK2_CLR__dma7_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma7_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma7_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma7_descr__BITNR 14
+#define R_IRQ_MASK2_CLR__dma7_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma7_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma7_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma6_eop__BITNR 13
+#define R_IRQ_MASK2_CLR__dma6_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma6_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma6_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma6_descr__BITNR 12
+#define R_IRQ_MASK2_CLR__dma6_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma6_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma6_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma5_eop__BITNR 11
+#define R_IRQ_MASK2_CLR__dma5_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma5_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma5_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma5_descr__BITNR 10
+#define R_IRQ_MASK2_CLR__dma5_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma5_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma5_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma4_eop__BITNR 9
+#define R_IRQ_MASK2_CLR__dma4_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma4_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma4_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma4_descr__BITNR 8
+#define R_IRQ_MASK2_CLR__dma4_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma4_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma4_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma3_eop__BITNR 7
+#define R_IRQ_MASK2_CLR__dma3_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma3_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma3_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma3_descr__BITNR 6
+#define R_IRQ_MASK2_CLR__dma3_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma3_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma3_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma2_eop__BITNR 5
+#define R_IRQ_MASK2_CLR__dma2_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma2_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma2_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma2_descr__BITNR 4
+#define R_IRQ_MASK2_CLR__dma2_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma2_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma2_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma1_eop__BITNR 3
+#define R_IRQ_MASK2_CLR__dma1_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma1_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma1_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma1_descr__BITNR 2
+#define R_IRQ_MASK2_CLR__dma1_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma1_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma1_descr__nop 0
+#define R_IRQ_MASK2_CLR__dma0_eop__BITNR 1
+#define R_IRQ_MASK2_CLR__dma0_eop__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma0_eop__clr 1
+#define R_IRQ_MASK2_CLR__dma0_eop__nop 0
+#define R_IRQ_MASK2_CLR__dma0_descr__BITNR 0
+#define R_IRQ_MASK2_CLR__dma0_descr__WIDTH 1
+#define R_IRQ_MASK2_CLR__dma0_descr__clr 1
+#define R_IRQ_MASK2_CLR__dma0_descr__nop 0
+
+#define R_IRQ_READ2 (IO_TYPECAST_RO_UDWORD 0xb00000d4)
+#define R_IRQ_READ2__dma8_sub3_descr__BITNR 23
+#define R_IRQ_READ2__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub3_descr__active 1
+#define R_IRQ_READ2__dma8_sub3_descr__inactive 0
+#define R_IRQ_READ2__dma8_sub2_descr__BITNR 22
+#define R_IRQ_READ2__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub2_descr__active 1
+#define R_IRQ_READ2__dma8_sub2_descr__inactive 0
+#define R_IRQ_READ2__dma8_sub1_descr__BITNR 21
+#define R_IRQ_READ2__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub1_descr__active 1
+#define R_IRQ_READ2__dma8_sub1_descr__inactive 0
+#define R_IRQ_READ2__dma8_sub0_descr__BITNR 20
+#define R_IRQ_READ2__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_sub0_descr__active 1
+#define R_IRQ_READ2__dma8_sub0_descr__inactive 0
+#define R_IRQ_READ2__dma9_eop__BITNR 19
+#define R_IRQ_READ2__dma9_eop__WIDTH 1
+#define R_IRQ_READ2__dma9_eop__active 1
+#define R_IRQ_READ2__dma9_eop__inactive 0
+#define R_IRQ_READ2__dma9_descr__BITNR 18
+#define R_IRQ_READ2__dma9_descr__WIDTH 1
+#define R_IRQ_READ2__dma9_descr__active 1
+#define R_IRQ_READ2__dma9_descr__inactive 0
+#define R_IRQ_READ2__dma8_eop__BITNR 17
+#define R_IRQ_READ2__dma8_eop__WIDTH 1
+#define R_IRQ_READ2__dma8_eop__active 1
+#define R_IRQ_READ2__dma8_eop__inactive 0
+#define R_IRQ_READ2__dma8_descr__BITNR 16
+#define R_IRQ_READ2__dma8_descr__WIDTH 1
+#define R_IRQ_READ2__dma8_descr__active 1
+#define R_IRQ_READ2__dma8_descr__inactive 0
+#define R_IRQ_READ2__dma7_eop__BITNR 15
+#define R_IRQ_READ2__dma7_eop__WIDTH 1
+#define R_IRQ_READ2__dma7_eop__active 1
+#define R_IRQ_READ2__dma7_eop__inactive 0
+#define R_IRQ_READ2__dma7_descr__BITNR 14
+#define R_IRQ_READ2__dma7_descr__WIDTH 1
+#define R_IRQ_READ2__dma7_descr__active 1
+#define R_IRQ_READ2__dma7_descr__inactive 0
+#define R_IRQ_READ2__dma6_eop__BITNR 13
+#define R_IRQ_READ2__dma6_eop__WIDTH 1
+#define R_IRQ_READ2__dma6_eop__active 1
+#define R_IRQ_READ2__dma6_eop__inactive 0
+#define R_IRQ_READ2__dma6_descr__BITNR 12
+#define R_IRQ_READ2__dma6_descr__WIDTH 1
+#define R_IRQ_READ2__dma6_descr__active 1
+#define R_IRQ_READ2__dma6_descr__inactive 0
+#define R_IRQ_READ2__dma5_eop__BITNR 11
+#define R_IRQ_READ2__dma5_eop__WIDTH 1
+#define R_IRQ_READ2__dma5_eop__active 1
+#define R_IRQ_READ2__dma5_eop__inactive 0
+#define R_IRQ_READ2__dma5_descr__BITNR 10
+#define R_IRQ_READ2__dma5_descr__WIDTH 1
+#define R_IRQ_READ2__dma5_descr__active 1
+#define R_IRQ_READ2__dma5_descr__inactive 0
+#define R_IRQ_READ2__dma4_eop__BITNR 9
+#define R_IRQ_READ2__dma4_eop__WIDTH 1
+#define R_IRQ_READ2__dma4_eop__active 1
+#define R_IRQ_READ2__dma4_eop__inactive 0
+#define R_IRQ_READ2__dma4_descr__BITNR 8
+#define R_IRQ_READ2__dma4_descr__WIDTH 1
+#define R_IRQ_READ2__dma4_descr__active 1
+#define R_IRQ_READ2__dma4_descr__inactive 0
+#define R_IRQ_READ2__dma3_eop__BITNR 7
+#define R_IRQ_READ2__dma3_eop__WIDTH 1
+#define R_IRQ_READ2__dma3_eop__active 1
+#define R_IRQ_READ2__dma3_eop__inactive 0
+#define R_IRQ_READ2__dma3_descr__BITNR 6
+#define R_IRQ_READ2__dma3_descr__WIDTH 1
+#define R_IRQ_READ2__dma3_descr__active 1
+#define R_IRQ_READ2__dma3_descr__inactive 0
+#define R_IRQ_READ2__dma2_eop__BITNR 5
+#define R_IRQ_READ2__dma2_eop__WIDTH 1
+#define R_IRQ_READ2__dma2_eop__active 1
+#define R_IRQ_READ2__dma2_eop__inactive 0
+#define R_IRQ_READ2__dma2_descr__BITNR 4
+#define R_IRQ_READ2__dma2_descr__WIDTH 1
+#define R_IRQ_READ2__dma2_descr__active 1
+#define R_IRQ_READ2__dma2_descr__inactive 0
+#define R_IRQ_READ2__dma1_eop__BITNR 3
+#define R_IRQ_READ2__dma1_eop__WIDTH 1
+#define R_IRQ_READ2__dma1_eop__active 1
+#define R_IRQ_READ2__dma1_eop__inactive 0
+#define R_IRQ_READ2__dma1_descr__BITNR 2
+#define R_IRQ_READ2__dma1_descr__WIDTH 1
+#define R_IRQ_READ2__dma1_descr__active 1
+#define R_IRQ_READ2__dma1_descr__inactive 0
+#define R_IRQ_READ2__dma0_eop__BITNR 1
+#define R_IRQ_READ2__dma0_eop__WIDTH 1
+#define R_IRQ_READ2__dma0_eop__active 1
+#define R_IRQ_READ2__dma0_eop__inactive 0
+#define R_IRQ_READ2__dma0_descr__BITNR 0
+#define R_IRQ_READ2__dma0_descr__WIDTH 1
+#define R_IRQ_READ2__dma0_descr__active 1
+#define R_IRQ_READ2__dma0_descr__inactive 0
+
+#define R_IRQ_MASK2_SET (IO_TYPECAST_UDWORD 0xb00000d4)
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__BITNR 23
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub3_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__BITNR 22
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub2_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__BITNR 21
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub1_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__BITNR 20
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_sub0_descr__nop 0
+#define R_IRQ_MASK2_SET__dma9_eop__BITNR 19
+#define R_IRQ_MASK2_SET__dma9_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma9_eop__set 1
+#define R_IRQ_MASK2_SET__dma9_eop__nop 0
+#define R_IRQ_MASK2_SET__dma9_descr__BITNR 18
+#define R_IRQ_MASK2_SET__dma9_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma9_descr__set 1
+#define R_IRQ_MASK2_SET__dma9_descr__nop 0
+#define R_IRQ_MASK2_SET__dma8_eop__BITNR 17
+#define R_IRQ_MASK2_SET__dma8_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_eop__set 1
+#define R_IRQ_MASK2_SET__dma8_eop__nop 0
+#define R_IRQ_MASK2_SET__dma8_descr__BITNR 16
+#define R_IRQ_MASK2_SET__dma8_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma8_descr__set 1
+#define R_IRQ_MASK2_SET__dma8_descr__nop 0
+#define R_IRQ_MASK2_SET__dma7_eop__BITNR 15
+#define R_IRQ_MASK2_SET__dma7_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma7_eop__set 1
+#define R_IRQ_MASK2_SET__dma7_eop__nop 0
+#define R_IRQ_MASK2_SET__dma7_descr__BITNR 14
+#define R_IRQ_MASK2_SET__dma7_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma7_descr__set 1
+#define R_IRQ_MASK2_SET__dma7_descr__nop 0
+#define R_IRQ_MASK2_SET__dma6_eop__BITNR 13
+#define R_IRQ_MASK2_SET__dma6_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma6_eop__set 1
+#define R_IRQ_MASK2_SET__dma6_eop__nop 0
+#define R_IRQ_MASK2_SET__dma6_descr__BITNR 12
+#define R_IRQ_MASK2_SET__dma6_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma6_descr__set 1
+#define R_IRQ_MASK2_SET__dma6_descr__nop 0
+#define R_IRQ_MASK2_SET__dma5_eop__BITNR 11
+#define R_IRQ_MASK2_SET__dma5_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma5_eop__set 1
+#define R_IRQ_MASK2_SET__dma5_eop__nop 0
+#define R_IRQ_MASK2_SET__dma5_descr__BITNR 10
+#define R_IRQ_MASK2_SET__dma5_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma5_descr__set 1
+#define R_IRQ_MASK2_SET__dma5_descr__nop 0
+#define R_IRQ_MASK2_SET__dma4_eop__BITNR 9
+#define R_IRQ_MASK2_SET__dma4_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma4_eop__set 1
+#define R_IRQ_MASK2_SET__dma4_eop__nop 0
+#define R_IRQ_MASK2_SET__dma4_descr__BITNR 8
+#define R_IRQ_MASK2_SET__dma4_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma4_descr__set 1
+#define R_IRQ_MASK2_SET__dma4_descr__nop 0
+#define R_IRQ_MASK2_SET__dma3_eop__BITNR 7
+#define R_IRQ_MASK2_SET__dma3_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma3_eop__set 1
+#define R_IRQ_MASK2_SET__dma3_eop__nop 0
+#define R_IRQ_MASK2_SET__dma3_descr__BITNR 6
+#define R_IRQ_MASK2_SET__dma3_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma3_descr__set 1
+#define R_IRQ_MASK2_SET__dma3_descr__nop 0
+#define R_IRQ_MASK2_SET__dma2_eop__BITNR 5
+#define R_IRQ_MASK2_SET__dma2_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma2_eop__set 1
+#define R_IRQ_MASK2_SET__dma2_eop__nop 0
+#define R_IRQ_MASK2_SET__dma2_descr__BITNR 4
+#define R_IRQ_MASK2_SET__dma2_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma2_descr__set 1
+#define R_IRQ_MASK2_SET__dma2_descr__nop 0
+#define R_IRQ_MASK2_SET__dma1_eop__BITNR 3
+#define R_IRQ_MASK2_SET__dma1_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma1_eop__set 1
+#define R_IRQ_MASK2_SET__dma1_eop__nop 0
+#define R_IRQ_MASK2_SET__dma1_descr__BITNR 2
+#define R_IRQ_MASK2_SET__dma1_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma1_descr__set 1
+#define R_IRQ_MASK2_SET__dma1_descr__nop 0
+#define R_IRQ_MASK2_SET__dma0_eop__BITNR 1
+#define R_IRQ_MASK2_SET__dma0_eop__WIDTH 1
+#define R_IRQ_MASK2_SET__dma0_eop__set 1
+#define R_IRQ_MASK2_SET__dma0_eop__nop 0
+#define R_IRQ_MASK2_SET__dma0_descr__BITNR 0
+#define R_IRQ_MASK2_SET__dma0_descr__WIDTH 1
+#define R_IRQ_MASK2_SET__dma0_descr__set 1
+#define R_IRQ_MASK2_SET__dma0_descr__nop 0
+
+#define R_VECT_MASK_RD (IO_TYPECAST_RO_UDWORD 0xb00000d8)
+#define R_VECT_MASK_RD__usb__BITNR 31
+#define R_VECT_MASK_RD__usb__WIDTH 1
+#define R_VECT_MASK_RD__usb__active 1
+#define R_VECT_MASK_RD__usb__inactive 0
+#define R_VECT_MASK_RD__dma9__BITNR 25
+#define R_VECT_MASK_RD__dma9__WIDTH 1
+#define R_VECT_MASK_RD__dma9__active 1
+#define R_VECT_MASK_RD__dma9__inactive 0
+#define R_VECT_MASK_RD__dma8__BITNR 24
+#define R_VECT_MASK_RD__dma8__WIDTH 1
+#define R_VECT_MASK_RD__dma8__active 1
+#define R_VECT_MASK_RD__dma8__inactive 0
+#define R_VECT_MASK_RD__dma7__BITNR 23
+#define R_VECT_MASK_RD__dma7__WIDTH 1
+#define R_VECT_MASK_RD__dma7__active 1
+#define R_VECT_MASK_RD__dma7__inactive 0
+#define R_VECT_MASK_RD__dma6__BITNR 22
+#define R_VECT_MASK_RD__dma6__WIDTH 1
+#define R_VECT_MASK_RD__dma6__active 1
+#define R_VECT_MASK_RD__dma6__inactive 0
+#define R_VECT_MASK_RD__dma5__BITNR 21
+#define R_VECT_MASK_RD__dma5__WIDTH 1
+#define R_VECT_MASK_RD__dma5__active 1
+#define R_VECT_MASK_RD__dma5__inactive 0
+#define R_VECT_MASK_RD__dma4__BITNR 20
+#define R_VECT_MASK_RD__dma4__WIDTH 1
+#define R_VECT_MASK_RD__dma4__active 1
+#define R_VECT_MASK_RD__dma4__inactive 0
+#define R_VECT_MASK_RD__dma3__BITNR 19
+#define R_VECT_MASK_RD__dma3__WIDTH 1
+#define R_VECT_MASK_RD__dma3__active 1
+#define R_VECT_MASK_RD__dma3__inactive 0
+#define R_VECT_MASK_RD__dma2__BITNR 18
+#define R_VECT_MASK_RD__dma2__WIDTH 1
+#define R_VECT_MASK_RD__dma2__active 1
+#define R_VECT_MASK_RD__dma2__inactive 0
+#define R_VECT_MASK_RD__dma1__BITNR 17
+#define R_VECT_MASK_RD__dma1__WIDTH 1
+#define R_VECT_MASK_RD__dma1__active 1
+#define R_VECT_MASK_RD__dma1__inactive 0
+#define R_VECT_MASK_RD__dma0__BITNR 16
+#define R_VECT_MASK_RD__dma0__WIDTH 1
+#define R_VECT_MASK_RD__dma0__active 1
+#define R_VECT_MASK_RD__dma0__inactive 0
+#define R_VECT_MASK_RD__ext_dma1__BITNR 13
+#define R_VECT_MASK_RD__ext_dma1__WIDTH 1
+#define R_VECT_MASK_RD__ext_dma1__active 1
+#define R_VECT_MASK_RD__ext_dma1__inactive 0
+#define R_VECT_MASK_RD__ext_dma0__BITNR 12
+#define R_VECT_MASK_RD__ext_dma0__WIDTH 1
+#define R_VECT_MASK_RD__ext_dma0__active 1
+#define R_VECT_MASK_RD__ext_dma0__inactive 0
+#define R_VECT_MASK_RD__pa__BITNR 11
+#define R_VECT_MASK_RD__pa__WIDTH 1
+#define R_VECT_MASK_RD__pa__active 1
+#define R_VECT_MASK_RD__pa__inactive 0
+#define R_VECT_MASK_RD__irq_intnr__BITNR 10
+#define R_VECT_MASK_RD__irq_intnr__WIDTH 1
+#define R_VECT_MASK_RD__irq_intnr__active 1
+#define R_VECT_MASK_RD__irq_intnr__inactive 0
+#define R_VECT_MASK_RD__sw__BITNR 9
+#define R_VECT_MASK_RD__sw__WIDTH 1
+#define R_VECT_MASK_RD__sw__active 1
+#define R_VECT_MASK_RD__sw__inactive 0
+#define R_VECT_MASK_RD__serial__BITNR 8
+#define R_VECT_MASK_RD__serial__WIDTH 1
+#define R_VECT_MASK_RD__serial__active 1
+#define R_VECT_MASK_RD__serial__inactive 0
+#define R_VECT_MASK_RD__snmp__BITNR 7
+#define R_VECT_MASK_RD__snmp__WIDTH 1
+#define R_VECT_MASK_RD__snmp__active 1
+#define R_VECT_MASK_RD__snmp__inactive 0
+#define R_VECT_MASK_RD__network__BITNR 6
+#define R_VECT_MASK_RD__network__WIDTH 1
+#define R_VECT_MASK_RD__network__active 1
+#define R_VECT_MASK_RD__network__inactive 0
+#define R_VECT_MASK_RD__scsi1__BITNR 5
+#define R_VECT_MASK_RD__scsi1__WIDTH 1
+#define R_VECT_MASK_RD__scsi1__active 1
+#define R_VECT_MASK_RD__scsi1__inactive 0
+#define R_VECT_MASK_RD__par1__BITNR 5
+#define R_VECT_MASK_RD__par1__WIDTH 1
+#define R_VECT_MASK_RD__par1__active 1
+#define R_VECT_MASK_RD__par1__inactive 0
+#define R_VECT_MASK_RD__scsi0__BITNR 4
+#define R_VECT_MASK_RD__scsi0__WIDTH 1
+#define R_VECT_MASK_RD__scsi0__active 1
+#define R_VECT_MASK_RD__scsi0__inactive 0
+#define R_VECT_MASK_RD__par0__BITNR 4
+#define R_VECT_MASK_RD__par0__WIDTH 1
+#define R_VECT_MASK_RD__par0__active 1
+#define R_VECT_MASK_RD__par0__inactive 0
+#define R_VECT_MASK_RD__ata__BITNR 4
+#define R_VECT_MASK_RD__ata__WIDTH 1
+#define R_VECT_MASK_RD__ata__active 1
+#define R_VECT_MASK_RD__ata__inactive 0
+#define R_VECT_MASK_RD__mio__BITNR 4
+#define R_VECT_MASK_RD__mio__WIDTH 1
+#define R_VECT_MASK_RD__mio__active 1
+#define R_VECT_MASK_RD__mio__inactive 0
+#define R_VECT_MASK_RD__p21__BITNR 4
+#define R_VECT_MASK_RD__p21__WIDTH 1
+#define R_VECT_MASK_RD__p21__active 1
+#define R_VECT_MASK_RD__p21__inactive 0
+#define R_VECT_MASK_RD__timer1__BITNR 3
+#define R_VECT_MASK_RD__timer1__WIDTH 1
+#define R_VECT_MASK_RD__timer1__active 1
+#define R_VECT_MASK_RD__timer1__inactive 0
+#define R_VECT_MASK_RD__timer0__BITNR 2
+#define R_VECT_MASK_RD__timer0__WIDTH 1
+#define R_VECT_MASK_RD__timer0__active 1
+#define R_VECT_MASK_RD__timer0__inactive 0
+#define R_VECT_MASK_RD__nmi__BITNR 1
+#define R_VECT_MASK_RD__nmi__WIDTH 1
+#define R_VECT_MASK_RD__nmi__active 1
+#define R_VECT_MASK_RD__nmi__inactive 0
+#define R_VECT_MASK_RD__some__BITNR 0
+#define R_VECT_MASK_RD__some__WIDTH 1
+#define R_VECT_MASK_RD__some__active 1
+#define R_VECT_MASK_RD__some__inactive 0
+
+#define R_VECT_MASK_CLR (IO_TYPECAST_UDWORD 0xb00000d8)
+#define R_VECT_MASK_CLR__usb__BITNR 31
+#define R_VECT_MASK_CLR__usb__WIDTH 1
+#define R_VECT_MASK_CLR__usb__clr 1
+#define R_VECT_MASK_CLR__usb__nop 0
+#define R_VECT_MASK_CLR__dma9__BITNR 25
+#define R_VECT_MASK_CLR__dma9__WIDTH 1
+#define R_VECT_MASK_CLR__dma9__clr 1
+#define R_VECT_MASK_CLR__dma9__nop 0
+#define R_VECT_MASK_CLR__dma8__BITNR 24
+#define R_VECT_MASK_CLR__dma8__WIDTH 1
+#define R_VECT_MASK_CLR__dma8__clr 1
+#define R_VECT_MASK_CLR__dma8__nop 0
+#define R_VECT_MASK_CLR__dma7__BITNR 23
+#define R_VECT_MASK_CLR__dma7__WIDTH 1
+#define R_VECT_MASK_CLR__dma7__clr 1
+#define R_VECT_MASK_CLR__dma7__nop 0
+#define R_VECT_MASK_CLR__dma6__BITNR 22
+#define R_VECT_MASK_CLR__dma6__WIDTH 1
+#define R_VECT_MASK_CLR__dma6__clr 1
+#define R_VECT_MASK_CLR__dma6__nop 0
+#define R_VECT_MASK_CLR__dma5__BITNR 21
+#define R_VECT_MASK_CLR__dma5__WIDTH 1
+#define R_VECT_MASK_CLR__dma5__clr 1
+#define R_VECT_MASK_CLR__dma5__nop 0
+#define R_VECT_MASK_CLR__dma4__BITNR 20
+#define R_VECT_MASK_CLR__dma4__WIDTH 1
+#define R_VECT_MASK_CLR__dma4__clr 1
+#define R_VECT_MASK_CLR__dma4__nop 0
+#define R_VECT_MASK_CLR__dma3__BITNR 19
+#define R_VECT_MASK_CLR__dma3__WIDTH 1
+#define R_VECT_MASK_CLR__dma3__clr 1
+#define R_VECT_MASK_CLR__dma3__nop 0
+#define R_VECT_MASK_CLR__dma2__BITNR 18
+#define R_VECT_MASK_CLR__dma2__WIDTH 1
+#define R_VECT_MASK_CLR__dma2__clr 1
+#define R_VECT_MASK_CLR__dma2__nop 0
+#define R_VECT_MASK_CLR__dma1__BITNR 17
+#define R_VECT_MASK_CLR__dma1__WIDTH 1
+#define R_VECT_MASK_CLR__dma1__clr 1
+#define R_VECT_MASK_CLR__dma1__nop 0
+#define R_VECT_MASK_CLR__dma0__BITNR 16
+#define R_VECT_MASK_CLR__dma0__WIDTH 1
+#define R_VECT_MASK_CLR__dma0__clr 1
+#define R_VECT_MASK_CLR__dma0__nop 0
+#define R_VECT_MASK_CLR__ext_dma1__BITNR 13
+#define R_VECT_MASK_CLR__ext_dma1__WIDTH 1
+#define R_VECT_MASK_CLR__ext_dma1__clr 1
+#define R_VECT_MASK_CLR__ext_dma1__nop 0
+#define R_VECT_MASK_CLR__ext_dma0__BITNR 12
+#define R_VECT_MASK_CLR__ext_dma0__WIDTH 1
+#define R_VECT_MASK_CLR__ext_dma0__clr 1
+#define R_VECT_MASK_CLR__ext_dma0__nop 0
+#define R_VECT_MASK_CLR__pa__BITNR 11
+#define R_VECT_MASK_CLR__pa__WIDTH 1
+#define R_VECT_MASK_CLR__pa__clr 1
+#define R_VECT_MASK_CLR__pa__nop 0
+#define R_VECT_MASK_CLR__irq_intnr__BITNR 10
+#define R_VECT_MASK_CLR__irq_intnr__WIDTH 1
+#define R_VECT_MASK_CLR__irq_intnr__clr 1
+#define R_VECT_MASK_CLR__irq_intnr__nop 0
+#define R_VECT_MASK_CLR__sw__BITNR 9
+#define R_VECT_MASK_CLR__sw__WIDTH 1
+#define R_VECT_MASK_CLR__sw__clr 1
+#define R_VECT_MASK_CLR__sw__nop 0
+#define R_VECT_MASK_CLR__serial__BITNR 8
+#define R_VECT_MASK_CLR__serial__WIDTH 1
+#define R_VECT_MASK_CLR__serial__clr 1
+#define R_VECT_MASK_CLR__serial__nop 0
+#define R_VECT_MASK_CLR__snmp__BITNR 7
+#define R_VECT_MASK_CLR__snmp__WIDTH 1
+#define R_VECT_MASK_CLR__snmp__clr 1
+#define R_VECT_MASK_CLR__snmp__nop 0
+#define R_VECT_MASK_CLR__network__BITNR 6
+#define R_VECT_MASK_CLR__network__WIDTH 1
+#define R_VECT_MASK_CLR__network__clr 1
+#define R_VECT_MASK_CLR__network__nop 0
+#define R_VECT_MASK_CLR__scsi1__BITNR 5
+#define R_VECT_MASK_CLR__scsi1__WIDTH 1
+#define R_VECT_MASK_CLR__scsi1__clr 1
+#define R_VECT_MASK_CLR__scsi1__nop 0
+#define R_VECT_MASK_CLR__par1__BITNR 5
+#define R_VECT_MASK_CLR__par1__WIDTH 1
+#define R_VECT_MASK_CLR__par1__clr 1
+#define R_VECT_MASK_CLR__par1__nop 0
+#define R_VECT_MASK_CLR__scsi0__BITNR 4
+#define R_VECT_MASK_CLR__scsi0__WIDTH 1
+#define R_VECT_MASK_CLR__scsi0__clr 1
+#define R_VECT_MASK_CLR__scsi0__nop 0
+#define R_VECT_MASK_CLR__par0__BITNR 4
+#define R_VECT_MASK_CLR__par0__WIDTH 1
+#define R_VECT_MASK_CLR__par0__clr 1
+#define R_VECT_MASK_CLR__par0__nop 0
+#define R_VECT_MASK_CLR__ata__BITNR 4
+#define R_VECT_MASK_CLR__ata__WIDTH 1
+#define R_VECT_MASK_CLR__ata__clr 1
+#define R_VECT_MASK_CLR__ata__nop 0
+#define R_VECT_MASK_CLR__mio__BITNR 4
+#define R_VECT_MASK_CLR__mio__WIDTH 1
+#define R_VECT_MASK_CLR__mio__clr 1
+#define R_VECT_MASK_CLR__mio__nop 0
+#define R_VECT_MASK_CLR__p21__BITNR 4
+#define R_VECT_MASK_CLR__p21__WIDTH 1
+#define R_VECT_MASK_CLR__p21__clr 1
+#define R_VECT_MASK_CLR__p21__nop 0
+#define R_VECT_MASK_CLR__timer1__BITNR 3
+#define R_VECT_MASK_CLR__timer1__WIDTH 1
+#define R_VECT_MASK_CLR__timer1__clr 1
+#define R_VECT_MASK_CLR__timer1__nop 0
+#define R_VECT_MASK_CLR__timer0__BITNR 2
+#define R_VECT_MASK_CLR__timer0__WIDTH 1
+#define R_VECT_MASK_CLR__timer0__clr 1
+#define R_VECT_MASK_CLR__timer0__nop 0
+#define R_VECT_MASK_CLR__nmi__BITNR 1
+#define R_VECT_MASK_CLR__nmi__WIDTH 1
+#define R_VECT_MASK_CLR__nmi__clr 1
+#define R_VECT_MASK_CLR__nmi__nop 0
+#define R_VECT_MASK_CLR__some__BITNR 0
+#define R_VECT_MASK_CLR__some__WIDTH 1
+#define R_VECT_MASK_CLR__some__clr 1
+#define R_VECT_MASK_CLR__some__nop 0
+
+#define R_VECT_READ (IO_TYPECAST_RO_UDWORD 0xb00000dc)
+#define R_VECT_READ__usb__BITNR 31
+#define R_VECT_READ__usb__WIDTH 1
+#define R_VECT_READ__usb__active 1
+#define R_VECT_READ__usb__inactive 0
+#define R_VECT_READ__dma9__BITNR 25
+#define R_VECT_READ__dma9__WIDTH 1
+#define R_VECT_READ__dma9__active 1
+#define R_VECT_READ__dma9__inactive 0
+#define R_VECT_READ__dma8__BITNR 24
+#define R_VECT_READ__dma8__WIDTH 1
+#define R_VECT_READ__dma8__active 1
+#define R_VECT_READ__dma8__inactive 0
+#define R_VECT_READ__dma7__BITNR 23
+#define R_VECT_READ__dma7__WIDTH 1
+#define R_VECT_READ__dma7__active 1
+#define R_VECT_READ__dma7__inactive 0
+#define R_VECT_READ__dma6__BITNR 22
+#define R_VECT_READ__dma6__WIDTH 1
+#define R_VECT_READ__dma6__active 1
+#define R_VECT_READ__dma6__inactive 0
+#define R_VECT_READ__dma5__BITNR 21
+#define R_VECT_READ__dma5__WIDTH 1
+#define R_VECT_READ__dma5__active 1
+#define R_VECT_READ__dma5__inactive 0
+#define R_VECT_READ__dma4__BITNR 20
+#define R_VECT_READ__dma4__WIDTH 1
+#define R_VECT_READ__dma4__active 1
+#define R_VECT_READ__dma4__inactive 0
+#define R_VECT_READ__dma3__BITNR 19
+#define R_VECT_READ__dma3__WIDTH 1
+#define R_VECT_READ__dma3__active 1
+#define R_VECT_READ__dma3__inactive 0
+#define R_VECT_READ__dma2__BITNR 18
+#define R_VECT_READ__dma2__WIDTH 1
+#define R_VECT_READ__dma2__active 1
+#define R_VECT_READ__dma2__inactive 0
+#define R_VECT_READ__dma1__BITNR 17
+#define R_VECT_READ__dma1__WIDTH 1
+#define R_VECT_READ__dma1__active 1
+#define R_VECT_READ__dma1__inactive 0
+#define R_VECT_READ__dma0__BITNR 16
+#define R_VECT_READ__dma0__WIDTH 1
+#define R_VECT_READ__dma0__active 1
+#define R_VECT_READ__dma0__inactive 0
+#define R_VECT_READ__ext_dma1__BITNR 13
+#define R_VECT_READ__ext_dma1__WIDTH 1
+#define R_VECT_READ__ext_dma1__active 1
+#define R_VECT_READ__ext_dma1__inactive 0
+#define R_VECT_READ__ext_dma0__BITNR 12
+#define R_VECT_READ__ext_dma0__WIDTH 1
+#define R_VECT_READ__ext_dma0__active 1
+#define R_VECT_READ__ext_dma0__inactive 0
+#define R_VECT_READ__pa__BITNR 11
+#define R_VECT_READ__pa__WIDTH 1
+#define R_VECT_READ__pa__active 1
+#define R_VECT_READ__pa__inactive 0
+#define R_VECT_READ__irq_intnr__BITNR 10
+#define R_VECT_READ__irq_intnr__WIDTH 1
+#define R_VECT_READ__irq_intnr__active 1
+#define R_VECT_READ__irq_intnr__inactive 0
+#define R_VECT_READ__sw__BITNR 9
+#define R_VECT_READ__sw__WIDTH 1
+#define R_VECT_READ__sw__active 1
+#define R_VECT_READ__sw__inactive 0
+#define R_VECT_READ__serial__BITNR 8
+#define R_VECT_READ__serial__WIDTH 1
+#define R_VECT_READ__serial__active 1
+#define R_VECT_READ__serial__inactive 0
+#define R_VECT_READ__snmp__BITNR 7
+#define R_VECT_READ__snmp__WIDTH 1
+#define R_VECT_READ__snmp__active 1
+#define R_VECT_READ__snmp__inactive 0
+#define R_VECT_READ__network__BITNR 6
+#define R_VECT_READ__network__WIDTH 1
+#define R_VECT_READ__network__active 1
+#define R_VECT_READ__network__inactive 0
+#define R_VECT_READ__scsi1__BITNR 5
+#define R_VECT_READ__scsi1__WIDTH 1
+#define R_VECT_READ__scsi1__active 1
+#define R_VECT_READ__scsi1__inactive 0
+#define R_VECT_READ__par1__BITNR 5
+#define R_VECT_READ__par1__WIDTH 1
+#define R_VECT_READ__par1__active 1
+#define R_VECT_READ__par1__inactive 0
+#define R_VECT_READ__scsi0__BITNR 4
+#define R_VECT_READ__scsi0__WIDTH 1
+#define R_VECT_READ__scsi0__active 1
+#define R_VECT_READ__scsi0__inactive 0
+#define R_VECT_READ__par0__BITNR 4
+#define R_VECT_READ__par0__WIDTH 1
+#define R_VECT_READ__par0__active 1
+#define R_VECT_READ__par0__inactive 0
+#define R_VECT_READ__ata__BITNR 4
+#define R_VECT_READ__ata__WIDTH 1
+#define R_VECT_READ__ata__active 1
+#define R_VECT_READ__ata__inactive 0
+#define R_VECT_READ__mio__BITNR 4
+#define R_VECT_READ__mio__WIDTH 1
+#define R_VECT_READ__mio__active 1
+#define R_VECT_READ__mio__inactive 0
+#define R_VECT_READ__p21__BITNR 4
+#define R_VECT_READ__p21__WIDTH 1
+#define R_VECT_READ__p21__active 1
+#define R_VECT_READ__p21__inactive 0
+#define R_VECT_READ__timer1__BITNR 3
+#define R_VECT_READ__timer1__WIDTH 1
+#define R_VECT_READ__timer1__active 1
+#define R_VECT_READ__timer1__inactive 0
+#define R_VECT_READ__timer0__BITNR 2
+#define R_VECT_READ__timer0__WIDTH 1
+#define R_VECT_READ__timer0__active 1
+#define R_VECT_READ__timer0__inactive 0
+#define R_VECT_READ__nmi__BITNR 1
+#define R_VECT_READ__nmi__WIDTH 1
+#define R_VECT_READ__nmi__active 1
+#define R_VECT_READ__nmi__inactive 0
+#define R_VECT_READ__some__BITNR 0
+#define R_VECT_READ__some__WIDTH 1
+#define R_VECT_READ__some__active 1
+#define R_VECT_READ__some__inactive 0
+
+#define R_VECT_MASK_SET (IO_TYPECAST_UDWORD 0xb00000dc)
+#define R_VECT_MASK_SET__usb__BITNR 31
+#define R_VECT_MASK_SET__usb__WIDTH 1
+#define R_VECT_MASK_SET__usb__set 1
+#define R_VECT_MASK_SET__usb__nop 0
+#define R_VECT_MASK_SET__dma9__BITNR 25
+#define R_VECT_MASK_SET__dma9__WIDTH 1
+#define R_VECT_MASK_SET__dma9__set 1
+#define R_VECT_MASK_SET__dma9__nop 0
+#define R_VECT_MASK_SET__dma8__BITNR 24
+#define R_VECT_MASK_SET__dma8__WIDTH 1
+#define R_VECT_MASK_SET__dma8__set 1
+#define R_VECT_MASK_SET__dma8__nop 0
+#define R_VECT_MASK_SET__dma7__BITNR 23
+#define R_VECT_MASK_SET__dma7__WIDTH 1
+#define R_VECT_MASK_SET__dma7__set 1
+#define R_VECT_MASK_SET__dma7__nop 0
+#define R_VECT_MASK_SET__dma6__BITNR 22
+#define R_VECT_MASK_SET__dma6__WIDTH 1
+#define R_VECT_MASK_SET__dma6__set 1
+#define R_VECT_MASK_SET__dma6__nop 0
+#define R_VECT_MASK_SET__dma5__BITNR 21
+#define R_VECT_MASK_SET__dma5__WIDTH 1
+#define R_VECT_MASK_SET__dma5__set 1
+#define R_VECT_MASK_SET__dma5__nop 0
+#define R_VECT_MASK_SET__dma4__BITNR 20
+#define R_VECT_MASK_SET__dma4__WIDTH 1
+#define R_VECT_MASK_SET__dma4__set 1
+#define R_VECT_MASK_SET__dma4__nop 0
+#define R_VECT_MASK_SET__dma3__BITNR 19
+#define R_VECT_MASK_SET__dma3__WIDTH 1
+#define R_VECT_MASK_SET__dma3__set 1
+#define R_VECT_MASK_SET__dma3__nop 0
+#define R_VECT_MASK_SET__dma2__BITNR 18
+#define R_VECT_MASK_SET__dma2__WIDTH 1
+#define R_VECT_MASK_SET__dma2__set 1
+#define R_VECT_MASK_SET__dma2__nop 0
+#define R_VECT_MASK_SET__dma1__BITNR 17
+#define R_VECT_MASK_SET__dma1__WIDTH 1
+#define R_VECT_MASK_SET__dma1__set 1
+#define R_VECT_MASK_SET__dma1__nop 0
+#define R_VECT_MASK_SET__dma0__BITNR 16
+#define R_VECT_MASK_SET__dma0__WIDTH 1
+#define R_VECT_MASK_SET__dma0__set 1
+#define R_VECT_MASK_SET__dma0__nop 0
+#define R_VECT_MASK_SET__ext_dma1__BITNR 13
+#define R_VECT_MASK_SET__ext_dma1__WIDTH 1
+#define R_VECT_MASK_SET__ext_dma1__set 1
+#define R_VECT_MASK_SET__ext_dma1__nop 0
+#define R_VECT_MASK_SET__ext_dma0__BITNR 12
+#define R_VECT_MASK_SET__ext_dma0__WIDTH 1
+#define R_VECT_MASK_SET__ext_dma0__set 1
+#define R_VECT_MASK_SET__ext_dma0__nop 0
+#define R_VECT_MASK_SET__pa__BITNR 11
+#define R_VECT_MASK_SET__pa__WIDTH 1
+#define R_VECT_MASK_SET__pa__set 1
+#define R_VECT_MASK_SET__pa__nop 0
+#define R_VECT_MASK_SET__irq_intnr__BITNR 10
+#define R_VECT_MASK_SET__irq_intnr__WIDTH 1
+#define R_VECT_MASK_SET__irq_intnr__set 1
+#define R_VECT_MASK_SET__irq_intnr__nop 0
+#define R_VECT_MASK_SET__sw__BITNR 9
+#define R_VECT_MASK_SET__sw__WIDTH 1
+#define R_VECT_MASK_SET__sw__set 1
+#define R_VECT_MASK_SET__sw__nop 0
+#define R_VECT_MASK_SET__serial__BITNR 8
+#define R_VECT_MASK_SET__serial__WIDTH 1
+#define R_VECT_MASK_SET__serial__set 1
+#define R_VECT_MASK_SET__serial__nop 0
+#define R_VECT_MASK_SET__snmp__BITNR 7
+#define R_VECT_MASK_SET__snmp__WIDTH 1
+#define R_VECT_MASK_SET__snmp__set 1
+#define R_VECT_MASK_SET__snmp__nop 0
+#define R_VECT_MASK_SET__network__BITNR 6
+#define R_VECT_MASK_SET__network__WIDTH 1
+#define R_VECT_MASK_SET__network__set 1
+#define R_VECT_MASK_SET__network__nop 0
+#define R_VECT_MASK_SET__scsi1__BITNR 5
+#define R_VECT_MASK_SET__scsi1__WIDTH 1
+#define R_VECT_MASK_SET__scsi1__set 1
+#define R_VECT_MASK_SET__scsi1__nop 0
+#define R_VECT_MASK_SET__par1__BITNR 5
+#define R_VECT_MASK_SET__par1__WIDTH 1
+#define R_VECT_MASK_SET__par1__set 1
+#define R_VECT_MASK_SET__par1__nop 0
+#define R_VECT_MASK_SET__scsi0__BITNR 4
+#define R_VECT_MASK_SET__scsi0__WIDTH 1
+#define R_VECT_MASK_SET__scsi0__set 1
+#define R_VECT_MASK_SET__scsi0__nop 0
+#define R_VECT_MASK_SET__par0__BITNR 4
+#define R_VECT_MASK_SET__par0__WIDTH 1
+#define R_VECT_MASK_SET__par0__set 1
+#define R_VECT_MASK_SET__par0__nop 0
+#define R_VECT_MASK_SET__ata__BITNR 4
+#define R_VECT_MASK_SET__ata__WIDTH 1
+#define R_VECT_MASK_SET__ata__set 1
+#define R_VECT_MASK_SET__ata__nop 0
+#define R_VECT_MASK_SET__mio__BITNR 4
+#define R_VECT_MASK_SET__mio__WIDTH 1
+#define R_VECT_MASK_SET__mio__set 1
+#define R_VECT_MASK_SET__mio__nop 0
+#define R_VECT_MASK_SET__p21__BITNR 4
+#define R_VECT_MASK_SET__p21__WIDTH 1
+#define R_VECT_MASK_SET__p21__set 1
+#define R_VECT_MASK_SET__p21__nop 0
+#define R_VECT_MASK_SET__timer1__BITNR 3
+#define R_VECT_MASK_SET__timer1__WIDTH 1
+#define R_VECT_MASK_SET__timer1__set 1
+#define R_VECT_MASK_SET__timer1__nop 0
+#define R_VECT_MASK_SET__timer0__BITNR 2
+#define R_VECT_MASK_SET__timer0__WIDTH 1
+#define R_VECT_MASK_SET__timer0__set 1
+#define R_VECT_MASK_SET__timer0__nop 0
+#define R_VECT_MASK_SET__nmi__BITNR 1
+#define R_VECT_MASK_SET__nmi__WIDTH 1
+#define R_VECT_MASK_SET__nmi__set 1
+#define R_VECT_MASK_SET__nmi__nop 0
+#define R_VECT_MASK_SET__some__BITNR 0
+#define R_VECT_MASK_SET__some__WIDTH 1
+#define R_VECT_MASK_SET__some__set 1
+#define R_VECT_MASK_SET__some__nop 0
+
+/*
+!* DMA registers
+!*/
+
+#define R_SET_EOP (IO_TYPECAST_UDWORD 0xb000003c)
+#define R_SET_EOP__ch9_eop__BITNR 3
+#define R_SET_EOP__ch9_eop__WIDTH 1
+#define R_SET_EOP__ch9_eop__set 1
+#define R_SET_EOP__ch9_eop__nop 0
+#define R_SET_EOP__ch7_eop__BITNR 2
+#define R_SET_EOP__ch7_eop__WIDTH 1
+#define R_SET_EOP__ch7_eop__set 1
+#define R_SET_EOP__ch7_eop__nop 0
+#define R_SET_EOP__ch5_eop__BITNR 1
+#define R_SET_EOP__ch5_eop__WIDTH 1
+#define R_SET_EOP__ch5_eop__set 1
+#define R_SET_EOP__ch5_eop__nop 0
+#define R_SET_EOP__ch3_eop__BITNR 0
+#define R_SET_EOP__ch3_eop__WIDTH 1
+#define R_SET_EOP__ch3_eop__set 1
+#define R_SET_EOP__ch3_eop__nop 0
+
+#define R_DMA_CH0_HWSW (IO_TYPECAST_UDWORD 0xb0000100)
+#define R_DMA_CH0_HWSW__hw__BITNR 16
+#define R_DMA_CH0_HWSW__hw__WIDTH 16
+#define R_DMA_CH0_HWSW__sw__BITNR 0
+#define R_DMA_CH0_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH0_DESCR (IO_TYPECAST_UDWORD 0xb000010c)
+#define R_DMA_CH0_DESCR__descr__BITNR 0
+#define R_DMA_CH0_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH0_NEXT (IO_TYPECAST_UDWORD 0xb0000104)
+#define R_DMA_CH0_NEXT__next__BITNR 0
+#define R_DMA_CH0_NEXT__next__WIDTH 32
+
+#define R_DMA_CH0_BUF (IO_TYPECAST_UDWORD 0xb0000108)
+#define R_DMA_CH0_BUF__buf__BITNR 0
+#define R_DMA_CH0_BUF__buf__WIDTH 32
+
+#define R_DMA_CH0_FIRST (IO_TYPECAST_UDWORD 0xb00001a0)
+#define R_DMA_CH0_FIRST__first__BITNR 0
+#define R_DMA_CH0_FIRST__first__WIDTH 32
+
+#define R_DMA_CH0_CMD (IO_TYPECAST_BYTE 0xb00001d0)
+#define R_DMA_CH0_CMD__cmd__BITNR 0
+#define R_DMA_CH0_CMD__cmd__WIDTH 3
+#define R_DMA_CH0_CMD__cmd__hold 0
+#define R_DMA_CH0_CMD__cmd__start 1
+#define R_DMA_CH0_CMD__cmd__restart 3
+#define R_DMA_CH0_CMD__cmd__continue 3
+#define R_DMA_CH0_CMD__cmd__reset 4
+
+#define R_DMA_CH0_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d1)
+#define R_DMA_CH0_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH0_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH0_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH0_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH0_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH0_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH0_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH0_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH0_STATUS (IO_TYPECAST_RO_BYTE 0xb00001d2)
+#define R_DMA_CH0_STATUS__avail__BITNR 0
+#define R_DMA_CH0_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH1_HWSW (IO_TYPECAST_UDWORD 0xb0000110)
+#define R_DMA_CH1_HWSW__hw__BITNR 16
+#define R_DMA_CH1_HWSW__hw__WIDTH 16
+#define R_DMA_CH1_HWSW__sw__BITNR 0
+#define R_DMA_CH1_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH1_DESCR (IO_TYPECAST_UDWORD 0xb000011c)
+#define R_DMA_CH1_DESCR__descr__BITNR 0
+#define R_DMA_CH1_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH1_NEXT (IO_TYPECAST_UDWORD 0xb0000114)
+#define R_DMA_CH1_NEXT__next__BITNR 0
+#define R_DMA_CH1_NEXT__next__WIDTH 32
+
+#define R_DMA_CH1_BUF (IO_TYPECAST_UDWORD 0xb0000118)
+#define R_DMA_CH1_BUF__buf__BITNR 0
+#define R_DMA_CH1_BUF__buf__WIDTH 32
+
+#define R_DMA_CH1_FIRST (IO_TYPECAST_UDWORD 0xb00001a4)
+#define R_DMA_CH1_FIRST__first__BITNR 0
+#define R_DMA_CH1_FIRST__first__WIDTH 32
+
+#define R_DMA_CH1_CMD (IO_TYPECAST_BYTE 0xb00001d4)
+#define R_DMA_CH1_CMD__cmd__BITNR 0
+#define R_DMA_CH1_CMD__cmd__WIDTH 3
+#define R_DMA_CH1_CMD__cmd__hold 0
+#define R_DMA_CH1_CMD__cmd__start 1
+#define R_DMA_CH1_CMD__cmd__restart 3
+#define R_DMA_CH1_CMD__cmd__continue 3
+#define R_DMA_CH1_CMD__cmd__reset 4
+
+#define R_DMA_CH1_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d5)
+#define R_DMA_CH1_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH1_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH1_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH1_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH1_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH1_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH1_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH1_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH1_STATUS (IO_TYPECAST_RO_BYTE 0xb00001d6)
+#define R_DMA_CH1_STATUS__avail__BITNR 0
+#define R_DMA_CH1_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH2_HWSW (IO_TYPECAST_UDWORD 0xb0000120)
+#define R_DMA_CH2_HWSW__hw__BITNR 16
+#define R_DMA_CH2_HWSW__hw__WIDTH 16
+#define R_DMA_CH2_HWSW__sw__BITNR 0
+#define R_DMA_CH2_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH2_DESCR (IO_TYPECAST_UDWORD 0xb000012c)
+#define R_DMA_CH2_DESCR__descr__BITNR 0
+#define R_DMA_CH2_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH2_NEXT (IO_TYPECAST_UDWORD 0xb0000124)
+#define R_DMA_CH2_NEXT__next__BITNR 0
+#define R_DMA_CH2_NEXT__next__WIDTH 32
+
+#define R_DMA_CH2_BUF (IO_TYPECAST_UDWORD 0xb0000128)
+#define R_DMA_CH2_BUF__buf__BITNR 0
+#define R_DMA_CH2_BUF__buf__WIDTH 32
+
+#define R_DMA_CH2_FIRST (IO_TYPECAST_UDWORD 0xb00001a8)
+#define R_DMA_CH2_FIRST__first__BITNR 0
+#define R_DMA_CH2_FIRST__first__WIDTH 32
+
+#define R_DMA_CH2_CMD (IO_TYPECAST_BYTE 0xb00001d8)
+#define R_DMA_CH2_CMD__cmd__BITNR 0
+#define R_DMA_CH2_CMD__cmd__WIDTH 3
+#define R_DMA_CH2_CMD__cmd__hold 0
+#define R_DMA_CH2_CMD__cmd__start 1
+#define R_DMA_CH2_CMD__cmd__restart 3
+#define R_DMA_CH2_CMD__cmd__continue 3
+#define R_DMA_CH2_CMD__cmd__reset 4
+
+#define R_DMA_CH2_CLR_INTR (IO_TYPECAST_BYTE 0xb00001d9)
+#define R_DMA_CH2_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH2_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH2_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH2_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH2_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH2_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH2_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH2_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH2_STATUS (IO_TYPECAST_RO_BYTE 0xb00001da)
+#define R_DMA_CH2_STATUS__avail__BITNR 0
+#define R_DMA_CH2_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH3_HWSW (IO_TYPECAST_UDWORD 0xb0000130)
+#define R_DMA_CH3_HWSW__hw__BITNR 16
+#define R_DMA_CH3_HWSW__hw__WIDTH 16
+#define R_DMA_CH3_HWSW__sw__BITNR 0
+#define R_DMA_CH3_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH3_DESCR (IO_TYPECAST_UDWORD 0xb000013c)
+#define R_DMA_CH3_DESCR__descr__BITNR 0
+#define R_DMA_CH3_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH3_NEXT (IO_TYPECAST_UDWORD 0xb0000134)
+#define R_DMA_CH3_NEXT__next__BITNR 0
+#define R_DMA_CH3_NEXT__next__WIDTH 32
+
+#define R_DMA_CH3_BUF (IO_TYPECAST_UDWORD 0xb0000138)
+#define R_DMA_CH3_BUF__buf__BITNR 0
+#define R_DMA_CH3_BUF__buf__WIDTH 32
+
+#define R_DMA_CH3_FIRST (IO_TYPECAST_UDWORD 0xb00001ac)
+#define R_DMA_CH3_FIRST__first__BITNR 0
+#define R_DMA_CH3_FIRST__first__WIDTH 32
+
+#define R_DMA_CH3_CMD (IO_TYPECAST_BYTE 0xb00001dc)
+#define R_DMA_CH3_CMD__cmd__BITNR 0
+#define R_DMA_CH3_CMD__cmd__WIDTH 3
+#define R_DMA_CH3_CMD__cmd__hold 0
+#define R_DMA_CH3_CMD__cmd__start 1
+#define R_DMA_CH3_CMD__cmd__restart 3
+#define R_DMA_CH3_CMD__cmd__continue 3
+#define R_DMA_CH3_CMD__cmd__reset 4
+
+#define R_DMA_CH3_CLR_INTR (IO_TYPECAST_BYTE 0xb00001dd)
+#define R_DMA_CH3_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH3_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH3_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH3_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH3_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH3_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH3_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH3_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH3_STATUS (IO_TYPECAST_RO_BYTE 0xb00001de)
+#define R_DMA_CH3_STATUS__avail__BITNR 0
+#define R_DMA_CH3_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH4_HWSW (IO_TYPECAST_UDWORD 0xb0000140)
+#define R_DMA_CH4_HWSW__hw__BITNR 16
+#define R_DMA_CH4_HWSW__hw__WIDTH 16
+#define R_DMA_CH4_HWSW__sw__BITNR 0
+#define R_DMA_CH4_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH4_DESCR (IO_TYPECAST_UDWORD 0xb000014c)
+#define R_DMA_CH4_DESCR__descr__BITNR 0
+#define R_DMA_CH4_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH4_NEXT (IO_TYPECAST_UDWORD 0xb0000144)
+#define R_DMA_CH4_NEXT__next__BITNR 0
+#define R_DMA_CH4_NEXT__next__WIDTH 32
+
+#define R_DMA_CH4_BUF (IO_TYPECAST_UDWORD 0xb0000148)
+#define R_DMA_CH4_BUF__buf__BITNR 0
+#define R_DMA_CH4_BUF__buf__WIDTH 32
+
+#define R_DMA_CH4_FIRST (IO_TYPECAST_UDWORD 0xb00001b0)
+#define R_DMA_CH4_FIRST__first__BITNR 0
+#define R_DMA_CH4_FIRST__first__WIDTH 32
+
+#define R_DMA_CH4_CMD (IO_TYPECAST_BYTE 0xb00001e0)
+#define R_DMA_CH4_CMD__cmd__BITNR 0
+#define R_DMA_CH4_CMD__cmd__WIDTH 3
+#define R_DMA_CH4_CMD__cmd__hold 0
+#define R_DMA_CH4_CMD__cmd__start 1
+#define R_DMA_CH4_CMD__cmd__restart 3
+#define R_DMA_CH4_CMD__cmd__continue 3
+#define R_DMA_CH4_CMD__cmd__reset 4
+
+#define R_DMA_CH4_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e1)
+#define R_DMA_CH4_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH4_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH4_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH4_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH4_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH4_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH4_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH4_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH4_STATUS (IO_TYPECAST_RO_BYTE 0xb00001e2)
+#define R_DMA_CH4_STATUS__avail__BITNR 0
+#define R_DMA_CH4_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH5_HWSW (IO_TYPECAST_UDWORD 0xb0000150)
+#define R_DMA_CH5_HWSW__hw__BITNR 16
+#define R_DMA_CH5_HWSW__hw__WIDTH 16
+#define R_DMA_CH5_HWSW__sw__BITNR 0
+#define R_DMA_CH5_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH5_DESCR (IO_TYPECAST_UDWORD 0xb000015c)
+#define R_DMA_CH5_DESCR__descr__BITNR 0
+#define R_DMA_CH5_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH5_NEXT (IO_TYPECAST_UDWORD 0xb0000154)
+#define R_DMA_CH5_NEXT__next__BITNR 0
+#define R_DMA_CH5_NEXT__next__WIDTH 32
+
+#define R_DMA_CH5_BUF (IO_TYPECAST_UDWORD 0xb0000158)
+#define R_DMA_CH5_BUF__buf__BITNR 0
+#define R_DMA_CH5_BUF__buf__WIDTH 32
+
+#define R_DMA_CH5_FIRST (IO_TYPECAST_UDWORD 0xb00001b4)
+#define R_DMA_CH5_FIRST__first__BITNR 0
+#define R_DMA_CH5_FIRST__first__WIDTH 32
+
+#define R_DMA_CH5_CMD (IO_TYPECAST_BYTE 0xb00001e4)
+#define R_DMA_CH5_CMD__cmd__BITNR 0
+#define R_DMA_CH5_CMD__cmd__WIDTH 3
+#define R_DMA_CH5_CMD__cmd__hold 0
+#define R_DMA_CH5_CMD__cmd__start 1
+#define R_DMA_CH5_CMD__cmd__restart 3
+#define R_DMA_CH5_CMD__cmd__continue 3
+#define R_DMA_CH5_CMD__cmd__reset 4
+
+#define R_DMA_CH5_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e5)
+#define R_DMA_CH5_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH5_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH5_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH5_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH5_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH5_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH5_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH5_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH5_STATUS (IO_TYPECAST_RO_BYTE 0xb00001e6)
+#define R_DMA_CH5_STATUS__avail__BITNR 0
+#define R_DMA_CH5_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH6_HWSW (IO_TYPECAST_UDWORD 0xb0000160)
+#define R_DMA_CH6_HWSW__hw__BITNR 16
+#define R_DMA_CH6_HWSW__hw__WIDTH 16
+#define R_DMA_CH6_HWSW__sw__BITNR 0
+#define R_DMA_CH6_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH6_DESCR (IO_TYPECAST_UDWORD 0xb000016c)
+#define R_DMA_CH6_DESCR__descr__BITNR 0
+#define R_DMA_CH6_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH6_NEXT (IO_TYPECAST_UDWORD 0xb0000164)
+#define R_DMA_CH6_NEXT__next__BITNR 0
+#define R_DMA_CH6_NEXT__next__WIDTH 32
+
+#define R_DMA_CH6_BUF (IO_TYPECAST_UDWORD 0xb0000168)
+#define R_DMA_CH6_BUF__buf__BITNR 0
+#define R_DMA_CH6_BUF__buf__WIDTH 32
+
+#define R_DMA_CH6_FIRST (IO_TYPECAST_UDWORD 0xb00001b8)
+#define R_DMA_CH6_FIRST__first__BITNR 0
+#define R_DMA_CH6_FIRST__first__WIDTH 32
+
+#define R_DMA_CH6_CMD (IO_TYPECAST_BYTE 0xb00001e8)
+#define R_DMA_CH6_CMD__cmd__BITNR 0
+#define R_DMA_CH6_CMD__cmd__WIDTH 3
+#define R_DMA_CH6_CMD__cmd__hold 0
+#define R_DMA_CH6_CMD__cmd__start 1
+#define R_DMA_CH6_CMD__cmd__restart 3
+#define R_DMA_CH6_CMD__cmd__continue 3
+#define R_DMA_CH6_CMD__cmd__reset 4
+
+#define R_DMA_CH6_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e9)
+#define R_DMA_CH6_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH6_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH6_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH6_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH6_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH6_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH6_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH6_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH6_STATUS (IO_TYPECAST_RO_BYTE 0xb00001ea)
+#define R_DMA_CH6_STATUS__avail__BITNR 0
+#define R_DMA_CH6_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH7_HWSW (IO_TYPECAST_UDWORD 0xb0000170)
+#define R_DMA_CH7_HWSW__hw__BITNR 16
+#define R_DMA_CH7_HWSW__hw__WIDTH 16
+#define R_DMA_CH7_HWSW__sw__BITNR 0
+#define R_DMA_CH7_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH7_DESCR (IO_TYPECAST_UDWORD 0xb000017c)
+#define R_DMA_CH7_DESCR__descr__BITNR 0
+#define R_DMA_CH7_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH7_NEXT (IO_TYPECAST_UDWORD 0xb0000174)
+#define R_DMA_CH7_NEXT__next__BITNR 0
+#define R_DMA_CH7_NEXT__next__WIDTH 32
+
+#define R_DMA_CH7_BUF (IO_TYPECAST_UDWORD 0xb0000178)
+#define R_DMA_CH7_BUF__buf__BITNR 0
+#define R_DMA_CH7_BUF__buf__WIDTH 32
+
+#define R_DMA_CH7_FIRST (IO_TYPECAST_UDWORD 0xb00001bc)
+#define R_DMA_CH7_FIRST__first__BITNR 0
+#define R_DMA_CH7_FIRST__first__WIDTH 32
+
+#define R_DMA_CH7_CMD (IO_TYPECAST_BYTE 0xb00001ec)
+#define R_DMA_CH7_CMD__cmd__BITNR 0
+#define R_DMA_CH7_CMD__cmd__WIDTH 3
+#define R_DMA_CH7_CMD__cmd__hold 0
+#define R_DMA_CH7_CMD__cmd__start 1
+#define R_DMA_CH7_CMD__cmd__restart 3
+#define R_DMA_CH7_CMD__cmd__continue 3
+#define R_DMA_CH7_CMD__cmd__reset 4
+
+#define R_DMA_CH7_CLR_INTR (IO_TYPECAST_BYTE 0xb00001ed)
+#define R_DMA_CH7_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH7_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH7_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH7_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH7_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH7_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH7_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH7_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH7_STATUS (IO_TYPECAST_RO_BYTE 0xb00001ee)
+#define R_DMA_CH7_STATUS__avail__BITNR 0
+#define R_DMA_CH7_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH8_HWSW (IO_TYPECAST_UDWORD 0xb0000180)
+#define R_DMA_CH8_HWSW__hw__BITNR 16
+#define R_DMA_CH8_HWSW__hw__WIDTH 16
+#define R_DMA_CH8_HWSW__sw__BITNR 0
+#define R_DMA_CH8_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH8_DESCR (IO_TYPECAST_UDWORD 0xb000018c)
+#define R_DMA_CH8_DESCR__descr__BITNR 0
+#define R_DMA_CH8_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH8_NEXT (IO_TYPECAST_UDWORD 0xb0000184)
+#define R_DMA_CH8_NEXT__next__BITNR 0
+#define R_DMA_CH8_NEXT__next__WIDTH 32
+
+#define R_DMA_CH8_BUF (IO_TYPECAST_UDWORD 0xb0000188)
+#define R_DMA_CH8_BUF__buf__BITNR 0
+#define R_DMA_CH8_BUF__buf__WIDTH 32
+
+#define R_DMA_CH8_FIRST (IO_TYPECAST_UDWORD 0xb00001c0)
+#define R_DMA_CH8_FIRST__first__BITNR 0
+#define R_DMA_CH8_FIRST__first__WIDTH 32
+
+#define R_DMA_CH8_CMD (IO_TYPECAST_BYTE 0xb00001f0)
+#define R_DMA_CH8_CMD__cmd__BITNR 0
+#define R_DMA_CH8_CMD__cmd__WIDTH 3
+#define R_DMA_CH8_CMD__cmd__hold 0
+#define R_DMA_CH8_CMD__cmd__start 1
+#define R_DMA_CH8_CMD__cmd__restart 3
+#define R_DMA_CH8_CMD__cmd__continue 3
+#define R_DMA_CH8_CMD__cmd__reset 4
+
+#define R_DMA_CH8_CLR_INTR (IO_TYPECAST_BYTE 0xb00001f1)
+#define R_DMA_CH8_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH8_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH8_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH8_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH8_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH8_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH8_STATUS (IO_TYPECAST_RO_BYTE 0xb00001f2)
+#define R_DMA_CH8_STATUS__avail__BITNR 0
+#define R_DMA_CH8_STATUS__avail__WIDTH 7
+
+#define R_DMA_CH8_SUB (IO_TYPECAST_UDWORD 0xb000018c)
+#define R_DMA_CH8_SUB__sub__BITNR 0
+#define R_DMA_CH8_SUB__sub__WIDTH 32
+
+#define R_DMA_CH8_NEP (IO_TYPECAST_UDWORD 0xb00001c0)
+#define R_DMA_CH8_NEP__nep__BITNR 0
+#define R_DMA_CH8_NEP__nep__WIDTH 32
+
+#define R_DMA_CH8_SUB0_EP (IO_TYPECAST_UDWORD 0xb00001c8)
+#define R_DMA_CH8_SUB0_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB0_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB0_CMD (IO_TYPECAST_BYTE 0xb00001d3)
+#define R_DMA_CH8_SUB0_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB0_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB0_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB0_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB0_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e3)
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB0_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH8_SUB1_EP (IO_TYPECAST_UDWORD 0xb00001cc)
+#define R_DMA_CH8_SUB1_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB1_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB1_CMD (IO_TYPECAST_BYTE 0xb00001d7)
+#define R_DMA_CH8_SUB1_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB1_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB1_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB1_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB1_CLR_INTR (IO_TYPECAST_BYTE 0xb00001e7)
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB1_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH8_SUB2_EP (IO_TYPECAST_UDWORD 0xb00001f8)
+#define R_DMA_CH8_SUB2_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB2_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB2_CMD (IO_TYPECAST_BYTE 0xb00001db)
+#define R_DMA_CH8_SUB2_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB2_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB2_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB2_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB2_CLR_INTR (IO_TYPECAST_BYTE 0xb00001eb)
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB2_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH8_SUB3_EP (IO_TYPECAST_UDWORD 0xb00001fc)
+#define R_DMA_CH8_SUB3_EP__ep__BITNR 0
+#define R_DMA_CH8_SUB3_EP__ep__WIDTH 32
+
+#define R_DMA_CH8_SUB3_CMD (IO_TYPECAST_BYTE 0xb00001df)
+#define R_DMA_CH8_SUB3_CMD__cmd__BITNR 0
+#define R_DMA_CH8_SUB3_CMD__cmd__WIDTH 1
+#define R_DMA_CH8_SUB3_CMD__cmd__stop 0
+#define R_DMA_CH8_SUB3_CMD__cmd__start 1
+
+#define R_DMA_CH8_SUB3_CLR_INTR (IO_TYPECAST_BYTE 0xb00001ef)
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__dont 0
+#define R_DMA_CH8_SUB3_CLR_INTR__clr_descr__do 1
+
+#define R_DMA_CH9_HWSW (IO_TYPECAST_UDWORD 0xb0000190)
+#define R_DMA_CH9_HWSW__hw__BITNR 16
+#define R_DMA_CH9_HWSW__hw__WIDTH 16
+#define R_DMA_CH9_HWSW__sw__BITNR 0
+#define R_DMA_CH9_HWSW__sw__WIDTH 16
+
+#define R_DMA_CH9_DESCR (IO_TYPECAST_UDWORD 0xb000019c)
+#define R_DMA_CH9_DESCR__descr__BITNR 0
+#define R_DMA_CH9_DESCR__descr__WIDTH 32
+
+#define R_DMA_CH9_NEXT (IO_TYPECAST_UDWORD 0xb0000194)
+#define R_DMA_CH9_NEXT__next__BITNR 0
+#define R_DMA_CH9_NEXT__next__WIDTH 32
+
+#define R_DMA_CH9_BUF (IO_TYPECAST_UDWORD 0xb0000198)
+#define R_DMA_CH9_BUF__buf__BITNR 0
+#define R_DMA_CH9_BUF__buf__WIDTH 32
+
+#define R_DMA_CH9_FIRST (IO_TYPECAST_UDWORD 0xb00001c4)
+#define R_DMA_CH9_FIRST__first__BITNR 0
+#define R_DMA_CH9_FIRST__first__WIDTH 32
+
+#define R_DMA_CH9_CMD (IO_TYPECAST_BYTE 0xb00001f4)
+#define R_DMA_CH9_CMD__cmd__BITNR 0
+#define R_DMA_CH9_CMD__cmd__WIDTH 3
+#define R_DMA_CH9_CMD__cmd__hold 0
+#define R_DMA_CH9_CMD__cmd__start 1
+#define R_DMA_CH9_CMD__cmd__restart 3
+#define R_DMA_CH9_CMD__cmd__continue 3
+#define R_DMA_CH9_CMD__cmd__reset 4
+
+#define R_DMA_CH9_CLR_INTR (IO_TYPECAST_BYTE 0xb00001f5)
+#define R_DMA_CH9_CLR_INTR__clr_eop__BITNR 1
+#define R_DMA_CH9_CLR_INTR__clr_eop__WIDTH 1
+#define R_DMA_CH9_CLR_INTR__clr_eop__do 1
+#define R_DMA_CH9_CLR_INTR__clr_eop__dont 0
+#define R_DMA_CH9_CLR_INTR__clr_descr__BITNR 0
+#define R_DMA_CH9_CLR_INTR__clr_descr__WIDTH 1
+#define R_DMA_CH9_CLR_INTR__clr_descr__do 1
+#define R_DMA_CH9_CLR_INTR__clr_descr__dont 0
+
+#define R_DMA_CH9_STATUS (IO_TYPECAST_RO_BYTE 0xb00001f6)
+#define R_DMA_CH9_STATUS__avail__BITNR 0
+#define R_DMA_CH9_STATUS__avail__WIDTH 7
+
+/*
+!* Test mode registers
+!*/
+
+#define R_TEST_MODE (IO_TYPECAST_UDWORD 0xb00000fc)
+#define R_TEST_MODE__single_step__BITNR 19
+#define R_TEST_MODE__single_step__WIDTH 1
+#define R_TEST_MODE__single_step__on 1
+#define R_TEST_MODE__single_step__off 0
+#define R_TEST_MODE__step_wr__BITNR 18
+#define R_TEST_MODE__step_wr__WIDTH 1
+#define R_TEST_MODE__step_wr__on 1
+#define R_TEST_MODE__step_wr__off 0
+#define R_TEST_MODE__step_rd__BITNR 17
+#define R_TEST_MODE__step_rd__WIDTH 1
+#define R_TEST_MODE__step_rd__on 1
+#define R_TEST_MODE__step_rd__off 0
+#define R_TEST_MODE__step_fetch__BITNR 16
+#define R_TEST_MODE__step_fetch__WIDTH 1
+#define R_TEST_MODE__step_fetch__on 1
+#define R_TEST_MODE__step_fetch__off 0
+#define R_TEST_MODE__mmu_test__BITNR 12
+#define R_TEST_MODE__mmu_test__WIDTH 1
+#define R_TEST_MODE__mmu_test__on 1
+#define R_TEST_MODE__mmu_test__off 0
+#define R_TEST_MODE__usb_test__BITNR 11
+#define R_TEST_MODE__usb_test__WIDTH 1
+#define R_TEST_MODE__usb_test__on 1
+#define R_TEST_MODE__usb_test__off 0
+#define R_TEST_MODE__scsi_timer_test__BITNR 10
+#define R_TEST_MODE__scsi_timer_test__WIDTH 1
+#define R_TEST_MODE__scsi_timer_test__on 1
+#define R_TEST_MODE__scsi_timer_test__off 0
+#define R_TEST_MODE__backoff__BITNR 9
+#define R_TEST_MODE__backoff__WIDTH 1
+#define R_TEST_MODE__backoff__on 1
+#define R_TEST_MODE__backoff__off 0
+#define R_TEST_MODE__snmp_test__BITNR 8
+#define R_TEST_MODE__snmp_test__WIDTH 1
+#define R_TEST_MODE__snmp_test__on 1
+#define R_TEST_MODE__snmp_test__off 0
+#define R_TEST_MODE__snmp_inc__BITNR 7
+#define R_TEST_MODE__snmp_inc__WIDTH 1
+#define R_TEST_MODE__snmp_inc__do 1
+#define R_TEST_MODE__snmp_inc__dont 0
+#define R_TEST_MODE__ser_loop__BITNR 6
+#define R_TEST_MODE__ser_loop__WIDTH 1
+#define R_TEST_MODE__ser_loop__on 1
+#define R_TEST_MODE__ser_loop__off 0
+#define R_TEST_MODE__baudrate__BITNR 5
+#define R_TEST_MODE__baudrate__WIDTH 1
+#define R_TEST_MODE__baudrate__on 1
+#define R_TEST_MODE__baudrate__off 0
+#define R_TEST_MODE__timer__BITNR 3
+#define R_TEST_MODE__timer__WIDTH 2
+#define R_TEST_MODE__timer__off 0
+#define R_TEST_MODE__timer__even 1
+#define R_TEST_MODE__timer__odd 2
+#define R_TEST_MODE__timer__all 3
+#define R_TEST_MODE__cache_test__BITNR 2
+#define R_TEST_MODE__cache_test__WIDTH 1
+#define R_TEST_MODE__cache_test__normal 0
+#define R_TEST_MODE__cache_test__test 1
+#define R_TEST_MODE__tag_test__BITNR 1
+#define R_TEST_MODE__tag_test__WIDTH 1
+#define R_TEST_MODE__tag_test__normal 0
+#define R_TEST_MODE__tag_test__test 1
+#define R_TEST_MODE__cache_enable__BITNR 0
+#define R_TEST_MODE__cache_enable__WIDTH 1
+#define R_TEST_MODE__cache_enable__enable 1
+#define R_TEST_MODE__cache_enable__disable 0
+
+#define R_SINGLE_STEP (IO_TYPECAST_BYTE 0xb00000fe)
+#define R_SINGLE_STEP__single_step__BITNR 3
+#define R_SINGLE_STEP__single_step__WIDTH 1
+#define R_SINGLE_STEP__single_step__on 1
+#define R_SINGLE_STEP__single_step__off 0
+#define R_SINGLE_STEP__step_wr__BITNR 2
+#define R_SINGLE_STEP__step_wr__WIDTH 1
+#define R_SINGLE_STEP__step_wr__on 1
+#define R_SINGLE_STEP__step_wr__off 0
+#define R_SINGLE_STEP__step_rd__BITNR 1
+#define R_SINGLE_STEP__step_rd__WIDTH 1
+#define R_SINGLE_STEP__step_rd__on 1
+#define R_SINGLE_STEP__step_rd__off 0
+#define R_SINGLE_STEP__step_fetch__BITNR 0
+#define R_SINGLE_STEP__step_fetch__WIDTH 1
+#define R_SINGLE_STEP__step_fetch__on 1
+#define R_SINGLE_STEP__step_fetch__off 0
+
+/*
+!* USB interface control registers
+!*/
+
+#define R_USB_REVISION (IO_TYPECAST_RO_BYTE 0xb0000200)
+#define R_USB_REVISION__major__BITNR 4
+#define R_USB_REVISION__major__WIDTH 4
+#define R_USB_REVISION__minor__BITNR 0
+#define R_USB_REVISION__minor__WIDTH 4
+
+#define R_USB_COMMAND (IO_TYPECAST_BYTE 0xb0000201)
+#define R_USB_COMMAND__port_sel__BITNR 6
+#define R_USB_COMMAND__port_sel__WIDTH 2
+#define R_USB_COMMAND__port_sel__nop 0
+#define R_USB_COMMAND__port_sel__port1 1
+#define R_USB_COMMAND__port_sel__port2 2
+#define R_USB_COMMAND__port_sel__both 3
+#define R_USB_COMMAND__port_cmd__BITNR 4
+#define R_USB_COMMAND__port_cmd__WIDTH 2
+#define R_USB_COMMAND__port_cmd__reset 0
+#define R_USB_COMMAND__port_cmd__disable 1
+#define R_USB_COMMAND__port_cmd__suspend 2
+#define R_USB_COMMAND__port_cmd__resume 3
+#define R_USB_COMMAND__ctrl_cmd__BITNR 0
+#define R_USB_COMMAND__ctrl_cmd__WIDTH 3
+#define R_USB_COMMAND__ctrl_cmd__nop 0
+#define R_USB_COMMAND__ctrl_cmd__reset 1
+#define R_USB_COMMAND__ctrl_cmd__deconfig 2
+#define R_USB_COMMAND__ctrl_cmd__host_config 3
+#define R_USB_COMMAND__ctrl_cmd__dev_config 4
+#define R_USB_COMMAND__ctrl_cmd__host_reset 5
+#define R_USB_COMMAND__ctrl_cmd__host_run 6
+#define R_USB_COMMAND__ctrl_cmd__host_stop 7
+
+#define R_USB_STATUS (IO_TYPECAST_RO_BYTE 0xb0000202)
+#define R_USB_STATUS__busy__BITNR 7
+#define R_USB_STATUS__busy__WIDTH 1
+#define R_USB_STATUS__busy__no 0
+#define R_USB_STATUS__busy__yes 1
+#define R_USB_STATUS__device_mode__BITNR 3
+#define R_USB_STATUS__device_mode__WIDTH 1
+#define R_USB_STATUS__device_mode__no 0
+#define R_USB_STATUS__device_mode__yes 1
+#define R_USB_STATUS__host_mode__BITNR 2
+#define R_USB_STATUS__host_mode__WIDTH 1
+#define R_USB_STATUS__host_mode__no 0
+#define R_USB_STATUS__host_mode__yes 1
+#define R_USB_STATUS__started__BITNR 1
+#define R_USB_STATUS__started__WIDTH 1
+#define R_USB_STATUS__started__no 0
+#define R_USB_STATUS__started__yes 1
+#define R_USB_STATUS__running__BITNR 0
+#define R_USB_STATUS__running__WIDTH 1
+#define R_USB_STATUS__running__no 0
+#define R_USB_STATUS__running__yes 1
+
+#define R_USB_IRQ_MASK_SET (IO_TYPECAST_UWORD 0xb0000204)
+#define R_USB_IRQ_MASK_SET__intr_eof__BITNR 13
+#define R_USB_IRQ_MASK_SET__intr_eof__WIDTH 1
+#define R_USB_IRQ_MASK_SET__intr_eof__nop 0
+#define R_USB_IRQ_MASK_SET__intr_eof__set 1
+#define R_USB_IRQ_MASK_SET__iso_eof__BITNR 12
+#define R_USB_IRQ_MASK_SET__iso_eof__WIDTH 1
+#define R_USB_IRQ_MASK_SET__iso_eof__nop 0
+#define R_USB_IRQ_MASK_SET__iso_eof__set 1
+#define R_USB_IRQ_MASK_SET__bulk_eot__BITNR 11
+#define R_USB_IRQ_MASK_SET__bulk_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__bulk_eot__nop 0
+#define R_USB_IRQ_MASK_SET__bulk_eot__set 1
+#define R_USB_IRQ_MASK_SET__ctl_eot__BITNR 10
+#define R_USB_IRQ_MASK_SET__ctl_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__ctl_eot__nop 0
+#define R_USB_IRQ_MASK_SET__ctl_eot__set 1
+#define R_USB_IRQ_MASK_SET__intr_eot__BITNR 9
+#define R_USB_IRQ_MASK_SET__intr_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__intr_eot__nop 0
+#define R_USB_IRQ_MASK_SET__intr_eot__set 1
+#define R_USB_IRQ_MASK_SET__iso_eot__BITNR 8
+#define R_USB_IRQ_MASK_SET__iso_eot__WIDTH 1
+#define R_USB_IRQ_MASK_SET__iso_eot__nop 0
+#define R_USB_IRQ_MASK_SET__iso_eot__set 1
+#define R_USB_IRQ_MASK_SET__sof__BITNR 2
+#define R_USB_IRQ_MASK_SET__sof__WIDTH 1
+#define R_USB_IRQ_MASK_SET__sof__nop 0
+#define R_USB_IRQ_MASK_SET__sof__set 1
+#define R_USB_IRQ_MASK_SET__port_status__BITNR 1
+#define R_USB_IRQ_MASK_SET__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_SET__port_status__nop 0
+#define R_USB_IRQ_MASK_SET__port_status__set 1
+#define R_USB_IRQ_MASK_SET__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_SET__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_SET__ctl_status__nop 0
+#define R_USB_IRQ_MASK_SET__ctl_status__set 1
+
+#define R_USB_IRQ_MASK_READ (IO_TYPECAST_RO_UWORD 0xb0000204)
+#define R_USB_IRQ_MASK_READ__intr_eof__BITNR 13
+#define R_USB_IRQ_MASK_READ__intr_eof__WIDTH 1
+#define R_USB_IRQ_MASK_READ__intr_eof__no_pend 0
+#define R_USB_IRQ_MASK_READ__intr_eof__pend 1
+#define R_USB_IRQ_MASK_READ__iso_eof__BITNR 12
+#define R_USB_IRQ_MASK_READ__iso_eof__WIDTH 1
+#define R_USB_IRQ_MASK_READ__iso_eof__no_pend 0
+#define R_USB_IRQ_MASK_READ__iso_eof__pend 1
+#define R_USB_IRQ_MASK_READ__bulk_eot__BITNR 11
+#define R_USB_IRQ_MASK_READ__bulk_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__bulk_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__bulk_eot__pend 1
+#define R_USB_IRQ_MASK_READ__ctl_eot__BITNR 10
+#define R_USB_IRQ_MASK_READ__ctl_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__ctl_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__ctl_eot__pend 1
+#define R_USB_IRQ_MASK_READ__intr_eot__BITNR 9
+#define R_USB_IRQ_MASK_READ__intr_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__intr_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__intr_eot__pend 1
+#define R_USB_IRQ_MASK_READ__iso_eot__BITNR 8
+#define R_USB_IRQ_MASK_READ__iso_eot__WIDTH 1
+#define R_USB_IRQ_MASK_READ__iso_eot__no_pend 0
+#define R_USB_IRQ_MASK_READ__iso_eot__pend 1
+#define R_USB_IRQ_MASK_READ__sof__BITNR 2
+#define R_USB_IRQ_MASK_READ__sof__WIDTH 1
+#define R_USB_IRQ_MASK_READ__sof__no_pend 0
+#define R_USB_IRQ_MASK_READ__sof__pend 1
+#define R_USB_IRQ_MASK_READ__port_status__BITNR 1
+#define R_USB_IRQ_MASK_READ__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_READ__port_status__no_pend 0
+#define R_USB_IRQ_MASK_READ__port_status__pend 1
+#define R_USB_IRQ_MASK_READ__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_READ__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_READ__ctl_status__no_pend 0
+#define R_USB_IRQ_MASK_READ__ctl_status__pend 1
+
+#define R_USB_IRQ_MASK_CLR (IO_TYPECAST_UWORD 0xb0000206)
+#define R_USB_IRQ_MASK_CLR__intr_eof__BITNR 13
+#define R_USB_IRQ_MASK_CLR__intr_eof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__intr_eof__nop 0
+#define R_USB_IRQ_MASK_CLR__intr_eof__clr 1
+#define R_USB_IRQ_MASK_CLR__iso_eof__BITNR 12
+#define R_USB_IRQ_MASK_CLR__iso_eof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__iso_eof__nop 0
+#define R_USB_IRQ_MASK_CLR__iso_eof__clr 1
+#define R_USB_IRQ_MASK_CLR__bulk_eot__BITNR 11
+#define R_USB_IRQ_MASK_CLR__bulk_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__bulk_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__bulk_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__ctl_eot__BITNR 10
+#define R_USB_IRQ_MASK_CLR__ctl_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__ctl_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__ctl_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__intr_eot__BITNR 9
+#define R_USB_IRQ_MASK_CLR__intr_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__intr_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__intr_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__iso_eot__BITNR 8
+#define R_USB_IRQ_MASK_CLR__iso_eot__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__iso_eot__nop 0
+#define R_USB_IRQ_MASK_CLR__iso_eot__clr 1
+#define R_USB_IRQ_MASK_CLR__sof__BITNR 2
+#define R_USB_IRQ_MASK_CLR__sof__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__sof__nop 0
+#define R_USB_IRQ_MASK_CLR__sof__clr 1
+#define R_USB_IRQ_MASK_CLR__port_status__BITNR 1
+#define R_USB_IRQ_MASK_CLR__port_status__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__port_status__nop 0
+#define R_USB_IRQ_MASK_CLR__port_status__clr 1
+#define R_USB_IRQ_MASK_CLR__ctl_status__BITNR 0
+#define R_USB_IRQ_MASK_CLR__ctl_status__WIDTH 1
+#define R_USB_IRQ_MASK_CLR__ctl_status__nop 0
+#define R_USB_IRQ_MASK_CLR__ctl_status__clr 1
+
+#define R_USB_IRQ_READ (IO_TYPECAST_RO_UWORD 0xb0000206)
+#define R_USB_IRQ_READ__intr_eof__BITNR 13
+#define R_USB_IRQ_READ__intr_eof__WIDTH 1
+#define R_USB_IRQ_READ__intr_eof__no_pend 0
+#define R_USB_IRQ_READ__intr_eof__pend 1
+#define R_USB_IRQ_READ__iso_eof__BITNR 12
+#define R_USB_IRQ_READ__iso_eof__WIDTH 1
+#define R_USB_IRQ_READ__iso_eof__no_pend 0
+#define R_USB_IRQ_READ__iso_eof__pend 1
+#define R_USB_IRQ_READ__bulk_eot__BITNR 11
+#define R_USB_IRQ_READ__bulk_eot__WIDTH 1
+#define R_USB_IRQ_READ__bulk_eot__no_pend 0
+#define R_USB_IRQ_READ__bulk_eot__pend 1
+#define R_USB_IRQ_READ__ctl_eot__BITNR 10
+#define R_USB_IRQ_READ__ctl_eot__WIDTH 1
+#define R_USB_IRQ_READ__ctl_eot__no_pend 0
+#define R_USB_IRQ_READ__ctl_eot__pend 1
+#define R_USB_IRQ_READ__intr_eot__BITNR 9
+#define R_USB_IRQ_READ__intr_eot__WIDTH 1
+#define R_USB_IRQ_READ__intr_eot__no_pend 0
+#define R_USB_IRQ_READ__intr_eot__pend 1
+#define R_USB_IRQ_READ__iso_eot__BITNR 8
+#define R_USB_IRQ_READ__iso_eot__WIDTH 1
+#define R_USB_IRQ_READ__iso_eot__no_pend 0
+#define R_USB_IRQ_READ__iso_eot__pend 1
+#define R_USB_IRQ_READ__sof__BITNR 2
+#define R_USB_IRQ_READ__sof__WIDTH 1
+#define R_USB_IRQ_READ__sof__no_pend 0
+#define R_USB_IRQ_READ__sof__pend 1
+#define R_USB_IRQ_READ__port_status__BITNR 1
+#define R_USB_IRQ_READ__port_status__WIDTH 1
+#define R_USB_IRQ_READ__port_status__no_pend 0
+#define R_USB_IRQ_READ__port_status__pend 1
+#define R_USB_IRQ_READ__ctl_status__BITNR 0
+#define R_USB_IRQ_READ__ctl_status__WIDTH 1
+#define R_USB_IRQ_READ__ctl_status__no_pend 0
+#define R_USB_IRQ_READ__ctl_status__pend 1
+
+#define R_USB_FM_NUMBER (IO_TYPECAST_RO_UDWORD 0xb000020c)
+#define R_USB_FM_NUMBER__value__BITNR 0
+#define R_USB_FM_NUMBER__value__WIDTH 32
+
+#define R_USB_FM_INTERVAL (IO_TYPECAST_UWORD 0xb0000210)
+#define R_USB_FM_INTERVAL__fixed__BITNR 6
+#define R_USB_FM_INTERVAL__fixed__WIDTH 8
+#define R_USB_FM_INTERVAL__adj__BITNR 0
+#define R_USB_FM_INTERVAL__adj__WIDTH 6
+
+#define R_USB_FM_REMAINING (IO_TYPECAST_RO_UWORD 0xb0000212)
+#define R_USB_FM_REMAINING__value__BITNR 0
+#define R_USB_FM_REMAINING__value__WIDTH 14
+
+#define R_USB_FM_PSTART (IO_TYPECAST_UWORD 0xb0000214)
+#define R_USB_FM_PSTART__value__BITNR 0
+#define R_USB_FM_PSTART__value__WIDTH 14
+
+#define R_USB_LS_THRESHOLD (IO_TYPECAST_UWORD 0xb0000216)
+#define R_USB_LS_THRESHOLD__value__BITNR 0
+#define R_USB_LS_THRESHOLD__value__WIDTH 14
+
+#define R_USB_RH_STATUS (IO_TYPECAST_RO_BYTE 0xb0000203)
+#define R_USB_RH_STATUS__bus1__BITNR 4
+#define R_USB_RH_STATUS__bus1__WIDTH 2
+#define R_USB_RH_STATUS__bus1__SE0 0
+#define R_USB_RH_STATUS__bus1__Diff0 1
+#define R_USB_RH_STATUS__bus1__Diff1 1
+#define R_USB_RH_STATUS__bus1__SE1 3
+#define R_USB_RH_STATUS__bus2__BITNR 2
+#define R_USB_RH_STATUS__bus2__WIDTH 2
+#define R_USB_RH_STATUS__bus2__SE0 0
+#define R_USB_RH_STATUS__bus2__Diff0 1
+#define R_USB_RH_STATUS__bus2__Diff1 1
+#define R_USB_RH_STATUS__bus2__SE1 3
+#define R_USB_RH_STATUS__nports__BITNR 0
+#define R_USB_RH_STATUS__nports__WIDTH 2
+
+#define R_USB_RH_PORT_STATUS_1 (IO_TYPECAST_RO_UWORD 0xb0000218)
+#define R_USB_RH_PORT_STATUS_1__speed__BITNR 9
+#define R_USB_RH_PORT_STATUS_1__speed__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__speed__full 0
+#define R_USB_RH_PORT_STATUS_1__speed__low 1
+#define R_USB_RH_PORT_STATUS_1__power__BITNR 8
+#define R_USB_RH_PORT_STATUS_1__power__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__reset__BITNR 4
+#define R_USB_RH_PORT_STATUS_1__reset__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__reset__no 0
+#define R_USB_RH_PORT_STATUS_1__reset__yes 1
+#define R_USB_RH_PORT_STATUS_1__overcurent__BITNR 3
+#define R_USB_RH_PORT_STATUS_1__overcurent__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__overcurent__no 0
+#define R_USB_RH_PORT_STATUS_1__overcurent__yes 1
+#define R_USB_RH_PORT_STATUS_1__suspended__BITNR 2
+#define R_USB_RH_PORT_STATUS_1__suspended__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__suspended__no 0
+#define R_USB_RH_PORT_STATUS_1__suspended__yes 1
+#define R_USB_RH_PORT_STATUS_1__enabled__BITNR 1
+#define R_USB_RH_PORT_STATUS_1__enabled__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__enabled__no 0
+#define R_USB_RH_PORT_STATUS_1__enabled__yes 1
+#define R_USB_RH_PORT_STATUS_1__connected__BITNR 0
+#define R_USB_RH_PORT_STATUS_1__connected__WIDTH 1
+#define R_USB_RH_PORT_STATUS_1__connected__no 0
+#define R_USB_RH_PORT_STATUS_1__connected__yes 1
+
+#define R_USB_RH_PORT_STATUS_2 (IO_TYPECAST_RO_UWORD 0xb000021a)
+#define R_USB_RH_PORT_STATUS_2__speed__BITNR 9
+#define R_USB_RH_PORT_STATUS_2__speed__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__speed__full 0
+#define R_USB_RH_PORT_STATUS_2__speed__low 1
+#define R_USB_RH_PORT_STATUS_2__power__BITNR 8
+#define R_USB_RH_PORT_STATUS_2__power__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__reset__BITNR 4
+#define R_USB_RH_PORT_STATUS_2__reset__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__reset__no 0
+#define R_USB_RH_PORT_STATUS_2__reset__yes 1
+#define R_USB_RH_PORT_STATUS_2__overcurent__BITNR 3
+#define R_USB_RH_PORT_STATUS_2__overcurent__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__overcurent__no 0
+#define R_USB_RH_PORT_STATUS_2__overcurent__yes 1
+#define R_USB_RH_PORT_STATUS_2__suspended__BITNR 2
+#define R_USB_RH_PORT_STATUS_2__suspended__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__suspended__no 0
+#define R_USB_RH_PORT_STATUS_2__suspended__yes 1
+#define R_USB_RH_PORT_STATUS_2__enabled__BITNR 1
+#define R_USB_RH_PORT_STATUS_2__enabled__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__enabled__no 0
+#define R_USB_RH_PORT_STATUS_2__enabled__yes 1
+#define R_USB_RH_PORT_STATUS_2__connected__BITNR 0
+#define R_USB_RH_PORT_STATUS_2__connected__WIDTH 1
+#define R_USB_RH_PORT_STATUS_2__connected__no 0
+#define R_USB_RH_PORT_STATUS_2__connected__yes 1
+
+#define R_USB_EPT_INDEX (IO_TYPECAST_BYTE 0xb0000208)
+#define R_USB_EPT_INDEX__value__BITNR 0
+#define R_USB_EPT_INDEX__value__WIDTH 5
+
+#define R_USB_EPT_DATA (IO_TYPECAST_UDWORD 0xb000021c)
+#define R_USB_EPT_DATA__valid__BITNR 31
+#define R_USB_EPT_DATA__valid__WIDTH 1
+#define R_USB_EPT_DATA__valid__no 0
+#define R_USB_EPT_DATA__valid__yes 1
+#define R_USB_EPT_DATA__hold__BITNR 30
+#define R_USB_EPT_DATA__hold__WIDTH 1
+#define R_USB_EPT_DATA__hold__no 0
+#define R_USB_EPT_DATA__hold__yes 1
+#define R_USB_EPT_DATA__error_count_in__BITNR 28
+#define R_USB_EPT_DATA__error_count_in__WIDTH 2
+#define R_USB_EPT_DATA__t_in__BITNR 27
+#define R_USB_EPT_DATA__t_in__WIDTH 1
+#define R_USB_EPT_DATA__low_speed__BITNR 26
+#define R_USB_EPT_DATA__low_speed__WIDTH 1
+#define R_USB_EPT_DATA__low_speed__no 0
+#define R_USB_EPT_DATA__low_speed__yes 1
+#define R_USB_EPT_DATA__port__BITNR 24
+#define R_USB_EPT_DATA__port__WIDTH 2
+#define R_USB_EPT_DATA__port__any 0
+#define R_USB_EPT_DATA__port__p1 1
+#define R_USB_EPT_DATA__port__p2 2
+#define R_USB_EPT_DATA__port__undef 3
+#define R_USB_EPT_DATA__error_code__BITNR 22
+#define R_USB_EPT_DATA__error_code__WIDTH 2
+#define R_USB_EPT_DATA__error_code__no_error 0
+#define R_USB_EPT_DATA__error_code__stall 1
+#define R_USB_EPT_DATA__error_code__bus_error 2
+#define R_USB_EPT_DATA__error_code__TBD3 3
+#define R_USB_EPT_DATA__t_out__BITNR 21
+#define R_USB_EPT_DATA__t_out__WIDTH 1
+#define R_USB_EPT_DATA__error_count_out__BITNR 19
+#define R_USB_EPT_DATA__error_count_out__WIDTH 2
+#define R_USB_EPT_DATA__max_len__BITNR 11
+#define R_USB_EPT_DATA__max_len__WIDTH 7
+#define R_USB_EPT_DATA__ep__BITNR 7
+#define R_USB_EPT_DATA__ep__WIDTH 4
+#define R_USB_EPT_DATA__dev__BITNR 0
+#define R_USB_EPT_DATA__dev__WIDTH 7
+
+#define R_USB_EPT_DATA_ISO (IO_TYPECAST_UDWORD 0xb000021c)
+#define R_USB_EPT_DATA_ISO__valid__BITNR 31
+#define R_USB_EPT_DATA_ISO__valid__WIDTH 1
+#define R_USB_EPT_DATA_ISO__valid__no 0
+#define R_USB_EPT_DATA_ISO__valid__yes 1
+#define R_USB_EPT_DATA_ISO__port__BITNR 24
+#define R_USB_EPT_DATA_ISO__port__WIDTH 2
+#define R_USB_EPT_DATA_ISO__port__any 0
+#define R_USB_EPT_DATA_ISO__port__p1 1
+#define R_USB_EPT_DATA_ISO__port__p2 2
+#define R_USB_EPT_DATA_ISO__port__undef 3
+#define R_USB_EPT_DATA_ISO__error_code__BITNR 22
+#define R_USB_EPT_DATA_ISO__error_code__WIDTH 2
+#define R_USB_EPT_DATA_ISO__error_code__no_error 0
+#define R_USB_EPT_DATA_ISO__error_code__stall 1
+#define R_USB_EPT_DATA_ISO__error_code__bus_error 2
+#define R_USB_EPT_DATA_ISO__error_code__TBD3 3
+#define R_USB_EPT_DATA_ISO__max_len__BITNR 11
+#define R_USB_EPT_DATA_ISO__max_len__WIDTH 10
+#define R_USB_EPT_DATA_ISO__ep__BITNR 7
+#define R_USB_EPT_DATA_ISO__ep__WIDTH 4
+#define R_USB_EPT_DATA_ISO__dev__BITNR 0
+#define R_USB_EPT_DATA_ISO__dev__WIDTH 7
+
+#define R_USB_EPT_DATA_DEV (IO_TYPECAST_UDWORD 0xb000021c)
+#define R_USB_EPT_DATA_DEV__valid__BITNR 31
+#define R_USB_EPT_DATA_DEV__valid__WIDTH 1
+#define R_USB_EPT_DATA_DEV__valid__no 0
+#define R_USB_EPT_DATA_DEV__valid__yes 1
+#define R_USB_EPT_DATA_DEV__hold__BITNR 30
+#define R_USB_EPT_DATA_DEV__hold__WIDTH 1
+#define R_USB_EPT_DATA_DEV__hold__no 0
+#define R_USB_EPT_DATA_DEV__hold__yes 1
+#define R_USB_EPT_DATA_DEV__stall__BITNR 29
+#define R_USB_EPT_DATA_DEV__stall__WIDTH 1
+#define R_USB_EPT_DATA_DEV__stall__no 0
+#define R_USB_EPT_DATA_DEV__stall__yes 1
+#define R_USB_EPT_DATA_DEV__quiet__BITNR 28
+#define R_USB_EPT_DATA_DEV__quiet__WIDTH 1
+#define R_USB_EPT_DATA_DEV__quiet__no 0
+#define R_USB_EPT_DATA_DEV__quiet__yes 1
+#define R_USB_EPT_DATA_DEV__ctrl__BITNR 27
+#define R_USB_EPT_DATA_DEV__ctrl__WIDTH 1
+#define R_USB_EPT_DATA_DEV__ctrl__no 0
+#define R_USB_EPT_DATA_DEV__ctrl__yes 1
+#define R_USB_EPT_DATA_DEV__iso__BITNR 26
+#define R_USB_EPT_DATA_DEV__iso__WIDTH 1
+#define R_USB_EPT_DATA_DEV__iso__no 0
+#define R_USB_EPT_DATA_DEV__iso__yes 1
+#define R_USB_EPT_DATA_DEV__port__BITNR 24
+#define R_USB_EPT_DATA_DEV__port__WIDTH 2
+#define R_USB_EPT_DATA_DEV__t__BITNR 21
+#define R_USB_EPT_DATA_DEV__t__WIDTH 1
+#define R_USB_EPT_DATA_DEV__max_len__BITNR 11
+#define R_USB_EPT_DATA_DEV__max_len__WIDTH 10
+#define R_USB_EPT_DATA_DEV__ep__BITNR 7
+#define R_USB_EPT_DATA_DEV__ep__WIDTH 4
+#define R_USB_EPT_DATA_DEV__dev__BITNR 0
+#define R_USB_EPT_DATA_DEV__dev__WIDTH 7
+
+#define R_USB_SNMP_TERROR (IO_TYPECAST_UDWORD 0xb0000220)
+#define R_USB_SNMP_TERROR__value__BITNR 0
+#define R_USB_SNMP_TERROR__value__WIDTH 32
+
+/*
+!* MMU registers
+!*/
+
+#define R_MMU_CONFIG (IO_TYPECAST_UDWORD 0xb0000240)
+#define R_MMU_CONFIG__mmu_enable__BITNR 31
+#define R_MMU_CONFIG__mmu_enable__WIDTH 1
+#define R_MMU_CONFIG__mmu_enable__enable 1
+#define R_MMU_CONFIG__mmu_enable__disable 0
+#define R_MMU_CONFIG__inv_excp__BITNR 18
+#define R_MMU_CONFIG__inv_excp__WIDTH 1
+#define R_MMU_CONFIG__inv_excp__enable 1
+#define R_MMU_CONFIG__inv_excp__disable 0
+#define R_MMU_CONFIG__acc_excp__BITNR 17
+#define R_MMU_CONFIG__acc_excp__WIDTH 1
+#define R_MMU_CONFIG__acc_excp__enable 1
+#define R_MMU_CONFIG__acc_excp__disable 0
+#define R_MMU_CONFIG__we_excp__BITNR 16
+#define R_MMU_CONFIG__we_excp__WIDTH 1
+#define R_MMU_CONFIG__we_excp__enable 1
+#define R_MMU_CONFIG__we_excp__disable 0
+#define R_MMU_CONFIG__seg_f__BITNR 15
+#define R_MMU_CONFIG__seg_f__WIDTH 1
+#define R_MMU_CONFIG__seg_f__seg 1
+#define R_MMU_CONFIG__seg_f__page 0
+#define R_MMU_CONFIG__seg_e__BITNR 14
+#define R_MMU_CONFIG__seg_e__WIDTH 1
+#define R_MMU_CONFIG__seg_e__seg 1
+#define R_MMU_CONFIG__seg_e__page 0
+#define R_MMU_CONFIG__seg_d__BITNR 13
+#define R_MMU_CONFIG__seg_d__WIDTH 1
+#define R_MMU_CONFIG__seg_d__seg 1
+#define R_MMU_CONFIG__seg_d__page 0
+#define R_MMU_CONFIG__seg_c__BITNR 12
+#define R_MMU_CONFIG__seg_c__WIDTH 1
+#define R_MMU_CONFIG__seg_c__seg 1
+#define R_MMU_CONFIG__seg_c__page 0
+#define R_MMU_CONFIG__seg_b__BITNR 11
+#define R_MMU_CONFIG__seg_b__WIDTH 1
+#define R_MMU_CONFIG__seg_b__seg 1
+#define R_MMU_CONFIG__seg_b__page 0
+#define R_MMU_CONFIG__seg_a__BITNR 10
+#define R_MMU_CONFIG__seg_a__WIDTH 1
+#define R_MMU_CONFIG__seg_a__seg 1
+#define R_MMU_CONFIG__seg_a__page 0
+#define R_MMU_CONFIG__seg_9__BITNR 9
+#define R_MMU_CONFIG__seg_9__WIDTH 1
+#define R_MMU_CONFIG__seg_9__seg 1
+#define R_MMU_CONFIG__seg_9__page 0
+#define R_MMU_CONFIG__seg_8__BITNR 8
+#define R_MMU_CONFIG__seg_8__WIDTH 1
+#define R_MMU_CONFIG__seg_8__seg 1
+#define R_MMU_CONFIG__seg_8__page 0
+#define R_MMU_CONFIG__seg_7__BITNR 7
+#define R_MMU_CONFIG__seg_7__WIDTH 1
+#define R_MMU_CONFIG__seg_7__seg 1
+#define R_MMU_CONFIG__seg_7__page 0
+#define R_MMU_CONFIG__seg_6__BITNR 6
+#define R_MMU_CONFIG__seg_6__WIDTH 1
+#define R_MMU_CONFIG__seg_6__seg 1
+#define R_MMU_CONFIG__seg_6__page 0
+#define R_MMU_CONFIG__seg_5__BITNR 5
+#define R_MMU_CONFIG__seg_5__WIDTH 1
+#define R_MMU_CONFIG__seg_5__seg 1
+#define R_MMU_CONFIG__seg_5__page 0
+#define R_MMU_CONFIG__seg_4__BITNR 4
+#define R_MMU_CONFIG__seg_4__WIDTH 1
+#define R_MMU_CONFIG__seg_4__seg 1
+#define R_MMU_CONFIG__seg_4__page 0
+#define R_MMU_CONFIG__seg_3__BITNR 3
+#define R_MMU_CONFIG__seg_3__WIDTH 1
+#define R_MMU_CONFIG__seg_3__seg 1
+#define R_MMU_CONFIG__seg_3__page 0
+#define R_MMU_CONFIG__seg_2__BITNR 2
+#define R_MMU_CONFIG__seg_2__WIDTH 1
+#define R_MMU_CONFIG__seg_2__seg 1
+#define R_MMU_CONFIG__seg_2__page 0
+#define R_MMU_CONFIG__seg_1__BITNR 1
+#define R_MMU_CONFIG__seg_1__WIDTH 1
+#define R_MMU_CONFIG__seg_1__seg 1
+#define R_MMU_CONFIG__seg_1__page 0
+#define R_MMU_CONFIG__seg_0__BITNR 0
+#define R_MMU_CONFIG__seg_0__WIDTH 1
+#define R_MMU_CONFIG__seg_0__seg 1
+#define R_MMU_CONFIG__seg_0__page 0
+
+#define R_MMU_KSEG (IO_TYPECAST_UWORD 0xb0000240)
+#define R_MMU_KSEG__seg_f__BITNR 15
+#define R_MMU_KSEG__seg_f__WIDTH 1
+#define R_MMU_KSEG__seg_f__seg 1
+#define R_MMU_KSEG__seg_f__page 0
+#define R_MMU_KSEG__seg_e__BITNR 14
+#define R_MMU_KSEG__seg_e__WIDTH 1
+#define R_MMU_KSEG__seg_e__seg 1
+#define R_MMU_KSEG__seg_e__page 0
+#define R_MMU_KSEG__seg_d__BITNR 13
+#define R_MMU_KSEG__seg_d__WIDTH 1
+#define R_MMU_KSEG__seg_d__seg 1
+#define R_MMU_KSEG__seg_d__page 0
+#define R_MMU_KSEG__seg_c__BITNR 12
+#define R_MMU_KSEG__seg_c__WIDTH 1
+#define R_MMU_KSEG__seg_c__seg 1
+#define R_MMU_KSEG__seg_c__page 0
+#define R_MMU_KSEG__seg_b__BITNR 11
+#define R_MMU_KSEG__seg_b__WIDTH 1
+#define R_MMU_KSEG__seg_b__seg 1
+#define R_MMU_KSEG__seg_b__page 0
+#define R_MMU_KSEG__seg_a__BITNR 10
+#define R_MMU_KSEG__seg_a__WIDTH 1
+#define R_MMU_KSEG__seg_a__seg 1
+#define R_MMU_KSEG__seg_a__page 0
+#define R_MMU_KSEG__seg_9__BITNR 9
+#define R_MMU_KSEG__seg_9__WIDTH 1
+#define R_MMU_KSEG__seg_9__seg 1
+#define R_MMU_KSEG__seg_9__page 0
+#define R_MMU_KSEG__seg_8__BITNR 8
+#define R_MMU_KSEG__seg_8__WIDTH 1
+#define R_MMU_KSEG__seg_8__seg 1
+#define R_MMU_KSEG__seg_8__page 0
+#define R_MMU_KSEG__seg_7__BITNR 7
+#define R_MMU_KSEG__seg_7__WIDTH 1
+#define R_MMU_KSEG__seg_7__seg 1
+#define R_MMU_KSEG__seg_7__page 0
+#define R_MMU_KSEG__seg_6__BITNR 6
+#define R_MMU_KSEG__seg_6__WIDTH 1
+#define R_MMU_KSEG__seg_6__seg 1
+#define R_MMU_KSEG__seg_6__page 0
+#define R_MMU_KSEG__seg_5__BITNR 5
+#define R_MMU_KSEG__seg_5__WIDTH 1
+#define R_MMU_KSEG__seg_5__seg 1
+#define R_MMU_KSEG__seg_5__page 0
+#define R_MMU_KSEG__seg_4__BITNR 4
+#define R_MMU_KSEG__seg_4__WIDTH 1
+#define R_MMU_KSEG__seg_4__seg 1
+#define R_MMU_KSEG__seg_4__page 0
+#define R_MMU_KSEG__seg_3__BITNR 3
+#define R_MMU_KSEG__seg_3__WIDTH 1
+#define R_MMU_KSEG__seg_3__seg 1
+#define R_MMU_KSEG__seg_3__page 0
+#define R_MMU_KSEG__seg_2__BITNR 2
+#define R_MMU_KSEG__seg_2__WIDTH 1
+#define R_MMU_KSEG__seg_2__seg 1
+#define R_MMU_KSEG__seg_2__page 0
+#define R_MMU_KSEG__seg_1__BITNR 1
+#define R_MMU_KSEG__seg_1__WIDTH 1
+#define R_MMU_KSEG__seg_1__seg 1
+#define R_MMU_KSEG__seg_1__page 0
+#define R_MMU_KSEG__seg_0__BITNR 0
+#define R_MMU_KSEG__seg_0__WIDTH 1
+#define R_MMU_KSEG__seg_0__seg 1
+#define R_MMU_KSEG__seg_0__page 0
+
+#define R_MMU_CTRL (IO_TYPECAST_BYTE 0xb0000242)
+#define R_MMU_CTRL__inv_excp__BITNR 2
+#define R_MMU_CTRL__inv_excp__WIDTH 1
+#define R_MMU_CTRL__inv_excp__enable 1
+#define R_MMU_CTRL__inv_excp__disable 0
+#define R_MMU_CTRL__acc_excp__BITNR 1
+#define R_MMU_CTRL__acc_excp__WIDTH 1
+#define R_MMU_CTRL__acc_excp__enable 1
+#define R_MMU_CTRL__acc_excp__disable 0
+#define R_MMU_CTRL__we_excp__BITNR 0
+#define R_MMU_CTRL__we_excp__WIDTH 1
+#define R_MMU_CTRL__we_excp__enable 1
+#define R_MMU_CTRL__we_excp__disable 0
+
+#define R_MMU_ENABLE (IO_TYPECAST_BYTE 0xb0000243)
+#define R_MMU_ENABLE__mmu_enable__BITNR 7
+#define R_MMU_ENABLE__mmu_enable__WIDTH 1
+#define R_MMU_ENABLE__mmu_enable__enable 1
+#define R_MMU_ENABLE__mmu_enable__disable 0
+
+#define R_MMU_KBASE_LO (IO_TYPECAST_UDWORD 0xb0000244)
+#define R_MMU_KBASE_LO__base_7__BITNR 28
+#define R_MMU_KBASE_LO__base_7__WIDTH 4
+#define R_MMU_KBASE_LO__base_6__BITNR 24
+#define R_MMU_KBASE_LO__base_6__WIDTH 4
+#define R_MMU_KBASE_LO__base_5__BITNR 20
+#define R_MMU_KBASE_LO__base_5__WIDTH 4
+#define R_MMU_KBASE_LO__base_4__BITNR 16
+#define R_MMU_KBASE_LO__base_4__WIDTH 4
+#define R_MMU_KBASE_LO__base_3__BITNR 12
+#define R_MMU_KBASE_LO__base_3__WIDTH 4
+#define R_MMU_KBASE_LO__base_2__BITNR 8
+#define R_MMU_KBASE_LO__base_2__WIDTH 4
+#define R_MMU_KBASE_LO__base_1__BITNR 4
+#define R_MMU_KBASE_LO__base_1__WIDTH 4
+#define R_MMU_KBASE_LO__base_0__BITNR 0
+#define R_MMU_KBASE_LO__base_0__WIDTH 4
+
+#define R_MMU_KBASE_HI (IO_TYPECAST_UDWORD 0xb0000248)
+#define R_MMU_KBASE_HI__base_f__BITNR 28
+#define R_MMU_KBASE_HI__base_f__WIDTH 4
+#define R_MMU_KBASE_HI__base_e__BITNR 24
+#define R_MMU_KBASE_HI__base_e__WIDTH 4
+#define R_MMU_KBASE_HI__base_d__BITNR 20
+#define R_MMU_KBASE_HI__base_d__WIDTH 4
+#define R_MMU_KBASE_HI__base_c__BITNR 16
+#define R_MMU_KBASE_HI__base_c__WIDTH 4
+#define R_MMU_KBASE_HI__base_b__BITNR 12
+#define R_MMU_KBASE_HI__base_b__WIDTH 4
+#define R_MMU_KBASE_HI__base_a__BITNR 8
+#define R_MMU_KBASE_HI__base_a__WIDTH 4
+#define R_MMU_KBASE_HI__base_9__BITNR 4
+#define R_MMU_KBASE_HI__base_9__WIDTH 4
+#define R_MMU_KBASE_HI__base_8__BITNR 0
+#define R_MMU_KBASE_HI__base_8__WIDTH 4
+
+#define R_MMU_CONTEXT (IO_TYPECAST_BYTE 0xb000024c)
+#define R_MMU_CONTEXT__page_id__BITNR 0
+#define R_MMU_CONTEXT__page_id__WIDTH 6
+
+#define R_MMU_CAUSE (IO_TYPECAST_RO_UDWORD 0xb0000250)
+#define R_MMU_CAUSE__vpn__BITNR 13
+#define R_MMU_CAUSE__vpn__WIDTH 19
+#define R_MMU_CAUSE__miss_excp__BITNR 12
+#define R_MMU_CAUSE__miss_excp__WIDTH 1
+#define R_MMU_CAUSE__miss_excp__yes 1
+#define R_MMU_CAUSE__miss_excp__no 0
+#define R_MMU_CAUSE__inv_excp__BITNR 11
+#define R_MMU_CAUSE__inv_excp__WIDTH 1
+#define R_MMU_CAUSE__inv_excp__yes 1
+#define R_MMU_CAUSE__inv_excp__no 0
+#define R_MMU_CAUSE__acc_excp__BITNR 10
+#define R_MMU_CAUSE__acc_excp__WIDTH 1
+#define R_MMU_CAUSE__acc_excp__yes 1
+#define R_MMU_CAUSE__acc_excp__no 0
+#define R_MMU_CAUSE__we_excp__BITNR 9
+#define R_MMU_CAUSE__we_excp__WIDTH 1
+#define R_MMU_CAUSE__we_excp__yes 1
+#define R_MMU_CAUSE__we_excp__no 0
+#define R_MMU_CAUSE__page_id__BITNR 0
+#define R_MMU_CAUSE__page_id__WIDTH 6
+
+#define R_TLB_SELECT (IO_TYPECAST_BYTE 0xb0000254)
+#define R_TLB_SELECT__index__BITNR 0
+#define R_TLB_SELECT__index__WIDTH 6
+
+#define R_TLB_LO (IO_TYPECAST_UDWORD 0xb0000258)
+#define R_TLB_LO__pfn__BITNR 13
+#define R_TLB_LO__pfn__WIDTH 19
+#define R_TLB_LO__global__BITNR 3
+#define R_TLB_LO__global__WIDTH 1
+#define R_TLB_LO__global__yes 1
+#define R_TLB_LO__global__no 0
+#define R_TLB_LO__valid__BITNR 2
+#define R_TLB_LO__valid__WIDTH 1
+#define R_TLB_LO__valid__yes 1
+#define R_TLB_LO__valid__no 0
+#define R_TLB_LO__kernel__BITNR 1
+#define R_TLB_LO__kernel__WIDTH 1
+#define R_TLB_LO__kernel__yes 1
+#define R_TLB_LO__kernel__no 0
+#define R_TLB_LO__we__BITNR 0
+#define R_TLB_LO__we__WIDTH 1
+#define R_TLB_LO__we__yes 1
+#define R_TLB_LO__we__no 0
+
+#define R_TLB_HI (IO_TYPECAST_UDWORD 0xb000025c)
+#define R_TLB_HI__vpn__BITNR 13
+#define R_TLB_HI__vpn__WIDTH 19
+#define R_TLB_HI__page_id__BITNR 0
+#define R_TLB_HI__page_id__WIDTH 6
+
+/*
+!* Syncrounous serial port registers
+!*/
+
+#define R_SYNC_SERIAL1_REC_DATA (IO_TYPECAST_RO_UDWORD 0xb000006c)
+#define R_SYNC_SERIAL1_REC_DATA__data_in__BITNR 0
+#define R_SYNC_SERIAL1_REC_DATA__data_in__WIDTH 32
+
+#define R_SYNC_SERIAL1_REC_WORD (IO_TYPECAST_RO_UWORD 0xb000006c)
+#define R_SYNC_SERIAL1_REC_WORD__data_in__BITNR 0
+#define R_SYNC_SERIAL1_REC_WORD__data_in__WIDTH 16
+
+#define R_SYNC_SERIAL1_REC_BYTE (IO_TYPECAST_RO_BYTE 0xb000006c)
+#define R_SYNC_SERIAL1_REC_BYTE__data_in__BITNR 0
+#define R_SYNC_SERIAL1_REC_BYTE__data_in__WIDTH 8
+
+#define R_SYNC_SERIAL1_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000068)
+#define R_SYNC_SERIAL1_STATUS__rec_status__BITNR 15
+#define R_SYNC_SERIAL1_STATUS__rec_status__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__rec_status__running 0
+#define R_SYNC_SERIAL1_STATUS__rec_status__idle 1
+#define R_SYNC_SERIAL1_STATUS__tr_empty__BITNR 14
+#define R_SYNC_SERIAL1_STATUS__tr_empty__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__tr_empty__empty 1
+#define R_SYNC_SERIAL1_STATUS__tr_empty__not_empty 0
+#define R_SYNC_SERIAL1_STATUS__tr_ready__BITNR 13
+#define R_SYNC_SERIAL1_STATUS__tr_ready__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__tr_ready__full 0
+#define R_SYNC_SERIAL1_STATUS__tr_ready__ready 1
+#define R_SYNC_SERIAL1_STATUS__pin_1__BITNR 12
+#define R_SYNC_SERIAL1_STATUS__pin_1__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__pin_1__low 0
+#define R_SYNC_SERIAL1_STATUS__pin_1__high 1
+#define R_SYNC_SERIAL1_STATUS__pin_0__BITNR 11
+#define R_SYNC_SERIAL1_STATUS__pin_0__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__pin_0__low 0
+#define R_SYNC_SERIAL1_STATUS__pin_0__high 1
+#define R_SYNC_SERIAL1_STATUS__underflow__BITNR 10
+#define R_SYNC_SERIAL1_STATUS__underflow__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__underflow__no 0
+#define R_SYNC_SERIAL1_STATUS__underflow__yes 1
+#define R_SYNC_SERIAL1_STATUS__overrun__BITNR 9
+#define R_SYNC_SERIAL1_STATUS__overrun__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__overrun__no 0
+#define R_SYNC_SERIAL1_STATUS__overrun__yes 1
+#define R_SYNC_SERIAL1_STATUS__data_avail__BITNR 8
+#define R_SYNC_SERIAL1_STATUS__data_avail__WIDTH 1
+#define R_SYNC_SERIAL1_STATUS__data_avail__no 0
+#define R_SYNC_SERIAL1_STATUS__data_avail__yes 1
+#define R_SYNC_SERIAL1_STATUS__data__BITNR 0
+#define R_SYNC_SERIAL1_STATUS__data__WIDTH 8
+
+#define R_SYNC_SERIAL1_TR_DATA (IO_TYPECAST_UDWORD 0xb000006c)
+#define R_SYNC_SERIAL1_TR_DATA__data_out__BITNR 0
+#define R_SYNC_SERIAL1_TR_DATA__data_out__WIDTH 32
+
+#define R_SYNC_SERIAL1_TR_WORD (IO_TYPECAST_UWORD 0xb000006c)
+#define R_SYNC_SERIAL1_TR_WORD__data_out__BITNR 0
+#define R_SYNC_SERIAL1_TR_WORD__data_out__WIDTH 16
+
+#define R_SYNC_SERIAL1_TR_BYTE (IO_TYPECAST_BYTE 0xb000006c)
+#define R_SYNC_SERIAL1_TR_BYTE__data_out__BITNR 0
+#define R_SYNC_SERIAL1_TR_BYTE__data_out__WIDTH 8
+
+#define R_SYNC_SERIAL1_CTRL (IO_TYPECAST_UDWORD 0xb0000068)
+#define R_SYNC_SERIAL1_CTRL__tr_baud__BITNR 28
+#define R_SYNC_SERIAL1_CTRL__tr_baud__WIDTH 4
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c150Hz 0
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c300Hz 1
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c600Hz 2
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c1200Hz 3
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c2400Hz 4
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c4800Hz 5
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c9600Hz 6
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c19k2Hz 7
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c28k8Hz 8
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c57k6Hz 9
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c115k2Hz 10
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c230k4Hz 11
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c460k8Hz 12
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c921k6Hz 13
+#define R_SYNC_SERIAL1_CTRL__tr_baud__c3125kHz 14
+#define R_SYNC_SERIAL1_CTRL__tr_baud__reserved 15
+#define R_SYNC_SERIAL1_CTRL__dma_enable__BITNR 27
+#define R_SYNC_SERIAL1_CTRL__dma_enable__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__dma_enable__on 1
+#define R_SYNC_SERIAL1_CTRL__dma_enable__off 0
+#define R_SYNC_SERIAL1_CTRL__mode__BITNR 24
+#define R_SYNC_SERIAL1_CTRL__mode__WIDTH 3
+#define R_SYNC_SERIAL1_CTRL__mode__master_output 0
+#define R_SYNC_SERIAL1_CTRL__mode__slave_output 1
+#define R_SYNC_SERIAL1_CTRL__mode__master_input 2
+#define R_SYNC_SERIAL1_CTRL__mode__slave_input 3
+#define R_SYNC_SERIAL1_CTRL__mode__master_bidir 4
+#define R_SYNC_SERIAL1_CTRL__mode__slave_bidir 5
+#define R_SYNC_SERIAL1_CTRL__error__BITNR 23
+#define R_SYNC_SERIAL1_CTRL__error__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__error__normal 0
+#define R_SYNC_SERIAL1_CTRL__error__ignore 1
+#define R_SYNC_SERIAL1_CTRL__rec_enable__BITNR 22
+#define R_SYNC_SERIAL1_CTRL__rec_enable__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__rec_enable__disable 0
+#define R_SYNC_SERIAL1_CTRL__rec_enable__enable 1
+#define R_SYNC_SERIAL1_CTRL__f_synctype__BITNR 21
+#define R_SYNC_SERIAL1_CTRL__f_synctype__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__f_synctype__normal 0
+#define R_SYNC_SERIAL1_CTRL__f_synctype__early 1
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__BITNR 19
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__WIDTH 2
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__bit 0
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__word 1
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__extended 2
+#define R_SYNC_SERIAL1_CTRL__f_syncsize__reserved 3
+#define R_SYNC_SERIAL1_CTRL__f_sync__BITNR 18
+#define R_SYNC_SERIAL1_CTRL__f_sync__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__f_sync__on 0
+#define R_SYNC_SERIAL1_CTRL__f_sync__off 1
+#define R_SYNC_SERIAL1_CTRL__clk_mode__BITNR 17
+#define R_SYNC_SERIAL1_CTRL__clk_mode__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_mode__normal 0
+#define R_SYNC_SERIAL1_CTRL__clk_mode__gated 1
+#define R_SYNC_SERIAL1_CTRL__clk_halt__BITNR 16
+#define R_SYNC_SERIAL1_CTRL__clk_halt__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_halt__running 0
+#define R_SYNC_SERIAL1_CTRL__clk_halt__stopped 1
+#define R_SYNC_SERIAL1_CTRL__bitorder__BITNR 15
+#define R_SYNC_SERIAL1_CTRL__bitorder__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__bitorder__lsb 0
+#define R_SYNC_SERIAL1_CTRL__bitorder__msb 1
+#define R_SYNC_SERIAL1_CTRL__tr_enable__BITNR 14
+#define R_SYNC_SERIAL1_CTRL__tr_enable__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__tr_enable__disable 0
+#define R_SYNC_SERIAL1_CTRL__tr_enable__enable 1
+#define R_SYNC_SERIAL1_CTRL__wordsize__BITNR 11
+#define R_SYNC_SERIAL1_CTRL__wordsize__WIDTH 3
+#define R_SYNC_SERIAL1_CTRL__wordsize__size8bit 0
+#define R_SYNC_SERIAL1_CTRL__wordsize__size12bit 1
+#define R_SYNC_SERIAL1_CTRL__wordsize__size16bit 2
+#define R_SYNC_SERIAL1_CTRL__wordsize__size24bit 3
+#define R_SYNC_SERIAL1_CTRL__wordsize__size32bit 4
+#define R_SYNC_SERIAL1_CTRL__buf_empty__BITNR 10
+#define R_SYNC_SERIAL1_CTRL__buf_empty__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__buf_empty__lmt_8 0
+#define R_SYNC_SERIAL1_CTRL__buf_empty__lmt_0 1
+#define R_SYNC_SERIAL1_CTRL__buf_full__BITNR 9
+#define R_SYNC_SERIAL1_CTRL__buf_full__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__buf_full__lmt_32 0
+#define R_SYNC_SERIAL1_CTRL__buf_full__lmt_8 1
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__BITNR 8
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__disabled 0
+#define R_SYNC_SERIAL1_CTRL__flow_ctrl__enabled 1
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__BITNR 6
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__pos 0
+#define R_SYNC_SERIAL1_CTRL__clk_polarity__neg 1
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__BITNR 5
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__normal 0
+#define R_SYNC_SERIAL1_CTRL__frame_polarity__inverted 1
+#define R_SYNC_SERIAL1_CTRL__status_polarity__BITNR 4
+#define R_SYNC_SERIAL1_CTRL__status_polarity__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__status_polarity__normal 0
+#define R_SYNC_SERIAL1_CTRL__status_polarity__inverted 1
+#define R_SYNC_SERIAL1_CTRL__clk_driver__BITNR 3
+#define R_SYNC_SERIAL1_CTRL__clk_driver__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__clk_driver__normal 0
+#define R_SYNC_SERIAL1_CTRL__clk_driver__inverted 1
+#define R_SYNC_SERIAL1_CTRL__frame_driver__BITNR 2
+#define R_SYNC_SERIAL1_CTRL__frame_driver__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__frame_driver__normal 0
+#define R_SYNC_SERIAL1_CTRL__frame_driver__inverted 1
+#define R_SYNC_SERIAL1_CTRL__status_driver__BITNR 1
+#define R_SYNC_SERIAL1_CTRL__status_driver__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__status_driver__normal 0
+#define R_SYNC_SERIAL1_CTRL__status_driver__inverted 1
+#define R_SYNC_SERIAL1_CTRL__def_out0__BITNR 0
+#define R_SYNC_SERIAL1_CTRL__def_out0__WIDTH 1
+#define R_SYNC_SERIAL1_CTRL__def_out0__high 1
+#define R_SYNC_SERIAL1_CTRL__def_out0__low 0
+
+#define R_SYNC_SERIAL3_REC_DATA (IO_TYPECAST_RO_UDWORD 0xb000007c)
+#define R_SYNC_SERIAL3_REC_DATA__data_in__BITNR 0
+#define R_SYNC_SERIAL3_REC_DATA__data_in__WIDTH 32
+
+#define R_SYNC_SERIAL3_REC_WORD (IO_TYPECAST_RO_UWORD 0xb000007c)
+#define R_SYNC_SERIAL3_REC_WORD__data_in__BITNR 0
+#define R_SYNC_SERIAL3_REC_WORD__data_in__WIDTH 16
+
+#define R_SYNC_SERIAL3_REC_BYTE (IO_TYPECAST_RO_BYTE 0xb000007c)
+#define R_SYNC_SERIAL3_REC_BYTE__data_in__BITNR 0
+#define R_SYNC_SERIAL3_REC_BYTE__data_in__WIDTH 8
+
+#define R_SYNC_SERIAL3_STATUS (IO_TYPECAST_RO_UDWORD 0xb0000078)
+#define R_SYNC_SERIAL3_STATUS__rec_status__BITNR 15
+#define R_SYNC_SERIAL3_STATUS__rec_status__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__rec_status__running 0
+#define R_SYNC_SERIAL3_STATUS__rec_status__idle 1
+#define R_SYNC_SERIAL3_STATUS__tr_empty__BITNR 14
+#define R_SYNC_SERIAL3_STATUS__tr_empty__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__tr_empty__empty 1
+#define R_SYNC_SERIAL3_STATUS__tr_empty__not_empty 0
+#define R_SYNC_SERIAL3_STATUS__tr_ready__BITNR 13
+#define R_SYNC_SERIAL3_STATUS__tr_ready__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__tr_ready__full 0
+#define R_SYNC_SERIAL3_STATUS__tr_ready__ready 1
+#define R_SYNC_SERIAL3_STATUS__pin_1__BITNR 12
+#define R_SYNC_SERIAL3_STATUS__pin_1__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__pin_1__low 0
+#define R_SYNC_SERIAL3_STATUS__pin_1__high 1
+#define R_SYNC_SERIAL3_STATUS__pin_0__BITNR 11
+#define R_SYNC_SERIAL3_STATUS__pin_0__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__pin_0__low 0
+#define R_SYNC_SERIAL3_STATUS__pin_0__high 1
+#define R_SYNC_SERIAL3_STATUS__underflow__BITNR 10
+#define R_SYNC_SERIAL3_STATUS__underflow__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__underflow__no 0
+#define R_SYNC_SERIAL3_STATUS__underflow__yes 1
+#define R_SYNC_SERIAL3_STATUS__overrun__BITNR 9
+#define R_SYNC_SERIAL3_STATUS__overrun__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__overrun__no 0
+#define R_SYNC_SERIAL3_STATUS__overrun__yes 1
+#define R_SYNC_SERIAL3_STATUS__data_avail__BITNR 8
+#define R_SYNC_SERIAL3_STATUS__data_avail__WIDTH 1
+#define R_SYNC_SERIAL3_STATUS__data_avail__no 0
+#define R_SYNC_SERIAL3_STATUS__data_avail__yes 1
+#define R_SYNC_SERIAL3_STATUS__data__BITNR 0
+#define R_SYNC_SERIAL3_STATUS__data__WIDTH 8
+
+#define R_SYNC_SERIAL3_TR_DATA (IO_TYPECAST_UDWORD 0xb000007c)
+#define R_SYNC_SERIAL3_TR_DATA__data_out__BITNR 0
+#define R_SYNC_SERIAL3_TR_DATA__data_out__WIDTH 32
+
+#define R_SYNC_SERIAL3_TR_WORD (IO_TYPECAST_UWORD 0xb000007c)
+#define R_SYNC_SERIAL3_TR_WORD__data_out__BITNR 0
+#define R_SYNC_SERIAL3_TR_WORD__data_out__WIDTH 16
+
+#define R_SYNC_SERIAL3_TR_BYTE (IO_TYPECAST_BYTE 0xb000007c)
+#define R_SYNC_SERIAL3_TR_BYTE__data_out__BITNR 0
+#define R_SYNC_SERIAL3_TR_BYTE__data_out__WIDTH 8
+
+#define R_SYNC_SERIAL3_CTRL (IO_TYPECAST_UDWORD 0xb0000078)
+#define R_SYNC_SERIAL3_CTRL__tr_baud__BITNR 28
+#define R_SYNC_SERIAL3_CTRL__tr_baud__WIDTH 4
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c150Hz 0
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c300Hz 1
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c600Hz 2
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c1200Hz 3
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c2400Hz 4
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c4800Hz 5
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c9600Hz 6
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c19k2Hz 7
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c28k8Hz 8
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c57k6Hz 9
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c115k2Hz 10
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c230k4Hz 11
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c460k8Hz 12
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c921k6Hz 13
+#define R_SYNC_SERIAL3_CTRL__tr_baud__c3125kHz 14
+#define R_SYNC_SERIAL3_CTRL__tr_baud__reserved 15
+#define R_SYNC_SERIAL3_CTRL__dma_enable__BITNR 27
+#define R_SYNC_SERIAL3_CTRL__dma_enable__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__dma_enable__on 1
+#define R_SYNC_SERIAL3_CTRL__dma_enable__off 0
+#define R_SYNC_SERIAL3_CTRL__mode__BITNR 24
+#define R_SYNC_SERIAL3_CTRL__mode__WIDTH 3
+#define R_SYNC_SERIAL3_CTRL__mode__master_output 0
+#define R_SYNC_SERIAL3_CTRL__mode__slave_output 1
+#define R_SYNC_SERIAL3_CTRL__mode__master_input 2
+#define R_SYNC_SERIAL3_CTRL__mode__slave_input 3
+#define R_SYNC_SERIAL3_CTRL__mode__master_bidir 4
+#define R_SYNC_SERIAL3_CTRL__mode__slave_bidir 5
+#define R_SYNC_SERIAL3_CTRL__error__BITNR 23
+#define R_SYNC_SERIAL3_CTRL__error__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__error__normal 0
+#define R_SYNC_SERIAL3_CTRL__error__ignore 1
+#define R_SYNC_SERIAL3_CTRL__rec_enable__BITNR 22
+#define R_SYNC_SERIAL3_CTRL__rec_enable__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__rec_enable__disable 0
+#define R_SYNC_SERIAL3_CTRL__rec_enable__enable 1
+#define R_SYNC_SERIAL3_CTRL__f_synctype__BITNR 21
+#define R_SYNC_SERIAL3_CTRL__f_synctype__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__f_synctype__normal 0
+#define R_SYNC_SERIAL3_CTRL__f_synctype__early 1
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__BITNR 19
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__WIDTH 2
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__bit 0
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__word 1
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__extended 2
+#define R_SYNC_SERIAL3_CTRL__f_syncsize__reserved 3
+#define R_SYNC_SERIAL3_CTRL__f_sync__BITNR 18
+#define R_SYNC_SERIAL3_CTRL__f_sync__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__f_sync__on 0
+#define R_SYNC_SERIAL3_CTRL__f_sync__off 1
+#define R_SYNC_SERIAL3_CTRL__clk_mode__BITNR 17
+#define R_SYNC_SERIAL3_CTRL__clk_mode__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_mode__normal 0
+#define R_SYNC_SERIAL3_CTRL__clk_mode__gated 1
+#define R_SYNC_SERIAL3_CTRL__clk_halt__BITNR 16
+#define R_SYNC_SERIAL3_CTRL__clk_halt__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_halt__running 0
+#define R_SYNC_SERIAL3_CTRL__clk_halt__stopped 1
+#define R_SYNC_SERIAL3_CTRL__bitorder__BITNR 15
+#define R_SYNC_SERIAL3_CTRL__bitorder__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__bitorder__lsb 0
+#define R_SYNC_SERIAL3_CTRL__bitorder__msb 1
+#define R_SYNC_SERIAL3_CTRL__tr_enable__BITNR 14
+#define R_SYNC_SERIAL3_CTRL__tr_enable__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__tr_enable__disable 0
+#define R_SYNC_SERIAL3_CTRL__tr_enable__enable 1
+#define R_SYNC_SERIAL3_CTRL__wordsize__BITNR 11
+#define R_SYNC_SERIAL3_CTRL__wordsize__WIDTH 3
+#define R_SYNC_SERIAL3_CTRL__wordsize__size8bit 0
+#define R_SYNC_SERIAL3_CTRL__wordsize__size12bit 1
+#define R_SYNC_SERIAL3_CTRL__wordsize__size16bit 2
+#define R_SYNC_SERIAL3_CTRL__wordsize__size24bit 3
+#define R_SYNC_SERIAL3_CTRL__wordsize__size32bit 4
+#define R_SYNC_SERIAL3_CTRL__buf_empty__BITNR 10
+#define R_SYNC_SERIAL3_CTRL__buf_empty__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__buf_empty__lmt_8 0
+#define R_SYNC_SERIAL3_CTRL__buf_empty__lmt_0 1
+#define R_SYNC_SERIAL3_CTRL__buf_full__BITNR 9
+#define R_SYNC_SERIAL3_CTRL__buf_full__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__buf_full__lmt_32 0
+#define R_SYNC_SERIAL3_CTRL__buf_full__lmt_8 1
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__BITNR 8
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__disabled 0
+#define R_SYNC_SERIAL3_CTRL__flow_ctrl__enabled 1
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__BITNR 6
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__pos 0
+#define R_SYNC_SERIAL3_CTRL__clk_polarity__neg 1
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__BITNR 5
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__normal 0
+#define R_SYNC_SERIAL3_CTRL__frame_polarity__inverted 1
+#define R_SYNC_SERIAL3_CTRL__status_polarity__BITNR 4
+#define R_SYNC_SERIAL3_CTRL__status_polarity__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__status_polarity__normal 0
+#define R_SYNC_SERIAL3_CTRL__status_polarity__inverted 1
+#define R_SYNC_SERIAL3_CTRL__clk_driver__BITNR 3
+#define R_SYNC_SERIAL3_CTRL__clk_driver__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__clk_driver__normal 0
+#define R_SYNC_SERIAL3_CTRL__clk_driver__inverted 1
+#define R_SYNC_SERIAL3_CTRL__frame_driver__BITNR 2
+#define R_SYNC_SERIAL3_CTRL__frame_driver__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__frame_driver__normal 0
+#define R_SYNC_SERIAL3_CTRL__frame_driver__inverted 1
+#define R_SYNC_SERIAL3_CTRL__status_driver__BITNR 1
+#define R_SYNC_SERIAL3_CTRL__status_driver__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__status_driver__normal 0
+#define R_SYNC_SERIAL3_CTRL__status_driver__inverted 1
+#define R_SYNC_SERIAL3_CTRL__def_out0__BITNR 0
+#define R_SYNC_SERIAL3_CTRL__def_out0__WIDTH 1
+#define R_SYNC_SERIAL3_CTRL__def_out0__high 1
+#define R_SYNC_SERIAL3_CTRL__def_out0__low 0
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/sv_addr_ag.h linux/include/asm-cris/sv_addr_ag.h
--- v2.4.1/linux/include/asm-cris/sv_addr_ag.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/sv_addr_ag.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,129 @@
+/*!**************************************************************************
+*!                                                            
+*! MACROS:
+*!   IO_MASK(reg,field)
+*!   IO_STATE(reg,field,state)
+*!   IO_EXTRACT(reg,field,val)
+*!   IO_STATE_VALUE(reg,field,state)
+*!   IO_BITNR(reg,field)
+*!   IO_WIDTH(reg,field)
+*!   IO_FIELD(reg,field,val)
+*!   IO_RD(reg)
+*!   All moderegister addresses and fields of these.
+*!
+*!**************************************************************************/
+
+#ifndef __sv_addr_ag_h__
+#define __sv_addr_ag_h__
+
+
+#define __test_sv_addr__ 0
+
+/*------------------------------------------------------------
+!* General macros to manipulate moderegisters.
+!*-----------------------------------------------------------*/
+
+/* IO_MASK returns a mask for a specified bitfield in a register.
+   Note that this macro doesn't work when field width is 32 bits. */
+#define IO_MASK(reg,field) \
+    ( ( ( 1 << reg##__##field##__WIDTH ) - 1 ) << reg##__##field##__BITNR )
+
+/* IO_STATE returns a constant corresponding to a one of the symbolic
+   states that the bitfield can have. (Shifted to correct position)  */
+#define IO_STATE(reg,field,state) \
+    ( reg##__##field##__##state << reg##__##field##__BITNR )
+
+/* IO_EXTRACT returns the masked and shifted value corresponding to the
+   bitfield can have. */
+#define IO_EXTRACT(reg,field,val) ( (( ( ( 1 << reg##__##field##__WIDTH ) \
+     - 1 ) << reg##__##field##__BITNR ) & (val)) >> reg##__##field##__BITNR )
+
+/* IO_STATE_VALUE returns a constant corresponding to a one of the symbolic
+   states that the bitfield can have. (Not shifted)  */
+#define IO_STATE_VALUE(reg,field,state) ( reg##__##field##__##state )
+
+/* IO_FIELD shifts the val parameter to be aligned with the bitfield
+   specified. */
+#define IO_FIELD(reg,field,val) ((val) << reg##__##field##__BITNR)
+
+/* IO_BITNR returns the starting bitnumber of a bitfield. Bit 0 is
+   LSB and the returned bitnumber is LSB of the field. */
+#define IO_BITNR(reg,field) (reg##__##field##__BITNR)
+
+/* IO_WIDTH returns the width, in bits, of a bitfield. */
+#define IO_WIDTH(reg,field) (reg##__##field##__WIDTH)
+
+/*--- Obsolete. Kept for backw compatibility. ---*/
+/* Reads (or writes) a byte/uword/udword from the specified mode
+   register. */
+#define IO_RD(reg) (*(volatile u32*)(reg))
+#define IO_RD_B(reg) (*(volatile u8*)(reg))
+#define IO_RD_W(reg) (*(volatile u16*)(reg))
+#define IO_RD_D(reg) (*(volatile u32*)(reg))
+
+/*------------------------------------------------------------
+!* Start addresses of the different memory areas.
+!*-----------------------------------------------------------*/
+
+#define MEM_CSE0_START (0x00000000)
+#define MEM_CSE1_START (0x04000000)
+#define MEM_CSR0_START (0x08000000)
+#define MEM_CSR1_START (0x0c000000)
+#define MEM_CSP0_START (0x10000000)
+#define MEM_CSP1_START (0x14000000)
+#define MEM_CSP2_START (0x18000000)
+#define MEM_CSP3_START (0x1c000000)
+#define MEM_CSP4_START (0x20000000)
+#define MEM_CSP5_START (0x24000000)
+#define MEM_CSP6_START (0x28000000)
+#define MEM_CSP7_START (0x2c000000)
+#define MEM_DRAM_START (0x40000000)
+
+#define MEM_NON_CACHEABLE (0x80000000)
+
+/*------------------------------------------------------------
+!* Type casts used in mode register macros, making pointer
+!* dereferencing possible. Empty in assembler.
+!*-----------------------------------------------------------*/
+
+#ifndef __ASSEMBLER__
+# define  IO_TYPECAST_UDWORD  (volatile u32*)
+# define  IO_TYPECAST_RO_UDWORD  (const volatile u32*)
+# define  IO_TYPECAST_UWORD  (volatile u16*)
+# define  IO_TYPECAST_RO_UWORD  (const volatile u16*)
+# define  IO_TYPECAST_BYTE  (volatile u8*)
+# define  IO_TYPECAST_RO_BYTE  (const volatile u8*)
+#else
+# define  IO_TYPECAST_UDWORD
+# define  IO_TYPECAST_RO_UDWORD
+# define  IO_TYPECAST_UWORD
+# define  IO_TYPECAST_RO_UWORD
+# define  IO_TYPECAST_BYTE
+# define  IO_TYPECAST_RO_BYTE
+#endif
+
+/*------------------------------------------------------------*/
+
+#include "sv_addr.agh"
+
+#if __test_sv_addr__
+/* IO_MASK( R_BUS_CONFIG , CE ) */
+IO_MASK( R_WAITSTATES , SRAM_WS )
+IO_MASK( R_TEST , W32 )
+
+IO_STATE( R_BUS_CONFIG, CE, DISABLE )
+IO_STATE( R_BUS_CONFIG, CE, ENABLE )
+
+IO_STATE( R_DRAM_TIMING, REF, IVAL2 )
+
+IO_MASK( R_DRAM_TIMING, REF )
+
+IO_MASK( R_EXT_DMA_0_STAT, TFR_COUNT ) >> IO_BITNR( R_EXT_DMA_0_STAT, TFR_COUNT )
+
+IO_RD(R_EXT_DMA_0_STAT) & IO_MASK( R_EXT_DMA_0_STAT, S ) 
+   == IO_STATE( R_EXT_DMA_0_STAT, S, STARTED )
+#endif
+
+
+#endif  /* ifndef __sv_addr_ag_h__ */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/svinto.h linux/include/asm-cris/svinto.h
--- v2.4.1/linux/include/asm-cris/svinto.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/svinto.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,46 @@
+#ifndef _ASM_CRIS_SVINTO_H
+#define _ASM_CRIS_SVINTO_H
+
+#include "sv_addr_ag.h"
+
+extern unsigned int genconfig_shadow; /* defined and set in head.S */
+
+/* dma stuff */
+
+enum {                          /* Available in:  */
+	d_eol      = (1 << 0),  /* flags          */
+	d_eop      = (1 << 1),  /* flags & status */
+	d_wait     = (1 << 2),  /* flags          */
+	d_int      = (1 << 3),  /* flags          */
+	d_txerr    = (1 << 4),  /* flags          */
+	d_stop     = (1 << 4),  /*         status */
+	d_ecp      = (1 << 4),  /* flags & status */
+	d_pri      = (1 << 5),  /* flags & status */
+	d_alignerr = (1 << 6),  /*         status */
+	d_crcerr   = (1 << 7)   /*         status */
+};
+
+/* Do remember that DMA does not go through the MMU and needs
+ * a real physical address, not an address virtually mapped or
+ * paged. Therefore the buf/next ptrs below are unsigned long instead
+ * of void * to give a warning if you try to put a pointer directly
+ * to them instead of going through virt_to_phys/phys_to_virt.
+ */
+
+typedef struct etrax_dma_descr {
+	unsigned short sw_len;                /* 0-1 */
+	unsigned short ctrl;                  /* 2-3 */
+	unsigned long  next;                  /* 4-7 */
+	unsigned long  buf;                   /* 8-11 */
+	unsigned short hw_len;                /* 12-13 */
+	unsigned short status;                /* 14-15 */
+} etrax_dma_descr;
+
+#define RESET_DMA( n ) \
+  *R_DMA_CH##n##_CMD = IO_STATE( R_DMA_CH0_CMD, cmd, reset )
+
+#define WAIT_DMA( n ) \
+  while( (*R_DMA_CH##n##_CMD & IO_MASK( R_DMA_CH0_CMD, cmd )) != \
+         IO_STATE( R_DMA_CH0_CMD, cmd, hold ) )
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/system.h linux/include/asm-cris/system.h
--- v2.4.1/linux/include/asm-cris/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/system.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,170 @@
+/* $Id: system.h,v 1.3 2000/10/17 14:56:27 bjornw Exp $ */
+
+#ifndef __ASM_CRIS_SYSTEM_H
+#define __ASM_CRIS_SYSTEM_H
+
+#include <asm/segment.h>
+
+/* I need a task-specific debug struct (and the define for #ifdef
+   RELOC_DEBUG) to kludge into task_struct. */
+#include <linux/config.h>
+#include <asm/eshlibld.h>
+
+/* the switch_to macro calls resume, an asm function in entry.S which does the actual
+ * task switching.
+ */
+
+extern struct task_struct *resume(struct task_struct *prev, struct task_struct *next, int);
+#define prepare_to_switch()     do { } while(0)
+#define switch_to(prev,next,last) last = resume(prev,next, \
+					 (int)&((struct task_struct *)0)->thread)
+
+/* read/write the user-mode stackpointer */
+
+extern inline unsigned long rdusp(void) {
+	unsigned long usp;
+	__asm__ __volatile__("move usp,%0" : "=rm" (usp));
+	return usp;
+}
+
+#define wrusp(usp) \
+	__asm__ __volatile__("move %0,usp" : /* no outputs */ : "rm" (usp))
+
+/* read the current stackpointer */
+
+extern inline unsigned long rdsp(void) {
+	unsigned long sp;
+	__asm__ __volatile__("move.d sp,%0" : "=rm" (sp));
+	return sp;
+}
+
+static inline unsigned long _get_base(char * addr)
+{
+  return 0;
+}
+
+#define nop() __asm__ __volatile__ ("nop");
+
+#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
+#define tas(ptr) (xchg((ptr),1))
+
+struct __xchg_dummy { unsigned long a[100]; };
+#define __xg(x) ((struct __xchg_dummy *)(x))
+
+#if 0
+/* use these and an oscilloscope to see the fraction of time we're running with IRQ's disabled */
+/* it assumes the LED's are on port 0x90000000 of course. */
+#define sti() __asm__ __volatile__ ( "ei\n\tpush r0\n\tmoveq 0,r0\n\tmove.d r0,[0x90000000]\n\tpop r0" );
+#define cli() __asm__ __volatile__ ( "di\n\tpush r0\n\tmove.d 0x40000,r0\n\tmove.d r0,[0x90000000]\n\tpop r0");
+#define save_flags(x) __asm__ __volatile__ ("move ccr,%0" : "=rm" (x) : : "memory");
+#define restore_flags(x) __asm__ __volatile__ ("move %0,ccr\n\tbtstq 5,%0\n\tbpl 1f\n\tnop\n\tpush r0\n\tmoveq 0,r0\n\tmove.d r0,[0x90000000]\n\tpop r0\n1:\n" : : "r" (x) : "memory");
+#else
+#define __cli() __asm__ __volatile__ ( "di");
+#define __sti() __asm__ __volatile__ ( "ei" );
+#define __save_flags(x) __asm__ __volatile__ ("move ccr,%0" : "=rm" (x) : : "memory");
+#define __restore_flags(x) __asm__ __volatile__ ("move %0,ccr" : : "rm" (x) : "memory");
+
+/* For spinlocks etc */
+#define local_irq_save(x) __asm__ __volatile__ ("move ccr,%0\n\tdi" : "=rm" (x) : : "memory"); 
+#define local_irq_restore(x) restore_flags(x)
+
+#define local_irq_disable()  cli()
+#define local_irq_enable()   sti()
+
+#endif
+
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define restore_flags(x) __restore_flags(x)
+#define save_and_cli(x) do { __save_flags(x); cli(); } while(0)
+
+static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+{
+  /* since Etrax doesn't have any atomic xchg instructions, we need to disable
+     irq's (if enabled) and do it with move.d's */
+#if 0
+  unsigned int flags;
+  save_flags(flags); /* save flags, including irq enable bit */
+  cli();             /* shut off irq's */
+  switch (size) {
+  case 1:
+    __asm__ __volatile__ (
+       "move.b %0,r0\n\t"
+       "move.b %1,%0\n\t"
+       "move.b r0,%1\n\t"
+       : "=r" (x)
+       : "m" (*__xg(ptr)), "r" (x)
+       : "memory","r0");    
+    break;
+  case 2:
+    __asm__ __volatile__ (
+       "move.w %0,r0\n\t"
+       "move.w %1,%0\n\t"
+       "move.w r0,%1\n\t"
+       : "=r" (x)
+       : "m" (*__xg(ptr)), "r" (x)
+       : "memory","r0");
+    break;
+  case 4:
+    __asm__ __volatile__ (
+       "move.d %0,r0\n\t"
+       "move.d %1,%0\n\t"
+       "move.d r0,%1\n\t"
+       : "=r" (x)
+       : "m" (*__xg(ptr)), "r" (x)
+       : "memory","r0");
+    break;
+  }
+  restore_flags(flags); /* restore irq enable bit */
+  return x;
+#else
+  unsigned long flags,temp;
+  save_flags(flags); /* save flags, including irq enable bit */
+  cli();             /* shut off irq's */
+  switch (size) {
+  case 1:
+    *((unsigned char *)&temp) = x;
+    x = *(unsigned char *)ptr;
+    *(unsigned char *)ptr = *((unsigned char *)&temp);
+    break;
+  case 2:
+    *((unsigned short *)&temp) = x;
+    x = *(unsigned short *)ptr;
+    *(unsigned short *)ptr = *((unsigned short *)&temp);
+    break;
+  case 4:
+    temp = x;
+    x = *(unsigned long *)ptr;
+    *(unsigned long *)ptr = temp;
+    break;
+  }
+  restore_flags(flags); /* restore irq enable bit */
+  return x;
+#endif
+}
+
+#define mb() __asm__ __volatile__ ("" : : : "memory")
+#define rmb() mb()
+#define wmb() mb()
+
+#ifdef CONFIG_SMP
+#define smp_mb()        mb()
+#define smp_rmb()       rmb()
+#define smp_wmb()       wmb()
+#else
+#define smp_mb()        barrier()
+#define smp_rmb()       barrier()
+#define smp_wmb()       barrier()
+#endif
+
+#define iret()
+
+/*
+ * disable hlt during certain critical i/o operations
+ */
+#define HAVE_DISABLE_HLT
+void disable_hlt(void);
+void enable_hlt(void);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/termbits.h linux/include/asm-cris/termbits.h
--- v2.4.1/linux/include/asm-cris/termbits.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/termbits.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,166 @@
+/* $Id: termbits.h,v 1.1 2000/07/10 16:32:31 bjornw Exp $ */
+
+#ifndef __ARCH_ETRAX100_TERMBITS_H__
+#define __ARCH_ETRAX100_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define  B57600  0010001
+#define  B115200 0010002
+#define  B230400 0010003
+#define  B460800 0010004
+/* etrax100 supports these additional three baud rates */
+#define  B921600 0010005
+#define  B1843200 0010006
+#define  B6250000 0010007
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/termios.h linux/include/asm-cris/termios.h
--- v2.4.1/linux/include/asm-cris/termios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/termios.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,106 @@
+#ifndef _CRIS_TERMIOS_H
+#define _CRIS_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP	0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC		13	/* synchronous HDLC */
+#define N_SYNC_PPP	14	/* synchronous PPP */
+#define N_BT		15	/* bluetooth */
+
+#ifdef __KERNEL__
+
+/*	intr=^C		quit=^\		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
+	unsigned short __tmp; \
+	get_user(__tmp,&(termio)->x); \
+	*(unsigned short *) &(termios)->x = __tmp; \
+}
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
+	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+	put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	put_user((termios)->c_line,  &(termio)->c_line); \
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _CRIS_TERMIOS_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/timex.h linux/include/asm-cris/timex.h
--- v2.4.1/linux/include/asm-cris/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/timex.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,23 @@
+/*
+ * linux/include/asm-cris/timex.h
+ *
+ * CRIS architecture timex specifications
+ */
+#ifndef _ASM_CRIS_TIMEX_H
+#define _ASM_CRIS_TIMEX_H
+
+#define CLOCK_TICK_RATE 9600 /* Underlying frequency of the HZ timer */
+
+/*
+ * We don't have a cycle-counter.. but we do not support SMP anyway where this is
+ * used so it does not matter.
+ */
+
+typedef unsigned int cycles_t;
+
+static inline cycles_t get_cycles(void)
+{
+        return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/types.h linux/include/asm-cris/types.h
--- v2.4.1/linux/include/asm-cris/types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/types.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,50 @@
+#ifndef _ETRAX_TYPES_H
+#define _ETRAX_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide, just like our other addresses.  */
+ 
+typedef u32 dma_addr_t;
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/uaccess.h linux/include/asm-cris/uaccess.h
--- v2.4.1/linux/include/asm-cris/uaccess.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/uaccess.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,1075 @@
+/* 
+ * Authors:    Bjorn Wesen (bjornw@axis.com)
+ *	       Hans-Peter Nilsson (hp@axis.com)
+ *
+ * $Log: uaccess.h,v $
+ * Revision 1.5  2000/10/25 03:33:21  hp
+ * - Provide implementation for everything else but get_user and put_user;
+ *   copying inline to/from user for constant length 0..16, 20, 24, and
+ *   clearing for 0..4, 8, 12, 16, 20, 24, strncpy_from_user and strnlen_user
+ *   always inline.
+ * - Constraints for destination addr in get_user cannot be memory, only reg.
+ * - Correct labels for PC at expected fault points.
+ * - Nits with assembly code.
+ * - Don't use statement expressions without value; use "do {} while (0)".
+ * - Return correct values from __generic_... functions.
+ *
+ * Revision 1.4  2000/09/12 16:28:25  bjornw
+ * * Removed comments from the get/put user asm code
+ * * Constrains for destination addr in put_user cannot be memory, only reg
+ *
+ * Revision 1.3  2000/09/12 14:30:20  bjornw
+ * MAX_ADDR_USER does not exist anymore
+ *
+ * Revision 1.2  2000/07/13 15:52:48  bjornw
+ * New user-access functions
+ *
+ * Revision 1.1.1.1  2000/07/10 16:32:31  bjornw
+ * CRIS architecture, working draft
+ *
+ *
+ *
+ */
+
+/* Asm:s have been tweaked (within the domain of correctness) to give
+   satisfactory results for "gcc version 2.96 20000427 (experimental)".
+
+   Check regularly...
+
+   Register r9 is chosen for temporaries, being a call-clobbered register
+   first in line to be used (notably for local blocks), not colliding with
+   parameter registers.  */
+
+#ifndef _CRIS_UACCESS_H
+#define _CRIS_UACCESS_H
+
+#ifndef __ASSEMBLY__
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <asm/processor.h>
+#include <asm/page.h>
+
+#define VERIFY_READ	0
+#define VERIFY_WRITE	1
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+/* addr_limit is the maximum accessible address for the task. we misuse
+ * the KERNEL_DS and USER_DS values to both assign and compare the 
+ * addr_limit values through the equally misnamed get/set_fs macros.
+ * (see above)
+ */
+
+#define KERNEL_DS	MAKE_MM_SEG(0xFFFFFFFF)
+#define USER_DS		MAKE_MM_SEG(TASK_SIZE)
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current->addr_limit)
+#define set_fs(x)	(current->addr_limit = (x))
+
+#define segment_eq(a,b)	((a).seg == (b).seg)
+
+#define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
+#define __user_ok(addr,size) (((size) <= TASK_SIZE)&&((addr) <= TASK_SIZE-(size)))
+#define __access_ok(addr,size) (__kernel_ok || __user_ok((addr),(size)))
+#define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+	return access_ok(type,addr,size) ? 0 : -EFAULT;
+}
+
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+	unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ *
+ * This gets kind of ugly. We want to return _two_ values in "get_user()"
+ * and yet we don't want to do any pointers, because that is too much
+ * of a performance impact. Thus we have a few rather ugly macros here,
+ * and hide all the uglyness from the user.
+ *
+ * The "__xxx" versions of the user access functions are versions that
+ * do not verify the address space, that must have been done previously
+ * with a separate "access_ok()" call (this is used when we do multiple
+ * accesses to the same area of user memory).
+ *
+ * As we use the same address space for kernel and user data on
+ * CRIS, we can just do these as direct assignments.  (Of course, the
+ * exception handling means that it's no longer "just"...)
+ */
+#define get_user(x,ptr) \
+  __get_user_check((x),(ptr),sizeof(*(ptr)))
+#define put_user(x,ptr) \
+  __put_user_check((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+#define __get_user(x,ptr) \
+  __get_user_nocheck((x),(ptr),sizeof(*(ptr)))
+#define __put_user(x,ptr) \
+  __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr)))
+
+/*
+ * The "xxx_ret" versions return constant specified in third argument, if
+ * something bad happens. These macros can be optimized for the
+ * case of just returning from the function xxx_ret is used.
+ */
+
+#define put_user_ret(x,ptr,ret) \
+	do { if (put_user(x,ptr)) return ret; } while (0)
+
+#define get_user_ret(x,ptr,ret) \
+	do { if (get_user(x,ptr)) return ret; } while (0)
+
+#define __put_user_ret(x,ptr,ret) \
+	do { if (__put_user(x,ptr)) return ret; } while (0)
+
+#define __get_user_ret(x,ptr,ret) \
+	do { if (__get_user(x,ptr)) return ret; } while (0)
+
+
+extern long __put_user_bad(void);
+
+#define __put_user_nocheck(x,ptr,size)			\
+({							\
+	long __pu_err;					\
+	__put_user_size((x),(ptr),(size),__pu_err);	\
+	__pu_err;					\
+})
+
+#define __put_user_check(x,ptr,size)				\
+({								\
+	long __pu_err = -EFAULT;				\
+	__typeof__(*(ptr)) *__pu_addr = (ptr);			\
+	if (access_ok(VERIFY_WRITE,__pu_addr,size))		\
+		__put_user_size((x),__pu_addr,(size),__pu_err);	\
+	__pu_err;						\
+})
+
+#define __put_user_size(x,ptr,size,retval)			\
+do {								\
+	retval = 0;						\
+	switch (size) {						\
+	  case 1: __put_user_asm(x,ptr,retval,"move.b"); break;	\
+	  case 2: __put_user_asm(x,ptr,retval,"move.w"); break;	\
+	  case 4: __put_user_asm(x,ptr,retval,"move.d"); break;	\
+	  default: __put_user_bad();				\
+	}							\
+} while (0)
+
+struct __large_struct { unsigned long buf[100]; };
+#define __m(x) (*(struct __large_struct *)(x))
+
+/*
+ * We don't tell gcc that we are accessing memory, but this is OK
+ * because we do not write to any memory gcc knows about, so there
+ * are no aliasing issues.
+ *
+ * Note that PC at a fault is the address *after* the faulting
+ * instruction.
+ */
+#define __put_user_asm(x, addr, err, op)			\
+	__asm__ __volatile__(					\
+		"	"op" %1,[%2]\n"				\
+		"2:\n"						\
+		"	.section .fixup,\"ax\"\n"		\
+		"3:	move.d %3,%0\n"				\
+		"	jump 2b\n"				\
+		"	.previous\n"				\
+		"	.section __ex_table,\"a\"\n"		\
+		"	.dword 2b,3b\n"				\
+		"	.previous\n"				\
+		: "=r" (err)					\
+		: "r" (x), "r" (addr), "g" (-EFAULT), "0" (err))
+
+
+#define __get_user_nocheck(x,ptr,size)				\
+({								\
+	long __gu_err, __gu_val;				\
+	__get_user_size(__gu_val,(ptr),(size),__gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;			\
+	__gu_err;						\
+})
+
+#define __get_user_check(x,ptr,size)					\
+({									\
+	long __gu_err = -EFAULT, __gu_val = 0;				\
+	const __typeof__(*(ptr)) *__gu_addr = (ptr);			\
+	if (access_ok(VERIFY_READ,__gu_addr,size))			\
+		__get_user_size(__gu_val,__gu_addr,(size),__gu_err);	\
+	(x) = (__typeof__(*(ptr)))__gu_val;				\
+	__gu_err;							\
+})
+
+extern long __get_user_bad(void);
+
+#define __get_user_size(x,ptr,size,retval)			\
+do {								\
+	retval = 0;						\
+	switch (size) {						\
+	  case 1: __get_user_asm(x,ptr,retval,"move.b"); break;	\
+	  case 2: __get_user_asm(x,ptr,retval,"move.w"); break;	\
+	  case 4: __get_user_asm(x,ptr,retval,"move.d"); break;	\
+	  default: (x) = __get_user_bad();			\
+	}							\
+} while (0)
+
+/* See comment before __put_user_asm.  */
+
+#define __get_user_asm(x, addr, err, op)		\
+	__asm__ __volatile__(				\
+		"	"op" [%2],%1\n"			\
+		"2:\n"					\
+		"	.section .fixup,\"ax\"\n"	\
+		"3:	move.d %3,%0\n"			\
+		"	moveq 0,%1\n"			\
+		"	jump 2b\n"			\
+		"	.previous\n"			\
+		"	.section __ex_table,\"a\"\n"	\
+		"	.dword 2b,3b\n"			\
+		"	.previous\n"			\
+		: "=r" (err), "=r" (x)			\
+		: "r" (addr), "g" (-EFAULT), "0" (err))
+
+/* More complex functions.  Most are inline, but some call functions that
+   live in lib/usercopy.c  */
+
+extern unsigned long __copy_user(void *to, const void *from, unsigned long n);
+extern unsigned long __copy_user_zeroing(void *to, const void *from, unsigned long n);
+extern unsigned long __do_clear_user(void *to, unsigned long n);
+
+/*
+ * Copy a null terminated string from userspace.
+ *
+ * Must return:
+ * -EFAULT		for an exception
+ * count		if we hit the buffer limit
+ * bytes copied		if we hit a null byte
+ * (without the null byte)
+ */
+
+static inline long         
+__do_strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res;
+
+	if (count == 0)
+		return 0;
+
+	/*
+	 * Currently, in 2.4.0-test9, most ports use a simple byte-copy loop.
+	 *  So do we.
+	 *
+	 *  This code is deduced from:
+	 *
+	 *	char tmp2;
+	 *	long tmp1, tmp3	
+	 *	tmp1 = count;
+	 *	while ((*dst++ = (tmp2 = *src++)) != 0
+	 *	       && --tmp1)
+	 *	  ;
+	 *
+	 *	res = count - tmp1;
+	 *
+	 *  with tweaks.
+	 */
+
+	__asm__ __volatile__ (
+		"	move.d %3,%0\n"
+		"	move.b [%2+],r9\n"
+		"1:	beq 2f\n"
+		"	move.b r9,[%1+]\n"
+
+		"	subq 1,%0\n"
+		"	bne 1b\n"
+		"	move.b [%2+],r9\n"
+
+		"2:	sub.d %3,%0\n"
+		"	neg.d %0,%0\n"
+		"3:\n"
+		"	.section .fixup,\"ax\"\n"
+		"4:	move.d %7,%0\n"
+		"	jump 3b\n"
+
+		/* There's one address for a fault at the first move, and
+		   two possible PC values for a fault at the second move,
+		   being a delay-slot filler.  However, the branch-target
+		   for the second move is the same as the first address.
+		   Just so you don't get confused...  */
+		"	.previous\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.dword 1b,4b\n"
+		"	.dword 2b,4b\n"
+		"	.previous"
+		: "=r" (res), "=r" (dst), "=r" (src), "=r" (count)
+		: "3" (count), "1" (dst), "2" (src), "g" (-EFAULT)
+		: "r9");
+
+	return res;
+}
+
+static inline unsigned long
+__generic_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		return __copy_user(to,from,n);
+	return n;
+}
+
+static inline unsigned long
+__generic_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	if (access_ok(VERIFY_READ, from, n))
+		return __copy_user_zeroing(to,from,n);
+	return n;
+}
+
+static inline unsigned long
+__generic_clear_user(void *to, unsigned long n)
+{
+	if (access_ok(VERIFY_WRITE, to, n))
+		return __do_clear_user(to,n);
+	return n;
+}
+
+static inline long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+	return __do_strncpy_from_user(dst, src, count);
+}
+
+static inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+	long res = -EFAULT;
+	if (access_ok(VERIFY_READ, src, 1))
+		res = __do_strncpy_from_user(dst, src, count);
+	return res;
+}
+
+/* A few copy asms to build up the more complex ones from.
+
+   Note again, a post-increment is performed regardless of whether a bus
+   fault occurred in that instruction, and PC for a faulted insn is the
+   address *after* the insn.  */
+
+#define __asm_copy_user_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm__ __volatile__ (				\
+			COPY				\
+		"1:\n"					\
+		"	.section .fixup,\"ax\"\n"	\
+			FIXUP				\
+		"	jump 1b\n"			\
+		"	.previous\n"			\
+		"	.section __ex_table,\"a\"\n"	\
+			TENTRY				\
+		"	.previous\n"			\
+		: "=r" (to), "=r" (from), "=r" (ret)	\
+		: "0" (to), "1" (from), "2" (ret)	\
+		: "r9", "memory")
+
+#define __asm_copy_from_user_1(to, from, ret) \
+	__asm_copy_user_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"	\
+		"2:	move.b r9,[%0+]\n",	\
+		"3:	addq 1,%2\n"		\
+		"	clear.b [%0+]\n",	\
+		"	.dword 2b,3b\n")
+
+#define __asm_copy_from_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_user_cont(to, from, ret,		\
+		"	move.w [%1+],r9\n"		\
+		"2:	move.w r9,[%0+]\n" COPY,	\
+		"3:	addq 2,%2\n"			\
+		"	clear.w [%0+]\n" FIXUP,		\
+		"	.dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_from_user_2(to, from, ret) \
+	__asm_copy_from_user_2x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_3(to, from, ret)		\
+	__asm_copy_from_user_2x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"4:	move.b r9,[%0+]\n",		\
+		"5:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 4b,5b\n")
+
+#define __asm_copy_from_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_user_cont(to, from, ret,		\
+		"	move.d [%1+],r9\n"		\
+		"2:	move.d r9,[%0+]\n" COPY,	\
+		"3:	addq 4,%2\n"			\
+		"	clear.d [%0+]\n" FIXUP,		\
+		"	.dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_from_user_4(to, from, ret) \
+	__asm_copy_from_user_4x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_5(to, from, ret) \
+	__asm_copy_from_user_4x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"4:	move.b r9,[%0+]\n",		\
+		"5:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 4b,5b\n")
+
+#define __asm_copy_from_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_4x_cont(to, from, ret,	\
+		"	move.w [%1+],r9\n"		\
+		"4:	move.w r9,[%0+]\n" COPY,	\
+		"5:	addq 2,%2\n"			\
+		"	clear.w [%0+]\n" FIXUP,		\
+		"	.dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_from_user_6(to, from, ret) \
+	__asm_copy_from_user_6x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_7(to, from, ret) \
+	__asm_copy_from_user_6x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"6:	move.b r9,[%0+]\n",		\
+		"7:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 6b,7b\n")
+
+#define __asm_copy_from_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_4x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"4:	move.d r9,[%0+]\n" COPY,	\
+		"5:	addq 4,%2\n"			\
+		"	clear.d [%0+]\n" FIXUP,		\
+		"	.dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_from_user_8(to, from, ret) \
+	__asm_copy_from_user_8x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_9(to, from, ret) \
+	__asm_copy_from_user_8x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"6:	move.b r9,[%0+]\n",		\
+		"7:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 6b,7b\n")
+
+#define __asm_copy_from_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_8x_cont(to, from, ret,	\
+		"	move.w [%1+],r9\n"		\
+		"6:	move.w r9,[%0+]\n" COPY,	\
+		"7:	addq 2,%2\n"			\
+		"	clear.w [%0+]\n" FIXUP,		\
+		"	.dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_from_user_10(to, from, ret) \
+	__asm_copy_from_user_10x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_11(to, from, ret)		\
+	__asm_copy_from_user_10x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"8:	move.b r9,[%0+]\n",		\
+		"9:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 8b,9b\n")
+
+#define __asm_copy_from_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_8x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"6:	move.d r9,[%0+]\n" COPY,	\
+		"7:	addq 4,%2\n"			\
+		"	clear.d [%0+]\n" FIXUP,		\
+		"	.dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_from_user_12(to, from, ret) \
+	__asm_copy_from_user_12x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_13(to, from, ret) \
+	__asm_copy_from_user_12x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"8:	move.b r9,[%0+]\n",		\
+		"9:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 8b,9b\n")
+
+#define __asm_copy_from_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_12x_cont(to, from, ret,	\
+		"	move.w [%1+],r9\n"		\
+		"8:	move.w r9,[%0+]\n" COPY,	\
+		"9:	addq 2,%2\n"			\
+		"	clear.w [%0+]\n" FIXUP,		\
+		"	.dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_from_user_14(to, from, ret) \
+	__asm_copy_from_user_14x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_15(to, from, ret) \
+	__asm_copy_from_user_14x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"10:	move.b r9,[%0+]\n",		\
+		"11:	addq 1,%2\n"			\
+		"	clear.b [%0+]\n",		\
+		"	.dword 10b,11b\n")
+
+#define __asm_copy_from_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_12x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"8:	move.d r9,[%0+]\n" COPY,	\
+		"9:	addq 4,%2\n"			\
+		"	clear.d [%0+]\n" FIXUP,		\
+		"	.dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_from_user_16(to, from, ret) \
+	__asm_copy_from_user_16x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_16x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"10:	move.d r9,[%0+]\n" COPY,	\
+		"11:	addq 4,%2\n"			\
+		"	clear.d [%0+]\n" FIXUP,		\
+		"	.dword 10b,11b\n" TENTRY)
+
+#define __asm_copy_from_user_20(to, from, ret) \
+	__asm_copy_from_user_20x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_from_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_from_user_20x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"12:	move.d r9,[%0+]\n" COPY,	\
+		"13:	addq 4,%2\n"			\
+		"	clear.d [%0+]\n" FIXUP,		\
+		"	.dword 12b,13b\n" TENTRY)
+
+#define __asm_copy_from_user_24(to, from, ret) \
+	__asm_copy_from_user_24x_cont(to, from, ret, "", "", "")
+
+/* And now, the to-user ones.  */
+
+#define __asm_copy_to_user_1(to, from, ret)	\
+	__asm_copy_user_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"	\
+		"	move.b r9,[%0+]\n2:\n",	\
+		"3:	addq 1,%2\n",		\
+		"	.dword 2b,3b\n")
+
+#define __asm_copy_to_user_2x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_user_cont(to, from, ret,		\
+		"	move.w [%1+],r9\n"		\
+		"	move.w r9,[%0+]\n2:\n" COPY,	\
+		"3:	addq 2,%2\n" FIXUP,		\
+		"	.dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_to_user_2(to, from, ret) \
+	__asm_copy_to_user_2x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_3(to, from, ret) \
+	__asm_copy_to_user_2x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n4:\n",		\
+		"5:	addq 1,%2\n",			\
+		"	.dword 4b,5b\n")
+
+#define __asm_copy_to_user_4x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_user_cont(to, from, ret,		\
+		"	move.d [%1+],r9\n"		\
+		"	move.d r9,[%0+]\n2:\n" COPY,	\
+		"3:	addq 4,%2\n" FIXUP,		\
+		"	.dword 2b,3b\n" TENTRY)
+
+#define __asm_copy_to_user_4(to, from, ret) \
+	__asm_copy_to_user_4x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_5(to, from, ret) \
+	__asm_copy_to_user_4x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n4:\n",		\
+		"5:	addq 1,%2\n",			\
+		"	.dword 4b,5b\n")
+
+#define __asm_copy_to_user_6x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_4x_cont(to, from, ret,	\
+		"	move.w [%1+],r9\n"		\
+		"	move.w r9,[%0+]\n4:\n" COPY,	\
+		"5:	addq 2,%2\n" FIXUP,		\
+		"	.dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_to_user_6(to, from, ret) \
+	__asm_copy_to_user_6x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_7(to, from, ret) \
+	__asm_copy_to_user_6x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n6:\n",		\
+		"7:	addq 1,%2\n",			\
+		"	.dword 6b,7b\n")
+
+#define __asm_copy_to_user_8x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_4x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"	move.d r9,[%0+]\n4:\n" COPY,	\
+		"5:	addq 4,%2\n"  FIXUP,		\
+		"	.dword 4b,5b\n" TENTRY)
+
+#define __asm_copy_to_user_8(to, from, ret) \
+	__asm_copy_to_user_8x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_9(to, from, ret) \
+	__asm_copy_to_user_8x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n6:\n",		\
+		"7:	addq 1,%2\n",			\
+		"	.dword 6b,7b\n")
+
+#define __asm_copy_to_user_10x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_8x_cont(to, from, ret,	\
+		"	move.w [%1+],r9\n"		\
+		"	move.w r9,[%0+]\n6:\n" COPY,	\
+		"7:	addq 2,%2\n" FIXUP,		\
+		"	.dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_to_user_10(to, from, ret) \
+	__asm_copy_to_user_10x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_11(to, from, ret) \
+	__asm_copy_to_user_10x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n8:\n",		\
+		"9:	addq 1,%2\n",			\
+		"	.dword 8b,9b\n")
+
+#define __asm_copy_to_user_12x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_8x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"	move.d r9,[%0+]\n6:\n" COPY,	\
+		"7:	addq 4,%2\n" FIXUP,		\
+		"	.dword 6b,7b\n" TENTRY)
+
+#define __asm_copy_to_user_12(to, from, ret) \
+	__asm_copy_to_user_12x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_13(to, from, ret) \
+	__asm_copy_to_user_12x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n8:\n",		\
+		"9:	addq 1,%2\n",			\
+		"	.dword 8b,9b\n")
+
+#define __asm_copy_to_user_14x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_12x_cont(to, from, ret,	\
+		"	move.w [%1+],r9\n"		\
+		"	move.w r9,[%0+]\n8:\n" COPY,	\
+		"9:	addq 2,%2\n" FIXUP,		\
+		"	.dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_to_user_14(to, from, ret)	\
+	__asm_copy_to_user_14x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_15(to, from, ret) \
+	__asm_copy_to_user_14x_cont(to, from, ret,	\
+		"	move.b [%1+],r9\n"		\
+		"	move.b r9,[%0+]\n10:\n",		\
+		"11:	addq 1,%2\n",			\
+		"	.dword 10b,11b\n")
+
+#define __asm_copy_to_user_16x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_12x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"	move.d r9,[%0+]\n8:\n" COPY,	\
+		"9:	addq 4,%2\n" FIXUP,		\
+		"	.dword 8b,9b\n" TENTRY)
+
+#define __asm_copy_to_user_16(to, from, ret) \
+	__asm_copy_to_user_16x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_20x_cont(to, from, ret, COPY, FIXUP, TENTRY) \
+	__asm_copy_to_user_16x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"	move.d r9,[%0+]\n10:\n" COPY,	\
+		"11:	addq 4,%2\n" FIXUP,		\
+		"	.dword 10b,11b\n" TENTRY)
+
+#define __asm_copy_to_user_20(to, from, ret) \
+	__asm_copy_to_user_20x_cont(to, from, ret, "", "", "")
+
+#define __asm_copy_to_user_24x_cont(to, from, ret, COPY, FIXUP, TENTRY)	\
+	__asm_copy_to_user_20x_cont(to, from, ret,	\
+		"	move.d [%1+],r9\n"		\
+		"	move.d r9,[%0+]\n12:\n" COPY,	\
+		"13:	addq 4,%2\n" FIXUP,		\
+		"	.dword 12b,13b\n" TENTRY)
+
+#define __asm_copy_to_user_24(to, from, ret)	\
+	__asm_copy_to_user_24x_cont(to, from, ret, "", "", "")
+
+/* Define a few clearing asms with exception handlers.  */
+
+/* This frame-asm is like the __asm_copy_user_cont one, but has one less
+   input.  */
+
+#define __asm_clear(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm__ __volatile__ (				\
+			CLEAR				\
+		"1:\n"					\
+		"	.section .fixup,\"ax\"\n"	\
+			FIXUP				\
+		"	jump 1b\n"			\
+		"	.previous\n"			\
+		"	.section __ex_table,\"a\"\n"	\
+			TENTRY				\
+		"	.previous"			\
+		: "=r" (to), "=r" (ret)			\
+		: "0" (to), "1" (ret)			\
+		: "r9", "memory")
+
+#define __asm_clear_1(to, ret) \
+	__asm_clear(to, ret,			\
+		"	clear.b [%0+]\n2:\n",	\
+		"3:	addq 1,%1\n",		\
+		"	.dword 2b,3b\n")
+
+#define __asm_clear_2(to, ret) \
+	__asm_clear(to, ret,			\
+		"	clear.w [%0+]\n2:\n",	\
+		"3:	addq 2,%1\n",		\
+		"	.dword 2b,3b\n")
+
+#define __asm_clear_3(to, ret) \
+     __asm_clear(to, ret,			\
+		 "	clear.w [%0+]\n"	\
+		 "2:	clear.b [%0+]\n3:\n",	\
+		 "4:	addq 2,%1\n"		\
+		 "5:	addq 1,%1\n",		\
+		 "	.dword 2b,4b\n"		\
+		 "	.dword 3b,5b\n")
+
+#define __asm_clear_4x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm_clear(to, ret,				\
+		"	clear.d [%0+]\n2:\n" CLEAR,	\
+		"3:	addq 4,%1\n" FIXUP,		\
+		"	.dword 2b,3b\n" TENTRY)
+
+#define __asm_clear_4(to, ret) \
+	__asm_clear_4x_cont(to, ret, "", "", "")
+
+#define __asm_clear_8x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm_clear_4x_cont(to, ret,			\
+		"	clear.d [%0+]\n4:\n" CLEAR,	\
+		"5:	addq 4,%1\n" FIXUP,		\
+		"	.dword 4b,5b\n" TENTRY)
+
+#define __asm_clear_8(to, ret) \
+	__asm_clear_8x_cont(to, ret, "", "", "")
+
+#define __asm_clear_12x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm_clear_8x_cont(to, ret,			\
+		"	clear.d [%0+]\n6:\n" CLEAR,	\
+		"7:	addq 4,%1\n" FIXUP,		\
+		"	.dword 6b,7b\n" TENTRY)
+
+#define __asm_clear_12(to, ret) \
+	__asm_clear_12x_cont(to, ret, "", "", "")
+
+#define __asm_clear_16x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm_clear_12x_cont(to, ret,			\
+		"	clear.d [%0+]\n8:\n" CLEAR,	\
+		"9:	addq 4,%1\n" FIXUP,		\
+		"	.dword 8b,9b\n" TENTRY)
+
+#define __asm_clear_16(to, ret) \
+	__asm_clear_16x_cont(to, ret, "", "", "")
+
+#define __asm_clear_20x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm_clear_16x_cont(to, ret,			\
+		"	clear.d [%0+]\n10:\n" CLEAR,	\
+		"11:	addq 4,%1\n" FIXUP,		\
+		"	.dword 10b,11b\n" TENTRY)
+
+#define __asm_clear_20(to, ret) \
+	__asm_clear_20x_cont(to, ret, "", "", "")
+
+#define __asm_clear_24x_cont(to, ret, CLEAR, FIXUP, TENTRY) \
+	__asm_clear_20x_cont(to, ret,			\
+		"	clear.d [%0+]\n12:\n" CLEAR,	\
+		"13:	addq 4,%1\n" FIXUP,		\
+		"	.dword 12b,13b\n" TENTRY)
+
+#define __asm_clear_24(to, ret) \
+	__asm_clear_24x_cont(to, ret, "", "", "")
+
+/* Note that if these expand awfully if made into switch constructs, so
+   don't do that.  */
+
+static inline unsigned long
+__constant_copy_from_user(void *to, const void *from, unsigned long n)
+{
+	unsigned long ret = 0;
+	if (n == 0)
+		;
+	else if (n == 1)
+		__asm_copy_from_user_1(to, from, ret);
+	else if (n == 2)
+		__asm_copy_from_user_2(to, from, ret);
+	else if (n == 3)
+		__asm_copy_from_user_3(to, from, ret);
+	else if (n == 4)
+		__asm_copy_from_user_4(to, from, ret);
+	else if (n == 5)
+		__asm_copy_from_user_5(to, from, ret);
+	else if (n == 6)
+		__asm_copy_from_user_6(to, from, ret);
+	else if (n == 7)
+		__asm_copy_from_user_7(to, from, ret);
+	else if (n == 8)
+		__asm_copy_from_user_8(to, from, ret);
+	else if (n == 9)
+		__asm_copy_from_user_9(to, from, ret);
+	else if (n == 10)
+		__asm_copy_from_user_10(to, from, ret);
+	else if (n == 11)
+		__asm_copy_from_user_11(to, from, ret);
+	else if (n == 12)
+		__asm_copy_from_user_12(to, from, ret);
+	else if (n == 13)
+		__asm_copy_from_user_13(to, from, ret);
+	else if (n == 14)
+		__asm_copy_from_user_14(to, from, ret);
+	else if (n == 15)
+		__asm_copy_from_user_15(to, from, ret);
+	else if (n == 16)
+		__asm_copy_from_user_16(to, from, ret);
+	else if (n == 20)
+		__asm_copy_from_user_20(to, from, ret);
+	else if (n == 24)
+		__asm_copy_from_user_24(to, from, ret);
+	else
+		ret = __generic_copy_from_user(to, from, n);
+
+	return ret;
+}
+
+/* Ditto, don't make a switch out of this.  */
+
+static inline unsigned long
+__constant_copy_to_user(void *to, const void *from, unsigned long n)
+{
+	unsigned long ret = 0;
+	if (n == 0)
+		;
+	else if (n == 1)
+		__asm_copy_to_user_1(to, from, ret);
+	else if (n == 2)
+		__asm_copy_to_user_2(to, from, ret);
+	else if (n == 3)
+		__asm_copy_to_user_3(to, from, ret);
+	else if (n == 4)
+		__asm_copy_to_user_4(to, from, ret);
+	else if (n == 5)
+		__asm_copy_to_user_5(to, from, ret);
+	else if (n == 6)
+		__asm_copy_to_user_6(to, from, ret);
+	else if (n == 7)
+		__asm_copy_to_user_7(to, from, ret);
+	else if (n == 8)
+		__asm_copy_to_user_8(to, from, ret);
+	else if (n == 9)
+		__asm_copy_to_user_9(to, from, ret);
+	else if (n == 10)
+		__asm_copy_to_user_10(to, from, ret);
+	else if (n == 11)
+		__asm_copy_to_user_11(to, from, ret);
+	else if (n == 12)
+		__asm_copy_to_user_12(to, from, ret);
+	else if (n == 13)
+		__asm_copy_to_user_13(to, from, ret);
+	else if (n == 14)
+		__asm_copy_to_user_14(to, from, ret);
+	else if (n == 15)
+		__asm_copy_to_user_15(to, from, ret);
+	else if (n == 16)
+		__asm_copy_to_user_16(to, from, ret);
+	else if (n == 20)
+		__asm_copy_to_user_20(to, from, ret);
+	else if (n == 24)
+		__asm_copy_to_user_24(to, from, ret);
+	else
+		ret = __generic_copy_to_user(to, from, n);
+
+	return ret;
+}
+
+/* No switch, please.  */
+
+static inline unsigned long
+__constant_clear_user(void *to, unsigned long n)
+{
+	unsigned long ret = 0;
+	if (n == 0)
+		;
+	else if (n == 1)
+		__asm_clear_1(to, ret);
+	else if (n == 2)
+		__asm_clear_2(to, ret);
+	else if (n == 3)
+		__asm_clear_3(to, ret);
+	else if (n == 4)
+		__asm_clear_4(to, ret);
+	else if (n == 8)
+		__asm_clear_8(to, ret);
+	else if (n == 12)
+		__asm_clear_12(to, ret);
+	else if (n == 16)
+		__asm_clear_16(to, ret);
+	else if (n == 20)
+		__asm_clear_20(to, ret);
+	else if (n == 24)
+		__asm_clear_24(to, ret);
+	else
+		ret = __generic_clear_user(to, n);
+
+	return ret;
+}
+
+
+#define clear_user(to, n)			\
+(__builtin_constant_p(n) ?			\
+ __constant_clear_user(to, n) :			\
+ __generic_clear_user(to, n))
+
+#define copy_from_user(to, from, n)		\
+(__builtin_constant_p(n) ?			\
+ __constant_copy_from_user(to, from, n) :	\
+ __generic_copy_from_user(to, from, n))
+
+#define copy_to_user(to, from, n)		\
+(__builtin_constant_p(n) ?			\
+ __constant_copy_to_user(to, from, n) :		\
+ __generic_copy_to_user(to, from, n))
+
+#define copy_to_user_ret(to,from,n,retval) \
+	do { if (copy_to_user(to,from,n)) return retval; } while (0)
+#define copy_from_user_ret(to,from,n,retval) \
+	do { if (copy_from_user(to,from,n)) return retval; } while (0)
+
+/* We let the __ versions of copy_from/to_user inline, because they're often
+ * used in fast paths and have only a small space overhead.
+ */
+
+static inline unsigned long
+__generic_copy_from_user_nocheck(void *to, const void *from, unsigned long n)
+{
+	return __copy_user_zeroing(to,from,n);
+}
+
+static inline unsigned long
+__generic_copy_to_user_nocheck(void *to, const void *from, unsigned long n)
+{
+	return __copy_user(to,from,n);
+}
+
+static inline unsigned long
+__generic_clear_user_nocheck(void *to, unsigned long n)
+{
+	return __do_clear_user(to,n);
+}
+
+/* without checking */
+
+#define __copy_to_user(to,from,n)   __generic_copy_to_user_nocheck((to),(from),(n))
+#define __copy_from_user(to,from,n) __generic_copy_from_user_nocheck((to),(from),(n))
+#define __clear_user(to,n) __generic_clear_user_nocheck((to),(n))
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return length of string in userspace including terminating 0
+ * or 0 for error.  Return a value greater than N if too long.
+ */
+
+static inline long
+strnlen_user(const char *s, long n)
+{
+	long res, tmp1, tmp2;
+
+	if (!access_ok(VERIFY_READ, s, 0))
+		return 0;
+
+	/*
+	 * This code is deduced from:
+	 *
+	 *	tmp1 = n;
+	 *	while (tmp1-- > 0 && *s++)
+	 *	  ;
+	 *
+	 *	res = n - tmp1;
+	 *
+	 *  (with tweaks).
+	 */
+
+	__asm__ __volatile__ (
+		"	move.d %1,r9\n"
+		"0:\n"
+		"	ble 1f\n"
+		"	subq 1,r9\n"
+
+		"	test.b [%0+]\n"
+		"	bne 0b\n"
+		"	test.d r9\n"
+		"1:\n"
+		"	move.d %1,%0\n"
+		"	sub.d r9,%0\n"
+		"2:\n"
+		"	.section .fixup,\"ax\"\n"
+
+		"3:	clear.d %0\n"
+		"	jump 2b\n"
+
+		/* There's one address for a fault at the first move, and
+		   two possible PC values for a fault at the second move,
+		   being a delay-slot filler.  However, the branch-target
+		   for the second move is the same as the first address.
+		   Just so you don't get confused...  */
+		"	.previous\n"
+		"	.section __ex_table,\"a\"\n"
+		"	.dword 0b,3b\n"
+		"	.dword 1b,3b\n"
+		"	.previous\n"
+		: "=r" (res), "=r" (tmp1)
+		: "0" (s), "1" (n)
+		: "r9");
+
+	return res;
+}
+
+#define strlen_user(str)	strnlen_user((str), 0x7ffffffe)
+
+#endif  /* __ASSEMBLY__ */
+
+#endif	/* _CRIS_UACCESS_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/ucontext.h linux/include/asm-cris/ucontext.h
--- v2.4.1/linux/include/asm-cris/ucontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/ucontext.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,12 @@
+#ifndef _ASM_CRIS_UCONTEXT_H
+#define _ASM_CRIS_UCONTEXT_H
+
+struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	struct sigcontext uc_mcontext;
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+};
+
+#endif /* !_ASM_CRIS_UCONTEXT_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/unaligned.h linux/include/asm-cris/unaligned.h
--- v2.4.1/linux/include/asm-cris/unaligned.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/unaligned.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,16 @@
+#ifndef __CRIS_UNALIGNED_H
+#define __CRIS_UNALIGNED_H
+
+/*
+ * CRIS can do unaligned accesses itself. 
+ *
+ * The strange macros are there to make sure these can't
+ * be misused in a way that makes them not work on other
+ * architectures where unaligned accesses aren't as simple.
+ */
+
+#define get_unaligned(ptr) (*(ptr))
+
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/unistd.h linux/include/asm-cris/unistd.h
--- v2.4.1/linux/include/asm-cris/unistd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/unistd.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,373 @@
+#ifndef _ASM_CRIS_UNISTD_H_
+#define _ASM_CRIS_UNISTD_H_
+
+/*
+ * This file contains the system call numbers, and stub macros for libc.
+ */
+
+#define __NR_setup		  0	/* used only by init, to get system going */
+#define __NR_exit		  1
+#define __NR_fork		  2
+#define __NR_read		  3
+#define __NR_write		  4
+#define __NR_open		  5
+#define __NR_close		  6
+#define __NR_waitpid		  7
+#define __NR_creat		  8
+#define __NR_link		  9
+#define __NR_unlink		 10
+#define __NR_execve		 11
+#define __NR_chdir		 12
+#define __NR_time		 13
+#define __NR_mknod		 14
+#define __NR_chmod		 15
+#define __NR_lchown		 16
+#define __NR_break		 17
+#define __NR_oldstat		 18
+#define __NR_lseek		 19
+#define __NR_getpid		 20
+#define __NR_mount		 21
+#define __NR_umount		 22
+#define __NR_setuid		 23
+#define __NR_getuid		 24
+#define __NR_stime		 25
+#define __NR_ptrace		 26
+#define __NR_alarm		 27
+#define __NR_oldfstat		 28
+#define __NR_pause		 29
+#define __NR_utime		 30
+#define __NR_stty		 31
+#define __NR_gtty		 32
+#define __NR_access		 33
+#define __NR_nice		 34
+#define __NR_ftime		 35
+#define __NR_sync		 36
+#define __NR_kill		 37
+#define __NR_rename		 38
+#define __NR_mkdir		 39
+#define __NR_rmdir		 40
+#define __NR_dup		 41
+#define __NR_pipe		 42
+#define __NR_times		 43
+#define __NR_prof		 44
+#define __NR_brk		 45
+#define __NR_setgid		 46
+#define __NR_getgid		 47
+#define __NR_signal		 48
+#define __NR_geteuid		 49
+#define __NR_getegid		 50
+#define __NR_acct		 51
+#define __NR_phys		 52
+#define __NR_lock		 53
+#define __NR_ioctl		 54
+#define __NR_fcntl		 55
+#define __NR_mpx		 56
+#define __NR_setpgid		 57
+#define __NR_ulimit		 58
+#define __NR_oldolduname	 59
+#define __NR_umask		 60
+#define __NR_chroot		 61
+#define __NR_ustat		 62
+#define __NR_dup2		 63
+#define __NR_getppid		 64
+#define __NR_getpgrp		 65
+#define __NR_setsid		 66
+#define __NR_sigaction		 67
+#define __NR_sgetmask		 68
+#define __NR_ssetmask		 69
+#define __NR_setreuid		 70
+#define __NR_setregid		 71
+#define __NR_sigsuspend		 72
+#define __NR_sigpending		 73
+#define __NR_sethostname	 74
+#define __NR_setrlimit		 75
+#define __NR_getrlimit		 76
+#define __NR_getrusage		 77
+#define __NR_gettimeofday	 78
+#define __NR_settimeofday	 79
+#define __NR_getgroups		 80
+#define __NR_setgroups		 81
+#define __NR_select		 82
+#define __NR_symlink		 83
+#define __NR_oldlstat		 84
+#define __NR_readlink		 85
+#define __NR_uselib		 86
+#define __NR_swapon		 87
+#define __NR_reboot		 88
+#define __NR_readdir		 89
+#define __NR_mmap		 90
+#define __NR_munmap		 91
+#define __NR_truncate		 92
+#define __NR_ftruncate		 93
+#define __NR_fchmod		 94
+#define __NR_fchown		 95
+#define __NR_getpriority	 96
+#define __NR_setpriority	 97
+#define __NR_profil		 98
+#define __NR_statfs		 99
+#define __NR_fstatfs		100
+#define __NR_ioperm		101
+#define __NR_socketcall		102
+#define __NR_syslog		103
+#define __NR_setitimer		104
+#define __NR_getitimer		105
+#define __NR_stat		106
+#define __NR_lstat		107
+#define __NR_fstat		108
+#define __NR_olduname		109
+#define __NR_iopl		110
+#define __NR_vhangup		111
+#define __NR_idle		112
+#define __NR_vm86		113
+#define __NR_wait4		114
+#define __NR_swapoff		115
+#define __NR_sysinfo		116
+#define __NR_ipc		117
+#define __NR_fsync		118
+#define __NR_sigreturn		119
+#define __NR_clone		120
+#define __NR_setdomainname	121
+#define __NR_uname		122
+#define __NR_modify_ldt		123
+#define __NR_adjtimex		124
+#define __NR_mprotect		125
+#define __NR_sigprocmask	126
+#define __NR_create_module	127
+#define __NR_init_module	128
+#define __NR_delete_module	129
+#define __NR_get_kernel_syms	130
+#define __NR_quotactl		131
+#define __NR_getpgid		132
+#define __NR_fchdir		133
+#define __NR_bdflush		134
+#define __NR_sysfs		135
+#define __NR_personality	136
+#define __NR_afs_syscall	137 /* Syscall for Andrew File System */
+#define __NR_setfsuid		138
+#define __NR_setfsgid		139
+#define __NR__llseek		140
+#define __NR_getdents		141
+#define __NR__newselect		142
+#define __NR_flock		143
+#define __NR_msync		144
+#define __NR_readv		145
+#define __NR_writev		146
+#define __NR_getsid		147
+#define __NR_fdatasync		148
+#define __NR__sysctl		149
+#define __NR_mlock		150
+#define __NR_munlock		151
+#define __NR_mlockall		152
+#define __NR_munlockall		153
+#define __NR_sched_setparam		154
+#define __NR_sched_getparam		155
+#define __NR_sched_setscheduler		156
+#define __NR_sched_getscheduler		157
+#define __NR_sched_yield		158
+#define __NR_sched_get_priority_max	159
+#define __NR_sched_get_priority_min	160
+#define __NR_sched_rr_get_interval	161
+#define __NR_nanosleep		162
+#define __NR_mremap		163
+#define __NR_setresuid		164
+#define __NR_getresuid		165
+
+#define __NR_query_module	167
+#define __NR_poll		168
+#define __NR_nfsservctl		169
+#define __NR_setresgid		170
+#define __NR_getresgid		171
+#define __NR_prctl              172
+#define __NR_rt_sigreturn	173
+#define __NR_rt_sigaction	174
+#define __NR_rt_sigprocmask	175
+#define __NR_rt_sigpending	176
+#define __NR_rt_sigtimedwait	177
+#define __NR_rt_sigqueueinfo	178
+#define __NR_rt_sigsuspend	179
+#define __NR_pread		180
+#define __NR_pwrite		181
+#define __NR_chown		182
+#define __NR_getcwd		183
+#define __NR_capget		184
+#define __NR_capset		185
+#define __NR_sigaltstack	186
+#define __NR_sendfile		187
+#define __NR_getpmsg		188	/* some people actually want streams */
+#define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
+#define __NR_ugetrlimit		191	/* SuS compliant getrlimit */
+#define __NR_mmap2		192
+#define __NR_truncate64		193
+#define __NR_ftruncate64	194
+#define __NR_stat64		195
+#define __NR_lstat64		196
+#define __NR_fstat64		197
+#define __NR_lchown32		198
+#define __NR_getuid32		199
+#define __NR_getgid32		200
+#define __NR_geteuid32		201
+#define __NR_getegid32		202
+#define __NR_setreuid32		203
+#define __NR_setregid32		204
+#define __NR_getgroups32	205
+#define __NR_setgroups32	206
+#define __NR_fchown32		207
+#define __NR_setresuid32	208
+#define __NR_getresuid32	209
+#define __NR_setresgid32	210
+#define __NR_getresgid32	211
+#define __NR_chown32		212
+#define __NR_setuid32		213
+#define __NR_setgid32		214
+#define __NR_setfsuid32		215
+#define __NR_setfsgid32		216
+#define __NR_pivot_root		217
+#define __NR_mincore		218
+#define __NR_madvise		219
+#define __NR_getdents64		220
+#define __NR_fcntl64		221
+
+/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */
+#define _syscall0(type,name) \
+type name(void) \
+{ \
+  register long __a __asm__ ("r10"); \
+  __asm__ __volatile__ ("move.d %1,r1\n\tbreak 13" \
+			: "=r" (__a) \
+			: "g" (__NR_##name) \
+			: "r10", "r1"); \
+  if(__a >= 0) \
+     return (type) __a; \
+  errno = -__a; \
+  return -1; \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) \
+{ \
+  register long __a __asm__ ("r10") = (long) arg1; \
+  __asm__ __volatile__ ("move.d %1,r1\n\tbreak 13" \
+			: "=r" (__a) \
+			: "g" (__NR_##name), "0" (__a) \
+			: "r10", "r1"); \
+  if(__a >= 0) \
+     return (type) __a; \
+  errno = -__a; \
+  return -1; \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) \
+{ \
+  register long __a __asm__ ("r10") = (long) arg1; \
+  register long __b __asm__ ("r11") = (long) arg2; \
+  __asm__ __volatile__ ("move.d %1,r1\n\tbreak 13" \
+			: "=r" (__a) \
+			: "g" (__NR_##name), "0" (__a), "r" (__b) \
+			: "r10", "r1"); \
+  if(__a >= 0) \
+     return (type) __a; \
+  errno = -__a; \
+  return -1; \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) \
+{ \
+  register long __a __asm__ ("r10") = (long) arg1; \
+  register long __b __asm__ ("r11") = (long) arg2; \
+  register long __c __asm__ ("r12") = (long) arg3; \
+  __asm__ __volatile__ ("move.d %1,r1\n\tbreak 13" \
+			: "=r" (__a) \
+			: "g" (__NR_##name), "0" (__a), "r" (__b), "r" (__c) \
+			: "r10", "r1"); \
+  if(__a >= 0) \
+     return (type) __a; \
+  errno = -__a; \
+  return -1; \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+{ \
+  register long __a __asm__ ("r10") = (long) arg1; \
+  register long __b __asm__ ("r11") = (long) arg2; \
+  register long __c __asm__ ("r12") = (long) arg3; \
+  register long __d __asm__ ("r13") = (long) arg4; \
+  __asm__ __volatile__ ("move.d %1,r1\n\tbreak 13" \
+			: "=r" (__a) \
+			: "g" (__NR_##name), "0" (__a), "r" (__b), \
+			  "r" (__c), "r" (__d) \
+			: "r10", "r1"); \
+  if(__a >= 0) \
+     return (type) __a; \
+  errno = -__a; \
+  return -1; \
+} 
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
+	  type5,arg5) \
+type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+{ \
+  register long __a __asm__ ("r10") = (long) arg1; \
+  register long __b __asm__ ("r11") = (long) arg2; \
+  register long __c __asm__ ("r12") = (long) arg3; \
+  register long __d __asm__ ("r13") = (long) arg4; \
+  register long __e __asm__ ("r0") = (long) arg5; \
+  __asm__ __volatile__ ("move.d %1,r1\n\tbreak 13" \
+			: "=r" (__a) \
+			: "g" (__NR_##name), "0" (__a), "r" (__b), \
+			  "r" (__c), "r" (__d), "r" (__e) \
+			: "r10", "r1"); \
+  if(__a >= 0) \
+     return (type) __a; \
+  errno = -__a; \
+  return -1; \
+}
+
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static inline _syscall0(int,idle)
+static inline _syscall0(int,fork)
+static inline _syscall2(int,clone,unsigned long,flags,char *,esp)
+static inline _syscall0(int,pause)
+static inline _syscall0(int,setup)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
+
+  /* the following are just while developing the elinux port! */
+
+static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static inline _syscall2(int,socketcall,int,call,unsigned long *,args)
+static inline _syscall3(int,ioctl,unsigned int,fd,unsigned int,cmd,unsigned long,arg)
+static inline _syscall5(int,mount,const char *,a,const char *,b,const char *,c,unsigned long,rwflag,const void *,data)
+
+static inline pid_t wait(int * wait_stat)
+{
+	return waitpid(-1,wait_stat,0);
+}
+
+#endif
+
+#endif /* _ASM_CRIS_UNISTD_H_ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-cris/user.h linux/include/asm-cris/user.h
--- v2.4.1/linux/include/asm-cris/user.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-cris/user.h	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,51 @@
+#ifndef __ASM_CRIS_USER_H
+#define __ASM_CRIS_USER_H
+
+#include <linux/types.h>
+#include <asm/ptrace.h>
+#include <asm/page.h>
+
+/*
+ * Core file format: The core file is written in such a way that gdb
+ * can understand it and provide useful information to the user (under
+ * linux we use the `trad-core' bfd).  The file contents are as follows:
+ *
+ *  upage: 1 page consisting of a user struct that tells gdb
+ *	what is present in the file.  Directly after this is a
+ *	copy of the task_struct, which is currently not used by gdb,
+ *	but it may come in handy at some point.  All of the registers
+ *	are stored as part of the upage.  The upage should always be
+ *	only one page long.
+ *  data: The data segment follows next.  We use current->end_text to
+ *	current->brk to pick up all of the user variables, plus any memory
+ *	that may have been sbrk'ed.  No attempt is made to determine if a
+ *	page is demand-zero or if a page is totally unused, we just cover
+ *	the entire range.  All of the addresses are rounded in such a way
+ *	that an integral number of pages is written.
+ *  stack: We need the stack information in order to get a meaningful
+ *	backtrace.  We need to write the data from usp to
+ *	current->start_stack, so we round each of these in order to be able
+ *	to write an integer number of pages.
+ */
+
+struct user {
+	struct pt_regs	regs;			/* entire machine state */
+	size_t		u_tsize;		/* text size (pages) */
+	size_t		u_dsize;		/* data size (pages) */
+	size_t		u_ssize;		/* stack size (pages) */
+	unsigned long	start_code;		/* text starting address */
+	unsigned long	start_data;		/* data starting address */
+	unsigned long	start_stack;		/* stack starting address */
+	long int	signal;			/* signal causing core dump */
+	struct regs *	u_ar0;			/* help gdb find registers */
+	unsigned long	magic;			/* identifies a core file */
+	char		u_comm[32];		/* user command name */
+};
+
+#define NBPG			PAGE_SIZE
+#define UPAGES			1
+#define HOST_TEXT_START_ADDR	(u.start_code)
+#define HOST_DATA_START_ADDR	(u.start_data)
+#define HOST_STACK_END_ADDR	(u.start_stack + u.u_ssize * NBPG)
+
+#endif /* __ASM_CRIS_USER_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-i386/errno.h linux/include/asm-i386/errno.h
--- v2.4.1/linux/include/asm-i386/errno.h	Sat Feb  3 19:51:31 2001
+++ linux/include/asm-i386/errno.h	Fri Feb  9 11:40:02 2001
@@ -128,6 +128,5 @@
 
 #define	ENOMEDIUM	123	/* No medium found */
 #define	EMEDIUMTYPE	124	/* Wrong medium type */
-#define	EHASHCOLLISION	125	/* Number of hash collisons exceeds maximum generation counter value.  */
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-i386/socket.h linux/include/asm-i386/socket.h
--- v2.4.1/linux/include/asm-i386/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-i386/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nasty libc5 fixup - bletch */
 #if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-i386/termios.h linux/include/asm-i386/termios.h
--- v2.4.1/linux/include/asm-i386/termios.h	Thu Jan 27 16:40:09 2000
+++ linux/include/asm-i386/termios.h	Sat Feb  3 20:00:45 2001
@@ -51,7 +51,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-ia64/socket.h linux/include/asm-ia64/socket.h
--- v2.4.1/linux/include/asm-ia64/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-ia64/socket.h	Sat Feb  3 11:26:44 2001
@@ -50,6 +50,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-ia64/termios.h linux/include/asm-ia64/termios.h
--- v2.4.1/linux/include/asm-ia64/termios.h	Sun Feb  6 18:42:40 2000
+++ linux/include/asm-ia64/termios.h	Sat Feb  3 20:00:45 2001
@@ -58,7 +58,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS msgs */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/bitops.h linux/include/asm-m68k/bitops.h
--- v2.4.1/linux/include/asm-m68k/bitops.h	Mon Nov 27 18:00:49 2000
+++ linux/include/asm-m68k/bitops.h	Sat Feb  3 11:26:44 2001
@@ -228,7 +228,7 @@
 {
 	int cnt;
 
-	asm ("bfffo %1{#0:#0}" : "=d" (cnt) : "dm" (x & -x));
+	asm ("bfffo %1{#0:#0},%0" : "=d" (cnt) : "dm" (x & -x));
 
 	return 32 - cnt;
 }
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/socket.h linux/include/asm-m68k/socket.h
--- v2.4.1/linux/include/asm-m68k/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-m68k/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-m68k/termios.h linux/include/asm-m68k/termios.h
--- v2.4.1/linux/include/asm-m68k/termios.h	Thu Jan 27 16:40:09 2000
+++ linux/include/asm-m68k/termios.h	Sat Feb  3 20:00:45 2001
@@ -61,7 +61,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips/socket.h linux/include/asm-mips/socket.h
--- v2.4.1/linux/include/asm-mips/socket.h	Sun Jul  9 22:32:15 2000
+++ linux/include/asm-mips/socket.h	Sat Feb  3 11:26:44 2001
@@ -33,6 +33,7 @@
 #define SO_RCVLOWAT	0x1004	/* receive low-water mark */
 #define SO_SNDTIMEO	0x1005	/* send timeout */
 #define SO_RCVTIMEO 	0x1006	/* receive timeout */
+#define SO_ACCEPTCONN	0x1007
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips/termios.h linux/include/asm-mips/termios.h
--- v2.4.1/linux/include/asm-mips/termios.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips/termios.h	Sat Feb  3 20:00:45 2001
@@ -97,7 +97,7 @@
 #define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/delay.h linux/include/asm-mips64/delay.h
--- v2.4.1/linux/include/asm-mips64/delay.h	Tue Jul 11 11:18:53 2000
+++ linux/include/asm-mips64/delay.h	Sun Feb  4 21:48:46 2001
@@ -12,6 +12,8 @@
 
 #include <linux/config.h>
 
+extern unsigned long loops_per_sec;
+
 extern __inline__ void
 __delay(unsigned long loops)
 {
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/errno.h linux/include/asm-mips64/errno.h
--- v2.4.1/linux/include/asm-mips64/errno.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips64/errno.h	Sun Feb  4 21:48:46 2001
@@ -1,10 +1,10 @@
-/* $Id: errno.h,v 1.1 1999/08/18 23:37:51 ralf Exp $
- *
+/*
  * 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.
  *
- * Copyright (C) 1995 by Ralf Baechle
+ * Copyright (C) 1995, 2001 by Ralf Baechle
+ * Copyright (C) 2001 Silicon Graphics, Inc.
  */
 #ifndef _ASM_ERRNO_H
 #define _ASM_ERRNO_H
@@ -142,6 +142,7 @@
  */
 #define ENOMEDIUM	159	/* No medium found */
 #define EMEDIUMTYPE	160	/* Wrong medium type */
+#define EHASHCOLLISION	125	/* Number of hash collisons exceeds maximum generation counter value.  */
 
 #define EDQUOT		1133	/* Quota exceeded */
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/sn/mapped_kernel.h linux/include/asm-mips64/sn/mapped_kernel.h
--- v2.4.1/linux/include/asm-mips64/sn/mapped_kernel.h	Tue Nov 28 21:42:04 2000
+++ linux/include/asm-mips64/sn/mapped_kernel.h	Sun Feb  4 21:48:46 2001
@@ -52,4 +52,4 @@
 #define MAPPED_KERN_RO_TO_K0(x)	PHYS_TO_K0(MAPPED_KERN_RO_TO_PHYS(x))
 #define MAPPED_KERN_RW_TO_K0(x)	PHYS_TO_K0(MAPPED_KERN_RW_TO_PHYS(x))
 
-#endif __ASM_SN_MAPPED_KERNEL_H
+#endif /* __ASM_SN_MAPPED_KERNEL_H  */
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/socket.h linux/include/asm-mips64/socket.h
--- v2.4.1/linux/include/asm-mips64/socket.h	Tue Jul 11 11:17:45 2000
+++ linux/include/asm-mips64/socket.h	Sat Feb  3 11:26:44 2001
@@ -41,6 +41,7 @@
 #define SO_RCVLOWAT	0x1004	/* receive low-water mark */
 #define SO_SNDTIMEO	0x1005	/* send timeout */
 #define SO_RCVTIMEO 	0x1006	/* receive timeout */
+#define SO_ACCEPTCONN	0x1007
 
 /* linux-specific, might as well be the same as on i386 */
 #define SO_NO_CHECK	11
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/termios.h linux/include/asm-mips64/termios.h
--- v2.4.1/linux/include/asm-mips64/termios.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips64/termios.h	Sat Feb  3 20:00:45 2001
@@ -97,7 +97,7 @@
 #define N_MASC		8	/* Reserved fo Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-mips64/watch.h linux/include/asm-mips64/watch.h
--- v2.4.1/linux/include/asm-mips64/watch.h	Sat May 13 08:31:25 2000
+++ linux/include/asm-mips64/watch.h	Sun Feb  4 21:48:46 2001
@@ -1,10 +1,9 @@
-/* $Id: watch.h,v 1.1 1999/09/27 16:01:41 ralf Exp $
- *
+/*
  * 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.
  *
- * Copyright (C) 1996, 1997, 1998, 1999 by Ralf Baechle
+ * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 by Ralf Baechle
  */
 #ifndef _ASM_WATCH_H
 #define _ASM_WATCH_H
@@ -35,4 +34,4 @@
 	if (watch_available)					\
 		__watch_reenable()
 
-#endif _ASM_WATCH_H
+#endif /* _ASM_WATCH_H  */
diff -u --recursive --new-file v2.4.1/linux/include/asm-parisc/socket.h linux/include/asm-parisc/socket.h
--- v2.4.1/linux/include/asm-parisc/socket.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_ATTACH_FILTER        0x401a
 #define SO_DETACH_FILTER        0x401b
 
+#define SO_ACCEPTCONN		0x401c
+
 #if defined(__KERNEL__)
 #define SOCK_STREAM	1	/* stream (connection) socket	*/
 #define SOCK_DGRAM	2	/* datagram (conn.less) socket	*/
diff -u --recursive --new-file v2.4.1/linux/include/asm-parisc/termios.h linux/include/asm-parisc/termios.h
--- v2.4.1/linux/include/asm-parisc/termios.h	Tue Dec  5 12:29:39 2000
+++ linux/include/asm-parisc/termios.h	Sat Feb  3 20:00:45 2001
@@ -51,7 +51,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 
 #ifdef __KERNEL__
diff -u --recursive --new-file v2.4.1/linux/include/asm-ppc/socket.h linux/include/asm-ppc/socket.h
--- v2.4.1/linux/include/asm-ppc/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-ppc/socket.h	Sat Feb  3 11:26:44 2001
@@ -49,6 +49,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-ppc/termios.h linux/include/asm-ppc/termios.h
--- v2.4.1/linux/include/asm-ppc/termios.h	Sat Feb  3 19:51:31 2001
+++ linux/include/asm-ppc/termios.h	Sat Feb  3 20:00:45 2001
@@ -186,7 +186,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/atomic.h linux/include/asm-s390/atomic.h
--- v2.4.1/linux/include/asm-s390/atomic.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/atomic.h	Tue Feb 13 14:13:44 2001
@@ -38,74 +38,80 @@
 {
         __asm__ __volatile__("st  %1,%0\n\t"
                              "bcr 15,0"
-                             : : "m" (*v), "d" (i) : "memory");
+                             : "=m" (*v) : "d" (i) );
 }
 
 static __inline__ void atomic_add(int i, atomic_t *v)
 {
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    1,0\n"
                              "   ar    1,%1\n"
-                             "   cs    0,1,%0\n"
+                             "   cs    0,1,0(2)\n"
                              "   jl    0b"
-                             : "+m" (*v) : "d" (i) : "0", "1" );
+                             : "+m" (*v) : "d" (i) : "0", "1", "2", "cc" );
 }
 
 static __inline__ int atomic_add_return (int i, atomic_t *v)
 {
 	int newval;
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    %1,0\n"
                              "   ar    %1,%2\n"
-                             "   cs    0,%1,%0\n"
+                             "   cs    0,%1,0(1)\n"
                              "   jl    0b"
                              : "+m" (*v), "=&d" (newval)
-			     : "d" (i) : "0", "cc" );
+			     : "d" (i) : "0", "1", "cc" );
 	return newval;
 }
 
 static __inline__ int atomic_add_negative(int i, atomic_t *v)
 {
 	int newval;
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    %1,0\n"
                              "   ar    %1,%2\n"
-                             "   cs    0,%1,%0\n"
+                             "   cs    0,%1,0(1)\n"
                              "   jl    0b\n"
                              : "+m" (*v), "=&d" (newval)
-                             : "d" (i) : "0", "cc" );
+                             : "d" (i) : "0", "1", "cc" );
         return newval < 0;
 }
 
 static __inline__ void atomic_sub(int i, atomic_t *v)
 {
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    1,0\n"
                              "   sr    1,%1\n"
-                             "   cs    0,1,%0\n"
+                             "   cs    0,1,0(2)\n"
                              "   jl    0b"
-                             : "+m" (*v) : "d" (i) : "0", "1" );
+                             : "+m" (*v) : "d" (i) : "0", "1", "2", "cc" );
 }
 
 static __inline__ void atomic_inc(volatile atomic_t *v)
 {
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    1,0\n"
                              "   ahi   1,1\n"
-                             "   cs    0,1,%0\n"
+                             "   cs    0,1,0(2)\n"
                              "   jl    0b"
-                             : "+m" (*v) : : "0", "1" );
+                             : "+m" (*v) : : "0", "1", "2", "cc" );
 }
 
 static __inline__ int atomic_inc_return(volatile atomic_t *v)
 {
         int i;
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    %1,0\n"
                              "   ahi   %1,1\n"
-                             "   cs    0,%1,%0\n"
+                             "   cs    0,%1,0(1)\n"
                              "   jl    0b"
-                             : "+m" (*v), "=&d" (i) : : "0" );
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
         return i;
 }
 
@@ -113,67 +119,74 @@
 {
        int i;
 
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    %1,0\n"
                              "   ahi   %1,1\n"
-                             "   cs    0,%1,%0\n"
+                             "   cs    0,%1,0(1)\n"
                              "   jl    0b"
-                             : "+m" (*v), "=&d" (i) : : "0" );
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
        return i != 0;
 }
 
 static __inline__ void atomic_dec(volatile atomic_t *v)
 {
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    1,0\n"
                              "   ahi   1,-1\n"
-                             "   cs    0,1,%0\n"
+                             "   cs    0,1,0(2)\n"
                              "   jl    0b"
-                             : "+m" (*v) : : "0", "1" );
+                             : "+m" (*v) : : "0", "1", "2", "cc" );
 }
 
 static __inline__ int atomic_dec_return(volatile atomic_t *v)
 {
         int i;
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    %1,0\n"
                              "   ahi   %1,-1\n"
-                             "   cs    0,%1,%0\n"
+                             "   cs    0,%1,0(1)\n"
                              "   jl    0b"
-                             : "+m" (*v), "=&d" (i) : : "0" );
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
         return i;
 }
 
 static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
 {
         int i;
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    %1,0\n"
                              "   ahi   %1,-1\n"
-                             "   cs    0,%1,%0\n"
+                             "   cs    0,%1,0(1)\n"
                              "   jl    0b"
-                             : "+m" (*v), "=&d" (i) : : "0");
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
         return i == 0;
 }
 
 static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
 {
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    1,0\n"
                              "   nr    1,%1\n"
-                             "   cs    0,1,%0\n"
+                             "   cs    0,1,0(2)\n"
                              "   jl    0b"
-                             : "+m" (*v) : "d" (~(mask)) : "0", "1" );
+                             : "+m" (*v) : "d" (~(mask)) 
+                             : "0", "1", "2", "cc" );
 }
 
 static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
 {
-        __asm__ __volatile__("   l     0,%0\n"
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,%0\n"
                              "0: lr    1,0\n"
                              "   or    1,%1\n"
-                             "   cs    0,1,%0\n"
+                             "   cs    0,1,0(2)\n"
                              "   jl    0b"
-                             : "+m" (*v) : "d" (mask) : "0", "1" );
+                             : "+m" (*v) : "d" (mask) : "0", "1", "2", "cc" );
 }
 
 /*
@@ -186,13 +199,15 @@
         int retval;
 
         __asm__ __volatile__(
-                "  cs   %2,%3,%1\n"
+                "  la   1,%1\n"
+                "  lr   0,%2\n"
+                "  cs   0,%3,0(1)\n"
                 "  ipm  %0\n"
                 "  srl  %0,28\n"
                 "0:"
                 : "=&r" (retval), "+m" (*v)
                 : "d" (expected_oldval) , "d" (new_val)
-                : "memory", "cc");
+                : "0", "1", "cc");
         return retval;
 }
 
@@ -203,12 +218,20 @@
 atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
 {
         __asm__ __volatile__(
+                "   la  2,%0\n"
                 "0: lr  1,%1\n"
-                "   cs  1,%2,%0\n"
+                "   cs  1,%2,0(2)\n"
                 "   jl  0b\n"
                 : "+m" (*v)
                 : "d" (expected_oldval) , "d" (new_val)
-                : "memory", "cc", "1");
+                : "cc", "1", "2");
+}
+
+#define atomic_compare_and_swap_debug(where,from,to) \
+if (atomic_compare_and_swap ((from), (to), (where))) {\
+	printk (KERN_WARNING"%s/%d atomic counter:%s couldn't be changed from %d(%s) to %d(%s), was %d\n",\
+		__FILE__,__LINE__,#where,(from),#from,(to),#to,atomic_read (where));\
+        atomic_set(where,(to));\
 }
 
 #endif                                 /* __ARCH_S390_ATOMIC __            */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/bitops.h linux/include/asm-s390/bitops.h
--- v2.4.1/linux/include/asm-s390/bitops.h	Wed Jul  5 22:15:26 2000
+++ linux/include/asm-s390/bitops.h	Tue Feb 13 14:13:44 2001
@@ -41,32 +41,11 @@
 extern const char _ni_bitmap[];
 extern const char _zb_findmap[];
 
-/*
- * Function prototypes to keep gcc -Wall happy
- */
-extern void __set_bit(int nr, volatile void * addr);
-extern void __constant_set_bit(int nr, volatile void * addr);
-extern int __test_bit(int nr, volatile void * addr);
-extern int __constant_test_bit(int nr, volatile void * addr);
-extern void __clear_bit(int nr, volatile void * addr);
-extern void __constant_clear_bit(int nr, volatile void * addr);
-extern void __change_bit(int nr, volatile void * addr);
-extern void __constant_change_bit(int nr, volatile void * addr);
-extern int test_and_set_bit(int nr, volatile void * addr);
-extern int test_and_clear_bit(int nr, volatile void * addr);
-extern int test_and_change_bit(int nr, volatile void * addr);
-extern int test_and_set_bit_simple(int nr, volatile void * addr);
-extern int test_and_clear_bit_simple(int nr, volatile void * addr);
-extern int test_and_change_bit_simple(int nr, volatile void * addr);
-extern int find_first_zero_bit(void * addr, unsigned size);
-extern int find_next_zero_bit (void * addr, int size, int offset);
-extern unsigned long ffz(unsigned long word);
-
 #ifdef CONFIG_SMP
 /*
  * SMP save set_bit routine based on compare and swap (CS)
  */
-extern __inline__ void set_bit_cs(int nr, volatile void * addr)
+static __inline__ void set_bit_cs(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
 #if ALIGN_CS == 1
@@ -80,8 +59,8 @@
              "   nr    1,%0\n"         /* make shift value */
              "   xr    %0,1\n"
              "   srl   %0,3\n"
-             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
              "   lhi   2,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
              "   sll   2,0(1)\n"       /* make OR mask */
              "   l     %0,0(%1)\n"
              "0: lr    1,%0\n"         /* CS loop starts here */
@@ -95,7 +74,7 @@
 /*
  * SMP save clear_bit routine based on compare and swap (CS)
  */
-extern __inline__ void clear_bit_cs(int nr, volatile void * addr)
+static __inline__ void clear_bit_cs(int nr, volatile void * addr)
 {
         static const int mask = -1;
         __asm__ __volatile__(
@@ -110,8 +89,8 @@
              "   nr    1,%0\n"         /* make shift value */
              "   xr    %0,1\n"
              "   srl   %0,3\n"
-             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
              "   lhi   2,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
              "   sll   2,0(1)\n"
              "   x     2,%2\n"         /* make AND mask */
              "   l     %0,0(%1)\n"
@@ -126,7 +105,7 @@
 /*
  * SMP save change_bit routine based on compare and swap (CS)
  */
-extern __inline__ void change_bit_cs(int nr, volatile void * addr)
+static __inline__ void change_bit_cs(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
 #if ALIGN_CS == 1
@@ -140,8 +119,8 @@
              "   nr    1,%0\n"         /* make shift value */
              "   xr    %0,1\n"
              "   srl   %0,3\n"
-             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
              "   lhi   2,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
              "   sll   2,0(1)\n"       /* make XR mask */
              "   l     %0,0(%1)\n"
              "0: lr    1,%0\n"         /* CS loop starts here */
@@ -155,7 +134,7 @@
 /*
  * SMP save test_and_set_bit routine based on compare and swap (CS)
  */
-extern __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
+static __inline__ int test_and_set_bit_cs(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
 #if ALIGN_CS == 1
@@ -186,7 +165,7 @@
 /*
  * SMP save test_and_clear_bit routine based on compare and swap (CS)
  */
-extern __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
+static __inline__ int test_and_clear_bit_cs(int nr, volatile void * addr)
 {
         static const int mask = -1;
         __asm__ __volatile__(
@@ -220,7 +199,7 @@
 /*
  * SMP save test_and_change_bit routine based on compare and swap (CS) 
  */
-extern __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
+static __inline__ int test_and_change_bit_cs(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
 #if ALIGN_CS == 1
@@ -252,7 +231,7 @@
 /*
  * fast, non-SMP set_bit routine
  */
-extern __inline__ void __set_bit(int nr, volatile void * addr)
+static __inline__ void __set_bit(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
              "   lhi   2,24\n"
@@ -267,7 +246,7 @@
              : "cc", "memory", "1", "2" );
 }
 
-extern __inline__ void 
+static __inline__ void 
 __constant_set_bit(const int nr, volatile void * addr)
 {
   switch (nr&7) {
@@ -330,7 +309,7 @@
 /*
  * fast, non-SMP clear_bit routine
  */
-extern __inline__ void 
+static __inline__ void 
 __clear_bit(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
@@ -346,7 +325,7 @@
              : "cc", "memory", "1", "2" );
 }
 
-extern __inline__ void 
+static __inline__ void 
 __constant_clear_bit(const int nr, volatile void * addr)
 {
   switch (nr&7) {
@@ -409,7 +388,7 @@
 /* 
  * fast, non-SMP change_bit routine 
  */
-extern __inline__ void __change_bit(int nr, volatile void * addr)
+static __inline__ void __change_bit(int nr, volatile void * addr)
 {
         __asm__ __volatile__(
              "   lhi   2,24\n"
@@ -424,7 +403,7 @@
              : "cc", "memory", "1", "2" );
 }
 
-extern __inline__ void 
+static __inline__ void 
 __constant_change_bit(const int nr, volatile void * addr) 
 {
   switch (nr&7) {
@@ -487,7 +466,7 @@
 /*
  * fast, non-SMP test_and_set_bit routine
  */
-extern __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
+static __inline__ int test_and_set_bit_simple(int nr, volatile void * addr)
 {
         static const int mask = 1;
         int oldbit;
@@ -512,7 +491,7 @@
 /*
  * fast, non-SMP test_and_clear_bit routine
  */
-extern __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
+static __inline__ int test_and_clear_bit_simple(int nr, volatile void * addr)
 {
         static const int mask = 1;
         int oldbit;
@@ -538,7 +517,7 @@
 /*
  * fast, non-SMP test_and_change_bit routine
  */
-extern __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
+static __inline__ int test_and_change_bit_simple(int nr, volatile void * addr)
 {
         static const int mask = 1;
         int oldbit;
@@ -582,7 +561,7 @@
  * This routine doesn't need to be atomic.
  */
 
-extern __inline__ int __test_bit(int nr, volatile void * addr)
+static __inline__ int __test_bit(int nr, volatile void * addr)
 {
         static const int mask = 1;
         int oldbit;
@@ -602,7 +581,7 @@
         return oldbit;
 }
 
-extern __inline__ int __constant_test_bit(int nr, volatile void * addr) {
+static __inline__ int __constant_test_bit(int nr, volatile void * addr) {
     return (((volatile char *) addr)[(nr>>3)^3] & (1<<(nr&7))) != 0;
 }
 
@@ -614,7 +593,7 @@
 /*
  * Find-bit routines..
  */
-extern __inline__ int find_first_zero_bit(void * addr, unsigned size)
+static __inline__ int find_first_zero_bit(void * addr, unsigned size)
 {
         static const int mask = 0xffL;
         int res;
@@ -633,7 +612,7 @@
                 "   lr   2,%1\n"
                 "   j    4f\n"
                 "1: l    1,0(2,%2)\n"
-                "   sll  2,3(0)\n"
+                "   sll  2,3\n"
                 "   tml  1,0xFFFF\n"
                 "   jno  2f\n"
                 "   ahi  2,16\n"
@@ -653,7 +632,7 @@
         return (res < size) ? res : size;
 }
 
-extern __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
 {
         static const int mask = 0xffL;
         unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
@@ -698,7 +677,7 @@
  * ffz = Find First Zero in word. Undefined if no zero exists,
  * so code should check against ~0UL first..
  */
-extern __inline__ unsigned long ffz(unsigned long word)
+static __inline__ unsigned long ffz(unsigned long word)
 {
         static const int mask = 0xffL;
         int result;
@@ -738,24 +717,24 @@
           return 0;
         __asm__("    lr   %%r1,%1\n"
                 "    sr   %0,%0\n"
-                "    tmh  %%r1,0xFFFF\n"
-                "    jz   0f\n"
+                "    tml  %%r1,0xFFFF\n"
+                "    jnz  0f\n"
                 "    ahi  %0,16\n"
                 "    srl  %%r1,16\n"
-                "0:  tml  %%r1,0xFF00\n"
-                "    jz   1f\n"
+                "0:  tml  %%r1,0x00FF\n"
+                "    jnz  1f\n"
                 "    ahi  %0,8\n"
                 "    srl  %%r1,8\n"
-                "1:  tml  %%r1,0x00F0\n"
-                "    jz   2f\n"
+                "1:  tml  %%r1,0x000F\n"
+                "    jnz  2f\n"
                 "    ahi  %0,4\n"
                 "    srl  %%r1,4\n"
-                "2:  tml  %%r1,0x000C\n"
-                "    jz   3f\n"
+                "2:  tml  %%r1,0x0003\n"
+                "    jnz  3f\n"
                 "    ahi  %0,2\n"
                 "    srl  %%r1,2\n"
-                "3:  tml  %%r1,0x0002\n"
-                "    jz   4f\n"
+                "3:  tml  %%r1,0x0001\n"
+                "    jnz  4f\n"
                 "    ahi  %0,1\n"
                 "4:"
                 : "=&d" (r) : "d" (x) : "cc", "1" );
@@ -787,9 +766,8 @@
 #define ext2_set_bit(nr, addr)       test_and_set_bit((nr)^24, addr)
 #define ext2_clear_bit(nr, addr)     test_and_clear_bit((nr)^24, addr)
 #define ext2_test_bit(nr, addr)      test_bit((nr)^24, addr)
-extern __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
+static __inline__ int ext2_find_first_zero_bit(void *vaddr, unsigned size)
 {
-        static const int mask = 0xffL;
         int res;
 
         if (!size)
@@ -806,7 +784,8 @@
                 "   lr   2,%1\n"
                 "   j    4f\n"
                 "1: l    1,0(2,%2)\n"
-                "   sll  2,3(0)\n"
+                "   sll  2,3\n"
+                "   lhi  0,0xff\n"
                 "   ahi  2,24\n"
                 "   tmh  1,0xFFFF\n"
                 "   jo   2f\n"
@@ -816,31 +795,19 @@
                 "   jo   3f\n"
                 "   ahi  2,-8\n"
                 "   srl  1,8\n"
-                "3: n    1,%3\n"
-                "   ic   1,0(1,%4)\n"
-                "   n    1,%3\n"
+                "3: nr   1,0\n"
+                "   ic   1,0(1,%3)\n"
                 "   ar   2,1\n"
                 "4: lr   %0,2"
                 : "=d" (res) : "a" (size), "a" (vaddr),
-                  "m" (mask), "a" (&_zb_findmap)
+                  "a" (&_zb_findmap)
                   : "cc", "0", "1", "2" );
         return (res < size) ? res : size;
 }
 
-extern __inline__ int 
+static __inline__ int 
 ext2_find_next_zero_bit(void *vaddr, unsigned size, unsigned offset)
 {
-        static const int mask = 0xffL;
-        static unsigned long orword[32] = {
-		0x00000000, 0x01000000, 0x03000000, 0x07000000,
-		0x0f000000, 0x1f000000, 0x3f000000, 0x7f000000,
-		0xff000000, 0xff010000, 0xff030000, 0xff070000,
-                0xff0f0000, 0xff1f0000, 0xff3f0000, 0xff7f0000,
-		0xffff0000, 0xffff0100, 0xffff0300, 0xffff0700,
-		0xffff0f00, 0xffff1f00, 0xffff3f00, 0xffff7f00,
-		0xffffff00, 0xffffff01, 0xffffff03, 0xffffff07,
-		0xffffff0f, 0xffffff1f, 0xffffff3f, 0xffffff7f
-	};
         unsigned long *addr = vaddr;
         unsigned long *p = addr + (offset >> 5);
         unsigned long word;
@@ -850,23 +817,29 @@
                 return size;
 
         if (bit) {
-		word = *p | orword[bit];
+                __asm__("   ic   %0,0(%1)\n"
+                        "   icm  %0,2,1(%1)\n"
+                        "   icm  %0,4,2(%1)\n"
+                        "   icm  %0,8,3(%1)"
+                        : "=&a" (word) : "a" (p) );
+		word >>= bit;
+                res = bit;
                 /* Look for zero in first longword */
-                __asm__("   lhi  %0,24\n"
-                	"   tmh  %1,0xFFFF\n"
-                	"   jo   0f\n"
-                	"   ahi  %0,-16\n"
+                __asm__("   lhi  0,0xff\n"
+                        "   tml  %1,0xffff\n"
+                	"   jno   0f\n"
+                	"   ahi  %0,16\n"
                 	"   srl  %1,16\n"
-                	"0: tml  %1,0xFF00\n"
-                	"   jo   1f\n"
-                	"   ahi  %0,-8\n"
+                	"0: tml  %1,0x00ff\n"
+                	"   jno  1f\n"
+                	"   ahi  %0,8\n"
                 	"   srl  %1,8\n"
-                	"1: n    %1,%2\n"
-                	"   ic   %1,0(%1,%3)\n"
+                	"1: nr   %1,0\n"
+                	"   ic   %1,0(%1,%2)\n"
                 	"   alr  %0,%1"
-                	: "=&d" (res), "+&d" (word)
-                  	: "m" (mask), "a" (&_zb_findmap)
-                	: "cc" );
+                	: "+&d" (res), "+&a" (word)
+                  	: "a" (&_zb_findmap)
+                	: "cc", "0" );
                 if (res < 32)
 			return (p - addr)*32 + res;
                 p++;
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/ccwcache.h linux/include/asm-s390/ccwcache.h
--- v2.4.1/linux/include/asm-s390/ccwcache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/ccwcache.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,84 @@
+/* 
+   * File...........: linux/include/asm-s390/ccwcache.h
+   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+   * Bugreports.to..: <Linux390@de.ibm.com>
+   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+#ifndef CCWCACHE_H
+#define CCWCACHE_H
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#ifndef __KERNEL__
+#define kmem_cache_t void
+#endif /* __KERNEL__ */
+
+typedef struct ccw_req_t {
+	/* eye catcher plus queueing information  */
+	unsigned int magic;	
+	struct ccw_req_t *next;	/* pointer to next ccw_req_t in queue */
+	struct ccw_req_t *int_next;	/* for internal queueing */
+	struct ccw_req_t *int_prev;	/* for internal queueing */
+
+	/* Where to execute what... */
+	void *device;		/* index of the device the req is for */
+	void *req;		/* pointer to originating request */
+	ccw1_t *cpaddr;		/* address of channel program */
+	char status;	        /* reflecting the status of this request */
+	char flags;              /* see below */
+	short retries;		/* A retry counter to be set when filling */
+
+	/* ... and how */
+	int options;		/* options for execution */
+	char lpm;               /* logical path mask                      */
+	void *data;		/* pointer to data area */
+	devstat_t *dstat;	/* The device status in case of an error */
+
+	/* these are important for recovering erroneous requests          */
+	struct ccw_req_t *refers;	/* Does this request refer to another one? */
+	void *function; /* refers to the originating ERP action */ ;
+
+	unsigned long long expires;	/* expiratioj period */
+	/* these are for profiling purposes */
+	unsigned long long buildclk;	/* TOD-clock of request generation */
+	unsigned long long startclk;	/* TOD-clock of request start */
+	unsigned long long stopclk;	/* TOD-clock of request interrupt */
+	unsigned long long endclk;	/* TOD-clock of request termination */
+
+	/* these are for internal use */
+	int cplength;		/* length of the channel program in CCWs */
+	int datasize;		/* amount of additional data in bytes */
+	kmem_cache_t *cache;	/* the cache this data comes from */
+
+} __attribute__ ((aligned(4))) ccw_req_t;
+
+/* 
+ * ccw_req_t -> status can be:
+ */
+#define CQR_STATUS_EMPTY    0x00	/* request is empty */
+#define CQR_STATUS_FILLED   0x01	/* request is ready to be preocessed */
+#define CQR_STATUS_QUEUED   0x02	/* request is queued to be processed */
+#define CQR_STATUS_IN_IO    0x03	/* request is currently in IO */
+#define CQR_STATUS_DONE     0x04	/* request is completed sucessfully */
+#define CQR_STATUS_ERROR    0x05	/* request is completed with error */
+#define CQR_STATUS_FAILED   0x06	/* request is finally failed */
+
+#define CQR_FLAGS_CHAINED  0x01	/* request is chained by another (last CCW is TIC) */
+
+#ifdef __KERNEL__
+#define SMALLEST_SLAB (sizeof(struct ccw_req_t) <= 128 ? 128 :\
+ sizeof(struct ccw_req_t) <= 256 ? 256 : 512 )
+
+/* SMALLEST_SLAB(1),... PAGE_SIZE(CCW_NUMBER_CACHES) */
+#define CCW_NUMBER_CACHES (sizeof(struct ccw_req_t) <= 128 ? 6 :\
+ sizeof(struct ccw_req_t) <= 256 ? 5 : 4 )
+
+int ccwcache_init (void);
+
+ccw_req_t *ccw_alloc_request (char *magic, int cplength, int additional_data);
+void ccw_free_request (ccw_req_t * request);
+#endif /* __KERNEL__ */
+#endif				/* CCWCACHE_H */
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/chandev.h linux/include/asm-s390/chandev.h
--- v2.4.1/linux/include/asm-s390/chandev.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/chandev.h	Tue Feb 13 14:13:44 2001
@@ -1,87 +1,151 @@
 /*
  *  include/asm-s390/chandev.h
  *
- *  S390 version
  *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
- *
+ * 
+ *  Generic channel device initialisation support. 
  */
-
+#include <linux/version.h>
 #include <asm/types.h>
+#include <linux/netdevice.h>
 
+/* chandev_type is a bitmask for registering & describing device types. */
 typedef enum
 {
-	none=0,
-	ctc=1,
-	escon=2,
-	lcs=4,
-	osad=8,
-	claw=16,
+	none=0x0,
+	ctc=0x1,
+	escon=0x2,
+	lcs=0x4,
+	osad=0x8,
+	qeth=0x10,
+	claw=0x20,
 } chandev_type;
 
-typedef struct chandev_model_info chandev_model_info;
-
-struct chandev_model_info
+typedef enum
 {
-	struct chandev_model_info *next;
+	no_category,
+	network_device,
+	serial_device,
+} chandev_category;
+
+/*
+ * The chandev_probeinfo structure is passed to the device driver with configuration
+ * info for which irq's & ports to use when attempting to probe the device.
+ */
+typedef struct
+{
+        int     read_irq;
+	int     write_irq;
+	u16     read_devno;
+	u16     write_devno;
+        s16     port_protocol_no; /* -1 don't care */
+	u8      hint_port_no;   /* lcs specific */
+	u8      max_port_no;    /* lcs specific */
 	chandev_type chan_type;
-	u16 cu_type;
-	u8  cu_model;
-	u8  max_port_no;
-};
+	u8      checksum_received_ip_pkts;
+	u8      use_hw_stats; /* where available e.g. lcs */
+	u16     cu_type;      /* control unit type */
+	u8      cu_model;     /* control unit model */
+	u16     dev_type;     /* device type */
+	u8      dev_model;    /* device model */
+	char    *parmstr;       /* driver specific parameters added by add_parms keyword */
+	/* newdevice used internally by chandev.c */
+	struct  chandev_activelist *newdevice; 
+	s32     devif_num; 
+/* devif_num=-1 implies don't care,0 implies tr0, info used by chandev_initnetdevice */
+} chandev_probeinfo;
 
-typedef struct chandev chandev;
-struct chandev
-{
-	struct chandev *next;
-	chandev_model_info *model_info;
-	u16 devno;
-	int irq;
-};
+/*
+ * This is a wrapper to the machine check handler & should be used
+ * instead of reqest_irq or s390_request_irq_special for anything
+ * using the channel device layer.
+ */
+int chandev_request_irq(unsigned int   irq,
+                      void           (*handler)(int, void *, struct pt_regs *),
+                      unsigned long  irqflags,
+                      const char    *devname,
+                      void          *dev_id);
 
-typedef struct chandev_noauto_range chandev_noauto_range;
-struct chandev_noauto_range
+typedef enum
 {
-	struct chandev_noauto_range *next;
-	u16     lo_devno;
-	u16     hi_devno;
-};
+	good=0,
+	not_oper,
+	first_msck=not_oper,
+	no_path,
+	revalidate,
+	gone,
+	last_msck,
+} chandev_msck_status;
+
+typedef int (*chandev_probefunc)(chandev_probeinfo *probeinfo);
+typedef void (*chandev_shutdownfunc)(void *device);
+typedef void (*chandev_unregfunc)(void *device);
+typedef void (*chandev_reoperfunc)(void *device,int msck_for_read_chan,chandev_msck_status prevstatus);
+
+
+
+/* A driver should call chandev_register_and_probe when ready to be probed,
+ * after registeration the drivers probefunction will be called asynchronously
+ * when more devices become available at normal task time.
+ * The shutdownfunc parameter is used so that the channel layer
+ * can request a driver to close unregister itself & release its interrupts.
+ * repoper func is used when a device becomes operational again after being temporarily
+ * not operational the previous status is sent in the prevstatus variable.
+ * This can be used in cases when the default handling isn't quite adequete
+ * e.g. if a ssch is needed to reinitialize long running channel programs.
+ */
+int chandev_register_and_probe(chandev_probefunc probefunc,
+			       chandev_shutdownfunc shutdownfunc,
+			       chandev_reoperfunc reoperfunc,
+			       chandev_type chan_type);
+
+/* The chandev_unregister function is typically called when a module is being removed 
+ * from the system. The shutdown parameter if TRUE calls shutdownfunc for each 
+ * device instance so the driver writer doesn't have to.
+ */
+void chandev_unregister(chandev_probefunc probefunc,int call_shutdown);
+
+/* chandev_initdevice should be called immeadiately before returning after */
+/* a successful probe. */
+int chandev_initdevice(chandev_probeinfo *probeinfo,void *dev_ptr,u8 port_no,char *devname,
+chandev_category category,chandev_unregfunc unreg_dev);
+
+/* chandev_initnetdevice registers a network device with the channel layer. 
+ * It returns the device structure if successful,if dev=NULL it kmallocs it, 
+ * On device initialisation failure it will kfree it under ALL curcumstances
+ * i.e. if dev is not NULL on entering this routine it MUST be malloced with kmalloc. 
+ * The base name is tr ( e.g. tr0 without the 0 ), for token ring eth for ethernet,
+ *  ctc or escon for ctc device drivers.
+ * If valid function pointers are given they will be called to setup,
+ * register & unregister the device. 
+ * An example of setup is eth_setup in drivers/net/net_init.c.
+ * An example of init_dev is init_trdev(struct net_device *dev)
+ * & an example of unregister is unregister_trdev, 
+ * unregister_netdev should be used for escon & ctc
+ * as there is no network unregister_ctcdev in the kernel.
+*/
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+					 struct net_device *dev,int sizeof_priv, 
+					 char *basename, 
+					 struct net_device *(*init_netdevfunc)
+					 (struct net_device *dev, int sizeof_priv),
+					 void (*unreg_netdevfunc)(struct net_device *dev));
+#else
+struct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+				     struct device *dev,int sizeof_priv,
+				     char *basename, 
+				     struct device *(*init_netdevfunc)
+				     (struct device *dev, int sizeof_priv),
+				     void (*unreg_netdevfunc)(struct device *dev));
+#endif
 
-typedef struct chandev_force chandev_force;
-struct chandev_force
-{
-	struct chandev_force *next;
-	chandev_type chan_type;
-	s32     devif_num; /* -1 don't care e.g. tr0 implies 0 */
-        u16     read_devno;
-	u16     write_devno;
-        s16     port_no; /* where available e.g. lcs,-1 don't care */
-	u8      do_ip_checksumming;
-	u8      use_hw_stats; /* where available e.g. lcs */
-};
 
 
 
-typedef struct
-{
-	s32     devif_num; /* -1 don't care e.g. tr0 implies 0 */
-        int     read_irq;
-	int     write_irq;
-        s16     forced_port_no; /* -1 don't care */
-	u8      hint_port_no;
-	u8      max_port_no;
-	u8      do_ip_checksumming;
-	u8      use_hw_stats; /* where available e.g. lcs */
-} chandev_probeinfo;
 
 
-typedef int (*chandev_probefunc)(chandev_probeinfo *probeinfo);
 
 
-typedef struct chandev_probelist chandev_probelist;
-struct chandev_probelist
-{
-	struct chandev_probelist *next;
-	chandev_probefunc       probefunc;
-	chandev_type            chan_type;
-};
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/checksum.h linux/include/asm-s390/checksum.h
--- v2.4.1/linux/include/asm-s390/checksum.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/checksum.h	Tue Feb 13 14:13:44 2001
@@ -141,20 +141,19 @@
                    unsigned int sum)
 {
 	__asm__ __volatile__ (
-		"    sll   %3,16\n"
-		"    or    %3,%4\n"  /* newproto=proto<<16 in hiword, len in lowword */
-		"    alr   %1,%2\n"  /* saddr+=daddr */
-		"    brc   12,0f\n"
-		"    ahi   %1,1\n"   /* add carry */
-		"0:  alr   %1,%3\n"  /* add saddr+=newproto */
-		"    brc   12,1f\n"
-		"    ahi   %1,1\n"   /* add carry again */
-		"1:  alr   %0,%1\n"  /* sum+=saddr */
+                "    alr   %0,%1\n"  /* sum += saddr */
+                "    brc   12,0f\n"
+		"    ahi   %0,1\n"   /* add carry */
+		"0:  alr   %0,%2\n"  /* sum += daddr */
+                "    brc   12,1f\n"
+                "    ahi   %0,1\n"   /* add carry */
+		"1:  alr   %0,%3\n"  /* sum += (len<<16) + (proto<<8) */
 		"    brc   12,2f\n"
-		"    ahi   %0,1\n"   /* add carry again */
+		"    ahi   %0,1\n"   /* add carry */
 		"2:"
 		: "+&d" (sum)
-		: "d" (saddr), "d" (daddr), "d" (proto), "d" (len)
+		: "d" (saddr), "d" (daddr),
+		  "d" (((unsigned int) len<<16) + (unsigned int) proto)
 		: "cc" );
 	return sum;
 }
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/current.h linux/include/asm-s390/current.h
--- v2.4.1/linux/include/asm-s390/current.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/current.h	Tue Feb 13 14:13:44 2001
@@ -20,7 +20,7 @@
         struct task_struct *current;
         __asm__("lhi   %0,-8192\n\t"
                 "nr    %0,15"
-                : "=r" (current) );
+                : "=&r" (current) );
         return current;
  }
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/dasd.h linux/include/asm-s390/dasd.h
--- v2.4.1/linux/include/asm-s390/dasd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/dasd.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,339 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ */
+
+#ifndef DASD_H
+#define DASD_H
+
+#include <linux/ioctl.h>
+#include <asm/irq.h>
+
+#define IOCTL_LETTER 'D'
+/* Disable the volume (for Linux) */
+#define BIODASDDISABLE _IO(IOCTL_LETTER,0) 
+/* Enable the volume (for Linux) */
+#define BIODASDENABLE  _IO(IOCTL_LETTER,1) 
+/* Issue a reserve/release command, rsp. */
+#define BIODASDRSRV    _IO(IOCTL_LETTER,2) /* reserve */
+#define BIODASDRLSE    _IO(IOCTL_LETTER,3) /* release */
+#define BIODASDSLCK    _IO(IOCTL_LETTER,4) /* steal lock */
+/* Read sense ID infpormation */
+#define BIODASDRSID    _IOR(IOCTL_LETTER,0,senseid_t)
+/* Format the volume or an extent */
+#define BIODASDFORMAT  _IOW(IOCTL_LETTER,0,format_data_t) 
+/* translate blocknumber of partition to absolute */
+#define BIODASDRWTB    _IOWR(IOCTL_LETTER,0,int)
+
+#define DASD_NAME "dasd"
+#define DASD_PARTN_BITS 2
+#define DASD_PER_MAJOR ( 1U<<(MINORBITS-DASD_PARTN_BITS))
+
+/* 
+ * struct format_data_t
+ * represents all data necessary to format a dasd
+ */
+typedef struct format_data_t {
+	int start_unit; /* from track */
+	int stop_unit;  /* to track */
+	int blksize;    /* sectorsize */
+        int intensity;  /* 0: normal, 1:record zero, 3:home address, 4 invalidate tracks */
+} __attribute__ ((packed)) format_data_t;
+
+#define DASD_FORMAT_DEFAULT_START_UNIT 0
+#define DASD_FORMAT_DEFAULT_STOP_UNIT -1
+#define DASD_FORMAT_DEFAULT_BLOCKSIZE -1
+#define DASD_FORMAT_DEFAULT_INTENSITY -1
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#include <linux/major.h>
+#include <linux/wait.h>
+#include <asm/ccwcache.h>
+#include <linux/blk.h> 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#include <linux/blkdev.h> 
+#include <linux/devfs_fs_kernel.h>
+#endif
+#include <linux/genhd.h>
+#include <linux/hdreg.h>
+#include <linux/compatmac.h>
+
+#include <asm/s390dyn.h>
+#include <asm/todclk.h>
+#include <asm/debug.h>
+
+/* Kernel Version Compatibility section */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+typedef struct request *request_queue_t;
+#define block_device_operations file_operations
+#define __setup(x,y) struct dasd_device_t
+#define devfs_register_blkdev(major,name,ops) register_blkdev(major,name,ops)
+#define register_disk(dd,dev,partn,ops,size) \
+do { \
+	dd->sizes[MINOR(dev)] = size >> 1; \
+	resetup_one_dev(dd,MINOR(dev)>>DASD_PARTN_BITS); \
+} while(0)
+#define init_waitqueue_head(x) do { *x = NULL; } while(0)
+#define blk_cleanup_queue(x) do {} while(0)
+#define blk_init_queue(x...) do {} while(0)
+#define blk_queue_headactive(x...) do {} while(0)
+#define blk_queue_make_request(x) do {} while(0)
+#define list_empty(x) (0)
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+        blk_dev[d_major].request_fn = d_request_fn; \
+        blk_dev[d_major].queue = d_queue_fn; \
+        blk_dev[d_major].current_request = d_current; \
+} while(0)
+#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
+	major:D_MAJOR, \
+	major_name:D_NAME, \
+	minor_shift:D_PARTN_BITS, \
+	max_p:1 << D_PARTN_BITS, \
+	max_nr:D_PER_MAJOR, \
+	nr_real:D_PER_MAJOR,
+static inline struct request * 
+dasd_next_request( request_queue_t *queue ) 
+{
+    return *queue;
+}
+static inline void 
+dasd_dequeue_request( request_queue_t * q, struct request *req )
+{
+        *q = req->next;
+        req->next = NULL;
+}
+#else
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+        blk_dev[d_major].queue = d_queue_fn; \
+} while(0)
+#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
+	major:D_MAJOR, \
+	major_name:D_NAME, \
+	minor_shift:D_PARTN_BITS, \
+	max_p:1 << D_PARTN_BITS, \
+	nr_real:D_PER_MAJOR,
+static inline struct request * 
+dasd_next_request( request_queue_t *queue ) 
+{
+        return blkdev_entry_next_request(&queue->queue_head);
+}
+static inline void 
+dasd_dequeue_request( request_queue_t * q, struct request *req )
+{
+        blkdev_dequeue_request (req);
+}
+#endif
+
+/* dasd_range_t are used for dynamic device att-/detachment */
+typedef struct dasd_devreg_t {
+        devreg_t devreg; /* the devreg itself */
+        /* build a linked list of devregs, needed for cleanup */
+        struct dasd_devreg_t *next;
+} dasd_devreg_t;
+
+typedef enum {
+	dasd_era_fatal = -1,	/* no chance to recover              */
+	dasd_era_none = 0,	/* don't recover, everything alright */
+	dasd_era_msg = 1,	/* don't recover, just report...     */
+	dasd_era_recover = 2	/* recovery action recommended       */
+} dasd_era_t;
+
+/* BIT DEFINITIONS FOR SENSE DATA */
+#define DASD_SENSE_BIT_0 0x80
+#define DASD_SENSE_BIT_1 0x40
+#define DASD_SENSE_BIT_2 0x20
+#define DASD_SENSE_BIT_3 0x10
+
+#define check_then_set(where,from,to) \
+do { \
+        if ((*(where)) != (from) ) { \
+                printk (KERN_ERR PRINTK_HEADER "was %d\n", *(where)); \
+                BUG(); \
+        } \
+        (*(where)) = (to); \
+} while (0)
+
+#define DASD_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
+do { \
+        int d_devno = d_device->devinfo.devno; \
+        int d_irq = d_device->devinfo.irq; \
+        char *d_name = d_device->name; \
+        int d_major = MAJOR(d_device->kdev); \
+        int d_minor = MINOR(d_device->kdev); \
+        printk(d_loglevel PRINTK_HEADER \
+               "/dev/%s(%d:%d), 0x%04X on SCH 0x%x:" \
+               d_string "\n",d_name,d_major,d_minor,d_devno,d_irq,d_args ); \
+} while(0)
+
+/* 
+ * struct dasd_sizes_t
+ * represents all data needed to access dasd with properly set up sectors
+ */
+typedef
+struct dasd_sizes_t {
+	unsigned long blocks; /* size of volume in blocks */
+	unsigned int bp_block; /* bytes per block */
+	unsigned int s2b_shift; /* log2 (bp_block/512) */
+} dasd_sizes_t;
+
+/* 
+ * struct dasd_chanq_t 
+ * represents a queue of channel programs related to a single device
+ */
+typedef
+struct dasd_chanq_t {
+	ccw_req_t *head;
+	ccw_req_t *tail;
+} dasd_chanq_t;
+
+struct dasd_device_t;
+struct request;
+
+/* 
+ * signatures for the functions of dasd_discipline_t 
+ * make typecasts much easier
+ */
+typedef ccw_req_t *(*dasd_erp_action_fn_t) (ccw_req_t * cqr);
+typedef ccw_req_t *(*dasd_erp_postaction_fn_t) (ccw_req_t * cqr);
+
+typedef int (*dasd_ck_id_fn_t) (s390_dev_info_t *);
+typedef int (*dasd_ck_characteristics_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_fill_geometry_fn_t) (struct dasd_device_t *, struct hd_geometry *);
+typedef ccw_req_t *(*dasd_format_fn_t) (struct dasd_device_t *, struct format_data_t *);
+typedef ccw_req_t *(*dasd_init_analysis_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_do_analysis_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_io_starter_fn_t) (ccw_req_t *);
+typedef void (*dasd_int_handler_fn_t)(int irq, void *, struct pt_regs *);
+typedef dasd_era_t (*dasd_error_examine_fn_t) (ccw_req_t *, devstat_t * stat);
+typedef dasd_erp_action_fn_t (*dasd_error_analyse_fn_t) (ccw_req_t *);
+typedef dasd_erp_postaction_fn_t (*dasd_erp_analyse_fn_t) (ccw_req_t *);
+typedef ccw_req_t *(*dasd_cp_builder_fn_t)(struct dasd_device_t *,struct request *);
+typedef char *(*dasd_dump_sense_fn_t)(struct dasd_device_t *,ccw_req_t *);
+typedef ccw_req_t *(*dasd_reserve_fn_t)(struct dasd_device_t *);
+typedef ccw_req_t *(*dasd_release_fn_t)(struct dasd_device_t *);
+typedef ccw_req_t *(*dasd_merge_cp_fn_t)(struct dasd_device_t *);
+
+
+/*
+ * the dasd_discipline_t is
+ * sth like a table of virtual functions, if you think of dasd_eckd
+ * inheriting dasd...
+ * no, currently we are not planning to reimplement the driver in C++
+ */
+typedef struct dasd_discipline_t {
+	char ebcname[8]; /* a name used for tagging and printks */
+        char name[8];		/* a name used for tagging and printks */
+
+	dasd_ck_id_fn_t id_check;	/* to check sense data */
+	dasd_ck_characteristics_fn_t check_characteristics;	/* to check the characteristics */
+	dasd_init_analysis_fn_t init_analysis;	/* to start the analysis of the volume */
+	dasd_do_analysis_fn_t do_analysis;	/* to complete the analysis of the volume */
+	dasd_fill_geometry_fn_t fill_geometry;	/* to set up hd_geometry */
+	dasd_io_starter_fn_t start_IO;
+        dasd_format_fn_t format_device;		/* to format the device */
+	dasd_error_examine_fn_t examine_error;
+	dasd_error_analyse_fn_t erp_action;
+	dasd_erp_analyse_fn_t erp_postaction;
+        dasd_cp_builder_fn_t build_cp_from_req;
+        dasd_dump_sense_fn_t dump_sense;
+        dasd_int_handler_fn_t int_handler;
+        dasd_reserve_fn_t reserve;
+        dasd_release_fn_t release;
+        dasd_merge_cp_fn_t merge_cp;
+	
+	struct dasd_discipline_t *next;	/* used for list of disciplines */
+} dasd_discipline_t;
+
+typedef struct major_info_t {
+	struct major_info_t *next;
+	struct dasd_device_t **dasd_device;
+	struct gendisk gendisk; /* actually contains the major number */
+} __attribute__ ((packed)) major_info_t;
+
+typedef struct dasd_profile_info_t {
+        unsigned long dasd_io_reqs;	/* number of requests processed at all */
+        unsigned long dasd_io_secs[32];	/* histogram of request's sizes */
+        unsigned long dasd_io_times[32];	/* histogram of requests's times */
+        unsigned long dasd_io_timps[32];	/* histogram of requests's times per sector */
+        unsigned long dasd_io_time1[32];	/* histogram of time from build to start */
+       unsigned  long dasd_io_time2[32];	/* histogram of time from start to irq */
+        unsigned long dasd_io_time2ps[32];	/* histogram of time from start to irq */
+        unsigned long dasd_io_time3[32];	/* histogram of time from irq to end */
+} dasd_profile_info_t;
+
+typedef struct dasd_device_t {
+	s390_dev_info_t devinfo;
+	dasd_discipline_t *discipline;
+	int level;
+        int open_count;
+        kdev_t kdev;
+        major_info_t *major_info;
+	struct dasd_chanq_t queue;
+        wait_queue_head_t wait_q;
+        request_queue_t request_queue;
+	devstat_t dev_status; /* needed ONLY!! for request_irq */
+        dasd_sizes_t sizes;
+        char name[16]; /* The name of the device in /dev */
+	char *private;	/* to be used by the discipline internally */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+        devfs_handle_t devfs_entry;
+#endif /* LINUX_IS_24 */
+	struct tq_struct bh_tq;
+        atomic_t bh_scheduled;
+        debug_info_t *debug_area;
+        dasd_profile_info_t profile;
+        struct proc_dir_entry *proc_dir; /* directory node */
+        struct proc_dir_entry *proc_info; /* information from dasd_device_t */
+        struct proc_dir_entry *proc_stats; /* statictics information */
+}  dasd_device_t;
+
+/* dasd_device_t.level can be: */
+#define DASD_DEVICE_LEVEL_UNKNOWN 0x00
+#define DASD_DEVICE_LEVEL_RECOGNIZED 0x01
+#define DASD_DEVICE_LEVEL_ANALYSIS_PENDING 0x02
+#define DASD_DEVICE_LEVEL_ANALYSIS_PREPARED 0x04
+#define DASD_DEVICE_LEVEL_ANALYSED 0x08
+#define DASD_DEVICE_LEVEL_PARTITIONED 0x10
+
+int dasd_init (void);
+void dasd_discipline_enq (dasd_discipline_t *);
+int dasd_discipline_deq(dasd_discipline_t *);
+int dasd_start_IO (ccw_req_t *);
+void dasd_int_handler (int , void *, struct pt_regs *);
+ccw_req_t *default_erp_action (ccw_req_t *);
+ccw_req_t *default_erp_postaction (ccw_req_t *);
+int dasd_chanq_deq (dasd_chanq_t *, ccw_req_t *);
+ccw_req_t *dasd_alloc_request (char *, int, int);
+void dasd_free_request (ccw_req_t *);
+int (*genhd_dasd_name) (char *, int, int, struct gendisk *);
+int dasd_oper_handler (int irq, devreg_t * devreg);
+
+#endif /* __KERNEL__ */
+
+#endif				/* DASD_H */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/debug.h linux/include/asm-s390/debug.h
--- v2.4.1/linux/include/asm-s390/debug.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/debug.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,210 @@
+/*
+ *  include/asm-s390/debug.h
+ *   S/390 debug facility
+ *
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+ *                             IBM Corporation
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* Note:
+ * struct __debug_entry must be defined outside of #ifdef __KERNEL__ 
+ * in order to allow a user program to analyze the 'raw'-view.
+ */
+
+struct __debug_entry{
+        union {
+                struct {
+                        unsigned long long clock:52;
+                        unsigned long long exception:1;
+                        unsigned long long used:1;
+                        unsigned long long unused:1;
+                        unsigned long long cpuid:9;
+                } fields;
+
+                unsigned long long stck;
+        } id;
+        void* caller;
+} __attribute__((packed));
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+ #include <asm/spinlock.h>
+#else
+ #include <linux/spinlock.h>
+#endif /* LINUX_VERSION_CODE */
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+
+#define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
+#define DEBUG_OFF_LEVEL            -1 /* level where debug is switched off */
+#define DEBUG_MAX_VIEWS            10 /* max number of views in proc fs */
+#define DEBUG_MAX_PROCF_LEN        16 /* max length for a proc file name */
+#define DEBUG_DEFAULT_LEVEL        3  /* initial debug level */
+#define DEBUG_FEATURE_VERSION      1  /* version of debug feature */
+
+#define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
+
+#define DEBUG_DATA(entry) (char*)(entry + 1) /* data is stored behind */
+                                             /* the entry information */
+
+#define STCK(x)	asm volatile ("STCK %0":"=m" (x))
+
+typedef struct __debug_entry debug_entry_t;
+
+struct debug_view;
+
+typedef struct debug_info {	
+	struct debug_info* next;
+	struct debug_info* prev;
+	atomic_t ref_count;
+	spinlock_t lock;			
+	int level;
+	int nr_areas;
+	int page_order;
+	int buf_size;
+	int entry_size;	
+	debug_entry_t** areas;
+	int active_area;
+	int *active_entry;
+	struct proc_dir_entry* proc_root_entry;
+	struct proc_dir_entry* proc_entries[DEBUG_MAX_VIEWS];
+	struct debug_view* views[DEBUG_MAX_VIEWS];	
+	char name[DEBUG_MAX_PROCF_LEN];
+} debug_info_t;
+
+typedef int (debug_header_proc_t) (debug_info_t* id,
+				   struct debug_view* view,
+				   int area,
+				   debug_entry_t* entry,
+				   char* out_buf);
+
+typedef int (debug_format_proc_t) (debug_info_t* id,
+				   struct debug_view* view, char* out_buf,
+				   const char* in_buf);
+typedef int (debug_prolog_proc_t) (debug_info_t* id,
+				   struct debug_view* view,
+				   char* out_buf);
+typedef int (debug_input_proc_t) (debug_info_t* id,
+				  struct debug_view* view,
+				  struct file* file, const char* user_buf,
+				  size_t in_buf_size, loff_t* offset);
+
+int debug_dflt_header_fn(debug_info_t* id, struct debug_view* view,
+		         int area, debug_entry_t* entry, char* out_buf);						
+				
+struct debug_view {
+	char name[DEBUG_MAX_PROCF_LEN];
+	debug_prolog_proc_t* prolog_proc;
+	debug_header_proc_t* header_proc;
+	debug_format_proc_t* format_proc;
+	debug_input_proc_t*  input_proc;
+};
+
+extern struct debug_view debug_hex_ascii_view;
+extern struct debug_view debug_raw_view;
+
+debug_info_t* debug_register(char* name, int pages_index, int nr_areas,
+			     int buf_size);
+void debug_unregister(debug_info_t* id);
+
+void debug_set_level(debug_info_t* id, int new_level);
+
+debug_entry_t* debug_event(debug_info_t* id, int level, void* data,
+			   int length);
+debug_entry_t* debug_int_event(debug_info_t* id, int level,
+			       unsigned int tag);
+debug_entry_t* debug_text_event(debug_info_t* id, int level,
+				const char* txt);
+
+debug_entry_t* debug_exception(debug_info_t* id, int level, void* data,
+			       int length);
+debug_entry_t* debug_int_exception(debug_info_t* id, int level,
+				   unsigned int tag);
+debug_entry_t* debug_text_exception(debug_info_t* id, int level,
+				    const char* txt);
+
+static inline debug_entry_t *
+debug_long_event (debug_info_t* id, int level, unsigned long tag)
+{
+	unsigned long t=tag;
+	return debug_event(id,level,&t,sizeof(unsigned long));
+}
+static inline debug_entry_t *
+debug_long_exception (debug_info_t* id, int level, unsigned long tag)
+{
+	unsigned long t=tag;
+	return debug_exception(id,level,&t,sizeof(unsigned long));
+}
+int debug_register_view(debug_info_t* id, struct debug_view* view);
+int debug_unregister_view(debug_info_t* id, struct debug_view* view);
+
+/*
+   define the debug levels:
+   - 0 No debugging output to console or syslog
+   - 1 Log internal errors to syslog, ignore check conditions 
+   - 2 Log internal errors and check conditions to syslog
+   - 3 Log internal errors to console, log check conditions to syslog
+   - 4 Log internal errors and check conditions to console
+   - 5 panic on internal errors, log check conditions to console
+   - 6 panic on both, internal errors and check conditions
+ */
+
+#ifndef DEBUG_LEVEL
+#define DEBUG_LEVEL 4
+#endif
+
+#define INTERNAL_ERRMSG(x,y...) "E" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_WRNMSG(x,y...) "W" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_INFMSG(x,y...) "I" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_DEBMSG(x,y...) "D" __FILE__ "%d: " x, __LINE__, y
+
+#if DEBUG_LEVEL > 0
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER x )
+#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER x )
+#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER x )
+#define PRINT_FATAL(x...) panic ( PRINTK_HEADER x )
+#else
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#endif				/* DASD_DEBUG */
+
+#if DASD_DEBUG > 4
+#define INTERNAL_ERROR(x...) PRINT_FATAL ( INTERNAL_ERRMSG ( x ) )
+#elif DASD_DEBUG > 2
+#define INTERNAL_ERROR(x...) PRINT_ERR ( INTERNAL_ERRMSG ( x ) )
+#elif DASD_DEBUG > 0
+#define INTERNAL_ERROR(x...) PRINT_WARN ( INTERNAL_ERRMSG ( x ) )
+#else
+#define INTERNAL_ERROR(x...)
+#endif				/* DASD_DEBUG */
+
+#if DASD_DEBUG > 5
+#define INTERNAL_CHECK(x...) PRINT_FATAL ( INTERNAL_CHKMSG ( x ) )
+#elif DASD_DEBUG > 3
+#define INTERNAL_CHECK(x...) PRINT_ERR ( INTERNAL_CHKMSG ( x ) )
+#elif DASD_DEBUG > 1
+#define INTERNAL_CHECK(x...) PRINT_WARN ( INTERNAL_CHKMSG ( x ) )
+#else
+#define INTERNAL_CHECK(x...)
+#endif				/* DASD_DEBUG */
+
+#undef DEBUG_MALLOC
+#ifdef DEBUG_MALLOC
+void *b;
+#define kmalloc(x...) (PRINT_INFO(" kmalloc %p\n",b=kmalloc(x)),b)
+#define kfree(x) PRINT_INFO(" kfree %p\n",x);kfree(x)
+#define get_free_page(x...) (PRINT_INFO(" gfp %p\n",b=get_free_page(x)),b)
+#define __get_free_pages(x...) (PRINT_INFO(" gfps %p\n",b=__get_free_pages(x)),b)
+#endif				/* DEBUG_MALLOC */
+
+#endif				/* __KERNEL__ */
+#endif				/* DEBUG_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/delay.h linux/include/asm-s390/delay.h
--- v2.4.1/linux/include/asm-s390/delay.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/delay.h	Tue Feb 13 14:13:44 2001
@@ -15,11 +15,8 @@
 #define _S390_DELAY_H
 
 extern void __udelay(unsigned long usecs);
-extern void __const_udelay(unsigned long usecs);
 extern void __delay(unsigned long loops);
 
-#define udelay(n) (__builtin_constant_p(n) ? \
-	__const_udelay((n) * 0x10c6ul) : \
-	__udelay(n))
+#define udelay(n) __udelay(n)
 
 #endif /* defined(_S390_DELAY_H) */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/dma.h linux/include/asm-s390/dma.h
--- v2.4.1/linux/include/asm-s390/dma.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/dma.h	Tue Feb 13 14:13:44 2001
@@ -1,5 +1,5 @@
 /*
- *  include/asm-s390/delay.h
+ *  include/asm-s390/dma.h
  *
  *  S390 version
  *
@@ -11,7 +11,6 @@
 
 #include <asm/io.h>		/* need byte IO */
 
-#define MAX_DMA_CHANNELS	0
 #define MAX_DMA_ADDRESS         0x80000000
 
 #endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/ebcdic.h linux/include/asm-s390/ebcdic.h
--- v2.4.1/linux/include/asm-s390/ebcdic.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/ebcdic.h	Tue Feb 13 14:13:44 2001
@@ -14,6 +14,8 @@
 #include <types.h>
 #endif
 
+extern __u8 _ascebc_500[];   /* ASCII -> EBCDIC 500 conversion table */
+extern __u8 _ebcasc_500[];   /* EBCDIC 500 -> ASCII conversion table */
 extern __u8 _ascebc[];   /* ASCII -> EBCDIC conversion table */
 extern __u8 _ebcasc[];   /* EBCDIC -> ASCII conversion table */
 extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
@@ -44,6 +46,8 @@
 
 #define ASCEBC(addr,nr) codepage_convert(_ascebc, addr, nr)
 #define EBCASC(addr,nr) codepage_convert(_ebcasc, addr, nr)
+#define ASCEBC_500(addr,nr) codepage_convert(_ascebc_500, addr, nr)
+#define EBCASC_500(addr,nr) codepage_convert(_ebcasc_500, addr, nr)
 #define EBC_TOLOWER(addr,nr) codepage_convert(_ebc_tolower, addr, nr)
 #define EBC_TOUPPER(addr,nr) codepage_convert(_ebc_toupper, addr, nr)
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/elf.h linux/include/asm-s390/elf.h
--- v2.4.1/linux/include/asm-s390/elf.h	Tue Jul 11 19:02:37 2000
+++ linux/include/asm-s390/elf.h	Tue Feb 13 14:13:44 2001
@@ -19,10 +19,6 @@
 
 typedef s390_fp_regs elf_fpregset_t;
 typedef s390_regs elf_gregset_t;
-/*
- * This is used to ensure we don't load something for the wrong architecture.
- */
-#define elf_check_arch(x) ((x)->e_machine == EM_S390) 
 
 /*
  * These are used to set parameters in the core dumps.
@@ -31,6 +27,12 @@
 #define ELF_DATA	ELFDATA2MSB
 #define ELF_ARCH	EM_S390
 
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+	((x)->e_machine == ELF_ARCH && (x)->e_ident[EI_CLASS] == ELF_CLASS) 
+
 /* For SVR4/S390 the function pointer to be registered with `atexit` is
    passed in R14. */
 #define ELF_PLAT_INIT(_r) \
@@ -73,8 +75,7 @@
 #define ELF_PLATFORM (NULL)
 
 #ifdef __KERNEL__
-#define SET_PERSONALITY(ex, ibcs2) \
-	current->personality = (ibcs2 ? PER_SVR4 : PER_LINUX)
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
 #endif
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/fcntl.h linux/include/asm-s390/fcntl.h
--- v2.4.1/linux/include/asm-s390/fcntl.h	Fri Sep 22 14:21:21 2000
+++ linux/include/asm-s390/fcntl.h	Tue Feb 13 14:13:44 2001
@@ -42,6 +42,11 @@
 #define F_SETSIG	10	/*  for sockets. */
 #define F_GETSIG	11	/*  for sockets. */
 
+#define F_GETLK64	12	/*  using 'struct flock64' */
+#define F_SETLK64	13
+#define F_SETLKW64	14
+                               
+
 /* for F_[GET|SET]FL */
 #define FD_CLOEXEC	1	/* actually anything with low bit set goes */
 
@@ -75,6 +80,14 @@
 	off_t l_start;
 	off_t l_len;
 	pid_t l_pid;
+};
+
+struct flock64 {
+	short  l_type;
+	short  l_whence;
+	loff_t l_start;
+	loff_t l_len;
+	pid_t  l_pid;
 };
 
 #define F_LINUX_SPECIFIC_BASE	1024
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/hardirq.h linux/include/asm-s390/hardirq.h
--- v2.4.1/linux/include/asm-s390/hardirq.h	Fri Aug  4 16:15:37 2000
+++ linux/include/asm-s390/hardirq.h	Tue Feb 13 14:13:44 2001
@@ -50,14 +50,14 @@
  * Special definitions for s390, always access current PSA.
  */
 #define in_interrupt() ((S390_lowcore.__local_irq_count + S390_lowcore.__local_bh_count) != 0)
-
+  
 #define in_irq() (S390_lowcore.__local_irq_count != 0)
-
+  
 #ifndef CONFIG_SMP
-
+  
 #define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
 #define hardirq_endlock(cpu)	do { } while (0)
-
+  
 #define hardirq_enter(cpu)	(local_irq_count(cpu)++)
 #define hardirq_exit(cpu)	(local_irq_count(cpu)--)
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/idals.h linux/include/asm-s390/idals.h
--- v2.4.1/linux/include/asm-s390/idals.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/idals.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,57 @@
+/* 
+   * File...........: linux/include/asm-s390x/idals.h
+   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+   * Bugreports.to..: <Linux390@de.ibm.com>
+   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
+   
+   * History of changes
+   * 07/24/00 new file
+ */
+#include <linux/config.h>
+#include <asm/irq.h>
+
+typedef unsigned long idaw_t;
+
+static inline idaw_t *
+idal_alloc ( int nridaws )
+{
+	if ( nridaws > 33 )
+		BUG();
+	return kmalloc(nridaws * sizeof(idaw_t), GFP_ATOMIC | GFP_DMA );
+}
+
+static inline void 
+idal_free ( idaw_t *idal )
+{
+	kfree (idal);
+}
+
+/*
+ * Function: set_normalized_cda
+ * sets the address of the data in CCW
+ * if necessary it allocates an IDAL and sets sthe appropriate flags
+ */
+#if defined (CONFIG_ARCH_S390X)
+extern void set_normalized_cda(ccw1_t * ccw, unsigned long address);
+#else
+static inline void
+set_normalized_cda(ccw1_t * ccw, unsigned long address)
+{
+	ccw->cda = address;
+}
+#endif
+
+/*
+ * Function: clear_normalized_cda
+ * releases any allocated IDAL related to the CCW
+ */
+static inline void
+clear_normalized_cda ( ccw1_t * ccw ) 
+{
+	if ( ccw -> flags & CCW_FLAG_IDA ) {
+		idal_free ( (idaw_t *) (ccw -> cda ));
+		ccw -> flags &= ~CCW_FLAG_IDA;
+	}
+	ccw -> cda = 0;
+}
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/io.h linux/include/asm-s390/io.h
--- v2.4.1/linux/include/asm-s390/io.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/io.h	Tue Feb 13 14:13:44 2001
@@ -27,7 +27,7 @@
 extern inline unsigned long virt_to_phys(volatile void * address)
 {
 	unsigned long real_address;
-	__asm__ ("   lra    %0,0(0,%1)\n"
+	__asm__ ("   lra    %0,0(%1)\n"
                  "   jz     0f\n"
                  "   sr     %0,%0\n"
                  "0:"
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/ioctls.h linux/include/asm-s390/ioctls.h
--- v2.4.1/linux/include/asm-s390/ioctls.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/ioctls.h	Tue Feb 13 14:13:44 2001
@@ -73,6 +73,7 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define FIOQSIZE	0x545E
 
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/irq.h linux/include/asm-s390/irq.h
--- v2.4.1/linux/include/asm-s390/irq.h	Fri Aug  4 16:15:37 2000
+++ linux/include/asm-s390/irq.h	Tue Feb 13 14:13:44 2001
@@ -1,15 +1,8 @@
-/*
- *  arch/s390/kernel/s390io.h
- *
- *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Ingo Adlung (adlung@de.ibm.com)
- */
-
 #ifndef __irq_h
 #define __irq_h
 
 #include <linux/config.h>
+#ifdef __KERNEL__
 #include <asm/hardirq.h>
 
 /*
@@ -18,6 +11,8 @@
 #define __MAX_SUBCHANNELS 65536
 #define NR_IRQS           __MAX_SUBCHANNELS
 
+#define LPM_ANYPATH 0xff /* doesn't really belong here, Ingo? */
+
 #define INVALID_STORAGE_AREA ((void *)(-1 - 0x3FFF ))
 
 extern int disable_irq(unsigned int);
@@ -50,7 +45,8 @@
  */
 typedef struct {
       __u32 intparm;      /* interruption parameter */
-      __u32 res0 : 2;     /* reserved zeros */
+      __u32 qf   : 1;     /* qdio facility */
+      __u32 res0 : 1;     /* reserved zeros */
       __u32 isc  : 3;     /* interruption sublass */
       __u32 res5 : 3;     /* reserved zeros */
       __u32 ena  : 1;     /* enabled */
@@ -77,6 +73,7 @@
                           /*  ... in an operand exception.       */
    } __attribute__ ((packed)) pmcw_t;
 
+#endif /* __KERNEL__ */
 /*
  * subchannel status word
  */
@@ -89,7 +86,7 @@
       __u32 pfch : 1; /* prefetch */
       __u32 isic : 1; /* initial-status interruption control */
       __u32 alcc : 1; /* address-limit checking control */
-      __u32 ssi  : 1; /* supress-suspended interruption */
+      __u32 ssi  : 1; /* suppress-suspended interruption */
       __u32 zcc  : 1; /* zero condition code */
       __u32 ectl : 1; /* extended control */
       __u32 pno  : 1;     /* path not operational */
@@ -140,6 +137,44 @@
 #define SCHN_STAT_CHAIN_CHECK    0x01
 
 /*
+ * architectured values for first sense byte
+ */
+#define SNS0_CMD_REJECT         0x80
+#define SNS_CMD_REJECT          SNS0_CMD_REJECT
+#define SNS0_INTERVENTION_REQ   0x40
+#define SNS0_BUS_OUT_CHECK      0x20
+#define SNS0_EQUIPMENT_CHECK    0x10
+#define SNS0_DATA_CHECK         0x08
+#define SNS0_OVERRUN            0x04
+/*                              0x02 reserved */
+#define SNS0_INCOMPL_DOMAIN     0x01
+
+/*
+ * architectured values for second sense byte
+ */
+#define SNS1_PERM_ERR           0x80
+#define SNS1_INV_TRACK_FORMAT   0x40
+#define SNS1_EOC                0x20
+#define SNS1_MESSAGE_TO_OPER    0x10
+#define SNS1_NO_REC_FOUND       0x08
+#define SNS1_FILE_PROTECTED     0x04
+#define SNS1_WRITE_INHIBITED    0x02
+#define SNS1_INPRECISE_END      0x01
+
+/*
+ * architectured values for third sense byte
+ */
+#define SNS2_REQ_INH_WRITE      0x80
+#define SNS2_CORRECTABLE        0x40
+#define SNS2_FIRST_LOG_ERR      0x20
+#define SNS2_ENV_DATA_PRESENT   0x10
+/*                              0x08 reserved */
+#define SNS2_INPRECISE_END      0x04
+/*                              0x02 reserved */
+/*                              0x01 reserved */
+
+#ifdef __KERNEL__
+/*
  * subchannel information block
  */
 typedef struct {
@@ -147,13 +182,14 @@
       scsw_t scsw;             /* subchannel status word */
       __u8 mda[12];            /* model dependent area */
    } __attribute__ ((packed,aligned(4))) schib_t;
+#endif /* __KERNEL__ */
 
 typedef struct {
       __u8  cmd_code;/* command code */
-      __u8  flags;   /* flags, like IDA adressing, etc. */
+      __u8  flags;   /* flags, like IDA addressing, etc. */
       __u16 count;   /* byte count */
       __u32 cda;     /* data address */
-   } ccw1_t __attribute__ ((packed,aligned(8)));
+   } __attribute__ ((packed,aligned(8))) ccw1_t;
 
 #define CCW_FLAG_DC             0x80
 #define CCW_FLAG_CC             0x40
@@ -168,10 +204,13 @@
 #define CCW_CMD_BASIC_SENSE     0x04
 #define CCW_CMD_TIC             0x08
 #define CCW_CMD_SENSE_PGID      0x34
+#define CCW_CMD_SUSPEND_RECONN  0x5B
 #define CCW_CMD_RDC             0x64
 #define CCW_CMD_SET_PGID        0xAF
 #define CCW_CMD_SENSE_ID        0xE4
+#define CCW_CMD_DCTL            0xF3
 
+#ifdef __KERNEL__
 #define SENSE_MAX_COUNT         0x20
 
 /*
@@ -192,19 +231,25 @@
       __u32 intparm;  /* interruption parameter */
       __u32 key  : 4; /* flags, like key, suspend control, etc. */
       __u32 spnd : 1; /* suspend control */
-      __u32 res1 : 3; /* reserved */
+      __u32 res1 : 1; /* reserved */
+      __u32 mod  : 1; /* modification control */
+      __u32 sync : 1; /* synchronize control */
       __u32 fmt  : 1; /* format control */
       __u32 pfch : 1; /* prefetch control */
       __u32 isic : 1; /* initial-status-interruption control */
       __u32 alcc : 1; /* address-limit-checking control */
       __u32 ssic : 1; /* suppress-suspended-interr. control */
-      __u32 res2 : 3; /* reserved */
+      __u32 res2 : 1; /* reserved */
+      __u32 c64  : 1; /* IDAW/QDIO 64 bit control  */
+      __u32 i2k  : 1; /* IDAW 2/4kB block size control */
       __u32 lpm  : 8; /* logical path mask */
       __u32 ils  : 1; /* incorrect length */
-      __u32 zero : 7; /* reserved zeros */
+      __u32 zero : 6; /* reserved zeros */
+      __u32 orbx : 1; /* ORB extension control */
       __u32 cpa;      /* channel program address */
    }  __attribute__ ((packed,aligned(4))) orb_t;
 
+#endif /* __KERNEL__ */
 typedef struct {
       __u32 res0  : 4;  /* reserved */
       __u32 pvrf  : 1;  /* path-verification-required flag */
@@ -249,7 +294,7 @@
 typedef struct {
       __u8  zero0;    /* reserved zeros */
       __u8  lpum;     /* last path used mask */
-      __u8  zero16;   /* reserved zeros */
+      __u16 zero16;   /* reserved zeros */
       erw_t erw;      /* extended report word */
       __u32 zeros[3]; /* 2 fullwords of zeros */
    } __attribute__ ((packed)) esw1_t;
@@ -291,30 +336,24 @@
       esw_t  esw;              /* extended status word */
       __u8   ecw[32];          /* extended control word */
    } irb_t __attribute__ ((packed,aligned(4)));
+#ifdef __KERNEL__
 
 /*
  * TPI info structure
  */
 typedef struct {
-      __u32 res : 16;   /* reserved 0x00000001 */
-      __u32 irq : 16;   /* aka. subchannel number */
-      __u32 intparm;    /* interruption parameter */
+	__u32 reserved1  : 16;   /* reserved 0x00000001 */
+	__u32 irq        : 16;   /* aka. subchannel number */
+	__u32 intparm;           /* interruption parameter */
+	__u32 adapter_IO : 1;
+	__u32 reserved2  : 1;
+	__u32 isc        : 3;
+	__u32 reserved3  : 12;
+	__u32 int_type   : 3;
+	__u32 reserved4  : 12;
    } __attribute__ ((packed)) tpi_info_t;
 
 
-/*
- * 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 {
-      __u32                     status;    /* IRQ status - IRQ_INPROGRESS, IRQ_DISABLED */
-      struct hw_interrupt_type *handler;   /* handle/enable/disable functions */
-      struct irqaction         *action;    /* IRQ action list */
-   } irq_desc_t;
-
 //
 // command information word  (CIW) layout
 //
@@ -330,6 +369,7 @@
 #define CIW_TYPE_SII    0x1    // set interface identifier
 #define CIW_TYPE_RNI    0x2    // read node identifier
 
+#define MAX_CIWS 8
 //
 // sense-id response buffer layout
 //
@@ -342,9 +382,10 @@
       __u8           dev_model;    /* device model */
       __u8           unused;       /* padding byte */
   /* extended part */
-      ciw_t    ciw[62];            /* variable # of CIWs */
+      ciw_t    ciw[MAX_CIWS];      /* variable # of CIWs */
    }  __attribute__ ((packed,aligned(4))) senseid_t;
 
+#endif /* __KERNEL__ */
 /*
  * sense data
  */
@@ -363,7 +404,7 @@
  */
 typedef struct {
      __u16         devno;    /* device number, aka. "cuu" from irb */
-     unsigned int  intparm;  /* interrupt parameter */
+     unsigned long intparm;  /* interrupt parameter */
      __u8          cstat;    /* channel status - accumulated */
      __u8          dstat;    /* device status - accumulated */
      __u8          lpum;     /* last path used mask from irb */
@@ -387,9 +428,53 @@
 #define DEVSTAT_DEVICE_GONE        0x00000040
 #define DEVSTAT_DEVICE_OWNED       0x00000080
 #define DEVSTAT_CLEAR_FUNCTION     0x00000100
+#define DEVSTAT_PCI                0x00000200
+#define DEVSTAT_SUSPENDED          0x00000400
+#define DEVSTAT_UNKNOWN_DEV        0x00000800
 #define DEVSTAT_FINAL_STATUS       0x80000000
 
+#define DEVINFO_NOT_OPER           DEVSTAT_NOT_OPER
+#define DEVINFO_UNKNOWN_DEV        DEVSTAT_UNKNOWN_DEV
+#define DEVINFO_DEVICE_OWNED       DEVSTAT_DEVICE_OWNED
+#define DEVINFO_QDIO_CAPABLE       0x40000000
+
 #define INTPARM_STATUS_PENDING     0xFFFFFFFF
+#ifdef __KERNEL__
+
+#define IO_INTERRUPT_TYPE          0 /* I/O interrupt type */
+
+typedef  void (* io_handler_func1_t) ( int             irq,
+                                       devstat_t      *devstat,
+                                       struct pt_regs *rgs);
+
+typedef  void (* io_handler_func_t) ( int             irq,
+                                      void           *devstat,
+                                      struct pt_regs *rgs);
+
+typedef  void ( * not_oper_handler_func_t)( int irq,
+                                            int status );
+
+typedef  int  (* adapter_int_handler_t)( __u32 intparm );
+
+struct s390_irqaction {
+	io_handler_func_t  handler;
+	unsigned long      flags;
+	const char        *name;
+	devstat_t         *dev_id;
+};
+
+/*
+ * 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 s390_irqaction    *action;    /* IRQ action list */
+   } irq_desc_t;
 
 typedef struct {
 	__u8  state1    :  2;   /* path state value 1 */
@@ -409,36 +494,39 @@
 	__u32 tod_high;         /* high word TOD clock */
 	} __attribute__ ((packed)) pgid_t;
 
+#define SPID_FUNC_SINGLE_PATH      0x00
 #define SPID_FUNC_MULTI_PATH       0x80
 #define SPID_FUNC_ESTABLISH        0x00
 #define SPID_FUNC_RESIGN           0x40
 #define SPID_FUNC_DISBAND          0x20
 
-#define SNID_STATE1_RESET          0x0
-#define SNID_STATE1_UNGROUPED      0x8
-#define SNID_STATE1_GROUPED        0xC
-
-#define SNID_STATE2_NOT_RESVD      0x0
-#define SNID_STATE2_RESVD_ELSE     0x8
-#define SNID_STATE2_RESVD_SELF     0xC
+#define SNID_STATE1_RESET          0
+#define SNID_STATE1_UNGROUPED      2
+#define SNID_STATE1_GROUPED        3
+
+#define SNID_STATE2_NOT_RESVD      0
+#define SNID_STATE2_RESVD_ELSE     2
+#define SNID_STATE2_RESVD_SELF     3
 
 #define SNID_STATE3_MULTI_PATH     1
+#define SNID_STATE3_SINGLE_PATH    0
 
 /*
  * Flags used as input parameters for do_IO()
  */
-#define DOIO_EARLY_NOTIFICATION 0x01    /* allow for I/O completion ... */
+#define DOIO_EARLY_NOTIFICATION  0x0001 /* allow for I/O completion ... */
                                         /* ... notification after ... */
                                         /* ... primary interrupt status */
-#define DOIO_RETURN_CHAN_END       DOIO_EARLY_NOTIFICATION
-#define DOIO_VALID_LPM          0x02    /* LPM input parameter is valid */
-#define DOIO_WAIT_FOR_INTERRUPT 0x04    /* wait synchronously for interrupt */
-#define DOIO_REPORT_ALL         0x08    /* report all interrupt conditions */
-#define DOIO_ALLOW_SUSPEND      0x10    /* allow for channel prog. suspend */
-#define DOIO_DENY_PREFETCH      0x20    /* don't allow for CCW prefetch */
-#define DOIO_SUPPRESS_INTER     0x40    /* suppress intermediate inter. */
+#define DOIO_RETURN_CHAN_END     DOIO_EARLY_NOTIFICATION
+#define DOIO_VALID_LPM           0x0002 /* LPM input parameter is valid */
+#define DOIO_WAIT_FOR_INTERRUPT  0x0004 /* wait synchronously for interrupt */
+#define DOIO_REPORT_ALL          0x0008 /* report all interrupt conditions */
+#define DOIO_ALLOW_SUSPEND       0x0010 /* allow for channel prog. suspend */
+#define DOIO_DENY_PREFETCH       0x0020 /* don't allow for CCW prefetch */
+#define DOIO_SUPPRESS_INTER      0x0040 /* suppress intermediate inter. */
                                         /* ... for suspended CCWs */
-#define DOIO_TIMEOUT            0x80    /* 3 secs. timeout for sync. I/O */
+#define DOIO_TIMEOUT             0x0080 /* 3 secs. timeout for sync. I/O */
+#define DOIO_DONT_CALL_INTHDLR   0x0100 /* don't call interrupt handler */
 
 /*
  * do_IO()
@@ -464,7 +552,7 @@
 
 int start_IO( int           irq,       /* IRQ aka. subchannel number */
               ccw1_t       *cpa,       /* logical channel program address */
-              unsigned int  intparm,   /* interruption parameter */
+              unsigned long  intparm,   /* interruption parameter */
               __u8          lpm,       /* logical path mask */
               unsigned int  flag);     /* flags : see above */
 
@@ -493,12 +581,12 @@
      __u16        devno;                /* device number */
      unsigned int status;               /* device status */
      senseid_t    sid_data;             /* senseID data */
-     } dev_info_t;
+     } s390_dev_info_t;
 
-int get_dev_info( int irq, dev_info_t *);   /* to be eliminated - don't use */
+int get_dev_info( int irq, s390_dev_info_t *);   /* to be eliminated - don't use */
 
-int get_dev_info_by_irq  ( int irq, dev_info_t *pdi);
-int get_dev_info_by_devno( __u16 devno, dev_info_t *pdi);
+int get_dev_info_by_irq  ( int irq, s390_dev_info_t *pdi);
+int get_dev_info_by_devno( __u16 devno, s390_dev_info_t *pdi);
 
 int          get_irq_by_devno( __u16 devno );
 unsigned int get_devno_by_irq( int irq );
@@ -507,7 +595,16 @@
 int get_irq_next ( int irq );
 
 int read_dev_chars( int irq, void **buffer, int length );
-int read_conf_data( int irq, void **buffer, int *length );
+int read_conf_data( int irq, void **buffer, int *length, __u8 lpm );
+
+int  s390_DevicePathVerification( int irq, __u8 domask );
+
+int s390_request_irq_special( int                      irq,
+                              io_handler_func_t        io_handler,
+                              not_oper_handler_func_t  not_oper_handler,
+                              unsigned long            irqflags,
+                              const char              *devname,
+                              void                    *dev_id);
 
 extern int handle_IRQ_event( unsigned int irq, int cpu, struct pt_regs *);
 
@@ -524,7 +621,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "STSCH 0(%2)\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -538,7 +639,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "MSCH 0(%2)\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -552,6 +657,21 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "    lgr  1,%1\n"
+                "    msch 0(%2)\n"
+                "0:  ipm  %0\n"
+                "    srl  %0,28\n"
+                "1:\n"
+                ".section .fixup,\"ax\"\n"
+                "2:  l    %0,%3\n"
+                "    jg   1b\n"
+                ".previous\n"
+                ".section __ex_table,\"a\"\n"
+                "   .align 8\n"
+                "   .quad 0b,2b\n"
+                ".previous"
+#else
                 "    lr   1,%1\n"
                 "    msch 0(%2)\n"
                 "0:  ipm  %0\n"
@@ -568,6 +688,7 @@
                 "   .align 4\n"
                 "   .long 0b,2b\n"
                 ".previous"
+#endif
                 : "=d" (ccode)
                 : "r" (irq | 0x10000L), "a" (addr), "i" (__LC_PGM_ILC)
                 : "cc", "1" );
@@ -579,7 +700,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "TSCH 0(%2)\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -606,7 +731,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "SSCH 0(%2)\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -620,7 +749,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "RSCH\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -634,7 +767,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "CSCH\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -648,7 +785,11 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
                 "LR 1,%1\n\t"
+#endif
                 "HSCH\n\t"
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
@@ -669,6 +810,24 @@
         return ccode;
 }
 
+extern __inline__ int rchp(int chpid)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "RCHP\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (chpid)
+                : "cc", "1" );
+        return ccode;
+}
+
 typedef struct {
      __u16 vrdcdvno : 16;   /* device number (input) */
      __u16 vrdclen  : 16;   /* data block length (input) */
@@ -690,12 +849,18 @@
         int ccode;
 
         __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "SAM31\n\t"
+                "DIAG %1,0,0x210\n\t"
+                "SAM64\n\t"
+#else
                 "LR 1,%1\n\t"
                 ".long 0x83110210\n\t"
+#endif
                 "IPM %0\n\t"
                 "SRL %0,28\n\t"
                 : "=d" (ccode) : "a" (addr)
-                : "cc", "1" );
+                : "cc" );
         return ccode;
 }
 
@@ -720,9 +885,15 @@
 static inline void irq_enter(int cpu, unsigned int irq)
 {
         hardirq_enter(cpu);
+#ifdef CONFIG_ARCH_S390X
+        while (atomic_read(&global_irq_lock) != 0) {
+                eieio();
+        }
+#else
         while (test_bit(0,&global_irq_lock)) {
                 eieio();
         }
+#endif
 }
 
 static inline void irq_exit(int cpu, unsigned int irq)
@@ -754,10 +925,13 @@
  * x86 profiling function, SMP safe. We might want to do this in
  * assembly totally?
  */
+extern char _stext;
 static inline void s390_do_profile (unsigned long addr)
 {
-#if 0
         if (prof_buffer && current->pid) {
+#ifndef CONFIG_ARCH_S390X
+                addr &= 0x7fffffff;
+#endif
                 addr -= (unsigned long) &_stext;
                 addr >>= prof_shift;
                 /*
@@ -769,7 +943,6 @@
                         addr = prof_len-1;
                 atomic_inc((atomic_t *)&prof_buffer[addr]);
         }
-#endif
 }
 
 #include <asm/s390io.h>
@@ -784,5 +957,6 @@
         spin_lock_irqsave(&(ioinfo[irq]->irq_lock), flags)
 #define s390irq_spin_unlock_irqrestore(irq,flags) \
         spin_unlock_irqrestore(&(ioinfo[irq]->irq_lock), flags)
+#endif /* __KERNEL__ */
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/irqextras390.h linux/include/asm-s390/irqextras390.h
--- v2.4.1/linux/include/asm-s390/irqextras390.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/irqextras390.h	Tue Feb 13 14:13:44 2001
@@ -100,7 +100,7 @@
 
       __u16	count;
 
-      void	*ccw_data_address;
+      __u32     ccw_data_address;
 } ccw1_bits_t __attribute__((packed,aligned(8)));
 
 typedef struct
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/lowcore.h linux/include/asm-s390/lowcore.h
--- v2.4.1/linux/include/asm-s390/lowcore.h	Fri Aug  4 16:15:37 2000
+++ linux/include/asm-s390/lowcore.h	Tue Feb 13 14:13:44 2001
@@ -31,10 +31,11 @@
 #define __LC_SUBCHANNEL_ID              0x0B8
 #define __LC_SUBCHANNEL_NR              0x0BA
 #define __LC_IO_INT_PARM                0x0BC
+#define __LC_IO_INT_WORD                0x0C0
 #define __LC_MCCK_CODE                  0x0E8
-#define __LC_AREGS_SAVE_AREA            0x200
-#define __LC_CREGS_SAVE_AREA            0x240
-#define __LC_RETURN_PSW                 0x280
+#define __LC_AREGS_SAVE_AREA            0x120
+#define __LC_CREGS_SAVE_AREA            0x1C0
+#define __LC_RETURN_PSW                 0x200
 
 #define __LC_SYNC_IO_WORD               0x400
 
@@ -45,7 +46,7 @@
 #define __LC_CPUID                      0xC60
 #define __LC_CPUADDR                    0xC68
 #define __LC_IPLDEV                     0xC7C
-
+#define __LC_PANIC_MAGIC                0xE00
 
 /* interrupt handler start with all io, external and mcck interrupt disabled */
 
@@ -53,7 +54,7 @@
 #define _EXT_PSW_MASK        0x04080000
 #define _PGM_PSW_MASK        0x04080000
 #define _SVC_PSW_MASK        0x04080000
-#define _MCCK_PSW_MASK       0x040A0000
+#define _MCCK_PSW_MASK       0x04080000
 #define _IO_PSW_MASK         0x04080000
 #define _USER_PSW_MASK       0x070DC000/* DAT, IO, EXT, Home-space         */
 #define _WAIT_PSW_MASK       0x070E0000/* DAT, IO, EXT, Wait, Home-space   */
@@ -119,7 +120,8 @@
 	__u16        subchannel_id;            /* 0x0b8 */
 	__u16        subchannel_nr;            /* 0x0ba */
 	__u32        io_int_parm;              /* 0x0bc */
-	__u8         pad3[0xD8-0xC0];          /* 0x0c0 */
+	__u32        io_int_word;              /* 0x0c0 */
+        __u8         pad3[0xD8-0xC4];          /* 0x0c4 */
 	__u32        cpu_timer_save_area[2];   /* 0x0d8 */
 	__u32        clock_comp_save_area[2];  /* 0x0e0 */
 	__u32        mcck_interuption_code[2]; /* 0x0e8 */
@@ -128,15 +130,14 @@
 	__u32        failing_storage_address;  /* 0x0f8 */
 	__u8         pad5[0x100-0xfc];         /* 0x0fc */
 	__u32        st_status_fixed_logout[4];/* 0x100 */
-	__u8         pad6[0x160-0x110];        /* 0x110 */
+	__u8         pad6[0x120-0x110];        /* 0x110 */
+	__u32        access_regs_save_area[16];/* 0x120 */
 	__u32        floating_pt_save_area[8]; /* 0x160 */
 	__u32        gpregs_save_area[16];     /* 0x180 */
-	__u8         pad7[0x200-0x1c0];        /* 0x1c0 */
-
-	__u32        access_regs_save_area[16];/* 0x200 */
 	__u32        cregs_save_area[16];      /* 0x240 */	
-        psw_t        return_psw;               /* 0x280 */
-	__u8         pad8[0x400-0x288];        /* 0x288 */
+
+        psw_t        return_psw;               /* 0x200 */
+	__u8         pad8[0x400-0x208];        /* 0x208 */
 
 	__u32        sync_io_word;	       /* 0x400 */
 
@@ -163,9 +164,14 @@
 	atomic_t     ext_call_fast;            /* 0xc88 */
 	atomic_t     ext_call_queue;           /* 0xc8c */
         atomic_t     ext_call_count;           /* 0xc90 */
+        __u8         pad11[0xe00-0xc94];       /* 0xc94 */
 
-        /* Align SMP info to the top 1k of prefix area */
-	__u8         pad11[0x1000-0xc94];      /* 0xc94 */
+        /* 0xe00 is used as indicator for dump tools */
+        /* whether the kernel died with panic() or not */
+        __u32        panic_magic;              /* 0xe00 */
+
+        /* Align to the top 1k of prefix area */
+	__u8         pad12[0x1000-0xe04];      /* 0xe04 */
 } __attribute__((packed)); /* End structure*/
 
 extern __inline__ void set_prefix(__u32 address)
@@ -185,6 +191,8 @@
         ((cpu)==smp_processor_id() ? S390_lowcore:(*lowcore_ptr[(cpu)]))
 #endif
 #endif /* __ASSEMBLY__ */
+
+#define __PANIC_MAGIC           0xDEADC0DE
 
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/mathemu.h linux/include/asm-s390/mathemu.h
--- v2.4.1/linux/include/asm-s390/mathemu.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/mathemu.h	Tue Feb 13 14:13:44 2001
@@ -12,12 +12,12 @@
 
 extern int math_emu_b3(__u8 *, struct pt_regs *);
 extern int math_emu_ed(__u8 *, struct pt_regs *);
-extern void math_emu_ldr(__u8 *);
-extern void math_emu_ler(__u8 *);
-extern void math_emu_std(__u8 *, struct pt_regs *);
-extern void math_emu_ld(__u8 *, struct pt_regs *);
-extern void math_emu_ste(__u8 *, struct pt_regs *);
-extern void math_emu_le(__u8 *, struct pt_regs *);
+extern int math_emu_ldr(__u8 *);
+extern int math_emu_ler(__u8 *);
+extern int math_emu_std(__u8 *, struct pt_regs *);
+extern int math_emu_ld(__u8 *, struct pt_regs *);
+extern int math_emu_ste(__u8 *, struct pt_regs *);
+extern int math_emu_le(__u8 *, struct pt_regs *);
 extern int math_emu_lfpc(__u8 *, struct pt_regs *);
 extern int math_emu_stfpc(__u8 *, struct pt_regs *);
 extern int math_emu_srnm(__u8 *, struct pt_regs *);
@@ -45,4 +45,7 @@
 extern __u64  __extendsfdf2(__u32);
 
 #endif                                 /* __MATHEMU__                      */
+
+
+
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/misc390.h linux/include/asm-s390/misc390.h
--- v2.4.1/linux/include/asm-s390/misc390.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/misc390.h	Tue Feb 13 14:13:44 2001
@@ -12,3 +12,4 @@
 
 #define	allocaligned(type,name,number)  allocaligned2(type,name,number,__alignof__(type))
 
+extern void s390_daemonize(char *name,unsigned long mask,int use_init_fs);
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/mmu_context.h linux/include/asm-s390/mmu_context.h
--- v2.4.1/linux/include/asm-s390/mmu_context.h	Thu Aug 10 13:30:05 2000
+++ linux/include/asm-s390/mmu_context.h	Tue Feb 13 14:13:44 2001
@@ -27,7 +27,8 @@
         unsigned long pgd;
 
         if (prev != next) {
-                pgd = (__pa(next->pgd) & PAGE_MASK) | _SEGMENT_TABLE;
+	        pgd = (__pa(next->pgd)&PAGE_MASK) | 
+                      (_SEGMENT_TABLE|USER_STD_MASK);
                 /* Load page tables */
                 asm volatile("    lctl  7,7,%0\n"   /* secondary space */
                              "    lctl  13,13,%0\n" /* home space */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/namei.h linux/include/asm-s390/namei.h
--- v2.4.1/linux/include/asm-s390/namei.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/namei.h	Tue Feb 13 14:13:44 2001
@@ -16,7 +16,6 @@
  * Look at asm-sparc/namei.h for details.
  */
 
-#define __prefix_lookup_dentry(name, lookup_flags) \
-        do {} while (0)
+#define __emul_prefix() NULL
 
 #endif /* __S390_NAMEI_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/page.h linux/include/asm-s390/page.h
--- v2.4.1/linux/include/asm-s390/page.h	Wed Aug  9 13:46:01 2000
+++ linux/include/asm-s390/page.h	Tue Feb 13 14:13:44 2001
@@ -17,7 +17,15 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#define STRICT_MM_TYPECHECKS
+/*
+ * gcc uses builtin, i.e. MVCLE for both operations
+ */
+
+#define clear_page(page)        memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from)      memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr)	clear_page(page)
+#define copy_user_page(to, from, vaddr)	copy_page(to, from)
 
 #define BUG() do { \
         printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
@@ -43,14 +51,6 @@
 }
 
 /*
- * gcc uses builtin, i.e. MVCLE for both operations
- */
-
-#define clear_page(page)        memset((void *)(page), 0, PAGE_SIZE)
-#define copy_page(to,from)      memcpy((void *)(to), (void *)(from), PAGE_SIZE)
-
-#ifdef STRICT_MM_TYPECHECKS
-/*
  * These are used to make use of C type-checking..
  */
 typedef struct { unsigned long pte; } pte_t;
@@ -73,48 +73,18 @@
 #define __pgd(x)        ((pgd_t) { (x) } )
 #define __pgprot(x)     ((pgprot_t) { (x) } )
 
-#else
-/*
- * .. while these make it easier on the compiler
- */
-typedef unsigned long pte_t;
-typedef unsigned long pmd_t;
-typedef struct {
-        unsigned long pgd0;
-        unsigned long pgd1;
-        unsigned long pgd2;
-        unsigned long pgd3;
-        } pgd_t;
-typedef unsigned long pgprot_t;
-
-#define pte_val(x)      (x)
-#define pmd_val(x)      (x)
-#define pgd_val(x)      (x)
-#define pgprot_val(x)   (x)
-
-#define __pte(x)        (x)
-#define __pmd(x)        (x)
-#define __pgd(x)        (x)
-#define __pgprot(x)     (x)
-
-#endif
-#endif                                 /* !__ASSEMBLY__                    */
+#endif /* !__ASSEMBLY__ */
 
 /* to align the pointer to the (next) page boundary */
 #define PAGE_ALIGN(addr)        (((addr)+PAGE_SIZE-1)&PAGE_MASK)
 
-/*
- *
- *
- */
-
-#define __PAGE_OFFSET           (0x0)
-#define PAGE_OFFSET             ((unsigned long)__PAGE_OFFSET)
-#define __pa(x)                 ((unsigned long)(x)-PAGE_OFFSET)
-#define __va(x)                 ((void *)((unsigned long)(x)+PAGE_OFFSET))
+#define __PAGE_OFFSET           0x0UL
+#define PAGE_OFFSET             0x0UL
+#define __pa(x)                 (unsigned long)(x)
+#define __va(x)                 (void *)(x)
 #define virt_to_page(kaddr)	(mem_map + (__pa(kaddr) >> PAGE_SHIFT))
 #define VALID_PAGE(page)	((page - mem_map) < max_mapnr)
 
-#endif                                 /* __KERNEL__                       */
+#endif /* __KERNEL__ */
 
-#endif                                 /* _S390_PAGE_H                     */
+#endif /* _S390_PAGE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/param.h linux/include/asm-s390/param.h
--- v2.4.1/linux/include/asm-s390/param.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/param.h	Tue Feb 13 14:13:44 2001
@@ -25,4 +25,8 @@
 
 #define MAXHOSTNAMELEN	64	/* max length of hostname */
 
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC		HZ	/* frequency at which times() counts */
+#endif
+
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/pgalloc.h linux/include/asm-s390/pgalloc.h
--- v2.4.1/linux/include/asm-s390/pgalloc.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/pgalloc.h	Tue Feb 13 14:13:44 2001
@@ -31,7 +31,7 @@
 extern __inline__ pgd_t* get_pgd_slow(void)
 {
         int i;
-        pgd_t *pgd,*ret = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
+        pgd_t *pgd,*ret = (pgd_t *)__get_free_pages(GFP_KERNEL,1);
 	if (ret)
 		for (i=0,pgd=ret;i<USER_PTRS_PER_PGD;i++,pgd++)
 			pmd_clear(pmd_offset(pgd,i*PGDIR_SIZE));
@@ -40,47 +40,80 @@
 
 extern __inline__ pgd_t* get_pgd_fast(void)
 {
-        unsigned long *ret;
+        unsigned long *ret = pgd_quicklist;
 	
-        if((ret = pgd_quicklist) != NULL) {
+        if (ret != NULL) {
                 pgd_quicklist = (unsigned long *)(*ret);
                 ret[0] = ret[1];
-                pgtable_cache_size--;
-		/*
-		 * Need to flush tlb, since private page tables
-		 * are unique thru address of pgd and virtual address.
-		 * If we reuse pgd we need to be sure no tlb entry
-		 * with that pdg is left -> global flush
-		 *
-		 * Fixme: To avoid this global flush we should
-		 * use pdg_quicklist as fix lenght fifo list
-		 * and not as stack
-		 */
-        } else
-                ret = (unsigned long *)get_pgd_slow();
+                pgtable_cache_size -= 2;
+        }
         return (pgd_t *)ret;
 }
 
+extern __inline__ pgd_t *pgd_alloc(void)
+{
+	pgd_t *pgd;
+
+	pgd = get_pgd_fast();
+	if (!pgd)
+		pgd = get_pgd_slow();
+	return pgd;
+}
+
 extern __inline__ void free_pgd_fast(pgd_t *pgd)
 {
         *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
         pgd_quicklist = (unsigned long *) pgd;
-        pgtable_cache_size++;
+        pgtable_cache_size += 2;
 }
 
 extern __inline__ void free_pgd_slow(pgd_t *pgd)
 {
-        free_pages((unsigned long)pgd,2);
+        free_pages((unsigned long) pgd, 1);
+}
+
+#define pgd_free(pgd)           free_pgd_fast(pgd)
+
+/*
+ * page middle directory allocation/free routines.
+ * We don't use pmd cache, so these are dummy routines.
+ */
+extern __inline__ pmd_t *get_pmd_fast(void)
+{
+        return (pmd_t *)0;
+}
+
+extern __inline__ void free_pmd_fast(pmd_t *pmd)
+{
+}
+
+extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
+{
+        return (pmd_t *) pgd;
+}
+
+extern __inline__ void free_pmd_slow(pmd_t *pmd)
+{
+}
+
+extern inline void pmd_free(pmd_t * pmd)
+{
 }
 
+#define pmd_free_kernel         pmd_free
+#define pmd_alloc_kernel        pmd_alloc
+
+/*
+ * page table entry allocation/free routines.
+ */
+extern pte_t empty_bad_pte_table[];
 extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
-extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);
 
 extern __inline__ pte_t* get_pte_fast(void)
 {
-        unsigned long *ret;
+        unsigned long *ret = (unsigned long *) pte_quicklist;
 
-        if((ret = (unsigned long *)pte_quicklist) != NULL) {
+        if (ret != NULL) {
                 pte_quicklist = (unsigned long *)(*ret);
                 ret[0] = ret[1];
                 pgtable_cache_size--;
@@ -90,6 +123,8 @@
 
 extern __inline__ void free_pte_fast(pte_t *pte)
 {
+	if (pte == empty_bad_pte_table)
+		return;
         *(unsigned long *)pte = (unsigned long) pte_quicklist;
         pte_quicklist = (unsigned long *) pte;
         pgtable_cache_size++;
@@ -97,79 +132,41 @@
 
 extern __inline__ void free_pte_slow(pte_t *pte)
 {
-        free_page((unsigned long)pte);
-}
-
-#define pte_free_kernel(pte)    free_pte_fast(pte)
-#define pte_free(pte)           free_pte_fast(pte)
-#define pgd_free(pgd)           free_pgd_fast(pgd)
-#define pgd_alloc()             get_pgd_fast()
-
-extern inline pte_t * pte_alloc_kernel(pmd_t * pmd, unsigned long address)
-{
-        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-        if (pmd_none(*pmd)) {
-                pte_t * page = (pte_t *) get_pte_fast();
-
-                if (!page)
-                        return get_pte_kernel_slow(pmd, address);
-                pmd_val(pmd[0]) = _KERNPG_TABLE + __pa(page);
-                pmd_val(pmd[1]) = _KERNPG_TABLE + __pa(page+1024);
-                pmd_val(pmd[2]) = _KERNPG_TABLE + __pa(page+2048);
-                pmd_val(pmd[3]) = _KERNPG_TABLE + __pa(page+3072);
-                return page + address;
-        }
-        if (pmd_bad(*pmd)) {
-                __handle_bad_pmd_kernel(pmd);
-                return NULL;
-        }
-        return (pte_t *) pmd_page(*pmd) + address;
+        free_page((unsigned long) pte);
 }
 
-extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address)
+extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long vmaddr)
 {
-        address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	unsigned long offset;
 
-        if (pmd_none(*pmd))
-                goto getnew;
+	offset = (vmaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+        if (pmd_none(*pmd)) {
+		unsigned long page = (unsigned long) get_pte_fast();
+		
+		if (!page)
+			return get_pte_slow(pmd, offset);
+		pmd_val(pmd[0]) = _PAGE_TABLE + __pa(page);
+		pmd_val(pmd[1]) = _PAGE_TABLE + __pa(page+1024);
+		pmd_val(pmd[2]) = _PAGE_TABLE + __pa(page+2048);
+		pmd_val(pmd[3]) = _PAGE_TABLE + __pa(page+3072);
+		return (pte_t *) page + offset;
+	}
         if (pmd_bad(*pmd))
-                goto fix;
-        return (pte_t *) pmd_page(*pmd) + address;
-getnew:
-{
-        unsigned long page = (unsigned long) get_pte_fast();
-
-        if (!page)
-                return get_pte_slow(pmd, address);
-        pmd_val(pmd[0]) = _PAGE_TABLE + __pa(page);
-        pmd_val(pmd[1]) = _PAGE_TABLE + __pa(page+1024);
-        pmd_val(pmd[2]) = _PAGE_TABLE + __pa(page+2048);
-        pmd_val(pmd[3]) = _PAGE_TABLE + __pa(page+3072);
-        return (pte_t *) page + address;
-}
-fix:
-        __handle_bad_pmd(pmd);
-        return NULL;
+		BUG();
+        return (pte_t *) pmd_page(*pmd) + offset;
 }
 
-/*
- * allocating and freeing a pmd is trivial: the 1-entry pmd is
- * inside the pgd, so has no extra memory associated with it.
- */
-extern inline void pmd_free(pmd_t * pmd)
-{
-}
-
-extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address)
-{
-        return (pmd_t *) pgd;
-}
-
-#define pmd_free_kernel         pmd_free
-#define pmd_alloc_kernel        pmd_alloc
+#define pte_alloc_kernel(pmd, addr) pte_alloc(pmd, addr)
+#define pte_free_kernel(pte)    free_pte_fast(pte)
+#define pte_free(pte)           free_pte_fast(pte)
 
 extern int do_check_pgt_cache(int, int);
 
+/*
+ * This establishes kernel virtual mappings (e.g., as a result of a
+ * vmalloc call).  Since s390-esame uses a separate kernel page table,
+ * there is nothing to do here... :)
+ */
 #define set_pgdir(addr,entry) do { } while(0)
 
 /*
@@ -185,161 +182,122 @@
  */
 
 /*
- * s390 has two ways of flushing TLBs
+ * S/390 has three ways of flushing TLBs
  * 'ptlb' does a flush of the local processor
- * 'ipte' invalidates a pte in a page table and flushes that out of 
- * the TLBs of all PUs of a SMP 
+ * 'csp' flushes the TLBs on all PUs of a SMP
+ * 'ipte' invalidates a pte in a page table and flushes that out of
+ * the TLBs of all PUs of a SMP
  */
 
-#define __flush_tlb() \
+#define local_flush_tlb() \
 do {  __asm__ __volatile__("ptlb": : :"memory"); } while (0)
 
 
-static inline void __flush_global_tlb(void) 
-{
-	int cs1=0,dum=0;
-	int *adr;
-	long long dummy=0;
-	adr = (int*) (((int)(((int*) &dummy)+1) & 0xfffffffc)|1);
-	__asm__ __volatile__("lr    2,%0\n\t"
-			     "lr    3,%1\n\t"
-			     "lr    4,%2\n\t"
-			     ".long 0xb2500024" :
-			     : "d" (cs1), "d" (dum), "d" (adr)
-			     : "2", "3", "4");
-}
-
-#if 0
-#define flush_tlb_one(a,b)     __flush_tlb()
-#define __flush_tlb_one(a,b)   __flush_tlb()
-#else
-static inline void __flush_tlb_one(struct mm_struct *mm,
-                                   unsigned long addr)
-{
-	pgd_t * pgdir;
-	pmd_t * pmd;
-	pte_t * pte, *pto;
-	
-	pgdir = pgd_offset(mm, addr);
-	if (pgd_none(*pgdir) || pgd_bad(*pgdir))
-		return;
-	pmd = pmd_offset(pgdir, addr);
-	if (pmd_none(*pmd) || pmd_bad(*pmd))
-		return;
-	pte = pte_offset(pmd,addr);
-
-	/*
-	 * S390 has 1mb segments, we are emulating 4MB segments
-	 */
-
-	pto = (pte_t*) (((unsigned long) pte) & 0x7ffffc00);
-	       
-       	__asm__ __volatile("    ic   0,2(%0)\n"
-			   "    ipte %1,%2\n"
-			   "    stc  0,2(%0)"
-			   : : "a" (pte), "a" (pto), "a" (addr): "0");
-}
-#endif
-
-
 #ifndef CONFIG_SMP
 
-#define flush_tlb()       __flush_tlb()
-#define flush_tlb_all()   __flush_tlb()
-#define local_flush_tlb() __flush_tlb()
-
 /*
  * We always need to flush, since s390 does not flush tlb
  * on each context switch
  */
 
-
-static inline void flush_tlb_mm(struct mm_struct *mm)
-{
-        __flush_tlb();
-}
-
-static inline void flush_tlb_page(struct vm_area_struct *vma,
-        unsigned long addr)
-{
-        __flush_tlb_one(vma->vm_mm,addr);
-}
-
-static inline void flush_tlb_range(struct mm_struct *mm,
-        unsigned long start, unsigned long end)
-{
-        __flush_tlb();
-}
+#define flush_tlb()			local_flush_tlb()
+#define flush_tlb_all()			local_flush_tlb()
+#define flush_tlb_mm(mm)		local_flush_tlb()
+#define flush_tlb_page(vma, va)		local_flush_tlb()
+#define flush_tlb_range(mm, start, end)	local_flush_tlb()
 
 #else
 
-/*
- * We aren't very clever about this yet -  SMP could certainly
- * avoid some global flushes..
- */
-
 #include <asm/smp.h>
 
-#define local_flush_tlb() \
-        __flush_tlb()
+extern void smp_ptlb_all(void);
+static inline void global_flush_tlb_csp(void)
+{
+	int cs1=0,dum=0;
+	int *adr;
+	long long dummy=0;
+	adr = (int*) (((int)(((int*) &dummy)+1) & 0xfffffffc)|1);
+	__asm__ __volatile__("lr    2,%0\n\t"
+                             "lr    3,%1\n\t"
+                             "lr    4,%2\n\t"
+                             "csp   2,4" :
+                             : "d" (cs1), "d" (dum), "d" (adr)
+                             : "2", "3", "4");
+}
+static inline void global_flush_tlb(void)
+{
+	if (MACHINE_HAS_CSP)
+		global_flush_tlb_csp();
+	else
+		smp_ptlb_all();
+}
 
 /*
- *      We only have to do global flush of tlb if process run since last
- *      flush on any other pu than current. 
- *      If we have threads (mm->count > 1) we always do a global flush, 
- *      since the process runs on more than one processor at the same time.
+ * We only have to do global flush of tlb if process run since last
+ * flush on any other pu than current. 
+ * If we have threads (mm->count > 1) we always do a global flush, 
+ * since the process runs on more than one processor at the same time.
  */
 
-static inline void flush_tlb_current_task(void)
+static inline void __flush_tlb_mm(struct mm_struct * mm)
 {
-	if ((atomic_read(&current->mm->mm_count) != 1) ||
-	    (current->mm->cpu_vm_mask != (1UL << smp_processor_id()))) {
-		current->mm->cpu_vm_mask = (1UL << smp_processor_id());
-		__flush_global_tlb();
+	if ((smp_num_cpus > 1) &&
+	    ((atomic_read(&mm->mm_count) != 1) ||
+	     (mm->cpu_vm_mask != (1UL << smp_processor_id())))) {
+		mm->cpu_vm_mask = (1UL << smp_processor_id());
+		global_flush_tlb();
 	} else {                 
 		local_flush_tlb();
 	}
 }
 
-#define flush_tlb() flush_tlb_current_task()
+#define flush_tlb()			__flush_tlb_mm(current->mm)
+#define flush_tlb_all()			global_flush_tlb()
+#define flush_tlb_mm(mm)		__flush_tlb_mm(mm)
+#define flush_tlb_page(vma, va)		__flush_tlb_mm((vma)->vm_mm)
+#define flush_tlb_range(mm, start, end)	__flush_tlb_mm(mm)
 
-#define flush_tlb_all() __flush_global_tlb()
+#endif
 
-static inline void flush_tlb_mm(struct mm_struct * mm)
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+                                      unsigned long start, unsigned long end)
 {
-	if ((atomic_read(&mm->mm_count) != 1) ||
-	    (mm->cpu_vm_mask != (1UL << smp_processor_id()))) {
-		mm->cpu_vm_mask = (1UL << smp_processor_id());
-		__flush_global_tlb();
-	} else {                 
-		local_flush_tlb();
-	}
+        /* S/390 does not keep any page table caches in TLB */
 }
 
-static inline void flush_tlb_page(struct vm_area_struct * vma,
-        unsigned long va)
+
+static inline int ptep_test_and_clear_and_flush_young(struct vm_area_struct *vma, 
+                                                      unsigned long address, pte_t *ptep)
 {
-	__flush_tlb_one(vma->vm_mm,va);
+	/* No need to flush TLB; bits are in storage key */
+	return ptep_test_and_clear_young(ptep);
 }
 
-static inline void flush_tlb_range(struct mm_struct * mm,
-				   unsigned long start, unsigned long end)
+static inline int ptep_test_and_clear_and_flush_dirty(struct vm_area_struct *vma, 
+                                                      unsigned long address, pte_t *ptep)
 {
-	if ((atomic_read(&mm->mm_count) != 1) ||
-	    (mm->cpu_vm_mask != (1UL << smp_processor_id()))) {
-		mm->cpu_vm_mask = (1UL << smp_processor_id());
-		__flush_global_tlb();
-	} else {                 
-		local_flush_tlb();
-	}
+	/* No need to flush TLB; bits are in storage key */
+	return ptep_test_and_clear_dirty(ptep);
 }
 
-#endif
+static inline pte_t ptep_invalidate(struct vm_area_struct *vma, 
+                                    unsigned long address, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!(pte_val(pte) & _PAGE_INVALID)) {
+		/* S390 has 1mb segments, we are emulating 4MB segments */
+		pte_t *pto = (pte_t *) (((unsigned long) ptep) & 0x7ffffc00);
+		__asm__ __volatile__ ("ipte %0,%1" : : "a" (pto), "a" (address));
+	}
+	pte_clear(ptep);
+	return pte;
+}
 
-extern inline void flush_tlb_pgtables(struct mm_struct *mm,
-                                      unsigned long start, unsigned long end)
+static inline void ptep_establish(struct vm_area_struct *vma, 
+                                  unsigned long address, pte_t *ptep, pte_t entry)
 {
-        /* S/390 does not keep any page table caches in TLB */
+	ptep_invalidate(vma, address, ptep);
+	set_pte(ptep, entry);
 }
 
 #endif /* _S390_PGALLOC_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/pgtable.h linux/include/asm-s390/pgtable.h
--- v2.4.1/linux/include/asm-s390/pgtable.h	Tue Nov  7 10:46:04 2000
+++ linux/include/asm-s390/pgtable.h	Tue Feb 13 14:13:44 2001
@@ -3,7 +3,9 @@
  *
  *  S390 version
  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner
+ *    Author(s): Hartmut Penner (hp@de.ibm.com)
+ *               Ulrich Weigand (weigand@de.ibm.com)
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/pgtable.h"
  */
@@ -17,14 +19,19 @@
  * table, so that we physically have the same two-level page table as the
  * S390 mmu expects.
  *
+ * The "pgd_xxx()" functions are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ *
  * This file contains the functions and defines necessary to modify and use
  * the S390 page table tree.
  */
 #ifndef __ASSEMBLY__
 #include <asm/processor.h>
-#include <linux/tasks.h>
+#include <linux/threads.h>
 
 extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
+extern void paging_init(void);
 
 /* Caches aren't brain-dead on S390. */
 #define flush_cache_all()                       do { } while (0)
@@ -37,20 +44,30 @@
 #define flush_icache_page(vma,pg)               do { } while (0)
 
 /*
+ * The S390 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+#define update_mmu_cache(vma, address, pte)     do { } while (0)
+
+/*
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern unsigned long empty_zero_page[1024];
+extern char empty_zero_page[PAGE_SIZE];
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 #endif /* !__ASSEMBLY__ */
 
-/* Certain architectures need to do special things when PTEs
+/*
+ * Certain architectures need to do special things when PTEs
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
  */
 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
 
-/* PMD_SHIFT determines the size of the area a second-level page table can map */
+/*
+ * PMD_SHIFT determines the size of the area a second-level page
+ * table can map
+ */
 #define PMD_SHIFT       22
 #define PMD_SIZE        (1UL << PMD_SHIFT)
 #define PMD_MASK        (~(PMD_SIZE-1))
@@ -70,7 +87,6 @@
 #define PTRS_PER_PMD    1
 #define PTRS_PER_PGD    512
 
-
 /*
  * pgd entries used up by user/kernel:
  */
@@ -87,7 +103,8 @@
 	printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
 
 #ifndef __ASSEMBLY__
-/* Just any arbitrary offset to the start of the vmalloc VM area: the
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
  * current 8MB value just means that there will be a 8MB "hole" after the
  * physical memory until the kernel virtual memory starts.  That means that
  * any out-of-bounds memory accesses will hopefully be caught.
@@ -95,14 +112,14 @@
  * area for the same reason. ;)
  */
 #define VMALLOC_OFFSET  (8*1024*1024)
-#define VMALLOC_START   (((unsigned long) high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_START   (((unsigned long) high_memory + VMALLOC_OFFSET) \
+			 & ~(VMALLOC_OFFSET-1))
 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
 #define VMALLOC_END     (0x7fffffffL)
 
 
 /*
  * A pagetable entry of S390 has following format:
- *
  *  |   PFRA          |    |  OS  |
  * 0                   0IP0
  * 00000000001111111111222222222233
@@ -110,11 +127,8 @@
  *
  * I Page-Invalid Bit:    Page is not available for address-translation
  * P Page-Protection Bit: Store access not possible for page
- */
-
-/*
- * A segmenttable entry of S390 has following format:
  *
+ * A segmenttable entry of S390 has following format:
  *  |   P-table origin      |  |PTL
  * 0                         IC
  * 00000000001111111111222222222233
@@ -122,10 +136,8 @@
  *
  * I Segment-Invalid Bit:    Segment is not available for address-translation
  * C Common-Segment Bit:     Segment is not private (PoP 3-30)
- * PTL Page-Table-Length:    Length of Page-table (PTL+1*16 entries -> up to 256 entries)
- */
-
-/*
+ * PTL Page-Table-Length:    Page-table length (PTL+1*16 entries -> up to 256)
+ *
  * The segmenttable origin of S390 has following format:
  *
  *  |S-table origin   |     | STL |
@@ -137,27 +149,38 @@
  * G Segment-Invalid Bit:     *
  * P Private-Space Bit:       Segment is not private (PoP 3-30)
  * S Storage-Alteration:
- * STL Segment-Table-Length:  Length of Page-table (STL+1*16 entries -> up to 2048 entries)
+ * STL Segment-Table-Length:  Segment-table length (STL+1*16 entries -> up to 2048)
+ *
+ * A storage key has the following format:
+ * | ACC |F|R|C|0|
+ *  0   3 4 5 6 7
+ * ACC: access key
+ * F  : fetch protection bit
+ * R  : referenced bit
+ * C  : changed bit
  */
 
+/* Bits in the page table entry */
 #define _PAGE_PRESENT   0x001          /* Software                         */
-#define _PAGE_ACCESSED  0x002          /* Software accessed                */
-#define _PAGE_DIRTY     0x004          /* Software dirty                   */
 #define _PAGE_RO        0x200          /* HW read-only                     */
 #define _PAGE_INVALID   0x400          /* HW invalid                       */
 
+/* Bits in the segment table entry */
 #define _PAGE_TABLE_LEN 0xf            /* only full page-tables            */
 #define _PAGE_TABLE_COM 0x10           /* common page-table                */
 #define _PAGE_TABLE_INV 0x20           /* invalid page-table               */
 #define _SEG_PRESENT    0x001          /* Software (overlap with PTL)      */
 
+/* Bits int the storage key */
+#define _PAGE_CHANGED    0x02          /* HW changed bit                   */
+#define _PAGE_REFERENCED 0x04          /* HW referenced bit                */
+
 #define _USER_SEG_TABLE_LEN    0x7f    /* user-segment-table up to 2 GB    */
 #define _KERNEL_SEG_TABLE_LEN  0x7f    /* kernel-segment-table up to 2 GB  */
 
 /*
  * User and Kernel pagetables are identical
  */
-
 #define _PAGE_TABLE     (_PAGE_TABLE_LEN )
 #define _KERNPG_TABLE   (_PAGE_TABLE_LEN )
 
@@ -165,22 +188,25 @@
  * The Kernel segment-tables includes the User segment-table
  */
 
-#define _SEGMENT_TABLE  (_USER_SEG_TABLE_LEN|0x80000000)
+#define _SEGMENT_TABLE  (_USER_SEG_TABLE_LEN|0x80000000|0x100)
 #define _KERNSEG_TABLE  (_KERNEL_SEG_TABLE_LEN)
+
 /*
  * No mapping available
  */
-#define PAGE_NONE       __pgprot(_PAGE_INVALID )
-
-#define PAGE_SHARED     __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
-#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_RO)
-#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_RO)
-#define PAGE_KERNEL     __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY)
+#define PAGE_INVALID  __pgprot(_PAGE_INVALID)
+#define PAGE_NONE     __pgprot(_PAGE_PRESENT | _PAGE_INVALID)
+#define PAGE_COPY     __pgprot(_PAGE_PRESENT | _PAGE_RO)
+#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_RO)
+#define PAGE_SHARED   __pgprot(_PAGE_PRESENT)
+#define PAGE_KERNEL   __pgprot(_PAGE_PRESENT)
 
 /*
- * The S390 can't do page protection for execute, and considers that the same are read.
- * Also, write permissions imply read permissions. This is the closest we can get..
+ * The S390 can't do page protection for execute, and considers that the
+ * same are read. Also, write permissions imply read permissions. This is
+ * the closest we can get..
  */
+         /*xwr*/
 #define __P000  PAGE_NONE
 #define __P001  PAGE_READONLY
 #define __P010  PAGE_COPY
@@ -200,212 +226,245 @@
 #define __S111  PAGE_SHARED
 
 /*
- * Define this if things work differently on an i386 and an i486:
- * it will (on an i486) warn about kernel memory accesses that are
- * done without a 'verify_area(VERIFY_WRITE,..)'
- *
- * Kernel and User memory-access are done equal, so we don't need verify
+ * Permanent address of a page.
  */
-#undef TEST_VERIFY_AREA
-
-/* page table for 0-4MB for everybody */
-extern unsigned long pg0[1024];
-
-/* number of bits that fit into a memory pointer */
-#define BITS_PER_PTR                    (8*sizeof(unsigned long))
-
-/* to align the pointer to a pointer address */
-#define PTR_MASK                        (~(sizeof(void*)-1))
-
-/* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
-/* 64-bit machines, beware!  SRB. */
-#define SIZEOF_PTR_LOG2                 2
-
-/* to find an entry in a page-table */
-#define PAGE_PTR(address) \
-((unsigned long)(address)>>(PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
-
-
-
-/* 
- * CR 7 (SPST) and cr 13 (HPST) are set to the user pgdir. 
- * Kernel is running in its own, disjunct address space,
- * running in primary address space.
- * Copy to/from user is done via access register mode with
- * access registers set to 0 or 1. For that purpose we need 
- * set up CR 7 with the user pgd.  
- * 
- */
-
-#define SET_PAGE_DIR(tsk,pgdir)                                              \
-do {                                                                         \
-        unsigned long __pgdir = (__pa(pgdir) & PAGE_MASK ) | _SEGMENT_TABLE; \
-        (tsk)->thread.user_seg = __pgdir;                                    \
-        if ((tsk) == current) {                                              \
-                __asm__ __volatile__("lctl  7,7,%0": :"m" (__pgdir));        \
-                __asm__ __volatile__("lctl  13,13,%0": :"m" (__pgdir));      \
-        }                                                                    \
-} while (0)
-
-/* 
- * CR 7 (SPST) and cr 13 (HPST) are set to the user pgdir. 
- * Kernel is running in its own, disjunct address space,
- * running in primary address space.
- * Copy to/from user is done via access register mode with
- * access registers set to 0 or 1. For that purpose we need 
- * set up CR 7 with the user pgd.  
- * 
- */
-
-#define SET_PAGE_DIR(tsk,pgdir)                                              \
-do {                                                                         \
-        unsigned long __pgdir = (__pa(pgdir) & PAGE_MASK ) | _SEGMENT_TABLE; \
-        (tsk)->thread.user_seg = __pgdir;                                    \
-        if ((tsk) == current) {                                              \
-                __asm__ __volatile__("lctl  7,7,%0": :"m" (__pgdir));        \
-                __asm__ __volatile__("lctl  13,13,%0": :"m" (__pgdir));      \
-        }                                                                    \
-} while (0)
-
-
-extern inline int pte_none(pte_t pte)           { return ((pte_val(pte) & (_PAGE_INVALID | _PAGE_RO)) == _PAGE_INVALID); } 
-extern inline int pte_present(pte_t pte)        { return pte_val(pte) & _PAGE_PRESENT; }
-extern inline void pte_clear(pte_t *ptep)       { pte_val(*ptep) = _PAGE_INVALID; }
-#define PTE_INIT(x) pte_clear(x)
-
-extern inline int pmd_none(pmd_t pmd)           { return pmd_val(pmd) & _PAGE_TABLE_INV; }
-extern inline int pmd_bad(pmd_t pmd)            { return (pmd_val(pmd) == 0); }
-extern inline int pmd_present(pmd_t pmd)        { return pmd_val(pmd) & _SEG_PRESENT; }
-extern inline void pmd_clear(pmd_t * pmdp)      {
-                                                        pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
-                                                        pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
-                                                        pmd_val(pmdp[2]) = _PAGE_TABLE_INV;
-                                                        pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
-                                                }
+#define page_address(page) ((page)->virtual)
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
 
 /*
- * The "pgd_xxx()" functions here are trivial for a folded two-level
- * setup: the pgd is never bad, and a pmd always exists (as it's folded
- * into the pgd entry)
+ * pgd/pmd/pte query functions
  */
-extern inline int pgd_none(pgd_t pgd)           { return 0; }
-extern inline int pgd_bad(pgd_t pgd)            { return 0; }
-extern inline int pgd_present(pgd_t pgd)        { return 1; }
-extern inline void pgd_clear(pgd_t * pgdp)      { }
+extern inline int pgd_present(pgd_t pgd) { return 1; }
+extern inline int pgd_none(pgd_t pgd)    { return 0; }
+extern inline int pgd_bad(pgd_t pgd)     { return 0; }
 
+extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) & _SEG_PRESENT; }
+extern inline int pmd_none(pmd_t pmd)    { return pmd_val(pmd) & _PAGE_TABLE_INV; }
+extern inline int pmd_bad(pmd_t pmd)
+{
+	return (pmd_val(pmd) & (~PAGE_MASK & ~_PAGE_TABLE_INV)) != _PAGE_TABLE;
+}
+
+extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_none(pte_t pte)
+{
+	return ((pte_val(pte) & 
+                (_PAGE_INVALID | _PAGE_RO | _PAGE_PRESENT)) == _PAGE_INVALID);
+}
+
+#define pte_same(a,b)	(pte_val(a) == pte_val(b))
 
 /*
- * The following only work if pte_present() is true.
- * Undefined behaviour if not..
+ * query functions pte_write/pte_dirty/pte_young only work if
+ * pte_present() is true. Undefined behaviour if not..
  */
-extern inline int pte_write(pte_t pte)          { return !(pte_val(pte) & _PAGE_RO); }
-extern inline int pte_dirty(pte_t pte)          { return pte_val(pte) & _PAGE_DIRTY; }
-extern inline int pte_young(pte_t pte)          { return pte_val(pte) & _PAGE_ACCESSED; }
-
-/* who needs that
-extern inline int pte_read(pte_t pte)           { return !(pte_val(pte) & _PAGE_INVALID); }
-extern inline int pte_exec(pte_t pte)           { return !(pte_val(pte) & _PAGE_INVALID); }
-extern inline pte_t pte_rdprotect(pte_t pte)    { pte_val(pte) |= _PAGE_INVALID; return pte; }
-extern inline pte_t pte_exprotect(pte_t pte)    { pte_val(pte) |= _PAGE_INVALID; return pte; }
-extern inline pte_t pte_mkread(pte_t pte)       { pte_val(pte) &= _PAGE_INVALID; return pte; }
-extern inline pte_t pte_mkexec(pte_t pte)       { pte_val(pte) &= _PAGE_INVALID; return pte; }
-*/
+extern inline int pte_write(pte_t pte)
+{
+	return (pte_val(pte) & _PAGE_RO) == 0;
+}
 
-extern inline pte_t pte_wrprotect(pte_t pte)    { pte_val(pte) |= _PAGE_RO; return pte; }
-extern inline pte_t pte_mkwrite(pte_t pte)      { pte_val(pte) &= ~_PAGE_RO ; return pte; }
+extern inline int pte_dirty(pte_t pte)
+{
+	int skey;
 
-extern inline pte_t pte_mkclean(pte_t pte)      { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
-extern inline pte_t pte_mkdirty(pte_t pte)      { pte_val(pte) |= _PAGE_DIRTY; return pte; }
+	asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
+	return skey & _PAGE_CHANGED;
+}
 
-extern inline pte_t pte_mkold(pte_t pte)        { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
-extern inline pte_t pte_mkyoung(pte_t pte)      { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
+extern inline int pte_young(pte_t pte)
+{
+	int skey;
 
+	asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
+	return skey & _PAGE_REFERENCED;
+}
 
 /*
- * Conversion functions: convert a page and protection to a page entry,
- * and a page entry and page directory to the page they refer to.
+ * pgd/pmd/pte modification functions
  */
-#define mk_pte(page, pgprot) \
-({ pte_t __pte; pte_val(__pte) = __pa(((page)-mem_map)<<PAGE_SHIFT) + pgprot_val(pgprot); __pte; })
+extern inline void pgd_clear(pgd_t * pgdp)      { }
 
-/* This takes a physical page address that is used by the remapping functions */
-#define mk_pte_phys(physpage, pgprot) \
-({ pte_t __pte; pte_val(__pte) = physpage + pgprot_val(pgprot); __pte; })
+extern inline void pmd_clear(pmd_t * pmdp)
+{
+	pmd_val(pmdp[0]) = _PAGE_TABLE_INV;
+	pmd_val(pmdp[1]) = _PAGE_TABLE_INV;
+	pmd_val(pmdp[2]) = _PAGE_TABLE_INV;
+	pmd_val(pmdp[3]) = _PAGE_TABLE_INV;
+}
 
-extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
-{ pte_val(pte) = (pte_val(pte) & PAGE_MASK) | pgprot_val(newprot); return pte; }
+extern inline void pte_clear(pte_t *ptep)
+{
+	pte_val(*ptep) = _PAGE_INVALID; 
+}
 
-#define page_address(page)  ((page)->virtual)
-#define pte_page(x) (mem_map+(unsigned long)((pte_val(pte) >> PAGE_SHIFT)))
+#define PTE_INIT(x) pte_clear(x)
 
-#define pmd_page(pmd) \
-((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+/*
+ * The following pte modification functions only work if
+ * pte_present() is true. Undefined behaviour if not..
+ */
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) = (pte_val(pte) & PAGE_MASK) | pgprot_val(newprot);
+	return pte;
+}
 
-/* to find an entry in a page-table-directory */
-#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+extern inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_RO;
+	return pte;
+}
 
-#define __pgd_offset(address) pgd_index(address)
+extern inline pte_t pte_mkwrite(pte_t pte) 
+{
+	pte_val(pte) &= ~_PAGE_RO;
+	return pte;
+}
 
-#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
+extern inline pte_t pte_mkclean(pte_t pte)
+{
+	/* We can't clear the changed bit atomically. The iske/and/sske
+         * sequence has a race condition with the page referenced bit.
+         * At the moment pte_mkclean is always followed by a pte_mkold.
+         * So its safe to ignore the problem for now. Hope this will
+         * never change ... */
+	asm volatile ("sske %0,%1" 
+	              : : "d" (0), "a" (pte_val(pte)));
+	return pte;
+}
 
-/* to find an entry in a kernel page-table-directory */
-#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+extern inline pte_t pte_mkdirty(pte_t pte)
+{
+	/* We can't set the changed bit atomically either. For now we
+         * set (!) the page referenced bit. */
+	asm volatile ("sske %0,%1" 
+	              : : "d" (_PAGE_CHANGED|_PAGE_REFERENCED),
+		          "a" (pte_val(pte)));
+	return pte;
+}
 
-/* Find an entry in the second-level page table.. */
-extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+extern inline pte_t pte_mkold(pte_t pte)
 {
-        return (pmd_t *) dir;
+	asm volatile ("rrbe 0,%0" : : "a" (pte_val(pte)));
+	return pte;
 }
 
-/* Find an entry in the third-level page table.. */
-#define pte_offset(pmd, address) \
-((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2))))
+extern inline pte_t pte_mkyoung(pte_t pte)
+{
+	/* To set the referenced bit we read the first word from the real
+	 * page with a special instruction: load using real address (lura).
+	 * Isn't S/390 a nice architecture ?! */
+	asm volatile ("lura 0,%0" : : "a" (pte_val(pte) & PAGE_MASK) : "0" );
+	return pte;
+}
 
+static inline int ptep_test_and_clear_young(pte_t *ptep)
+{
+	int ccode;
 
-/* We don't use pmd cache, so these are dummy routines */
-extern __inline__ pmd_t *get_pmd_fast(void)
+	asm volatile ("rrbe 0,%1\n\t"
+		      "ipm  %0\n\t"
+		      "srl  %0,28\n\t" : "=d" (ccode) : "a" (pte_val(*ptep)));
+	return ccode & 2;
+}
+
+static inline int ptep_test_and_clear_dirty(pte_t *ptep)
 {
-        return (pmd_t *)0;
+	int skey;
+
+	asm volatile ("iske %0,%1" : "=d" (skey) : "a" (*ptep));
+	if ((skey & _PAGE_CHANGED) == 0)
+		return 0;
+	/* We can't clear the changed bit atomically. For now we
+         * clear (!) the page referenced bit. */
+	asm volatile ("sske %0,%1" 
+	              : : "d" (0), "a" (*ptep));
+	return 1;
 }
 
-extern __inline__ void free_pmd_fast(pmd_t *pmd)
+static inline pte_t ptep_get_and_clear(pte_t *ptep)
 {
+	pte_t pte = *ptep;
+	pte_clear(ptep);
+	return pte;
 }
 
-extern __inline__ void free_pmd_slow(pmd_t *pmd)
+static inline void ptep_set_wrprotect(pte_t *ptep)
 {
+	pte_t old_pte = *ptep;
+	set_pte(ptep, pte_wrprotect(old_pte));
 }
 
-extern void __handle_bad_pmd(pmd_t *pmd);
-extern void __handle_bad_pmd_kernel(pmd_t *pmd);
+static inline void ptep_mkdirty(pte_t *ptep)
+{
+	pte_mkdirty(*ptep);
+}
 
 /*
- * The S390 doesn't have any external MMU info: the kernel page
- * tables contain all the necessary information.
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
  */
-extern inline void update_mmu_cache(struct vm_area_struct * vma,
-        unsigned long address, pte_t pte)
+extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
 {
+	pte_t __pte;
+	pte_val(__pte) = physpage + pgprot_val(pgprot);
+	return __pte;
 }
+#define mk_pte(page,pgprot) mk_pte_phys(__pa(((page)-mem_map)<<PAGE_SHIFT),pgprot)
+
+#define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
+
+#define pmd_page(pmd) \
+        ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level page table.. */
+extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+{
+        return (pmd_t *) dir;
+}
+
+/* Find an entry in the third-level page table.. */
+#define pte_offset(pmd, address) \
+        ((pte_t *) (pmd_page(*pmd) + ((address>>10) & ((PTRS_PER_PTE-1)<<2))))
 
 /*
- * a page-table entry has only 19 bit for offset and 7 bit for type
- * if bits 0, 20 or 23 are set, a translation specification exceptions occures, and it's
- * hard to find out the failing address
- * therefor, we zero out this bits
+ * A page-table entry has some bits we have to treat in a special way.
+ * Bits 0, 20 and bit 23 have to be zero, otherwise an specification
+ * exception will occur instead of a page translation exception. The
+ * specifiation exception has the bad habit not to store necessary
+ * information in the lowcore.
+ * Bit 21 and bit 22 are the page invalid bit and the page protection
+ * bit. We set both to indicate a swapped page.
+ * Bit 31 is used as the software page present bit. If a page is
+ * swapped this obviously has to be zero.
+ * This leaves the bits 1-19 and bits 24-30 to store type and offset.
+ * We use the 7 bits from 24-30 for the type and the 19 bits from 1-19
+ * for the offset.
+ * 0|     offset      |0110|type |0
+ * 00000000001111111111222222222233
+ * 01234567890123456789012345678901
  */
+extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
+{
+	pte_t pte;
+	pte_val(pte) = (type << 1) | (offset << 12) | _PAGE_INVALID | _PAGE_RO;
+	pte_val(pte) &= 0x7ffff6fe;  /* better to be paranoid */
+	return pte;
+}
 
-#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f)
-#define SWP_OFFSET(entry) (((entry).val >> 12) & 0x7FFFF )
-#define SWP_ENTRY(type,offset) ((swp_entry_t) { (((type) << 1) | \
-                                                 ((offset) << 12) | \
-                                                 _PAGE_INVALID | _PAGE_RO) \
-                                                 & 0x7ffff6fe })
-
-#define pte_to_swp_entry(pte)           ((swp_entry_t) { pte_val(pte) })
-#define swp_entry_to_pte(x)             ((pte_t) { (x).val })
+#define SWP_TYPE(entry)		(((entry).val >> 1) & 0x3f)
+#define SWP_OFFSET(entry)	(((entry).val >> 12) & 0x7FFFF )
+#define SWP_ENTRY(type,offset)	((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })
 
-#include <asm-generic/pgtable.h>
+#define pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)	((pte_t) { (x).val })
 
 #endif /* !__ASSEMBLY__ */
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/processor.h linux/include/asm-s390/processor.h
--- v2.4.1/linux/include/asm-s390/processor.h	Sat Dec 30 09:35:41 2000
+++ linux/include/asm-s390/processor.h	Tue Feb 13 14:13:44 2001
@@ -41,7 +41,7 @@
         cpuid_t  cpu_id;
         __u16    cpu_addr;
         __u16    cpu_nr;
-        unsigned long loops_per_sec;
+        unsigned long loops_per_jiffy;
         unsigned long *pgd_quick;
         unsigned long *pte_quick;
         unsigned long pgtable_cache_sz;
@@ -87,13 +87,15 @@
         /* perform syscall argument validation (get/set_fs) */
         mm_segment_t fs;
         per_struct per_info;/* Must be aligned on an 4 byte boundary*/
+	addr_t  ieee_instruction_pointer; 
+	/* Used to give failing instruction back to user for ieee exceptions */
 };
 
 typedef struct thread_struct thread_struct;
 
 #define INIT_MMAP \
 { &init_mm, 0, 0, NULL, PAGE_SHARED, \
-VM_READ | VM_WRITE | VM_EXEC, 1, NULL, &init_mm.mmap }
+VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL }
 
 #define INIT_THREAD { (struct pt_regs *) 0,                       \
                     { 0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
@@ -108,12 +110,8 @@
 
 /* need to define ... */
 #define start_thread(regs, new_psw, new_stackp) do {            \
-        unsigned long *u_stack = new_stackp;                    \
         regs->psw.mask  = _USER_PSW_MASK;                       \
-        regs->psw.addr  = new_psw | 0x80000000 ;                \
-        get_user(regs->gprs[2],u_stack);                        \
-        get_user(regs->gprs[3],u_stack+1);                      \
-        get_user(regs->gprs[4],u_stack+2);                      \
+        regs->psw.addr  = new_psw | 0x80000000;                 \
         regs->gprs[15]  = new_stackp ;                          \
 } while (0)
 
@@ -172,13 +170,33 @@
 static inline void disabled_wait(unsigned long code)
 {
         char psw_buffer[2*sizeof(psw_t)];
+        char ctl_buf[4];
         psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
                                   & -sizeof(psw_t));
 
         dw_psw->mask = 0x000a0000;
         dw_psw->addr = code;
-        /* load disabled wait psw, the processor is dead afterwards */
-        asm volatile ("lpsw 0(%0)" : : "a" (dw_psw));
+        /* 
+         * Store status and then load disabled wait psw,
+         * the processor is dead afterwards
+         */
+
+        asm volatile ("    stctl 0,0,0(%1)\n"
+                      "    ni    0(%1),0xef\n" /* switch off protection */
+                      "    lctl  0,0,0(%1)\n"
+                      "    stpt  0xd8\n"       /* store timer */
+                      "    stckc 0xe0\n"       /* store clock comparator */
+                      "    stpx  0x108\n"      /* store prefix register */
+                      "    stam  0,15,0x120\n" /* store access registers */
+                      "    std   0,0x160\n"    /* store f0 */
+                      "    std   2,0x168\n"    /* store f2 */
+                      "    std   4,0x170\n"    /* store f4 */
+                      "    std   6,0x178\n"    /* store f6 */
+                      "    stm   0,15,0x180\n" /* store general registers */
+                      "    stctl 0,15,0x1c0\n" /* store control registers */
+                      "    oi    0(%1),0x10\n" /* fake protection bit */
+                      "    lpsw 0(%0)"
+                      : : "a" (dw_psw), "a" (&ctl_buf));
 }
 
 #endif                                 /* __ASM_S390_PROCESSOR_H           */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/ptrace.h linux/include/asm-s390/ptrace.h
--- v2.4.1/linux/include/asm-s390/ptrace.h	Mon Jul 10 14:35:07 2000
+++ linux/include/asm-s390/ptrace.h	Tue Feb 13 14:13:44 2001
@@ -63,8 +63,8 @@
 	unsigned    storage_alt_space_ctl:1;
 	unsigned    :5;
 	unsigned    :16;
-	__u32   starting_addr;
-	__u32   ending_addr;
+	addr_t      starting_addr;
+	addr_t      ending_addr;
 } per_cr_bits  __attribute__((packed));
 
 typedef struct
@@ -83,13 +83,25 @@
 	unsigned       perc_store_real_address:1;
 	unsigned       :3;
 	unsigned       :1;
-	unsigned       atmid:5;
+	unsigned       atmid_validity_bit:1;
+	unsigned       atmid_psw_bit_32:1;
+	unsigned       atmid_psw_bit_5:1;
+	unsigned       atmid_psw_bit_16:1;
+	unsigned       atmid_psw_bit_17:1;
 	unsigned       si:2;
-	__u32          address;              /* 0x098 */
+	addr_t         address;              /* 0x098 */
 	unsigned       :4;                   /* 0x0a1 */
 	unsigned       access_id:4;           
 } per_lowcore_bits __attribute__((packed));
 
+typedef enum
+{
+	primary_asce,
+	ar_asce,
+	secondary_asce,
+	home_space_asce
+} per_ai_codes;
+
 typedef struct
 {
 	union
@@ -134,6 +146,8 @@
  * this is the way intel does it
  */
 	per_struct per_info;
+	addr_t  ieee_instruction_pointer; 
+	/* Used to give failing instruction back to user for ieee exceptions */
 };
 
 typedef struct user_regs_struct user_regs_struct;
@@ -143,12 +157,8 @@
 #ifdef __KERNEL__
 #define user_mode(regs) (((regs)->psw.mask & PSW_PROBLEM_STATE) != 0)
 #define instruction_pointer(regs) ((regs)->psw.addr)
-
-struct thread_struct;
-extern int sprintf_regs(int line,char *buff,struct task_struct * task,
-			struct thread_struct *tss,struct pt_regs * regs);
-extern void show_regs(struct task_struct * task,struct thread_struct *tss,
-		      struct pt_regs * regs);
+extern void show_regs(struct pt_regs * regs);
+extern char *task_show_regs(struct task_struct *task, char *buffer);
 #endif
 
 
@@ -270,8 +280,9 @@
 	PT_CR_9=pt_off(per_info.control_regs.words.cr[0]),
 	PT_CR_10=pt_off(per_info.control_regs.words.cr[1]),
 	PT_CR_11=pt_off(per_info.control_regs.words.cr[2]),
-	PT_LASTOFF=PT_CR_11,
-	PT_ENDREGS=offsetof(user_regs_struct,per_info.lowcore.words.perc_atmid)
+	PT_IEEE_IP=pt_off(ieee_instruction_pointer),
+	PT_LASTOFF=PT_IEEE_IP,
+	PT_ENDREGS=sizeof(user_regs_struct)-1
 };
 
 #define PTRACE_AREA \
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/queue.h linux/include/asm-s390/queue.h
--- v2.4.1/linux/include/asm-s390/queue.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/queue.h	Tue Feb 13 14:13:44 2001
@@ -70,6 +70,35 @@
 	*lhead=member;
 }
 
+static __inline__ list *remove_listhead(list **lhead)
+{
+	list *oldhead=*lhead;
+
+	if(oldhead)
+		*lhead=(*lhead)->next;
+	return(oldhead);
+}
+
+static __inline__ void add_to_list_tail(list **lhead,list *member)
+{
+	list *curr,*prev;
+	if(*lhead==NULL)
+		*lhead=member;
+	else
+	{
+		prev=*lhead;
+		for(curr=(*lhead)->next;curr!=NULL;curr=curr->next)
+			prev=curr;
+		prev->next=member;
+	}
+}
+static __inline__ void add_to_list_tail_null(list **lhead,list *member)
+{
+	member->next=NULL;
+	add_to_list_tail_null(lhead,member);
+}
+
+
 static __inline__ int is_in_list(list *lhead,list *member)
 {
 	list *curr;
@@ -96,6 +125,7 @@
 }
 
 
+
 static __inline__ int remove_from_list(list **lhead,list *member)
 {
 	list *prev;
@@ -112,6 +142,29 @@
 	return(FALSE);
 }
 
+static __inline__ int remove_from_queue(qheader *qhead,queue *member)
+{
+	queue *prev;
+
+	if(get_prev(qhead->head,(list *)member,(list **)&prev))
+	{
+
+		if(prev)
+		{
+			prev->next=member->next;
+			if(prev->next==NULL)
+				qhead->tail=prev;
+		}
+		else
+		{
+			if(qhead->head==qhead->tail)
+				qhead->tail=NULL;
+			qhead->head=member->next;
+		}
+		return(TRUE);
+	}
+	return(FALSE);
+}
 
 
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/resource.h linux/include/asm-s390/resource.h
--- v2.4.1/linux/include/asm-s390/resource.h	Fri Sep 22 14:21:21 2000
+++ linux/include/asm-s390/resource.h	Tue Feb 13 14:13:44 2001
@@ -23,8 +23,8 @@
 #define RLIMIT_NOFILE	7		/* max number of open files */
 #define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
 #define RLIMIT_AS	9		/* address space limit */
-#define RLIMIT_AS	10		/* maximum file locks held */
-
+#define RLIMIT_LOCKS	10		/* maximum file locks held */
+  
 #define RLIM_NLIMITS	11
 
 /*
@@ -37,17 +37,17 @@
 
 #define INIT_RLIMITS					\
 {							\
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ _STK_LIM, LONG_MAX },				\
-	{        0, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ MAX_TASKS_PER_USER, MAX_TASKS_PER_USER },	\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{      _STK_LIM, RLIM_INFINITY },		\
+	{             0, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{             0,             0 },		\
 	{ INR_OPEN, INR_OPEN },                         \
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
-	{ LONG_MAX, LONG_MAX },				\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
 }
 
 #endif /* __KERNEL__ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/s390-gdbregs.h linux/include/asm-s390/s390-gdbregs.h
--- v2.4.1/linux/include/asm-s390/s390-gdbregs.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/s390-gdbregs.h	Tue Feb 13 14:13:44 2001
@@ -8,13 +8,14 @@
  *  used both by the linux kernel for remote debugging & gdb 
  */
 
-/* Say how long (ordinary) registers are.  This is a piece of bogosity
-   used in push_word and a few other places; REGISTER_RAW_SIZE is the
-   real way to know how big a register is.  */
 #ifndef _S390_GDBREGS_H
 #define _S390_GDBREGS_H
 
+#ifdef __KERNEL__
 #include <asm/s390-regs-common.h>
+#else
+#include <s390/s390-regs-common.h>
+#endif
 #define S390_MAX_INSTR_SIZE 6
 #define NUM_REGS      (2+NUM_GPRS+NUM_ACRS+NUM_CRS+1+NUM_FPRS)
 #define FIRST_ACR     (2+NUM_GPRS)
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/s390-regs-common.h linux/include/asm-s390/s390-regs-common.h
--- v2.4.1/linux/include/asm-s390/s390-regs-common.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/s390-regs-common.h	Tue Feb 13 14:13:44 2001
@@ -16,8 +16,9 @@
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 #endif
-
+#if defined(WANT_S390_TGT_DEFS) || defined(__KERNEL__)
 #define REGISTER_SIZE 4
+#endif
 #define NUM_GPRS      16
 #define GPR_SIZE      4
 #define PSW_MASK_SIZE 4
@@ -41,8 +42,6 @@
         __u32   addr;
 } psw_t __attribute__ ((aligned(8)));
 
-typedef __u32 gpr_t;
-
 /* 2 __u32's are used for floats instead to compile  with a __STRICT_ANSI__ defined */ 
 typedef union
 {
@@ -71,6 +70,13 @@
 	freg_t  fprs[NUM_FPRS];              
 } s390_fp_regs;
 
+#define FPC_EXCEPTION_MASK      0xF8000000
+#define FPC_FLAGS_MASK          0x00F80000
+#define FPC_DXC_MASK            0x0000FF00
+#define FPC_RM_MASK             0x00000003
+#define FPC_VALID_MASK         ((FPC_EXCEPTION_MASK|FPC_FLAGS_MASK| \
+                                 FPC_DXC_MASK|FPC_RM_MASK))
+
 /*
   gdb structures & the kernel have this much always in common
  */
@@ -90,7 +96,9 @@
 #define S390_BREAKPOINT_U16 ((__u16)0x0001)
 #define S390_SYSCALL_OPCODE ((__u16)0x0a00)
 #define S390_SYSCALL_SIZE   2
+#if defined(WANT_S390_TGT_DEFS) || defined(__KERNEL__)
 #define ADDR_BITS_REMOVE(addr) ((addr)&0x7fffffff)
+#endif
 #endif
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/s390_ext.h linux/include/asm-s390/s390_ext.h
--- v2.4.1/linux/include/asm-s390/s390_ext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/s390_ext.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,30 @@
+#ifndef _S390_EXTINT_H
+#define _S390_EXTINT_H
+
+/*
+ *  include/asm-s390/s390_ext.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+typedef void (*ext_int_handler_t)(struct pt_regs *regs, __u16 code);
+
+/*
+ * Warning: if you change ext_int_info_t you have to change the
+ * external interrupt handler in entry.S too.
+ */ 
+typedef struct ext_int_info_t {
+	struct ext_int_info_t *next;
+	ext_int_handler_t handler;
+	__u16 code;
+} __attribute__ ((packed)) ext_int_info_t;
+
+extern ext_int_info_t *ext_int_hash[];
+
+int register_external_interrupt(__u16 code, ext_int_handler_t handler);
+int unregister_external_interrupt(__u16 code, ext_int_handler_t handler);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/s390dyn.h linux/include/asm-s390/s390dyn.h
--- v2.4.1/linux/include/asm-s390/s390dyn.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/s390dyn.h	Tue Feb 13 14:13:44 2001
@@ -12,28 +12,20 @@
 
 struct _devreg;
 
-typedef  int (* oper_handler_func_t)( int             irq,
-                                      struct _devreg *dreg);
-typedef  void (* io_handler_func_t) ( int  irq,
-                                      __u32 intparm );
-typedef  void ( * not_oper_handler_func_t)( int irq,
-                                            int status );
+typedef  int  (* oper_handler_func_t)( int             irq,
+                                       struct _devreg *dreg);
+
+typedef struct _devreg_hc_t {
+	__u16 ctype;
+	__u8  cmode;
+	__u16 dtype;
+	__u8  dmode;
+   }  __attribute__ ((packed)) devreg_hc_t;
 
 typedef struct _devreg {
 	union {
-		struct _hc {
-			__u16 ctype;
-			__u8  cmode;
-			__u16 dtype;
-			__u8  dmode;
-		} hc;       /* has controller info */
-
-		struct _hnc {
-			__u16 dtype;
-			__u8  dmode;
-			__u16 res1;
-			__u8  res2;
-		} hnc;      /* has no controller info */
+		int devno;
+		devreg_hc_t hc;       /* has controller info */
 	} ci;
 
 	int                  flag;
@@ -46,15 +38,13 @@
 #define DEVREG_MATCH_DEV_TYPE   0x00000002
 #define DEVREG_MATCH_CU_TYPE    0x00000004
 #define DEVREG_NO_CU_INFO       0x00000008
+#define DEVREG_NO_DEV_INFO      0x00000010
 
+#define DEVREG_TYPE_DEVNO       0x80000000
+#define DEVREG_TYPE_DEVCHARS    0x40000000
 
-int s390_device_register    ( devreg_t *drinfo );
-int s390_device_deregister  ( devreg_t *dreg );
-int s390_request_irq_special( int                      irq,
-                              io_handler_func_t        io_handler,
-                              not_oper_handler_func_t  not_oper_handler,
-                              unsigned long            irqflags,
-                              const char              *devname,
-                              void                    *dev_id);
+int        s390_device_register  ( devreg_t *drinfo );
+int        s390_device_unregister( devreg_t *dreg );
+devreg_t * s390_search_devreg    ( ioinfo_t *ioinfo );
 
 #endif /* __s390dyn */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/s390io.h linux/include/asm-s390/s390io.h
--- v2.4.1/linux/include/asm-s390/s390io.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/s390io.h	Tue Feb 13 14:13:44 2001
@@ -47,25 +47,35 @@
            unsigned int  s_pend    : 1;  /* status pending condition */
            unsigned int  pgid      : 1;  /* "path group ID" is valid */
            unsigned int  pgid_supp : 1;  /* "path group ID" command is supported */
-           unsigned int  unused    : (sizeof(unsigned int)*8 - 18); /* unused */
+           unsigned int  esid      : 1;  /* Ext. SenseID supported by HW */
+           unsigned int  rcd       : 1;  /* RCD supported by HW */
+           unsigned int  repnone   : 1;  /* don't call IRQ handler on interrupt */
+           unsigned int  newreq    : 1;  /* new register interface */
+           unsigned int  dval      : 1;  /* device number valid */
+           unsigned int  unknown   : 1;  /* unknown device - if SenseID failed */
+           unsigned int  unused    : (sizeof(unsigned int)*8 - 24); /* unused */
               } __attribute__ ((packed)) flags;
         } ui;
 
      unsigned long u_intparm;     /* user interruption parameter */
      senseid_t     senseid;       /* SenseID info */
      irq_desc_t    irq_desc;      /* irq descriptor */
+     not_oper_handler_func_t nopfunc; 	/* not oper handler */		
      __u8          ulpm;          /* logical path mask used for I/O */
      __u8          opm;           /* path mask of operational paths */
+     __u16         devno;         /* device number */
      pgid_t        pgid;          /* path group ID */
      schib_t       schib;         /* subchannel information block */
      orb_t         orb;           /* operation request block */
      devstat_t     devstat;       /* device status */
      ccw1_t       *qcpa;          /* queued channel program */
      ccw1_t        senseccw;      /* ccw for sense command */
+     __u8          sense_data[32];/* buffer for basic sense */
      unsigned int  stctl;         /* accumulated status control from irb */
      unsigned long qintparm;      /* queued interruption parameter  */
      unsigned long qflag;         /* queued flags */
-     unsigned char qlpm;          /* queued logical path mask */
+     __u8          qlpm;          /* queued logical path mask */
+     __u32         syncnt;       /* sync I/O recursive usage count */
 
    } __attribute__ ((aligned(8))) ioinfo_t;
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/s390mach.h linux/include/asm-s390/s390mach.h
--- v2.4.1/linux/include/asm-s390/s390mach.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/s390mach.h	Tue Feb 13 14:13:44 2001
@@ -12,14 +12,21 @@
 
 #include <asm/types.h>
 
-//
-// machine-check-interruption code
-//
-typedef struct _mcic {
+typedef struct _mci {
 	__u32	to_be_defined_1 :  9;
 	__u32 cp              :  1; /* channel-report pending */
 	__u32	to_be_defined_2 : 22;
 	__u32	to_be_defined_3;
+	} mci_t;
+
+//
+// machine-check-interruption code
+//
+typedef struct _mcic {
+   union _mcc {
+      __u64 mcl;	/* machine check int. code - long info */	
+      mci_t mcd;  /* machine check int. code - details   */
+   } mcc;
 } __attribute__ ((packed)) mcic_t;
 
 //
@@ -37,29 +44,63 @@
 	__u32 rsid    : 16;   /* reporting-source ID */
 } __attribute__ ((packed)) crw_t;
 
+#define CRW_RSC_MONITOR  0x2  /* monitoring facility */
+#define CRW_RSC_SCH      0x3  /* subchannel */
+#define CRW_RSC_CPATH    0x4  /* channel path */
+#define CRW_RSC_CONFIG   0x9  /* configuration-alert facility */
+#define CRW_RSC_CSS      0xB  /* channel subsystem */
+
+#define CRW_ERC_EVENT    0x00 /* event information pending */
+#define CRW_ERC_AVAIL    0x01 /* available */
+#define CRW_ERC_INIT     0x02 /* initialized */
+#define CRW_ERC_TERROR   0x03 /* temporary error */
+#define CRW_ERC_IPARM    0x04 /* installed parm initialized */
+#define CRW_ERC_TERM     0x05 /* terminal */
+#define CRW_ERC_PERRN    0x06 /* perm. error, fac. not init */
+#define CRW_ERC_PERRI    0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD     0x08 /* installed parameters modified */
+
+#define MAX_CRW_PENDING  1024
+#define MAX_MACH_PENDING 1024
+
 //
 // CRW Entry
 //
 typedef struct _crwe {
-	crw_t  crw;
-	crw_t *crw_next;
+	crw_t   crw;
+	struct _crwe *crwe_next;
 } __attribute__ ((packed)) crwe_t;
 
-typedef struct _mchchk_queue_element {
-	spinlock_t                   lock;
-	unsigned int                 status;
-	mcic_t                       mcic;
-	crwe_t                      *crwe;		/* CRW if applicable */
-	struct mchchk_queue_element *next;
-	struct mchchk_queue_element *prev;
-} mchchk_queue_element_t;
+typedef struct _mache {
+	spinlock_t     lock;
+	unsigned int   status;
+	mcic_t         mcic;
+	union _mc {
+	   crwe_t     *crwe;		/* CRW if applicable */
+   } mc;
+	struct _mache *next;
+	struct _mache *prev;
+} mache_t;
 
 #define MCHCHK_STATUS_TO_PROCESS    0x00000001
 #define MCHCHK_STATUS_IN_PROGRESS   0x00000002
 #define MCHCHK_STATUS_WAITING       0x00000004
 
-void        s390_init_machine_check   ( void );
-void __init s390_do_machine_check     ( void );
-void __init s390_machine_check_handler( struct semaphore * );
+void s390_init_machine_check( void );
+void s390_do_machine_check  ( void );
+void s390_do_crw_pending    ( crwe_t *pcrwe );
+
+extern __inline__ int stcrw( __u32 *pcrw )
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "STCRW 0(%1)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "a" (pcrw)
+                : "cc", "1" );
+        return ccode;
+}
 
 #endif /* __s390mach */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/scatterlist.h linux/include/asm-s390/scatterlist.h
--- v2.4.1/linux/include/asm-s390/scatterlist.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/scatterlist.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,13 @@
+#ifndef _ASMS390X_SCATTERLIST_H
+#define _ASMS390X_SCATTERLIST_H
+
+struct scatterlist {
+    char *  address;    /* Location data is to be transferred to */
+    char * alt_address; /* Location of actual if address is a 
+			 * dma indirect buffer.  NULL otherwise */
+    unsigned int length;
+};
+
+#define ISA_DMA_THRESHOLD (0xffffffffffffffff)
+
+#endif /* _ASMS390X_SCATTERLIST_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/semaphore.h linux/include/asm-s390/semaphore.h
--- v2.4.1/linux/include/asm-s390/semaphore.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/semaphore.h	Tue Feb 13 14:13:44 2001
@@ -36,7 +36,7 @@
 #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
 #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
 
-extern inline void sema_init (struct semaphore *sem, int val)
+static inline void sema_init (struct semaphore *sem, int val)
 {
 	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
 }
@@ -61,13 +61,13 @@
 asmlinkage int  __down_trylock(struct semaphore * sem);
 asmlinkage void __up(struct semaphore * sem);
 
-extern inline void down(struct semaphore * sem)
+static inline void down(struct semaphore * sem)
 {
 	if (atomic_dec_return(&sem->count) < 0)
 		__down(sem);
 }
 
-extern inline int down_interruptible(struct semaphore * sem)
+static inline int down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 
@@ -76,7 +76,7 @@
 	return ret;
 }
 
-extern inline int down_trylock(struct semaphore * sem)
+static inline int down_trylock(struct semaphore * sem)
 {
 	int ret = 0;
 
@@ -85,7 +85,7 @@
 	return ret;
 }
 
-extern inline void up(struct semaphore * sem)
+static inline void up(struct semaphore * sem)
 {
 	if (atomic_inc_return(&sem->count) <= 0)
 		__up(sem);
@@ -136,7 +136,7 @@
 #define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
 #define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
 
-extern inline void init_rwsem(struct rw_semaphore *sem)
+static inline void init_rwsem(struct rw_semaphore *sem)
 {
 	atomic_set(&sem->count, RW_LOCK_BIAS);
 	sem->read_bias_granted = 0;
@@ -149,7 +149,7 @@
 extern void __down_write_failed(int, struct rw_semaphore *);
 extern void __rwsem_wake(int, struct rw_semaphore *);
 
-extern inline void down_read(struct rw_semaphore *sem)
+static inline void down_read(struct rw_semaphore *sem)
 {
 	int count;
 	count = atomic_dec_return(&sem->count);
@@ -157,7 +157,7 @@
 		__down_read_failed(count, sem);
 }
 
-extern inline void down_write(struct rw_semaphore *sem)
+static inline void down_write(struct rw_semaphore *sem)
 {
 	int count;
 	count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
@@ -169,7 +169,7 @@
  * case is when there was a writer waiting, and we've
  * bumped the count to 0: we must wake the writer up.
  */
-extern inline void up_read(struct rw_semaphore *sem)
+static inline void up_read(struct rw_semaphore *sem)
 {
 	int count;
 	count = atomic_inc_return(&sem->count);
@@ -180,7 +180,7 @@
 /* releasing the writer is easy -- just release it and
  * wake up any sleepers.
  */
-extern inline void up_write(struct rw_semaphore *sem)
+static inline void up_write(struct rw_semaphore *sem)
 {
 	int count;
 	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/setup.h linux/include/asm-s390/setup.h
--- v2.4.1/linux/include/asm-s390/setup.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/setup.h	Tue Feb 13 14:13:44 2001
@@ -41,6 +41,7 @@
 #define MACHINE_IS_VM    (MACHINE_FLAGS & 1)
 #define MACHINE_HAS_IEEE (MACHINE_FLAGS & 2)
 #define MACHINE_IS_P390  (MACHINE_FLAGS & 4)
+#define MACHINE_HAS_CSP  (MACHINE_FLAGS & 8)
 
 #define RAMDISK_ORIGIN            0x800000
 #define RAMDISK_BLKSIZE           0x1000
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/sigcontext.h linux/include/asm-s390/sigcontext.h
--- v2.4.1/linux/include/asm-s390/sigcontext.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/sigcontext.h	Tue Feb 13 14:13:44 2001
@@ -2,12 +2,15 @@
  *  include/asm-s390/sigcontext.h
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  */
 
 #ifndef _ASM_S390_SIGCONTEXT_H
 #define _ASM_S390_SIGCONTEXT_H
-#include <asm/s390-regs-common.h>
+
+#define __NUM_GPRS 16
+#define __NUM_FPRS 16
+#define __NUM_ACRS 16
 
 /*
   Has to be at least _NSIG_WORDS from asm/signal.h
@@ -15,20 +18,39 @@
 #define _SIGCONTEXT_NSIG      64
 #define _SIGCONTEXT_NSIG_BPW  32
 /* Size of stack frame allocated when calling signal handler. */
-#define __SIGNAL_FRAMESIZE      STACK_FRAME_OVERHEAD
-#define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
-#define SIGMASK_COPY_SIZE       (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
+#define __SIGNAL_FRAMESIZE	96
+#define _SIGCONTEXT_NSIG_WORDS	(_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
+#define _SIGMASK_COPY_SIZE	(sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
+
+typedef struct 
+{
+        unsigned long mask;
+        unsigned long addr;
+} _psw_t __attribute__ ((aligned(8)));
+
+typedef struct
+{
+	_psw_t psw;
+	unsigned long gprs[__NUM_GPRS];
+	unsigned int  acrs[__NUM_ACRS];
+} _s390_regs_common __attribute__ ((packed));
+
+typedef struct
+{
+	unsigned int fpc;
+	double   fprs[__NUM_FPRS];
+} _s390_fp_regs;
 
 typedef struct
 {
-	s390_regs_common regs;
-	s390_fp_regs     fpregs;
-} sigregs;
+	_s390_regs_common regs;
+	_s390_fp_regs     fpregs;
+} _sigregs;
 
 struct sigcontext
 {
 	unsigned long	oldmask[_SIGCONTEXT_NSIG_WORDS];
-	sigregs         *sregs;
+	_sigregs        *sregs;
 };
 
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/siginfo.h linux/include/asm-s390/siginfo.h
--- v2.4.1/linux/include/asm-s390/siginfo.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/siginfo.h	Tue Feb 13 14:13:44 2001
@@ -85,6 +85,25 @@
 #define si_band		_sifields._sigpoll._band
 #define si_fd		_sifields._sigpoll._fd
 
+#ifdef __KERNEL__
+#define __SI_MASK	0xffff0000
+#define __SI_KILL	(0 << 16)
+#define __SI_TIMER	(1 << 16)
+#define __SI_POLL	(2 << 16)
+#define __SI_FAULT	(3 << 16)
+#define __SI_CHLD	(4 << 16)
+#define __SI_RT		(5 << 16)
+#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#else
+#define __SI_KILL	0
+#define __SI_TIMER	0
+#define __SI_POLL	0
+#define __SI_FAULT	0
+#define __SI_CHLD	0
+#define __SI_RT		0
+#define __SI_CODE(T,N)	(N)
+#endif
+
 /*
  * si_code values
  * Digital reserves positive values for kernel-generated signals.
@@ -201,5 +220,21 @@
 
 #define sigev_notify_function	_sigev_un._sigev_thread._function
 #define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+
+extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(siginfo_t));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+}
+
+extern int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from);
+
+#endif /* __KERNEL__ */
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/sigp.h linux/include/asm-s390/sigp.h
--- v2.4.1/linux/include/asm-s390/sigp.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/sigp.h	Tue Feb 13 14:13:44 2001
@@ -41,83 +41,6 @@
 	sigp_store_extended_status_at_address
 } sigp_order_code;
 
-#if 0
-/*
- * these definitions are not used at the moment, but we might need
- * them in future.
- */
-typedef struct
-{
-        __u64   cpu_timer;
-        psw_t   current_psw;
-        __u32   prefix;
-        __u32   access_regs[16];
-        __u64   float_regs[4];
-        __u32   gpr_regs[16];
-        __u32   control_regs[16];
-} sigp_status __attribute__((packed));
-
-typedef struct
-{
-        __u8    unused1[216];
-        __u64   cpu_timer;
-        psw_t   current_psw;
-        __u32   prefix;
-        __u32   access_regs[16];
-        __u64   float_regs[4];
-        __u32   gpr_regs[16];
-        __u32   control_regs[16];
-} sigp_status_512 __attribute__((packed));
-
-typedef struct
-{
-        __u32   extended_save_area_address;
-        __u64   cpu_timer;
-        psw_t   current_psw;
-        __u32   prefix;
-        __u32   access_regs[16];
-        __u64   float_regs[4];
-        __u32   gpr_regs[16];
-        __u32   control_regs[16];
-} sigp_extended_status __attribute__((packed));
-
-typedef struct
-{
-        __u8    unused1[212];
-        __u32   extended_save_area_address;
-        __u64   cpu_timer;
-        psw_t   current_psw;
-        __u32   prefix;
-        __u32   access_regs[16];
-        __u64   float_regs[4];
-        __u32   gpr_regs[16];
-        __u32   control_regs[16];
-} sigp_extended_status_512 __attribute__((packed));
-
-typedef struct
-{
-	__u64   bfp_float_regs[16];
-	__u32   bfp_float_control_reg;
-	__u8    reserved[12];                     
-} sigp_extended_save_area __attribute__ ((packed));
-
-typedef struct
-{
-	unsigned equipment_check:1;
-	unsigned unassigned1:20;
-	unsigned incorrect_state:1;
-	unsigned invalid_parameter:1;
-	unsigned external_call_pending:1;
-	unsigned stopped:1;
-	unsigned operator_intervening:1;
-	unsigned check_stop:1;
-	unsigned unassigned2:1;
-	unsigned inoperative:1;
-	unsigned invalid_order:1;
-	unsigned receiver_check:1;
-} sigp_status_bits __attribute__((packed));
-#endif
-
 typedef __u32 sigp_status_word;
 
 typedef enum
@@ -140,16 +63,15 @@
         ec_restart,
         ec_halt,
         ec_power_off,
+        ec_ptlb,
 	ec_bit_last
 } ec_bit_sig;
 
 /* Signals which come with a parameter area, synchronous */
 typedef enum
 {
-	ec_set_ctl,
-	ec_get_ctl,
-	ec_set_ctl_masked,
-        ec_cmd_last
+        ec_callback_async,
+        ec_callback_sync
 } ec_cmd_sig;
 
 /* state information for synchronous signals */
@@ -166,25 +88,9 @@
 	ec_cmd_sig cmd;
 	atomic_t status;
 	struct ec_ext_call *next;
-	void *parms;
+        void (*func)(void *info);
+        void *info;
 } ec_ext_call;
-
-/* parameter area for the ec_set_ctl and ec_get_ctl signal */
-typedef struct
-{
-	__u16 start_ctl;
-	__u16 end_ctl;
-	__u32 cregs[16];
-} ec_creg_parms;
-
-/* parameter area for the ec_set_ctl_masked signal */
-typedef struct
-{
-	__u16 start_ctl;
-	__u16 end_ctl;
-	__u32 orvals[16];
-	__u32 andvals[16];
-} ec_creg_mask_parms;
 
 /*
  * Signal processor
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/smp.h linux/include/asm-s390/smp.h
--- v2.4.1/linux/include/asm-s390/smp.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/smp.h	Tue Feb 13 14:13:44 2001
@@ -13,7 +13,7 @@
 #ifndef __ASSEMBLY__
 
 #include <asm/lowcore.h>
-#include <linux/tasks.h>    // FOR NR_CPUS definition only.
+#include <linux/threads.h>  // FOR NR_CPUS definition only.
 #include <linux/kernel.h>   // FOR FASTCALL definition
 
 #define smp_processor_id() (current->processor)
@@ -31,7 +31,6 @@
  
 #define PROC_CHANGE_PENALTY	20		/* Schedule penalty */
 
-extern unsigned long ipi_count;
 extern void count_cpus(void);
 
 extern __inline__ int cpu_logical_map(int cpu)
@@ -67,10 +66,11 @@
 	__u16      cpu;
 } sigp_info;
 
-sigp_ccode smp_ext_call_sync(int cpu, ec_cmd_sig cmd,void *parms);
-sigp_ccode smp_ext_call_async(int cpu, ec_bit_sig sig);
-void smp_ext_call_sync_others(ec_cmd_sig cmd, void *parms);
-void smp_ext_call_async_others(ec_bit_sig sig);
+sigp_ccode
+smp_ext_call(int cpu, void (*callback)(void *info), void *info, int wait);
+void smp_ext_call_others(void (*callback)(void *info), void *info, int wait);
+sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig);
+void smp_ext_bitcall_others(ec_bit_sig sig);
 
 int smp_signal_others(sigp_order_code order_code,__u32 parameter,
                       int spin,sigp_info *info);
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/smplock.h linux/include/asm-s390/smplock.h
--- v2.4.1/linux/include/asm-s390/smplock.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/smplock.h	Tue Feb 13 14:13:44 2001
@@ -7,9 +7,11 @@
  */
 
 #include <linux/interrupt.h>
-#include <asm/spinlock.h>
+#include <linux/spinlock.h>
 
 extern spinlock_t kernel_flag;
+
+#define kernel_locked()                spin_is_locked(&kernel_flag)
 
 /*
  * Release global kernel lock and global interrupt lock
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/socket.h linux/include/asm-s390/socket.h
--- v2.4.1/linux/include/asm-s390/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-s390/socket.h	Sat Feb  3 11:26:44 2001
@@ -51,6 +51,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/spinlock.h linux/include/asm-s390/spinlock.h
--- v2.4.1/linux/include/asm-s390/spinlock.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/spinlock.h	Tue Feb 13 14:13:44 2001
@@ -24,37 +24,36 @@
 
 #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
 #define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
-#define spin_unlock_wait(lp)	do { barrier(); } while((volatile spinlock_t *)(lp)->lock)
+#define spin_unlock_wait(lp)	do { barrier(); } while(((volatile spinlock_t *)(lp))->lock)
 #define spin_is_locked(x) ((x)->lock != 0)
 
 extern inline void spin_lock(spinlock_t *lp)
 {
-	__asm__ __volatile("    lhi   1,-1\n"
-			   "0:  slr   0,0\n"
-			   "    cs    0,1,%1\n"
-			   "    jl    0b"
-			   : "=m" (lp->lock)
-			   : "0" (lp->lock) : "0", "1");
+        __asm__ __volatile("    bras  1,1f\n"
+                           "0:  diag  0,0,68\n"
+                           "1:  slr   0,0\n"
+                           "    cs    0,1,%1\n"
+                           "    jl    0b\n"
+                           : "=m" (lp->lock)
+                           : "0" (lp->lock) : "0", "1", "cc" );
 }
 
 extern inline int spin_trylock(spinlock_t *lp)
 {
 	unsigned long result;
 	__asm__ __volatile("    slr   %1,%1\n"
-			   "    lhi   0,-1\n"
-			   "0:  cs    %1,0,%0"
+			   "    basr  1,0\n"
+			   "0:  cs    %1,1,%0"
 			   : "=m" (lp->lock), "=&d" (result)
-			   : "0" (lp->lock) : "0");
+			   : "0" (lp->lock) : "1", "cc" );
 	return !result;
 }
 
-
-
 extern inline void spin_unlock(spinlock_t *lp)
 {
 	__asm__ __volatile("    xc 0(4,%0),0(%0)\n"
                            "    bcr 15,0"
-			   : /* no output */ : "a" (lp) );
+			   : /* no output */ : "a" (lp) : "memory", "cc" );
 }
 		
 /*
@@ -76,45 +75,42 @@
 
 #define read_lock(rw)   \
         asm volatile("   l     2,%0\n"   \
-                     "0: sll   2,1\n"    \
-                     "   srl   2,1\n"     /* clear high (=write) bit */ \
-                     "   lr    3,2\n"    \
-                     "   ahi   3,1\n"     /* one more reader */ \
+                     "   j     1f\n"     \
+                     "0: diag  0,0,68\n" \
+                     "1: la    2,0(2)\n"  /* clear high (=write) bit */ \
+                     "   la    3,1(2)\n"  /* one more reader */ \
                      "   cs    2,3,%0\n"  /* try to write new value */ \
                      "   jl    0b"       \
-                     : "+m" ((rw)->lock) : : "2", "3" );
+                     : "+m" ((rw)->lock) : : "2", "3", "cc" );
 
 #define read_unlock(rw) \
         asm volatile("   l     2,%0\n"   \
-                     "0: lr    3,2\n"    \
+                     "   j     1f\n"     \
+                     "0: diag  0,0,68\n" \
+                     "1: lr    3,2\n"    \
                      "   ahi   3,-1\n"    /* one less reader */ \
                      "   cs    2,3,%0\n" \
                      "   jl    0b"       \
-                     : "+m" ((rw)->lock) : : "2", "3" );
+                     : "+m" ((rw)->lock) : : "2", "3", "cc" );
 
 #define write_lock(rw) \
         asm volatile("   lhi   3,1\n"    \
                      "   sll   3,31\n"    /* new lock value = 0x80000000 */ \
-                     "0: slr   2,2\n"     /* old lock value must be 0 */ \
+                     "   j     1f\n"     \
+                     "0: diag  0,0,68\n" \
+                     "1: slr   2,2\n"     /* old lock value must be 0 */ \
                      "   cs    2,3,%0\n" \
                      "   jl    0b"       \
-                     : "+m" ((rw)->lock) : : "2", "3" );
+                     : "+m" ((rw)->lock) : : "2", "3", "cc" );
 
 #define write_unlock(rw) \
         asm volatile("   slr   3,3\n"     /* new lock value = 0 */ \
-                     "0: lhi   2,1\n"    \
+                     "   j     1f\n"     \
+                     "0: diag  0,0,68\n" \
+                     "1: lhi   2,1\n"    \
                      "   sll   2,31\n"    /* old lock value must be 0x80000000 */ \
                      "   cs    2,3,%0\n" \
                      "   jl    0b"       \
-                     : "+m" ((rw)->lock) : : "2", "3" );
+                     : "+m" ((rw)->lock) : : "2", "3", "cc" );
 
 #endif /* __ASM_SPINLOCK_H */
-
-
-
-
-
-
-
-
-
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/stat.h linux/include/asm-s390/stat.h
--- v2.4.1/linux/include/asm-s390/stat.h	Tue Aug  1 14:08:00 2000
+++ linux/include/asm-s390/stat.h	Tue Feb 13 14:13:44 2001
@@ -50,36 +50,30 @@
  * insane amounts of padding around dev_t's.
  */
 struct stat64 {
-        unsigned short  st_dev;
         unsigned char   __pad0[6];
-
-        unsigned long long st_ino;
+        unsigned short  st_dev;
+        unsigned int    __pad1;
+#define STAT64_HAS_BROKEN_ST_INO        1
+        unsigned long   __st_ino;
         unsigned int    st_mode;
         unsigned int    st_nlink;
-
         unsigned long   st_uid;
         unsigned long   st_gid;
-
+        unsigned char   __pad2[6];
         unsigned short  st_rdev;
-        unsigned char   __pad3[10];
-
+        unsigned int    __pad3;
         long long       st_size;
         unsigned long   st_blksize;
-
-        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
-        unsigned long   __pad4;         /* future possible st_blocks high bits */
-
+        unsigned char   __pad4[4];
+        unsigned long   __pad5;     /* future possible st_blocks high bits */
+        unsigned long   st_blocks;  /* Number 512-byte blocks allocated. */
         unsigned long   st_atime;
-        unsigned long   __pad5;
-
-        unsigned long   st_mtime;
         unsigned long   __pad6;
-
+        unsigned long   st_mtime;
+        unsigned long   __pad7;
         unsigned long   st_ctime;
-        unsigned long   __pad7;         /* will be high 32 bits of ctime someday */
-
-        unsigned long   __unused1;
-        unsigned long   __unused2;
+        unsigned long   __pad8;     /* will be high 32 bits of ctime someday */
+        unsigned long long      st_ino;
 };
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/string.h linux/include/asm-s390/string.h
--- v2.4.1/linux/include/asm-s390/string.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/string.h	Tue Feb 13 14:13:44 2001
@@ -40,24 +40,29 @@
 #undef __HAVE_ARCH_STRSTR
 
 extern void *memset(void *, int, size_t);
+extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
+extern char *strncpy(char *, const char *, size_t);
+extern int strcmp(const char *,const char *);
 
-extern inline void * memchr(const void * cs,int c,size_t count)
+static inline void * memchr(const void * cs,int c,size_t count)
 {
     void *ptr;
 
     __asm__ __volatile__ ("   lr    0,%2\n"
+                          "   lr    1,%1\n"
                           "   la    %0,0(%3,%1)\n"
-                          "0: srst  %0,%1\n"
+                          "0: srst  %0,1\n"
                           "   jo    0b\n"
                           "   brc   13,1f\n"
                           "   slr   %0,%0\n"
                           "1:"
-                          : "=a" (ptr) : "a" (cs), "d" (c), "d" (count)
-                          : "cc", "0" );
+                          : "=&a" (ptr) : "a" (cs), "d" (c), "d" (count)
+                          : "cc", "0", "1" );
     return ptr;
 }
 
-extern __inline__ char *strcpy(char *dest, const char *src)
+static __inline__ char *strcpy(char *dest, const char *src)
 {
     char *tmp = dest;
 
@@ -69,7 +74,7 @@
     return tmp;
 }
 
-extern __inline__ size_t strlen(const char *s)
+static __inline__ size_t strlen(const char *s)
 {
     size_t len;
 
@@ -84,7 +89,7 @@
     return len;
 }
 
-extern __inline__ char *strcat(char *dest, const char *src)
+static __inline__ char *strcat(char *dest, const char *src)
 {
     char *tmp = dest;
 
@@ -100,8 +105,13 @@
     return tmp;
 }
 
+extern void *alloca(size_t);
 
 #endif /* __KERNEL__ */
 
 #endif /* __S390_STRING_H_ */
+
+
+
+
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/system.h linux/include/asm-s390/system.h
--- v2.4.1/linux/include/asm-s390/system.h	Thu Aug  3 15:38:11 2000
+++ linux/include/asm-s390/system.h	Tue Feb 13 14:13:44 2001
@@ -12,6 +12,7 @@
 #define __ASM_SYSTEM_H
 
 #include <linux/config.h>
+#include <asm/types.h>
 #ifdef __KERNEL__
 #include <asm/lowcore.h>
 #endif
@@ -40,7 +41,7 @@
                         asm volatile (
                                 "   lhi   1,3\n"
                                 "   nr    1,%0\n"     /* isolate last 2 bits */
-                                "   xr    1,%0\n"     /* align ptr */
+                                "   xr    %0,1\n"     /* align ptr */
                                 "   bras  2,0f\n"
                                 "   icm   1,8,%1\n"   /* for ptr&3 == 0 */
                                 "   stcm  0,8,%1\n"
@@ -52,13 +53,13 @@
                                 "   stcm  0,1,%1\n"
                                 "0: sll   1,3\n"
                                 "   la    2,0(1,2)\n" /* r2 points to an icm */
-                                "   l     0,%1\n"     /* get fullword */
+                                "   l     0,0(%0)\n"  /* get fullword */
                                 "1: lr    1,0\n"      /* cs loop */
                                 "   ex    0,0(2)\n"   /* insert x */
-                                "   cs    0,1,%1\n"
+                                "   cs    0,1,0(%0)\n"
                                 "   jl    1b\n"
                                 "   ex    0,4(2)"     /* store *ptr to x */
-                                : "+a&" (ptr) : "m" (x)
+                                : "+a&" (ptr), "+m" (x) :
                                 : "memory", "0", "1", "2");
                 case 2:
                         if(((__u32)ptr)&1)
@@ -66,7 +67,7 @@
                         asm volatile (
                                 "   lhi   1,2\n"
                                 "   nr    1,%0\n"     /* isolate bit 2^1 */
-                                "   xr    1,%0\n"     /* align ptr */
+                                "   xr    %0,1\n"     /* align ptr */
                                 "   bras  2,0f\n"
                                 "   icm   1,12,%1\n"   /* for ptr&2 == 0 */
                                 "   stcm  0,12,%1\n"
@@ -74,13 +75,13 @@
                                 "   stcm  0,3,%1\n"
                                 "0: sll   1,2\n"
                                 "   la    2,0(1,2)\n" /* r2 points to an icm */
-                                "   l     0,%1\n"     /* get fullword */
+                                "   l     0,0(%0)\n"  /* get fullword */
                                 "1: lr    1,0\n"      /* cs loop */
                                 "   ex    0,0(2)\n"   /* insert x */
-                                "   cs    0,1,%1\n"
+                                "   cs    0,1,0(%0)\n"
                                 "   jl    1b\n"
                                 "   ex    0,4(2)"     /* store *ptr to x */
-                                : "+a&" (ptr) : "m" (x)
+                                : "+a&" (ptr), "+m" (x) :
                                 : "memory", "0", "1", "2");
                         break;
                 case 4:
@@ -115,6 +116,12 @@
 #define mb()    eieio()
 #define rmb()   eieio()
 #define wmb()   eieio()
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_mb__before_clear_bit()     smp_mb()
+#define smp_mb__after_clear_bit()      smp_mb()
+
 
 #define set_mb(var, value)      do { var = value; mb(); } while (0)
 #define set_wmb(var, value)     do { var = value; wmb(); } while (0)
@@ -139,6 +146,27 @@
 #define __restore_flags(x) \
         __asm__ __volatile__("ssm   %0" : : "m" (x) : "memory")
 
+#define __load_psw(psw) \
+	__asm__ __volatile__("lpsw %0" : : "m" (psw));
+
+#define __ctl_load(array, low, high) ({ \
+	__asm__ __volatile__ ( \
+		"   la    1,%0\n" \
+		"   bras  2,0f\n" \
+                "   lctl  0,0,0(1)\n" \
+		"0: ex    %1,0(2)" \
+		: : "m" (array), "a" (((low)<<4)+(high)) : "1", "2" ); \
+	})
+
+#define __ctl_store(array, low, high) ({ \
+	__asm__ __volatile__ ( \
+		"   la    1,%0\n" \
+		"   bras  2,0f\n" \
+		"   stctl 0,0,0(1)\n" \
+		"0: ex    %1,0(2)" \
+		: "=m" (array) : "a" (((low)<<4)+(high)): "1", "2" ); \
+	})
+
 #define __ctl_set_bit(cr, bit) ({ \
         __u8 dummy[16]; \
         __asm__ __volatile__ ( \
@@ -220,7 +248,6 @@
 extern void save_fp_regs(s390_fp_regs *fpregs);
 extern int restore_fp_regs1(s390_fp_regs *fpregs);
 extern void restore_fp_regs(s390_fp_regs *fpregs);
-extern void show_crashed_task_info(void);
 #endif
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/termios.h linux/include/asm-s390/termios.h
--- v2.4.1/linux/include/asm-s390/termios.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/termios.h	Tue Feb 13 14:13:44 2001
@@ -60,7 +60,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC         13	/* synchronous HDLC */
 
@@ -77,18 +77,19 @@
 /*
  * Translate a "termio" structure into a "termios". Ugh.
  */
-#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
-	unsigned short __tmp; \
-	get_user(__tmp,&(termio)->x); \
-	*(unsigned short *) &(termios)->x = __tmp; \
-}
 
 #define user_termio_to_kernel_termios(termios, termio) \
 ({ \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
-	SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
+        unsigned short tmp; \
+        get_user(tmp, &(termio)->c_iflag); \
+        (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
+        get_user(tmp, &(termio)->c_oflag); \
+        (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
+        get_user(tmp, &(termio)->c_cflag); \
+        (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
+        get_user(tmp, &(termio)->c_lflag); \
+        (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
+        get_user((termios)->c_line, &(termio)->c_line); \
 	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
 })
 
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/todclk.h linux/include/asm-s390/todclk.h
--- v2.4.1/linux/include/asm-s390/todclk.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390/todclk.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,19 @@
+/*
+ * File...........: linux/include/asm/todclk.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ */
+
+#ifndef __ASM_TODCLK_H
+#define __ASM_TODCLK_H
+
+#define TOD_uSEC (0x1000ULL)
+#define TOD_mSEC (1000 * TOD_uSEC)
+#define TOD_SEC (1000 * TOD_mSEC)
+#define TOD_MIN (60 * TOD_SEC)
+#define TOD_HOUR (60 * TOD_MIN)
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/uaccess.h linux/include/asm-s390/uaccess.h
--- v2.4.1/linux/include/asm-s390/uaccess.h	Tue Aug 29 14:09:16 2000
+++ linux/include/asm-s390/uaccess.h	Tue Feb 13 14:13:44 2001
@@ -84,15 +84,14 @@
 {
         int err;
 
-        __asm__ __volatile__ (  "   iac   1\n"
-				"   sr    %1,%1\n"
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
 				"   la    4,%0\n"
                                 "   sacf  512\n"
                                 "0: st    %2,0(4)\n"
-                                "   sacf  0(1)\n"
+                                "   sacf  0\n"
 				"1:\n"
 				".section .fixup,\"ax\"\n"
-				"2: sacf  0(1)\n"
+				"2: sacf  0\n"
 				"   lhi   %1,%h3\n"
 				"   bras  4,3f\n"
 				"   .long 1b\n"
@@ -105,7 +104,7 @@
 				".previous"
                                 : "=m" (*((__u32*) ptr)) , "=&d" (err)
                                 : "d" (x), "K" (-EFAULT)
-                                : "1", "4" );
+                                : "4" );
         return err;
 }
 
@@ -113,15 +112,14 @@
 {
         int err;
 
-        __asm__ __volatile__ (  "   iac   1\n"
-				"   sr    %1,%1\n"
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
 				"   la    4,%0\n"
                                 "   sacf  512\n"
                                 "0: sth   %2,0(4)\n"
-                                "   sacf  0(1)\n"
+                                "   sacf  0\n"
 				"1:\n"
 				".section .fixup,\"ax\"\n"
-				"2: sacf  0(1)\n"
+				"2: sacf  0\n"
 				"   lhi   %1,%h3\n"
 				"   bras  4,3f\n"
 				"   .long 1b\n"
@@ -134,7 +132,7 @@
 				".previous"
                                 : "=m" (*((__u16*) ptr)) , "=&d" (err)
                                 : "d" (x), "K" (-EFAULT)
-                                : "1", "4" );
+                                : "4" );
         return err;
 }
 
@@ -142,15 +140,14 @@
 {
         int err;
 
-        __asm__ __volatile__ (  "   iac   1\n"
-				"   sr    %1,%1\n"
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
 				"   la    4,%0\n"
                                 "   sacf  512\n"
                                 "0: stc   %2,0(4)\n"
-                                "   sacf  0(1)\n"
+                                "   sacf  0\n"
 				"1:\n"
 				".section .fixup,\"ax\"\n"
-				"2: sacf  0(1)\n"
+				"2: sacf  0\n"
 				"   lhi   %1,%h3\n"
 				"   bras  4,3f\n"
 				"   .long 1b\n"
@@ -163,7 +160,7 @@
 				".previous"
                                 : "=m" (*((__u8*) ptr)) , "=&d" (err)
                                 : "d" (x), "K" (-EFAULT)
-                                : "1", "4" );
+                                : "4" );
         return err;
 }
 
@@ -176,13 +173,13 @@
         int __pu_err;                                           \
         switch (sizeof (*(ptr))) {                              \
                 case 1:                                         \
-                        __pu_err = __put_user_asm_1((__u8)(__u32)x,ptr);\
+                        __pu_err = __put_user_asm_1((__u8)(__u32)x,(ptr));\
                         break;                                  \
                 case 2:                                         \
-                        __pu_err = __put_user_asm_2((__u16)(__u32)x,ptr);\
+                        __pu_err = __put_user_asm_2((__u16)(__u32)x,(ptr));\
                         break;                                  \
                 case 4:                                         \
-                        __pu_err = __put_user_asm_4((__u32) x,ptr);\
+                        __pu_err = __put_user_asm_4((__u32) x,(ptr));\
                         break;                                  \
                 default:                                        \
                 __pu_err = __put_user_bad();                    \
@@ -195,7 +192,7 @@
 ({                                                              \
         long __pu_err = -EFAULT;                                \
         __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
-        __typeof__(x) __x = (x);                                \
+        __typeof__(*(ptr)) __x = (x);                           \
         if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) {      \
                 __pu_err = 0;                                   \
                 __put_user((__x), (__pu_addr));                 \
@@ -206,83 +203,80 @@
 extern int __put_user_bad(void);
 
 
-#define __get_user_asm_4(x, ptr, err)                                   \
-({                                                                      \
-        __asm__ __volatile__ (  "   iac   1\n"                          \
-                                "   sr    %1,%1\n"                      \
-                                "   la    4,%2\n"                       \
-                                "   sacf  512\n"                        \
-                                "0: l     %0,0(4)\n"                    \
-                                "   sacf  0(1)\n"                       \
-                                "1:\n"                                  \
-                                ".section .fixup,\"ax\"\n"              \
-                                "2: sacf  0(1)\n"                       \
-                                "   lhi   %1,%h3\n"                     \
-                                "   bras  4,3f\n"                       \
-                                "   .long 1b\n"                         \
-                                "3: l     4,0(4)\n"                     \
-                                "   br    4\n"                          \
-                                ".previous\n"                           \
-                                ".section __ex_table,\"a\"\n"           \
-                                "   .align 4\n"                         \
-                                "   .long 0b,2b\n"                      \
-                                ".previous"                             \
-                                : "=d" (x) , "=&d" (err)                \
-                                : "m" (*(__u32*) ptr), "K" (-EFAULT)    \
-                                : "1", "4" );                           \
-})
-
-#define __get_user_asm_2(x, ptr, err)                                   \
-({                                                                      \
-        __asm__ __volatile__ (  "   iac   1\n"                          \
-                                "   sr    %1,%1\n"                      \
-                                "   la    4,%2\n"                       \
-                                "   sacf  512\n"                        \
-                                "0: lh    %0,0(4)\n"                    \
-                                "   sacf  0(1)\n"                       \
-                                "1:\n"                                  \
-                                ".section .fixup,\"ax\"\n"              \
-                                "2: sacf  0(1)\n"                       \
-                                "   lhi   %1,%h3\n"                     \
-                                "   bras  4,3f\n"                       \
-                                "   .long 1b\n"                         \
-                                "3: l     4,0(4)\n"                     \
-                                "   br    4\n"                          \
-                                ".previous\n"                           \
-                                ".section __ex_table,\"a\"\n"           \
-                                "   .align 4\n"                         \
-                                "   .long 0b,2b\n"                      \
-                                ".previous"                             \
-                                : "=d" (x) , "=&d" (err)                \
-                                : "m" (*(__u16*) ptr), "K" (-EFAULT)    \
-                                : "1", "4" );                           \
-})
-
-#define __get_user_asm_1(x, ptr, err)                                   \
-({                                                                      \
-        __asm__ __volatile__ (  "   iac   1\n"                          \
-                                "   sr    %1,%1\n"                      \
-                                "   la    4,%2\n"                       \
-                                "   sr    %0,%0\n"                      \
-                                "   sacf  512\n"                        \
-                                "0: ic    %0,0(4)\n"                    \
-                                "   sacf  0(1)\n"                       \
-                                "1:\n"                                  \
-                                ".section .fixup,\"ax\"\n"              \
-                                "2: sacf  0(1)\n"                       \
-                                "   lhi   %1,%h3\n"                     \
-                                "   bras  4,3f\n"                       \
-                                "   .long 1b\n"                         \
-                                "3: l     4,0(4)\n"                     \
-                                "   br    4\n"                          \
-                                ".previous\n"                           \
-                                ".section __ex_table,\"a\"\n"           \
-                                "   .align 4\n"                         \
-                                "   .long 0b,2b\n"                      \
-                                ".previous"                             \
-                                : "=d" (x) , "=&d" (err)                \
-                                : "m" (*(__u8*) ptr), "K" (-EFAULT)     \
-                                : "1", "4" );                           \
+#define __get_user_asm_4(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: l     %0,0(4)\n"                       \
+                                "   sacf  0\n"                             \
+                                "1:\n"                                     \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: sacf  0\n"                             \
+                                "   lhi   %1,%h3\n"                        \
+                                "   bras  4,3f\n"                          \
+                                "   .long 1b\n"                            \
+                                "3: l     4,0(4)\n"                        \
+                                "   br    4\n"                             \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 4\n"                            \
+                                "   .long 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+
+#define __get_user_asm_2(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: lh    %0,0(4)\n"                       \
+                                "   sacf  0\n"                             \
+                                "1:\n"                                     \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: sacf  0\n"                             \
+                                "   lhi   %1,%h3\n"                        \
+                                "   bras  4,3f\n"                          \
+                                "   .long 1b\n"                            \
+                                "3: l     4,0(4)\n"                        \
+                                "   br    4\n"                             \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 4\n"                            \
+                                "   .long 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+
+#define __get_user_asm_1(x, ptr, err)                                     \
+({                                                                        \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                        \
+                                "   la    4,%2\n"                         \
+                                "   sr    %0,%0\n"                        \
+                                "   sacf  512\n"                          \
+                                "0: ic    %0,0(4)\n"                      \
+                                "   sacf  0\n"                            \
+                                "1:\n"                                    \
+                                ".section .fixup,\"ax\"\n"                \
+                                "2: sacf  0\n"                            \
+                                "   lhi   %1,%h3\n"                       \
+                                "   bras  4,3f\n"                         \
+                                "   .long 1b\n"                           \
+                                "3: l     4,0(4)\n"                       \
+                                "   br    4\n"                            \
+                                ".previous\n"                             \
+                                ".section __ex_table,\"a\"\n"             \
+                                "   .align 4\n"                           \
+                                "   .long 0b,2b\n"                        \
+                                ".previous"                               \
+                                : "=d" (x) , "=&d" (err)                  \
+                                : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                  \
 })
 
 #define __get_user(x, ptr)                                      \
@@ -310,7 +304,7 @@
 ({                                                              \
         long __gu_err = -EFAULT;                                \
         __typeof__(ptr) __gu_addr = (ptr);                      \
-        __typeof__(x) __x;                                      \
+        __typeof__(*(ptr)) __x;                                 \
         if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) {      \
                 __gu_err = 0;                                   \
                 __get_user((__x), (__gu_addr));                 \
@@ -327,26 +321,28 @@
  * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
  */
 
+asmlinkage void __copy_from_user_fixup(void /* special calling convention */);
+asmlinkage void __copy_to_user_fixup(void /* special calling convention */);
+
 extern inline unsigned long
 __copy_to_user_asm(void* to, const void* from,  long n)
 {
 
-        __asm__ __volatile__ (  "   iac   1\n"
-                                "   lr    2,%2\n"
+        __asm__ __volatile__ (  "   lr    2,%2\n"
                                 "   lr    4,%1\n"
                                 "   lr    3,%0\n"
                                 "   lr    5,3\n"
                                 "   sacf  512\n"
                                 "0: mvcle 4,2,0\n"
                                 "   jo    0b\n"
-                                "1: sacf  0(1)\n"
+                                "   sacf  0\n"
                                 "   lr    %0,3\n"
 				".section __ex_table,\"a\"\n"
 				"   .align 4\n"
-				"   .long  0b,1b\n"
+				"   .long  0b,__copy_to_user_fixup\n"
 				".previous"
                                 : "+&d" (n) : "d" (to), "d" (from)
-                                : "1", "2", "3", "4", "5" );
+                                : "2", "3", "4", "5" );
         return n;
 }
 
@@ -370,22 +366,21 @@
 extern inline unsigned long
 __copy_from_user_asm(void* to, const void* from,  long n)
 {
-        __asm__ __volatile__ (  "   iac   1\n"
-				"   lr    2,%1\n"
+        __asm__ __volatile__ (  "   lr    2,%1\n"
                                 "   lr    4,%2\n"
                                 "   lr    3,%0\n"
                                 "   lr    5,3\n"
                                 "   sacf  512\n"
                                 "0: mvcle 2,4,0\n"
                                 "   jo    0b\n"
-                                "1: sacf  0(1)\n"
+                                "   sacf  0\n"
                                 "   lr    %0,3\n"
 				".section __ex_table,\"a\"\n"
 				"   .align 4\n"
-				"   .long  0b,1b\n"
+				"   .long  0b,__copy_from_user_fixup\n"
 				".previous"
                                 : "+&d" (n) : "d" (to), "d" (from)
-                                : "1", "2", "3", "4", "5" );
+                                : "2", "3", "4", "5" );
         return n;
 }
 
@@ -412,11 +407,10 @@
  */
 
 static inline long
-strncpy_from_user(char *dst, const char *src, long count)
+__strncpy_from_user(char *dst, const char *src, long count)
 {
         int len;
-        __asm__ __volatile__ (  "   iac   1\n"
-				"   slr   %0,%0\n"
+        __asm__ __volatile__ (  "   slr   %0,%0\n"
 				"   lr    2,%1\n"
                                 "   lr    4,%2\n"
                                 "   slr   3,3\n"
@@ -428,7 +422,7 @@
                                 "   ahi   %0,1\n"
                                 "   clr   %0,%3\n"
                                 "   jl    0b\n"
-                                "2: sacf  0(1)\n"
+                                "2: sacf  0\n"
 				".section .fixup,\"ax\"\n"
                                 "3: lhi   %0,%h4\n"
 				"   basr  3,0\n"
@@ -444,10 +438,20 @@
                                 : "=&a" (len)
                                 : "a" (dst), "d" (src), "d" (count),
                                   "K" (-EFAULT)
-                                : "1", "2", "3", "4", "memory" );
+                                : "2", "3", "4", "memory" );
         return len;
 }
 
+static inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+        long res = -EFAULT;
+        if (access_ok(VERIFY_READ, src, 1))
+                res = __strncpy_from_user(dst, src, count);
+        return res;
+}
+
+
 /*
  * Return the size of a string (including the ending 0)
  *
@@ -456,8 +460,7 @@
 static inline unsigned long
 strnlen_user(const char * src, unsigned long n)
 {
-	__asm__ __volatile__ ("   iac   1\n"
-                              "   alr   %0,%1\n"
+	__asm__ __volatile__ ("   alr   %0,%1\n"
 			      "   slr   0,0\n"
 			      "   lr    4,%1\n"
 			      "   sacf  512\n"
@@ -465,10 +468,10 @@
 			      "   jo    0b\n"
 			      "   slr   %0,%1\n"
 			      "   ahi   %0,1\n"
-			      "   sacf  0(1)\n"
+			      "   sacf  0\n"
                               "1:\n"
                               ".section .fixup,\"ax\"\n"
-                              "2: sacf  0(1)\n"
+                              "2: sacf  0\n"
                               "   slr   %0,%0\n"
                               "   bras  4,3f\n"
                               "   .long 1b\n"
@@ -480,7 +483,7 @@
 			      "   .long  0b,2b\n"
 			      ".previous"
 			      : "+&a" (n) : "d" (src)
-			      : "cc", "0", "1", "4" );
+			      : "cc", "0", "4" );
         return n;
 }
 #define strlen_user(str) strnlen_user(str, ~0UL)
@@ -490,26 +493,45 @@
  */
 
 static inline unsigned long
-clear_user(void *to, unsigned long n)
+__clear_user(void *to, unsigned long n)
 {
-        __asm__ __volatile__ (  "   iac   1\n"
-                                "   sacf  512\n"
+        __asm__ __volatile__ (  "   sacf  512\n"
                                 "   lr    4,%1\n"
                                 "   lr    5,%0\n"
                                 "   sr    2,2\n"
                                 "   sr    3,3\n"
                                 "0: mvcle 4,2,0\n"
                                 "   jo    0b\n"
-                                "1: sacf  0(1)\n"
-                                "   lr    %0,3\n"
+                                "   sacf  0\n"
+                                "1: lr    %0,3\n"
+                                ".section .fixup,\"ax\"\n"
+                                "2: lhi   5,-4096\n"
+                                "   n     5,0x90\n"
+                                "   sr    5,4\n"
+                                "   mvcle 4,2,0\n"
+                                "   sacf  0\n"
+                                "   basr  4,0\n"
+                                "   l     4,3f-.(4)\n"
+                                "   br    4\n"
+                                "3: .long 1b\n"
+                                ".previous\n"
 				".section __ex_table,\"a\"\n"
 				"   .align 4\n"
-				"   .long  0b,1b\n"
+				"   .long  0b,2b\n"
 				".previous"
                                 : "+&a" (n)
                                 : "a"   (to)
-                                : "cc", "1", "2", "3", "4", "5" );
+                                : "cc", "2", "3", "4", "5" );
+        return n;
+}
+
+static inline unsigned long
+clear_user(void *to, unsigned long n)
+{
+        if (access_ok(VERIFY_WRITE, to, n))
+                n = __clear_user(to, n);
         return n;
 }
+
 
 #endif                                 /* _S390_UACCESS_H                  */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/ucontext.h linux/include/asm-s390/ucontext.h
--- v2.4.1/linux/include/asm-s390/ucontext.h	Fri May 12 11:41:44 2000
+++ linux/include/asm-s390/ucontext.h	Tue Feb 13 14:13:44 2001
@@ -13,8 +13,10 @@
 	unsigned long	  uc_flags;
 	struct ucontext  *uc_link;
 	stack_t		  uc_stack;
-	struct sigcontext uc_mcontext;
 	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+	struct sigcontext *sc; /* Added for pthread support */
 };
+
+
 
 #endif /* !_ASM_S390_UCONTEXT_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390/unistd.h linux/include/asm-s390/unistd.h
--- v2.4.1/linux/include/asm-s390/unistd.h	Fri Aug 11 14:29:03 2000
+++ linux/include/asm-s390/unistd.h	Tue Feb 13 14:13:44 2001
@@ -222,7 +222,7 @@
         return (type) (res);                                 \
 } while (0)
 
-#define _svc_clobber "cc", "memory"
+#define _svc_clobber "2", "cc", "memory"
 
 #define _syscall0(type,name)                                 \
 type name(void) {                                            \
@@ -359,7 +359,6 @@
 static inline _syscall1(int,delete_module,const char *,name)
 static inline _syscall2(long,stat,char *,filename,struct stat *,statbuf)
 
-extern int sys_wait4(int, int *, int, struct rusage *);
 static inline pid_t waitpid(int pid, int * wait_stat, int flags)
 {
         return sys_wait4(pid, wait_stat, flags, NULL);
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/a.out.h linux/include/asm-s390x/a.out.h
--- v2.4.1/linux/include/asm-s390x/a.out.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/a.out.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,38 @@
+/*
+ *  include/asm-s390/a.out.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ *  Derived from "include/asm-i386/a.out.h"
+ *    Copyright (C) 1992, Linus Torvalds
+ *
+ * I don't think we'll ever need a.out ...
+ */
+
+#ifndef __S390_A_OUT_H__
+#define __S390_A_OUT_H__
+
+struct exec
+{
+  unsigned long a_info;		/* Use macros N_MAGIC, etc for access */
+  unsigned a_text;		/* length of text, in bytes */
+  unsigned a_data;		/* length of data, in bytes */
+  unsigned a_bss;		/* length of uninitialized data area for file, in bytes */
+  unsigned a_syms;		/* length of symbol table data in file, in bytes */
+  unsigned a_entry;		/* start address */
+  unsigned a_trsize;		/* length of relocation info for text, in bytes */
+  unsigned a_drsize;		/* length of relocation info for data, in bytes */
+};
+
+#define N_TRSIZE(a)	((a).a_trsize)
+#define N_DRSIZE(a)	((a).a_drsize)
+#define N_SYMSIZE(a)	((a).a_syms)
+
+#ifdef __KERNEL__
+
+#define STACK_TOP	TASK_SIZE
+
+#endif
+
+#endif /* __A_OUT_GNU_H__ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/atomic.h linux/include/asm-s390x/atomic.h
--- v2.4.1/linux/include/asm-s390x/atomic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/atomic.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,236 @@
+#ifndef __ARCH_S390_ATOMIC__
+#define __ARCH_S390_ATOMIC__
+
+/*
+ *  include/asm-s390x/atomic.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Denis Joseph Barrow
+ *
+ *  Derived from "include/asm-i386/bitops.h"
+ *    Copyright (C) 1992, Linus Torvalds
+ *
+ */
+
+/*
+ * Atomic operations that C can't guarantee us.  Useful for
+ * resource counting etc..
+ * S390 uses 'Compare And Swap' for atomicity in SMP enviroment
+ */
+
+typedef struct { volatile int counter; } atomic_t __attribute__ ((aligned (4)));
+#define ATOMIC_INIT(i)  { (i) }
+
+#define atomic_eieio()          __asm__ __volatile__ ("BCR 15,0")
+
+static __inline__ int atomic_read(atomic_t *v)
+{
+        int retval;
+        __asm__ __volatile__("bcr      15,0\n\t"
+                             "l        %0,%1"
+                             : "=d" (retval) : "m" (*v) );
+        return retval;
+}
+
+static __inline__ void atomic_set(atomic_t *v, int i)
+{
+        __asm__ __volatile__("st  %1,%0\n\t"
+                             "bcr 15,0"
+                             : "=m" (*v) : "d" (i) );
+}
+
+static __inline__ void atomic_add(int i, atomic_t *v)
+{
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,0(2)\n"
+                             "0: lr    1,0\n"
+                             "   ar    1,%1\n"
+                             "   cs    0,1,0(2)\n"
+                             "   jl    0b"
+                             : "+m" (*v) : "d" (i) : "0", "1", "2", "cc" );
+}
+
+static __inline__ int atomic_add_return (int i, atomic_t *v)
+{
+	int newval;
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,0(1)\n"
+                             "0: lr    %1,0\n"
+                             "   ar    %1,%2\n"
+                             "   cs    0,%1,0(1)\n"
+                             "   jl    0b"
+                             : "+m" (*v), "=&d" (newval)
+			     : "d" (i) : "0", "1", "cc" );
+	return newval;
+}
+
+static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
+{
+       int i;
+
+        __asm__ __volatile__("   l     0,%0\n"
+                             "0: lr    %1,0\n"
+                             "   ahi   %1,1\n"
+                             "   cs    0,%1,%0\n"
+                             "   jl    0b"
+                             : "+m" (*v), "=&d" (i) : : "0", "cc" );
+       return i != 0;
+}
+
+static __inline__ int atomic_add_negative(int i, atomic_t *v)
+{
+	int newval;
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,0(1)\n"
+                             "0: lr    %1,0\n"
+                             "   ar    %1,%2\n"
+                             "   cs    0,%1,0(1)\n"
+                             "   jl    0b\n"
+                             : "+m" (*v), "=&d" (newval)
+                             : "d" (i) : "0", "1", "cc" );
+        return newval < 0;
+}
+
+static __inline__ void atomic_sub(int i, atomic_t *v)
+{
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,0(2)\n"
+                             "0: lr    1,0\n"
+                             "   sr    1,%1\n"
+                             "   cs    0,1,0(2)\n"
+                             "   jl    0b"
+                             : "+m" (*v) : "d" (i) : "0", "1", "2", "cc" );
+}
+
+static __inline__ void atomic_inc(volatile atomic_t *v)
+{
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,0(2)\n"
+                             "0: lr    1,0\n"
+                             "   ahi   1,1\n"
+                             "   cs    0,1,0(2)\n"
+                             "   jl    0b"
+                             : "+m" (*v) : : "0", "1", "2", "cc" );
+}
+
+static __inline__ int atomic_inc_return(volatile atomic_t *v)
+{
+        int i;
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,0(1)\n"
+                             "0: lr    %1,0\n"
+                             "   ahi   %1,1\n"
+                             "   cs    0,%1,0(1)\n"
+                             "   jl    0b"
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
+        return i;
+}
+
+static __inline__ void atomic_dec(volatile atomic_t *v)
+{
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,0(2)\n"
+                             "0: lr    1,0\n"
+                             "   ahi   1,-1\n"
+                             "   cs    0,1,0(2)\n"
+                             "   jl    0b"
+                             : "+m" (*v) : : "0", "1", "2", "cc" );
+}
+
+static __inline__ int atomic_dec_return(volatile atomic_t *v)
+{
+        int i;
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,0(1)\n"
+                             "0: lr    %1,0\n"
+                             "   ahi   %1,-1\n"
+                             "   cs    0,%1,0(1)\n"
+                             "   jl    0b"
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc" );
+        return i;
+}
+
+static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
+{
+        int i;
+        __asm__ __volatile__("   la    1,%0\n"
+                             "   l     0,0(1)\n"
+                             "0: lr    %1,0\n"
+                             "   ahi   %1,-1\n"
+                             "   cs    0,%1,0(1)\n"
+                             "   jl    0b"
+                             : "+m" (*v), "=&d" (i) : : "0", "1", "cc");
+        return i == 0;
+}
+
+static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
+{
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,0(2)\n"
+                             "0: lr    1,0\n"
+                             "   nr    1,%1\n"
+                             "   cs    0,1,0(2)\n"
+                             "   jl    0b"
+                             : "+m" (*v) : "d" (~(mask))
+                             : "0", "1", "2", "cc" );
+}
+
+static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
+{
+        __asm__ __volatile__("   la    2,%0\n"
+                             "   l     0,0(2)\n"
+                             "0: lr    1,0\n"
+                             "   or    1,%1\n"
+                             "   cs    0,1,0(2)\n"
+                             "   jl    0b"
+                             : "+m" (*v) : "d" (mask) : "0", "1", "2", "cc" );
+}
+
+/*
+  returns 0  if expected_oldval==value in *v ( swap was successful )
+  returns 1  if unsuccessful.
+*/
+static __inline__ int
+atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
+{
+        int retval;
+
+        __asm__ __volatile__(
+                "  la   1,%1\n"
+                "  lr   0,%2\n"
+                "  cs   0,%3,0(1)\n"
+                "  ipm  %0\n"
+                "  srl  %0,28"
+                : "=&r" (retval), "+m" (*v)
+                : "d" (expected_oldval) , "d" (new_val)
+                : "0", "1", "cc");
+        return retval;
+}
+
+/*
+  Spin till *v = expected_oldval then swap with newval.
+ */
+static __inline__ void
+atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
+{
+        __asm__ __volatile__(
+                "   la  1,%0\n"
+                "0: lr  0,%1\n"
+                "   cs  0,%2,0(1)\n"
+                "   jl  0b\n"
+                : "+m" (*v)
+                : "d" (expected_oldval) , "d" (new_val)
+                : "cc", "0", "1");
+}
+
+#define atomic_compare_and_swap_debug(where,from,to) \
+if (atomic_compare_and_swap ((from), (to), (where))) {\
+	printk (KERN_WARNING"%s/%d atomic counter:%s couldn't be changed from %d(%s) to %d(%s), was %d\n",\
+		__FILE__,__LINE__,#where,(from),#from,(to),#to,atomic_read (where));\
+        atomic_set(where,(to));\
+}
+
+#endif                                 /* __ARCH_S390_ATOMIC __            */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/bitops.h linux/include/asm-s390x/bitops.h
--- v2.4.1/linux/include/asm-s390x/bitops.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/bitops.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,884 @@
+/*
+ *  include/asm-s390/bitops.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/bitops.h"
+ *    Copyright (C) 1992, Linus Torvalds
+ *
+ */
+
+#ifndef _S390_BITOPS_H
+#define _S390_BITOPS_H
+
+/*
+ * bit 0 is the LSB of *addr; bit 63 is the MSB of *addr;
+ * bit 64 is the LSB of *(addr+8). That combined with the
+ * big endian byte order on S390 give the following bit
+ * order in memory:
+ *    3f 3e 3d 3c 3b 3a 39 38 37 36 35 34 33 32 31 30
+ *    2f 2e 2d 2c 2b 2a 29 28 27 26 25 24 23 22 21 20
+ *    1f 1e 1d 1c 1b 1a 19 18 17 16 15 14 13 12 11 10
+ *    0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
+ * after that follows the next long with bit numbers
+ *    7f 7e 7d 7c 7b 7a 79 78 77 76 75 74 73 72 71 70
+ *    6f 6e 6d 6c 6b 6a 69 68 67 66 65 64 63 62 61 60
+ *    5f 5e 5d 5c 5b 5a 59 58 57 56 55 54 53 52 51 50
+ *    4f 4e 4d 4c 4b 4a 49 48 47 46 45 44 43 42 41 40
+ * The reason for this bit ordering is the fact that
+ * in the architecture independent code bits operations
+ * of the form "flags |= (1 << bitnr)" are used INTERMIXED
+ * with operation of the form "set_bit(bitnr, flags)".
+ */
+#include <linux/config.h>
+
+/* set ALIGN_CS to 1 if the SMP safe bit operations should
+ * align the address to 4 byte boundary. It seems to work
+ * without the alignment. 
+ */
+#define ALIGN_CS 0
+
+/* bitmap tables from arch/S390/kernel/bitmap.S */
+extern const char _oi_bitmap[];
+extern const char _ni_bitmap[];
+extern const char _zb_findmap[];
+
+#ifdef CONFIG_SMP
+/*
+ * SMP save set_bit routine based on compare and swap (CS)
+ */
+static __inline__ void set_bit_cs(unsigned long nr, volatile void * addr)
+{
+        unsigned long bits, mask;
+        __asm__ __volatile__(
+#if ALIGN_CS == 1
+             "   lghi  %2,3\n"         /* CS must be aligned on 4 byte b. */
+             "   ngr   %2,%1\n"        /* isolate last 2 bits of address */
+             "   xgr   %1,%2\n"        /* make addr % 4 == 0 */
+             "   sllg  %2,%2,3\n"
+             "   agr   %0,%2\n"        /* add alignement to bitnr */
+#endif
+             "   lghi  %2,63\n"
+             "   nr    %2,%0\n"        /* make shift value */
+             "   xr    %0,%2\n"
+             "   srlg  %0,%0,3\n"
+             "   lghi  %3,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
+             "   sllg  %3,%3,0(%2)\n"  /* make OR mask */
+             "   lg    %0,0(%1)\n"
+             "0: lgr   %2,%0\n"        /* CS loop starts here */
+             "   ogr   %2,%3\n"        /* set bit */
+             "   csg   %0,%2,0(%1)\n"
+             "   jl    0b"
+             : "+a" (nr), "+a" (addr), "=a" (bits), "=d" (mask) :
+             : "cc", "memory" );
+}
+
+/*
+ * SMP save clear_bit routine based on compare and swap (CS)
+ */
+static __inline__ void clear_bit_cs(unsigned long nr, volatile void * addr)
+{
+        unsigned long bits, mask;
+        __asm__ __volatile__(
+#if ALIGN_CS == 1
+             "   lghi  %2,3\n"         /* CS must be aligned on 4 byte b. */
+             "   ngr   %2,%1\n"        /* isolate last 2 bits of address */
+             "   xgr   %1,%2\n"        /* make addr % 4 == 0 */
+             "   sllg  %2,%2,3\n"
+             "   agr   %0,%2\n"        /* add alignement to bitnr */
+#endif
+             "   lghi  %2,63\n"
+             "   nr    %2,%0\n"        /* make shift value */
+             "   xr    %0,%2\n"
+             "   srlg  %0,%0,3\n"
+             "   lghi  %3,-2\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
+             "   lghi  %3,-2\n"
+             "   rllg  %3,%3,0(%2)\n"  /* make AND mask */
+             "   lg    %0,0(%1)\n"
+             "0: lgr   %2,%0\n"        /* CS loop starts here */
+             "   ngr   %2,%3\n"        /* clear bit */
+             "   csg   %0,%2,0(%1)\n"
+             "   jl    0b"
+             : "+a" (nr), "+a" (addr), "=a" (bits), "=d" (mask) :
+             : "cc", "memory" );
+}
+
+/*
+ * SMP save change_bit routine based on compare and swap (CS)
+ */
+static __inline__ void change_bit_cs(unsigned long nr, volatile void * addr)
+{
+        unsigned long bits, mask;
+        __asm__ __volatile__(
+#if ALIGN_CS == 1
+             "   lghi  %2,3\n"         /* CS must be aligned on 4 byte b. */
+             "   ngr   %2,%1\n"        /* isolate last 2 bits of address */
+             "   xgr   %1,%2\n"        /* make addr % 4 == 0 */
+             "   sllg  %2,%2,3\n"
+             "   agr   %0,%2\n"        /* add alignement to bitnr */
+#endif
+             "   lghi  %2,63\n"
+             "   nr    %2,%0\n"        /* make shift value */
+             "   xr    %0,%2\n"
+             "   srlg  %0,%0,3\n"
+             "   lghi  %3,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
+             "   sllg  %3,%3,0(%2)\n"  /* make XR mask */
+             "   lg    %0,0(%1)\n"
+             "0: lgr   %2,%0\n"        /* CS loop starts here */
+             "   xgr   %2,%3\n"        /* change bit */
+             "   csg   %0,%2,0(%1)\n"
+             "   jl    0b"
+             : "+a" (nr), "+a" (addr), "=a" (bits), "=d" (mask) : 
+             : "cc", "memory" );
+}
+
+/*
+ * SMP save test_and_set_bit routine based on compare and swap (CS)
+ */
+static __inline__ int 
+test_and_set_bit_cs(unsigned long nr, volatile void * addr)
+{
+        unsigned long bits, mask;
+        __asm__ __volatile__(
+#if ALIGN_CS == 1
+             "   lghi  %2,3\n"         /* CS must be aligned on 4 byte b. */
+             "   ngr   %2,%1\n"        /* isolate last 2 bits of address */
+             "   xgr   %1,%2\n"        /* make addr % 4 == 0 */
+             "   sllg  %2,%2,3\n"
+             "   agr   %0,%2\n"        /* add alignement to bitnr */
+#endif
+             "   lghi  %2,63\n"
+             "   nr    %2,%0\n"        /* make shift value */
+             "   xr    %0,%2\n"
+             "   srlg  %0,%0,3\n"
+             "   lghi  %3,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
+             "   sllg  %3,%3,0(%2)\n"  /* make OR mask */
+             "   lg    %0,0(%1)\n"
+             "0: lgr   %2,%0\n"        /* CS loop starts here */
+             "   ogr   %2,%3\n"        /* set bit */
+             "   csg   %0,%2,0(%1)\n"
+             "   jl    0b\n"
+             "   ngr   %0,%3\n"        /* isolate old bit */
+             : "+a" (nr), "+a" (addr), "=a" (bits), "=d" (mask) :
+             : "cc", "memory" );
+        return nr != 0;
+}
+
+/*
+ * SMP save test_and_clear_bit routine based on compare and swap (CS)
+ */
+static __inline__ int
+test_and_clear_bit_cs(unsigned long nr, volatile void * addr)
+{
+        unsigned long bits, mask;
+        __asm__ __volatile__(
+#if ALIGN_CS == 1
+             "   lghi  %2,3\n"         /* CS must be aligned on 4 byte b. */
+             "   ngr   %2,%1\n"        /* isolate last 2 bits of address */
+             "   xgr   %1,%2\n"        /* make addr % 4 == 0 */
+             "   sllg  %2,%2,3\n"
+             "   agr   %0,%2\n"        /* add alignement to bitnr */
+#endif
+             "   lghi  %2,63\n"
+             "   nr    %2,%0\n"        /* make shift value */
+             "   xr    %0,%2\n"
+             "   srlg  %0,%0,3\n"
+             "   lghi  %3,-2\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
+             "   rllg  %3,%3,0(%2)\n"  /* make AND mask */
+             "   lg    %0,0(%1)\n"
+             "0: lgr   %2,%0\n"        /* CS loop starts here */
+             "   ngr   %2,%3\n"        /* clear bit */
+             "   csg   %0,%2,0(%1)\n"
+             "   jl    0b\n"
+             "   xgr   %0,%2\n"        /* isolate old bit */
+             : "+a" (nr), "+a" (addr), "=a" (bits), "=d" (mask) :
+             : "cc", "memory" );
+        return nr != 0;
+}
+
+/*
+ * SMP save test_and_change_bit routine based on compare and swap (CS) 
+ */
+static __inline__ int
+test_and_change_bit_cs(unsigned long nr, volatile void * addr)
+{
+        unsigned long bits, mask;
+        __asm__ __volatile__(
+#if ALIGN_CS == 1
+             "   lghi  %2,3\n"         /* CS must be aligned on 4 byte b. */
+             "   ngr   %2,%1\n"        /* isolate last 2 bits of address */
+             "   xgr   %1,%2\n"        /* make addr % 4 == 0 */
+             "   sllg  %2,%2,3\n"
+             "   agr   %0,%2\n"        /* add alignement to bitnr */
+#endif
+             "   lghi  %2,63\n"
+             "   nr    %2,%0\n"        /* make shift value */
+             "   xr    %0,%2\n"
+             "   srlg  %0,%0,3\n"
+             "   lghi  %3,1\n"
+             "   la    %1,0(%0,%1)\n"  /* calc. address for CS */
+             "   sllg  %3,%3,0(%2)\n"  /* make OR mask */
+             "   lg    %0,0(%1)\n"
+             "0: lgr   %2,%0\n"        /* CS loop starts here */
+             "   xgr   %2,%3\n"        /* change bit */
+             "   csg   %0,%2,0(%1)\n"
+             "   jl    0b\n"
+             "   ngr   %0,%3\n"        /* isolate old bit */
+             : "+a" (nr), "+a" (addr), "=a" (bits), "=d" (mask) :
+             : "cc", "memory" );
+        return nr != 0;
+}
+#endif /* CONFIG_SMP */
+
+/*
+ * fast, non-SMP set_bit routine
+ */
+static __inline__ void __set_bit(unsigned long nr, volatile void * addr)
+{
+        __asm__ __volatile__(
+             "   lghi  2,56\n"
+             "   lghi  1,7\n"
+             "   xgr   2,%0\n"
+             "   nr    1,%0\n"
+             "   srlg  2,2,3\n"
+             "   la    2,0(2,%1)\n"
+             "   la    1,0(1,%2)\n"
+             "   oc    0(1,2),0(1)"
+             :  : "a" (nr), "a" (addr), "a" (&_oi_bitmap)
+             : "cc", "memory", "1", "2" );
+}
+
+static __inline__ void 
+__constant_set_bit(const unsigned long nr, volatile void * addr)
+{
+  switch (nr&7) {
+  case 0:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x01"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7))) 
+                          : : "1", "cc", "memory");
+    break;
+  case 1:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x02"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 2:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x04"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 3:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x08"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 4:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x10"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 5:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x20"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 6:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x40"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 7:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "oi 0(1),0x80"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  }
+}
+
+#define set_bit_simple(nr,addr) \
+(__builtin_constant_p((nr)) ? \
+ __constant_set_bit((nr),(addr)) : \
+ __set_bit((nr),(addr)) )
+
+/*
+ * fast, non-SMP clear_bit routine
+ */
+static __inline__ void 
+__clear_bit(unsigned long nr, volatile void * addr)
+{
+        __asm__ __volatile__(
+             "   lghi  2,56\n"
+             "   lghi  1,7\n"
+             "   xgr   2,%0\n"
+             "   nr    1,%0\n"
+             "   srlg  2,2,3\n"
+             "   la    2,0(2,%1)\n"
+             "   la    1,0(1,%2)\n"
+             "   nc    0(1,2),0(1)"
+             :  : "d" (nr), "a" (addr), "a" (&_ni_bitmap)
+             : "cc", "memory", "1", "2" );
+}
+
+static __inline__ void 
+__constant_clear_bit(const unsigned long nr, volatile void * addr)
+{
+  switch (nr&7) {
+  case 0:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xFE"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 1:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xFD"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 2:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xFB"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 3:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xF7"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 4:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xEF"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "cc", "memory" );
+    break;
+  case 5:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xDF"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 6:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0xBF"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 7:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "ni 0(1),0x7F"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  }
+}
+
+#define clear_bit_simple(nr,addr) \
+(__builtin_constant_p((nr)) ? \
+ __constant_clear_bit((nr),(addr)) : \
+ __clear_bit((nr),(addr)) )
+
+/* 
+ * fast, non-SMP change_bit routine 
+ */
+static __inline__ void __change_bit(unsigned long nr, volatile void * addr)
+{
+        __asm__ __volatile__(
+             "   lghi  2,56\n"
+             "   lghi  1,7\n"
+             "   xgr   2,%0\n"
+             "   nr    1,%0\n"
+             "   srlg  2,2,3\n"
+             "   la    2,0(2,%1)\n"
+             "   la    1,0(1,%2)\n"
+             "   xc    0(1,2),0(1)"
+             :  : "d" (nr), "a" (addr), "a" (&_oi_bitmap)
+             : "cc", "memory", "1", "2" );
+}
+
+static __inline__ void 
+__constant_change_bit(const unsigned long nr, volatile void * addr) 
+{
+  switch (nr&7) {
+  case 0:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x01"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "cc", "memory" );
+    break;
+  case 1:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x02"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "cc", "memory" );
+    break;
+  case 2:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x04"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "cc", "memory" );
+    break;
+  case 3:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x08"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "cc", "memory" );
+    break;
+  case 4:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x10"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "cc", "memory" );
+    break;
+  case 5:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x20"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 6:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x40"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  case 7:
+    __asm__ __volatile__ ("la 1,%0\n\t"
+                          "xi 0(1),0x80"
+                          : "=m" (*((volatile char *) addr + ((nr>>3)^7)))
+                          : : "1", "cc", "memory" );
+    break;
+  }
+}
+
+#define change_bit_simple(nr,addr) \
+(__builtin_constant_p((nr)) ? \
+ __constant_change_bit((nr),(addr)) : \
+ __change_bit((nr),(addr)) )
+
+/*
+ * fast, non-SMP test_and_set_bit routine
+ */
+static __inline__ int
+test_and_set_bit_simple(unsigned long nr, volatile void * addr)
+{
+        int oldbit;
+        __asm__ __volatile__(
+             "   lghi  1,56\n"
+             "   lghi  2,7\n"
+             "   xgr   1,%1\n"
+             "   nr    2,%1\n"
+             "   srlg  1,1,3\n"
+             "   la    1,0(1,%2)\n"
+             "   ic    %0,0(1)\n"
+             "   srl   %0,0(2)\n"
+             "   la    2,0(2,%3)\n"
+             "   oc    0(1,1),0(2)"
+             : "=&d" (oldbit) : "d" (nr), "a" (addr), "a" (&_oi_bitmap)
+             : "cc", "memory", "1", "2" );
+        return oldbit & 1;
+}
+
+/*
+ * fast, non-SMP test_and_clear_bit routine
+ */
+static __inline__ int
+test_and_clear_bit_simple(unsigned long nr, volatile void * addr)
+{
+        int oldbit;
+
+        __asm__ __volatile__(
+             "   lghi  1,56\n"
+             "   lghi  2,7\n"
+             "   xgr   1,%1\n"
+             "   nr    2,%1\n"
+             "   srlg  1,1,3\n"
+             "   la    1,0(1,%2)\n"
+             "   ic    %0,0(1)\n"
+             "   srl   %0,0(2)\n"
+             "   la    2,0(2,%3)\n"
+             "   nc    0(1,1),0(2)"
+             : "=&d" (oldbit) : "d" (nr), "a" (addr), "a" (&_ni_bitmap)
+             : "cc", "memory", "1", "2" );
+        return oldbit & 1;
+}
+
+/*
+ * fast, non-SMP test_and_change_bit routine
+ */
+static __inline__ int
+test_and_change_bit_simple(unsigned long nr, volatile void * addr)
+{
+        int oldbit;
+
+        __asm__ __volatile__(
+             "   lghi  1,56\n"
+             "   lghi  2,7\n"
+             "   xgr   1,%1\n"
+             "   nr    2,%1\n"
+             "   srlg  1,1,3\n"
+             "   la    1,0(1,%2)\n"
+             "   ic    %0,0(1)\n"
+             "   srl   %0,0(2)\n"
+             "   la    2,0(2,%3)\n"
+             "   xc    0(1,1),0(2)"
+             : "=&d" (oldbit) : "d" (nr), "a" (addr), "a" (&_oi_bitmap)
+             : "cc", "memory", "1", "2" );
+        return oldbit & 1;
+}
+
+#ifdef CONFIG_SMP
+#define set_bit             set_bit_cs
+#define clear_bit           clear_bit_cs
+#define change_bit          change_bit_cs
+#define test_and_set_bit    test_and_set_bit_cs
+#define test_and_clear_bit  test_and_clear_bit_cs
+#define test_and_change_bit test_and_change_bit_cs
+#else
+#define set_bit             set_bit_simple
+#define clear_bit           clear_bit_simple
+#define change_bit          change_bit_simple
+#define test_and_set_bit    test_and_set_bit_simple
+#define test_and_clear_bit  test_and_clear_bit_simple
+#define test_and_change_bit test_and_change_bit_simple
+#endif
+
+
+/*
+ * This routine doesn't need to be atomic.
+ */
+
+static __inline__ int __test_bit(unsigned long nr, volatile void * addr)
+{
+        int oldbit;
+
+        __asm__ __volatile__(
+             "   lghi  2,56\n"
+             "   lghi  1,7\n"
+             "   xgr   2,%1\n"
+             "   nr    1,%1\n"
+             "   srlg  2,2,3\n"
+             "   ic    %0,0(2,%2)\n"
+             "   srl   %0,0(1)\n"
+             : "=&d" (oldbit) : "d" (nr), "a" (addr)
+             : "cc", "1", "2" );
+        return oldbit & 1;
+}
+
+static __inline__ int 
+__constant_test_bit(unsigned long nr, volatile void * addr) {
+    return (((volatile char *) addr)[(nr>>3)^7] & (1<<(nr&7))) != 0;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p((nr)) ? \
+ __constant_test_bit((nr),(addr)) : \
+ __test_bit((nr),(addr)) )
+
+/*
+ * Find-bit routines..
+ */
+static __inline__ unsigned long
+find_first_zero_bit(void * addr, unsigned long size)
+{
+        unsigned long res;
+
+        if (!size)
+                return 0;
+        __asm__("   lghi  0,-1\n"
+                "   lgr   1,%1\n"
+                "   slgr  %0,%0\n"
+                "   aghi  1,63\n"
+                "   srlg  1,1,6\n"
+                "0: cg    0,0(%0,%2)\n"
+                "   jne   1f\n"
+                "   aghi  %0,8\n"
+                "   brct  1,0b\n"
+                "   lgr   %0,%1\n"
+                "   j     5f\n"
+                "1: lg    1,0(%0,%2)\n"
+                "   sllg  %0,%0,3\n"
+                "   clr   1,0\n"
+		"   jne   2f\n"
+		"   aghi  %0,32\n"
+                "   srlg  1,1,32\n"
+		"2: lghi  0,0xff\n"
+                "   tmll  1,0xffff\n"
+                "   jno   3f\n"
+                "   aghi  %0,16\n"
+                "   srl   1,16\n"
+                "3: tmll  1,0x00ff\n"
+                "   jno   4f\n"
+                "   aghi  %0,8\n"
+                "   srl   1,8\n"
+                "4: ngr   1,0\n"
+                "   ic    1,0(1,%3)\n"
+                "   algr  %0,1\n"
+                "5:"
+                : "=&a" (res) : "a" (size), "a" (addr), "a" (&_zb_findmap)
+                : "cc", "0", "1" );
+        return (res < size) ? res : size;
+}
+
+static __inline__ unsigned long
+find_next_zero_bit (void * addr, unsigned long size, unsigned long offset)
+{
+        unsigned long * p = ((unsigned long *) addr) + (offset >> 6);
+        unsigned long bitvec;
+        unsigned long set, bit = offset & 63, res;
+
+        if (bit) {
+                /*
+                 * Look for zero in first word
+                 */
+                bitvec = (*p) >> bit;
+                __asm__("   lhi  0,-1\n"
+                        "   lgr  1,%1\n"
+                        "   slgr %0,%0\n"
+                        "   clr  1,0\n"
+                        "   jne  0f\n"
+                        "   aghi %0,32\n"
+                        "   srlg 1,1,32\n"
+			"0: lghi 0,0xff\n"
+                        "   tmll 1,0xffff\n"
+                        "   jno  1f\n"
+                        "   aghi %0,16\n"
+                        "   srlg 1,1,16\n"
+                        "1: tmll 1,0x00ff\n"
+                        "   jno  2f\n"
+                        "   aghi %0,8\n"
+                        "   srlg 1,1,8\n"
+                        "2: ngr  1,0\n"
+                        "   ic   1,0(1,%2)\n"
+                        "   algr %0,1"
+                        : "=&d" (set) 
+                        : "d" (bitvec), "a" (&_zb_findmap)
+                        : "cc", "0", "1" );
+                if (set < (64 - bit))
+                        return set + offset;
+                offset += 64 - bit;
+                p++;
+        }
+        /*
+         * No zero yet, search remaining full words for a zero
+         */
+        res = find_first_zero_bit (p, size - 64 * (p - (unsigned long *) addr));
+        return (offset + res);
+}
+
+/*
+ * ffz = Find First Zero in word. Undefined if no zero exists,
+ * so code should check against ~0UL first..
+ */
+static __inline__ unsigned long ffz(unsigned long word)
+{
+        int result;
+
+        __asm__("   lhi  0,-1\n"
+                "   lgr  1,%1\n"
+                "   slgr %0,%0\n"
+                "   clr  1,0\n"
+                "   jne  0f\n"
+                "   aghi %0,32\n"
+                "   srlg 1,1,32\n"
+                "0: lghi 0,0xff\n"
+                "   tmll 1,0xffff\n"
+                "   jno  1f\n"
+                "   aghi %0,16\n"
+                "   srlg 1,1,16\n"
+                "1: tmll 1,0x00ff\n"
+                "   jno  2f\n"
+                "   aghi %0,8\n"
+                "   srlg 1,1,8\n"
+                "2: ngr  1,0\n"
+                "   ic   1,0(1,%2)\n"
+                "   algr %0,1"
+                : "=&d" (result)
+                : "d" (word), "a" (&_zb_findmap)
+                : "cc", "0", "1" );
+
+        return result;
+}
+
+/*
+ * ffs: find first bit set. This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+
+extern int __inline__ ffs (int x)
+{
+        int r;
+
+        if (x == 0)
+          return 0;
+        __asm__("    lr   1,%1\n"
+                "    slr  %0,%0\n"
+                "    tml  1,0xFFFF\n"
+                "    jnz  0f\n"
+                "    ahi  %0,16\n"
+                "    srl  1,16\n"
+                "0:  tml  1,0x00FF\n"
+                "    jnz  1f\n"
+                "    ahi  %0,8\n"
+                "    srl  1,8\n"
+                "1:  tml  1,0x000F\n"
+                "    jnz  2f\n"
+                "    ahi  %0,4\n"
+                "    srl  1,4\n"
+                "2:  tml  1,0x0003\n"
+                "    jnz  3f\n"
+                "    ahi  %0,2\n"
+                "    srl  1,2\n"
+                "3:  tml  1,0x0001\n"
+                "    jnz  4f\n"
+                "    ahi  %0,1\n"
+                "4:"
+                : "=&d" (r) : "d" (x) : "cc", "1" );
+        return r+1;
+}
+
+/*
+ * hweightN: returns the hamming weight (i.e. the number
+ * of bits set) of a N-bit word
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+
+#ifdef __KERNEL__
+
+/*
+ * ATTENTION: intel byte ordering convention for ext2 and minix !!
+ * bit 0 is the LSB of addr; bit 31 is the MSB of addr;
+ * bit 32 is the LSB of (addr+4).
+ * That combined with the little endian byte order of Intel gives the
+ * following bit order in memory:
+ *    07 06 05 04 03 02 01 00 15 14 13 12 11 10 09 08 \
+ *    23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
+ */
+
+#define ext2_set_bit(nr, addr)       test_and_set_bit((nr)^56, addr)
+#define ext2_clear_bit(nr, addr)     test_and_clear_bit((nr)^56, addr)
+#define ext2_test_bit(nr, addr)      test_bit((nr)^56, addr)
+static __inline__ unsigned long
+ext2_find_first_zero_bit(void *vaddr, unsigned long size)
+{
+        unsigned long res;
+
+        if (!size)
+                return 0;
+        __asm__("   lghi  0,-1\n"
+                "   lgr   1,%1\n"
+                "   aghi  1,63\n"
+                "   srlg  1,1,6\n"
+                "   slgr  %0,%0\n"
+                "0: clg   0,0(%0,%2)\n"
+                "   jne   1f\n"
+                "   aghi  %0,8\n"
+                "   brct  1,0b\n"
+                "   lgr   %0,%1\n"
+                "   j     5f\n"
+                "1: cl    0,0(%0,%2)\n"
+		"   jne   2f\n"
+		"   aghi  %0,4\n"
+		"2: l     1,0(%0,%2)\n"
+                "   sllg  %0,%0,3\n"
+                "   aghi  %0,24\n"
+                "   lghi  0,0xff\n"
+                "   tmlh  1,0xffff\n"
+                "   jo    3f\n"
+                "   aghi  %0,-16\n"
+                "   srl   1,16\n"
+                "3: tmll  1,0xff00\n"
+                "   jo    4f\n"
+                "   aghi  %0,-8\n"
+                "   srl   1,8\n"
+                "4: ngr   1,0\n"
+                "   ic    1,0(1,%3)\n"
+                "   algr  %0,1\n"
+                "5:"
+                : "=&a" (res) : "a" (size), "a" (vaddr), "a" (&_zb_findmap)
+                : "cc", "0", "1" );
+        return (res < size) ? res : size;
+}
+
+static __inline__ unsigned long
+ext2_find_next_zero_bit(void *vaddr, unsigned long size, unsigned long offset)
+{
+        unsigned long *addr = vaddr;
+        unsigned long *p = addr + (offset >> 6);
+        unsigned long word;
+        unsigned long bit = offset & 63UL, res;
+
+        if (offset >= size)
+                return size;
+
+        if (bit) {
+                __asm__("   lrvg %0,%1" /* load reversed, neat instruction */
+                        : "=a" (word) : "m" (*p) );
+                word >>= bit;
+                res = bit;
+                /* Look for zero in first 8 byte word */
+                __asm__("   lgr  1,%1\n"
+                        "   lghi 0,0xff\n"
+			"   tmll 1,0xffff\n"
+			"   jno  2f\n"
+			"   ahi  %0,16\n"
+			"   srlg 1,1,16\n"
+                	"0: tmll 1,0xffff\n"
+                        "   jno  2f\n"
+                        "   ahi  %0,16\n"
+                        "   srlg 1,1,16\n"
+                        "1: tmll 1,0xffff\n"
+                        "   jno  2f\n"
+                        "   ahi  %0,16\n"
+                        "   srl  1,16\n"
+                        "2: tmll 1,0x00ff\n"
+                	"   jno  3f\n"
+                	"   ahi  %0,8\n"
+                	"   srl  1,8\n"
+                	"3: ngr  1,0\n"
+                	"   ic   1,0(1,%2)\n"
+                	"   alr  %0,1"
+                	: "+&d" (res) 
+                  	: "d" (word), "a" (&_zb_findmap)
+                	: "cc", "0", "1" );
+                if (res < 64)
+			return (p - addr)*64 + res;
+                p++;
+        }
+        /* No zero yet, search remaining full bytes for a zero */
+        res = ext2_find_first_zero_bit (p, size - 64 * (p - addr));
+        return (p - addr) * 64 + res;
+}
+
+/* Bitmap functions for the minix filesystem.  */
+/* FIXME !!! */
+#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _S390_BITOPS_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/bugs.h linux/include/asm-s390x/bugs.h
--- v2.4.1/linux/include/asm-s390x/bugs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/bugs.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,22 @@
+/*
+ *  include/asm-s390/bugs.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/bugs.h"
+ *    Copyright (C) 1994  Linus Torvalds
+ */
+
+/*
+ * This is included by init/main.c to check for architecture-dependent bugs.
+ *
+ * Needs:
+ *      void check_bugs(void);
+ */
+
+static void __init check_bugs(void)
+{
+  /* s390 has no bugs ... */
+}
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/byteorder.h linux/include/asm-s390x/byteorder.h
--- v2.4.1/linux/include/asm-s390x/byteorder.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/byteorder.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,113 @@
+#ifndef _S390_BYTEORDER_H
+#define _S390_BYTEORDER_H
+
+/*
+ *  include/asm-s390/byteorder.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+static __inline__ __const__ __u64 ___arch__swab64(__u64 x)
+{
+  __u64 result;
+
+  __asm__ __volatile__ (
+          "   lrvg %0,%1"
+          : "=&d" (result) : "m" (x) );
+  return result;
+}
+
+static __inline__ __const__ __u64 ___arch__swab64p(__u64 *x)
+{
+  __u64 result;
+
+  __asm__ __volatile__ (
+          "   lrvg %0,%1"
+          : "=d" (result) : "m" (*x) );
+  return result;
+}
+
+static __inline__ void ___arch__swab64s(__u64 *x)
+{
+  __asm__ __volatile__ (
+          "   lrvg %0,%1\n"
+	  "   stg  %0,%1"
+          : : "m" (*x) : "memory");
+}
+
+static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
+{
+  __u32 result;
+
+  __asm__ __volatile__ (
+          "   lrv  %0,%1"
+          : "=&d" (result) : "m" (x) );
+  return result;
+}
+
+static __inline__ __const__ __u32 ___arch__swab32p(__u32 *x)
+{
+  __u32 result;
+
+  __asm__ __volatile__ (
+          "   lrv  %0,%1"
+          : "=d" (result) : "m" (*x) );
+  return result;
+}
+
+static __inline__ void ___arch__swab32s(__u32 *x)
+{
+  __asm__ __volatile__ (
+          "   lrv  %0,%1\n"
+	  "   st   %0,%1"
+          : : "m" (*x) : "memory");
+}
+
+static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
+{
+  __u16 result;
+
+  __asm__ __volatile__ (
+          "   lrvh %0,%1"
+          : "=d" (result) : "m" (x) );
+  return result;
+}
+
+static __inline__ __const__ __u16 ___arch__swab16p(__u16 *x)
+{
+  __u16 result;
+
+  __asm__ __volatile__ (
+          "   lrvh %0,%1"
+          : "=d" (result) : "m" (*x) );
+  return result;
+}
+
+static __inline__ void ___arch__swab16s(__u16 *x)
+{
+  __asm__ __volatile__ (
+          "   lrvh %0,%1\n"
+	  "   sth  %0,%1"
+          : : "m" (*x) : "memory");
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+#define __arch__swab32p(x) ___arch__swab32p(x)
+#define __arch__swab16p(x) ___arch__swab16p(x)
+#define __arch__swab32s(x) ___arch__swab32s(x)
+#define __arch__swab16s(x) ___arch__swab16s(x)
+
+#define __BYTEORDER_HAS_U64__
+
+#endif /* __GNUC__ */
+
+#include <linux/byteorder/big_endian.h>
+
+#endif /* _S390_BYTEORDER_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/cache.h linux/include/asm-s390x/cache.h
--- v2.4.1/linux/include/asm-s390x/cache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/cache.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,16 @@
+/*
+ *  include/asm-s390/cache.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ *  Derived from "include/asm-i386/cache.h"
+ *    Copyright (C) 1992, Linus Torvalds
+ */
+
+#ifndef __ARCH_S390_CACHE_H
+#define __ARCH_S390_CACHE_H
+
+#define L1_CACHE_BYTES     16
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ccwcache.h linux/include/asm-s390x/ccwcache.h
--- v2.4.1/linux/include/asm-s390x/ccwcache.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ccwcache.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,84 @@
+/* 
+   * File...........: linux/include/asm-s390/ccwcache.h
+   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+   * Bugreports.to..: <Linux390@de.ibm.com>
+   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000
+ */
+#ifndef CCWCACHE_H
+#define CCWCACHE_H
+#include <linux/slab.h>
+#include <asm/irq.h>
+
+#ifndef __KERNEL__
+#define kmem_cache_t void
+#endif /* __KERNEL__ */
+
+typedef struct ccw_req_t {
+	/* eye catcher plus queueing information  */
+	unsigned int magic;	
+	struct ccw_req_t *next;	/* pointer to next ccw_req_t in queue */
+	struct ccw_req_t *int_next;	/* for internal queueing */
+	struct ccw_req_t *int_prev;	/* for internal queueing */
+
+	/* Where to execute what... */
+	void *device;		/* index of the device the req is for */
+	void *req;		/* pointer to originating request */
+	ccw1_t *cpaddr;		/* address of channel program */
+	char status;	        /* reflecting the status of this request */
+	char flags;              /* see below */
+	short retries;		/* A retry counter to be set when filling */
+
+	/* ... and how */
+	int options;		/* options for execution */
+	char lpm;               /* logical path mask                      */
+	void *data;		/* pointer to data area */
+	devstat_t *dstat;	/* The device status in case of an error */
+
+	/* these are important for recovering erroneous requests          */
+	struct ccw_req_t *refers;	/* Does this request refer to another one? */
+	void *function; /* refers to the originating ERP action */ ;
+
+	unsigned long long expires;	/* expiratioj period */
+	/* these are for profiling purposes */
+	unsigned long long buildclk;	/* TOD-clock of request generation */
+	unsigned long long startclk;	/* TOD-clock of request start */
+	unsigned long long stopclk;	/* TOD-clock of request interrupt */
+	unsigned long long endclk;	/* TOD-clock of request termination */
+
+	/* these are for internal use */
+	int cplength;		/* length of the channel program in CCWs */
+	int datasize;		/* amount of additional data in bytes */
+	kmem_cache_t *cache;	/* the cache this data comes from */
+
+} __attribute__ ((aligned(4))) ccw_req_t;
+
+/* 
+ * ccw_req_t -> status can be:
+ */
+#define CQR_STATUS_EMPTY    0x00	/* request is empty */
+#define CQR_STATUS_FILLED   0x01	/* request is ready to be preocessed */
+#define CQR_STATUS_QUEUED   0x02	/* request is queued to be processed */
+#define CQR_STATUS_IN_IO    0x03	/* request is currently in IO */
+#define CQR_STATUS_DONE     0x04	/* request is completed sucessfully */
+#define CQR_STATUS_ERROR    0x05	/* request is completed with error */
+#define CQR_STATUS_FAILED   0x06	/* request is finally failed */
+
+#define CQR_FLAGS_CHAINED  0x01	/* request is chained by another (last CCW is TIC) */
+
+#ifdef __KERNEL__
+#define SMALLEST_SLAB (sizeof(struct ccw_req_t) <= 128 ? 128 :\
+ sizeof(struct ccw_req_t) <= 256 ? 256 : 512 )
+
+/* SMALLEST_SLAB(1),... PAGE_SIZE(CCW_NUMBER_CACHES) */
+#define CCW_NUMBER_CACHES (sizeof(struct ccw_req_t) <= 128 ? 6 :\
+ sizeof(struct ccw_req_t) <= 256 ? 5 : 4 )
+
+int ccwcache_init (void);
+
+ccw_req_t *ccw_alloc_request (char *magic, int cplength, int additional_data);
+void ccw_free_request (ccw_req_t * request);
+#endif /* __KERNEL__ */
+#endif				/* CCWCACHE_H */
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/chandev.h linux/include/asm-s390x/chandev.h
--- v2.4.1/linux/include/asm-s390x/chandev.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/chandev.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,151 @@
+/*
+ *  include/asm-s390/chandev.h
+ *
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ * 
+ *  Generic channel device initialisation support. 
+ */
+#include <linux/version.h>
+#include <asm/types.h>
+#include <linux/netdevice.h>
+
+/* chandev_type is a bitmask for registering & describing device types. */
+typedef enum
+{
+	none=0x0,
+	ctc=0x1,
+	escon=0x2,
+	lcs=0x4,
+	osad=0x8,
+	qeth=0x10,
+	claw=0x20,
+} chandev_type;
+
+typedef enum
+{
+	no_category,
+	network_device,
+	serial_device,
+} chandev_category;
+
+/*
+ * The chandev_probeinfo structure is passed to the device driver with configuration
+ * info for which irq's & ports to use when attempting to probe the device.
+ */
+typedef struct
+{
+        int     read_irq;
+	int     write_irq;
+	u16     read_devno;
+	u16     write_devno;
+        s16     port_protocol_no; /* -1 don't care */
+	u8      hint_port_no;   /* lcs specific */
+	u8      max_port_no;    /* lcs specific */
+	chandev_type chan_type;
+	u8      checksum_received_ip_pkts;
+	u8      use_hw_stats; /* where available e.g. lcs */
+	u16     cu_type;      /* control unit type */
+	u8      cu_model;     /* control unit model */
+	u16     dev_type;     /* device type */
+	u8      dev_model;    /* device model */
+	char    *parmstr;       /* driver specific parameters added by add_parms keyword */
+	/* newdevice used internally by chandev.c */
+	struct  chandev_activelist *newdevice; 
+	s32     devif_num; 
+/* devif_num=-1 implies don't care,0 implies tr0, info used by chandev_initnetdevice */
+} chandev_probeinfo;
+
+/*
+ * This is a wrapper to the machine check handler & should be used
+ * instead of reqest_irq or s390_request_irq_special for anything
+ * using the channel device layer.
+ */
+int chandev_request_irq(unsigned int   irq,
+                      void           (*handler)(int, void *, struct pt_regs *),
+                      unsigned long  irqflags,
+                      const char    *devname,
+                      void          *dev_id);
+
+typedef enum
+{
+	good=0,
+	not_oper,
+	first_msck=not_oper,
+	no_path,
+	revalidate,
+	gone,
+	last_msck,
+} chandev_msck_status;
+
+typedef int (*chandev_probefunc)(chandev_probeinfo *probeinfo);
+typedef void (*chandev_shutdownfunc)(void *device);
+typedef void (*chandev_unregfunc)(void *device);
+typedef void (*chandev_reoperfunc)(void *device,int msck_for_read_chan,chandev_msck_status prevstatus);
+
+
+
+/* A driver should call chandev_register_and_probe when ready to be probed,
+ * after registeration the drivers probefunction will be called asynchronously
+ * when more devices become available at normal task time.
+ * The shutdownfunc parameter is used so that the channel layer
+ * can request a driver to close unregister itself & release its interrupts.
+ * repoper func is used when a device becomes operational again after being temporarily
+ * not operational the previous status is sent in the prevstatus variable.
+ * This can be used in cases when the default handling isn't quite adequete
+ * e.g. if a ssch is needed to reinitialize long running channel programs.
+ */
+int chandev_register_and_probe(chandev_probefunc probefunc,
+			       chandev_shutdownfunc shutdownfunc,
+			       chandev_reoperfunc reoperfunc,
+			       chandev_type chan_type);
+
+/* The chandev_unregister function is typically called when a module is being removed 
+ * from the system. The shutdown parameter if TRUE calls shutdownfunc for each 
+ * device instance so the driver writer doesn't have to.
+ */
+void chandev_unregister(chandev_probefunc probefunc,int call_shutdown);
+
+/* chandev_initdevice should be called immeadiately before returning after */
+/* a successful probe. */
+int chandev_initdevice(chandev_probeinfo *probeinfo,void *dev_ptr,u8 port_no,char *devname,
+chandev_category category,chandev_unregfunc unreg_dev);
+
+/* chandev_initnetdevice registers a network device with the channel layer. 
+ * It returns the device structure if successful,if dev=NULL it kmallocs it, 
+ * On device initialisation failure it will kfree it under ALL curcumstances
+ * i.e. if dev is not NULL on entering this routine it MUST be malloced with kmalloc. 
+ * The base name is tr ( e.g. tr0 without the 0 ), for token ring eth for ethernet,
+ *  ctc or escon for ctc device drivers.
+ * If valid function pointers are given they will be called to setup,
+ * register & unregister the device. 
+ * An example of setup is eth_setup in drivers/net/net_init.c.
+ * An example of init_dev is init_trdev(struct net_device *dev)
+ * & an example of unregister is unregister_trdev, 
+ * unregister_netdev should be used for escon & ctc
+ * as there is no network unregister_ctcdev in the kernel.
+*/
+
+#if LINUX_VERSION_CODE>=KERNEL_VERSION(2,3,0)
+struct net_device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+					 struct net_device *dev,int sizeof_priv, 
+					 char *basename, 
+					 struct net_device *(*init_netdevfunc)
+					 (struct net_device *dev, int sizeof_priv),
+					 void (*unreg_netdevfunc)(struct net_device *dev));
+#else
+struct device *chandev_initnetdevice(chandev_probeinfo *probeinfo,u8 port_no,
+				     struct device *dev,int sizeof_priv,
+				     char *basename, 
+				     struct device *(*init_netdevfunc)
+				     (struct device *dev, int sizeof_priv),
+				     void (*unreg_netdevfunc)(struct device *dev));
+#endif
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/checksum.h linux/include/asm-s390x/checksum.h
--- v2.4.1/linux/include/asm-s390x/checksum.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/checksum.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,188 @@
+#ifndef _S390_CHECKSUM_H
+#define _S390_CHECKSUM_H
+
+/*
+ *  include/asm-s390/checksum.h
+ *    S390 fast network checksum routines
+ *    see also arch/S390/lib/checksum.c
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ulrich Hild        (first version)
+ *               Martin Schwidefsky (heavily optimized CKSM version)
+ *               D.J. Barrow        (third attempt) 
+ */
+
+#include <asm/uaccess.h>
+
+/*
+ * computes the checksum of a memory block at buff, length len,
+ * and adds in "sum" (32-bit)
+ *
+ * returns a 32-bit number suitable for feeding into itself
+ * or csum_tcpudp_magic
+ *
+ * this function must be called with even lengths, except
+ * for the last fragment, which may be odd
+ *
+ * it's best to have buff aligned on a 32-bit boundary
+ */
+unsigned int
+csum_partial(const unsigned char * buff, int len, unsigned int sum);
+
+/*
+ * csum_partial as an inline function
+ */
+extern inline unsigned int 
+csum_partial_inline(const unsigned char * buff, int len, unsigned int sum)
+{
+	__asm__ __volatile__ (
+		"    lgr  2,%1\n"    /* address in gpr 2 */
+		"    lgfr 3,%2\n"    /* length in gpr 3 */
+		"0:  cksm %0,2\n"    /* do checksum on longs */
+		"    jo   0b\n"
+                : "+&d" (sum)
+		: "d" (buff), "d" (len)
+                : "cc", "2", "3" );
+	return sum;
+}
+
+/*
+ * the same as csum_partial, but copies from src while it
+ * checksums
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern inline unsigned int 
+csum_partial_copy(const char *src, char *dst, int len,unsigned int sum)
+{
+	memcpy(dst,src,len);
+        return csum_partial_inline(dst, len, sum);
+}
+
+/*
+ * the same as csum_partial_copy, but copies from user space.
+ *
+ * here even more important to align src and dst on a 32-bit (or even
+ * better 64-bit) boundary
+ */
+
+extern inline unsigned int 
+csum_partial_copy_from_user(const char *src, char *dst,
+                            int len, unsigned int sum, int *errp)
+{
+	if (copy_from_user(dst, src, len)) {
+		*errp = -EFAULT;
+		memset(dst, 0, len);
+		return sum;
+        }
+        return csum_partial_inline(dst, len, sum);
+}
+
+extern inline unsigned int
+csum_partial_copy_nocheck (const char *src, char *dst, int len, unsigned int sum)
+{
+        memcpy(dst,src,len);
+        return csum_partial_inline(dst, len, sum);
+}
+
+/*
+ *      Fold a partial checksum without adding pseudo headers
+ */
+extern inline unsigned short
+csum_fold(unsigned int sum)
+{
+	__asm__ __volatile__ (
+		"    sr   3,3\n"   /* %0 = H*65536 + L */
+		"    lr   2,%0\n"  /* %0 = H L, R2/R3 = H L / 0 0 */
+		"    srdl 2,16\n"  /* %0 = H L, R2/R3 = 0 H / L 0 */
+		"    alr  2,3\n"   /* %0 = H L, R2/R3 = L H / L 0 */
+		"    alr  %0,2\n"  /* %0 = H+L+C L+H */
+                "    srl  %0,16\n" /* %0 = H+L+C */
+		: "+&d" (sum) : : "cc", "2", "3");
+	return ((unsigned short) ~sum);
+}
+
+/*
+ *	This is a version of ip_compute_csum() optimized for IP headers,
+ *	which always checksum on 4 octet boundaries.
+ *
+ */
+extern inline unsigned short
+ip_fast_csum(unsigned char *iph, unsigned int ihl)
+{
+	unsigned long sum;
+
+        __asm__ __volatile__ (
+		"    slgr %0,%0\n"   /* set sum to zero */
+                "    lgr  2,%1\n"    /* address in gpr 2 */
+                "    lgfr 3,%2\n"    /* length in gpr 3 */
+                "0:  cksm %0,2\n"    /* do checksum on ints */
+                "    jo   0b\n"
+                : "=&d" (sum)
+                : "d" (iph), "d" (ihl*4)
+                : "cc", "2", "3" );
+        return csum_fold(sum);
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 32-bit checksum
+ */
+extern inline unsigned int 
+csum_tcpudp_nofold(unsigned long saddr, unsigned long daddr,
+                   unsigned short len, unsigned short proto,
+                   unsigned int sum)
+{
+	__asm__ __volatile__ (
+                "    lgfr  %0,%0\n"
+                "    algr  %0,%1\n"  /* sum += saddr */
+                "    brc   12,0f\n"
+		"    aghi  %0,1\n"   /* add carry */
+		"0:  algr  %0,%2\n"  /* sum += daddr */
+                "    brc   12,1f\n"
+                "    aghi  %0,1\n"   /* add carry */
+		"1:  algfr %0,%3\n"  /* sum += (len<<16) + proto */
+		"    brc   12,2f\n"
+		"    aghi  %0,1\n"   /* add carry */
+		"2:  srlg  0,%0,32\n"
+                "    alr   %0,0\n"   /* fold to 32 bits */
+                "    brc   12,3f\n"
+                "    ahi   %0,1\n"   /* add carry */
+                "3:  llgfr %0,%0"
+		: "+&d" (sum)
+		: "d" (saddr), "d" (daddr),
+		  "d" (((unsigned int) len<<16) + (unsigned int) proto)
+		: "cc", "0" );
+	return sum;
+}
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+
+extern inline unsigned short int
+csum_tcpudp_magic(unsigned long saddr, unsigned long daddr,
+                  unsigned short len, unsigned short proto,
+                  unsigned int sum)
+{
+	return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum));
+}
+
+/*
+ * this routine is used for miscellaneous IP-like checksums, mainly
+ * in icmp.c
+ */
+
+extern inline unsigned short
+ip_compute_csum(unsigned char * buff, int len)
+{
+	return csum_fold(csum_partial_inline(buff, len, 0));
+}
+
+#endif /* _S390_CHECKSUM_H */
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/current.h linux/include/asm-s390x/current.h
--- v2.4.1/linux/include/asm-s390x/current.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/current.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,31 @@
+/*
+ *  include/asm-s390/current.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/current.h"
+ */
+
+#ifndef _S390_CURRENT_H
+#define _S390_CURRENT_H
+
+#ifdef __KERNEL__
+
+struct task_struct;
+
+static inline struct task_struct * get_current(void)
+{
+        struct task_struct *current;
+        __asm__("lghi  %0,-16384\n\t"
+                "ngr   %0,15"
+                : "=&r" (current) );
+        return current;
+ }
+
+#define current get_current()
+
+#endif
+
+#endif /* !(_S390_CURRENT_H) */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/dasd.h linux/include/asm-s390x/dasd.h
--- v2.4.1/linux/include/asm-s390x/dasd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/dasd.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,339 @@
+/* 
+ * File...........: linux/drivers/s390/block/dasd.c
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ */
+
+#ifndef DASD_H
+#define DASD_H
+
+#include <linux/ioctl.h>
+#include <asm/irq.h>
+
+#define IOCTL_LETTER 'D'
+/* Disable the volume (for Linux) */
+#define BIODASDDISABLE _IO(IOCTL_LETTER,0) 
+/* Enable the volume (for Linux) */
+#define BIODASDENABLE  _IO(IOCTL_LETTER,1) 
+/* Issue a reserve/release command, rsp. */
+#define BIODASDRSRV    _IO(IOCTL_LETTER,2) /* reserve */
+#define BIODASDRLSE    _IO(IOCTL_LETTER,3) /* release */
+#define BIODASDSLCK    _IO(IOCTL_LETTER,4) /* steal lock */
+/* Read sense ID infpormation */
+#define BIODASDRSID    _IOR(IOCTL_LETTER,0,senseid_t)
+/* Format the volume or an extent */
+#define BIODASDFORMAT  _IOW(IOCTL_LETTER,0,format_data_t) 
+/* translate blocknumber of partition to absolute */
+#define BIODASDRWTB    _IOWR(IOCTL_LETTER,0,int)
+
+#define DASD_NAME "dasd"
+#define DASD_PARTN_BITS 2
+#define DASD_PER_MAJOR ( 1U<<(MINORBITS-DASD_PARTN_BITS))
+
+/* 
+ * struct format_data_t
+ * represents all data necessary to format a dasd
+ */
+typedef struct format_data_t {
+	int start_unit; /* from track */
+	int stop_unit;  /* to track */
+	int blksize;    /* sectorsize */
+        int intensity;  /* 0: normal, 1:record zero, 3:home address, 4 invalidate tracks */
+} __attribute__ ((packed)) format_data_t;
+
+#define DASD_FORMAT_DEFAULT_START_UNIT 0
+#define DASD_FORMAT_DEFAULT_STOP_UNIT -1
+#define DASD_FORMAT_DEFAULT_BLOCKSIZE -1
+#define DASD_FORMAT_DEFAULT_INTENSITY -1
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#include <linux/major.h>
+#include <linux/wait.h>
+#include <asm/ccwcache.h>
+#include <linux/blk.h> 
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+#include <linux/blkdev.h> 
+#include <linux/devfs_fs_kernel.h>
+#endif
+#include <linux/genhd.h>
+#include <linux/hdreg.h>
+#include <linux/compatmac.h>
+
+#include <asm/s390dyn.h>
+#include <asm/todclk.h>
+#include <asm/debug.h>
+
+/* Kernel Version Compatibility section */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,98))
+typedef struct request *request_queue_t;
+#define block_device_operations file_operations
+#define __setup(x,y) struct dasd_device_t
+#define devfs_register_blkdev(major,name,ops) register_blkdev(major,name,ops)
+#define register_disk(dd,dev,partn,ops,size) \
+do { \
+	dd->sizes[MINOR(dev)] = size >> 1; \
+	resetup_one_dev(dd,MINOR(dev)>>DASD_PARTN_BITS); \
+} while(0)
+#define init_waitqueue_head(x) do { *x = NULL; } while(0)
+#define blk_cleanup_queue(x) do {} while(0)
+#define blk_init_queue(x...) do {} while(0)
+#define blk_queue_headactive(x...) do {} while(0)
+#define blk_queue_make_request(x) do {} while(0)
+#define list_empty(x) (0)
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+        blk_dev[d_major].request_fn = d_request_fn; \
+        blk_dev[d_major].queue = d_queue_fn; \
+        blk_dev[d_major].current_request = d_current; \
+} while(0)
+#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
+	major:D_MAJOR, \
+	major_name:D_NAME, \
+	minor_shift:D_PARTN_BITS, \
+	max_p:1 << D_PARTN_BITS, \
+	max_nr:D_PER_MAJOR, \
+	nr_real:D_PER_MAJOR,
+static inline struct request * 
+dasd_next_request( request_queue_t *queue ) 
+{
+    return *queue;
+}
+static inline void 
+dasd_dequeue_request( request_queue_t * q, struct request *req )
+{
+        *q = req->next;
+        req->next = NULL;
+}
+#else
+#define INIT_BLK_DEV(d_major,d_request_fn,d_queue_fn,d_current) \
+do { \
+        blk_dev[d_major].queue = d_queue_fn; \
+} while(0)
+#define INIT_GENDISK(D_MAJOR,D_NAME,D_PARTN_BITS,D_PER_MAJOR) \
+	major:D_MAJOR, \
+	major_name:D_NAME, \
+	minor_shift:D_PARTN_BITS, \
+	max_p:1 << D_PARTN_BITS, \
+	nr_real:D_PER_MAJOR,
+static inline struct request * 
+dasd_next_request( request_queue_t *queue ) 
+{
+        return blkdev_entry_next_request(&queue->queue_head);
+}
+static inline void 
+dasd_dequeue_request( request_queue_t * q, struct request *req )
+{
+        blkdev_dequeue_request (req);
+}
+#endif
+
+/* dasd_range_t are used for dynamic device att-/detachment */
+typedef struct dasd_devreg_t {
+        devreg_t devreg; /* the devreg itself */
+        /* build a linked list of devregs, needed for cleanup */
+        struct dasd_devreg_t *next;
+} dasd_devreg_t;
+
+typedef enum {
+	dasd_era_fatal = -1,	/* no chance to recover              */
+	dasd_era_none = 0,	/* don't recover, everything alright */
+	dasd_era_msg = 1,	/* don't recover, just report...     */
+	dasd_era_recover = 2	/* recovery action recommended       */
+} dasd_era_t;
+
+/* BIT DEFINITIONS FOR SENSE DATA */
+#define DASD_SENSE_BIT_0 0x80
+#define DASD_SENSE_BIT_1 0x40
+#define DASD_SENSE_BIT_2 0x20
+#define DASD_SENSE_BIT_3 0x10
+
+#define check_then_set(where,from,to) \
+do { \
+        if ((*(where)) != (from) ) { \
+                printk (KERN_ERR PRINTK_HEADER "was %d\n", *(where)); \
+                BUG(); \
+        } \
+        (*(where)) = (to); \
+} while (0)
+
+#define DASD_MESSAGE(d_loglevel,d_device,d_string,d_args...)\
+do { \
+        int d_devno = d_device->devinfo.devno; \
+        int d_irq = d_device->devinfo.irq; \
+        char *d_name = d_device->name; \
+        int d_major = MAJOR(d_device->kdev); \
+        int d_minor = MINOR(d_device->kdev); \
+        printk(d_loglevel PRINTK_HEADER \
+               "/dev/%s(%d:%d), 0x%04X on SCH 0x%x:" \
+               d_string "\n",d_name,d_major,d_minor,d_devno,d_irq,d_args ); \
+} while(0)
+
+/* 
+ * struct dasd_sizes_t
+ * represents all data needed to access dasd with properly set up sectors
+ */
+typedef
+struct dasd_sizes_t {
+	unsigned long blocks; /* size of volume in blocks */
+	unsigned int bp_block; /* bytes per block */
+	unsigned int s2b_shift; /* log2 (bp_block/512) */
+} dasd_sizes_t;
+
+/* 
+ * struct dasd_chanq_t 
+ * represents a queue of channel programs related to a single device
+ */
+typedef
+struct dasd_chanq_t {
+	ccw_req_t *head;
+	ccw_req_t *tail;
+} dasd_chanq_t;
+
+struct dasd_device_t;
+struct request;
+
+/* 
+ * signatures for the functions of dasd_discipline_t 
+ * make typecasts much easier
+ */
+typedef ccw_req_t *(*dasd_erp_action_fn_t) (ccw_req_t * cqr);
+typedef ccw_req_t *(*dasd_erp_postaction_fn_t) (ccw_req_t * cqr);
+
+typedef int (*dasd_ck_id_fn_t) (dev_info_t *);
+typedef int (*dasd_ck_characteristics_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_fill_geometry_fn_t) (struct dasd_device_t *, struct hd_geometry *);
+typedef ccw_req_t *(*dasd_format_fn_t) (struct dasd_device_t *, struct format_data_t *);
+typedef ccw_req_t *(*dasd_init_analysis_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_do_analysis_fn_t) (struct dasd_device_t *);
+typedef int (*dasd_io_starter_fn_t) (ccw_req_t *);
+typedef void (*dasd_int_handler_fn_t)(int irq, void *, struct pt_regs *);
+typedef dasd_era_t (*dasd_error_examine_fn_t) (ccw_req_t *, devstat_t * stat);
+typedef dasd_erp_action_fn_t (*dasd_error_analyse_fn_t) (ccw_req_t *);
+typedef dasd_erp_postaction_fn_t (*dasd_erp_analyse_fn_t) (ccw_req_t *);
+typedef ccw_req_t *(*dasd_cp_builder_fn_t)(struct dasd_device_t *,struct request *);
+typedef char *(*dasd_dump_sense_fn_t)(struct dasd_device_t *,ccw_req_t *);
+typedef ccw_req_t *(*dasd_reserve_fn_t)(struct dasd_device_t *);
+typedef ccw_req_t *(*dasd_release_fn_t)(struct dasd_device_t *);
+typedef ccw_req_t *(*dasd_merge_cp_fn_t)(struct dasd_device_t *);
+
+
+/*
+ * the dasd_discipline_t is
+ * sth like a table of virtual functions, if you think of dasd_eckd
+ * inheriting dasd...
+ * no, currently we are not planning to reimplement the driver in C++
+ */
+typedef struct dasd_discipline_t {
+	char ebcname[8]; /* a name used for tagging and printks */
+        char name[8];		/* a name used for tagging and printks */
+
+	dasd_ck_id_fn_t id_check;	/* to check sense data */
+	dasd_ck_characteristics_fn_t check_characteristics;	/* to check the characteristics */
+	dasd_init_analysis_fn_t init_analysis;	/* to start the analysis of the volume */
+	dasd_do_analysis_fn_t do_analysis;	/* to complete the analysis of the volume */
+	dasd_fill_geometry_fn_t fill_geometry;	/* to set up hd_geometry */
+	dasd_io_starter_fn_t start_IO;
+        dasd_format_fn_t format_device;		/* to format the device */
+	dasd_error_examine_fn_t examine_error;
+	dasd_error_analyse_fn_t erp_action;
+	dasd_erp_analyse_fn_t erp_postaction;
+        dasd_cp_builder_fn_t build_cp_from_req;
+        dasd_dump_sense_fn_t dump_sense;
+        dasd_int_handler_fn_t int_handler;
+        dasd_reserve_fn_t reserve;
+        dasd_release_fn_t release;
+        dasd_merge_cp_fn_t merge_cp;
+	
+	struct dasd_discipline_t *next;	/* used for list of disciplines */
+} dasd_discipline_t;
+
+typedef struct major_info_t {
+	struct major_info_t *next;
+	struct dasd_device_t **dasd_device;
+	struct gendisk gendisk; /* actually contains the major number */
+} __attribute__ ((packed)) major_info_t;
+
+typedef struct dasd_profile_info_t {
+        unsigned long dasd_io_reqs;	/* number of requests processed at all */
+        unsigned long dasd_io_secs[32];	/* histogram of request's sizes */
+        unsigned long dasd_io_times[32];	/* histogram of requests's times */
+        unsigned long dasd_io_timps[32];	/* histogram of requests's times per sector */
+        unsigned long dasd_io_time1[32];	/* histogram of time from build to start */
+       unsigned  long dasd_io_time2[32];	/* histogram of time from start to irq */
+        unsigned long dasd_io_time2ps[32];	/* histogram of time from start to irq */
+        unsigned long dasd_io_time3[32];	/* histogram of time from irq to end */
+} dasd_profile_info_t;
+
+typedef struct dasd_device_t {
+	dev_info_t devinfo;
+	dasd_discipline_t *discipline;
+	int level;
+        int open_count;
+        kdev_t kdev;
+        major_info_t *major_info;
+	struct dasd_chanq_t queue;
+        wait_queue_head_t wait_q;
+        request_queue_t request_queue;
+	devstat_t dev_status; /* needed ONLY!! for request_irq */
+        dasd_sizes_t sizes;
+        char name[16]; /* The name of the device in /dev */
+	char *private;	/* to be used by the discipline internally */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98))
+        devfs_handle_t devfs_entry;
+#endif /* LINUX_IS_24 */
+	struct tq_struct bh_tq;
+        atomic_t bh_scheduled;
+        debug_info_t *debug_area;
+        dasd_profile_info_t profile;
+        struct proc_dir_entry *proc_dir; /* directory node */
+        struct proc_dir_entry *proc_info; /* information from dasd_device_t */
+        struct proc_dir_entry *proc_stats; /* statictics information */
+}  dasd_device_t;
+
+/* dasd_device_t.level can be: */
+#define DASD_DEVICE_LEVEL_UNKNOWN 0x00
+#define DASD_DEVICE_LEVEL_RECOGNIZED 0x01
+#define DASD_DEVICE_LEVEL_ANALYSIS_PENDING 0x02
+#define DASD_DEVICE_LEVEL_ANALYSIS_PREPARED 0x04
+#define DASD_DEVICE_LEVEL_ANALYSED 0x08
+#define DASD_DEVICE_LEVEL_PARTITIONED 0x10
+
+int dasd_init (void);
+void dasd_discipline_enq (dasd_discipline_t *);
+int dasd_discipline_deq(dasd_discipline_t *);
+int dasd_start_IO (ccw_req_t *);
+void dasd_int_handler (int , void *, struct pt_regs *);
+ccw_req_t *default_erp_action (ccw_req_t *);
+ccw_req_t *default_erp_postaction (ccw_req_t *);
+int dasd_chanq_deq (dasd_chanq_t *, ccw_req_t *);
+ccw_req_t *dasd_alloc_request (char *, int, int);
+void dasd_free_request (ccw_req_t *);
+int (*genhd_dasd_name) (char *, int, int, struct gendisk *);
+int dasd_oper_handler (int irq, devreg_t * devreg);
+
+#endif /* __KERNEL__ */
+
+#endif				/* DASD_H */
+
+/*
+ * Overrides for Emacs so that we follow Linus's tabbing style.
+ * Emacs will notice this stuff at the end of the file and automatically
+ * adjust the settings for this buffer only.  This must remain at the end
+ * of the file.
+ * ---------------------------------------------------------------------------
+ * Local variables:
+ * c-indent-level: 4 
+ * c-brace-imaginary-offset: 0
+ * c-brace-offset: -4
+ * c-argdecl-indent: 4
+ * c-label-offset: -4
+ * c-continued-statement-offset: 4
+ * c-continued-brace-offset: 0
+ * indent-tabs-mode: nil
+ * tab-width: 8
+ * End:
+ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/debug.h linux/include/asm-s390x/debug.h
--- v2.4.1/linux/include/asm-s390x/debug.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/debug.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,210 @@
+/*
+ *  include/asm-s390/debug.h
+ *   S/390 debug facility
+ *
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
+ *                             IBM Corporation
+ */
+
+#ifndef DEBUG_H
+#define DEBUG_H
+
+/* Note:
+ * struct __debug_entry must be defined outside of #ifdef __KERNEL__ 
+ * in order to allow a user program to analyze the 'raw'-view.
+ */
+
+struct __debug_entry{
+        union {
+                struct {
+                        unsigned long long clock:52;
+                        unsigned long long exception:1;
+                        unsigned long long used:1;
+                        unsigned long long unused:1;
+                        unsigned long long cpuid:9;
+                } fields;
+
+                unsigned long long stck;
+        } id;
+        void* caller;
+} __attribute__((packed));
+
+#ifdef __KERNEL__
+#include <linux/version.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
+ #include <asm/spinlock.h>
+#else
+ #include <linux/spinlock.h>
+#endif /* LINUX_VERSION_CODE */
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/proc_fs.h>
+
+#define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
+#define DEBUG_OFF_LEVEL            -1 /* level where debug is switched off */
+#define DEBUG_MAX_VIEWS            10 /* max number of views in proc fs */
+#define DEBUG_MAX_PROCF_LEN        16 /* max length for a proc file name */
+#define DEBUG_DEFAULT_LEVEL        3  /* initial debug level */
+#define DEBUG_FEATURE_VERSION      1  /* version of debug feature */
+
+#define DEBUG_DIR_ROOT "s390dbf" /* name of debug root directory in proc fs */
+
+#define DEBUG_DATA(entry) (char*)(entry + 1) /* data is stored behind */
+                                             /* the entry information */
+
+#define STCK(x)	asm volatile ("STCK %0":"=m" (x))
+
+typedef struct __debug_entry debug_entry_t;
+
+struct debug_view;
+
+typedef struct debug_info {	
+	struct debug_info* next;
+	struct debug_info* prev;
+	atomic_t ref_count;
+	spinlock_t lock;			
+	int level;
+	int nr_areas;
+	int page_order;
+	int buf_size;
+	int entry_size;	
+	debug_entry_t** areas;
+	int active_area;
+	int *active_entry;
+	struct proc_dir_entry* proc_root_entry;
+	struct proc_dir_entry* proc_entries[DEBUG_MAX_VIEWS];
+	struct debug_view* views[DEBUG_MAX_VIEWS];	
+	char name[DEBUG_MAX_PROCF_LEN];
+} debug_info_t;
+
+typedef int (debug_header_proc_t) (debug_info_t* id,
+				   struct debug_view* view,
+				   int area,
+				   debug_entry_t* entry,
+				   char* out_buf);
+
+typedef int (debug_format_proc_t) (debug_info_t* id,
+				   struct debug_view* view, char* out_buf,
+				   const char* in_buf);
+typedef int (debug_prolog_proc_t) (debug_info_t* id,
+				   struct debug_view* view,
+				   char* out_buf);
+typedef int (debug_input_proc_t) (debug_info_t* id,
+				  struct debug_view* view,
+				  struct file* file, const char* user_buf,
+				  size_t in_buf_size, loff_t* offset);
+
+int debug_dflt_header_fn(debug_info_t* id, struct debug_view* view,
+		         int area, debug_entry_t* entry, char* out_buf);						
+				
+struct debug_view {
+	char name[DEBUG_MAX_PROCF_LEN];
+	debug_prolog_proc_t* prolog_proc;
+	debug_header_proc_t* header_proc;
+	debug_format_proc_t* format_proc;
+	debug_input_proc_t*  input_proc;
+};
+
+extern struct debug_view debug_hex_ascii_view;
+extern struct debug_view debug_raw_view;
+
+debug_info_t* debug_register(char* name, int pages_index, int nr_areas,
+			     int buf_size);
+void debug_unregister(debug_info_t* id);
+
+void debug_set_level(debug_info_t* id, int new_level);
+
+debug_entry_t* debug_event(debug_info_t* id, int level, void* data,
+			   int length);
+debug_entry_t* debug_int_event(debug_info_t* id, int level,
+			       unsigned int tag);
+debug_entry_t* debug_text_event(debug_info_t* id, int level,
+				const char* txt);
+
+debug_entry_t* debug_exception(debug_info_t* id, int level, void* data,
+			       int length);
+debug_entry_t* debug_int_exception(debug_info_t* id, int level,
+				   unsigned int tag);
+debug_entry_t* debug_text_exception(debug_info_t* id, int level,
+				    const char* txt);
+
+static inline debug_entry_t *
+debug_long_event (debug_info_t* id, int level, unsigned long tag)
+{
+	unsigned long t=tag;
+	return debug_event(id,level,&t,sizeof(unsigned long));
+}
+static inline debug_entry_t *
+debug_long_exception (debug_info_t* id, int level, unsigned long tag)
+{
+	unsigned long t=tag;
+	return debug_exception(id,level,&t,sizeof(unsigned long));
+}
+int debug_register_view(debug_info_t* id, struct debug_view* view);
+int debug_unregister_view(debug_info_t* id, struct debug_view* view);
+
+/*
+   define the debug levels:
+   - 0 No debugging output to console or syslog
+   - 1 Log internal errors to syslog, ignore check conditions 
+   - 2 Log internal errors and check conditions to syslog
+   - 3 Log internal errors to console, log check conditions to syslog
+   - 4 Log internal errors and check conditions to console
+   - 5 panic on internal errors, log check conditions to console
+   - 6 panic on both, internal errors and check conditions
+ */
+
+#ifndef DEBUG_LEVEL
+#define DEBUG_LEVEL 4
+#endif
+
+#define INTERNAL_ERRMSG(x,y...) "E" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_WRNMSG(x,y...) "W" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_INFMSG(x,y...) "I" __FILE__ "%d: " x, __LINE__, y
+#define INTERNAL_DEBMSG(x,y...) "D" __FILE__ "%d: " x, __LINE__, y
+
+#if DEBUG_LEVEL > 0
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER x )
+#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER x )
+#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER x )
+#define PRINT_FATAL(x...) panic ( PRINTK_HEADER x )
+#else
+#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
+#endif				/* DASD_DEBUG */
+
+#if DASD_DEBUG > 4
+#define INTERNAL_ERROR(x...) PRINT_FATAL ( INTERNAL_ERRMSG ( x ) )
+#elif DASD_DEBUG > 2
+#define INTERNAL_ERROR(x...) PRINT_ERR ( INTERNAL_ERRMSG ( x ) )
+#elif DASD_DEBUG > 0
+#define INTERNAL_ERROR(x...) PRINT_WARN ( INTERNAL_ERRMSG ( x ) )
+#else
+#define INTERNAL_ERROR(x...)
+#endif				/* DASD_DEBUG */
+
+#if DASD_DEBUG > 5
+#define INTERNAL_CHECK(x...) PRINT_FATAL ( INTERNAL_CHKMSG ( x ) )
+#elif DASD_DEBUG > 3
+#define INTERNAL_CHECK(x...) PRINT_ERR ( INTERNAL_CHKMSG ( x ) )
+#elif DASD_DEBUG > 1
+#define INTERNAL_CHECK(x...) PRINT_WARN ( INTERNAL_CHKMSG ( x ) )
+#else
+#define INTERNAL_CHECK(x...)
+#endif				/* DASD_DEBUG */
+
+#undef DEBUG_MALLOC
+#ifdef DEBUG_MALLOC
+void *b;
+#define kmalloc(x...) (PRINT_INFO(" kmalloc %p\n",b=kmalloc(x)),b)
+#define kfree(x) PRINT_INFO(" kfree %p\n",x);kfree(x)
+#define get_free_page(x...) (PRINT_INFO(" gfp %p\n",b=get_free_page(x)),b)
+#define __get_free_pages(x...) (PRINT_INFO(" gfps %p\n",b=__get_free_pages(x)),b)
+#endif				/* DEBUG_MALLOC */
+
+#endif				/* __KERNEL__ */
+#endif				/* DEBUG_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/delay.h linux/include/asm-s390x/delay.h
--- v2.4.1/linux/include/asm-s390x/delay.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/delay.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,22 @@
+/*
+ *  include/asm-s390/delay.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/delay.h"
+ *    Copyright (C) 1993 Linus Torvalds
+ *
+ *  Delay routines calling functions in arch/i386/lib/delay.c
+ */
+ 
+#ifndef _S390_DELAY_H
+#define _S390_DELAY_H
+
+extern void __udelay(unsigned long usecs);
+extern void __delay(unsigned long loops);
+
+#define udelay(n) __udelay(n)
+
+#endif /* defined(_S390_DELAY_H) */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/div64.h linux/include/asm-s390x/div64.h
--- v2.4.1/linux/include/asm-s390x/div64.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/div64.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,10 @@
+#ifndef __S390_DIV64
+#define __S390_DIV64
+
+#define do_div(n,base) ({ \
+int __res; \
+__res = ((unsigned long) n) % (unsigned) base; \
+n = ((unsigned long) n) / (unsigned) base; \
+__res; })
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/dma.h linux/include/asm-s390x/dma.h
--- v2.4.1/linux/include/asm-s390x/dma.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/dma.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,16 @@
+/*
+ *  include/asm-s390x/dma.h
+ *
+ *  S390 version
+ */
+
+#ifndef _ASM_DMA_H
+#define _ASM_DMA_H
+
+#include <asm/io.h>		/* need byte IO */
+
+/* The I/O subsystem can access only memory below 2GB.
+   We use the existing DMA zone mechanism to handle this. */
+#define MAX_DMA_ADDRESS         0x80000000
+
+#endif /* _ASM_DMA_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ebcdic.h linux/include/asm-s390x/ebcdic.h
--- v2.4.1/linux/include/asm-s390x/ebcdic.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ebcdic.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,55 @@
+/*
+ *  include/asm-s390/ebcdic.h
+ *    EBCDIC -> ASCII, ASCII -> EBCDIC conversion routines.
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+
+#ifndef _EBCDIC_H
+#define _EBCDIC_H
+
+#ifndef _S390_TYPES_H
+#include <types.h>
+#endif
+
+extern __u8 _ascebc_500[];   /* ASCII -> EBCDIC 500 conversion table */
+extern __u8 _ebcasc_500[];   /* EBCDIC 500 -> ASCII conversion table */
+extern __u8 _ascebc[];   /* ASCII -> EBCDIC conversion table */
+extern __u8 _ebcasc[];   /* EBCDIC -> ASCII conversion table */
+extern __u8 _ebc_tolower[]; /* EBCDIC -> lowercase */
+extern __u8 _ebc_toupper[]; /* EBCDIC -> uppercase */
+
+extern __inline__ void
+codepage_convert(const __u8 *codepage, volatile __u8 * addr, unsigned long nr)
+{
+        static const __u16 tr_op[] = { 0xDC00, 0x1000,0x3000 };
+        __asm__ __volatile__(
+                "   lgr   1,%0\n"
+                "   lgr   2,%1\n"
+                "   lgr   3,%2\n"
+                "   aghi  2,-256\n"
+                "   jm    1f\n"
+                "0: tr    0(256,1),0(3)\n"
+                "   aghi  1,256\n"
+                "   aghi  2,-256\n"
+                "   jp    0b\n"
+                "1: aghi  2,255\n"
+                "   jm    2f\n"
+                "   ex    2,%3\n"
+                "2:"
+                : /* no output */ 
+                : "a" (addr), "d" (nr), "a" (codepage), "m" (tr_op[0])
+                : "cc", "memory", "1", "2", "3" );
+}
+
+#define ASCEBC(addr,nr) codepage_convert(_ascebc, addr, nr)
+#define EBCASC(addr,nr) codepage_convert(_ebcasc, addr, nr)
+#define ASCEBC_500(addr,nr) codepage_convert(_ascebc_500, addr, nr)
+#define EBCASC_500(addr,nr) codepage_convert(_ebcasc_500, addr, nr)
+#define EBC_TOLOWER(addr,nr) codepage_convert(_ebc_tolower, addr, nr)
+#define EBC_TOUPPER(addr,nr) codepage_convert(_ebc_toupper, addr, nr)
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/elf.h linux/include/asm-s390x/elf.h
--- v2.4.1/linux/include/asm-s390x/elf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/elf.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,82 @@
+/*
+ *  include/asm-s390/elf.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/elf.h"
+ */
+
+#ifndef __ASMS390_ELF_H
+#define __ASMS390_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+
+#include <asm/ptrace.h>
+#include <asm/user.h>
+
+
+typedef s390_fp_regs elf_fpregset_t;
+typedef s390_regs elf_gregset_t;
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS64
+#define ELF_DATA	ELFDATA2MSB
+#define ELF_ARCH	EM_S390
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+#define elf_check_arch(x) \
+        ((x)->e_machine == ELF_ARCH && (x)->e_ident[EI_CLASS] == ELF_CLASS)
+
+/* For SVR4/S390 the function pointer to be registered with `atexit` is
+   passed in R14. */
+#define ELF_PLAT_INIT(_r) \
+	do { \
+	_r->gprs[14] = 0; \
+	current->thread.flags = 0; \
+	} while(0)
+
+#define USE_ELF_CORE_DUMP
+#define ELF_EXEC_PAGESIZE	4096
+
+/* This is the location that an ET_DYN program is loaded if exec'ed.  Typical
+   use of this is to invoke "./ld.so someprog" to test out a new version of
+   the loader.  We need to make sure that it is out of the way of the program
+   that it will "exec", and that there is sufficient room for the brk.  */
+
+#define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
+
+/* Wow, the "main" arch needs arch dependent functions too.. :) */
+
+/* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
+   now struct_user_regs, they are different) */
+
+#define ELF_CORE_COPY_REGS(pr_reg, regs)	\
+	memcpy(&pr_reg,regs,sizeof(elf_gregset_t)); \
+
+
+
+/* This yields a mask that user programs can use to figure out what
+   instruction set this CPU supports. */
+
+#define ELF_HWCAP (0)
+
+/* This yields a string that ld.so will use to load implementation
+   specific libraries for optimization.  This is more specific in
+   intent than poking at uname or /proc/cpuinfo.
+
+   For the moment, we have only optimizations for the Intel generations,
+   but that could change... */
+
+#define ELF_PLATFORM (NULL)
+
+#ifdef __KERNEL__
+#define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
+#endif
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/errno.h linux/include/asm-s390x/errno.h
--- v2.4.1/linux/include/asm-s390x/errno.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/errno.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,140 @@
+/*
+ *  include/asm-s390/errno.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/errno.h"
+ */
+
+#ifndef _S390_ERRNO_H
+#define _S390_ERRNO_H
+
+#define	EPERM		 1	/* Operation not permitted */
+#define	ENOENT		 2	/* No such file or directory */
+#define	ESRCH		 3	/* No such process */
+#define	EINTR		 4	/* Interrupted system call */
+#define	EIO		 5	/* I/O error */
+#define	ENXIO		 6	/* No such device or address */
+#define	E2BIG		 7	/* Arg list too long */
+#define	ENOEXEC		 8	/* Exec format error */
+#define	EBADF		 9	/* Bad file number */
+#define	ECHILD		10	/* No child processes */
+#define	EAGAIN		11	/* Try again */
+#define	ENOMEM		12	/* Out of memory */
+#define	EACCES		13	/* Permission denied */
+#define	EFAULT		14	/* Bad address */
+#define	ENOTBLK		15	/* Block device required */
+#define	EBUSY		16	/* Device or resource busy */
+#define	EEXIST		17	/* File exists */
+#define	EXDEV		18	/* Cross-device link */
+#define	ENODEV		19	/* No such device */
+#define	ENOTDIR		20	/* Not a directory */
+#define	EISDIR		21	/* Is a directory */
+#define	EINVAL		22	/* Invalid argument */
+#define	ENFILE		23	/* File table overflow */
+#define	EMFILE		24	/* Too many open files */
+#define	ENOTTY		25	/* Not a typewriter */
+#define	ETXTBSY		26	/* Text file busy */
+#define	EFBIG		27	/* File too large */
+#define	ENOSPC		28	/* No space left on device */
+#define	ESPIPE		29	/* Illegal seek */
+#define	EROFS		30	/* Read-only file system */
+#define	EMLINK		31	/* Too many links */
+#define	EPIPE		32	/* Broken pipe */
+#define	EDOM		33	/* Math argument out of domain of func */
+#define	ERANGE		34	/* Math result not representable */
+#define	EDEADLK		35	/* Resource deadlock would occur */
+#define	ENAMETOOLONG	36	/* File name too long */
+#define	ENOLCK		37	/* No record locks available */
+#define	ENOSYS		38	/* Function not implemented */
+#define	ENOTEMPTY	39	/* Directory not empty */
+#define	ELOOP		40	/* Too many symbolic links encountered */
+#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
+#define	ENOMSG		42	/* No message of desired type */
+#define	EIDRM		43	/* Identifier removed */
+#define	ECHRNG		44	/* Channel number out of range */
+#define	EL2NSYNC	45	/* Level 2 not synchronized */
+#define	EL3HLT		46	/* Level 3 halted */
+#define	EL3RST		47	/* Level 3 reset */
+#define	ELNRNG		48	/* Link number out of range */
+#define	EUNATCH		49	/* Protocol driver not attached */
+#define	ENOCSI		50	/* No CSI structure available */
+#define	EL2HLT		51	/* Level 2 halted */
+#define	EBADE		52	/* Invalid exchange */
+#define	EBADR		53	/* Invalid request descriptor */
+#define	EXFULL		54	/* Exchange full */
+#define	ENOANO		55	/* No anode */
+#define	EBADRQC		56	/* Invalid request code */
+#define	EBADSLT		57	/* Invalid slot */
+
+#define	EDEADLOCK	EDEADLK
+
+#define	EBFONT		59	/* Bad font file format */
+#define	ENOSTR		60	/* Device not a stream */
+#define	ENODATA		61	/* No data available */
+#define	ETIME		62	/* Timer expired */
+#define	ENOSR		63	/* Out of streams resources */
+#define	ENONET		64	/* Machine is not on the network */
+#define	ENOPKG		65	/* Package not installed */
+#define	EREMOTE		66	/* Object is remote */
+#define	ENOLINK		67	/* Link has been severed */
+#define	EADV		68	/* Advertise error */
+#define	ESRMNT		69	/* Srmount error */
+#define	ECOMM		70	/* Communication error on send */
+#define	EPROTO		71	/* Protocol error */
+#define	EMULTIHOP	72	/* Multihop attempted */
+#define	EDOTDOT		73	/* RFS specific error */
+#define	EBADMSG		74	/* Not a data message */
+#define	EOVERFLOW	75	/* Value too large for defined data type */
+#define	ENOTUNIQ	76	/* Name not unique on network */
+#define	EBADFD		77	/* File descriptor in bad state */
+#define	EREMCHG		78	/* Remote address changed */
+#define	ELIBACC		79	/* Can not access a needed shared library */
+#define	ELIBBAD		80	/* Accessing a corrupted shared library */
+#define	ELIBSCN		81	/* .lib section in a.out corrupted */
+#define	ELIBMAX		82	/* Attempting to link in too many shared libraries */
+#define	ELIBEXEC	83	/* Cannot exec a shared library directly */
+#define	EILSEQ		84	/* Illegal byte sequence */
+#define	ERESTART	85	/* Interrupted system call should be restarted */
+#define	ESTRPIPE	86	/* Streams pipe error */
+#define	EUSERS		87	/* Too many users */
+#define	ENOTSOCK	88	/* Socket operation on non-socket */
+#define	EDESTADDRREQ	89	/* Destination address required */
+#define	EMSGSIZE	90	/* Message too long */
+#define	EPROTOTYPE	91	/* Protocol wrong type for socket */
+#define	ENOPROTOOPT	92	/* Protocol not available */
+#define	EPROTONOSUPPORT	93	/* Protocol not supported */
+#define	ESOCKTNOSUPPORT	94	/* Socket type not supported */
+#define	EOPNOTSUPP	95	/* Operation not supported on transport endpoint */
+#define	EPFNOSUPPORT	96	/* Protocol family not supported */
+#define	EAFNOSUPPORT	97	/* Address family not supported by protocol */
+#define	EADDRINUSE	98	/* Address already in use */
+#define	EADDRNOTAVAIL	99	/* Cannot assign requested address */
+#define	ENETDOWN	100	/* Network is down */
+#define	ENETUNREACH	101	/* Network is unreachable */
+#define	ENETRESET	102	/* Network dropped connection because of reset */
+#define	ECONNABORTED	103	/* Software caused connection abort */
+#define	ECONNRESET	104	/* Connection reset by peer */
+#define	ENOBUFS		105	/* No buffer space available */
+#define	EISCONN		106	/* Transport endpoint is already connected */
+#define	ENOTCONN	107	/* Transport endpoint is not connected */
+#define	ESHUTDOWN	108	/* Cannot send after transport endpoint shutdown */
+#define	ETOOMANYREFS	109	/* Too many references: cannot splice */
+#define	ETIMEDOUT	110	/* Connection timed out */
+#define	ECONNREFUSED	111	/* Connection refused */
+#define	EHOSTDOWN	112	/* Host is down */
+#define	EHOSTUNREACH	113	/* No route to host */
+#define	EALREADY	114	/* Operation already in progress */
+#define	EINPROGRESS	115	/* Operation now in progress */
+#define	ESTALE		116	/* Stale NFS file handle */
+#define	EUCLEAN		117	/* Structure needs cleaning */
+#define	ENOTNAM		118	/* Not a XENIX named type file */
+#define	ENAVAIL		119	/* No XENIX semaphores available */
+#define	EISNAM		120	/* Is a named type file */
+#define	EREMOTEIO	121	/* Remote I/O error */
+#define	EDQUOT		122	/* Quota exceeded */
+
+#define	ENOMEDIUM	123	/* No medium found */
+#define	EMEDIUMTYPE	124	/* Wrong medium type */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/fcntl.h linux/include/asm-s390x/fcntl.h
--- v2.4.1/linux/include/asm-s390x/fcntl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/fcntl.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,85 @@
+/*
+ *  include/asm-s390/fcntl.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/fcntl.h"
+ */
+#ifndef _S390_FCNTL_H
+#define _S390_FCNTL_H
+
+/* open/fcntl - O_SYNC is only implemented on blocks devices and on files
+   located on an ext2 file system */
+#define O_ACCMODE	   0003
+#define O_RDONLY	     00
+#define O_WRONLY	     01
+#define O_RDWR		     02
+#define O_CREAT		   0100	/* not fcntl */
+#define O_EXCL		   0200	/* not fcntl */
+#define O_NOCTTY	   0400	/* not fcntl */
+#define O_TRUNC		  01000	/* not fcntl */
+#define O_APPEND	  02000
+#define O_NONBLOCK	  04000
+#define O_NDELAY	O_NONBLOCK
+#define O_SYNC		 010000
+#define FASYNC		 020000	/* fcntl, for BSD compatibility */
+#define O_DIRECT	 040000	/* direct disk access hint - currently ignored */
+#define O_LARGEFILE	0100000
+#define O_DIRECTORY	0200000	/* must be a directory */
+#define O_NOFOLLOW	0400000 /* don't follow links */
+
+#define F_DUPFD		0	/* dup */
+#define F_GETFD		1	/* get close_on_exec */
+#define F_SETFD		2	/* set/clear close_on_exec */
+#define F_GETFL		3	/* get file->f_flags */
+#define F_SETFL		4	/* set file->f_flags */
+#define F_GETLK		5
+#define F_SETLK		6
+#define F_SETLKW	7
+
+#define F_SETOWN	8	/*  for sockets. */
+#define F_GETOWN	9	/*  for sockets. */
+#define F_SETSIG	10	/*  for sockets. */
+#define F_GETSIG	11	/*  for sockets. */
+
+/* for F_[GET|SET]FL */
+#define FD_CLOEXEC	1	/* actually anything with low bit set goes */
+
+/* for posix fcntl() and lockf() */
+#define F_RDLCK		0
+#define F_WRLCK		1
+#define F_UNLCK		2
+
+/* for old implementation of bsd flock () */
+#define F_EXLCK		4	/* or 3 */
+#define F_SHLCK		8	/* or 4 */
+
+/* for leases */
+#define F_INPROGRESS	16
+
+/* operations for bsd flock(), also used by the kernel implementation */
+#define LOCK_SH		1	/* shared lock */
+#define LOCK_EX		2	/* exclusive lock */
+#define LOCK_NB		4	/* or'd with one of the above to prevent
+				   blocking */
+#define LOCK_UN		8	/* remove lock */
+
+#define LOCK_MAND	32	/* This is a mandatory flock */
+#define LOCK_READ	64	/* ... Which allows concurrent read operations */
+#define LOCK_WRITE	128	/* ... Which allows concurrent write operations
+*/
+#define LOCK_RW		192	/* ... Which allows concurrent read & write ops */
+
+struct flock {
+	short l_type;
+	short l_whence;
+	__kernel_off_t l_start;
+	__kernel_off_t l_len;
+	__kernel_pid_t l_pid;
+};
+
+#define F_LINUX_SPECIFIC_BASE  1024
+
+#define flock64   flock
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/gdb-stub.h linux/include/asm-s390x/gdb-stub.h
--- v2.4.1/linux/include/asm-s390x/gdb-stub.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/gdb-stub.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,18 @@
+/*
+ *  include/asm-s390/gdb-stub.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#ifndef __S390_GDB_STUB__
+#define __S390_GDB_STUB__
+#include <linux/config.h>
+#if CONFIG_REMOTE_DEBUG
+#include <asm/s390-gdbregs.h>
+#include <asm/ptrace.h>
+extern int    gdb_stub_initialised;
+extern void gdb_stub_handle_exception(gdb_pt_regs *regs,int sigval);
+#endif
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/hardirq.h linux/include/asm-s390x/hardirq.h
--- v2.4.1/linux/include/asm-s390x/hardirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/hardirq.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,108 @@
+/*
+ *  include/asm-s390/hardirq.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *  Derived from "include/asm-i386/hardirq.h"
+ */
+
+#ifndef __ASM_HARDIRQ_H
+#define __ASM_HARDIRQ_H
+
+#include <linux/config.h>
+#include <linux/threads.h>
+#include <asm/lowcore.h>
+#include <linux/sched.h>
+
+/* No irq_cpustat_t for s390, the data is held directly in S390_lowcore */
+
+/*
+ * Simple wrappers reducing source bloat.  S390 specific because each
+ * cpu stores its data in S390_lowcore (PSA) instead of using a cache
+ * aligned array element like most architectures.
+ */
+
+#ifdef CONFIG_SMP
+
+#define softirq_active(cpu)	(safe_get_cpu_lowcore(cpu).__softirq_active)
+#define softirq_mask(cpu)	(safe_get_cpu_lowcore(cpu).__softirq_mask)
+#define local_irq_count(cpu)	(safe_get_cpu_lowcore(cpu).__local_irq_count)
+#define local_bh_count(cpu)	(safe_get_cpu_lowcore(cpu).__local_bh_count)
+#define syscall_count(cpu)	(safe_get_cpu_lowcore(cpu).__syscall_count)
+
+#else	/* CONFIG_SMP */
+
+/* Optimize away the cpu calculation, it is always current PSA */
+#define softirq_active(cpu)	((void)(cpu), S390_lowcore.__softirq_active)
+#define softirq_mask(cpu)	((void)(cpu), S390_lowcore.__softirq_mask)
+#define local_irq_count(cpu)	((void)(cpu), S390_lowcore.__local_irq_count)
+#define local_bh_count(cpu)	((void)(cpu), S390_lowcore.__local_bh_count)
+#define syscall_count(cpu)	((void)(cpu), S390_lowcore.__syscall_count)
+
+#endif	/* CONFIG_SMP */
+
+/*
+ * Are we in an interrupt context? Either doing bottom half
+ * or hardware interrupt processing?
+ * Special definitions for s390, always access current PSA.
+ */
+#define in_interrupt() ((S390_lowcore.__local_irq_count + S390_lowcore.__local_bh_count) != 0)
+  
+#define in_irq() (S390_lowcore.__local_irq_count != 0)
+  
+#ifndef CONFIG_SMP
+  
+#define hardirq_trylock(cpu)	(local_irq_count(cpu) == 0)
+#define hardirq_endlock(cpu)	do { } while (0)
+  
+#define hardirq_enter(cpu)	(local_irq_count(cpu)++)
+#define hardirq_exit(cpu)	(local_irq_count(cpu)--)
+
+#define synchronize_irq()	do { } while (0)
+
+#else
+
+#include <asm/atomic.h>
+#include <asm/smp.h>
+
+extern atomic_t global_irq_holder;
+extern atomic_t global_irq_lock;
+extern atomic_t global_irq_count;
+
+static inline void release_irqlock(int cpu)
+{
+	/* if we didn't own the irq lock, just ignore.. */
+	if (atomic_read(&global_irq_holder) ==  cpu) {
+		atomic_set(&global_irq_holder,NO_PROC_ID);
+                atomic_set(&global_irq_lock,0);
+	}
+}
+
+static inline void hardirq_enter(int cpu)
+{
+        ++local_irq_count(cpu);
+	atomic_inc(&global_irq_count);
+}
+
+static inline void hardirq_exit(int cpu)
+{
+	atomic_dec(&global_irq_count);
+        --local_irq_count(cpu);
+}
+
+static inline int hardirq_trylock(int cpu)
+{
+	return !atomic_read(&global_irq_count) && 
+               !atomic_read(&global_irq_lock);
+}
+
+#define hardirq_endlock(cpu)	do { } while (0)
+
+extern void synchronize_irq(void);
+
+#endif /* CONFIG_SMP */
+
+#endif /* __ASM_HARDIRQ_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/hdreg.h linux/include/asm-s390x/hdreg.h
--- v2.4.1/linux/include/asm-s390x/hdreg.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/hdreg.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,13 @@
+/*
+ *  linux/include/asm-arm/hdreg.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+#ifndef __ASMS390_HDREG_H
+#define __ASMS390_HDREG_H
+
+typedef unsigned long ide_ioreg_t;
+
+#endif /* __ASMS390_HDREG_H */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/idals.h linux/include/asm-s390x/idals.h
--- v2.4.1/linux/include/asm-s390x/idals.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/idals.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,57 @@
+/* 
+   * File...........: linux/include/asm-s390x/idals.h
+   * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+   * Bugreports.to..: <Linux390@de.ibm.com>
+   * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
+   
+   * History of changes
+   * 07/24/00 new file
+ */
+#include <linux/config.h>
+#include <asm/irq.h>
+
+typedef unsigned long idaw_t;
+
+static inline idaw_t *
+idal_alloc ( int nridaws )
+{
+	if ( nridaws > 33 )
+		BUG();
+	return kmalloc(nridaws * sizeof(idaw_t), GFP_ATOMIC | GFP_DMA );
+}
+
+static inline void 
+idal_free ( idaw_t *idal )
+{
+	kfree (idal);
+}
+
+/*
+ * Function: set_normalized_cda
+ * sets the address of the data in CCW
+ * if necessary it allocates an IDAL and sets sthe appropriate flags
+ */
+#if defined (CONFIG_ARCH_S390X)
+extern void set_normalized_cda(ccw1_t * ccw, unsigned long address);
+#else
+static inline void
+set_normalized_cda(ccw1_t * ccw, unsigned long address)
+{
+	ccw->cda = address;
+}
+#endif
+
+/*
+ * Function: clear_normalized_cda
+ * releases any allocated IDAL related to the CCW
+ */
+static inline void
+clear_normalized_cda ( ccw1_t * ccw ) 
+{
+	if ( ccw -> flags & CCW_FLAG_IDA ) {
+		idal_free ( (idaw_t *)(unsigned long) (ccw -> cda ));
+		ccw -> flags &= ~CCW_FLAG_IDA;
+	}
+	ccw -> cda = 0;
+}
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ide.h linux/include/asm-s390x/ide.h
--- v2.4.1/linux/include/asm-s390x/ide.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ide.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,54 @@
+/*
+ *  linux/include/asm-arm/ide.h
+ *
+ *  Copyright (C) 1994-1996  Linus Torvalds & authors
+ */
+
+/* s390 does not have IDE */
+
+#ifndef __ASMS390_IDE_H
+#define __ASMS390_IDE_H
+
+#ifdef __KERNEL__
+
+#ifndef MAX_HWIFS
+#define MAX_HWIFS	0
+#endif
+
+#define ide__sti()	do {} while (0)
+
+typedef union {
+	unsigned all			: 8;	/* all of the bits together */
+	struct {
+		unsigned head		: 4;	/* always zeros here */
+		unsigned unit		: 1;	/* drive select number, 0 or 1 */
+		unsigned bit5		: 1;	/* always 1 */
+		unsigned lba		: 1;	/* using LBA instead of CHS */
+		unsigned bit7		: 1;	/* always 1 */
+	} b;
+	} select_t;
+
+#define ide_request_irq(irq,hand,flg,dev,id)	do {} while (0)
+#define ide_free_irq(irq,dev_id)		do {} while (0)
+#define ide_check_region(from,extent)		do {} while (0)
+#define ide_request_region(from,extent,name)	do {} while (0)
+#define ide_release_region(from,extent)		do {} while (0)
+
+/*
+ * The following are not needed for the non-m68k ports
+ */
+#define ide_ack_intr(hwif)		(1)
+#define ide_fix_driveid(id)		do {} while (0)
+#define ide_release_lock(lock)		do {} while (0)
+#define ide_get_lock(lock, hdlr, data)	do {} while (0)
+
+/*
+ * We always use the new IDE port registering,
+ * so these are fixed here.
+ */
+#define ide_default_io_base(i)		((ide_ioreg_t)0)
+#define ide_default_irq(b)		(0)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASMARM_IDE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/init.h linux/include/asm-s390x/init.h
--- v2.4.1/linux/include/asm-s390x/init.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/init.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,29 @@
+/*
+ *  include/asm-s390/init.h
+ *
+ *  S390 version
+ */
+
+#ifndef _S390_INIT_H
+#define _S390_INIT_H
+
+#define __init __attribute__ ((constructor))
+
+/* don't know, if need on S390 */
+#define __initdata
+#define __initfunc(__arginit) \
+        __arginit __init; \
+        __arginit
+/* For assembly routines
+ * need to define ?
+ */
+/*
+#define __INIT          .section        ".text.init",#alloc,#execinstr
+#define __FINIT .previous
+#define __INITDATA      .section        ".data.init",#alloc,#write
+*/
+
+#define __cacheline_aligned __attribute__ ((__aligned__(16)))
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/io.h linux/include/asm-s390x/io.h
--- v2.4.1/linux/include/asm-s390x/io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/io.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,94 @@
+/*
+ *  include/asm-s390/io.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/io.h"
+ */
+
+#ifndef _S390_IO_H
+#define _S390_IO_H
+
+#ifdef __KERNEL__
+
+#include <linux/vmalloc.h>
+#include <asm/page.h>
+
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define __io_virt(x)            ((void *)(PAGE_OFFSET | (unsigned long)(x)))
+#define __io_phys(x)            ((unsigned long)(x) & ~PAGE_OFFSET)
+/*
+ * Change virtual addresses to physical addresses and vv.
+ * These are pretty trivial
+ */
+extern inline unsigned long virt_to_phys(volatile void * address)
+{
+	unsigned long real_address;
+	__asm__ ("   lrag   %0,0(%1)\n"
+                 "   jz     0f\n"
+                 "   slgr   %0,%0\n"
+                 "0:"
+                 : "=a" (real_address) : "a" (address) );
+        return real_address;
+}
+
+extern inline void * phys_to_virt(unsigned long address)
+{
+        return __io_virt(address);
+}
+
+extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+extern inline void * ioremap (unsigned long offset, unsigned long size)
+{
+        return __ioremap(offset, size, 0);
+}
+
+/*
+ * This one maps high address device memory and turns off caching for that area.
+ * it's useful if some control registers are in such an area and write combining
+ * or read caching is not desirable:
+ */
+extern inline void * ioremap_nocache (unsigned long offset, unsigned long size)
+{
+        return __ioremap(offset, size, 0);
+}
+
+extern void iounmap(void *addr);
+
+/*
+ * IO bus memory addresses are also 1:1 with the physical address
+ */
+#define virt_to_bus virt_to_phys
+#define bus_to_virt phys_to_virt
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently.
+ */
+
+#define readb(addr) (*(volatile unsigned char *) __io_virt(addr))
+#define readw(addr) (*(volatile unsigned short *) __io_virt(addr))
+#define readl(addr) (*(volatile unsigned int *) __io_virt(addr))
+
+#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b))
+
+#define memset_io(a,b,c)        memset(__io_virt(a),(b),(c))
+#define memcpy_fromio(a,b,c)    memcpy((a),__io_virt(b),(c))
+#define memcpy_toio(a,b,c)      memcpy(__io_virt(a),(b),(c))
+
+#define inb_p(addr) readb(addr)
+#define inb(addr) readb(addr)
+
+#define outb(x,addr) ((void) writeb(x,addr))
+#define outb_p(x,addr) outb(x,addr)
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ioctl.h linux/include/asm-s390x/ioctl.h
--- v2.4.1/linux/include/asm-s390x/ioctl.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ioctl.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,78 @@
+/*
+ *  include/asm-s390/ioctl.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/ioctl.h"
+ */
+
+#ifndef _S390_IOCTL_H
+#define _S390_IOCTL_H
+
+/* ioctl command encoding: 32 bits total, command in lower 16 bits,
+ * size of the parameter structure in the lower 14 bits of the
+ * upper 16 bits.
+ * Encoding the size of the parameter structure in the ioctl request
+ * is useful for catching programs compiled with old versions
+ * and to avoid overwriting user space outside the user buffer area.
+ * The highest 2 bits are reserved for indicating the ``access mode''.
+ * NOTE: This limits the max parameter size to 16kB -1 !
+ */
+
+/*
+ * The following is for compatibility across the various Linux
+ * platforms.  The i386 ioctl numbering scheme doesn't really enforce
+ * a type field.  De facto, however, the top 8 bits of the lower 16
+ * bits are indeed used as a type field, so we might just as well make
+ * this explicit here.  Please be sure to use the decoding macros
+ * below from now on.
+ */
+#define _IOC_NRBITS	8
+#define _IOC_TYPEBITS	8
+#define _IOC_SIZEBITS	14
+#define _IOC_DIRBITS	2
+
+#define _IOC_NRMASK	((1 << _IOC_NRBITS)-1)
+#define _IOC_TYPEMASK	((1 << _IOC_TYPEBITS)-1)
+#define _IOC_SIZEMASK	((1 << _IOC_SIZEBITS)-1)
+#define _IOC_DIRMASK	((1 << _IOC_DIRBITS)-1)
+
+#define _IOC_NRSHIFT	0
+#define _IOC_TYPESHIFT	(_IOC_NRSHIFT+_IOC_NRBITS)
+#define _IOC_SIZESHIFT	(_IOC_TYPESHIFT+_IOC_TYPEBITS)
+#define _IOC_DIRSHIFT	(_IOC_SIZESHIFT+_IOC_SIZEBITS)
+
+/*
+ * Direction bits.
+ */
+#define _IOC_NONE	0U
+#define _IOC_WRITE	1U
+#define _IOC_READ	2U
+
+#define _IOC(dir,type,nr,size) \
+	(((dir)  << _IOC_DIRSHIFT) | \
+	 ((type) << _IOC_TYPESHIFT) | \
+	 ((nr)   << _IOC_NRSHIFT) | \
+	 ((size) << _IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _IO(type,nr)		_IOC(_IOC_NONE,(type),(nr),0)
+#define _IOR(type,nr,size)	_IOC(_IOC_READ,(type),(nr),sizeof(size))
+#define _IOW(type,nr,size)	_IOC(_IOC_WRITE,(type),(nr),sizeof(size))
+#define _IOWR(type,nr,size)	_IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size))
+
+/* used to decode ioctl numbers.. */
+#define _IOC_DIR(nr)		(((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK)
+#define _IOC_TYPE(nr)		(((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK)
+#define _IOC_NR(nr)		(((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK)
+#define _IOC_SIZE(nr)		(((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK)
+
+/* ...and for the drivers/sound files... */
+
+#define IOC_IN		(_IOC_WRITE << _IOC_DIRSHIFT)
+#define IOC_OUT		(_IOC_READ << _IOC_DIRSHIFT)
+#define IOC_INOUT	((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT)
+#define IOCSIZE_MASK	(_IOC_SIZEMASK << _IOC_SIZESHIFT)
+#define IOCSIZE_SHIFT	(_IOC_SIZESHIFT)
+
+#endif /* _S390_IOCTL_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ioctls.h linux/include/asm-s390x/ioctls.h
--- v2.4.1/linux/include/asm-s390x/ioctls.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ioctls.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,89 @@
+/*
+ *  include/asm-s390/ioctls.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/ioctls.h"
+ */
+
+#ifndef __ARCH_S390_IOCTLS_H__
+#define __ARCH_S390_IOCTLS_H__
+
+#include <asm/ioctl.h>
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define TCGETS		0x5401
+#define TCSETS		0x5402
+#define TCSETSW		0x5403
+#define TCSETSF		0x5404
+#define TCGETA		0x5405
+#define TCSETA		0x5406
+#define TCSETAW		0x5407
+#define TCSETAF		0x5408
+#define TCSBRK		0x5409
+#define TCXONC		0x540A
+#define TCFLSH		0x540B
+#define TIOCEXCL	0x540C
+#define TIOCNXCL	0x540D
+#define TIOCSCTTY	0x540E
+#define TIOCGPGRP	0x540F
+#define TIOCSPGRP	0x5410
+#define TIOCOUTQ	0x5411
+#define TIOCSTI		0x5412
+#define TIOCGWINSZ	0x5413
+#define TIOCSWINSZ	0x5414
+#define TIOCMGET	0x5415
+#define TIOCMBIS	0x5416
+#define TIOCMBIC	0x5417
+#define TIOCMSET	0x5418
+#define TIOCGSOFTCAR	0x5419
+#define TIOCSSOFTCAR	0x541A
+#define FIONREAD	0x541B
+#define TIOCINQ		FIONREAD
+#define TIOCLINUX	0x541C
+#define TIOCCONS	0x541D
+#define TIOCGSERIAL	0x541E
+#define TIOCSSERIAL	0x541F
+#define TIOCPKT		0x5420
+#define FIONBIO		0x5421
+#define TIOCNOTTY	0x5422
+#define TIOCSETD	0x5423
+#define TIOCGETD	0x5424
+#define TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */
+#define TIOCTTYGSTRUCT	0x5426  /* For debugging only */
+#define TIOCSBRK	0x5427  /* BSD compatibility */
+#define TIOCCBRK	0x5428  /* BSD compatibility */
+#define TIOCGSID	0x5429  /* Return the session ID of FD */
+#define TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
+
+#define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
+#define FIOCLEX		0x5451
+#define FIOASYNC	0x5452
+#define TIOCSERCONFIG	0x5453
+#define TIOCSERGWILD	0x5454
+#define TIOCSERSWILD	0x5455
+#define TIOCGLCKTRMIOS	0x5456
+#define TIOCSLCKTRMIOS	0x5457
+#define TIOCSERGSTRUCT	0x5458 /* For debugging only */
+#define TIOCSERGETLSR   0x5459 /* Get line status register */
+#define TIOCSERGETMULTI 0x545A /* Get multiport config  */
+#define TIOCSERSETMULTI 0x545B /* Set multiport config */
+
+#define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
+#define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define FIOQSIZE	0x545E
+
+/* Used for packet mode */
+#define TIOCPKT_DATA		 0
+#define TIOCPKT_FLUSHREAD	 1
+#define TIOCPKT_FLUSHWRITE	 2
+#define TIOCPKT_STOP		 4
+#define TIOCPKT_START		 8
+#define TIOCPKT_NOSTOP		16
+#define TIOCPKT_DOSTOP		32
+
+#define TIOCSER_TEMT    0x01	/* Transmitter physically empty */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ipc.h linux/include/asm-s390x/ipc.h
--- v2.4.1/linux/include/asm-s390x/ipc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ipc.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,39 @@
+/*
+ *  include/asm-s390/ipc.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/ipc.h"
+ */
+
+#ifndef __s390_IPC_H__
+#define __s390_IPC_H__
+
+/* 
+ * These are used to wrap system calls on S390.
+ *
+ * See arch/s390/kernel/sys_s390.c for ugly details..
+ */
+struct ipc_kludge {
+	struct msgbuf *msgp;
+	long msgtyp;
+};
+
+#define SEMOP		 1
+#define SEMGET		 2
+#define SEMCTL		 3
+#define MSGSND		11
+#define MSGRCV		12
+#define MSGGET		13
+#define MSGCTL		14
+#define SHMAT		21
+#define SHMDT		22
+#define SHMGET		23
+#define SHMCTL		24
+
+/* Used by the DIPC package, try and avoid reusing it */
+#define DIPC            25
+
+#define IPCCALL(version,op)	((version)<<16 | (op))
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ipcbuf.h linux/include/asm-s390x/ipcbuf.h
--- v2.4.1/linux/include/asm-s390x/ipcbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ipcbuf.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,28 @@
+#ifndef __S390_IPCBUF_H__
+#define __S390_IPCBUF_H__
+
+/*
+ * The user_ipc_perm structure for S/390 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 32-bit mode_t and seq
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct ipc64_perm
+{
+	__kernel_key_t		key;
+	__kernel_uid32_t	uid;
+	__kernel_gid32_t	gid;
+	__kernel_uid32_t	cuid;
+	__kernel_gid32_t	cgid;
+	__kernel_mode_t		mode;
+	unsigned short		__pad1;
+	unsigned short		seq;
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+#endif /* __S390_IPCBUF_H__ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/irq.h linux/include/asm-s390x/irq.h
--- v2.4.1/linux/include/asm-s390x/irq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/irq.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,962 @@
+#ifndef __irq_h
+#define __irq_h
+
+#include <linux/config.h>
+#ifdef __KERNEL__
+#include <asm/hardirq.h>
+
+/*
+ * How many IRQ's for S390 ?!?
+ */
+#define __MAX_SUBCHANNELS 65536
+#define NR_IRQS           __MAX_SUBCHANNELS
+
+#define LPM_ANYPATH 0xff /* doesn't really belong here, Ingo? */
+
+#define INVALID_STORAGE_AREA ((void *)(-1 - 0x3FFF ))
+
+extern int disable_irq(unsigned int);
+extern int enable_irq(unsigned int);
+
+/*
+ * Interrupt controller descriptor. This is all we need
+ * to describe about the low-level hardware.
+ */
+struct hw_interrupt_type {
+        const __u8   *typename;
+        int         (*handle)(unsigned int irq,
+                              int cpu,
+                              struct pt_regs * regs);
+        int         (*enable) (unsigned int irq);
+        int         (*disable)(unsigned int irq);
+};
+
+/*
+ * Status: reason for being disabled: somebody has
+ * done a "disable_irq()" or we must not re-enter the
+ * already executing irq..
+ */
+#define IRQ_INPROGRESS  1
+#define IRQ_DISABLED    2
+#define IRQ_PENDING     4
+
+/*
+ * path management control word
+ */
+typedef struct {
+      __u32 intparm;      /* interruption parameter */
+      __u32 qf   : 1;     /* qdio facility */
+      __u32 res0 : 1;     /* reserved zeros */
+      __u32 isc  : 3;     /* interruption sublass */
+      __u32 res5 : 3;     /* reserved zeros */
+      __u32 ena  : 1;     /* enabled */
+      __u32 lm   : 2;     /* limit mode */
+      __u32 mme  : 2;     /* measurement-mode enable */
+      __u32 mp   : 1;     /* multipath mode */
+      __u32 tf   : 1;     /* timing facility */
+      __u32 dnv  : 1;     /* device number valid */
+      __u32 dev  : 16;    /* device number */
+      __u8  lpm;          /* logical path mask */
+      __u8  pnom;         /* path not operational mask */
+      __u8  lpum;         /* last path used mask */
+      __u8  pim;          /* path installed mask */
+      __u16 mbi;          /* measurement-block index */
+      __u8  pom;          /* path operational mask */
+      __u8  pam;          /* path available mask */
+      __u8  chpid[8];     /* CHPID 0-7 (if available) */
+      __u32 unused1 : 8;  /* reserved zeros */
+      __u32 st      : 3;  /* subchannel type */
+      __u32 unused2 : 20; /* reserved zeros */
+      __u32 csense  : 1;  /* concurrent sense; can be enabled ...*/
+                          /*  ... per MSCH, however, if facility */
+                          /*  ... is not installed, this results */
+                          /*  ... in an operand exception.       */
+   } __attribute__ ((packed)) pmcw_t;
+
+#endif /* __KERNEL__ */
+/*
+ * subchannel status word
+ */
+typedef struct {
+      __u32 key  : 4; /* subchannel key */
+      __u32 sctl : 1; /* suspend control */
+      __u32 eswf : 1; /* ESW format */
+      __u32 cc   : 2; /* deferred condition code */
+      __u32 fmt  : 1; /* format */
+      __u32 pfch : 1; /* prefetch */
+      __u32 isic : 1; /* initial-status interruption control */
+      __u32 alcc : 1; /* address-limit checking control */
+      __u32 ssi  : 1; /* suppress-suspended interruption */
+      __u32 zcc  : 1; /* zero condition code */
+      __u32 ectl : 1; /* extended control */
+      __u32 pno  : 1;     /* path not operational */
+      __u32 res  : 1;     /* reserved */
+      __u32 fctl : 3;     /* function control */
+      __u32 actl : 7;     /* activity control */
+      __u32 stctl : 5;    /* status control */
+      __u32 cpa;          /* channel program address */
+      __u32 dstat : 8;    /* device status */
+      __u32 cstat : 8;    /* subchannel status */
+      __u32 count : 16;   /* residual count */
+   } __attribute__ ((packed)) scsw_t;
+
+#define SCSW_FCTL_CLEAR_FUNC     0x1
+#define SCSW_FCTL_HALT_FUNC      0x2
+#define SCSW_FCTL_START_FUNC     0x4
+
+#define SCSW_ACTL_SUSPENDED      0x1
+#define SCSW_ACTL_DEVACT         0x2
+#define SCSW_ACTL_SCHACT         0x4
+#define SCSW_ACTL_CLEAR_PEND     0x8
+#define SCSW_ACTL_HALT_PEND      0x10
+#define SCSW_ACTL_START_PEND     0x20
+#define SCSW_ACTL_RESUME_PEND    0x40
+
+#define SCSW_STCTL_STATUS_PEND   0x1
+#define SCSW_STCTL_SEC_STATUS    0x2
+#define SCSW_STCTL_PRIM_STATUS   0x4
+#define SCSW_STCTL_INTER_STATUS  0x8
+#define SCSW_STCTL_ALERT_STATUS  0x10
+
+#define DEV_STAT_ATTENTION       0x80
+#define DEV_STAT_STAT_MOD        0x40
+#define DEV_STAT_CU_END          0x20
+#define DEV_STAT_BUSY            0x10
+#define DEV_STAT_CHN_END         0x08
+#define DEV_STAT_DEV_END         0x04
+#define DEV_STAT_UNIT_CHECK      0x02
+#define DEV_STAT_UNIT_EXCEP      0x01
+
+#define SCHN_STAT_PCI            0x80
+#define SCHN_STAT_INCORR_LEN     0x40
+#define SCHN_STAT_PROG_CHECK     0x20
+#define SCHN_STAT_PROT_CHECK     0x10
+#define SCHN_STAT_CHN_DATA_CHK   0x08
+#define SCHN_STAT_CHN_CTRL_CHK   0x04
+#define SCHN_STAT_INTF_CTRL_CHK  0x02
+#define SCHN_STAT_CHAIN_CHECK    0x01
+
+/*
+ * architectured values for first sense byte
+ */
+#define SNS0_CMD_REJECT         0x80
+#define SNS_CMD_REJECT          SNS0_CMD_REJECT
+#define SNS0_INTERVENTION_REQ   0x40
+#define SNS0_BUS_OUT_CHECK      0x20
+#define SNS0_EQUIPMENT_CHECK    0x10
+#define SNS0_DATA_CHECK         0x08
+#define SNS0_OVERRUN            0x04
+/*                              0x02 reserved */
+#define SNS0_INCOMPL_DOMAIN     0x01
+
+/*
+ * architectured values for second sense byte
+ */
+#define SNS1_PERM_ERR           0x80
+#define SNS1_INV_TRACK_FORMAT   0x40
+#define SNS1_EOC                0x20
+#define SNS1_MESSAGE_TO_OPER    0x10
+#define SNS1_NO_REC_FOUND       0x08
+#define SNS1_FILE_PROTECTED     0x04
+#define SNS1_WRITE_INHIBITED    0x02
+#define SNS1_INPRECISE_END      0x01
+
+/*
+ * architectured values for third sense byte
+ */
+#define SNS2_REQ_INH_WRITE      0x80
+#define SNS2_CORRECTABLE        0x40
+#define SNS2_FIRST_LOG_ERR      0x20
+#define SNS2_ENV_DATA_PRESENT   0x10
+/*                              0x08 reserved */
+#define SNS2_INPRECISE_END      0x04
+/*                              0x02 reserved */
+/*                              0x01 reserved */
+
+#ifdef __KERNEL__
+/*
+ * subchannel information block
+ */
+typedef struct {
+      pmcw_t pmcw;             /* path management control word */
+      scsw_t scsw;             /* subchannel status word */
+      __u8 mda[12];            /* model dependent area */
+   } __attribute__ ((packed,aligned(4))) schib_t;
+#endif /* __KERNEL__ */
+
+typedef struct {
+      __u8  cmd_code;/* command code */
+      __u8  flags;   /* flags, like IDA addressing, etc. */
+      __u16 count;   /* byte count */
+      __u32 cda;     /* data address */
+   } __attribute__ ((packed,aligned(8))) ccw1_t;
+
+#define CCW_FLAG_DC             0x80
+#define CCW_FLAG_CC             0x40
+#define CCW_FLAG_SLI            0x20
+#define CCW_FLAG_SKIP           0x10
+#define CCW_FLAG_PCI            0x08
+#define CCW_FLAG_IDA            0x04
+#define CCW_FLAG_SUSPEND        0x02
+
+#define CCW_CMD_READ_IPL        0x02
+#define CCW_CMD_NOOP            0x03
+#define CCW_CMD_BASIC_SENSE     0x04
+#define CCW_CMD_TIC             0x08
+#define CCW_CMD_SENSE_PGID      0x34
+#define CCW_CMD_SUSPEND_RECONN  0x5B
+#define CCW_CMD_RDC             0x64
+#define CCW_CMD_SET_PGID        0xAF
+#define CCW_CMD_SENSE_ID        0xE4
+#define CCW_CMD_DCTL            0xF3
+
+#ifdef __KERNEL__
+#define SENSE_MAX_COUNT         0x20
+
+/*
+ * architectured values for first sense byte
+ */
+#define SNS0_CMD_REJECT         0x80
+#define SNS_CMD_REJECT          SNS0_CMD_REJECT
+#define SNS0_INTERVENTION_REQ   0x40
+#define SNS0_BUS_OUT_CHECK      0x20
+#define SNS0_EQUIPMENT_CHECK    0x10
+#define SNS0_DATA_CHECK         0x08
+#define SNS0_OVERRUN            0x04
+
+/*
+ * operation request block
+ */
+typedef struct {
+      __u32 intparm;  /* interruption parameter */
+      __u32 key  : 4; /* flags, like key, suspend control, etc. */
+      __u32 spnd : 1; /* suspend control */
+      __u32 res1 : 1; /* reserved */
+      __u32 mod  : 1; /* modification control */
+      __u32 sync : 1; /* synchronize control */
+      __u32 fmt  : 1; /* format control */
+      __u32 pfch : 1; /* prefetch control */
+      __u32 isic : 1; /* initial-status-interruption control */
+      __u32 alcc : 1; /* address-limit-checking control */
+      __u32 ssic : 1; /* suppress-suspended-interr. control */
+      __u32 res2 : 1; /* reserved */
+      __u32 c64  : 1; /* IDAW/QDIO 64 bit control  */
+      __u32 i2k  : 1; /* IDAW 2/4kB block size control */
+      __u32 lpm  : 8; /* logical path mask */
+      __u32 ils  : 1; /* incorrect length */
+      __u32 zero : 6; /* reserved zeros */
+      __u32 orbx : 1; /* ORB extension control */
+      __u32 cpa;      /* channel program address */
+   }  __attribute__ ((packed,aligned(4))) orb_t;
+
+#endif /* __KERNEL__ */
+typedef struct {
+      __u32 res0  : 4;  /* reserved */
+      __u32 pvrf  : 1;  /* path-verification-required flag */
+      __u32 cpt   : 1;  /* channel-path timeout */
+      __u32 fsavf : 1;  /* Failing storage address validity flag */
+      __u32 cons  : 1;  /* concurrent-sense */
+      __u32 res8  : 2;  /* reserved */
+      __u32 scnt  : 6;  /* sense count if cons == 1 */
+      __u32 res16 : 16; /* reserved */
+   } __attribute__ ((packed)) erw_t;
+
+/*
+ * subchannel logout area
+ */
+typedef struct {
+      __u32 res0  : 1;  /* reserved */
+      __u32 esf   : 7;  /* extended status flags */
+      __u32 lpum  : 8;  /* last path used mask */
+      __u32 res16 : 1;  /* reserved */
+      __u32 fvf   : 5;  /* field-validity flags */
+      __u32 sacc  : 2;  /* storage access code */
+      __u32 termc : 2;  /* termination code */
+      __u32 devsc : 1;  /* device-status check */
+      __u32 serr  : 1;  /* secondary error */
+      __u32 ioerr : 1;  /* i/o-error alert */
+      __u32 seqc  : 3;  /* sequence code */
+   } __attribute__ ((packed)) sublog_t ;
+
+/*
+ * Format 0 Extended Status Word (ESW)
+ */
+typedef struct {
+      sublog_t sublog;    /* subchannel logout */
+      erw_t    erw;       /* extended report word */
+      __u32    faddr;     /* failing address */
+      __u32    zeros[2];  /* 2 fullwords of zeros */
+   } __attribute__ ((packed)) esw0_t;
+
+/*
+ * Format 1 Extended Status Word (ESW)
+ */
+typedef struct {
+      __u8  zero0;    /* reserved zeros */
+      __u8  lpum;     /* last path used mask */
+      __u16 zero16;   /* reserved zeros */
+      erw_t erw;      /* extended report word */
+      __u32 zeros[3]; /* 2 fullwords of zeros */
+   } __attribute__ ((packed)) esw1_t;
+
+/*
+ * Format 2 Extended Status Word (ESW)
+ */
+typedef struct {
+      __u8  zero0;    /* reserved zeros */
+      __u8  lpum;     /* last path used mask */
+      __u16 dcti;     /* device-connect-time interval */
+      erw_t erw;      /* extended report word */
+      __u32 zeros[3]; /* 2 fullwords of zeros */
+   } __attribute__ ((packed)) esw2_t;
+
+/*
+ * Format 3 Extended Status Word (ESW)
+ */
+typedef struct {
+      __u8  zero0;    /* reserved zeros */
+      __u8  lpum;     /* last path used mask */
+      __u16 res;      /* reserved */
+      erw_t erw;      /* extended report word */
+      __u32 zeros[3]; /* 2 fullwords of zeros */
+   } __attribute__ ((packed)) esw3_t;
+
+typedef union {
+      esw0_t esw0;
+      esw1_t esw1;
+      esw2_t esw2;
+      esw3_t esw3;
+   } __attribute__ ((packed)) esw_t;
+
+/*
+ * interruption response block
+ */
+typedef struct {
+      scsw_t scsw;             /* subchannel status word */
+      esw_t  esw;              /* extended status word */
+      __u8   ecw[32];          /* extended control word */
+   } irb_t __attribute__ ((packed,aligned(4)));
+#ifdef __KERNEL__
+
+/*
+ * TPI info structure
+ */
+typedef struct {
+	__u32 reserved1  : 16;   /* reserved 0x00000001 */
+	__u32 irq        : 16;   /* aka. subchannel number */
+	__u32 intparm;           /* interruption parameter */
+	__u32 adapter_IO : 1;
+	__u32 reserved2  : 1;
+	__u32 isc        : 3;
+	__u32 reserved3  : 12;
+	__u32 int_type   : 3;
+	__u32 reserved4  : 12;
+   } __attribute__ ((packed)) tpi_info_t;
+
+
+//
+// command information word  (CIW) layout
+//
+typedef struct _ciw {
+   __u32        et       :  2; // entry type
+   __u32        reserved :  2; // reserved
+   __u32        ct       :  4; // command type
+   __u32        cmd      :  8; // command
+   __u32        count    : 16; // count
+   } __attribute__ ((packed)) ciw_t;
+
+#define CIW_TYPE_RCD    0x0    // read configuration data
+#define CIW_TYPE_SII    0x1    // set interface identifier
+#define CIW_TYPE_RNI    0x2    // read node identifier
+
+#define MAX_CIWS 8
+//
+// sense-id response buffer layout
+//
+typedef struct {
+  /* common part */
+      __u8           reserved;     /* always 0x'FF' */
+      __u16          cu_type;      /* control unit type */
+      __u8           cu_model;     /* control unit model */
+      __u16          dev_type;     /* device type */
+      __u8           dev_model;    /* device model */
+      __u8           unused;       /* padding byte */
+  /* extended part */
+      ciw_t    ciw[MAX_CIWS];      /* variable # of CIWs */
+   }  __attribute__ ((packed,aligned(4))) senseid_t;
+
+#endif /* __KERNEL__ */
+/*
+ * sense data
+ */
+typedef struct {
+      __u8          res[32];   /* reserved   */
+      __u8          data[32];  /* sense data */
+   } __attribute__ ((packed)) sense_t;
+
+/*
+ * device status area, to be provided by the device driver
+ *  when calling request_irq() as parameter "dev_id", later
+ *  tied to the "action" control block.
+ *
+ * Note : No data area must be added after union ii or the
+ *         effective devstat size calculation will fail !
+ */
+typedef struct {
+     __u16         devno;    /* device number, aka. "cuu" from irb */
+     unsigned long intparm;  /* interrupt parameter */
+     __u8          cstat;    /* channel status - accumulated */
+     __u8          dstat;    /* device status - accumulated */
+     __u8          lpum;     /* last path used mask from irb */
+     __u8          unused;   /* not used - reserved */
+     unsigned int  flag;     /* flag : see below */
+     __u32         cpa;      /* CCW address from irb at primary status */
+     __u32         rescnt;   /* res. count from irb at primary status */
+     __u32         scnt;     /* sense count, if DEVSTAT_FLAG_SENSE_AVAIL */
+     union {
+        irb_t   irb;         /* interruption response block */
+        sense_t sense;       /* sense information */
+        } ii;                /* interrupt information */
+  } devstat_t;
+
+#define DEVSTAT_FLAG_SENSE_AVAIL   0x00000001
+#define DEVSTAT_NOT_OPER           0x00000002
+#define DEVSTAT_START_FUNCTION     0x00000004
+#define DEVSTAT_HALT_FUNCTION      0x00000008
+#define DEVSTAT_STATUS_PENDING     0x00000010
+#define DEVSTAT_REVALIDATE         0x00000020
+#define DEVSTAT_DEVICE_GONE        0x00000040
+#define DEVSTAT_DEVICE_OWNED       0x00000080
+#define DEVSTAT_CLEAR_FUNCTION     0x00000100
+#define DEVSTAT_PCI                0x00000200
+#define DEVSTAT_SUSPENDED          0x00000400
+#define DEVSTAT_UNKNOWN_DEV        0x00000800
+#define DEVSTAT_FINAL_STATUS       0x80000000
+
+#define DEVINFO_NOT_OPER           DEVSTAT_NOT_OPER
+#define DEVINFO_UNKNOWN_DEV        DEVSTAT_UNKNOWN_DEV
+#define DEVINFO_DEVICE_OWNED       DEVSTAT_DEVICE_OWNED
+#define DEVINFO_QDIO_CAPABLE       0x40000000
+
+#define INTPARM_STATUS_PENDING     0xFFFFFFFF
+#ifdef __KERNEL__
+
+#define IO_INTERRUPT_TYPE          0 /* I/O interrupt type */
+
+typedef  void (* io_handler_func1_t) ( int             irq,
+                                       devstat_t      *devstat,
+                                       struct pt_regs *rgs);
+
+typedef  void (* io_handler_func_t) ( int             irq,
+                                      void           *devstat,
+                                      struct pt_regs *rgs);
+
+typedef  void ( * not_oper_handler_func_t)( int irq,
+                                            int status );
+
+typedef  int  (* adapter_int_handler_t)( __u32 intparm );
+
+struct s390_irqaction {
+	io_handler_func_t  handler;
+	unsigned long      flags;
+	const char        *name;
+	devstat_t         *dev_id;
+};
+
+/*
+ * 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 s390_irqaction    *action;    /* IRQ action list */
+   } irq_desc_t;
+
+typedef struct {
+	__u8  state1    :  2;   /* path state value 1 */
+	__u8  state2    :  2;   /* path state value 2 */
+	__u8  state3    :  1;   /* path state value 3 */
+	__u8  resvd     :  3;   /* reserved */
+	} __attribute__ ((packed)) path_state_t;
+
+typedef struct {
+   union {
+		__u8         fc;   /* SPID function code */
+		path_state_t ps;   /* SNID path state */
+	} inf;
+	__u32 cpu_addr  : 16;   /* CPU address */
+	__u32 cpu_id    : 24;   /* CPU identification */
+	__u32 cpu_model : 16;   /* CPU model */
+	__u32 tod_high;         /* high word TOD clock */
+	} __attribute__ ((packed)) pgid_t;
+
+#define SPID_FUNC_SINGLE_PATH      0x00
+#define SPID_FUNC_MULTI_PATH       0x80
+#define SPID_FUNC_ESTABLISH        0x00
+#define SPID_FUNC_RESIGN           0x40
+#define SPID_FUNC_DISBAND          0x20
+
+#define SNID_STATE1_RESET          0
+#define SNID_STATE1_UNGROUPED      2
+#define SNID_STATE1_GROUPED        3
+
+#define SNID_STATE2_NOT_RESVD      0
+#define SNID_STATE2_RESVD_ELSE     2
+#define SNID_STATE2_RESVD_SELF     3
+
+#define SNID_STATE3_MULTI_PATH     1
+#define SNID_STATE3_SINGLE_PATH    0
+
+/*
+ * Flags used as input parameters for do_IO()
+ */
+#define DOIO_EARLY_NOTIFICATION  0x0001 /* allow for I/O completion ... */
+                                        /* ... notification after ... */
+                                        /* ... primary interrupt status */
+#define DOIO_RETURN_CHAN_END     DOIO_EARLY_NOTIFICATION
+#define DOIO_VALID_LPM           0x0002 /* LPM input parameter is valid */
+#define DOIO_WAIT_FOR_INTERRUPT  0x0004 /* wait synchronously for interrupt */
+#define DOIO_REPORT_ALL          0x0008 /* report all interrupt conditions */
+#define DOIO_ALLOW_SUSPEND       0x0010 /* allow for channel prog. suspend */
+#define DOIO_DENY_PREFETCH       0x0020 /* don't allow for CCW prefetch */
+#define DOIO_SUPPRESS_INTER      0x0040 /* suppress intermediate inter. */
+                                        /* ... for suspended CCWs */
+#define DOIO_TIMEOUT             0x0080 /* 3 secs. timeout for sync. I/O */
+#define DOIO_DONT_CALL_INTHDLR   0x0100 /* don't call interrupt handler */
+
+/*
+ * do_IO()
+ *
+ * Start a S/390 channel program. When the interrupt arrives
+ *  handle_IRQ_event() is called, which eventually calls the
+ *  IRQ handler, either immediately, delayed (dev-end missing,
+ *  or sense required) or never (no IRQ handler registered -
+ *  should never occur, as the IRQ (subchannel ID) should be
+ *  disabled if no handler is present. Depending on the action
+ *  taken, do_IO() returns :  0      - Success
+ *                           -EIO    - Status pending
+ *                                        see : action->dev_id->cstat
+ *                                              action->dev_id->dstat
+ *                           -EBUSY  - Device busy
+ *                           -ENODEV - Device not operational
+ */
+int do_IO( int            irq,          /* IRQ aka. subchannel number */
+           ccw1_t        *cpa,          /* logical channel program address */
+           unsigned long  intparm,      /* interruption parameter */
+           __u8           lpm,          /* logical path mask */
+           unsigned long  flag);        /* flags : see above */
+
+int start_IO( int           irq,       /* IRQ aka. subchannel number */
+              ccw1_t       *cpa,       /* logical channel program address */
+              unsigned long  intparm,   /* interruption parameter */
+              __u8          lpm,       /* logical path mask */
+              unsigned int  flag);     /* flags : see above */
+
+void do_crw_pending( void  );	         /* CRW handler */
+
+int resume_IO( int irq);               /* IRQ aka. subchannel number */
+
+int halt_IO( int           irq,         /* IRQ aka. subchannel number */
+             unsigned long intparm,     /* dummy intparm */
+             unsigned long flag);       /* possible DOIO_WAIT_FOR_INTERRUPT */
+
+int clear_IO( int           irq,         /* IRQ aka. subchannel number */
+              unsigned long intparm,     /* dummy intparm */
+              unsigned long flag);       /* possible DOIO_WAIT_FOR_INTERRUPT */
+
+int process_IRQ( struct pt_regs regs,
+                 unsigned int   irq,
+                 unsigned int   intparm);
+
+
+int enable_cpu_sync_isc ( int irq );
+int disable_cpu_sync_isc( int irq );
+
+typedef struct {
+     int          irq;                  /* irq, aka. subchannel */
+     __u16        devno;                /* device number */
+     unsigned int status;               /* device status */
+     senseid_t    sid_data;             /* senseID data */
+     } s390_dev_info_t;
+
+int get_dev_info( int irq, s390_dev_info_t *);   /* to be eliminated - don't use */
+
+int get_dev_info_by_irq  ( int irq, s390_dev_info_t *pdi);
+int get_dev_info_by_devno( __u16 devno, s390_dev_info_t *pdi);
+
+int          get_irq_by_devno( __u16 devno );
+unsigned int get_devno_by_irq( int irq );
+
+int get_irq_first( void );
+int get_irq_next ( int irq );
+
+int read_dev_chars( int irq, void **buffer, int length );
+int read_conf_data( int irq, void **buffer, int *length, __u8 lpm );
+
+int  s390_DevicePathVerification( int irq, __u8 domask );
+
+int s390_request_irq_special( int                      irq,
+                              io_handler_func_t        io_handler,
+                              not_oper_handler_func_t  not_oper_handler,
+                              unsigned long            irqflags,
+                              const char              *devname,
+                              void                    *dev_id);
+
+extern int handle_IRQ_event( unsigned int irq, int cpu, struct pt_regs *);
+
+extern int set_cons_dev(int irq);
+extern int reset_cons_dev(int irq);
+extern int wait_cons_dev(int irq);
+
+/*
+ * Some S390 specific IO instructions as inline
+ */
+
+extern __inline__ int stsch(int irq, volatile schib_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "STSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int msch(int irq, volatile schib_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "MSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int msch_err(int irq, volatile schib_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "    lgr  1,%1\n"
+                "    msch 0(%2)\n"
+                "0:  ipm  %0\n"
+                "    srl  %0,28\n"
+                "1:\n"
+                ".section .fixup,\"ax\"\n"
+                "2:  l    %0,%3\n"
+                "    jg   1b\n"
+                ".previous\n"
+                ".section __ex_table,\"a\"\n"
+                "   .align 8\n"
+                "   .quad 0b,2b\n"
+                ".previous"
+#else
+                "    lr   1,%1\n"
+                "    msch 0(%2)\n"
+                "0:  ipm  %0\n"
+                "    srl  %0,28\n"
+                "1:\n"
+                ".section .fixup,\"ax\"\n"
+                "2:  l    %0,%3\n"
+                "    bras 1,3f\n"
+                "    .long 1b\n"
+                "3:  l    1,0(1)\n"
+                "    br   1\n"
+                ".previous\n"
+                ".section __ex_table,\"a\"\n"
+                "   .align 4\n"
+                "   .long 0b,2b\n"
+                ".previous"
+#endif
+                : "=d" (ccode)
+                : "r" (irq | 0x10000L), "a" (addr), "i" (__LC_PGM_ILC)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int tsch(int irq, volatile irb_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "TSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int tpi( volatile tpi_info_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "TPI 0(%1)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int ssch(int irq, volatile orb_t *addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "SSCH 0(%2)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L), "a" (addr)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int rsch(int irq)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "RSCH\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int csch(int irq)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "CSCH\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int hsch(int irq)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "HSCH\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (irq | 0x10000L)
+                : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int iac( void)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "IAC 1\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : : "cc", "1" );
+        return ccode;
+}
+
+extern __inline__ int rchp(int chpid)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "LGR 1,%1\n\t"
+#else
+                "LR 1,%1\n\t"
+#endif
+                "RCHP\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "r" (chpid)
+                : "cc", "1" );
+        return ccode;
+}
+
+typedef struct {
+     __u16 vrdcdvno : 16;   /* device number (input) */
+     __u16 vrdclen  : 16;   /* data block length (input) */
+     __u32 vrdcvcla : 8;    /* virtual device class (output) */
+     __u32 vrdcvtyp : 8;    /* virtual device type (output) */
+     __u32 vrdcvsta : 8;    /* virtual device status (output) */
+     __u32 vrdcvfla : 8;    /* virtual device flags (output) */
+     __u32 vrdcrccl : 8;    /* real device class (output) */
+     __u32 vrdccrty : 8;    /* real device type (output) */
+     __u32 vrdccrmd : 8;    /* real device model (output) */
+     __u32 vrdccrft : 8;    /* real device feature (output) */
+     } __attribute__ ((packed,aligned(4))) diag210_t;
+
+void VM_virtual_device_info( __u16      devno,   /* device number */
+                             senseid_t *ps );    /* ptr to senseID data */
+
+extern __inline__ int diag210( diag210_t * addr)
+{
+        int ccode;
+
+        __asm__ __volatile__(
+#ifdef CONFIG_ARCH_S390X
+                "SAM31\n\t"
+                "DIAG %1,0,0x210\n\t"
+                "SAM64\n\t"
+#else
+                "LR 1,%1\n\t"
+                ".long 0x83110210\n\t"
+#endif
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "a" (addr)
+                : "cc" );
+        return ccode;
+}
+
+/*
+ * 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
+ */
+
+void mask_irq(unsigned int irq);
+void unmask_irq(unsigned int irq);
+
+#define MAX_IRQ_SOURCES 128
+
+extern spinlock_t irq_controller_lock;
+
+#ifdef CONFIG_SMP
+
+#include <asm/atomic.h>
+
+static inline void irq_enter(int cpu, unsigned int irq)
+{
+        hardirq_enter(cpu);
+#ifdef CONFIG_ARCH_S390X
+        while (atomic_read(&global_irq_lock) != 0) {
+                eieio();
+        }
+#else
+        while (test_bit(0,&global_irq_lock)) {
+                eieio();
+        }
+#endif
+}
+
+static inline void irq_exit(int cpu, unsigned int irq)
+{
+        hardirq_exit(cpu);
+        release_irqlock(cpu);
+}
+
+
+#else
+
+#define irq_enter(cpu, irq)     (++local_irq_count(cpu))
+#define irq_exit(cpu, irq)      (--local_irq_count(cpu))
+
+#endif
+
+#define __STR(x) #x
+#define STR(x) __STR(x)
+
+#ifdef CONFIG_SMP
+
+/*
+ *      SMP has a few special interrupts for IPI messages
+ */
+
+#endif /* CONFIG_SMP */
+
+/*
+ * x86 profiling function, SMP safe. We might want to do this in
+ * assembly totally?
+ */
+extern char _stext;
+static inline void s390_do_profile (unsigned long addr)
+{
+        if (prof_buffer && current->pid) {
+#ifndef CONFIG_ARCH_S390X
+                addr &= 0x7fffffff;
+#endif
+                addr -= (unsigned long) &_stext;
+                addr >>= 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 (addr > prof_len-1)
+                        addr = prof_len-1;
+                atomic_inc((atomic_t *)&prof_buffer[addr]);
+        }
+}
+
+#include <asm/s390io.h>
+
+#define s390irq_spin_lock(irq) \
+        spin_lock(&(ioinfo[irq]->irq_lock))
+
+#define s390irq_spin_unlock(irq) \
+        spin_unlock(&(ioinfo[irq]->irq_lock))
+
+#define s390irq_spin_lock_irqsave(irq,flags) \
+        spin_lock_irqsave(&(ioinfo[irq]->irq_lock), flags)
+#define s390irq_spin_unlock_irqrestore(irq,flags) \
+        spin_unlock_irqrestore(&(ioinfo[irq]->irq_lock), flags)
+#endif /* __KERNEL__ */
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/irqextras390.h linux/include/asm-s390x/irqextras390.h
--- v2.4.1/linux/include/asm-s390x/irqextras390.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/irqextras390.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,151 @@
+/*
+ *  include/asm-s390/irqextras390.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#ifndef __irqextras390_h
+#define __irqextras390_h
+
+/*
+  irqextras390.h by D.J. Barrow
+  if you are a bitfield fan &  are paranoid that ansi dosen't
+  give hard definitions about the size of an int or long you might
+  prefer these definitions as an alternative.
+
+*/
+
+#include <linux/types.h>
+
+typedef struct 
+{
+      unsigned key:4;
+      unsigned s:1;
+      unsigned l:1;
+      unsigned cc:2;
+      unsigned f:1;
+      unsigned p:1;
+      unsigned i:1;
+      unsigned a:1;
+      unsigned u:1;
+      unsigned z:1;
+      unsigned e:1;
+      unsigned n:1;
+      unsigned zero:1;
+      
+      unsigned fc_start:1;
+      unsigned fc_halt:1;
+      unsigned fc_clear:1;
+      
+      unsigned ac_resume_pending:1;
+      unsigned ac_start_pending:1;
+      unsigned ac_halt_pending:1;
+      unsigned ac_clear_pending:1;
+      unsigned ac_subchannel_active:1;
+      unsigned ac_device_active:1;
+      unsigned ac_suspended:1;
+      
+      unsigned sc_alert:1;
+      unsigned sc_intermediate:1;
+      unsigned sc_primary:1;
+      unsigned sc_seconary:1;
+      unsigned sc_status_pending:1;
+      
+      __u32	   ccw_address;
+      
+      unsigned dev_status_attention:1;
+      unsigned dev_status_modifier:1;
+      unsigned dev_status_control_unit_end:1;
+      unsigned dev_status_busy:1;
+      unsigned dev_status_channel_end:1;
+      unsigned dev_status_device_end:1;
+      unsigned dev_status_unit_check:1;
+      unsigned dev_status_unit_exception:1;
+      
+      unsigned sch_status_program_cont_int:1;
+      unsigned sch_status_incorrect_length:1;
+      unsigned sch_status_program_check:1;
+      unsigned sch_status_protection_check:1;
+      unsigned sch_status_channel_data_check:1;
+      unsigned sch_status_channel_control_check:1;
+      unsigned sch_status_interface_control_check:1;
+      unsigned sch_status_chaining_check:1;
+     
+      __u16	   byte_count;
+} scsw_bits_t __attribute__((packed));
+
+typedef struct
+{
+  __u32      flags;
+  __u32      ccw_address;
+  __u8       dev_status;
+  __u8       sch_status;
+  __u16      byte_count;
+} scsw_words_t __attribute__((packed));
+
+typedef struct
+{
+      __u8     cmd_code;
+      
+      unsigned cd:1;
+      unsigned cc:1;
+      unsigned sli:1;
+      unsigned skip:1;
+      unsigned pci:1;
+      unsigned ida:1;
+      unsigned s:1;
+      unsigned res1:1;
+
+      __u16	count;
+
+      __u32     ccw_data_address;
+} ccw1_bits_t __attribute__((packed,aligned(8)));
+
+typedef struct
+{
+      __u32		interruption_parm;
+      unsigned key:4;
+      unsigned s:1;
+      unsigned res1:3;
+      unsigned f:1;
+      unsigned p:1;
+      unsigned i:1;
+      unsigned a:1;
+      unsigned u:1;
+      __u8	   lpm;
+      unsigned l:1;
+      unsigned res2:7;
+      ccw1_bits_t	*ccw_program_address;
+} orb_bits_t __attribute__((packed));
+
+void fixchannelprogram(orb_bits_t *orbptr);
+void fixccws(ccw1_bits_t *ccwptr);
+enum
+{
+   ccw_write=0x1,
+   ccw_read=0x2,
+   ccw_read_backward=0xc,
+   ccw_control=0x3,
+   ccw_sense=0x4,
+   ccw_sense_id=0xe4,
+   ccw_transfer_in_channel0=0x8,
+   ccw_transfer_in_channel1=0x8,
+   ccw_set_x_mode=0xc3,		// according to uli's lan notes
+   ccw_nop=0x3			// according to uli's notes again
+                                        // n.b. ccw_control clashes with this
+                                        // so I presume its a special case of
+					// control
+};
+
+
+
+#endif
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/lowcore.h linux/include/asm-s390x/lowcore.h
--- v2.4.1/linux/include/asm-s390x/lowcore.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/lowcore.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,196 @@
+/*
+ *  include/asm-s390/lowcore.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#ifndef _ASM_S390_LOWCORE_H
+#define _ASM_S390_LOWCORE_H
+
+#define __LC_EXT_OLD_PSW                0x0130
+#define __LC_SVC_OLD_PSW                0x0140
+#define __LC_PGM_OLD_PSW                0x0150
+#define __LC_MCK_OLD_PSW                0x0160
+#define __LC_IO_OLD_PSW                 0x0170
+#define __LC_EXT_NEW_PSW                0x01b0
+#define __LC_SVC_NEW_PSW                0x01c0
+#define __LC_PGM_NEW_PSW                0x01d0
+#define __LC_MCK_NEW_PSW                0x01e0
+#define __LC_IO_NEW_PSW                 0x01f0
+#define __LC_RETURN_PSW                 0x0200
+#define __LC_SYNC_IO_WORD               0x0210
+#define __LC_EXT_PARAMS                 0x080
+#define __LC_CPU_ADDRESS                0x084
+#define __LC_EXT_INT_CODE               0x086
+#define __LC_SVC_ILC                    0x088
+#define __LC_SVC_INT_CODE               0x08A
+#define __LC_PGM_ILC                    0x08C
+#define __LC_PGM_INT_CODE               0x08E
+#define __LC_TRANS_EXC_ADDR             0x0a8
+#define __LC_SUBCHANNEL_ID              0x0B8
+#define __LC_SUBCHANNEL_NR              0x0BA
+#define __LC_IO_INT_PARM                0x0BC
+#define __LC_IO_INT_WORD                0x0C0
+#define __LC_MCCK_CODE                  0x0E8
+
+#define __LC_SAVE_AREA                  0xC00
+#define __LC_CREGS_SAVE_AREA            0xC80
+#define __LC_AREGS_SAVE_AREA            0xD00
+#define __LC_KERNEL_STACK               0xD40
+#define __LC_KERNEL_LEVEL               0xD48
+#define __LC_IRQ_STAT                   0xD50
+#define __LC_CPUID                      0xD90
+#define __LC_CPUADDR                    0xD98
+#define __LC_IPLDEV                     0xDB8
+
+#define __LC_PANIC_MAGIC                0xE00
+
+
+/* interrupt handler start with all io, external and mcck interrupt disabled */
+
+#define _RESTART_PSW_MASK    0x0000000180000000
+#define _EXT_PSW_MASK        0x0400000180000000
+#define _PGM_PSW_MASK        0x0400000180000000
+#define _SVC_PSW_MASK        0x0400000180000000
+#define _MCCK_PSW_MASK       0x0400000180000000
+#define _IO_PSW_MASK         0x0400000180000000
+#define _USER_PSW_MASK       0x0701C00180000000
+#define _WAIT_PSW_MASK       0x0706000180000000
+#define _DW_PSW_MASK         0x0002000180000000
+
+#define _PRIMARY_MASK        0x0000    /* MASK for SACF                    */
+#define _SECONDARY_MASK      0x0100    /* MASK for SACF                    */
+#define _ACCESS_MASK         0x0200    /* MASK for SACF                    */
+#define _HOME_MASK           0x0300    /* MASK for SACF                    */
+
+#define _PSW_PRIM_SPACE_MODE 0x0000000000000000
+#define _PSW_SEC_SPACE_MODE  0x0000800000000000
+#define _PSW_ACC_REG_MODE    0x0000400000000000
+#define _PSW_HOME_SPACE_MODE 0x0000C00000000000
+
+#define _PSW_WAIT_MASK_BIT   0x0002000000000000
+#define _PSW_IO_MASK_BIT     0x0200000000000000
+#define _PSW_IO_WAIT         0x0202000000000000
+
+#ifndef __ASSEMBLY__
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <linux/types.h>
+#include <asm/atomic.h>
+#include <asm/sigp.h>
+
+
+struct _lowcore
+{
+        /* prefix area: defined by architecture */
+	__u32        ccw1[2];                  /* 0x000 */
+	__u32        ccw2[4];                  /* 0x008 */
+	__u8         pad1[0x80-0x18];          /* 0x018 */
+	__u32        ext_params;               /* 0x080 */
+	__u16        cpu_addr;                 /* 0x084 */
+	__u16        ext_int_code;             /* 0x086 */
+        __u16        svc_ilc;                  /* 0x088 */
+        __u16        scv_code;                 /* 0x08a */
+        __u16        pgm_ilc;                  /* 0x08c */
+        __u16        pgm_code;                 /* 0x08e */
+	__u32        data_exc_code;            /* 0x090 */
+	__u16        mon_class_num;            /* 0x094 */
+	__u16        per_perc_atmid;           /* 0x096 */
+	addr_t       per_address;              /* 0x098 */
+	__u8         exc_access_id;            /* 0x0a0 */
+	__u8         per_access_id;            /* 0x0a1 */
+	__u8         op_access_id;             /* 0x0a2 */
+	__u8         ar_access_id;             /* 0x0a3 */
+	__u8         pad2[0xA8-0xA4];          /* 0x0a4 */
+	addr_t       trans_exc_code;           /* 0x0A0 */
+	addr_t       monitor_code;             /* 0x09c */
+	__u16        subchannel_id;            /* 0x0b8 */
+	__u16        subchannel_nr;            /* 0x0ba */
+	__u32        io_int_parm;              /* 0x0bc */
+	__u32        io_int_word;              /* 0x0c0 */
+	__u8         pad3[0xc8-0xc4];          /* 0x0c4 */
+	__u32        stfl_fac_list;            /* 0x0c8 */
+	__u8         pad4[0xe8-0xcc];          /* 0x0cc */
+	__u32        mcck_interuption_code[2]; /* 0x0e8 */
+	__u8         pad5[0xf4-0xf0];          /* 0x0f0 */
+	__u32        external_damage_code;     /* 0x0f4 */
+	addr_t       failing_storage_address;  /* 0x0f8 */
+	__u8         pad6[0x120-0x100];        /* 0x100 */
+	psw_t        restart_old_psw;          /* 0x120 */
+	psw_t        external_old_psw;         /* 0x130 */
+	psw_t        svc_old_psw;              /* 0x140 */
+	psw_t        program_old_psw;          /* 0x150 */
+	psw_t        mcck_old_psw;             /* 0x160 */
+	psw_t        io_old_psw;               /* 0x170 */
+	__u8         pad7[0x1a0-0x180];        /* 0x180 */
+	psw_t        restart_psw;              /* 0x1a0 */
+	psw_t        external_new_psw;         /* 0x1b0 */
+	psw_t        svc_new_psw;              /* 0x1c0 */
+	psw_t        program_new_psw;          /* 0x1d0 */
+	psw_t        mcck_new_psw;             /* 0x1e0 */
+	psw_t        io_new_psw;               /* 0x1f0 */
+        psw_t        return_psw;               /* 0x200 */
+	__u32        sync_io_word;             /* 0x210 */
+        __u8         pad8[0xc00-0x214];        /* 0x214 */
+        /* System info area */
+	__u64        save_area[16];            /* 0xc00 */
+	__u64        cregs_save_area[16];      /* 0xc80 */
+	__u32        access_regs_save_area[16];/* 0xd00 */
+ 	__u64        kernel_stack;             /* 0xd40 */
+	__u64        kernel_level;             /* 0xd48 */
+	/* entry.S sensitive area start */
+	/* Next 6 words are the s390 equivalent of irq_stat */
+	__u32        __softirq_active;         /* 0xd50 */
+	__u32        __softirq_mask;           /* 0xd54 */
+	__u32        __local_irq_count;        /* 0xd58 */
+	__u32        __local_bh_count;         /* 0xd5c */
+	__u32        __syscall_count;          /* 0xd60 */
+	__u8         pad10[0xd80-0xd64];       /* 0xd64 */
+	struct       cpuinfo_S390 cpu_data;    /* 0xd80 */
+	__u32        ipl_device;               /* 0xdb8 */
+	__u32        pad13;                    /* 0xdbc was lsw word of ipl_device until a bug was found DJB */
+	/* entry.S sensitive area end */
+
+        /* SMP info area: defined by DJB */
+        __u64        jiffy_timer_cc;           /* 0xdc0 */
+	__u64        ext_call_fast;            /* 0xdc8 */
+	__u64        ext_call_queue;           /* 0xdd0 */
+        __u64        ext_call_count;           /* 0xdd8 */
+
+        __u8         pad11[0xe00-0xde0];       /* 0xde0 */
+
+        /* 0xe00 is used as indicator for dump tools */
+        /* whether the kernel died with panic() or not */
+        __u32        panic_magic;              /* 0xe00 */
+
+        /* Align to the top 1k of prefix area */
+	__u8         pad12[0x1000-0xe04];      /* 0xe04 */
+} __attribute__((packed)); /* End structure*/
+
+extern __inline__ void set_prefix(__u32 address)
+{
+        __asm__ __volatile__ ("spx %0" : : "m" (address) : "memory" );
+}
+
+#define S390_lowcore (*((struct _lowcore *) 0))
+extern struct _lowcore *lowcore_ptr[];
+
+#ifndef CONFIG_SMP
+#define get_cpu_lowcore(cpu)    S390_lowcore
+#define safe_get_cpu_lowcore(cpu) S390_lowcore
+#else
+#define get_cpu_lowcore(cpu)    (*lowcore_ptr[cpu])
+#define safe_get_cpu_lowcore(cpu) \
+        ((cpu)==smp_processor_id() ? S390_lowcore:(*lowcore_ptr[(cpu)]))
+#endif
+#endif /* __ASSEMBLY__ */
+
+#define __PANIC_MAGIC           0xDEADC0DE
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/major.h linux/include/asm-s390x/major.h
--- v2.4.1/linux/include/asm-s390x/major.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/major.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,150 @@
+#ifndef _LINUX_MAJOR_H
+#define _LINUX_MAJOR_H
+
+/*
+ * This file has definitions for major device numbers.
+ * For the device number assignments, see Documentation/devices.txt.
+ */
+
+/* limits */
+
+/*
+ * Important: Don't change this to 256.  Major number 255 is and must be
+ * reserved for future expansion into a larger dev_t space.
+ */
+#define MAX_CHRDEV	255
+#define MAX_BLKDEV	255
+
+#define UNNAMED_MAJOR	0
+#define MEM_MAJOR	1
+#define RAMDISK_MAJOR	1
+#define FLOPPY_MAJOR	2
+#define PTY_MASTER_MAJOR 2
+#define IDE0_MAJOR	3
+#define PTY_SLAVE_MAJOR 3
+#define HD_MAJOR	IDE0_MAJOR
+#define TTY_MAJOR	4
+#define TTYAUX_MAJOR	5
+#define LP_MAJOR	6
+#define VCS_MAJOR	7
+#define LOOP_MAJOR	7
+#define SCSI_DISK0_MAJOR 8
+#define SCSI_TAPE_MAJOR	9
+#define MD_MAJOR        9
+#define MISC_MAJOR	10
+#define SCSI_CDROM_MAJOR 11
+#define QIC02_TAPE_MAJOR 12
+#define XT_DISK_MAJOR	13
+#define SOUND_MAJOR	14
+#define CDU31A_CDROM_MAJOR 15
+#define JOYSTICK_MAJOR	15
+#define GOLDSTAR_CDROM_MAJOR 16
+#define OPTICS_CDROM_MAJOR 17
+#define SANYO_CDROM_MAJOR 18
+#define CYCLADES_MAJOR  19
+#define CYCLADESAUX_MAJOR 20
+#define MITSUMI_X_CDROM_MAJOR 20
+#define MFM_ACORN_MAJOR 21	/* ARM Linux /dev/mfm */
+#define SCSI_GENERIC_MAJOR 21
+#define Z8530_MAJOR 34
+#define DIGI_MAJOR 23
+#define IDE1_MAJOR	22
+#define DIGICU_MAJOR 22
+#define MITSUMI_CDROM_MAJOR 23
+#define CDU535_CDROM_MAJOR 24
+#define STL_SERIALMAJOR 24
+#define MATSUSHITA_CDROM_MAJOR 25
+#define STL_CALLOUTMAJOR 25
+#define MATSUSHITA_CDROM2_MAJOR 26
+#define QIC117_TAPE_MAJOR 27
+#define MATSUSHITA_CDROM3_MAJOR 27
+#define MATSUSHITA_CDROM4_MAJOR 28
+#define STL_SIOMEMMAJOR 28
+#define ACSI_MAJOR	28
+#define AZTECH_CDROM_MAJOR 29
+#define GRAPHDEV_MAJOR	29	/* SparcLinux & Linux/68k /dev/fb */
+#define SHMIQ_MAJOR	85	/* Linux/mips, SGI /dev/shmiq */
+#define CM206_CDROM_MAJOR 32
+#define IDE2_MAJOR	33
+#define IDE3_MAJOR	34
+#define NETLINK_MAJOR	36
+#define PS2ESDI_MAJOR	36
+#define IDETAPE_MAJOR	37
+#define Z2RAM_MAJOR	37
+#define APBLOCK_MAJOR   38   /* AP1000 Block device */
+#define DDV_MAJOR       39   /* AP1000 DDV block device */
+#define NBD_MAJOR	43   /* Network block device	*/
+#define RISCOM8_NORMAL_MAJOR 48
+#define DAC960_MAJOR	48	/* 48..55 */
+#define RISCOM8_CALLOUT_MAJOR 49
+#define MKISS_MAJOR	55
+#define DSP56K_MAJOR    55   /* DSP56001 processor device */
+
+#define IDE4_MAJOR	56
+#define IDE5_MAJOR	57
+
+#define SCSI_DISK1_MAJOR	65
+#define SCSI_DISK2_MAJOR	66
+#define SCSI_DISK3_MAJOR	67
+#define SCSI_DISK4_MAJOR	68
+#define SCSI_DISK5_MAJOR	69
+#define SCSI_DISK6_MAJOR	70
+#define SCSI_DISK7_MAJOR	71
+
+
+#define LVM_BLK_MAJOR	58	/* Logical Volume Manager */
+
+#define COMPAQ_SMART2_MAJOR	72
+#define COMPAQ_SMART2_MAJOR1	73
+#define COMPAQ_SMART2_MAJOR2	74
+#define COMPAQ_SMART2_MAJOR3	75
+#define COMPAQ_SMART2_MAJOR4	76
+#define COMPAQ_SMART2_MAJOR5	77
+#define COMPAQ_SMART2_MAJOR6	78
+#define COMPAQ_SMART2_MAJOR7	79
+
+#define SPECIALIX_NORMAL_MAJOR 75
+#define SPECIALIX_CALLOUT_MAJOR 76
+
+#define DASD_MAJOR      94
+
+#define LVM_CHAR_MAJOR	109	/* Logical Volume Manager */
+
+#define MDISK_MAJOR     64
+
+#define I2O_MAJOR		80	/* 80->87 */
+
+#define IDE6_MAJOR	88
+#define IDE7_MAJOR	89
+#define IDE8_MAJOR	90
+#define IDE9_MAJOR	91
+
+#define AURORA_MAJOR 79
+
+#define RTF_MAJOR	150
+#define RAW_MAJOR	162
+
+#define USB_ACM_MAJOR		166
+#define USB_ACM_AUX_MAJOR	167
+#define USB_CHAR_MAJOR		180
+
+#define UNIX98_PTY_MASTER_MAJOR	128
+#define UNIX98_PTY_MAJOR_COUNT	8
+#define UNIX98_PTY_SLAVE_MAJOR	(UNIX98_PTY_MASTER_MAJOR+UNIX98_PTY_MAJOR_COUNT)
+
+/*
+ * Tests for SCSI devices.
+ */
+
+#define SCSI_DISK_MAJOR(M) ((M) == SCSI_DISK0_MAJOR || \
+  ((M) >= SCSI_DISK1_MAJOR && (M) <= SCSI_DISK7_MAJOR))
+  
+#define SCSI_BLK_MAJOR(M) \
+  (SCSI_DISK_MAJOR(M)	\
+   || (M) == SCSI_CDROM_MAJOR)
+
+static __inline__ int scsi_blk_major(int m) {
+	return SCSI_BLK_MAJOR(m);
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/mathemu.h linux/include/asm-s390x/mathemu.h
--- v2.4.1/linux/include/asm-s390x/mathemu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/mathemu.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,48 @@
+/*
+ *  arch/s390/kernel/mathemu.h
+ *    IEEE floating point emulation.
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+#ifndef __MATHEMU__
+#define __MATHEMU__
+
+extern int math_emu_b3(__u8 *, struct pt_regs *);
+extern int math_emu_ed(__u8 *, struct pt_regs *);
+extern void math_emu_ldr(__u8 *);
+extern void math_emu_ler(__u8 *);
+extern void math_emu_std(__u8 *, struct pt_regs *);
+extern void math_emu_ld(__u8 *, struct pt_regs *);
+extern void math_emu_ste(__u8 *, struct pt_regs *);
+extern void math_emu_le(__u8 *, struct pt_regs *);
+extern int math_emu_lfpc(__u8 *, struct pt_regs *);
+extern int math_emu_stfpc(__u8 *, struct pt_regs *);
+extern int math_emu_srnm(__u8 *, struct pt_regs *);
+
+
+extern __u64 __adddf3(__u64,__u64);
+extern __u64 __subdf3(__u64,__u64);
+extern __u64 __muldf3(__u64,__u64);
+extern __u64 __divdf3(__u64,__u64);
+extern long  __cmpdf2(__u64,__u64);
+extern __u64 __negdf2(__u64);
+extern __u64 __absdf2(__u64);
+extern __u32 __addsf3(__u32,__u32);
+extern __u32 __subsf3(__u32,__u32);
+extern __u32 __mulsf3(__u32,__u32);
+extern __u32 __divsf3(__u32,__u32);
+extern __u32 __negsf2(__u32);
+extern __u32 __abssf2(__u32);
+extern long  __cmpsf2(__u32,__u32);
+extern __u32 __truncdfsf2(__u64);
+extern __u32 __fixsfsi(__u32);
+extern __u32 __fixdfsi(__u64);
+extern __u64  __floatsidf(__u32);
+extern __u32  __floatsisf(__u32);
+extern __u64  __extendsfdf2(__u32);
+
+#endif                                 /* __MATHEMU__                      */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/misc390.h linux/include/asm-s390x/misc390.h
--- v2.4.1/linux/include/asm-s390x/misc390.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/misc390.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,15 @@
+/*
+ *  include/asm-s390/misc390.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#define	allocaligned2(type,name,number,align)				\
+   __u8	name##buff[(sizeof(type)*(number+1))-1]; 	                \
+   type	*name=(type *)(((__u32)(&name##buff[align-1]))&(-align))
+
+#define	allocaligned(type,name,number)  allocaligned2(type,name,number,__alignof__(type))
+
+extern void s390_daemonize(char *name,unsigned long mask,int use_init_fs);
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/mman.h linux/include/asm-s390x/mman.h
--- v2.4.1/linux/include/asm-s390x/mman.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/mman.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,46 @@
+/*
+ *  include/asm-s390/mman.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/mman.h"
+ */
+
+#ifndef __S390_MMAN_H__
+#define __S390_MMAN_H__
+
+#define PROT_READ	0x1		/* page can be read */
+#define PROT_WRITE	0x2		/* page can be written */
+#define PROT_EXEC	0x4		/* page can be executed */
+#define PROT_NONE	0x0		/* page can not be accessed */
+
+#define MAP_SHARED	0x01		/* Share changes */
+#define MAP_PRIVATE	0x02		/* Changes are private */
+#define MAP_TYPE	0x0f		/* Mask for type of mapping */
+#define MAP_FIXED	0x10		/* Interpret addr exactly */
+#define MAP_ANONYMOUS	0x20		/* don't use a file */
+
+#define MAP_GROWSDOWN	0x0100		/* stack-like segment */
+#define MAP_DENYWRITE	0x0800		/* ETXTBSY */
+#define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
+#define MAP_LOCKED	0x2000		/* pages are locked */
+#define MAP_NORESERVE	0x4000		/* don't check for reservations */
+
+#define MS_ASYNC	1		/* sync memory asynchronously */
+#define MS_INVALIDATE	2		/* invalidate the caches */
+#define MS_SYNC		4		/* synchronous memory sync */
+
+#define MCL_CURRENT	1		/* lock all current mappings */
+#define MCL_FUTURE	2		/* lock all future mappings */
+
+#define MADV_NORMAL    0x0              /* default page-in behavior */
+#define MADV_RANDOM    0x1              /* page-in minimum required */
+#define MADV_SEQUENTIAL        0x2             /* read-ahead aggressively */
+#define MADV_WILLNEED  0x3              /* pre-fault pages */
+#define MADV_DONTNEED  0x4              /* discard these pages */
+
+/* compatibility flags */
+#define MAP_ANON	MAP_ANONYMOUS
+#define MAP_FILE	0
+
+#endif /* __S390_MMAN_H__ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/mmu.h linux/include/asm-s390x/mmu.h
--- v2.4.1/linux/include/asm-s390x/mmu.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/mmu.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,7 @@
+#ifndef __MMU_H
+#define __MMU_H
+
+/* Default "unsigned long" context */
+typedef unsigned long mm_context_t;
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/mmu_context.h linux/include/asm-s390x/mmu_context.h
--- v2.4.1/linux/include/asm-s390x/mmu_context.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/mmu_context.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,45 @@
+/*
+ *  include/asm-s390/mmu_context.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/mmu_context.h"
+ */
+
+#ifndef __S390_MMU_CONTEXT_H
+#define __S390_MMU_CONTEXT_H
+
+/*
+ * get a new mmu context.. S390 don't know about contexts.
+ */
+#define init_new_context(tsk,mm)        0
+
+#define destroy_context(mm)             flush_tlb_mm(mm)
+
+static inline void enter_lazy_tlb(struct mm_struct *mm,
+                                  struct task_struct *tsk, unsigned cpu)
+{
+}
+
+static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
+                             struct task_struct *tsk, unsigned cpu)
+{
+        unsigned long pgd;
+
+        if (prev != next) {
+                pgd = (__pa(next->pgd)&PAGE_MASK) | (_REGION_TABLE|USER_STD_MASK);
+                /* Load page tables */
+                asm volatile("    lctlg 7,7,%0\n"   /* secondary space */
+                             "    lctlg 13,13,%0\n" /* home space */
+                             : : "m" (pgd) );
+        }
+	set_bit(cpu, &next->cpu_vm_mask);
+}
+
+extern inline void activate_mm(struct mm_struct *prev,
+                               struct mm_struct *next)
+{
+        switch_mm(prev, next, current, smp_processor_id());
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/module.h linux/include/asm-s390x/module.h
--- v2.4.1/linux/include/asm-s390x/module.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/module.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,11 @@
+#ifndef _ASM_S390_MODULE_H
+#define _ASM_S390_MODULE_H
+/*
+ * This file contains the s390 architecture specific module code.
+ */
+
+#define module_map(x)		vmalloc(x)
+#define module_unmap(x)		vfree(x)
+#define module_arch_init(x)	(0)
+
+#endif /* _ASM_S390_MODULE_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/msgbuf.h linux/include/asm-s390x/msgbuf.h
--- v2.4.1/linux/include/asm-s390x/msgbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/msgbuf.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,27 @@
+#ifndef _S390_MSGBUF_H
+#define _S390_MSGBUF_H
+
+/* 
+ * The msqid64_ds structure for S/390 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 64-bit values
+ */
+
+struct msqid64_ds {
+	struct ipc64_perm msg_perm;
+	__kernel_time_t msg_stime;	/* last msgsnd time */
+	__kernel_time_t msg_rtime;	/* last msgrcv time */
+	__kernel_time_t msg_ctime;	/* last change time */
+	unsigned long  msg_cbytes;	/* current number of bytes on queue */
+	unsigned long  msg_qnum;	/* number of messages in queue */
+	unsigned long  msg_qbytes;	/* max number of bytes on queue */
+	__kernel_pid_t msg_lspid;	/* pid of last msgsnd */
+	__kernel_pid_t msg_lrpid;	/* last receive pid */
+	unsigned long  __unused1;
+	unsigned long  __unused2;
+};
+
+#endif /* _S390_MSGBUF_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/namei.h linux/include/asm-s390x/namei.h
--- v2.4.1/linux/include/asm-s390x/namei.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/namei.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,21 @@
+/*
+ *  include/asm-s390/namei.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/namei.h"
+ *
+ *  Included from linux/fs/namei.c
+ */
+
+#ifndef __S390_NAMEI_H
+#define __S390_NAMEI_H
+
+/* This dummy routine maybe changed to something useful
+ * for /usr/gnemul/ emulation stuff.
+ * Look at asm-sparc/namei.h for details.
+ */
+
+#define __emul_prefix() NULL
+
+#endif /* __S390_NAMEI_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/page.h linux/include/asm-s390x/page.h
--- v2.4.1/linux/include/asm-s390x/page.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/page.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,94 @@
+/*
+ *  include/asm-s390/page.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com)
+ */
+
+#ifndef _S390_PAGE_H
+#define _S390_PAGE_H
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT      12
+#define PAGE_SIZE       (1UL << PAGE_SHIFT)
+#define PAGE_MASK       (~(PAGE_SIZE-1))
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+/*
+ * gcc uses builtin, i.e. MVCLE for both operations
+ */
+
+#define clear_page(page)        memset((void *)(page), 0, PAGE_SIZE)
+#define copy_page(to,from)      memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+#define clear_user_page(page, vaddr)    clear_page(page)
+#define copy_user_page(to, from, vaddr) copy_page(to, from)
+
+#define BUG() do { \
+        printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \
+        __asm__ __volatile__(".long 0"); \
+} while (0)                                       
+
+#define PAGE_BUG(page) do { \
+        BUG(); \
+} while (0)                      
+
+/* Pure 2^n version of get_order */
+extern __inline__ int get_order(unsigned long size)
+{
+        int order;
+
+        size = (size-1) >> (PAGE_SHIFT-1);
+        order = -1;
+        do {
+                size >>= 1;
+                order++;
+        } while (size);
+        return order;
+}
+
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { 
+        unsigned long pmd0;
+        unsigned long pmd1; 
+        } pmd_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pmd_val(x)      ((x).pmd0)
+#define pmd_val1(x)     ((x).pmd1)
+#define pgd_val(x)      ((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) } )
+#define __pmd(x)        ((pmd_t) { (x) } )
+#define __pgd(x)        ((pgd_t) { (x) } )
+#define __pgprot(x)     ((pgprot_t) { (x) } )
+
+#endif                                 /* !__ASSEMBLY__                    */
+
+/* to align the pointer to the (next) page boundary */
+#define PAGE_ALIGN(addr)        (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+/*
+ *
+ *
+ */
+
+#define __PAGE_OFFSET           0x0UL
+#define PAGE_OFFSET             0x0UL
+#define __pa(x)                 (unsigned long)(x)
+#define __va(x)                 (void *)(x)
+#define virt_to_page(kaddr)	(mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+#define VALID_PAGE(page)	((page - mem_map) < max_mapnr)
+
+#endif                                 /* __KERNEL__                       */
+
+#endif                                 /* _S390_PAGE_H                     */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/param.h linux/include/asm-s390x/param.h
--- v2.4.1/linux/include/asm-s390x/param.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/param.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,32 @@
+/*
+ *  include/asm-s390/param.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/param.h"
+ */
+
+#ifndef _ASMS390_PARAM_H
+#define _ASMS390_PARAM_H
+
+#ifndef HZ
+#define HZ 100
+#endif
+
+#define EXEC_PAGESIZE	4096
+
+#ifndef NGROUPS
+#define NGROUPS		32
+#endif
+
+#ifndef NOGROUP
+#define NOGROUP		(-1)
+#endif
+
+#define MAXHOSTNAMELEN	64	/* max length of hostname */
+
+#ifdef __KERNEL__
+# define CLOCKS_PER_SEC		HZ	/* frequency at which times() counts */
+#endif
+                                 
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/pgalloc.h linux/include/asm-s390x/pgalloc.h
--- v2.4.1/linux/include/asm-s390x/pgalloc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/pgalloc.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,315 @@
+/*
+ *  include/asm-s390/pgalloc.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com)
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/pgalloc.h"
+ *    Copyright (C) 1994  Linus Torvalds
+ */
+
+#ifndef _S390_PGALLOC_H
+#define _S390_PGALLOC_H
+
+#include <linux/config.h>
+#include <asm/processor.h>
+#include <linux/threads.h>
+
+#define pgd_quicklist (S390_lowcore.cpu_data.pgd_quick)
+#define pmd_quicklist (S390_lowcore.cpu_data.pmd_quick)
+#define pte_quicklist (S390_lowcore.cpu_data.pte_quick)
+#define pgtable_cache_size (S390_lowcore.cpu_data.pgtable_cache_sz)
+
+/*
+ * Allocate and free page tables. The xxx_kernel() versions are
+ * used to allocate a kernel page table - this turns on ASN bits
+ * if any.
+ */
+
+/*
+ * page directory allocation/free routines.
+ */
+extern __inline__ pgd_t *get_pgd_slow (void)
+{
+        int i;
+	pgd_t *ret = (pgd_t *)__get_free_pages(GFP_KERNEL,2);
+	if (ret)
+	        for (i = 0; i < PTRS_PER_PGD; i++) 
+	                pgd_clear(ret + i);
+	return ret;
+}
+
+extern __inline__ pgd_t *get_pgd_fast (void)
+{
+	unsigned long *ret = pgd_quicklist;
+
+	if (ret != NULL) {
+		pgd_quicklist = (unsigned long *)(*ret);
+		ret[0] = ret[1];
+		pgtable_cache_size -= 4;
+	}
+	return (pgd_t *) ret;
+}
+
+extern __inline__ pgd_t *pgd_alloc (void)
+{
+	pgd_t *pgd;
+
+	pgd = get_pgd_fast();
+	if (!pgd)
+		pgd = get_pgd_slow();
+	return pgd;
+}
+
+extern __inline__ void free_pgd_fast (pgd_t *pgd)
+{
+	*(unsigned long *) pgd = (unsigned long) pgd_quicklist;
+	pgd_quicklist = (unsigned long *) pgd;
+	pgtable_cache_size += 4;
+}
+
+extern __inline__ void free_pgd_slow (pgd_t *pgd)
+{
+        free_pages((unsigned long) pgd, 2);
+}
+
+#define pgd_free(pgd)		free_pgd_fast(pgd)
+
+/*
+ * page middle directory allocation/free routines.
+ */
+extern pmd_t empty_bad_pmd_table[];
+extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address);
+
+extern __inline__ pmd_t *get_pmd_fast (void)
+{
+	unsigned long *ret = (unsigned long *) pmd_quicklist;
+	if (ret != NULL) {
+		pmd_quicklist = (unsigned long *)(*ret);
+		ret[0] = ret[1];
+		pgtable_cache_size -= 4;
+	}
+	return (pmd_t *) ret;
+}
+
+extern __inline__ void free_pmd_fast (pmd_t *pmd)
+{
+	if (pmd == empty_bad_pmd_table)
+		return;
+	*(unsigned long *) pmd = (unsigned long) pmd_quicklist;
+	pmd_quicklist = (unsigned long *) pmd;
+	pgtable_cache_size += 4;
+}
+
+extern __inline__ void free_pmd_slow (pmd_t *pmd)
+{
+	free_pages((unsigned long) pmd, 2);
+}
+
+extern __inline__ pmd_t *pmd_alloc (pgd_t *pgd, unsigned long vmaddr)
+{
+	unsigned long offset;
+
+	offset = (vmaddr >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
+	if (pgd_none(*pgd)) {
+		pmd_t *pmd_page = get_pmd_fast();
+
+		if (!pmd_page)
+			return get_pmd_slow(pgd, offset);
+                pgd_set(pgd, pmd_page);
+                return pmd_page + offset;
+	}
+	if (pgd_bad(*pgd))
+		BUG();
+	return (pmd_t *) pgd_page(*pgd) + offset;
+}
+
+#define pmd_alloc_kernel(pgd, addr)	pmd_alloc(pgd, addr)
+#define pmd_free_kernel(pmd)	free_pmd_fast(pmd)
+#define pmd_free(pmd)		free_pmd_fast(pmd)
+
+/*
+ * page table entry allocation/free routines.
+ */
+extern pte_t empty_bad_pte_table[];
+extern pte_t *get_pte_slow (pmd_t *pmd, unsigned long address_preadjusted);
+
+extern __inline__ pte_t *get_pte_fast (void)
+{
+	unsigned long *ret = (unsigned long *) pte_quicklist;
+
+	if (ret != NULL) {
+		pte_quicklist = (unsigned long *)(*ret);
+		ret[0] = ret[1];
+		pgtable_cache_size--;
+	}
+	return (pte_t *) ret;
+}
+
+extern __inline__ void free_pte_fast (pte_t *pte)
+{
+	if (pte == empty_bad_pte_table)
+		return;
+	*(unsigned long *) pte = (unsigned long) pte_quicklist;
+	pte_quicklist = (unsigned long *) pte;
+	pgtable_cache_size++;
+}
+
+extern __inline__ void free_pte_slow (pte_t *pte)
+{
+        free_page((unsigned long) pte);
+}
+
+extern __inline__ pte_t *pte_alloc (pmd_t *pmd, unsigned long vmaddr)
+{
+	unsigned long offset;
+
+	offset = (vmaddr >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
+	if (pmd_none(*pmd)) {
+		pte_t *pte_page = get_pte_fast();
+
+		if (!pte_page)
+			return get_pte_slow(pmd, offset);
+		pmd_set(pmd, pte_page);
+		return pte_page + offset;
+	}
+	if (pmd_bad(*pmd))
+		BUG();
+	return (pte_t *) pmd_page(*pmd) + offset;
+}
+
+#define pte_alloc_kernel(pmd, addr)	pte_alloc(pmd, addr)
+#define pte_free_kernel(pte)	free_pte_fast(pte)
+#define pte_free(pte)		free_pte_fast(pte)
+
+extern int do_check_pgt_cache (int, int);
+
+/*
+ * This establishes kernel virtual mappings (e.g., as a result of a
+ * vmalloc call).  Since s390-esame uses a separate kernel page table,
+ * there is nothing to do here... :)
+ */
+#define set_pgdir(vmaddr, entry)	do { } while(0)
+
+/*
+ * TLB flushing:
+ *
+ *  - flush_tlb() flushes the current mm struct TLBs
+ *  - flush_tlb_all() flushes all processes TLBs 
+ *    called only from vmalloc/vfree
+ *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ *  - flush_tlb_page(vma, vmaddr) flushes one page
+ *  - flush_tlb_range(mm, start, end) flushes a range of pages
+ *  - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ */
+
+/*
+ * S/390 has three ways of flushing TLBs
+ * 'ptlb' does a flush of the local processor
+ * 'csp' flushes the TLBs on all PUs of a SMP
+ * 'ipte' invalidates a pte in a page table and flushes that out of
+ * the TLBs of all PUs of a SMP
+ */
+
+#define local_flush_tlb() \
+do {  __asm__ __volatile__("ptlb": : :"memory"); } while (0)
+
+
+#ifndef CONFIG_SMP
+
+/*
+ * We always need to flush, since s390 does not flush tlb
+ * on each context switch
+ */
+
+#define flush_tlb()			local_flush_tlb()
+#define flush_tlb_all()			local_flush_tlb()
+#define flush_tlb_mm(mm)		local_flush_tlb()
+#define flush_tlb_page(vma, va)		local_flush_tlb()
+#define flush_tlb_range(mm, start, end)	local_flush_tlb()
+
+#else
+
+#include <asm/smp.h>
+
+static inline void global_flush_tlb(void)
+{
+	long dummy = 0;
+
+	__asm__ __volatile__ (
+                "    la   4,3(%0)\n"
+                "    nill 4,0xfffc\n"
+                "    la   4,1(4)\n"
+                "    slr  2,2\n"
+                "    slr  3,3\n"
+                "    csp  2,4"
+                : : "a" (&dummy) : "2", "3", "4" );
+}
+
+/*
+ * We only have to do global flush of tlb if process run since last
+ * flush on any other pu than current. 
+ * If we have threads (mm->count > 1) we always do a global flush, 
+ * since the process runs on more than one processor at the same time.
+ */
+static inline void __flush_tlb_mm(struct mm_struct * mm)
+{
+	if ((smp_num_cpus > 1) &&
+	    ((atomic_read(&mm->mm_count) != 1) ||
+	     (mm->cpu_vm_mask != (1UL << smp_processor_id())))) {
+		mm->cpu_vm_mask = (1UL << smp_processor_id());
+		global_flush_tlb();
+	} else {                 
+		local_flush_tlb();
+	}
+}
+
+#define flush_tlb()			__flush_tlb_mm(current->mm)
+#define flush_tlb_all()			global_flush_tlb()
+#define flush_tlb_mm(mm)		__flush_tlb_mm(mm)
+#define flush_tlb_page(vma, va)		__flush_tlb_mm((vma)->vm_mm)
+#define flush_tlb_range(mm, start, end)	__flush_tlb_mm(mm)
+
+#endif
+
+extern inline void flush_tlb_pgtables(struct mm_struct *mm,
+                                      unsigned long start, unsigned long end)
+{
+        /* S/390 does not keep any page table caches in TLB */
+}
+
+
+static inline int ptep_test_and_clear_and_flush_young(struct vm_area_struct *vma, 
+                                                      unsigned long address, pte_t *ptep)
+{
+	/* No need to flush TLB; bits are in storage key */
+	return ptep_test_and_clear_young(ptep);
+}
+
+static inline int ptep_test_and_clear_and_flush_dirty(struct vm_area_struct *vma, 
+                                                      unsigned long address, pte_t *ptep)
+{
+	/* No need to flush TLB; bits are in storage key */
+	return ptep_test_and_clear_dirty(ptep);
+}
+
+static inline pte_t ptep_invalidate(struct vm_area_struct *vma, 
+                                    unsigned long address, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!(pte_val(pte) & _PAGE_INVALID)) 
+		__asm__ __volatile__ ("ipte %0,%1" : : "a" (ptep), "a" (address));
+	pte_clear(ptep);
+	return pte;
+}
+
+static inline void ptep_establish(struct vm_area_struct *vma, 
+                                  unsigned long address, pte_t *ptep, pte_t entry)
+{
+	ptep_invalidate(vma, address, ptep);
+	set_pte(ptep, entry);
+}
+
+#endif /* _S390_PGALLOC_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/pgtable.h linux/include/asm-s390x/pgtable.h
--- v2.4.1/linux/include/asm-s390x/pgtable.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/pgtable.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,486 @@
+/*
+ *  include/asm-s390/pgtable.h
+ *
+ *  S390 64bit version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com)
+ *               Ulrich Weigand (weigand@de.ibm.com)
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/pgtable.h"
+ */
+
+#ifndef _ASM_S390_PGTABLE_H
+#define _ASM_S390_PGTABLE_H
+
+/*
+ * The Linux memory management assumes a three-level page table setup. On
+ * the S390, we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * S390 mmu expects.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the S390 page table tree.
+ */
+#ifndef __ASSEMBLY__
+#include <asm/processor.h>
+#include <linux/threads.h>
+
+extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096)));
+extern void paging_init(void);
+
+/* Caches aren't brain-dead on S390. */
+#define flush_cache_all()                       do { } while (0)
+#define flush_cache_mm(mm)                      do { } while (0)
+#define flush_cache_range(mm, start, end)       do { } while (0)
+#define flush_cache_page(vma, vmaddr)           do { } while (0)
+#define flush_page_to_ram(page)                 do { } while (0)
+#define flush_dcache_page(page)			do { } while (0)
+#define flush_icache_range(start, end)          do { } while (0)
+#define flush_icache_page(vma,pg)               do { } while (0)
+
+/*
+ * The S390 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+#define update_mmu_cache(vma, address, pte)     do { } while (0)
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern char empty_zero_page[PAGE_SIZE];
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+#endif /* !__ASSEMBLY__ */
+
+/*
+ * Certain architectures need to do special things when PTEs
+ * within a page table are directly modified.  Thus, the following
+ * hook is made available.
+ */
+#define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
+
+/*
+ * PMD_SHIFT determines the size of the area a second-level page
+ * table can map
+ */
+#define PMD_SHIFT       21
+#define PMD_SIZE        (1UL << PMD_SHIFT)
+#define PMD_MASK        (~(PMD_SIZE-1))
+
+/* PGDIR_SHIFT determines what a third-level page table entry can map */
+#define PGDIR_SHIFT     31
+#define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
+#define PGDIR_MASK      (~(PGDIR_SIZE-1))
+
+/*
+ * entries per page directory level: the S390 is two to five-level,
+ * currently we use a 3 level lookup
+ */
+#define PTRS_PER_PTE    512
+#define PTRS_PER_PMD    1024
+#define PTRS_PER_PGD    2048
+
+/*
+ * pgd entries used up by user/kernel:
+ */
+#define USER_PTRS_PER_PGD  2048
+#define USER_PGD_PTRS      2048
+#define KERNEL_PGD_PTRS    2048
+#define FIRST_USER_PGD_NR  0
+
+#define pte_ERROR(e) \
+	printk("%s:%d: bad pte %016lx.\n", __FILE__, __LINE__, pte_val(e))
+#define pmd_ERROR(e) \
+	printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
+#define pgd_ERROR(e) \
+	printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+#ifndef __ASSEMBLY__
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ */
+#define VMALLOC_OFFSET  (8*1024*1024)
+#define VMALLOC_START   (((unsigned long) high_memory + VMALLOC_OFFSET) \
+                         & ~(VMALLOC_OFFSET-1))
+#define VMALLOC_VMADDR(x) ((unsigned long)(x))
+#define VMALLOC_END     (0x40000000000L)
+
+
+/*
+ * A pagetable entry of S390 has following format:
+ * |                     PFRA                         |0IP0|  OS  |
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * I Page-Invalid Bit:    Page is not available for address-translation
+ * P Page-Protection Bit: Store access not possible for page
+ *
+ * A segmenttable entry of S390 has following format:
+ * |        P-table origin                              |      TT
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * I Segment-Invalid Bit:    Segment is not available for address-translation
+ * C Common-Segment Bit:     Segment is not private (PoP 3-30)
+ * P Page-Protection Bit: Store access not possible for page
+ * TT Type 00
+ *
+ * A region table entry of S390 has following format:
+ * |        S-table origin                             |   TF  TTTL
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * I Segment-Invalid Bit:    Segment is not available for address-translation
+ * TT Type 01
+ * TF
+ * TL Table lenght
+ *
+ * The regiontable origin of S390 has following format:
+ * |      region table origon                          |       DTTL
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ *
+ * X Space-Switch event:
+ * G Segment-Invalid Bit:  
+ * P Private-Space Bit:    
+ * S Storage-Alteration:
+ * R Real space
+ * TL Table-Length:
+ *
+ * A storage key has the following format:
+ * | ACC |F|R|C|0|
+ *  0   3 4 5 6 7
+ * ACC: access key
+ * F  : fetch protection bit
+ * R  : referenced bit
+ * C  : changed bit
+ */
+
+/* Bits in the page table entry */
+#define _PAGE_PRESENT   0x001          /* Software                         */
+#define _PAGE_RO        0x200          /* HW read-only                     */
+#define _PAGE_INVALID   0x400          /* HW invalid                       */
+
+/* Bits in the segment table entry */
+#define _PMD_ENTRY_INV   0x20          /* invalid segment table entry      */
+#define _PMD_ENTRY       0x00        
+
+/* Bits in the region third table entry */
+#define _PGD_ENTRY_INV   0x20          /* invalid region table entry       */
+#define _PGD_ENTRY       0x07
+
+/*
+ * User and kernel page directory
+ */
+#define _REGION_THIRD       0x4
+#define _REGION_THIRD_LEN   0x3 
+#define _REGION_TABLE       (_REGION_THIRD|_REGION_THIRD_LEN)
+
+/* Bits in the storage key */
+#define _PAGE_CHANGED    0x02          /* HW changed bit                   */
+#define _PAGE_REFERENCED 0x04          /* HW referenced bit                */
+
+/*
+ * No mapping available
+ */
+#define PAGE_INVALID    __pgprot(_PAGE_INVALID)
+#define PAGE_NONE       __pgprot(_PAGE_PRESENT | _PAGE_INVALID)
+#define PAGE_COPY       __pgprot(_PAGE_PRESENT | _PAGE_RO)
+#define PAGE_READONLY   __pgprot(_PAGE_PRESENT | _PAGE_RO)
+#define PAGE_SHARED     __pgprot(_PAGE_PRESENT )
+#define PAGE_KERNEL     __pgprot(_PAGE_PRESENT )
+
+/*
+ * The S390 can't do page protection for execute, and considers that the
+ * same are read. Also, write permissions imply read permissions. This is
+ * the closest we can get..
+ */
+#define __P000  PAGE_NONE
+#define __P001  PAGE_READONLY
+#define __P010  PAGE_COPY
+#define __P011  PAGE_COPY
+#define __P100  PAGE_READONLY
+#define __P101  PAGE_READONLY
+#define __P110  PAGE_COPY
+#define __P111  PAGE_COPY
+
+#define __S000  PAGE_NONE
+#define __S001  PAGE_READONLY
+#define __S010  PAGE_SHARED
+#define __S011  PAGE_SHARED
+#define __S100  PAGE_READONLY
+#define __S101  PAGE_READONLY
+#define __S110  PAGE_SHARED
+#define __S111  PAGE_SHARED
+
+/*
+ * Permanent address of a page.
+ */
+#define page_address(page) ((page)->virtual)
+#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+
+/*
+ * pgd/pmd/pte query functions
+ */
+extern inline int pgd_present(pgd_t pgd) { return pgd_val(pgd) != 0; }
+extern inline int pgd_none(pgd_t pgd)    { return pgd_val(pgd) & _PGD_ENTRY_INV; }
+extern inline int pgd_bad(pgd_t pgd)
+{
+	return (pgd_val(pgd) & (~PAGE_MASK & ~_PGD_ENTRY_INV)) != _PGD_ENTRY;
+}
+
+extern inline int pmd_present(pmd_t pmd) { return pmd_val(pmd) != 0; }
+extern inline int pmd_none(pmd_t pmd)    { return pmd_val(pmd) & _PMD_ENTRY_INV; }
+extern inline int pmd_bad(pmd_t pmd)
+{
+	return (pmd_val(pmd) & (~PAGE_MASK & ~_PMD_ENTRY_INV)) != _PMD_ENTRY;
+}
+
+extern inline int pte_present(pte_t pte) { return pte_val(pte) & _PAGE_PRESENT; }
+extern inline int pte_none(pte_t pte)
+{
+	return ((pte_val(pte) & 
+		 (_PAGE_INVALID | _PAGE_RO | _PAGE_PRESENT)) == _PAGE_INVALID);
+} 
+
+#define pte_same(a,b)	(pte_val(a) == pte_val(b))
+
+/*
+ * query functions pte_write/pte_dirty/pte_young only work if
+ * pte_present() is true. Undefined behaviour if not..
+ */
+extern inline int pte_write(pte_t pte)
+{
+	return (pte_val(pte) & _PAGE_RO) == 0;
+}
+
+extern inline int pte_dirty(pte_t pte)
+{
+	int skey;
+
+	asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
+	return skey & _PAGE_CHANGED;
+}
+
+extern inline int pte_young(pte_t pte)
+{
+	int skey;
+
+	asm volatile ("iske %0,%1" : "=d" (skey) : "a" (pte_val(pte)));
+	return skey & _PAGE_REFERENCED;
+}
+
+/*
+ * pgd/pmd/pte modification functions
+ */
+extern inline void pgd_clear(pgd_t * pgdp)
+{
+	pgd_val(*pgdp) = _PGD_ENTRY_INV | _PGD_ENTRY;
+}
+
+extern inline void pmd_clear(pmd_t * pmdp)
+{
+	pmd_val(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
+	pmd_val1(*pmdp) = _PMD_ENTRY_INV | _PMD_ENTRY;
+}
+
+extern inline void pte_clear(pte_t *ptep)
+{
+	pte_val(*ptep) = _PAGE_INVALID;
+}
+
+#define PTE_INIT(x) pte_clear(x)
+
+/*
+ * The following pte_modification functions only work if 
+ * pte_present() is true. Undefined behaviour if not..
+ */
+extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	pte_val(pte) = (pte_val(pte) & PAGE_MASK) | pgprot_val(newprot);
+	return pte; 
+}
+
+extern inline pte_t pte_wrprotect(pte_t pte)
+{
+	pte_val(pte) |= _PAGE_RO;
+	return pte;
+}
+
+extern inline pte_t pte_mkwrite(pte_t pte)
+{
+	pte_val(pte) &= ~_PAGE_RO;
+	return pte;
+}
+
+extern inline pte_t pte_mkclean(pte_t pte)
+{
+	/* We can't clear the changed bit atomically. The iske/and/sske
+         * sequence has a race condition with the page referenced bit.
+         * At the moment pte_mkclean is always followed by a pte_mkold.
+         * So its safe to ignore the problem for now. Hope this will
+         * never change ... */
+	asm volatile ("sske %0,%1" 
+	              : : "d" (0), "a" (pte_val(pte)));
+	return pte;
+}
+
+extern inline pte_t pte_mkdirty(pte_t pte)
+{ 
+	/* We can't set the changed bit atomically either. For now we
+         * set (!) the page referenced bit. */
+	asm volatile ("sske %0,%1" 
+	              : : "d" (_PAGE_CHANGED|_PAGE_REFERENCED),
+		          "a" (pte_val(pte)));
+	return pte;
+}
+
+extern inline pte_t pte_mkold(pte_t pte)
+{
+	asm volatile ("rrbe 0,%0" : : "a" (pte_val(pte)));
+	return pte;
+}
+
+extern inline pte_t pte_mkyoung(pte_t pte)
+{
+	/* To set the referenced bit we read the first word from the real
+	 * page with a special instruction: load using real address (lura).
+	 * Isn't S/390 a nice architecture ?! */
+	asm volatile ("lura 0,%0" : : "a" (pte_val(pte) & PAGE_MASK) : "0" );
+	return pte;
+}
+
+static inline int ptep_test_and_clear_young(pte_t *ptep)
+{
+	int ccode;
+
+	asm volatile ("rrbe 0,%1\n\t"
+		      "ipm  %0\n\t"
+		      "srl  %0,28\n\t" : "=d" (ccode) : "a" (pte_val(*ptep)));
+	return ccode & 2;
+}
+
+static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+{
+	int skey;
+
+	asm volatile ("iske %0,%1" : "=d" (skey) : "a" (*ptep));
+	if ((skey & _PAGE_CHANGED) == 0)
+		return 0;
+	/* We can't clear the changed bit atomically. For now we
+         * clear (!) the page referenced bit. */
+	asm volatile ("sske %0,%1" 
+	              : : "d" (0), "a" (*ptep));
+	return 1;
+}
+
+static inline pte_t ptep_get_and_clear(pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	pte_clear(ptep);
+	return pte;
+}
+
+static inline void ptep_set_wrprotect(pte_t *ptep)
+{
+	pte_t old_pte = *ptep;
+	set_pte(ptep, pte_wrprotect(old_pte));
+}
+
+static inline void ptep_mkdirty(pte_t *ptep)
+{
+	pte_mkdirty(*ptep);
+}
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+extern inline pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot)
+{
+	pte_t __pte;
+	pte_val(__pte) = physpage + pgprot_val(pgprot);
+	return __pte;
+}
+#define mk_pte(page,pgprot) mk_pte_phys(__pa(((page)-mem_map)<<PAGE_SHIFT),pgprot)
+
+#define pte_page(x) (mem_map+(unsigned long)((pte_val(x) >> PAGE_SHIFT)))
+
+extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
+{
+	pmd_val(*pmdp) = _PMD_ENTRY | __pa(ptep);
+	pmd_val1(*pmdp) = _PMD_ENTRY | __pa(ptep+256);
+}
+
+extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
+{
+	pgd_val(*pgdp) = _PGD_ENTRY | __pa(pmdp);
+}
+
+#define pmd_page(pmd) \
+        ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
+
+#define pgd_page(pmd) \
+        ((unsigned long) __va(pgd_val(pmd) & PAGE_MASK))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+/* Find an entry in the second-level page table.. */
+#define pmd_offset(dir,addr) \
+	((pmd_t *) pgd_page(*(dir)) + (((addr) >> PMD_SHIFT) & (PTRS_PER_PMD - 1)))
+
+/* Find an entry in the third-level page table.. */
+#define pte_offset(dir,addr) \
+	((pte_t *) pmd_page(*(dir)) + (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
+
+/*
+ * A page-table entry has some bits we have to treat in a special way.
+ * Bits 52 and bit 55 have to be zero, otherwise an specification
+ * exception will occur instead of a page translation exception. The
+ * specifiation exception has the bad habit not to store necessary
+ * information in the lowcore.
+ * Bit 53 and bit 54 are the page invalid bit and the page protection
+ * bit. We set both to indicate a swapped page.
+ * Bit 63 is used as the software page present bit. If a page is
+ * swapped this obviously has to be zero.
+ * This leaves the bits 0-51 and bits 56-62 to store type and offset.
+ * We use the 7 bits from 56-62 for the type and the 52 bits from 0-51
+ * for the offset.
+ * |                     offset                       |0110|type |0
+ * 0000000000111111111122222222223333333333444444444455555555556666
+ * 0123456789012345678901234567890123456789012345678901234567890123
+ */
+extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
+{
+	pte_t pte;
+	pte_val(pte) = (type << 1) | (offset << 12) | _PAGE_INVALID | _PAGE_RO;
+	pte_val(pte) &= 0xfffffffffffff6fe;  /* better to be paranoid */
+	return pte;
+}
+
+#define SWP_TYPE(entry)		(((entry).val >> 1) & 0x3f)
+#define SWP_OFFSET(entry)	((entry).val >> 12)
+#define SWP_ENTRY(type,offset)	((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) })
+
+#define pte_to_swp_entry(pte)	((swp_entry_t) { pte_val(pte) })
+#define swp_entry_to_pte(x)	((pte_t) { (x).val })
+
+#endif /* !__ASSEMBLY__ */
+
+/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+#define PageSkip(page)          (0)
+#define kern_addr_valid(addr)   (1)
+
+#endif /* _S390_PAGE_H */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/poll.h linux/include/asm-s390x/poll.h
--- v2.4.1/linux/include/asm-s390x/poll.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/poll.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,33 @@
+/*
+ *  include/asm-s390/poll.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/poll.h"
+ */
+
+#ifndef __S390_POLL_H
+#define __S390_POLL_H
+
+/* These are specified by iBCS2 */
+#define POLLIN          0x0001
+#define POLLPRI         0x0002
+#define POLLOUT         0x0004
+#define POLLERR         0x0008
+#define POLLHUP         0x0010
+#define POLLNVAL        0x0020
+
+/* The rest seem to be more-or-less nonstandard. Check them! */
+#define POLLRDNORM	0x0040
+#define POLLRDBAND	0x0080
+#define POLLWRNORM	0x0100
+#define POLLWRBAND	0x0200
+#define POLLMSG		0x0400
+
+struct pollfd {
+	int fd;
+	short events;
+	short revents;
+};
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/posix_types.h linux/include/asm-s390x/posix_types.h
--- v2.4.1/linux/include/asm-s390x/posix_types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/posix_types.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,74 @@
+/*
+ *  include/asm-s390/posix_types.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/posix_types.h"
+ */
+
+#ifndef __ARCH_S390_POSIX_TYPES_H
+#define __ARCH_S390_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.  Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned int    __kernel_dev_t;
+typedef unsigned int    __kernel_ino_t;
+typedef unsigned int    __kernel_mode_t;
+typedef unsigned int    __kernel_nlink_t;
+typedef long            __kernel_off_t;
+typedef long long       __kernel_loff_t;
+typedef int             __kernel_pid_t;
+typedef int             __kernel_ipc_pid_t;
+typedef unsigned int    __kernel_uid_t;
+typedef unsigned int    __kernel_gid_t;
+typedef unsigned long   __kernel_size_t;
+typedef long            __kernel_ssize_t;
+typedef long            __kernel_ptrdiff_t;
+typedef long            __kernel_time_t;
+typedef long            __kernel_suseconds_t;
+typedef long            __kernel_clock_t;
+typedef int             __kernel_daddr_t;
+typedef char *          __kernel_caddr_t;
+typedef unsigned long   __kernel_sigset_t;      /* at least 32 bits */
+typedef unsigned short	__kernel_uid16_t;
+typedef unsigned short	__kernel_gid16_t;
+
+typedef __kernel_uid_t __kernel_old_uid_t;
+typedef __kernel_gid_t __kernel_old_gid_t;
+typedef __kernel_uid_t __kernel_uid32_t;
+typedef __kernel_gid_t __kernel_gid32_t;
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+        int     val[2];
+#else                        /* !defined(__KERNEL__) && !defined(__USE_ALL)*/
+        int     __val[2];
+#endif                       /* !defined(__KERNEL__) && !defined(__USE_ALL)*/
+} __kernel_fsid_t;
+
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#ifndef _S390_BITOPS_H
+#include <asm/bitops.h>
+#endif
+
+#undef  __FD_SET
+#define __FD_SET(fd,fdsetp)  set_bit(fd,fdsetp)
+
+#undef  __FD_CLR
+#define __FD_CLR(fd,fdsetp)  clear_bit(fd,fdsetp)
+
+#undef  __FD_ISSET
+#define __FD_ISSET(fd,fdsetp)  test_bit(fd,fdsetp)
+
+#undef  __FD_ZERO
+#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
+
+#endif     /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)*/
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/processor.h linux/include/asm-s390x/processor.h
--- v2.4.1/linux/include/asm-s390x/processor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/processor.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,227 @@
+/*
+ *  include/asm-s390/processor.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hp@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/processor.h"
+ *    Copyright (C) 1994, Linus Torvalds
+ */
+
+#ifndef __ASM_S390_PROCESSOR_H
+#define __ASM_S390_PROCESSOR_H
+
+#include <asm/page.h>
+#include <asm/ptrace.h>
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ void *pc; __asm__("basr %0,0":"=a"(pc)); pc; })
+
+/*
+ *  CPU type and hardware bug flags. Kept separately for each CPU.
+ *  Members of this structure are referenced in head.S, so think twice
+ *  before touching them. [mj]
+ */
+
+typedef struct
+{
+        unsigned int version :  8;
+        unsigned int ident   : 24;
+        unsigned int machine : 16;
+        unsigned int unused  : 16;
+} __attribute__ ((packed)) cpuid_t;
+
+struct cpuinfo_S390
+{
+        cpuid_t  cpu_id;
+        unsigned long loops_per_jiffy;
+        unsigned long *pgd_quick;
+        unsigned long *pmd_quick;
+        unsigned long *pte_quick;
+        unsigned long pgtable_cache_sz;
+        __u16    cpu_addr;
+        __u16    cpu_nr;
+        __u16    pad[2];
+};
+
+extern void print_cpu_info(struct cpuinfo_S390 *);
+
+/* Lazy FPU handling on uni-processor */
+extern struct task_struct *last_task_used_math;
+
+#define S390_FLAG_31BIT 0x01UL
+
+/*
+ * User space process size: 4TB (default).
+ */
+#define TASK_SIZE       (0x40000000000UL)
+#define TASK31_SIZE     (0x80000000UL)
+
+/* This decides where the kernel will search for a free chunk of vm
+ * space during mmap's.
+ */
+#define TASK_UNMAPPED_BASE      ((current->thread.flags & S390_FLAG_31BIT) ? \
+	(TASK31_SIZE / 2) : (TASK_SIZE / 2))
+
+#define THREAD_SIZE (4*PAGE_SIZE)
+
+typedef struct {
+       __u32 ar4;
+} mm_segment_t;
+
+/* if you change the thread_struct structure, you must
+ * update the _TSS_* defines in entry.S
+ */
+
+struct thread_struct
+ {
+        struct pt_regs *regs;         /* the user registers can be found on*/
+	s390_fp_regs fp_regs;
+        __u32   ar2;                   /* kernel access register 2         */
+        __u32   ar4;                   /* kernel access register 4         */
+        addr_t  ksp;                   /* kernel stack pointer             */
+        addr_t  user_seg;              /* HSTD                             */
+        addr_t  prot_addr;             /* address of protection-excep.     */
+        __u32   error_code;            /* error-code of last prog-excep.   */
+        __u32   trap_no;
+        per_struct per_info;/* Must be aligned on an 4 byte boundary*/
+	addr_t  ieee_instruction_pointer; 
+	/* Used to give failing instruction back to user for ieee exceptions */
+	unsigned long flags;            /* various flags */
+};
+
+typedef struct thread_struct thread_struct;
+
+#define INIT_MMAP \
+{ &init_mm, 0, 0, NULL, PAGE_SHARED, \
+VM_READ | VM_WRITE | VM_EXEC, 1, NULL,NULL }
+
+#define INIT_THREAD { (struct pt_regs *) 0,                       \
+                    { 0,{{0},{0},{0},{0},{0},{0},{0},{0},{0},{0}, \
+			    {0},{0},{0},{0},{0},{0}}},            \
+                     0, 0,                                        \
+                    sizeof(init_stack) + (addr_t) &init_stack,    \
+              (__pa((addr_t) &swapper_pg_dir[0]) + _REGION_TABLE),\
+                     0,0,0,                                       \
+                     (per_struct) {{{{0,}}},0,0,0,0,{{0,}}},      \
+		     0					          \
+} 
+
+/* need to define ... */
+#define start_thread(regs, new_psw, new_stackp) do {            \
+        regs->psw.mask  = _USER_PSW_MASK;                       \
+        regs->psw.addr  = new_psw;                              \
+        regs->gprs[15]  = new_stackp;                           \
+} while (0)
+
+#define start_thread31(regs, new_psw, new_stackp) do {          \
+	regs->psw.mask  = _USER_PSW_MASK & ~(1L << 32);		\
+        regs->psw.addr  = new_psw;                              \
+        regs->gprs[15]  = new_stackp;                           \
+} while (0)
+
+
+/* Forward declaration, a strange C thing */
+struct mm_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
+/* Copy and release all segment info associated with a VM */
+#define copy_segments(nr, mm)           do { } while (0)
+#define release_segments(mm)            do { } while (0)
+
+/*
+ * Return saved PC of a blocked thread. used in kernel/sched
+ */
+extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+{
+        return (t->regs) ? ((unsigned long)t->regs->psw.addr) : 0;
+}
+
+unsigned long get_wchan(struct task_struct *p);
+#define KSTK_EIP(tsk)   ((tsk)->thread.regs->psw.addr)
+#define KSTK_ESP(tsk)   ((tsk)->thread.ksp)
+
+/* Allocation and freeing of basic task resources. */
+/*
+ * NOTE! The task struct and the stack go together
+ */
+#define alloc_task_struct() \
+        ((struct task_struct *) __get_free_pages(GFP_KERNEL,2))
+#define free_task_struct(p)     free_pages((unsigned long)(p),2)
+#define get_task_struct(tsk)      atomic_inc(&virt_to_page(tsk)->count)
+
+#define init_task       (init_task_union.task)
+#define init_stack      (init_task_union.stack)
+
+/*
+ * Set of msr bits that gdb can change on behalf of a process.
+ */
+/* Only let our hackers near the condition codes */
+#define PSW_MASK_DEBUGCHANGE    0x0000300000000000UL
+/* Don't let em near the addressing mode either */    
+#define PSW_ADDR_DEBUGCHANGE    0xFFFFFFFFFFFFFFFFUL
+#define PSW_ADDR_MASK           0xFFFFFFFFFFFFFFFFUL
+/* Program event recording mask */    
+#define PSW_PER_MASK            0x4000000000000000UL
+#define USER_STD_MASK           0x0000000000000080UL
+#define PSW_PROBLEM_STATE       0x0001000000000000UL
+
+/*
+ * Function to drop a processor into disabled wait state
+ */
+
+static inline void disabled_wait(addr_t code)
+{
+        char psw_buffer[2*sizeof(psw_t)];
+        char ctl_buf[8];
+        psw_t *dw_psw = (psw_t *)(((unsigned long) &psw_buffer+sizeof(psw_t)-1)
+                                  & -sizeof(psw_t));
+
+        dw_psw->mask = 0x0002000180000000;
+        dw_psw->addr = code;
+        /* 
+         * Store status and then load disabled wait psw,
+         * the processor is dead afterwards
+         */
+        asm volatile ("    stctg 0,0,0(%1)\n"
+                      "    ni    4(%1),0xef\n" /* switch off protection */
+                      "    lctlg 0,0,0(%1)\n"
+                      "    lghi  1,0x1000\n"
+                      "    stpt  0x328(1)\n"      /* store timer */
+                      "    stckc 0x330(1)\n"      /* store clock comparator */
+                      "    stpx  0x318(1)\n"      /* store prefix register */
+                      "    stam  0,15,0x340(1)\n" /* store access registers */
+                      "    stfpc 0x31c(1)\n"      /* store fpu control */
+                      "    std   0,0x200(1)\n"    /* store f0 */
+                      "    std   1,0x208(1)\n"    /* store f1 */
+                      "    std   2,0x210(1)\n"    /* store f2 */
+                      "    std   3,0x218(1)\n"    /* store f3 */
+                      "    std   4,0x220(1)\n"    /* store f4 */
+                      "    std   5,0x228(1)\n"    /* store f5 */
+                      "    std   6,0x230(1)\n"    /* store f6 */
+                      "    std   7,0x238(1)\n"    /* store f7 */
+                      "    std   8,0x240(1)\n"    /* store f8 */
+                      "    std   9,0x248(1)\n"    /* store f9 */
+                      "    std   10,0x250(1)\n"   /* store f10 */
+                      "    std   11,0x258(1)\n"   /* store f11 */
+                      "    std   12,0x260(1)\n"   /* store f12 */
+                      "    std   13,0x268(1)\n"   /* store f13 */
+                      "    std   14,0x270(1)\n"   /* store f14 */
+                      "    std   15,0x278(1)\n"   /* store f15 */
+                      "    stmg  0,15,0x280(1)\n" /* store general registers */
+                      "    stctg 0,15,0x380(1)\n" /* store control registers */
+                      "    oi    0x384(1),0x10\n" /* fake protection bit */
+                      "    lpswe 0(%0)"
+                      : : "a" (dw_psw), "a" (&ctl_buf) : "0", "1");
+}
+
+#endif                                 /* __ASM_S390_PROCESSOR_H           */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ptrace.h linux/include/asm-s390x/ptrace.h
--- v2.4.1/linux/include/asm-s390x/ptrace.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ptrace.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,326 @@
+/*
+ *  include/asm-s390/ptrace.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ */
+
+#ifndef _S390_PTRACE_H
+#define _S390_PTRACE_H
+#include <linux/config.h>
+#include <asm/s390-regs-common.h>
+#include <asm/current.h>
+#include <linux/types.h>
+#include <asm/setup.h>
+#include <linux/stddef.h>
+
+
+#define S390_REGS   \
+S390_REGS_COMMON    \
+addr_t orig_gpr2;
+
+typedef struct
+{
+	S390_REGS
+} __attribute__ ((packed)) s390_regs;
+
+struct pt_regs 
+{
+	S390_REGS
+	__u32 trap;
+} __attribute__ ((packed));
+
+#if CONFIG_REMOTE_DEBUG
+typedef struct
+{
+	S390_REGS
+	__u32 trap;
+	addr_t crs[16];
+	s390_fp_regs fp_regs;
+} __attribute__ ((packed)) gdb_pt_regs;
+#endif
+
+
+typedef struct
+{
+			addr_t   cr[3];
+} per_cr_words  __attribute__((packed));
+
+#define PER_EM_MASK 0x00000000E8000000UL
+typedef	struct
+{
+	unsigned    :32;
+	unsigned    em_branching:1;
+	unsigned    em_instruction_fetch:1;
+	/* Switching on storage alteration automatically fixes
+	   the storage alteration event bit in the users std. */
+	unsigned    em_storage_alteration:1;
+	unsigned    em_gpr_alt_unused:1;
+	unsigned    em_store_real_address:1;
+	unsigned    :3;
+	unsigned    branch_addr_ctl:1;
+	unsigned    :1;
+	unsigned    storage_alt_space_ctl:1;
+	unsigned    :5;
+	unsigned    :16;
+	addr_t      starting_addr;
+	addr_t      ending_addr;
+} per_cr_bits  __attribute__((packed));
+
+typedef struct
+{
+	__u16          perc_atmid;          /* 0x096 */
+	addr_t         address;             /* 0x098 */
+	__u8           access_id;           /* 0x0a1 */
+} per_lowcore_words  __attribute__((packed));
+
+typedef struct
+{
+	unsigned       perc_branching:1;               /* 0x096 */
+	unsigned       perc_instruction_fetch:1;
+	unsigned       perc_storage_alteration:1;
+	unsigned       perc_gpr_alt_unused:1;
+	unsigned       perc_store_real_address:1;
+	unsigned       :3;
+	unsigned       atmid_psw_bit_31:1;
+	unsigned       atmid_validity_bit:1;
+	unsigned       atmid_psw_bit_32:1;
+	unsigned       atmid_psw_bit_5:1;
+	unsigned       atmid_psw_bit_16:1;
+	unsigned       atmid_psw_bit_17:1;
+	unsigned       ai:2;
+	addr_t         address;              /* 0x098 */
+	unsigned       :4;                   /* 0x0a1 */
+	unsigned       access_id:4;           
+} per_lowcore_bits __attribute__((packed));
+
+
+typedef enum
+{
+	primary_asce,
+	ar_asce,
+	secondary_asce,
+	home_space_asce
+} per_ai_codes;
+
+
+
+typedef struct
+{
+	union
+	{
+		per_cr_words   words;
+		per_cr_bits    bits;
+	} control_regs  __attribute__((packed));
+	/* Use these flags instead of setting em_instruction_fetch */
+	/* directly they are used so that single stepping can be */
+	/* switched on & off while not affecting other tracing */
+	unsigned  single_step:1;
+	unsigned  instruction_fetch:1;
+	unsigned  :30;
+	/* These addresses are copied into cr10 & cr11 if single stepping
+	   is switched off */
+	addr_t     starting_addr;
+	addr_t     ending_addr;
+	union
+	{
+		per_lowcore_words words;
+		per_lowcore_bits  bits;
+	} lowcore; 
+} per_struct __attribute__((packed));
+
+
+
+/* this struct defines the way the registers are stored on the
+   stack during a system call. If you change the pt_regs structure,
+   you'll need to change user.h too. 
+
+   N.B. if you modify the pt_regs struct the strace command also has to be
+   modified & recompiled  ( just wait till we have gdb going ).
+
+*/
+
+struct user_regs_struct
+{
+	S390_REGS
+	s390_fp_regs fp_regs;
+/* These per registers are in here so that gdb can modify them itself
+ * as there is no "official" ptrace interface for hardware watchpoints.
+ * this is the way intel does it
+ */
+	per_struct per_info;
+	addr_t  ieee_instruction_pointer; 
+	/* Used to give failing instruction back to user for ieee exceptions */
+};
+
+typedef struct user_regs_struct user_regs_struct;
+
+typedef struct pt_regs pt_regs;
+
+#ifdef __KERNEL__
+#define user_mode(regs) (((regs)->psw.mask & PSW_PROBLEM_STATE) != 0)
+#define instruction_pointer(regs) ((regs)->psw.addr)
+extern void show_regs(struct pt_regs * regs);
+extern char *task_show_regs(struct task_struct *task, char *buffer);
+#endif
+
+
+
+
+
+#define FIX_PSW(addr) ((unsigned long)(addr))
+
+#define MULT_PROCPTR_TYPES    ((CONFIG_BINFMT_ELF)&&(CONFIG_BINFMT_TOC))
+
+typedef struct
+{
+  long addr;
+  long toc;
+} routine_descriptor;
+extern void fix_routine_descriptor_regs(routine_descriptor *rdes,pt_regs *regs);
+extern __inline__ void 
+fix_routine_descriptor_regs(routine_descriptor *rdes,pt_regs *regs)
+{
+  regs->psw.addr=FIX_PSW(rdes->addr);
+  regs->gprs[12]=rdes->toc;
+}
+
+/*
+ * Compiler optimisation should save this stuff from being non optimal
+ * & remove uneccessary code ( isnt gcc great DJB. )
+ */
+
+/*I'm just using this an indicator of what binformat we are using
+ * (DJB) N.B. this needs to stay a macro unfortunately as I am otherwise
+ * dereferencing incomplete pointer types in with load_toc_binary
+ */
+#if MULT_PROCPTR_TYPES
+#define uses_routine_descriptors() \
+(current->binfmt->load_binary==load_toc_binary)
+#else
+#if CONFIG_BINFMT_TOC
+#define uses_routine_descriptors() 1
+#else
+#define uses_routine_descriptors() 0
+#endif
+#endif
+
+#define pt_off(ptreg)   offsetof(user_regs_struct,ptreg)
+enum
+{
+	PT_PSWMASK=pt_off(psw.mask),
+	PT_PSWADDR=pt_off(psw.addr),
+	PT_GPR0=pt_off(gprs[0]),
+	PT_GPR1=pt_off(gprs[1]),
+	PT_GPR2=pt_off(gprs[2]),
+	PT_GPR3=pt_off(gprs[3]),
+	PT_GPR4=pt_off(gprs[4]),
+	PT_GPR5=pt_off(gprs[5]),
+	PT_GPR6=pt_off(gprs[6]),
+	PT_GPR7=pt_off(gprs[7]),
+	PT_GPR8=pt_off(gprs[8]),
+	PT_GPR9=pt_off(gprs[9]),
+	PT_GPR10=pt_off(gprs[10]),
+	PT_GPR11=pt_off(gprs[11]),
+	PT_GPR12=pt_off(gprs[12]),
+	PT_GPR13=pt_off(gprs[13]),
+	PT_GPR14=pt_off(gprs[14]),
+	PT_GPR15=pt_off(gprs[15]),
+        PT_ACR0=pt_off(acrs[0]),
+        PT_ACR1=pt_off(acrs[1]),
+        PT_ACR2=pt_off(acrs[2]),
+        PT_ACR3=pt_off(acrs[3]),
+        PT_ACR4=pt_off(acrs[4]),
+        PT_ACR5=pt_off(acrs[5]),
+        PT_ACR6=pt_off(acrs[6]),
+        PT_ACR7=pt_off(acrs[7]),
+        PT_ACR8=pt_off(acrs[8]),
+        PT_ACR9=pt_off(acrs[9]),
+        PT_ACR10=pt_off(acrs[10]),
+        PT_ACR11=pt_off(acrs[11]),
+        PT_ACR12=pt_off(acrs[12]),
+        PT_ACR13=pt_off(acrs[13]),
+        PT_ACR14=pt_off(acrs[14]),
+        PT_ACR15=pt_off(acrs[15]),
+	PT_ORIGGPR2=pt_off(orig_gpr2),
+	PT_FPC=pt_off(fp_regs.fpc),
+/*
+ *      A nasty fact of life that the ptrace api
+ *      only supports passing of longs.
+ */
+	PT_FPR0=pt_off(fp_regs.fprs[0].d),
+	PT_FPR1=pt_off(fp_regs.fprs[1].d),
+	PT_FPR2=pt_off(fp_regs.fprs[2].d),
+	PT_FPR3=pt_off(fp_regs.fprs[3].d),
+	PT_FPR4=pt_off(fp_regs.fprs[4].d),
+	PT_FPR5=pt_off(fp_regs.fprs[5].d),
+	PT_FPR6=pt_off(fp_regs.fprs[6].d),
+	PT_FPR7=pt_off(fp_regs.fprs[7].d),
+	PT_FPR8=pt_off(fp_regs.fprs[8].d),
+	PT_FPR9=pt_off(fp_regs.fprs[9].d),
+	PT_FPR10=pt_off(fp_regs.fprs[10].d),
+	PT_FPR11=pt_off(fp_regs.fprs[11].d),
+	PT_FPR12=pt_off(fp_regs.fprs[12].d),
+	PT_FPR13=pt_off(fp_regs.fprs[13].d),
+	PT_FPR14=pt_off(fp_regs.fprs[14].d),
+	PT_FPR15=pt_off(fp_regs.fprs[15].d),
+	PT_CR_9=pt_off(per_info.control_regs.words.cr[0]),
+	PT_CR_10=pt_off(per_info.control_regs.words.cr[1]),
+	PT_CR_11=pt_off(per_info.control_regs.words.cr[2]),
+        PT_IEEE_IP=pt_off(ieee_instruction_pointer),
+        PT_LASTOFF=PT_IEEE_IP,
+        PT_ENDREGS=sizeof(user_regs_struct)-1
+};
+
+#define PTRACE_AREA \
+__u32 len;          \
+addr_t  kernel_addr; \
+addr_t  process_addr;
+
+typedef struct
+{
+	 PTRACE_AREA
+} ptrace_area;
+
+/*
+  390 specific non posix ptrace requests
+  I chose unusual values so they are unlikely to clash with future ptrace definitions.
+ */
+#define PTRACE_PEEKUSR_AREA           0x5000
+#define PTRACE_POKEUSR_AREA           0x5001
+#define PTRACE_PEEKTEXT_AREA	      0x5002
+#define PTRACE_PEEKDATA_AREA	      0x5003
+#define PTRACE_POKETEXT_AREA	      0x5004
+#define PTRACE_POKEDATA_AREA 	      0x5005
+/* PT_PROT definition is loosely based on hppa bsd definition in gdb/hppab-nat.c */
+#define PTRACE_PROT                       21
+
+typedef enum
+{
+	ptprot_set_access_watchpoint,
+	ptprot_set_write_watchpoint,
+	ptprot_disable_watchpoint
+} ptprot_flags;
+
+typedef struct
+{
+	addr_t           lowaddr;
+	addr_t           hiaddr;
+	ptprot_flags     prot;
+} ptprot_area;                     
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/queue.h linux/include/asm-s390x/queue.h
--- v2.4.1/linux/include/asm-s390x/queue.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/queue.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,170 @@
+/*
+ *  include/asm-s390/queue.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *  A little set of queue utilies.
+ */
+#include <linux/stddef.h>
+#include <asm/types.h>
+
+typedef struct queue
+{
+	struct queue *next;	
+} queue;
+
+typedef queue list;
+
+typedef struct
+{
+	queue *head;
+	queue *tail;
+} qheader;
+
+static __inline__ void init_queue(qheader *qhead)
+{
+	memset(qhead,0,sizeof(*qhead));
+}
+
+static __inline__ void enqueue_tail(qheader *qhead,queue *member)
+{
+	queue *tail=qhead->tail;
+	member->next=NULL;
+	
+	if(member)
+	{
+		if(tail)
+			tail->next=member;
+		else
+			
+			qhead->head=member;
+		qhead->tail=member;
+		member->next=NULL;
+	}
+} 
+
+static __inline__ queue *dequeue_head(qheader *qhead)
+{
+	queue *head=qhead->head,*next_head;
+
+	if(head)
+	{
+		next_head=head->next;
+		qhead->head=next_head;
+	        if(!next_head)
+			qhead->tail=NULL;
+	}
+	return(head);
+}
+
+static __inline__ void init_list(list **lhead)
+{
+	*lhead=NULL;
+}
+
+static __inline__ void add_to_list(list **lhead,list *member)
+{
+	member->next=*lhead;
+	*lhead=member;
+}
+
+static __inline__ list *remove_listhead(list **lhead)
+{
+	list *oldhead=*lhead;
+
+	if(oldhead)
+		*lhead=(*lhead)->next;
+	return(oldhead);
+}
+
+static __inline__ void add_to_list_tail(list **lhead,list *member)
+{
+	list *curr,*prev;
+	if(*lhead==NULL)
+		*lhead=member;
+	else
+	{
+		prev=*lhead;
+		for(curr=(*lhead)->next;curr!=NULL;curr=curr->next)
+			prev=curr;
+		prev->next=member;
+	}
+}
+static __inline__ void add_to_list_tail_null(list **lhead,list *member)
+{
+	member->next=NULL;
+	add_to_list_tail_null(lhead,member);
+}
+
+
+static __inline__ int is_in_list(list *lhead,list *member)
+{
+	list *curr;
+
+	for(curr=lhead;curr!=NULL;curr=curr->next)
+		if(curr==member)
+			return(TRUE);
+	return(FALSE);
+}
+
+static __inline__ int get_prev(list *lhead,list *member,list **prev)
+{
+	list *curr;
+
+	*prev=NULL;
+	for(curr=lhead;curr!=NULL;curr=curr->next)
+	{
+		if(curr==member)
+			return(TRUE);
+		*prev=curr;
+	}
+	*prev=NULL;
+	return(FALSE);
+}
+
+
+
+static __inline__ int remove_from_list(list **lhead,list *member)
+{
+	list *prev;
+
+	if(get_prev(*lhead,member,&prev))
+	{
+
+		if(prev)
+			prev->next=member->next;
+		else
+			*lhead=member->next;
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+static __inline__ int remove_from_queue(qheader *qhead,queue *member)
+{
+	queue *prev;
+
+	if(get_prev(qhead->head,(list *)member,(list **)&prev))
+	{
+
+		if(prev)
+		{
+			prev->next=member->next;
+			if(prev->next==NULL)
+				qhead->tail=prev;
+		}
+		else
+		{
+			if(qhead->head==qhead->tail)
+				qhead->tail=NULL;
+			qhead->head=member->next;
+		}
+		return(TRUE);
+	}
+	return(FALSE);
+}
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/resource.h linux/include/asm-s390x/resource.h
--- v2.4.1/linux/include/asm-s390x/resource.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/resource.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,56 @@
+/*
+ *  include/asm-s390/resource.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/resources.h"
+ */
+
+#ifndef _S390_RESOURCE_H
+#define _S390_RESOURCE_H
+
+/*
+ * Resource limits
+ */
+
+#define RLIMIT_CPU	0		/* CPU time in ms */
+#define RLIMIT_FSIZE	1		/* Maximum filesize */
+#define RLIMIT_DATA	2		/* max data size */
+#define RLIMIT_STACK	3		/* max stack size */
+#define RLIMIT_CORE	4		/* max core file size */
+#define RLIMIT_RSS	5		/* max resident set size */
+#define RLIMIT_NPROC	6		/* max number of processes */
+#define RLIMIT_NOFILE	7		/* max number of open files */
+#define RLIMIT_MEMLOCK	8		/* max locked-in-memory address space */
+#define RLIMIT_AS	9		/* address space limit */
+#define RLIMIT_LOCKS	10		/* maximum file locks held */
+
+#define RLIM_NLIMITS	11
+
+/*
+ * SuS says limits have to be unsigned.
+ * Which makes a ton more sense anyway.
+ */
+#define RLIM_INFINITY   (~0UL)
+
+#ifdef __KERNEL__
+
+#define INIT_RLIMITS					\
+{							\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{      _STK_LIM, RLIM_INFINITY },		\
+	{             0, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{        0,        0 },                  	\
+	{ INR_OPEN, INR_OPEN },                         \
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+	{ RLIM_INFINITY, RLIM_INFINITY },		\
+}
+
+#endif /* __KERNEL__ */
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/s390-gdbregs.h linux/include/asm-s390x/s390-gdbregs.h
--- v2.4.1/linux/include/asm-s390x/s390-gdbregs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/s390-gdbregs.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,89 @@
+/*
+ *  include/asm-s390/s390-gdbregs.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *  used both by the linux kernel for remote debugging & gdb 
+ */
+
+#ifndef _S390_GDBREGS_H
+#define _S390_GDBREGS_H
+
+#ifdef __KERNEL__
+#include <asm/s390-regs-common.h>
+#else
+#include <s390x/s390-regs-common.h>
+#endif
+#define S390_MAX_INSTR_SIZE 6
+#define NUM_REGS      (2+NUM_GPRS+NUM_ACRS+NUM_CRS+1+NUM_FPRS)
+#define FIRST_ACR     (2+NUM_GPRS)
+#define LAST_ACR      (FIRST_ACR+NUM_ACRS-1)
+#define FIRST_CR      (FIRST_ACR+NUM_ACRS)
+#define LAST_CR       (FIRST_CR+NUM_CRS-1)
+
+#define PSWM_REGNUM    0
+#define PC_REGNUM      1
+#define	GP0_REGNUM     2		    /* GPR register 0 */ 
+#define GP_LAST_REGNUM (GP0_REGNUM+NUM_GPRS-1)
+#define RETADDR_REGNUM (GP0_REGNUM+14)                   /* Usually return address */
+#define SP_REGNUM      (GP0_REGNUM+15)	    /* Contains address of top of stack */
+#define FP_REGNUM     SP_REGNUM /* needed in findvar.c still */
+#define FRAME_REGNUM  (GP0_REGNUM+11)
+#define FPC_REGNUM    (GP0_REGNUM+NUM_GPRS+NUM_ACRS+NUM_CRS)
+#define FP0_REGNUM    (FPC_REGNUM+1) /* FPR (Floating point) register 0 */
+#define FPLAST_REGNUM (FP0_REGNUM+NUM_FPRS-1)	/* Last floating point register */
+
+/* The top of this structure is as similar as possible to a pt_regs structure to */
+/* simplify code */
+typedef struct
+{
+	S390_REGS_COMMON
+	__u32         crs[NUM_CRS];
+	s390_fp_regs  fp_regs;
+} s390_gdb_regs __attribute__((packed));
+
+#define REGISTER_NAMES                                           \
+{                                                                \
+"pswm","pswa",                                                   \
+"gpr0","gpr1","gpr2","gpr3","gpr4","gpr5","gpr6","gpr7",         \
+"gpr8","gpr9","gpr10","gpr11","gpr12","gpr13","gpr14","gpr15",   \
+"acr0","acr1","acr2","acr3","acr4","acr5","acr6","acr7",         \
+"acr8","acr9","acr10","acr11","acr12","acr13","acr14","acr15",   \
+"cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7",                 \
+"cr8","cr9","cr10","cr11","cr12","cr13","cr14","cr15",           \
+"fpc",                                                           \
+"fpr0","fpr1","fpr2","fpr3","fpr4","fpr5","fpr6","fpr7",         \
+"fpr8","fpr9","fpr10","fpr11","fpr12","fpr13","fpr14","fpr15"    \
+}
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define ACR0_OFFSET ((PSW_MASK_SIZE+PSW_ADDR_SIZE)+(GPR_SIZE*NUM_GPRS))
+#define CR0_OFFSET (ACR0_OFFSET+(ACR_SIZE+NUM_ACRS))
+#define FPC_OFFSET (CR0_OFFSET+(CR_SIZE*NUM_CRS))
+#define FP0_OFFSET (FPC_OFFSET+(FPC_SIZE+FPC_PAD_SIZE))
+
+#define REGISTER_BYTES    \
+((FP0_OFFSET)+(FPR_SIZE*NUM_FPRS))
+
+#define REGISTER_BYTE(N)  ((N)<=GP_LAST_REGNUM ? (N)*8: \
+(N) <= LAST_ACR ? (ACR0_OFFSET+(((N)-FIRST_ACR)*ACR_SIZE)): \
+(N) <= LAST_CR ? (CR0_OFFSET+(((N)-FIRST_CR)*CR_SIZE)): \
+(N) == FPC_REGNUM ? FPC_OFFSET:(FP0_OFFSET+(((N)-FP0_REGNUM)*FPR_SIZE)))
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/s390-regs-common.h linux/include/asm-s390x/s390-regs-common.h
--- v2.4.1/linux/include/asm-s390x/s390-regs-common.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/s390-regs-common.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,115 @@
+/*
+ *  include/asm-s390/s390-regs-common.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
+ *
+ *  this file is designed to keep as much compatibility between
+ *  gdb's representation of registers & the kernels representation of registers
+ *  as possible so as to minimise translation between gdb registers &
+ *  kernel registers please keep this matched with gdb & strace 
+ */
+
+#ifndef _S390_REGS_COMMON_H
+#define _S390_REGS_COMMON_H
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#endif
+#if defined(WANT_S390_TGT_DEFS) || defined(__KERNEL__)
+#define REGISTER_SIZE 8
+#endif
+#define NUM_GPRS      16
+#define GPR_SIZE      8
+#define PSW_MASK_SIZE 8
+#define PSW_ADDR_SIZE 8
+#define NUM_FPRS      16
+#define FPR_SIZE      8
+#define FPC_SIZE      4
+#define FPC_PAD_SIZE  4 /* gcc insists on aligning the fpregs */
+#define NUM_CRS       16
+#define CR_SIZE       8
+#define NUM_ACRS      16
+#define ACR_SIZE      4
+
+#define STACK_FRAME_OVERHEAD    160      /* size of minimum stack frame */
+
+#ifndef __ASSEMBLY__
+/* this typedef defines how a Program Status Word looks like */
+typedef struct 
+{
+        __u64   mask;
+        __u64   addr;
+} psw_t __attribute__ ((aligned(8)));
+
+typedef __u64 gpr_t;
+
+/* 2 __u32's are used for floats instead to compile  with a __STRICT_ANSI__ defined */ 
+typedef union
+{
+#ifdef __KERNEL__ 
+	__u64   d; /* mathemu.h gets upset otherwise */
+#else
+	double  d; /* ansi c dosen't like long longs & make sure that */
+	/* alignments are identical for both compiles */ 
+#endif
+       struct
+       {
+	       __u32 hi;
+	       __u32 lo;
+       } fp;
+       __u32    f; 
+} freg_t;
+
+typedef struct
+{
+/*
+  The compiler appears to like aligning freg_t on an 8 byte boundary
+  so I always access fpregs, this was causing fun when I was doing
+  coersions.
+ */
+	__u32   fpc;
+	freg_t  fprs[NUM_FPRS];              
+} s390_fp_regs;
+
+#define FPC_EXCEPTION_MASK      0xF8000000
+#define FPC_FLAGS_MASK          0x00F80000
+#define FPC_DXC_MASK            0x0000FF00
+#define FPC_RM_MASK             0x00000003
+#define FPC_VALID_MASK         ((FPC_EXCEPTION_MASK|FPC_FLAGS_MASK| \
+                                 FPC_DXC_MASK|FPC_RM_MASK))
+
+
+/*
+  gdb structures & the kernel have this much always in common
+ */
+#define S390_REGS_COMMON       \
+psw_t psw;                     \
+__u64 gprs[NUM_GPRS];          \
+__u32  acrs[NUM_ACRS];         \
+
+typedef struct
+{
+	S390_REGS_COMMON
+} s390_regs_common __attribute__ ((packed));
+
+
+/* Sequence of bytes for breakpoint illegal instruction.  */
+#define S390_BREAKPOINT {0x0,0x1}
+#define S390_BREAKPOINT_U16 ((__u16)0x0001)
+#define S390_SYSCALL_OPCODE ((__u16)0x0a00)
+#define S390_SYSCALL_SIZE   2
+#if defined(WANT_S390_TGT_DEFS) || defined(__KERNEL__)
+#define ADDR_BITS_REMOVE(addr) ((addr))
+#endif
+#endif
+#endif
+
+
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/s390_ext.h linux/include/asm-s390x/s390_ext.h
--- v2.4.1/linux/include/asm-s390x/s390_ext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/s390_ext.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,30 @@
+#ifndef _S390_EXTINT_H
+#define _S390_EXTINT_H
+
+/*
+ *  include/asm-s390/s390_ext.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+
+typedef void (*ext_int_handler_t)(struct pt_regs *regs, __u16 code);
+
+/*
+ * Warning: if you change ext_int_info_t you have to change the
+ * external interrupt handler in entry.S too.
+ */ 
+typedef struct ext_int_info_t {
+	struct ext_int_info_t *next;
+	ext_int_handler_t handler;
+	__u16 code;
+} __attribute__ ((packed)) ext_int_info_t;
+
+extern ext_int_info_t *ext_int_hash[];
+
+int register_external_interrupt(__u16 code, ext_int_handler_t handler);
+int unregister_external_interrupt(__u16 code, ext_int_handler_t handler);
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/s390dyn.h linux/include/asm-s390x/s390dyn.h
--- v2.4.1/linux/include/asm-s390x/s390dyn.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/s390dyn.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,50 @@
+/*
+ *  arch/s390/kernel/s390dyn.h
+ *   S/390 data definitions for dynamic device attachment
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#ifndef __s390dyn_h
+#define __s390dyn_h
+
+struct _devreg;
+
+typedef  int  (* oper_handler_func_t)( int             irq,
+                                       struct _devreg *dreg);
+
+typedef struct _devreg_hc_t {
+	__u16 ctype;
+	__u8  cmode;
+	__u16 dtype;
+	__u8  dmode;
+   }  __attribute__ ((packed)) devreg_hc_t;
+
+typedef struct _devreg {
+	union {
+		int devno;
+		devreg_hc_t hc;       /* has controller info */
+	} ci;
+
+	int                  flag;
+	oper_handler_func_t  oper_func;
+	struct _devreg      *prev;
+	struct _devreg      *next;
+} devreg_t;
+
+#define DEVREG_EXACT_MATCH      0x00000001
+#define DEVREG_MATCH_DEV_TYPE   0x00000002
+#define DEVREG_MATCH_CU_TYPE    0x00000004
+#define DEVREG_NO_CU_INFO       0x00000008
+#define DEVREG_NO_DEV_INFO      0x00000010
+
+#define DEVREG_TYPE_DEVNO       0x80000000
+#define DEVREG_TYPE_DEVCHARS    0x40000000
+
+int        s390_device_register  ( devreg_t *drinfo );
+int        s390_device_unregister( devreg_t *dreg );
+devreg_t * s390_search_devreg    ( ioinfo_t *ioinfo );
+
+#endif /* __s390dyn */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/s390io.h linux/include/asm-s390x/s390io.h
--- v2.4.1/linux/include/asm-s390x/s390io.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/s390io.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,95 @@
+/*
+ *  arch/s390/kernel/s390io.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#ifndef __s390io_h
+#define __s390io_h
+
+/*
+ * IRQ data structure used by I/O subroutines
+ *
+ * Note : If bit flags are added, the "unused" value must be
+ *        decremented accordingly !
+ */
+typedef struct _ioinfo {
+     unsigned int  irq;           /* aka. subchannel number */
+     spinlock_t    irq_lock;      /* irq lock */
+
+     struct _ioinfo *prev;
+     struct _ioinfo *next;
+
+     union {
+        unsigned int info;
+        struct {
+           unsigned int  busy      : 1;  /* device currently in use */
+           unsigned int  oper      : 1;  /* device is operational */
+           unsigned int  fast      : 1;  /* post with "channel end", ...    */
+                                         /* ... don't wait for "device end" */
+                                         /* ... from do_IO() parameters     */
+           unsigned int  ready     : 1;  /* interrupt handler registered */
+           unsigned int  haltio    : 1;  /* halt_IO in process */
+           unsigned int  doio      : 1;  /* do_IO in process */
+           unsigned int  doio_q    : 1;  /* do_IO queued - only possible ... */
+                                         /* ... if 'fast' is set too */
+           unsigned int  w4final   : 1;  /* wait for final status, internally */
+                                         /* ... used with 'fast' setting only */
+           unsigned int  repall    : 1;  /* report every interrupt status */
+           unsigned int  unready   : 1;  /* deregister irq handler in process */
+           unsigned int  d_disable : 1;  /* delayed disabling required */
+           unsigned int  w4sense   : 1;  /* SENSE status pending */
+           unsigned int  syncio    : 1;  /* synchronous I/O requested */
+           unsigned int  consns    : 1;  /* concurrent sense is available */
+           unsigned int  delsense  : 1;  /* delayed SENSE required */
+           unsigned int  s_pend    : 1;  /* status pending condition */
+           unsigned int  pgid      : 1;  /* "path group ID" is valid */
+           unsigned int  pgid_supp : 1;  /* "path group ID" command is supported */
+           unsigned int  esid      : 1;  /* Ext. SenseID supported by HW */
+           unsigned int  rcd       : 1;  /* RCD supported by HW */
+           unsigned int  repnone   : 1;  /* don't call IRQ handler on interrupt */
+           unsigned int  newreq    : 1;  /* new register interface */
+           unsigned int  dval      : 1;  /* device number valid */
+           unsigned int  unknown   : 1;  /* unknown device - if SenseID failed */
+           unsigned int  unused    : (sizeof(unsigned int)*8 - 24); /* unused */
+              } __attribute__ ((packed)) flags;
+        } ui;
+
+     unsigned long u_intparm;     /* user interruption parameter */
+     senseid_t     senseid;       /* SenseID info */
+     irq_desc_t    irq_desc;      /* irq descriptor */
+     not_oper_handler_func_t nopfunc; 	/* not oper handler */		
+     __u8          ulpm;          /* logical path mask used for I/O */
+     __u8          opm;           /* path mask of operational paths */
+     __u16         devno;         /* device number */
+     pgid_t        pgid;          /* path group ID */
+     schib_t       schib;         /* subchannel information block */
+     orb_t         orb;           /* operation request block */
+     devstat_t     devstat;       /* device status */
+     ccw1_t       *qcpa;          /* queued channel program */
+     ccw1_t        senseccw;      /* ccw for sense command */
+     __u8          sense_data[32];/* buffer for basic sense */
+     unsigned int  stctl;         /* accumulated status control from irb */
+     unsigned long qintparm;      /* queued interruption parameter  */
+     unsigned long qflag;         /* queued flags */
+     __u8          qlpm;          /* queued logical path mask */
+     __u32         syncnt;       /* sync I/O recursive usage count */
+
+   } __attribute__ ((aligned(8))) ioinfo_t;
+
+#define IOINFO_FLAGS_BUSY    0x80000000
+#define IOINFO_FLAGS_OPER    0x40000000
+#define IOINFO_FLAGS_FAST    0x20000000
+#define IOINFO_FLAGS_READY   0x10000000
+#define IOINFO_FLAGS_HALTIO  0x08000000
+#define IOINFO_FLAGS_DOIO    0x04000000
+#define IOINFO_FLAGS_DOIO_Q  0x02000000
+#define IOINFO_FLAGS_W4FINAL 0x01000000
+#define IOINFO_FLAGS_REPALL  0x00800000
+
+extern ioinfo_t *ioinfo[];
+
+#endif  /* __s390io_h */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/s390mach.h linux/include/asm-s390x/s390mach.h
--- v2.4.1/linux/include/asm-s390x/s390mach.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/s390mach.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,106 @@
+/*
+ *  arch/s390/kernel/s390mach.h
+ *   S/390 data definitions for machine check processing
+ *
+ *  S390 version
+ *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Ingo Adlung (adlung@de.ibm.com)
+ */
+
+#ifndef __s390mach_h
+#define __s390mach_h
+
+#include <asm/types.h>
+
+typedef struct _mci {
+	__u32	to_be_defined_1 :  9;
+	__u32 cp              :  1; /* channel-report pending */
+	__u32	to_be_defined_2 : 22;
+	__u32	to_be_defined_3;
+	} mci_t;
+
+//
+// machine-check-interruption code
+//
+typedef struct _mcic {
+   union _mcc {
+      __u64 mcl;	/* machine check int. code - long info */	
+      mci_t mcd;  /* machine check int. code - details   */
+   } mcc;
+} __attribute__ ((packed)) mcic_t;
+
+//
+// Channel Report Word
+//
+typedef struct _crw {
+	__u32 res1    :  1;   /* reserved zero */
+	__u32 slct    :  1;   /* solicited */
+	__u32 oflw    :  1;   /* overflow */
+	__u32 chn     :  1;   /* chained */
+	__u32 rsc     :  4;   /* reporting source code */
+	__u32 anc     :  1;   /* ancillary report */
+	__u32 res2    :  1;   /* reserved zero */
+	__u32 erc     :  6;   /* error-recovery code */
+	__u32 rsid    : 16;   /* reporting-source ID */
+} __attribute__ ((packed)) crw_t;
+
+#define CRW_RSC_MONITOR  0x2  /* monitoring facility */
+#define CRW_RSC_SCH      0x3  /* subchannel */
+#define CRW_RSC_CPATH    0x4  /* channel path */
+#define CRW_RSC_CONFIG   0x9  /* configuration-alert facility */
+#define CRW_RSC_CSS      0xB  /* channel subsystem */
+
+#define CRW_ERC_EVENT    0x00 /* event information pending */
+#define CRW_ERC_AVAIL    0x01 /* available */
+#define CRW_ERC_INIT     0x02 /* initialized */
+#define CRW_ERC_TERROR   0x03 /* temporary error */
+#define CRW_ERC_IPARM    0x04 /* installed parm initialized */
+#define CRW_ERC_TERM     0x05 /* terminal */
+#define CRW_ERC_PERRN    0x06 /* perm. error, fac. not init */
+#define CRW_ERC_PERRI    0x07 /* perm. error, facility init */
+#define CRW_ERC_PMOD     0x08 /* installed parameters modified */
+
+#define MAX_CRW_PENDING  1024
+#define MAX_MACH_PENDING 1024
+
+//
+// CRW Entry
+//
+typedef struct _crwe {
+	crw_t   crw;
+	struct _crwe *crwe_next;
+} __attribute__ ((packed)) crwe_t;
+
+typedef struct _mache {
+	spinlock_t     lock;
+	unsigned int   status;
+	mcic_t         mcic;
+	union _mc {
+	   crwe_t     *crwe;		/* CRW if applicable */
+   } mc;
+	struct _mache *next;
+	struct _mache *prev;
+} mache_t;
+
+#define MCHCHK_STATUS_TO_PROCESS    0x00000001
+#define MCHCHK_STATUS_IN_PROGRESS   0x00000002
+#define MCHCHK_STATUS_WAITING       0x00000004
+
+void s390_init_machine_check( void );
+void s390_do_machine_check  ( void );
+void s390_do_crw_pending    ( crwe_t *pcrwe );
+
+extern __inline__ int stcrw( __u32 *pcrw )
+{
+        int ccode;
+
+        __asm__ __volatile__(
+                "STCRW 0(%1)\n\t"
+                "IPM %0\n\t"
+                "SRL %0,28\n\t"
+                : "=d" (ccode) : "a" (pcrw)
+                : "cc", "1" );
+        return ccode;
+}
+
+#endif /* __s390mach */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/scatterlist.h linux/include/asm-s390x/scatterlist.h
--- v2.4.1/linux/include/asm-s390x/scatterlist.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/scatterlist.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,13 @@
+#ifndef _ASMS390X_SCATTERLIST_H
+#define _ASMS390X_SCATTERLIST_H
+
+struct scatterlist {
+    char *  address;    /* Location data is to be transferred to */
+    char * alt_address; /* Location of actual if address is a 
+			 * dma indirect buffer.  NULL otherwise */
+    unsigned int length;
+};
+
+#define ISA_DMA_THRESHOLD (0xffffffffffffffff)
+
+#endif /* _ASMS390X_SCATTERLIST_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/segment.h linux/include/asm-s390x/segment.h
--- v2.4.1/linux/include/asm-s390x/segment.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/segment.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,4 @@
+#ifndef _ASM_SEGMENT_H
+#define _ASM_SEGMENT_H
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/semaphore-helper.h linux/include/asm-s390x/semaphore-helper.h
--- v2.4.1/linux/include/asm-s390x/semaphore-helper.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/semaphore-helper.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,100 @@
+/*
+ *  include/asm-s390/semaphore-helper.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ *  Derived from "include/asm-i386/semaphore-helper.h"
+ *    (C) Copyright 1996 Linus Torvalds
+ *    (C) Copyright 1999 Andrea Arcangeli
+ */
+
+#ifndef _S390_SEMAPHORE_HELPER_H
+#define _S390_SEMAPHORE_HELPER_H
+
+/*
+ * These two _must_ execute atomically wrt each other.
+ *
+ * This is trivially done with load_locked/store_cond,
+ * but on the x86 we need an external synchronizer.
+ */
+static inline void wake_one_more(struct semaphore * sem)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	sem->waking++;
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+}
+
+static inline int waking_non_zero(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->waking > 0) {
+		sem->waking--;
+		ret = 1;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+/*
+ * waking_non_zero_interruptible:
+ *	1	got the lock
+ *	0	go to sleep
+ *	-EINTR	interrupted
+ *
+ * If we give up we must undo our count-decrease we previously did in down().
+ * Subtle: up() can continue to happens and increase the semaphore count
+ * even during our critical section protected by the spinlock. So
+ * we must remeber to undo the sem->waking that will be run from
+ * wake_one_more() some time soon, if the semaphore count become > 0.
+ */
+static inline int waking_non_zero_interruptible(struct semaphore *sem,
+						struct task_struct *tsk)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->waking > 0) {
+		sem->waking--;
+		ret = 1;
+	} else if (signal_pending(tsk)) {
+               if (atomic_inc_and_test_greater_zero(&sem->count))
+                       sem->waking--;
+		ret = -EINTR;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+/*
+ * waking_non_zero_trylock:
+ *	1	failed to lock
+ *	0	got the lock
+ *
+ * Implementation details are the same of the interruptible case.
+ */
+static inline int waking_non_zero_trylock(struct semaphore *sem)
+{
+	unsigned long flags;
+	int ret = 1;
+
+	spin_lock_irqsave(&semaphore_wake_lock, flags);
+	if (sem->waking <= 0)
+        {
+                if (atomic_inc_and_test_greater_zero(&sem->count))
+                        sem->waking--;
+        } else {
+		sem->waking--;
+		ret = 0;
+	}
+	spin_unlock_irqrestore(&semaphore_wake_lock, flags);
+	return ret;
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/semaphore.h linux/include/asm-s390x/semaphore.h
--- v2.4.1/linux/include/asm-s390x/semaphore.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/semaphore.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,191 @@
+/*
+ *  include/asm-s390/semaphore.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ *  Derived from "include/asm-i386/semaphore.h"
+ *    (C) Copyright 1996 Linus Torvalds
+ */
+
+#ifndef _S390_SEMAPHORE_H
+#define _S390_SEMAPHORE_H
+
+#include <asm/system.h>
+#include <asm/atomic.h>
+#include <linux/wait.h>
+
+struct semaphore {
+	atomic_t count;
+	int sleepers;
+	wait_queue_head_t wait;
+};
+
+#define __SEM_DEBUG_INIT(name)
+
+#define __SEMAPHORE_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
+	__SEM_DEBUG_INIT(name) }
+
+#define __MUTEX_INITIALIZER(name) \
+	__SEMAPHORE_INITIALIZER(name,1)
+
+#define __DECLARE_SEMAPHORE_GENERIC(name,count) \
+	struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
+
+#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
+#define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
+
+static inline void sema_init (struct semaphore *sem, int val)
+{
+	*sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
+}
+
+static inline void init_MUTEX (struct semaphore *sem)
+{
+	sema_init(sem, 1);
+}
+
+static inline void init_MUTEX_LOCKED (struct semaphore *sem)
+{
+	sema_init(sem, 0);
+}
+
+asmlinkage void __down_failed(void /* special register calling convention */);
+asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
+asmlinkage int  __down_failed_trylock(void  /* params in registers */);
+asmlinkage void __up_wakeup(void /* special register calling convention */);
+
+asmlinkage void __down(struct semaphore * sem);
+asmlinkage int  __down_interruptible(struct semaphore * sem);
+asmlinkage int  __down_trylock(struct semaphore * sem);
+asmlinkage void __up(struct semaphore * sem);
+
+static inline void down(struct semaphore * sem)
+{
+	if (atomic_dec_return(&sem->count) < 0)
+		__down(sem);
+}
+
+static inline int down_interruptible(struct semaphore * sem)
+{
+	int ret = 0;
+
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_interruptible(sem);
+	return ret;
+}
+
+static inline int down_trylock(struct semaphore * sem)
+{
+	int ret = 0;
+
+	if (atomic_dec_return(&sem->count) < 0)
+		ret = __down_trylock(sem);
+	return ret;
+}
+
+static inline void up(struct semaphore * sem)
+{
+	if (atomic_inc_return(&sem->count) <= 0)
+		__up(sem);
+}
+
+/* rw mutexes (should that be mutices? =) -- throw rw
+ * spinlocks and semaphores together, and this is what we
+ * end up with...
+ *
+ * The lock is initialized to BIAS.  This way, a writer
+ * subtracts BIAS ands gets 0 for the case of an uncontended
+ * lock.  Readers decrement by 1 and see a positive value
+ * when uncontended, negative if there are writers waiting
+ * (in which case it goes to sleep).
+ *
+ * The value 0x01000000 supports up to 128 processors and
+ * lots of processes.  BIAS must be chosen such that subl'ing
+ * BIAS once per CPU will result in the long remaining
+ * negative.
+ *
+ * In terms of fairness, this should result in the lock
+ * flopping back and forth between readers and writers
+ * under heavy use.
+ *
+ *		-ben
+ */
+struct rw_semaphore {
+	atomic_t		count;
+	volatile unsigned int	write_bias_granted;
+	volatile unsigned int	read_bias_granted;
+	wait_queue_head_t	wait;
+	wait_queue_head_t	write_bias_wait;
+};
+
+#define RW_LOCK_BIAS		 0x01000000
+
+#define __RWSEM_DEBUG_INIT	/* */
+
+#define __RWSEM_INITIALIZER(name,count) \
+{ ATOMIC_INIT(count), 0, 0, __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
+	__WAIT_QUEUE_HEAD_INITIALIZER((name).write_bias_wait) \
+	__SEM_DEBUG_INIT(name) __RWSEM_DEBUG_INIT }
+
+#define __DECLARE_RWSEM_GENERIC(name,count) \
+	struct rw_semaphore name = __RWSEM_INITIALIZER(name,count)
+
+#define DECLARE_RWSEM(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS)
+#define DECLARE_RWSEM_READ_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,RW_LOCK_BIAS-1)
+#define DECLARE_RWSEM_WRITE_LOCKED(name) __DECLARE_RWSEM_GENERIC(name,0)
+
+static inline void init_rwsem(struct rw_semaphore *sem)
+{
+	atomic_set(&sem->count, RW_LOCK_BIAS);
+	sem->read_bias_granted = 0;
+	sem->write_bias_granted = 0;
+	init_waitqueue_head(&sem->wait);
+	init_waitqueue_head(&sem->write_bias_wait);
+}
+
+extern void __down_read_failed(int, struct rw_semaphore *);
+extern void __down_write_failed(int, struct rw_semaphore *);
+extern void __rwsem_wake(int, struct rw_semaphore *);
+
+static inline void down_read(struct rw_semaphore *sem)
+{
+	int count;
+	count = atomic_dec_return(&sem->count);
+	if (count < 0)
+		__down_read_failed(count, sem);
+}
+
+static inline void down_write(struct rw_semaphore *sem)
+{
+	int count;
+	count = atomic_add_return (-RW_LOCK_BIAS, &sem->count);
+	if (count < 0)
+		__down_write_failed(count, sem);
+}
+
+/* When a reader does a release, the only significant
+ * case is when there was a writer waiting, and we've
+ * bumped the count to 0: we must wake the writer up.
+ */
+static inline void up_read(struct rw_semaphore *sem)
+{
+	int count;
+	count = atomic_inc_return(&sem->count);
+	if (count == 0)
+		__rwsem_wake(count, sem);
+}
+
+/* releasing the writer is easy -- just release it and
+ * wake up any sleepers.
+ */
+static inline void up_write(struct rw_semaphore *sem)
+{
+	int count;
+	count = atomic_add_return(RW_LOCK_BIAS, &sem->count);
+	if (count >= 0 && count < RW_LOCK_BIAS)
+		__rwsem_wake(count, sem);
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/sembuf.h linux/include/asm-s390x/sembuf.h
--- v2.4.1/linux/include/asm-s390x/sembuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/sembuf.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,22 @@
+#ifndef _S390_SEMBUF_H
+#define _S390_SEMBUF_H
+
+/* 
+ * The semid64_ds structure for S/390 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct semid64_ds {
+	struct ipc64_perm sem_perm;		/* permissions .. see ipc.h */
+	__kernel_time_t	sem_otime;		/* last semop time */
+	__kernel_time_t	sem_ctime;		/* last change time */
+	unsigned long	sem_nsems;		/* no. of semaphores in array */
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+};
+
+#endif /* _S390_SEMBUF_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/setup.h linux/include/asm-s390x/setup.h
--- v2.4.1/linux/include/asm-s390x/setup.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/setup.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,52 @@
+/*
+ *  include/asm-s390/setup.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ */
+
+#ifndef _ASM_S390_SETUP_H
+#define _ASM_S390_SETUP_H
+
+#define PARMAREA 0x10400
+
+#ifndef __ASSEMBLER__
+
+#define ORIG_ROOT_DEV     (*(unsigned long *) (0x10400))
+#define MOUNT_ROOT_RDONLY (*(unsigned short *) (0x10408))
+#define MEMORY_SIZE       (*(unsigned long *)  (0x1040a))
+#define MACHINE_FLAGS     (*(unsigned long *)  (0x10412))
+#define INITRD_START      (*(unsigned long *)  (0x1041a))
+#define INITRD_SIZE       (*(unsigned long *)  (0x10422))
+#define RAMDISK_FLAGS     (*(unsigned short *) (0x1042a))
+#define COMMAND_LINE      ((char *)            (0x10480))
+
+#else 
+
+#define ORIG_ROOT_DEV     0x10400
+#define MOUNT_ROOT_RDONLY 0x10408
+#define MEMORY_SIZE       0x1040a
+#define MACHINE_FLAGS     0x10412
+#define INITRD_START      0x1041a
+#define INITRD_SIZE       0x10422
+#define RAMDISK_FLAGS     0x1042a
+#define COMMAND_LINE      0x10480
+
+#endif
+
+#define COMMAND_LINE_SIZE 896
+/*
+ * Machine features detected in head.S
+ */
+#define MACHINE_IS_VM    (MACHINE_FLAGS & 1)
+#define MACHINE_IS_P390  (MACHINE_FLAGS & 4)
+
+#define RAMDISK_ORIGIN            0x800000
+#define RAMDISK_SIZE              0x800000
+#define RAMDISK_BLKSIZE           0x1000
+#define RAMDISK_IMAGE_START_MASK  0x07FF
+#define RAMDISK_PROMPT_FLAG       0x8000
+#define RAMDISK_LOAD_FLAG         0x4000
+
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/shmbuf.h linux/include/asm-s390x/shmbuf.h
--- v2.4.1/linux/include/asm-s390x/shmbuf.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/shmbuf.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,38 @@
+#ifndef _S390_SHMBUF_H
+#define _S390_SHMBUF_H
+
+/* 
+ * The shmid64_ds structure for S/390 architecture.
+ * Note extra padding because this structure is passed back and forth
+ * between kernel and user space.
+ *
+ * Pad space is left for:
+ * - 2 miscellaneous 32-bit values
+ */
+
+struct shmid64_ds {
+	struct ipc64_perm	shm_perm;	/* operation perms */
+	size_t			shm_segsz;	/* size of segment (bytes) */
+	__kernel_time_t		shm_atime;	/* last attach time */
+	__kernel_time_t		shm_dtime;	/* last detach time */
+	__kernel_time_t		shm_ctime;	/* last change time */
+	__kernel_pid_t		shm_cpid;	/* pid of creator */
+	__kernel_pid_t		shm_lpid;	/* pid of last operator */
+	unsigned long		shm_nattch;	/* no. of current attaches */
+	unsigned long		__unused1;
+	unsigned long		__unused2;
+};
+
+struct shminfo64 {
+	unsigned long	shmmax;
+	unsigned long	shmmin;
+	unsigned long	shmmni;
+	unsigned long	shmseg;
+	unsigned long	shmall;
+	unsigned long	__unused1;
+	unsigned long	__unused2;
+	unsigned long	__unused3;
+	unsigned long	__unused4;
+};
+
+#endif /* _S390_SHMBUF_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/shmparam.h linux/include/asm-s390x/shmparam.h
--- v2.4.1/linux/include/asm-s390x/shmparam.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/shmparam.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,13 @@
+/*
+ *  include/asm-s390/shmparam.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/shmparam.h"
+ */
+#ifndef _ASM_S390_SHMPARAM_H
+#define _ASM_S390_SHMPARAM_H
+
+#define SHMLBA PAGE_SIZE                 /* attach addr a multiple of this */
+
+#endif /* _ASM_S390_SHMPARAM_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/sigcontext.h linux/include/asm-s390x/sigcontext.h
--- v2.4.1/linux/include/asm-s390x/sigcontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/sigcontext.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,56 @@
+/*
+ *  include/asm-s390/sigcontext.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ */
+
+#ifndef _ASM_S390_SIGCONTEXT_H
+#define _ASM_S390_SIGCONTEXT_H
+
+#define __NUM_GPRS 16
+#define __NUM_FPRS 16
+#define __NUM_ACRS 16
+
+/* Has to be at least _NSIG_WORDS from asm/signal.h */
+#define _SIGCONTEXT_NSIG	64
+#define _SIGCONTEXT_NSIG_BPW	64 
+/* Size of stack frame allocated when calling signal handler. */
+#define __SIGNAL_FRAMESIZE	160
+#define _SIGCONTEXT_NSIG_WORDS	(_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW)
+#define _SIGMASK_COPY_SIZE	(sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS)
+
+typedef struct 
+{
+        unsigned long mask;
+        unsigned long addr;
+} _psw_t __attribute__ ((aligned(8)));
+
+typedef struct
+{
+	_psw_t psw;
+	unsigned long gprs[__NUM_GPRS];
+	unsigned int  acrs[__NUM_ACRS];
+} _s390_regs_common __attribute__ ((packed));
+
+typedef struct
+{
+	unsigned int fpc;
+	double   fprs[__NUM_FPRS];
+} _s390_fp_regs;
+
+typedef struct
+{
+	_s390_regs_common regs;
+	_s390_fp_regs     fpregs;
+} _sigregs;
+
+struct sigcontext
+{
+	unsigned long	oldmask[_SIGCONTEXT_NSIG_WORDS];
+	_sigregs        *sregs;
+};
+
+
+#endif
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/siginfo.h linux/include/asm-s390x/siginfo.h
--- v2.4.1/linux/include/asm-s390x/siginfo.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/siginfo.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,240 @@
+/*
+ *  include/asm-s390/siginfo.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/siginfo.h"
+ */
+
+#ifndef _S390_SIGINFO_H
+#define _S390_SIGINFO_H
+
+#include <linux/types.h>
+
+/* XXX: This structure was copied from the Alpha; is there an iBCS version?  */
+
+typedef union sigval {
+	int sival_int;
+	void *sival_ptr;
+} sigval_t;
+
+#define SI_MAX_SIZE	128
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct siginfo {
+	int si_signo;
+	int si_errno;
+	int si_code;
+
+	union {
+		int _pad[SI_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			unsigned int _timer1;
+			unsigned int _timer2;
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			pid_t _pid;		/* sender's pid */
+			uid_t _uid;		/* sender's uid */
+			sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			pid_t _pid;		/* which child */
+			uid_t _uid;		/* sender's uid */
+			int _status;		/* exit code */
+			clock_t _utime;
+			clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			void *_addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+	} _sifields;
+} siginfo_t;
+
+/*
+ * How these fields are to be accessed.
+ */
+#define si_pid		_sifields._kill._pid
+#define si_uid		_sifields._kill._uid
+#define si_status	_sifields._sigchld._status
+#define si_utime	_sifields._sigchld._utime
+#define si_stime	_sifields._sigchld._stime
+#define si_value	_sifields._rt._sigval
+#define si_int		_sifields._rt._sigval.sival_int
+#define si_ptr		_sifields._rt._sigval.sival_ptr
+#define si_addr		_sifields._sigfault._addr
+#define si_band		_sifields._sigpoll._band
+#define si_fd		_sifields._sigpoll._fd
+
+#ifdef __KERNEL__
+#define __SI_MASK	0xffff0000
+#define __SI_KILL	(0 << 16)
+#define __SI_TIMER	(1 << 16)
+#define __SI_POLL	(2 << 16)
+#define __SI_FAULT	(3 << 16)
+#define __SI_CHLD	(4 << 16)
+#define __SI_RT		(5 << 16)
+#define __SI_CODE(T,N)	((T) << 16 | ((N) & 0xffff))
+#else
+#define __SI_KILL	0
+#define __SI_TIMER	0
+#define __SI_POLL	0
+#define __SI_FAULT	0
+#define __SI_CHLD	0
+#define __SI_RT		0
+#define __SI_CODE(T,N)	(N)
+#endif
+
+/*
+ * si_code values
+ * Digital reserves positive values for kernel-generated signals.
+ */
+#define SI_USER		0	/* sent by kill, sigsend, raise */
+#define SI_KERNEL	0x80	/* sent by the kernel from somewhere */
+#define SI_QUEUE	-1	/* sent by sigqueue */
+#define SI_TIMER	-2	/* sent by timer expiration */
+#define SI_MESGQ	-3	/* sent by real time mesq state change */
+#define SI_ASYNCIO	-4	/* sent by AIO completion */
+#define SI_SIGIO	-5	/* sent by queued SIGIO */
+
+#define SI_FROMUSER(siptr)	((siptr)->si_code <= 0)
+#define SI_FROMKERNEL(siptr)	((siptr)->si_code > 0)
+
+/*
+ * SIGILL si_codes
+ */
+#define ILL_ILLOPC	1	/* illegal opcode */
+#define ILL_ILLOPN	2	/* illegal operand */
+#define ILL_ILLADR	3	/* illegal addressing mode */
+#define ILL_ILLTRP	4	/* illegal trap */
+#define ILL_PRVOPC	5	/* privileged opcode */
+#define ILL_PRVREG	6	/* privileged register */
+#define ILL_COPROC	7	/* coprocessor error */
+#define ILL_BADSTK	8	/* internal stack error */
+#define NSIGILL		8
+
+/*
+ * SIGFPE si_codes
+ */
+#define FPE_INTDIV	1	/* integer divide by zero */
+#define FPE_INTOVF	2	/* integer overflow */
+#define FPE_FLTDIV	3	/* floating point divide by zero */
+#define FPE_FLTOVF	4	/* floating point overflow */
+#define FPE_FLTUND	5	/* floating point underflow */
+#define FPE_FLTRES	6	/* floating point inexact result */
+#define FPE_FLTINV	7	/* floating point invalid operation */
+#define FPE_FLTSUB	8	/* subscript out of range */
+#define NSIGFPE		8
+
+/*
+ * SIGSEGV si_codes
+ */
+#define SEGV_MAPERR	1	/* address not mapped to object */
+#define SEGV_ACCERR	2	/* invalid permissions for mapped object */
+#define NSIGSEGV	2
+
+/*
+ * SIGBUS si_codes
+ */
+#define BUS_ADRALN	1	/* invalid address alignment */
+#define BUS_ADRERR	2	/* non-existant physical address */
+#define BUS_OBJERR	3	/* object specific hardware error */
+#define NSIGBUS		3
+
+/*
+ * SIGTRAP si_codes
+ */
+#define TRAP_BRKPT	1	/* process breakpoint */
+#define TRAP_TRACE	2	/* process trace trap */
+#define NSIGTRAP	2
+
+/*
+ * SIGCHLD si_codes
+ */
+#define CLD_EXITED	1	/* child has exited */
+#define CLD_KILLED	2	/* child was killed */
+#define CLD_DUMPED	3	/* child terminated abnormally */
+#define CLD_TRAPPED	4	/* traced child has trapped */
+#define CLD_STOPPED	5	/* child has stopped */
+#define CLD_CONTINUED	6	/* stopped child has continued */
+#define NSIGCHLD
+
+/*
+ * SIGPOLL si_codes
+ */
+#define POLL_IN		1	/* data input available */
+#define POLL_OUT	2	/* output buffers available */
+#define POLL_MSG	3	/* input message available */
+#define POLL_ERR	4	/* i/o error */
+#define POLL_PRI	5	/* high priority input available */
+#define POLL_HUP	6	/* device disconnected */
+#define NSIGPOLL	6
+
+/*
+ * sigevent definitions
+ * 
+ * It seems likely that SIGEV_THREAD will have to be handled from 
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+#define SIGEV_SIGNAL	0	/* notify via signal */
+#define SIGEV_NONE	1	/* other notification: meaningless */
+#define SIGEV_THREAD	2	/* deliver via thread creation */
+
+#define SIGEV_MAX_SIZE	64
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+
+typedef struct sigevent {
+	sigval_t sigev_value;
+	int sigev_signo;
+	int sigev_notify;
+	union {
+		int _pad[SIGEV_PAD_SIZE];
+
+		struct {
+			void (*_function)(sigval_t);
+			void *_attribute;	/* really pthread_attr_t */
+		} _sigev_thread;
+	} _sigev_un;
+} sigevent_t;
+
+#define sigev_notify_function	_sigev_un._sigev_thread._function
+#define sigev_notify_attributes	_sigev_un._sigev_thread._attribute
+
+#ifdef __KERNEL__
+#include <linux/string.h>
+
+extern inline void copy_siginfo(siginfo_t *to, siginfo_t *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(siginfo_t));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, 3*sizeof(int) + sizeof(from->_sifields._sigchld));
+}
+
+extern int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from);
+
+#endif /* __KERNEL__ */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/signal.h linux/include/asm-s390x/signal.h
--- v2.4.1/linux/include/asm-s390x/signal.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/signal.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,185 @@
+/*
+ *  include/asm-s390/signal.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/signal.h"
+ */
+
+#ifndef _ASMS390_SIGNAL_H
+#define _ASMS390_SIGNAL_H
+
+#include <linux/types.h>
+
+/* Avoid too many header ordering problems.  */
+struct siginfo;
+
+#ifdef __KERNEL__
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+#include <asm/sigcontext.h>
+#define _NSIG           _SIGCONTEXT_NSIG
+#define _NSIG_BPW       _SIGCONTEXT_NSIG_BPW
+#define _NSIG_WORDS     _SIGCONTEXT_NSIG_WORDS
+
+typedef unsigned long old_sigset_t;             /* at least 32 bits */
+
+typedef struct {
+        unsigned long sig[_NSIG_WORDS];
+} sigset_t;
+
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+#define NSIG            32
+typedef unsigned long sigset_t;
+
+#endif /* __KERNEL__ */
+
+#define SIGHUP           1
+#define SIGINT           2
+#define SIGQUIT          3
+#define SIGILL           4
+#define SIGTRAP          5
+#define SIGABRT          6
+#define SIGIOT           6
+#define SIGBUS           7
+#define SIGFPE           8
+#define SIGKILL          9
+#define SIGUSR1         10
+#define SIGSEGV         11
+#define SIGUSR2         12
+#define SIGPIPE         13
+#define SIGALRM         14
+#define SIGTERM         15
+#define SIGSTKFLT       16
+#define SIGCHLD         17
+#define SIGCONT         18
+#define SIGSTOP         19
+#define SIGTSTP         20
+#define SIGTTIN         21
+#define SIGTTOU         22
+#define SIGURG          23
+#define SIGXCPU         24
+#define SIGXFSZ         25
+#define SIGVTALRM       26
+#define SIGPROF         27
+#define SIGWINCH        28
+#define SIGIO           29
+#define SIGPOLL         SIGIO
+/*
+#define SIGLOST         29
+*/
+#define SIGPWR          30
+#define SIGUNUSED       31
+
+/* These should not be considered constants from userland.  */
+#define SIGRTMIN        32
+#define SIGRTMAX        (_NSIG-1)
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define SA_NOCLDSTOP    0x00000001
+#define SA_NOCLDWAIT    0x00000002 /* not supported yet */
+#define SA_SIGINFO      0x00000004
+#define SA_ONSTACK      0x08000000
+#define SA_RESTART      0x10000000
+#define SA_NODEFER      0x40000000
+#define SA_RESETHAND    0x80000000
+
+#define SA_NOMASK       SA_NODEFER
+#define SA_ONESHOT      SA_RESETHAND
+#define SA_INTERRUPT    0x20000000 /* dummy -- ignored */
+
+#define SA_RESTORER     0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define SS_ONSTACK      1
+#define SS_DISABLE      2
+
+#define MINSIGSTKSZ     2048
+#define SIGSTKSZ        8192
+
+#ifdef __KERNEL__
+
+/*
+ * These values of sa_flags are used only by the kernel as part of the
+ * irq handling routines.
+ *
+ * SA_INTERRUPT is also used by the irq handling routines.
+ * SA_SHIRQ is for shared interrupt support on PCI and EISA.
+ */
+#define SA_PROBE                SA_ONESHOT
+#define SA_SAMPLE_RANDOM        SA_RESTART
+#define SA_SHIRQ                0x04000000
+#endif
+
+#define SIG_BLOCK          0    /* for blocking signals */
+#define SIG_UNBLOCK        1    /* for unblocking signals */
+#define SIG_SETMASK        2    /* for setting the signal mask */
+
+/* Type of a signal handler.  */
+typedef void (*__sighandler_t)(int);
+
+#define SIG_DFL ((__sighandler_t)0)     /* default signal handling */
+#define SIG_IGN ((__sighandler_t)1)     /* ignore signal */
+#define SIG_ERR ((__sighandler_t)-1)    /* error return from signal */
+
+#ifdef __KERNEL__
+struct old_sigaction {
+        __sighandler_t sa_handler;
+        old_sigset_t sa_mask;
+        unsigned long sa_flags;
+        void (*sa_restorer)(void);
+};
+
+struct sigaction {
+        __sighandler_t sa_handler;
+        unsigned long sa_flags;
+        void (*sa_restorer)(void);
+        sigset_t sa_mask;               /* mask last for extensibility */
+};
+
+struct k_sigaction {
+        struct sigaction sa;
+};
+#else
+/* Here we must cater to libcs that poke about in kernel headers.  */
+
+struct sigaction {
+        union {
+          __sighandler_t _sa_handler;
+          void (*_sa_sigaction)(int, struct siginfo *, void *);
+        } _u;
+        sigset_t sa_mask;
+        unsigned long sa_flags;
+        void (*sa_restorer)(void);
+};
+
+#define sa_handler      _u._sa_handler
+#define sa_sigaction    _u._sa_sigaction
+
+#endif /* __KERNEL__ */
+
+typedef struct sigaltstack {
+        void *ss_sp;
+        int ss_flags;
+        size_t ss_size;
+} stack_t;
+
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/sigp.h linux/include/asm-s390x/sigp.h
--- v2.4.1/linux/include/asm-s390x/sigp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/sigp.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,159 @@
+/*
+ *  include/asm-s390/sigp.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  sigp.h by D.J. Barrow (c) IBM 1999
+ *  contains routines / structures for signalling other S/390 processors in an
+ *  SMP configuration.
+ */
+
+#ifndef __SIGP__
+#define __SIGP__
+
+#include <asm/ptrace.h>
+#include <asm/misc390.h>
+#include <asm/atomic.h>
+
+/* get real cpu address from logical cpu number */
+extern volatile int __cpu_logical_map[];
+
+typedef enum
+{
+	sigp_unassigned=0x0,
+	sigp_sense,
+	sigp_external_call,
+	sigp_emergency_signal,
+	sigp_start,
+	sigp_stop,
+	sigp_restart,
+	sigp_unassigned1,
+	sigp_unassigned2,
+	sigp_stop_and_store_status,
+	sigp_unassigned3,
+	sigp_initial_cpu_reset,
+	sigp_cpu_reset,
+	sigp_set_prefix,
+	sigp_store_status_at_address,
+	sigp_store_extended_status_at_address
+} sigp_order_code;
+
+typedef __u32 sigp_status_word;
+
+typedef enum
+{
+        sigp_order_code_accepted=0,
+	sigp_status_stored,
+	sigp_busy,
+	sigp_not_operational
+} sigp_ccode;
+
+
+/*
+ * Definitions for the external call
+ */
+
+/* 'Bit' signals, asynchronous */
+typedef enum
+{
+	ec_schedule=0,
+        ec_restart,
+        ec_halt,
+        ec_power_off,
+	ec_bit_last
+} ec_bit_sig;
+
+/* Signals which come with a parameter area */
+typedef enum
+{
+        ec_callback_sync,
+        ec_callback_async
+} ec_cmd_sig;
+
+/* state information for signals */
+typedef enum
+{
+	ec_pending,
+	ec_executing,
+	ec_done
+} ec_state;
+
+/* header for the queuing of callbacks */
+typedef struct ec_ext_call
+{
+	ec_cmd_sig cmd;
+	atomic_t status;
+	struct ec_ext_call *next;
+	void (*func)(void *info);
+	void *info;
+} ec_ext_call;
+
+/*
+ * Signal processor
+ */
+extern __inline__ sigp_ccode
+signal_processor(__u16 cpu_addr, sigp_order_code order_code)
+{
+	sigp_ccode ccode;
+
+	__asm__ __volatile__(
+		"    sgr    1,1\n"        /* parameter=0 in gpr 1 */
+		"    sigp   1,%1,0(%2)\n"
+		"    ipm    %0\n"
+		"    srl    %0,28"
+		: "=d" (ccode)
+		: "d" (__cpu_logical_map[cpu_addr]), "a" (order_code)
+		: "cc" , "memory", "1" );
+	return ccode;
+}
+
+/*
+ * Signal processor with parameter
+ */
+extern __inline__ sigp_ccode
+signal_processor_p(__u64 parameter,__u16 cpu_addr,sigp_order_code order_code)
+{
+	sigp_ccode ccode;
+	
+	__asm__ __volatile__(
+		"    lgr    1,%1\n"       /* parameter in gpr 1 */
+		"    sigp   1,%2,0(%3)\n"
+		"    ipm    %0\n"
+		"    srl    %0,28\n"
+		: "=d" (ccode)
+		: "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
+                  "a" (order_code)
+		: "cc" , "memory", "1" );
+	return ccode;
+}
+
+/*
+ * Signal processor with parameter and return status
+ */
+extern __inline__ sigp_ccode
+signal_processor_ps(__u32 *statusptr, __u64 parameter,
+		    __u16 cpu_addr, sigp_order_code order_code)
+{
+	sigp_ccode ccode;
+	
+	__asm__ __volatile__(
+		"    sgr    2,2\n"        /* clear status so it doesn't contain rubbish if not saved. */
+		"    lgr    3,%2\n"       /* parameter in gpr 3 */
+		"    sigp   2,%3,0(%4)\n"
+		"    stg    2,%1\n"
+		"    ipm    %0\n"
+		"    srl    %0,28\n"
+		: "=d" (ccode), "=m" (*statusptr)
+		: "d" (parameter), "d" (__cpu_logical_map[cpu_addr]),
+                  "a" (order_code)
+		: "cc" , "memory", "2" , "3"
+		);
+   return ccode;
+}
+
+#endif __SIGP__
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/smp.h linux/include/asm-s390x/smp.h
--- v2.4.1/linux/include/asm-s390x/smp.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/smp.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,78 @@
+/*
+ *  include/asm-s390/smp.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ */
+#ifndef __ASM_SMP_H
+#define __ASM_SMP_H
+#include <linux/config.h>
+#ifdef CONFIG_SMP
+#ifndef __ASSEMBLY__
+
+#include <asm/lowcore.h>
+#include <linux/kernel.h>   // FOR FASTCALL definition
+
+#define smp_processor_id() (current->processor)
+#define NO_PROC_ID		0xFF		/* No processor magic marker */
+
+/*
+ *	This magic constant controls our willingness to transfer
+ *	a process across CPUs. Such a transfer incurs misses on the L1
+ *	cache, and on a P6 or P5 with multiple L2 caches L2 hits. My
+ *	gut feeling is this will vary by board in value. For a board
+ *	with separate L2 cache it probably depends also on the RSS, and
+ *	for a board with shared L2 cache it ought to decay fast as other
+ *	processes are run.
+ */
+ 
+#define PROC_CHANGE_PENALTY	20		/* Schedule penalty */
+
+extern void count_cpus(void);
+
+extern __inline__ int cpu_logical_map(int cpu)
+{
+        return cpu;
+}
+
+extern __inline__ int cpu_number_map(int cpu)
+{
+        return cpu;
+}
+
+extern __inline__ __u16 hard_smp_processor_id(void)
+{
+        __u16 cpu_address;
+ 
+        __asm__ ("stap %0\n" : "=m" (cpu_address));
+        return cpu_address;
+}
+
+#define cpu_logical_map(cpu) (cpu)
+
+void smp_local_timer_interrupt(struct pt_regs * regs);
+
+/*
+  s390 specific smp.c headers
+ */
+typedef struct
+{
+	int        intresting;
+	sigp_ccode ccode; 
+	__u32      status;
+	__u16      cpu;
+} sigp_info;
+
+sigp_ccode
+smp_ext_call(int cpu, void (*callback)(void *info), void *info, int wait);
+void smp_ext_call_others(void (*callback)(void *info), void *info, int wait);
+sigp_ccode smp_ext_bitcall(int cpu, ec_bit_sig sig);
+void smp_ext_bitcall_others(ec_bit_sig sig);
+
+int smp_signal_others(sigp_order_code order_code,__u32 parameter,
+                      int spin,sigp_info *info);
+#endif
+#endif
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/smplock.h linux/include/asm-s390x/smplock.h
--- v2.4.1/linux/include/asm-s390x/smplock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/smplock.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,62 @@
+/*
+ *  include/asm-s390/smplock.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/smplock.h"
+ */
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+
+extern spinlock_t kernel_flag;
+
+#define kernel_locked()                spin_is_locked(&kernel_flag)
+
+/*
+ * Release global kernel lock and global interrupt lock
+ */
+#define release_kernel_lock(task, cpu)     \
+do {                                       \
+	if (task->lock_depth >= 0)         \
+		spin_unlock(&kernel_flag); \
+	release_irqlock(cpu);              \
+	__sti();                           \
+} while (0)
+
+/*
+ * Re-acquire the kernel lock
+ */
+#define reacquire_kernel_lock(task)        \
+do {                                       \
+	if (task->lock_depth >= 0)         \
+		spin_lock(&kernel_flag);   \
+} while (0)
+
+
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously,
+ * so we only need to worry about other
+ * CPU's.
+ */
+/*
+ * Getting the big kernel lock.
+ *
+ * This cannot happen asynchronously,
+ * so we only need to worry about other
+ * CPU's.
+ */
+extern __inline__ void lock_kernel(void)
+{
+        if (!++current->lock_depth)
+                spin_lock(&kernel_flag);
+}
+
+extern __inline__ void unlock_kernel(void)
+{
+        if (--current->lock_depth < 0)
+                spin_unlock(&kernel_flag);
+}
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/socket.h linux/include/asm-s390x/socket.h
--- v2.4.1/linux/include/asm-s390x/socket.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/socket.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,69 @@
+/*
+ *  include/asm-s390/socket.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/socket.h"
+ */
+
+#ifndef _ASM_SOCKET_H
+#define _ASM_SOCKET_H
+
+#include <asm/sockios.h>
+
+/* For setsockoptions(2) */
+#define SOL_SOCKET	1
+
+#define SO_DEBUG	1
+#define SO_REUSEADDR	2
+#define SO_TYPE		3
+#define SO_ERROR	4
+#define SO_DONTROUTE	5
+#define SO_BROADCAST	6
+#define SO_SNDBUF	7
+#define SO_RCVBUF	8
+#define SO_KEEPALIVE	9
+#define SO_OOBINLINE	10
+#define SO_NO_CHECK	11
+#define SO_PRIORITY	12
+#define SO_LINGER	13
+#define SO_BSDCOMPAT	14
+/* To add :#define SO_REUSEPORT 15 */
+#define SO_PASSCRED	16
+#define SO_PEERCRED	17
+#define SO_RCVLOWAT	18
+#define SO_SNDLOWAT	19
+#define SO_RCVTIMEO	20
+#define SO_SNDTIMEO	21
+
+/* Security levels - as per NRL IPv6 - don't actually do anything */
+#define SO_SECURITY_AUTHENTICATION		22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT	23
+#define SO_SECURITY_ENCRYPTION_NETWORK		24
+
+#define SO_BINDTODEVICE	25
+
+/* Socket filtering */
+#define SO_ATTACH_FILTER        26
+#define SO_DETACH_FILTER        27
+
+#define SO_PEERNAME		28
+#define SO_TIMESTAMP		29
+#define SCM_TIMESTAMP		SO_TIMESTAMP
+
+/* Nast libc5 fixup - bletch */
+#if defined(__KERNEL__)
+/* Socket types. */
+#define SOCK_STREAM	1		/* stream (connection) socket	*/
+#define SOCK_DGRAM	2		/* datagram (conn.less) socket	*/
+#define SOCK_RAW	3		/* raw socket			*/
+#define SOCK_RDM	4		/* reliably-delivered message	*/
+#define SOCK_SEQPACKET	5		/* sequential packet socket	*/
+#define SOCK_PACKET	10		/* linux specific way of	*/
+					/* getting packets at the dev	*/
+					/* level.  For writing rarp and	*/
+					/* other similar things on the	*/
+					/* user level.			*/
+#endif
+
+#endif /* _ASM_SOCKET_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/sockios.h linux/include/asm-s390x/sockios.h
--- v2.4.1/linux/include/asm-s390x/sockios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/sockios.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,20 @@
+/*
+ *  include/asm-s390/sockios.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/sockios.h"
+ */
+
+#ifndef __ARCH_S390_SOCKIOS__
+#define __ARCH_S390_SOCKIOS__
+
+/* Socket-level I/O control calls. */
+#define FIOSETOWN 	0x8901
+#define SIOCSPGRP	0x8902
+#define FIOGETOWN	0x8903
+#define SIOCGPGRP	0x8904
+#define SIOCATMARK	0x8905
+#define SIOCGSTAMP	0x8906		/* Get stamp */
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/softirq.h linux/include/asm-s390x/softirq.h
--- v2.4.1/linux/include/asm-s390x/softirq.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/softirq.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,35 @@
+/*
+ *  include/asm-s390/softirq.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/softirq.h"
+ */
+
+#ifndef __ASM_SOFTIRQ_H
+#define __ASM_SOFTIRQ_H
+
+#ifndef __LINUX_SMP_H
+#include <linux/smp.h>
+#endif
+
+#include <asm/atomic.h>
+#include <asm/hardirq.h>
+#include <asm/lowcore.h>
+
+#define cpu_bh_disable(cpu)	do { local_bh_count(cpu)++; barrier(); } while (0)
+#define cpu_bh_enable(cpu)	do { barrier(); local_bh_count(cpu)--; } while (0)
+
+#define local_bh_disable()	cpu_bh_disable(smp_processor_id())
+#define local_bh_enable()	cpu_bh_enable(smp_processor_id())
+
+#define in_softirq() (local_bh_count(smp_processor_id()) != 0)
+
+#endif	/* __ASM_SOFTIRQ_H */
+
+
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/spinlock.h linux/include/asm-s390x/spinlock.h
--- v2.4.1/linux/include/asm-s390x/spinlock.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/spinlock.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,119 @@
+/*
+ *  include/asm-s390/spinlock.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/spinlock.h"
+ */
+
+#ifndef __ASM_SPINLOCK_H
+#define __ASM_SPINLOCK_H
+
+/*
+ * Simple spin lock operations.  There are two variants, one clears IRQ's
+ * on the local processor, one does not.
+ *
+ * We make no fairness assumptions. They have a cost.
+ */
+
+typedef struct {
+	volatile unsigned int lock;
+} spinlock_t __attribute__ ((aligned (8)));
+
+#define SPIN_LOCK_UNLOCKED (spinlock_t) { 0 }
+#define spin_lock_init(lp) do { (lp)->lock = 0; } while(0)
+#define spin_unlock_wait(lp)	do { barrier(); } while(((volatile spinlock_t *)(lp))->lock)
+#define spin_is_locked(x) ((x)->lock != 0)
+
+extern inline void spin_lock(spinlock_t *lp)
+{
+        __asm__ __volatile("    bras  1,1f\n"
+                           "0:  # diag  0,0,68\n"
+                           "1:  slr   0,0\n"
+                           "    cs    0,1,%1\n"
+                           "    jl    0b\n"
+                           : "=m" (lp->lock)
+                           : "0" (lp->lock) : "0", "1", "cc" );
+}
+
+extern inline int spin_trylock(spinlock_t *lp)
+{
+	unsigned int result;
+	__asm__ __volatile("    slr   %1,%1\n"
+			   "    basr  1,0\n"
+			   "0:  cs    %1,1,%0"
+			   : "=m" (lp->lock), "=&d" (result)
+			   : "0" (lp->lock) : "1", "cc" );
+	return !result;
+}
+
+extern inline void spin_unlock(spinlock_t *lp)
+{
+	__asm__ __volatile("    xc 0(4,%0),0(%0)\n"
+                           "    bcr 15,0"
+			   : /* no output */ : "a" (lp) : "memory", "cc" );
+}
+		
+/*
+ * Read-write spinlocks, allowing multiple readers
+ * but only one writer.
+ *
+ * NOTE! it is quite common to have readers in interrupts
+ * but no interrupt writers. For those circumstances we
+ * can "mix" irq-safe locks - any writer needs to get a
+ * irq-safe write-lock, but readers can get non-irqsafe
+ * read-locks.
+ */
+typedef struct {
+	volatile unsigned long lock;
+	volatile unsigned long owner_pc;
+} rwlock_t;
+
+#define RW_LOCK_UNLOCKED (rwlock_t) { 0, 0 }
+
+#define read_lock(rw)   \
+        asm volatile("   la    1,%0\n"   \
+                     "   lg    2,0(1)\n"   \
+                     "   j     1f\n"     \
+                     "0: # diag  0,0,68\n" \
+                     "1: nihh  2,0x7fff\n" /* clear high (=write) bit */ \
+                     "   la    3,1(2)\n"   /* one more reader */  \
+                     "   csg   2,3,0(1)\n" /* try to write new value */ \
+                     "   jl    0b"       \
+                     : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+
+#define read_unlock(rw) \
+        asm volatile("   la    1,%0\n"   \
+                     "   lg    2,0(1)\n"   \
+                     "   j     1f\n"     \
+                     "0: # diag  0,0,68\n" \
+                     "1: lgr   3,2\n"    \
+                     "   bctgr 3,0\n"    /* one less reader */ \
+                     "   csg   2,3,0(1)\n" \
+                     "   jl    0b"       \
+                     : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+
+#define write_lock(rw) \
+        asm volatile("   la    1,%0\n"     \
+                     "   llihh 3,0x8000\n" /* new lock value = 0x80...0 */ \
+                     "   j     1f\n"       \
+                     "0: # diag  0,0,68\n"   \
+                     "1: slgr  2,2\n"      /* old lock value must be 0 */ \
+                     "   csg   2,3,0(1)\n" \
+                     "   jl    0b"         \
+                     : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+
+#define write_unlock(rw) \
+        asm volatile("   la    1,%0\n"     \
+                     "   slgr  3,3\n"      /* new lock value = 0 */ \
+                     "   j     1f\n"       \
+                     "0: # diag  0,0,68\n"   \
+                     "1: llihh 2,0x8000\n" /* old lock value must be 0x8..0 */\
+                     "   csg   2,3,0(1)\n"   \
+                     "   jl    0b"         \
+                     : "+m" ((rw)->lock) : : "1", "2", "3", "cc" );
+
+#endif /* __ASM_SPINLOCK_H */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/stat.h linux/include/asm-s390x/stat.h
--- v2.4.1/linux/include/asm-s390x/stat.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/stat.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,33 @@
+/*
+ *  include/asm-s390x/stat.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/stat.h"
+ */
+
+#ifndef _S390_STAT_H
+#define _S390_STAT_H
+
+struct stat {
+        unsigned long  st_dev;
+        unsigned long  st_ino;
+        unsigned long  st_nlink;
+        unsigned int   st_mode;
+        unsigned int   st_uid;
+        unsigned int   st_gid;
+        unsigned int   __pad1;
+        unsigned long  st_rdev;
+        unsigned long  st_size;
+        unsigned long  st_atime;
+	unsigned long	__reserved0;	/* reserved for atime.nanoseconds */
+        unsigned long  st_mtime;
+	unsigned long	__reserved1;	/* reserved for mtime.nanoseconds */
+        unsigned long  st_ctime;
+	unsigned long	__reserved2;	/* reserved for ctime.nanoseconds */
+        unsigned long  st_blksize;
+        long           st_blocks;
+        unsigned long  __unused[3];
+};
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/statfs.h linux/include/asm-s390x/statfs.h
--- v2.4.1/linux/include/asm-s390x/statfs.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/statfs.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,33 @@
+/*
+ *  include/asm-s390/statfs.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/statfs.h"
+ */
+
+#ifndef _S390_STATFS_H
+#define _S390_STATFS_H
+
+#ifndef __KERNEL_STRICT_NAMES
+
+#include <linux/types.h>
+
+typedef __kernel_fsid_t	fsid_t;
+
+#endif
+
+struct statfs {
+	int  f_type;
+	int  f_bsize;
+	long f_blocks;
+	long f_bfree;
+	long f_bavail;
+	long f_files;
+	long f_ffree;
+	__kernel_fsid_t f_fsid;
+	int  f_namelen;
+	int  f_spare[6];
+};
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/string.h linux/include/asm-s390x/string.h
--- v2.4.1/linux/include/asm-s390x/string.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/string.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,121 @@
+/*
+ *  include/asm-s390/string.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ */
+
+#ifndef _S390_STRING_H_
+#define _S390_STRING_H_
+
+#ifdef __KERNEL__
+
+#ifndef _LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+
+#define __HAVE_ARCH_MEMCHR
+#define __HAVE_ARCH_MEMCPY
+#define __HAVE_ARCH_MEMSET
+#define __HAVE_ARCH_STRCAT
+#define __HAVE_ARCH_STRCMP
+#define __HAVE_ARCH_STRCPY
+#define __HAVE_ARCH_STRLEN
+#define __HAVE_ARCH_STRNCPY
+
+#undef __HAVE_ARCH_MEMMOVE
+#undef __HAVE_ARCH_STRNICMP
+#undef __HAVE_ARCH_STRNCAT
+#undef __HAVE_ARCH_STRNCMP
+#undef __HAVE_ARCH_STRCHR
+#undef __HAVE_ARCH_STRRCHR
+#undef __HAVE_ARCH_STRNLEN
+#undef __HAVE_ARCH_STRSPN
+#undef __HAVE_ARCH_STRPBRK
+#undef __HAVE_ARCH_STRTOK
+#undef __HAVE_ARCH_BCOPY
+#undef __HAVE_ARCH_MEMCMP
+#undef __HAVE_ARCH_MEMSCAN
+#undef __HAVE_ARCH_STRSTR
+
+extern void *memset(void *, int, size_t);
+extern void *memcpy(void *, const void *, size_t);
+extern void *memmove(void *, const void *, size_t);
+extern char *strncpy(char *, const char *, size_t);
+extern int strcmp(const char *,const char *);
+
+#undef __HAVE_ARCH_MEMCHR
+#if 0
+static inline void * memchr(const void * cs,int c,size_t count)
+{
+    void *ptr;
+
+    __asm__ __volatile__ ("   lgr   0,%2\n"
+                          "   lgr   1,%1\n"
+                          "   la    %0,0(%3,%1)\n"
+                          "0: srst  %0,1\n"
+                          "   jo    0b\n"
+                          "   brc   13,1f\n"
+                          "   slgr  %0,%0\n"
+                          "1:"
+                          : "=&a" (ptr) : "a" (cs), "d" (c), "d" (count)
+                          : "cc", "0", "1" );
+    return ptr;
+}
+#endif
+
+static __inline__ char *strcpy(char *dest, const char *src)
+{
+    char *tmp = dest;
+
+    __asm__ __volatile__ ("   slgr  0,0\n"
+                          "0: mvst  %0,%1\n"
+                          "   jo    0b"
+                          : "+&a" (dest), "+&a" (src) :
+                          : "cc", "memory", "0" );
+    return tmp;
+}
+
+#undef __HAVE_ARCH_STRLEN
+#if 0
+static __inline__ size_t strlen(const char *s)
+{
+    size_t len;
+
+    __asm__ __volatile__ ("   slgr  0,0\n"
+                          "   lgr   %0,%1\n"
+                          "0: srst  0,%0\n"
+                          "   jo    0b\n"
+                          "   lgr   %0,0\n"
+                          "   sgr   %0,%1"
+                          : "=&a" (len) : "a" (s) 
+                          : "cc", "0" );
+    return len;
+}
+#endif
+
+#undef __HAVE_ARCH_STRCAT
+#if 0
+static __inline__ char *strcat(char *dest, const char *src)
+{
+    char *tmp = dest;
+
+    __asm__ __volatile__ ("   slgr  0,0\n"
+                          "0: srst  0,%0\n"
+                          "   jo    0b\n"
+                          "   lgr   %0,0\n"
+                          "   slgr  0,0\n"
+                          "1: mvst  %0,%1\n"
+                          "   jo    1b"
+                          : "+&a" (dest), "+&a" (src) :
+                          : "cc", "memory", "0" );
+    return tmp;
+}
+#endif
+
+extern void *alloca(size_t);
+#endif /* __KERNEL__ */
+
+#endif /* __S390_STRING_H_ */
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/system.h linux/include/asm-s390x/system.h
--- v2.4.1/linux/include/asm-s390x/system.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/system.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,264 @@
+/*
+ *  include/asm-s390/system.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
+ *
+ *  Derived from "include/asm-i386/system.h"
+ */
+
+#ifndef __ASM_SYSTEM_H
+#define __ASM_SYSTEM_H
+
+#include <linux/config.h>
+#ifdef __KERNEL__
+#include <asm/lowcore.h>
+#endif
+#include <linux/kernel.h>
+
+#define prepare_to_switch()	do { } while(0)
+#define switch_to(prev,next,last) do {                                       \
+        if (prev == next)                                                    \
+                break;                                                       \
+	save_fp_regs(&prev->thread.fp_regs);                                 \
+	restore_fp_regs(&next->thread.fp_regs);              		     \
+	last = resume(&prev->thread,&next->thread);                          \
+} while (0)
+
+struct task_struct;
+
+#define nop() __asm__ __volatile__ ("nop")
+
+#define xchg(ptr,x) \
+  ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(void *)(ptr),sizeof(*(ptr))))
+
+
+static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
+{
+        switch (size) {
+                case 1:
+                        asm volatile (
+                                "   lghi  1,3\n"
+                                "   nr    1,%0\n"     /* isolate last 2 bits */
+                                "   xr    %0,1\n"     /* align ptr */
+                                "   bras  2,0f\n"
+                                "   icm   1,8,%1\n"   /* for ptr&3 == 0 */
+                                "   stcm  0,8,%1\n"
+                                "   icm   1,4,%1\n"   /* for ptr&3 == 1 */
+                                "   stcm  0,4,%1\n"
+                                "   icm   1,2,%1\n"   /* for ptr&3 == 2 */
+                                "   stcm  0,2,%1\n"
+                                "   icm   1,1,%1\n"   /* for ptr&3 == 3 */
+                                "   stcm  0,1,%1\n"
+                                "0: sll   1,3\n"
+                                "   la    2,0(1,2)\n" /* r2 points to an icm */
+                                "   l     0,0(%0)\n"  /* get fullword */
+                                "1: lr    1,0\n"      /* cs loop */
+                                "   ex    0,0(2)\n"   /* insert x */
+                                "   cs    0,1,0(%0)\n"
+                                "   jl    1b\n"
+                                "   ex    0,4(2)"     /* store *ptr to x */
+                                : "+&a" (ptr), "+m" (x) :
+                                : "memory", "0", "1", "2");
+                case 2:
+                        if(((addr_t)ptr)&1)
+                                panic("misaligned (__u16 *) in __xchg\n");
+                        asm volatile (
+                                "   lghi  1,2\n"
+                                "   nr    1,%0\n"     /* isolate bit 2^1 */
+                                "   xr    %0,1\n"     /* align ptr */
+                                "   bras  2,0f\n"
+                                "   icm   1,12,%1\n"   /* for ptr&2 == 0 */
+                                "   stcm  0,12,%1\n"
+                                "   icm   1,3,%1\n"    /* for ptr&2 == 1 */
+                                "   stcm  0,3,%1\n"
+                                "0: sll   1,2\n"
+                                "   la    2,0(1,2)\n" /* r2 points to an icm */
+                                "   l     0,0(%0)\n"  /* get fullword */
+                                "1: lr    1,0\n"      /* cs loop */
+                                "   ex    0,0(2)\n"   /* insert x */
+                                "   cs    0,1,0(%0)\n"
+                                "   jl    1b\n"
+                                "   ex    0,4(2)"     /* store *ptr to x */
+                                : "+&a" (ptr), "+m" (x) :
+                                : "memory", "0", "1", "2");
+                        break;
+                case 4:
+                        if(((addr_t)ptr)&3)
+                                panic("misaligned (__u32 *) in __xchg\n");
+                        asm volatile (
+                                "    l    0,0(%1)\n"
+                                "0:  cs   0,%0,0(%1)\n"
+                                "    jl   0b\n"
+                                "    lgfr %0,0\n"
+                                : "+d" (x) : "a" (ptr)
+                                : "memory", "0" );
+                        break;
+                case 8:
+                        if(((addr_t)ptr)&7)
+                                panic("misaligned (__u64 *) in __xchg\n");
+                        asm volatile (
+                                "    lg  0,0(%1)\n"
+                                "0:  csg 0,%0,0(%1)\n"
+                                "    jl  0b\n"
+                                "    lgr %0,0\n"
+                                : "+d" (x) : "a" (ptr)
+                                : "memory", "0" );
+                        break;
+               default:
+                        abort();
+        }
+        return x;
+}
+
+/*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * This is very similar to the ppc eieio/sync instruction in that is
+ * does a checkpoint syncronisation & makes sure that 
+ * all memory ops have completed wrt other CPU's ( see 7-15 POP  DJB ).
+ */
+
+#define eieio()  __asm__ __volatile__ ("BCR 15,0") 
+# define SYNC_OTHER_CORES(x)   eieio() 
+#define mb()    eieio()
+#define rmb()   eieio()
+#define wmb()   eieio()
+#define smp_mb()       mb()
+#define smp_rmb()      rmb()
+#define smp_wmb()      wmb()
+#define smp_mb__before_clear_bit()     smp_mb()
+#define smp_mb__after_clear_bit()      smp_mb()
+
+#define set_mb(var, value)      do { var = value; mb(); } while (0)
+#define set_wmb(var, value)     do { var = value; wmb(); } while (0)
+
+/* interrupt control.. */
+#define __sti() ({ \
+        unsigned long dummy; \
+        __asm__ __volatile__ ( \
+                "stosm %0,0x03" : "=m" (dummy) : : "memory"); \
+        })
+
+#define __cli() ({ \
+        unsigned long flags; \
+        __asm__ __volatile__ ( \
+                "stnsm %0,0xFC" : "=m" (flags) : : "memory"); \
+        flags; \
+        })
+
+#define __save_flags(x) \
+        __asm__ __volatile__("stosm %0,0" : "=m" (x) : : "memory")
+
+#define __restore_flags(x) \
+        __asm__ __volatile__("ssm   %0" : : "m" (x) : "memory")
+
+#define __load_psw(psw) \
+        __asm__ __volatile__("lpswe %0" : : "m" (psw));
+
+#define __ctl_load(array, low, high) ({ \
+	__asm__ __volatile__ ( \
+		"   la    1,%0\n" \
+		"   bras  2,0f\n" \
+                "   lctlg 0,0,0(1)\n" \
+		"0: ex    %1,0(2)" \
+		: : "m" (array), "a" (((low)<<4)+(high)) : "1", "2" ); \
+	})
+
+#define __ctl_store(array, low, high) ({ \
+	__asm__ __volatile__ ( \
+		"   la    1,%0\n" \
+		"   bras  2,0f\n" \
+		"   stctg 0,0,0(1)\n" \
+		"0: ex    %1,0(2)" \
+		: "=m" (array) : "a" (((low)<<4)+(high)): "1", "2" ); \
+	})
+
+#define __ctl_set_bit(cr, bit) ({ \
+        __u8 dummy[24]; \
+        __asm__ __volatile__ ( \
+                "    la    1,%0\n"       /* align to 8 byte */ \
+                "    aghi  1,7\n" \
+                "    nill  1,0xfff8\n" \
+                "    bras  2,0f\n"       /* skip indirect insns */ \
+                "    stctg 0,0,0(1)\n" \
+                "    lctlg 0,0,0(1)\n" \
+                "0:  ex    %1,0(2)\n"    /* execute stctl */ \
+                "    lg    0,0(1)\n" \
+                "    ogr   0,%2\n"       /* set the bit */ \
+                "    stg   0,0(1)\n" \
+                "1:  ex    %1,6(2)"      /* execute lctl */ \
+                : "=m" (dummy) : "a" (cr*17), "a" (1L<<(bit)) \
+                : "0", "1", "2"); \
+        })
+
+#define __ctl_clear_bit(cr, bit) ({ \
+        __u8 dummy[24]; \
+        __asm__ __volatile__ ( \
+                "    la    1,%0\n"       /* align to 8 byte */ \
+                "    aghi  1,7\n" \
+                "    nill  1,0xfff8\n" \
+                "    bras  2,0f\n"       /* skip indirect insns */ \
+                "    stctg 0,0,0(1)\n" \
+                "    lctlg 0,0,0(1)\n" \
+                "0:  ex    %1,0(2)\n"    /* execute stctl */ \
+                "    lg    0,0(1)\n" \
+                "    ngr   0,%2\n"       /* set the bit */ \
+                "    stg   0,0(1)\n" \
+                "1:  ex    %1,6(2)"      /* execute lctl */ \
+                : "=m" (dummy) : "a" (cr*17), "a" (~(1L<<(bit))) \
+                : "0", "1", "2"); \
+        })
+
+/* For spinlocks etc */
+#define local_irq_save(x)	((x) = __cli())
+#define local_irq_restore(x)	__restore_flags(x)
+#define local_irq_disable()	__cli()
+#define local_irq_enable()	__sti()
+
+#ifdef CONFIG_SMP
+
+extern void __global_cli(void);
+extern void __global_sti(void);
+
+extern unsigned long __global_save_flags(void);
+extern void __global_restore_flags(unsigned long);
+#define cli() __global_cli()
+#define sti() __global_sti()
+#define save_flags(x) ((x)=__global_save_flags())
+#define restore_flags(x) __global_restore_flags(x)
+
+extern void smp_ctl_set_bit(int cr, int bit);
+extern void smp_ctl_clear_bit(int cr, int bit);
+#define ctl_set_bit(cr, bit) smp_ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) smp_ctl_clear_bit(cr, bit)
+
+#else
+
+#define cli() __cli()
+#define sti() __sti()
+#define save_flags(x) __save_flags(x)
+#define restore_flags(x) __restore_flags(x)
+
+#define ctl_set_bit(cr, bit) __ctl_set_bit(cr, bit)
+#define ctl_clear_bit(cr, bit) __ctl_clear_bit(cr, bit)
+
+
+#endif
+
+#ifdef __KERNEL__
+extern struct task_struct *resume(void *,void *);
+
+extern int save_fp_regs1(s390_fp_regs *fpregs);
+extern void save_fp_regs(s390_fp_regs *fpregs);
+extern int restore_fp_regs1(s390_fp_regs *fpregs);
+extern void restore_fp_regs(s390_fp_regs *fpregs);
+#endif
+
+#endif
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/termbits.h linux/include/asm-s390x/termbits.h
--- v2.4.1/linux/include/asm-s390x/termbits.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/termbits.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,180 @@
+/*
+ *  include/asm-s390/termbits.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/termbits.h"
+ */
+
+#ifndef __ARCH_S390_TERMBITS_H__
+#define __ARCH_S390_TERMBITS_H__
+
+#include <linux/posix_types.h>
+
+typedef unsigned char	cc_t;
+typedef unsigned int	speed_t;
+typedef unsigned int	tcflag_t;
+
+#define NCCS 19
+struct termios {
+	tcflag_t c_iflag;		/* input mode flags */
+	tcflag_t c_oflag;		/* output mode flags */
+	tcflag_t c_cflag;		/* control mode flags */
+	tcflag_t c_lflag;		/* local mode flags */
+	cc_t c_line;			/* line discipline */
+	cc_t c_cc[NCCS];		/* control characters */
+};
+
+/* c_cc characters */
+#define VINTR 0
+#define VQUIT 1
+#define VERASE 2
+#define VKILL 3
+#define VEOF 4
+#define VTIME 5
+#define VMIN 6
+#define VSWTC 7
+#define VSTART 8
+#define VSTOP 9
+#define VSUSP 10
+#define VEOL 11
+#define VREPRINT 12
+#define VDISCARD 13
+#define VWERASE 14
+#define VLNEXT 15
+#define VEOL2 16
+
+/* c_iflag bits */
+#define IGNBRK	0000001
+#define BRKINT	0000002
+#define IGNPAR	0000004
+#define PARMRK	0000010
+#define INPCK	0000020
+#define ISTRIP	0000040
+#define INLCR	0000100
+#define IGNCR	0000200
+#define ICRNL	0000400
+#define IUCLC	0001000
+#define IXON	0002000
+#define IXANY	0004000
+#define IXOFF	0010000
+#define IMAXBEL	0020000
+
+/* c_oflag bits */
+#define OPOST	0000001
+#define OLCUC	0000002
+#define ONLCR	0000004
+#define OCRNL	0000010
+#define ONOCR	0000020
+#define ONLRET	0000040
+#define OFILL	0000100
+#define OFDEL	0000200
+#define NLDLY	0000400
+#define   NL0	0000000
+#define   NL1	0000400
+#define CRDLY	0003000
+#define   CR0	0000000
+#define   CR1	0001000
+#define   CR2	0002000
+#define   CR3	0003000
+#define TABDLY	0014000
+#define   TAB0	0000000
+#define   TAB1	0004000
+#define   TAB2	0010000
+#define   TAB3	0014000
+#define   XTABS	0014000
+#define BSDLY	0020000
+#define   BS0	0000000
+#define   BS1	0020000
+#define VTDLY	0040000
+#define   VT0	0000000
+#define   VT1	0040000
+#define FFDLY	0100000
+#define   FF0	0000000
+#define   FF1	0100000
+
+/* c_cflag bit meaning */
+#define CBAUD	0010017
+#define  B0	0000000		/* hang up */
+#define  B50	0000001
+#define  B75	0000002
+#define  B110	0000003
+#define  B134	0000004
+#define  B150	0000005
+#define  B200	0000006
+#define  B300	0000007
+#define  B600	0000010
+#define  B1200	0000011
+#define  B1800	0000012
+#define  B2400	0000013
+#define  B4800	0000014
+#define  B9600	0000015
+#define  B19200	0000016
+#define  B38400	0000017
+#define EXTA B19200
+#define EXTB B38400
+#define CSIZE	0000060
+#define   CS5	0000000
+#define   CS6	0000020
+#define   CS7	0000040
+#define   CS8	0000060
+#define CSTOPB	0000100
+#define CREAD	0000200
+#define PARENB	0000400
+#define PARODD	0001000
+#define HUPCL	0002000
+#define CLOCAL	0004000
+#define CBAUDEX 0010000
+#define  B57600  0010001
+#define  B115200 0010002
+#define  B230400 0010003
+#define  B460800 0010004
+#define   B500000 0010005
+#define   B576000 0010006
+#define   B921600 0010007
+#define  B1000000 0010010
+#define  B1152000 0010011
+#define  B1500000 0010012
+#define  B2000000 0010013
+#define  B2500000 0010014
+#define  B3000000 0010015
+#define  B3500000 0010016
+#define  B4000000 0010017
+#define CIBAUD	  002003600000	/* input baud rate (not used) */
+#define CMSPAR	  010000000000		/* mark or space (stick) parity */
+#define CRTSCTS	  020000000000		/* flow control */
+
+/* c_lflag bits */
+#define ISIG	0000001
+#define ICANON	0000002
+#define XCASE	0000004
+#define ECHO	0000010
+#define ECHOE	0000020
+#define ECHOK	0000040
+#define ECHONL	0000100
+#define NOFLSH	0000200
+#define TOSTOP	0000400
+#define ECHOCTL	0001000
+#define ECHOPRT	0002000
+#define ECHOKE	0004000
+#define FLUSHO	0010000
+#define PENDIN	0040000
+#define IEXTEN	0100000
+
+/* tcflow() and TCXONC use these */
+#define	TCOOFF		0
+#define	TCOON		1
+#define	TCIOFF		2
+#define	TCION		3
+
+/* tcflush() and TCFLSH use these */
+#define	TCIFLUSH	0
+#define	TCOFLUSH	1
+#define	TCIOFLUSH	2
+
+/* tcsetattr uses these */
+#define	TCSANOW		0
+#define	TCSADRAIN	1
+#define	TCSAFLUSH	2
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/termios.h linux/include/asm-s390x/termios.h
--- v2.4.1/linux/include/asm-s390x/termios.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/termios.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,114 @@
+/*
+ *  include/asm-s390/termios.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/termios.h"
+ */
+
+#ifndef _S390_TERMIOS_H
+#define _S390_TERMIOS_H
+
+#include <asm/termbits.h>
+#include <asm/ioctls.h>
+
+
+struct winsize {
+	unsigned short ws_row;
+	unsigned short ws_col;
+	unsigned short ws_xpixel;
+	unsigned short ws_ypixel;
+};
+
+#define NCC 8
+struct termio {
+	unsigned short c_iflag;		/* input mode flags */
+	unsigned short c_oflag;		/* output mode flags */
+	unsigned short c_cflag;		/* control mode flags */
+	unsigned short c_lflag;		/* local mode flags */
+	unsigned char c_line;		/* line discipline */
+	unsigned char c_cc[NCC];	/* control characters */
+};
+
+/* modem lines */
+#define TIOCM_LE	0x001
+#define TIOCM_DTR	0x002
+#define TIOCM_RTS	0x004
+#define TIOCM_ST	0x008
+#define TIOCM_SR	0x010
+#define TIOCM_CTS	0x020
+#define TIOCM_CAR	0x040
+#define TIOCM_RNG	0x080
+#define TIOCM_DSR	0x100
+#define TIOCM_CD	TIOCM_CAR
+#define TIOCM_RI	TIOCM_RNG
+#define TIOCM_OUT1	0x2000
+#define TIOCM_OUT2	0x4000
+#define TIOCM_LOOP      0x8000
+
+/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
+
+/* line disciplines */
+#define N_TTY		0
+#define N_SLIP		1
+#define N_MOUSE		2
+#define N_PPP		3
+#define N_STRIP		4
+#define N_AX25		5
+#define N_X25		6	/* X.25 async */
+#define N_6PACK		7
+#define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
+#define N_R3964		9	/* Reserved for Simatic R3964 module */
+#define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
+#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define N_HDLC         13	/* synchronous HDLC */
+
+#ifdef __KERNEL__
+
+/*	intr=^C		quit=^\		erase=del	kill=^U
+	eof=^D		vtime=\0	vmin=\1		sxtc=\0
+	start=^Q	stop=^S		susp=^Z		eol=\0
+	reprint=^R	discard=^U	werase=^W	lnext=^V
+	eol2=\0
+*/
+#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
+
+/*
+ * Translate a "termio" structure into a "termios". Ugh.
+ */
+
+#define user_termio_to_kernel_termios(termios, termio) \
+({ \
+        unsigned short tmp; \
+        get_user(tmp, &(termio)->c_iflag); \
+        (termios)->c_iflag = (0xffff0000 & ((termios)->c_iflag)) | tmp; \
+        get_user(tmp, &(termio)->c_oflag); \
+        (termios)->c_oflag = (0xffff0000 & ((termios)->c_oflag)) | tmp; \
+        get_user(tmp, &(termio)->c_cflag); \
+        (termios)->c_cflag = (0xffff0000 & ((termios)->c_cflag)) | tmp; \
+        get_user(tmp, &(termio)->c_lflag); \
+        (termios)->c_lflag = (0xffff0000 & ((termios)->c_lflag)) | tmp; \
+        get_user((termios)->c_line, &(termio)->c_line); \
+	copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
+})
+
+/*
+ * Translate a "termios" structure into a "termio". Ugh.
+ */
+#define kernel_termios_to_user_termio(termio, termios) \
+({ \
+	put_user((termios)->c_iflag, &(termio)->c_iflag); \
+	put_user((termios)->c_oflag, &(termio)->c_oflag); \
+	put_user((termios)->c_cflag, &(termio)->c_cflag); \
+	put_user((termios)->c_lflag, &(termio)->c_lflag); \
+	put_user((termios)->c_line,  &(termio)->c_line); \
+	copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
+})
+
+#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
+#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
+
+#endif	/* __KERNEL__ */
+
+#endif	/* _S390_TERMIOS_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/timex.h linux/include/asm-s390x/timex.h
--- v2.4.1/linux/include/asm-s390x/timex.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/timex.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,29 @@
+/*
+ *  include/asm-s390/timex.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *
+ *  Derived from "include/asm-i386/timex.h"
+ *    Copyright (C) 1992, Linus Torvalds
+ */
+
+#ifndef _ASM_S390_TIMEX_H
+#define _ASM_S390_TIMEX_H
+
+#define CLOCK_TICK_RATE	1193180 /* Underlying HZ */
+#define CLOCK_TICK_FACTOR	20	/* Factor of both 1000000 and CLOCK_TICK_RATE */
+#define FINETUNE ((((((long)LATCH * HZ - CLOCK_TICK_RATE) << SHIFT_HZ) * \
+	(1000000/CLOCK_TICK_FACTOR) / (CLOCK_TICK_RATE/CLOCK_TICK_FACTOR)) \
+		<< (SHIFT_SCALE-SHIFT_HZ)) / HZ)
+
+typedef unsigned long cycles_t;
+
+extern cycles_t cacheflush_time;
+
+static inline cycles_t get_cycles(void)
+{
+        return 0;
+}
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/todclk.h linux/include/asm-s390x/todclk.h
--- v2.4.1/linux/include/asm-s390x/todclk.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/todclk.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,19 @@
+/*
+ * File...........: linux/include/asm/todclk.h
+ * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
+ * Bugreports.to..: <Linux390@de.ibm.com>
+ * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ *
+ * History of changes (starts July 2000)
+ */
+
+#ifndef __ASM_TODCLK_H
+#define __ASM_TODCLK_H
+
+#define TOD_uSEC (0x1000ULL)
+#define TOD_mSEC (1000 * TOD_uSEC)
+#define TOD_SEC (1000 * TOD_mSEC)
+#define TOD_MIN (60 * TOD_SEC)
+#define TOD_HOUR (60 * TOD_MIN)
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/types.h linux/include/asm-s390x/types.h
--- v2.4.1/linux/include/asm-s390x/types.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/types.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,69 @@
+/*
+ *  include/asm-s390/types.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/types.h"
+ */
+
+#ifndef _S390_TYPES_H
+#define _S390_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+typedef __signed__ long __s64;
+typedef unsigned long __u64;
+
+/* 
+ * A address type so that arithmetic can be done on it & it can be upgraded to
+ * 64 bit when neccessary 
+ */
+
+typedef unsigned long  addr_t; 
+typedef signed long  saddr_t;
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long s64;
+typedef unsigned  long u64;
+
+#define BITS_PER_LONG 64
+
+typedef u32 dma_addr_t;
+
+#endif                                 /* __KERNEL__                       */
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/uaccess.h linux/include/asm-s390x/uaccess.h
--- v2.4.1/linux/include/asm-s390x/uaccess.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/uaccess.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,559 @@
+/*
+ *  include/asm-s390/uaccess.h
+ *
+ *  S390 version
+ *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Author(s): Hartmut Penner (hpenner@de.ibm.com),
+ *               Martin Schwidefsky (schwidefsky@de.ibm.com)
+ *
+ *  Derived from "include/asm-i386/uaccess.h"
+ */
+#ifndef __S390_UACCESS_H
+#define __S390_UACCESS_H
+
+/*
+ * User space memory access functions
+ */
+#include <linux/sched.h>
+
+#define VERIFY_READ     0
+#define VERIFY_WRITE    1
+
+
+/*
+ * The fs value determines whether argument validity checking should be
+ * performed or not.  If get_fs() == USER_DS, checking is performed, with
+ * get_fs() == KERNEL_DS, checking is bypassed.
+ *
+ * For historical reasons, these macros are grossly misnamed.
+ */
+
+#define MAKE_MM_SEG(s)	((mm_segment_t) { (s) })
+
+
+#define KERNEL_DS	MAKE_MM_SEG(0)
+#define USER_DS		MAKE_MM_SEG(1)
+
+#define get_ds()	(KERNEL_DS)
+#define get_fs()	(current->addr_limit)
+#define set_fs(x)       ({asm volatile("sar   4,%0"::"a" ((x).ar4));\
+                          current->addr_limit = (x);})
+
+#define segment_eq(a,b)	((a).ar4 == (b).ar4)
+
+
+#define __access_ok(addr,size) (1)
+
+#define access_ok(type,addr,size) __access_ok(addr,size)
+
+extern inline int verify_area(int type, const void * addr, unsigned long size)
+{
+        return access_ok(type,addr,size)?0:-EFAULT;
+}
+
+/*
+ * The exception table consists of pairs of addresses: the first is the
+ * address of an instruction that is allowed to fault, and the second is
+ * the address at which the program should continue.  No registers are
+ * modified, so it is entirely up to the continuation code to figure out
+ * what to do.
+ *
+ * All the routines below use bits of fixup code that are out of line
+ * with the main instruction path.  This means when everything is well,
+ * we don't even have to jump over them.  Further, they do not intrude
+ * on our cache or tlb entries.
+ */
+
+struct exception_table_entry
+{
+        unsigned long insn, fixup;
+};
+
+/* Returns 0 if exception not found and fixup otherwise.  */
+extern unsigned long search_exception_table(unsigned long);
+
+
+/*
+ * These are the main single-value transfer routines.  They automatically
+ * use the right size if we just have the right pointer type.
+ */
+
+extern inline int __put_user_asm_8(__u64 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: stg   %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u64*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "4" );
+        return err;
+}
+extern inline int __put_user_asm_4(__u32 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: st    %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u32*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "4" );
+        return err;
+}
+
+extern inline int __put_user_asm_2(__u16 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: sth   %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u16*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "4" );
+        return err;
+}
+
+extern inline int __put_user_asm_1(__u8 x, void *ptr)
+{
+        int err;
+
+        __asm__ __volatile__ (  "   sr    %1,%1\n"
+				"   la    4,%0\n"
+                                "   sacf  512\n"
+                                "0: stc   %2,0(4)\n"
+                                "1: sacf  0\n"
+				".section .fixup,\"ax\"\n"
+				"2: lhi   %1,%h3\n"
+				"   jg    1b\n"
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,2b\n"
+				".previous"
+                                : "=m" (*((__u8*) ptr)) , "=&d" (err)
+                                : "d" (x), "K" (-EFAULT)
+                                : "1", "4" );
+        return err;
+}
+
+/*
+ * (u?)(u64) ... autsch, but that the only way we can suppress the
+ * warnings when compiling binfmt_elf.c
+ */
+#define __put_user(x, ptr)                                      \
+({                                                              \
+        int __pu_err;                                           \
+        switch (sizeof (*(ptr))) {                              \
+                case 1:                                         \
+                        __pu_err = __put_user_asm_1((__u8)(__u64)(x),(ptr));\
+                        break;                                  \
+                case 2:                                         \
+                        __pu_err = __put_user_asm_2((__u16)(__u64)(x),(ptr));\
+                        break;                                  \
+                case 4:                                         \
+                        __pu_err = __put_user_asm_4((__u32)(__u64)(x),(ptr));\
+                        break;                                  \
+                case 8:                                         \
+                        __pu_err = __put_user_asm_8((__u64)(x),(ptr));\
+                        break;                                  \
+                default:                                        \
+                __pu_err = __put_user_bad();                    \
+                break;                                          \
+         }                                                      \
+        __pu_err;                                               \
+})
+
+#define put_user(x, ptr)                                        \
+({                                                              \
+        long __pu_err = -EFAULT;                                \
+        __typeof__(*(ptr)) *__pu_addr = (ptr);                  \
+        __typeof__(*(ptr)) __x = (x);                           \
+        if (__access_ok((long)__pu_addr,sizeof(*(ptr)))) {      \
+                __pu_err = 0;                                   \
+                __put_user((__x), (__pu_addr));                 \
+        }                                                       \
+        __pu_err;                                               \
+})
+
+extern int __put_user_bad(void);
+
+
+#define __get_user_asm_8(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: lg    %0,0(4)\n"                       \
+                                "1: sacf  0\n"                             \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: lhi   %1,%h3\n"                        \
+                                "   jg    1b\n"                            \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 8\n"                            \
+                                "   .quad 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u64*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+#define __get_user_asm_4(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: l     %0,0(4)\n"                       \
+                                "1: sacf  0\n"                             \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: lhi   %1,%h3\n"                        \
+                                "   jg    1b\n"                            \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 8\n"                            \
+                                "   .quad 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u32*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+
+#define __get_user_asm_2(x, ptr, err)                                      \
+({                                                                         \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                         \
+                                "   la    4,%2\n"                          \
+                                "   sacf  512\n"                           \
+                                "0: lh    %0,0(4)\n"                       \
+                                "1: sacf  0\n"                             \
+                                ".section .fixup,\"ax\"\n"                 \
+                                "2: lhi   %1,%h3\n"                        \
+                                "   jg    1b\n"                            \
+                                ".previous\n"                              \
+                                ".section __ex_table,\"a\"\n"              \
+                                "   .align 8\n"                            \
+                                "   .quad 0b,2b\n"                         \
+                                ".previous"                                \
+                                : "=d" (x) , "=&d" (err)                   \
+                                : "m" (*(const __u16*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                   \
+})
+
+#define __get_user_asm_1(x, ptr, err)                                     \
+({                                                                        \
+        __asm__ __volatile__ (  "   sr    %1,%1\n"                        \
+                                "   la    4,%2\n"                         \
+                                "   sr    %0,%0\n"                        \
+                                "   sacf  512\n"                          \
+                                "0: ic    %0,0(4)\n"                      \
+                                "1: sacf  0\n"                            \
+                                ".section .fixup,\"ax\"\n"                \
+                                "2: lhi   %1,%h3\n"                       \
+                                "   jg    1b\n"                           \
+                                ".previous\n"                             \
+                                ".section __ex_table,\"a\"\n"             \
+                                "   .align 8\n"                           \
+                                "   .quad 0b,2b\n"                        \
+                                ".previous"                               \
+                                : "=d" (x) , "=&d" (err)                  \
+                                : "m" (*(const __u8*)(ptr)),"K" (-EFAULT) \
+                                : "4" );                                  \
+})
+
+#define __get_user(x, ptr)                                      \
+({                                                              \
+        int __gu_err;                                           \
+        switch (sizeof(*(ptr))) {                               \
+                case 1:                                         \
+                        __get_user_asm_1(x,ptr,__gu_err);       \
+                        break;                                  \
+                case 2:                                         \
+                        __get_user_asm_2(x,ptr,__gu_err);       \
+                        break;                                  \
+                case 4:                                         \
+                        __get_user_asm_4(x,ptr,__gu_err);       \
+                        break;                                  \
+                case 8:                                         \
+                        __get_user_asm_8(x,ptr,__gu_err);       \
+                        break;                                  \
+                default:                                        \
+                        (x) = 0;                                \
+                        __gu_err = __get_user_bad();            \
+                break;                                          \
+        }                                                       \
+        __gu_err;                                               \
+})
+
+#define get_user(x, ptr)                                        \
+({                                                              \
+        long __gu_err = -EFAULT;                                \
+        __typeof__(ptr) __gu_addr = (ptr);                      \
+        __typeof__(*(ptr)) __x;                                 \
+        if (__access_ok((long)__gu_addr,sizeof(*(ptr)))) {      \
+                __gu_err = 0;                                   \
+                __get_user((__x), (__gu_addr));                 \
+                (x) = __x;                                      \
+        }                                                       \
+        else                                                    \
+                (x) = 0;                                        \
+        __gu_err;                                               \
+})
+
+extern int __get_user_bad(void);
+
+/*
+ * access register are set up, that 4 points to secondary (user) , 2 to primary (kernel)
+ */
+
+asmlinkage void __copy_from_user_fixup(void /* special calling convention */);
+asmlinkage void __copy_to_user_fixup(void /* special calling convention */);
+
+extern inline unsigned long
+__copy_to_user_asm(void* to, const void* from,  long n)
+{
+
+        __asm__ __volatile__ (  "   lgr   2,%2\n"
+                                "   lgr   4,%1\n"
+                                "   lgr   3,%0\n"
+                                "   lgr   5,3\n"
+                                "   sacf  512\n"
+                                "0: mvcle 4,2,0\n"
+                                "   jo    0b\n"
+                                "   sacf  0\n"
+                                "   lgr   %0,3\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,__copy_to_user_fixup\n"
+				".previous"
+                                : "+&d" (n) : "d" (to), "d" (from)
+                                : "1", "2", "3", "4", "5" );
+        return n;
+}
+
+#define __copy_to_user(to, from, n)                             \
+({                                                              \
+        __copy_to_user_asm(to,from,n);                          \
+})
+
+#define copy_to_user(to, from, n)                               \
+({                                                              \
+        long err = 0;                                           \
+        __typeof__(n) __n = (n);                                \
+        if (__access_ok(to,__n)) {                              \
+                err = __copy_to_user_asm(to,from,__n);          \
+        }                                                       \
+        else                                                    \
+                err = __n;                                      \
+        err;                                                    \
+})
+
+extern inline unsigned long
+__copy_from_user_asm(void* to, const void* from,  long n)
+{
+        __asm__ __volatile__ (  "   lgr   2,%1\n"
+                                "   lgr   4,%2\n"
+                                "   lgr   3,%0\n"
+                                "   lgr   5,3\n"
+                                "   sacf  512\n"
+                                "0: mvcle 2,4,0\n"
+                                "   jo    0b\n"
+                                "   sacf  0\n"
+                                "   lgr   %0,5\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,__copy_from_user_fixup\n"
+				".previous"
+                                : "+&d" (n) : "d" (to), "d" (from)
+                                : "1", "2", "3", "4", "5" );
+        return n;
+}
+
+
+#define __copy_from_user(to, from, n)                           \
+({                                                              \
+        __copy_from_user_asm(to,from,n);                        \
+})
+
+#define copy_from_user(to, from, n)                             \
+({                                                              \
+        long err = 0;                                           \
+        __typeof__(n) __n = (n);                                \
+        if (__access_ok(from,__n)) {                            \
+                err = __copy_from_user_asm(to,from,__n);        \
+        }                                                       \
+        else                                                    \
+                err = __n;                                      \
+        err;                                                    \
+})
+
+/*
+ * Copy a null terminated string from userspace.
+ */
+
+static inline long
+__strncpy_from_user(char *dst, const char *src, long count)
+{
+        long len;
+        __asm__ __volatile__ (  "   slgr  %0,%0\n"
+				"   lgr   2,%1\n"
+                                "   lgr   4,%2\n"
+                                "   slr   3,3\n"
+                                "   sacf  512\n"
+                                "0: ic    3,0(%0,4)\n"
+                                "1: stc   3,0(%0,2)\n"
+                                "   aghi  %0,1\n"
+                                "   cgr   %0,%3\n"
+                                "   je    2f\n"
+                                "   ltr   3,3\n"
+                                "   jne   0b\n"
+                                "2: sacf  0\n"
+				"3:\n"
+				".section .fixup,\"ax\"\n"
+				"4: lghi  %0,%h4\n"
+				"   jg    3b\n"  
+				".previous\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,4b\n"
+				"   .quad  1b,4b\n"
+				".previous"
+                                : "=&a" (len)
+                                : "a"  (dst), "d" (src), "d" (count),
+                                  "K" (-EFAULT)
+                                : "2" ,"3", "4" );
+        return len;
+}
+
+static inline long
+strncpy_from_user(char *dst, const char *src, long count)
+{
+        long res = -EFAULT;
+        if (access_ok(VERIFY_READ, src, 1))
+                res = __strncpy_from_user(dst, src, count);
+        return res;
+}
+
+/*
+ * Return the size of a string (including the ending 0)
+ *
+ * Return 0 for error
+ */
+static inline unsigned long
+strnlen_user(const char * src, unsigned long n)
+{
+#if 0
+        __asm__ __volatile__ ("   algr  %0,%1\n"
+                              "   slgr  0,0\n"
+                              "   lgr   4,%1\n"
+                              "   sacf  512\n"
+                              "0: srst  %0,4\n"
+                              "   jo    0b\n"
+                              "   slgr  %0,%1\n"
+                              "   aghi  %0,1\n"
+                              "1: sacf  0\n"
+                              ".section .fixup,\"ax\"\n"
+                              "2: slgr  %0,%0\n"
+                              "   jg    1b\n"
+                              ".previous\n"
+                              ".section __ex_table,\"a\"\n"
+                              "   .align 8\n"
+                              "   .quad  0b,2b\n"
+                              ".previous"
+                              : "+&a" (n) : "d" (src)
+                              : "cc", "0", "4" );
+#else
+	__asm__ __volatile__ ("   lgr   4,%1\n"
+			      "   sacf  512\n"
+			      "0: cli   0(4),0x00\n"
+                              "   la    4,1(4)\n"
+			      "   je    1f\n"
+                              "   brctg %0,0b\n"
+			      "1: lgr   %0,4\n"
+			      "   slgr  %0,%1\n"
+			      "2: sacf  0\n"
+                              ".section .fixup,\"ax\"\n"
+                              "3: slgr  %0,%0\n"
+                              "   jg    2b\n"  
+                              ".previous\n"
+			      ".section __ex_table,\"a\"\n"
+			      "   .align 8\n"
+			      "   .quad  0b,3b\n"
+			      ".previous"
+			      : "+&a" (n) : "d" (src)
+			      : "cc", "4" );
+#endif
+        return n;
+}
+#define strlen_user(str) strnlen_user(str, ~0UL)
+
+/*
+ * Zero Userspace
+ */
+
+static inline unsigned long
+__clear_user(void *to, unsigned long n)
+{
+        __asm__ __volatile__ (  "   sacf  512\n"
+                                "   lgr   4,%1\n"
+                                "   lgr   5,%0\n"
+                                "   sgr   2,2\n"
+                                "   sgr   3,3\n"
+                                "0: mvcle 4,2,0\n"
+                                "   jo    0b\n"
+                                "1: sacf  0\n"
+                                "   lgr   %0,5\n"
+				".section __ex_table,\"a\"\n"
+				"   .align 8\n"
+				"   .quad  0b,__copy_to_user_fixup\n"
+				".previous"
+                                : "+&a" (n)
+                                : "a"   (to)
+                                : "cc", "1", "2", "3", "4", "5" );
+        return n;
+}
+
+static inline unsigned long
+clear_user(void *to, unsigned long n)
+{
+        if (access_ok(VERIFY_WRITE, to, n))
+                n = __clear_user(to, n);
+        return n;
+}
+
+#endif                                 /* _S390_UACCESS_H                  */
+
+
+
+
+
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/ucontext.h linux/include/asm-s390x/ucontext.h
--- v2.4.1/linux/include/asm-s390x/ucontext.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/ucontext.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,22 @@
+/*
+ *  include/asm-s390/ucontext.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/ucontext.h"
+ */
+
+#ifndef _ASM_S390_UCONTEXT_H
+#define _ASM_S390_UCONTEXT_H
+
+struct ucontext {
+	unsigned long	  uc_flags;
+	struct ucontext  *uc_link;
+	stack_t		  uc_stack;
+	sigset_t	  uc_sigmask;	/* mask last for extensibility */
+	struct sigcontext *sc; /* Added for pthread support */
+};
+
+
+
+#endif /* !_ASM_S390_UCONTEXT_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/unaligned.h linux/include/asm-s390x/unaligned.h
--- v2.4.1/linux/include/asm-s390x/unaligned.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/unaligned.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,24 @@
+/*
+ *  include/asm-s390/unaligned.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/unaligned.h"
+ */
+
+#ifndef __S390_UNALIGNED_H
+#define __S390_UNALIGNED_H
+
+/*
+ * The S390 can do unaligned accesses itself. 
+ *
+ * The strange macros are there to make sure these can't
+ * be misused in a way that makes them not work on other
+ * architectures where unaligned accesses aren't as simple.
+ */
+
+#define get_unaligned(ptr) (*(ptr))
+
+#define put_unaligned(val, ptr) ((void)( *(ptr) = (val) ))
+
+#endif
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/unistd.h linux/include/asm-s390x/unistd.h
--- v2.4.1/linux/include/asm-s390x/unistd.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/unistd.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,346 @@
+/*
+ *  include/asm-s390/unistd.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/unistd.h"
+ */
+
+#ifndef _ASM_S390_UNISTD_H_
+#define _ASM_S390_UNISTD_H_
+
+/*
+ * This file contains the system call numbers.
+ */
+
+#define __NR_exit                 1
+#define __NR_fork                 2
+#define __NR_read                 3
+#define __NR_write                4
+#define __NR_open                 5
+#define __NR_close                6
+#define __NR_creat                8
+#define __NR_link                 9
+#define __NR_unlink              10
+#define __NR_execve              11
+#define __NR_chdir               12
+#define __NR_mknod               14
+#define __NR_chmod               15
+#define __NR_lseek               19
+#define __NR_getpid              20
+#define __NR_mount               21
+#define __NR_umount              22
+#define __NR_ptrace              26
+#define __NR_alarm               27
+#define __NR_pause               29
+#define __NR_utime               30
+#define __NR_access              33
+#define __NR_nice                34
+#define __NR_sync                36
+#define __NR_kill                37
+#define __NR_rename              38
+#define __NR_mkdir               39
+#define __NR_rmdir               40
+#define __NR_dup                 41
+#define __NR_pipe                42
+#define __NR_times               43
+#define __NR_brk                 45
+#define __NR_signal              48
+#define __NR_acct                51
+#define __NR_umount2             52
+#define __NR_ioctl               54
+#define __NR_fcntl               55
+#define __NR_setpgid             57
+#define __NR_umask               60
+#define __NR_chroot              61
+#define __NR_ustat               62
+#define __NR_dup2                63
+#define __NR_getppid             64
+#define __NR_getpgrp             65
+#define __NR_setsid              66
+#define __NR_sigaction           67
+#define __NR_sigsuspend          72
+#define __NR_sigpending          73
+#define __NR_sethostname         74
+#define __NR_setrlimit           75
+#define __NR_getrusage           77
+#define __NR_gettimeofday        78
+#define __NR_settimeofday        79
+#define __NR_symlink             83
+#define __NR_readlink            85
+#define __NR_uselib              86
+#define __NR_swapon              87
+#define __NR_reboot              88
+#define __NR_readdir             89
+#define __NR_mmap                90
+#define __NR_munmap              91
+#define __NR_truncate            92
+#define __NR_ftruncate           93
+#define __NR_fchmod              94
+#define __NR_getpriority         96
+#define __NR_setpriority         97
+#define __NR_statfs              99
+#define __NR_fstatfs            100
+#define __NR_socketcall         102
+#define __NR_syslog             103
+#define __NR_setitimer          104
+#define __NR_getitimer          105
+#define __NR_stat               106
+#define __NR_lstat              107
+#define __NR_fstat              108
+#define __NR_vhangup            111
+#define __NR_idle               112
+#define __NR_wait4              114
+#define __NR_swapoff            115
+#define __NR_sysinfo            116
+#define __NR_ipc                117
+#define __NR_fsync              118
+#define __NR_sigreturn          119
+#define __NR_clone              120
+#define __NR_setdomainname      121
+#define __NR_uname              122
+#define __NR_adjtimex           124
+#define __NR_mprotect           125
+#define __NR_sigprocmask        126
+#define __NR_create_module      127
+#define __NR_init_module        128
+#define __NR_delete_module      129
+#define __NR_get_kernel_syms    130
+#define __NR_quotactl           131
+#define __NR_getpgid            132
+#define __NR_fchdir             133
+#define __NR_bdflush            134
+#define __NR_sysfs              135
+#define __NR_personality        136
+#define __NR_afs_syscall        137 /* Syscall for Andrew File System */
+#define __NR_getdents           141
+#define __NR_select             142
+#define __NR_flock              143
+#define __NR_msync              144
+#define __NR_readv              145
+#define __NR_writev             146
+#define __NR_getsid             147
+#define __NR_fdatasync          148
+#define __NR__sysctl            149
+#define __NR_mlock              150
+#define __NR_munlock            151
+#define __NR_mlockall           152
+#define __NR_munlockall         153
+#define __NR_sched_setparam             154
+#define __NR_sched_getparam             155
+#define __NR_sched_setscheduler         156
+#define __NR_sched_getscheduler         157
+#define __NR_sched_yield                158
+#define __NR_sched_get_priority_max     159
+#define __NR_sched_get_priority_min     160
+#define __NR_sched_rr_get_interval      161
+#define __NR_nanosleep          162
+#define __NR_mremap             163
+#define __NR_query_module       167
+#define __NR_poll               168
+#define __NR_nfsservctl         169
+#define __NR_prctl              172
+#define __NR_rt_sigreturn       173
+#define __NR_rt_sigaction       174
+#define __NR_rt_sigprocmask     175
+#define __NR_rt_sigpending      176
+#define __NR_rt_sigtimedwait    177
+#define __NR_rt_sigqueueinfo    178
+#define __NR_rt_sigsuspend      179
+#define __NR_pread              180
+#define __NR_pwrite             181
+#define __NR_getcwd             183
+#define __NR_capget             184
+#define __NR_capset             185
+#define __NR_sigaltstack        186
+#define __NR_sendfile           187
+#define __NR_vfork		190
+#define __NR_getrlimit		191	/* SuS compliant getrlimit */
+#define __NR_lchown  		198
+#define __NR_getuid  		199
+#define __NR_getgid  		200
+#define __NR_geteuid  		201
+#define __NR_getegid  		202
+#define __NR_setreuid  		203
+#define __NR_setregid  		204
+#define __NR_getgroups  	205
+#define __NR_setgroups  	206
+#define __NR_fchown  		207
+#define __NR_setresuid  	208
+#define __NR_getresuid  	209
+#define __NR_setresgid  	210
+#define __NR_getresgid  	211
+#define __NR_chown  		212
+#define __NR_setuid  		213
+#define __NR_setgid  		214
+#define __NR_setfsuid  		215
+#define __NR_setfsgid  		216
+#define __NR_pivot_root         217
+#define __NR_mincore            218
+#define __NR_madvise            219
+#define __NR_getdents64         220
+#define __NR_fcntl64            221
+
+
+/* user-visible error numbers are in the range -1 - -122: see <asm-s390/errno.h> */
+
+#define __syscall_return(type, res)                          \
+do {                                                         \
+        if ((unsigned long)(res) >= (unsigned long)(-125)) { \
+                errno = -(res);                              \
+                res = -1;                                    \
+        }                                                    \
+        return (type) (res);                                 \
+} while (0)
+
+#define _svc_clobber "2", "cc", "memory"
+
+#define _syscall0(type,name)                                 \
+type name(void) {                                            \
+        long __res;                                          \
+        __asm__ __volatile__ (                               \
+                "    svc %b1\n"                              \
+                "    lr  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name)                          \
+                : _svc_clobber );                            \
+        __syscall_return(type,__res);                        \
+}
+
+#define _syscall1(type,name,type1,arg1)                      \
+type name(type1 arg1) {                                      \
+        register type1 __arg1 asm("2") = arg1;               \
+        long __res;                                          \
+        __asm__ __volatile__ (                               \
+                "    svc %b1\n"                              \
+                "    lr  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name),                         \
+                  "d" (__arg1)                               \
+                : _svc_clobber );                            \
+        __syscall_return(type,__res);                        \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2)           \
+type name(type1 arg1, type2 arg2) {                          \
+        register type1 __arg1 asm("2") = arg1;               \
+        register type2 __arg2 asm("3") = arg2;               \
+        long __res;                                          \
+        __asm__ __volatile__ (                               \
+                "    svc %b1\n"                              \
+                "    lr  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name),                         \
+                  "d" (__arg1),                              \
+                  "d" (__arg2)                               \
+                : _svc_clobber );                            \
+        __syscall_return(type,__res);                        \
+}
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)\
+type name(type1 arg1, type2 arg2, type3 arg3) {              \
+        register type1 __arg1 asm("2") = arg1;               \
+        register type2 __arg2 asm("3") = arg2;               \
+        register type3 __arg3 asm("4") = arg3;               \
+        long __res;                                          \
+        __asm__ __volatile__ (                               \
+                "    svc %b1\n"                              \
+                "    lr  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name),                         \
+                  "d" (__arg1),                              \
+                  "d" (__arg2),                              \
+                  "d" (__arg3)                               \
+                : _svc_clobber );                            \
+        __syscall_return(type,__res);                        \
+}
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,\
+                  type4,name4)                               \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) {  \
+        register type1 __arg1 asm("2") = arg1;               \
+        register type2 __arg2 asm("3") = arg2;               \
+        register type3 __arg3 asm("4") = arg3;               \
+        register type4 __arg4 asm("5") = arg4;               \
+        long __res;                                          \
+        __asm__ __volatile__ (                               \
+                "    svc %b1\n"                              \
+                "    lr  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name),                         \
+                  "d" (__arg1),                              \
+                  "d" (__arg2),                              \
+                  "d" (__arg3),                              \
+                  "d" (__arg4)                               \
+                : _svc_clobber );                            \
+        __syscall_return(type,__res);                        \
+}
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,\
+                  type4,name4,type5,name5)                   \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4,    \
+          type5 arg5) {                                      \
+        register type1 __arg1 asm("2") = arg1;               \
+        register type2 __arg2 asm("3") = arg2;               \
+        register type3 __arg3 asm("4") = arg3;               \
+        register type4 __arg4 asm("5") = arg4;               \
+        register type5 __arg5 asm("6") = arg5;               \
+        long __res;                                          \
+        __asm__ __volatile__ (                               \
+                "    svc %b1\n"                              \
+                "    lr  %0,2"                               \
+                : "=d" (__res)                               \
+                : "i" (__NR_##name),                         \
+                  "d" (__arg1),                              \
+                  "d" (__arg2),                              \
+                  "d" (__arg3),                              \
+                  "d" (__arg4),                              \
+                  "d" (__arg5)                               \
+                : _svc_clobber );                            \
+        __syscall_return(type,__res);                        \
+}
+
+#ifdef __KERNEL_SYSCALLS__
+
+/*
+ * we need this inline - forking from kernel space will result
+ * in NO COPY ON WRITE (!!!), until an execve is executed. This
+ * is no problem, but for the stack. This is handled by not letting
+ * main() use the stack at all after fork(). Thus, no function
+ * calls - which means inline code for fork too, as otherwise we
+ * would use the stack upon exit from 'fork()'.
+ *
+ * Actually only pause and fork are needed inline, so that there
+ * won't be any messing with the stack from main(), but we define
+ * some others too.
+ */
+#define __NR__exit __NR_exit
+static inline _syscall0(int,idle)
+static inline _syscall0(int,pause)
+static inline _syscall0(int,sync)
+static inline _syscall0(pid_t,setsid)
+static inline _syscall3(int,write,int,fd,const char *,buf,off_t,count)
+static inline _syscall3(int,read,int,fd,char *,buf,off_t,count)
+static inline _syscall3(off_t,lseek,int,fd,off_t,offset,int,count)
+static inline _syscall1(int,dup,int,fd)
+static inline _syscall3(int,execve,const char *,file,char **,argv,char **,envp)
+static inline _syscall3(int,open,const char *,file,int,flag,int,mode)
+static inline _syscall1(int,close,int,fd)
+static inline _syscall1(int,_exit,int,exitcode)
+static inline _syscall1(int,delete_module,const char *,name)
+static inline _syscall2(long,stat,char *,filename,struct stat *,statbuf)
+
+extern int sys_wait4(int, int *, int, struct rusage *);
+static inline pid_t waitpid(int pid, int * wait_stat, int flags)
+{
+        return sys_wait4(pid, wait_stat, flags, NULL);
+}
+
+static inline pid_t wait(int * wait_stat)
+{
+        return waitpid(-1,wait_stat,0);
+}
+
+#endif
+
+#endif /* _ASM_S390_UNISTD_H_ */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/user.h linux/include/asm-s390x/user.h
--- v2.4.1/linux/include/asm-s390x/user.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/user.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1,77 @@
+/*
+ *  include/asm-s390/user.h
+ *
+ *  S390 version
+ *
+ *  Derived from "include/asm-i386/usr.h"
+ */
+
+#ifndef _S390_USER_H
+#define _S390_USER_H
+
+#include <asm/page.h>
+#include <linux/ptrace.h>
+/* Core file format: The core file is written in such a way that gdb
+   can understand it and provide useful information to the user (under
+   linux we use the 'trad-core' bfd).  There are quite a number of
+   obstacles to being able to view the contents of the floating point
+   registers, and until these are solved you will not be able to view the
+   contents of them.  Actually, you can read in the core file and look at
+   the contents of the user struct to find out what the floating point
+   registers contain.
+   The actual file contents are as follows:
+   UPAGE: 1 page consisting of a user struct that tells gdb what is present
+   in the file.  Directly after this is a copy of the task_struct, which
+   is currently not used by gdb, but it may come in useful at some point.
+   All of the registers are stored as part of the upage.  The upage should
+   always be only one page.
+   DATA: The data area is stored.  We use current->end_text to
+   current->brk to pick up all of the user variables, plus any memory
+   that may have been malloced.  No attempt is made to determine if a page
+   is demand-zero or if a page is totally unused, we just cover the entire
+   range.  All of the addresses are rounded in such a way that an integral
+   number of pages is written.
+   STACK: We need the stack information in order to get a meaningful
+   backtrace.  We need to write the data from (esp) to
+   current->start_stack, so we round each of these off in order to be able
+   to write an integer number of pages.
+   The minimum core file size is 3 pages, or 12288 bytes.
+*/
+
+
+/*
+ * This is the old layout of "struct pt_regs", and
+ * is still the layout used by user mode (the new
+ * pt_regs doesn't have all registers as the kernel
+ * doesn't use the extra segment registers)
+ */
+
+/* When the kernel dumps core, it starts by dumping the user struct -
+   this will be used by gdb to figure out where the data and stack segments
+   are within the file, and what virtual addresses to use. */
+struct user {
+/* We start with the registers, to mimic the way that "memory" is returned
+   from the ptrace(3,...) function.  */
+  struct user_regs_struct regs;		/* Where the registers are actually stored */
+/* The rest of this junk is to help gdb figure out what goes where */
+  size_t   u_tsize;	     /* Text segment size (pages). */
+  size_t   u_dsize;	     /* Data segment size (pages). */
+  size_t   u_ssize;	     /* Stack segment size (pages). */
+  unsigned long start_code;  /* Starting virtual address of text. */
+  unsigned long start_stack; /* Starting virtual address of stack area.
+			        This is actually the bottom of the stack,
+				the top of the stack is always found in the
+				gprs[15] register.  */
+  long int signal;     	     /* Signal that caused the core dump. */
+  struct user_regs_struct *u_ar0;
+				/* Used by gdb to help find the values for */
+				/* the registers. */
+  unsigned long magic;		/* To uniquely identify a core file */
+  char u_comm[32];		/* User command that was responsible */
+};
+#define NBPG PAGE_SIZE
+#define UPAGES 1
+#define HOST_TEXT_START_ADDR (u.start_code)
+#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
+
+#endif /* _S390_USER_H */
diff -u --recursive --new-file v2.4.1/linux/include/asm-s390x/xor.h linux/include/asm-s390x/xor.h
--- v2.4.1/linux/include/asm-s390x/xor.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-s390x/xor.h	Tue Feb 13 14:13:44 2001
@@ -0,0 +1 @@
+#include <asm-generic/xor.h>
diff -u --recursive --new-file v2.4.1/linux/include/asm-sh/socket.h linux/include/asm-sh/socket.h
--- v2.4.1/linux/include/asm-sh/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-sh/socket.h	Sat Feb  3 11:26:44 2001
@@ -43,6 +43,8 @@
 #define SO_TIMESTAMP		29
 #define SCM_TIMESTAMP		SO_TIMESTAMP
 
+#define SO_ACCEPTCONN		30
+
 /* Nast libc5 fixup - bletch */
 #if defined(__KERNEL__)
 /* Socket types. */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sh/termios.h linux/include/asm-sh/termios.h
--- v2.4.1/linux/include/asm-sh/termios.h	Sun Mar  5 09:33:55 2000
+++ linux/include/asm-sh/termios.h	Sat Feb  3 20:00:45 2001
@@ -51,7 +51,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IR - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc/highmem.h linux/include/asm-sparc/highmem.h
--- v2.4.1/linux/include/asm-sparc/highmem.h	Wed Nov  8 19:01:34 2000
+++ linux/include/asm-sparc/highmem.h	Sun Feb 18 19:49:55 2001
@@ -2,7 +2,7 @@
  * highmem.h: virtual kernel memory mappings for high memory
  *
  * Used in CONFIG_HIGHMEM systems for memory pages which
- * are not addressable by direct kernel virtual adresses.
+ * are not addressable by direct kernel virtual addresses.
  *
  * Copyright (C) 1999 Gerhard Wichert, Siemens AG
  *		      Gerhard.Wichert@pdb.siemens.de
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc/socket.h linux/include/asm-sparc/socket.h
--- v2.4.1/linux/include/asm-sparc/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-sparc/socket.h	Sat Feb  3 11:26:44 2001
@@ -1,4 +1,4 @@
-/* $Id: socket.h,v 1.15 2000/07/08 00:20:43 davem Exp $ */
+/* $Id: socket.h,v 1.16 2001/01/30 07:48:30 davem Exp $ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
@@ -22,6 +22,7 @@
 #define SO_SNDLOWAT     0x1000
 #define SO_RCVTIMEO     0x2000
 #define SO_SNDTIMEO     0x4000
+#define SO_ACCEPTCONN	0x8000
 
 /* wha!??? */
 #define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc/termios.h linux/include/asm-sparc/termios.h
--- v2.4.1/linux/include/asm-sparc/termios.h	Mon Dec 20 22:05:52 1999
+++ linux/include/asm-sparc/termios.h	Fri Feb  9 11:37:03 2001
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.30 1999/12/02 09:57:46 davem Exp $ */
+/* $Id: termios.h,v 1.31 2001/02/05 05:54:29 davem Exp $ */
 #ifndef _SPARC_TERMIOS_H
 #define _SPARC_TERMIOS_H
 
@@ -66,7 +66,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc64/socket.h linux/include/asm-sparc64/socket.h
--- v2.4.1/linux/include/asm-sparc64/socket.h	Sun Jul  9 22:30:40 2000
+++ linux/include/asm-sparc64/socket.h	Sat Feb  3 11:26:44 2001
@@ -1,4 +1,4 @@
-/* $Id: socket.h,v 1.8 2000/07/08 00:20:43 davem Exp $ */
+/* $Id: socket.h,v 1.9 2001/01/30 07:48:30 davem Exp $ */
 #ifndef _ASM_SOCKET_H
 #define _ASM_SOCKET_H
 
@@ -22,6 +22,7 @@
 #define SO_SNDLOWAT     0x1000
 #define SO_RCVTIMEO     0x2000
 #define SO_SNDTIMEO     0x4000
+#define SO_ACCEPTCONN	0x8000
 
 /* wha!??? */
 #define SO_DONTLINGER   (~SO_LINGER)  /* Older SunOS compat. hack */
diff -u --recursive --new-file v2.4.1/linux/include/asm-sparc64/termios.h linux/include/asm-sparc64/termios.h
--- v2.4.1/linux/include/asm-sparc64/termios.h	Mon Dec 20 22:05:52 1999
+++ linux/include/asm-sparc64/termios.h	Fri Feb  9 11:37:03 2001
@@ -1,4 +1,4 @@
-/* $Id: termios.h,v 1.9 1999/12/02 09:57:53 davem Exp $ */
+/* $Id: termios.h,v 1.10 2001/02/05 05:54:29 davem Exp $ */
 #ifndef _SPARC64_TERMIOS_H
 #define _SPARC64_TERMIOS_H
 
@@ -66,7 +66,7 @@
 #define N_MASC		8	/* Reserved for Mobitex module <kaz@cafe.net> */
 #define N_R3964		9	/* Reserved for Simatic R3964 module */
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
-#define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
+#define N_IRDA		11	/* Linux IrDa - http://irda.sourceforge.net/ */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
 #define N_HDLC		13	/* synchronous HDLC */
 #define N_SYNC_PPP	14	/* synchronous PPP */
diff -u --recursive --new-file v2.4.1/linux/include/linux/acpi.h linux/include/linux/acpi.h
--- v2.4.1/linux/include/linux/acpi.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/acpi.h	Fri Feb  9 11:45:58 2001
@@ -82,13 +82,11 @@
 /* PM_TMR masks */
 #define ACPI_TMR_VAL_EXT 0x00000100
 #define ACPI_TMR_MASK	 0x00ffffff
-#define ACPI_TMR_HZ	 3580000 /* 3.58 MHz */
+#define ACPI_TMR_HZ	 3579545 /* 3.58 MHz */
+#define ACPI_TMR_KHZ	 (ACPI_TMR_HZ / 1000)
 
-/* strangess to avoid integer overflow */
 #define ACPI_MICROSEC_TO_TMR_TICKS(val) \
-  (((val) * (ACPI_TMR_HZ / 10000)) / 100)
-#define ACPI_TMR_TICKS_TO_MICROSEC(ticks) \
-  (((ticks) * 100) / (ACPI_TMR_HZ / 10000))
+  (((val) * (ACPI_TMR_KHZ)) / 1000)
 
 /* PM2_CNT flags */
 #define ACPI_ARB_DIS 0x01
@@ -147,6 +145,9 @@
 	ACPI_C1_TIME,
 	ACPI_C2_TIME,
 	ACPI_C3_TIME,
+	ACPI_C1_COUNT,
+	ACPI_C2_COUNT,
+	ACPI_C3_COUNT,
 	ACPI_S0_SLP_TYP,
 	ACPI_S1_SLP_TYP,
 	ACPI_S5_SLP_TYP,
diff -u --recursive --new-file v2.4.1/linux/include/linux/agp_backend.h linux/include/linux/agp_backend.h
--- v2.4.1/linux/include/linux/agp_backend.h	Fri Dec 29 14:07:24 2000
+++ linux/include/linux/agp_backend.h	Tue Feb 13 14:13:43 2001
@@ -59,6 +59,12 @@
 	AMD_GENERIC,
 	AMD_IRONGATE,
 	ALI_M1541,
+	ALI_M1621,
+	ALI_M1631,
+	ALI_M1632,
+	ALI_M1641,
+	ALI_M1647,
+	ALI_M1651,
 	ALI_GENERIC
 };
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/coda_linux.h linux/include/linux/coda_linux.h
--- v2.4.1/linux/include/linux/coda_linux.h	Mon Dec 11 13:25:00 2000
+++ linux/include/linux/coda_linux.h	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/sched.h> 
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/wait.h>		
 #include <linux/types.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.4.1/linux/include/linux/dasd.h linux/include/linux/dasd.h
--- v2.4.1/linux/include/linux/dasd.h	Fri May 12 11:41:44 2000
+++ linux/include/linux/dasd.h	Wed Dec 31 16:00:00 1969
@@ -1,225 +0,0 @@
-
-#ifndef DASD_H
-#define DASD_H
-
-/* First of all the external stuff */
-#include <linux/ioctl.h>
-#include <linux/major.h>
-#include <linux/wait.h>
-
-#define IOCTL_LETTER 'D'
-#define BIODASDFORMAT  _IO(IOCTL_LETTER,0) /* Format the volume or an extent */
-#define BIODASDDISABLE _IO(IOCTL_LETTER,1) /* Disable the volume (for Linux) */
-#define BIODASDENABLE  _IO(IOCTL_LETTER,2) /* Enable the volume (for Linux) */
-/* Stuff for reading and writing the Label-Area to/from user space */
-#define BIODASDGTVLBL  _IOR(IOCTL_LETTER,3,dasd_volume_label_t)
-#define BIODASDSTVLBL  _IOW(IOCTL_LETTER,4,dasd_volume_label_t)
-#define BIODASDRWTB    _IOWR(IOCTL_LETTER,5,int)
-#define BIODASDRSID    _IOR(IOCTL_LETTER,6,senseid_t)
-
-typedef
-union {
-	char bytes[512];
-	struct {
-		/* 80 Bytes of Label data */
-		char identifier[4];	/* e.g. "LNX1", "VOL1" or "CMS1" */
-		char label[6];	/* Given by user */
-		char security;
-		char vtoc[5];	/* Null in "LNX1"-labelled partitions */
-		char reserved0[5];
-		long ci_size;
-		long blk_per_ci;
-		long lab_per_ci;
-		char reserved1[4];
-		char owner[0xe];
-		char no_part;
-		char reserved2[0x1c];
-		/* 16 Byte of some information on the dasd */
-		short blocksize;
-		char nopart;
-		char unused;
-		long unused2[3];
-		/* 7*10 = 70 Bytes of partition data */
-		struct {
-			char type;
-			long start;
-			long size;
-			char unused;
-		} part[7];
-	} __attribute__ ((packed)) label;
-} dasd_volume_label_t;
-
-typedef union {
-	struct {
-		unsigned long no;
-		unsigned int ct;
-	} __attribute__ ((packed)) input;
-	struct {
-		unsigned long noct;
-	} __attribute__ ((packed)) output;
-} __attribute__ ((packed)) dasd_xlate_t;
-
-int dasd_init (void);
-#ifdef MODULE
-int init_module (void);
-void cleanup_module (void);
-#endif				/* MODULE */
-
-/* Definitions for blk.h */
-/* #define DASD_MAGIC 0x44415344  is ascii-"DASD" */
-/* #define dasd_MAGIC 0x64617364;  is ascii-"dasd" */
-#define DASD_MAGIC 0xC4C1E2C4 /* is ebcdic-"DASD" */
-#define dasd_MAGIC 0x8481A284 /* is ebcdic-"dasd" */
-#define DASD_NAME "dasd"
-#define DASD_PARTN_BITS 2
-#define DASD_MAX_DEVICES (256>>DASD_PARTN_BITS)
-
-#define MAJOR_NR DASD_MAJOR
-#define PARTN_BITS DASD_PARTN_BITS
-
-#ifdef __KERNEL__
-/* Now lets turn to the internal sbtuff */
-/*
-   define the debug levels:
-   - 0 No debugging output to console or syslog
-   - 1 Log internal errors to syslog, ignore check conditions 
-   - 2 Log internal errors and check conditions to syslog
-   - 3 Log internal errors to console, log check conditions to syslog
-   - 4 Log internal errors and check conditions to console
-   - 5 panic on internal errors, log check conditions to console
-   - 6 panic on both, internal errors and check conditions
- */
-#define DASD_DEBUG 4
-
-#define DASD_PROFILE
-/*
-   define the level of paranoia
-   - 0 quite sure, that things are going right
-   - 1 sanity checking, only to avoid panics
-   - 2 normal sanity checking
-   - 3 extensive sanity checks
-   - 4 exhaustive debug messages
- */
-#define DASD_PARANOIA 2
-
-/*
-   define the depth of flow control, which is logged as a check condition
-   - 0 No flow control messages
-   - 1 Entry of functions logged like check condition
-   - 2 Entry and exit of functions logged like check conditions
-   - 3 Internal structure broken down
-   - 4 unrolling of loops,...
- */
-#define DASD_FLOW_CONTROL 0
-
-#if DASD_DEBUG > 0
-#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
-#define PRINT_INFO(x...) printk ( KERN_INFO PRINTK_HEADER x )
-#define PRINT_WARN(x...) printk ( KERN_WARNING PRINTK_HEADER x )
-#define PRINT_ERR(x...) printk ( KERN_ERR PRINTK_HEADER x )
-#define PRINT_FATAL(x...) panic ( PRINTK_HEADER x )
-#else
-#define PRINT_DEBUG(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
-#define PRINT_INFO(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
-#define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
-#define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
-#define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER x )
-#endif				/* DASD_DEBUG */
-
-#define INTERNAL_ERRMSG(x,y...) \
-"Internal error: in file " __FILE__ " line: %d: " x, __LINE__, y
-#define INTERNAL_CHKMSG(x,y...) \
-"Inconsistency: in file " __FILE__ " line: %d: " x, __LINE__, y
-#define INTERNAL_FLWMSG(x,y...) \
-"Flow control: file " __FILE__ " line: %d: " x, __LINE__, y
-
-#if DASD_DEBUG > 4
-#define INTERNAL_ERROR(x...) PRINT_FATAL ( INTERNAL_ERRMSG ( x ) )
-#elif DASD_DEBUG > 2
-#define INTERNAL_ERROR(x...) PRINT_ERR ( INTERNAL_ERRMSG ( x ) )
-#elif DASD_DEBUG > 0
-#define INTERNAL_ERROR(x...) PRINT_WARN ( INTERNAL_ERRMSG ( x ) )
-#else
-#define INTERNAL_ERROR(x...)
-#endif				/* DASD_DEBUG */
-
-#if DASD_DEBUG > 5
-#define INTERNAL_CHECK(x...) PRINT_FATAL ( INTERNAL_CHKMSG ( x ) )
-#elif DASD_DEBUG > 3
-#define INTERNAL_CHECK(x...) PRINT_ERR ( INTERNAL_CHKMSG ( x ) )
-#elif DASD_DEBUG > 1
-#define INTERNAL_CHECK(x...) PRINT_WARN ( INTERNAL_CHKMSG ( x ) )
-#else
-#define INTERNAL_CHECK(x...)
-#endif				/* DASD_DEBUG */
-
-#if DASD_DEBUG > 3
-#define INTERNAL_FLOW(x...) PRINT_ERR ( INTERNAL_FLWMSG ( x ) )
-#elif DASD_DEBUG > 2
-#define INTERNAL_FLOW(x...) PRINT_WARN ( INTERNAL_FLWMSG ( x ) )
-#else
-#define INTERNAL_FLOW(x...)
-#endif				/* DASD_DEBUG */
-
-#if DASD_FLOW_CONTROL > 0
-#define FUNCTION_ENTRY(x) INTERNAL_FLOW( x "entered %s\n","" );
-#else
-#define FUNCTION_ENTRY(x)
-#endif				/* DASD_FLOW_CONTROL */
-
-#if DASD_FLOW_CONTROL > 1
-#define FUNCTION_EXIT(x) INTERNAL_FLOW( x "exited %s\n","" );
-#else
-#define FUNCTION_EXIT(x)
-#endif				/* DASD_FLOW_CONTROL */
-
-#if DASD_FLOW_CONTROL > 2
-#define FUNCTION_CONTROL(x...) INTERNAL_FLOW( x );
-#else
-#define FUNCTION_CONTROL(x...)
-#endif				/* DASD_FLOW_CONTROL */
-
-#if DASD_FLOW_CONTROL > 3
-#define LOOP_CONTROL(x...) INTERNAL_FLOW( x );
-#else
-#define LOOP_CONTROL(x...)
-#endif				/* DASD_FLOW_CONTROL */
-
-#define DASD_DO_IO_SLEEP 0x01
-#define DASD_DO_IO_NOLOCK 0x02
-#define DASD_DO_IO_NODEC 0x04
-
-#define DASD_NOT_FORMATTED 0x01
-
-extern wait_queue_head_t dasd_waitq;
-
-#undef DEBUG_DASD_MALLOC
-#ifdef DEBUG_DASD_MALLOC
-void *b;
-#define kmalloc(x...) (PRINT_INFO(" kmalloc %p\n",b=kmalloc(x)),b)
-#define kfree(x) PRINT_INFO(" kfree %p\n",x);kfree(x)
-#define get_free_page(x...) (PRINT_INFO(" gfp %p\n",b=get_free_page(x)),b)
-#define __get_free_pages(x...) (PRINT_INFO(" gfps %p\n",b=__get_free_pages(x)),b)
-#endif				/* DEBUG_DASD_MALLOC */
-
-#endif				/* __KERNEL__ */
-#endif				/* DASD_H */
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-indent-level: 4 
- * c-brace-imaginary-offset: 0
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * c-continued-statement-offset: 4
- * c-continued-brace-offset: 0
- * indent-tabs-mode: nil
- * tab-width: 8
- * End:
- */
diff -u --recursive --new-file v2.4.1/linux/include/linux/dcache.h linux/include/linux/dcache.h
--- v2.4.1/linux/include/linux/dcache.h	Thu Jan  4 14:50:46 2001
+++ linux/include/linux/dcache.h	Wed Feb 21 16:09:56 2001
@@ -27,21 +27,28 @@
 	unsigned int hash;
 };
 
+struct dentry_stat_t {
+	int nr_dentry;
+	int nr_unused;
+	int age_limit;          /* age in seconds */
+	int want_pages;         /* pages requested by system */
+	int dummy[2];
+};
+extern struct dentry_stat_t dentry_stat;
+
 /* Name hashing routines. Initial hash value */
+/* Hash courtesy of the R5 hash in reiserfs modulo sign bits */
 #define init_name_hash()		0
 
 /* partial hash update function. Assume roughly 4 bits per character */
 static __inline__ unsigned long partial_name_hash(unsigned long c, unsigned long prevhash)
 {
-	prevhash = (prevhash << 4) | (prevhash >> (8*sizeof(unsigned long)-4));
-	return prevhash ^ c;
+	return (prevhash + (c << 4) + (c >> 4)) * 11;
 }
 
 /* Finally: cut down the number of bits to a int value (and try to avoid losing bits) */
 static __inline__ unsigned long end_name_hash(unsigned long hash)
 {
-	if (sizeof(hash) > sizeof(unsigned int))
-		hash += hash >> 4*sizeof(hash);
 	return (unsigned int) hash;
 }
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/elevator.h linux/include/linux/elevator.h
--- v2.4.1/linux/include/linux/elevator.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/elevator.h	Thu Feb 15 16:58:34 2001
@@ -1,14 +1,12 @@
 #ifndef _LINUX_ELEVATOR_H
 #define _LINUX_ELEVATOR_H
 
-#define ELEVATOR_DEBUG
-
 typedef void (elevator_fn) (struct request *, elevator_t *,
 			    struct list_head *,
 			    struct list_head *, int);
 
 typedef int (elevator_merge_fn) (request_queue_t *, struct request **, struct list_head *,
-				 struct buffer_head *, int, int, int);
+				 struct buffer_head *, int, int);
 
 typedef void (elevator_merge_cleanup_fn) (request_queue_t *, struct request *, int);
 
@@ -26,11 +24,11 @@
 	unsigned int queue_ID;
 };
 
-int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int);
+int elevator_noop_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int);
 void elevator_noop_merge_cleanup(request_queue_t *, struct request *, int);
 void elevator_noop_merge_req(struct request *, struct request *);
 
-int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int, int);
+int elevator_linus_merge(request_queue_t *, struct request **, struct list_head *, struct buffer_head *, int, int);
 void elevator_linus_merge_cleanup(request_queue_t *, struct request *, int);
 void elevator_linus_merge_req(struct request *, struct request *);
 
@@ -68,8 +66,9 @@
 	 (s1)->rq_dev < (s2)->rq_dev)
 
 #define BHRQ_IN_ORDER(bh, rq)			\
-	(((bh)->b_rdev == (rq)->rq_dev &&	\
-	  (bh)->b_rsector < (rq)->sector))
+	((((bh)->b_rdev == (rq)->rq_dev &&	\
+	   (bh)->b_rsector < (rq)->sector)) ||	\
+	 (bh)->b_rdev < (rq)->rq_dev)
 
 static inline int elevator_request_latency(elevator_t * elevator, int rw)
 {
diff -u --recursive --new-file v2.4.1/linux/include/linux/elf.h linux/include/linux/elf.h
--- v2.4.1/linux/include/linux/elf.h	Thu Jan  4 14:51:47 2001
+++ linux/include/linux/elf.h	Wed Feb 21 16:11:41 2001
@@ -74,6 +74,8 @@
 
 #define EM_X8664	62	/* AMD x86-64 */
 
+#define EM_CRIS         76      /* Axis Communications 32-bit embedded processor */
+
 /*
  * This is an interim value that we will use until the committee comes
  * up with a final number.
diff -u --recursive --new-file v2.4.1/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.4.1/linux/include/linux/fs.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/fs.h	Wed Feb 21 16:09:58 2001
@@ -53,6 +53,14 @@
 	int max_files;		/* tunable */
 };
 extern struct files_stat_struct files_stat;
+
+struct inodes_stat_t {
+	int nr_inodes;
+	int nr_unused;
+	int dummy[5];
+};
+extern struct inodes_stat_t inodes_stat;
+
 extern int max_super_blocks, nr_super_blocks;
 extern int leases_enable, dir_notify_enable, lease_break_time;
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/hfs_fs.h linux/include/linux/hfs_fs.h
--- v2.4.1/linux/include/linux/hfs_fs.h	Mon Dec 11 13:25:30 2000
+++ linux/include/linux/hfs_fs.h	Tue Feb 13 14:13:44 2001
@@ -2,7 +2,7 @@
  * linux/include/linux/hfs_fs.h
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * The source code distribution of the Columbia AppleTalk Package for
  * UNIX, version 6.0, (CAP) was used as a specification of the
diff -u --recursive --new-file v2.4.1/linux/include/linux/hfs_fs_i.h linux/include/linux/hfs_fs_i.h
--- v2.4.1/linux/include/linux/hfs_fs_i.h	Thu Feb 10 12:17:00 2000
+++ linux/include/linux/hfs_fs_i.h	Tue Feb 13 14:13:44 2001
@@ -2,7 +2,7 @@
  * linux/include/linux/hfs_fs_i.h
  *
  * Copyright (C) 1995, 1996  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file defines the type (struct hfs_inode_info) and the two
  * subordinate types hfs_extent and hfs_file.
diff -u --recursive --new-file v2.4.1/linux/include/linux/hfs_fs_sb.h linux/include/linux/hfs_fs_sb.h
--- v2.4.1/linux/include/linux/hfs_fs_sb.h	Wed May 12 13:26:20 1999
+++ linux/include/linux/hfs_fs_sb.h	Tue Feb 13 14:13:44 2001
@@ -2,7 +2,7 @@
  * linux/include/linux/hfs_fs_sb.h
  *
  * Copyright (C) 1995-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file defines the type (struct hfs_sb_info) which contains the
  * HFS-specific information in the in-core superblock.
diff -u --recursive --new-file v2.4.1/linux/include/linux/hfs_sysdep.h linux/include/linux/hfs_sysdep.h
--- v2.4.1/linux/include/linux/hfs_sysdep.h	Mon Dec 11 13:25:24 2000
+++ linux/include/linux/hfs_sysdep.h	Tue Feb 13 14:13:44 2001
@@ -2,7 +2,7 @@
  * linux/include/linux/hfs_sysdep.h
  *
  * Copyright (C) 1996-1997  Paul H. Hargrove
- * This file may be distributed under the terms of the GNU Public License.
+ * This file may be distributed under the terms of the GNU General Public License.
  *
  * This file contains constants, types and inline
  * functions for various system dependent things.
@@ -17,7 +17,7 @@
 #ifndef _HFS_SYSDEP_H
 #define _HFS_SYSDEP_H
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/locks.h>
 #include <linux/fs.h>
diff -u --recursive --new-file v2.4.1/linux/include/linux/highmem.h linux/include/linux/highmem.h
--- v2.4.1/linux/include/linux/highmem.h	Thu Jan  4 14:50:47 2001
+++ linux/include/linux/highmem.h	Wed Feb 21 16:09:58 2001
@@ -38,7 +38,7 @@
 #define kunmap_atomic(page,idx)		kunmap(page)
 
 #define bh_kmap(bh)	((bh)->b_data)
-#define bh_kunmap(bh)	do { } while (0);
+#define bh_kunmap(bh)	do { } while (0)
 
 #endif /* CONFIG_HIGHMEM */
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/interrupt.h linux/include/linux/interrupt.h
--- v2.4.1/linux/include/linux/interrupt.h	Thu Jan  4 14:50:47 2001
+++ linux/include/linux/interrupt.h	Wed Feb 21 16:09:58 2001
@@ -146,7 +146,7 @@
 
 #ifdef CONFIG_SMP
 #define tasklet_trylock(t) (!test_and_set_bit(TASKLET_STATE_RUN, &(t)->state))
-#define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { /* NOTHING */ }
+#define tasklet_unlock_wait(t) while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); }
 #define tasklet_unlock(t) clear_bit(TASKLET_STATE_RUN, &(t)->state)
 #else
 #define tasklet_trylock(t) 1
diff -u --recursive --new-file v2.4.1/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.4.1/linux/include/linux/isdn.h	Mon Dec 11 13:21:27 2000
+++ linux/include/linux/isdn.h	Fri Feb  9 11:29:44 2001
@@ -1,4 +1,4 @@
-/* $Id: isdn.h,v 1.111 2000/11/25 17:01:02 kai Exp $
+/* $Id: isdn.h,v 1.111.6.1 2001/02/07 11:31:31 kai Exp $
 
  * Main header for the Linux ISDN subsystem (linklevel).
  *
@@ -196,7 +196,7 @@
 #include <asm/io.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/wait.h>
 #include <linux/tty.h>
@@ -592,23 +592,6 @@
 	char *private;
 } infostruct;
 
-typedef struct isdn_module {
-	struct isdn_module *prev;
-	struct isdn_module *next;
-	char *name;
-	int (*get_free_channel)(int, int, int, int, int);
-	int (*free_channel)(int, int, int);
-	int (*status_callback)(isdn_ctrl *);
-	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 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;
-
 #define DRV_FLAG_RUNNING 1
 #define DRV_FLAG_REJBUS  2
 #define DRV_FLAG_LOADED  4
@@ -668,7 +651,6 @@
 	atomic_t          v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
 	isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
 	struct semaphore  sem;                       /* serialize list access*/
-	isdn_module       *modules;
 	unsigned long     global_features;
 #ifdef CONFIG_DEVFS_FS
 	devfs_handle_t devfs_handle_isdninfo;
diff -u --recursive --new-file v2.4.1/linux/include/linux/kdev_t.h linux/include/linux/kdev_t.h
--- v2.4.1/linux/include/linux/kdev_t.h	Mon Jan 24 11:04:37 2000
+++ linux/include/linux/kdev_t.h	Fri Feb 16 16:06:17 2001
@@ -1,6 +1,6 @@
 #ifndef _LINUX_KDEV_T_H
 #define _LINUX_KDEV_T_H
-#ifdef __KERNEL__
+#if defined(__KERNEL__) || defined(_LVM_H_INCLUDE)
 /*
 As a preparation for the introduction of larger device numbers,
 we introduce a type kdev_t to hold them. No information about
@@ -101,7 +101,7 @@
 	return MKDEV(major, minor);
 }
 
-#else /* __KERNEL__ */
+#else /* __KERNEL__ || _LVM_H_INCLUDE */
 
 /*
 Some programs want their definitions of MAJOR and MINOR and MKDEV
@@ -110,5 +110,5 @@
 #define MAJOR(dev)	((dev)>>8)
 #define MINOR(dev)	((dev) & 0xff)
 #define MKDEV(ma,mi)	((ma)<<8 | (mi))
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ || _LVM_H_INCLUDE */
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/linux/kernelcapi.h linux/include/linux/kernelcapi.h
--- v2.4.1/linux/include/linux/kernelcapi.h	Tue Nov 28 21:43:13 2000
+++ linux/include/linux/kernelcapi.h	Thu Feb  8 10:40:25 2001
@@ -1,5 +1,5 @@
 /*
- * $Id: kernelcapi.h,v 1.8.6.1 2000/11/28 09:36:56 kai Exp $
+ * $Id: kernelcapi.h,v 1.8.6.2 2001/02/07 11:31:31 kai Exp $
  * 
  * Kernel CAPI 2.0 Interface for Linux
  * 
@@ -10,8 +10,8 @@
 #ifndef __KERNELCAPI_H__
 #define __KERNELCAPI_H__
 
-#define CAPI_MAXAPPL	20	/* maximum number of applications  */
-#define CAPI_MAXCONTR	10	/* maximum number of controller    */
+#define CAPI_MAXAPPL	128	/* maximum number of applications  */
+#define CAPI_MAXCONTR	16	/* maximum number of controller    */
 #define CAPI_MAXDATAWINDOW	8
 
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/list.h linux/include/linux/list.h
--- v2.4.1/linux/include/linux/list.h	Tue Aug  8 12:18:58 2000
+++ linux/include/linux/list.h	Fri Feb 16 16:06:17 2001
@@ -1,7 +1,7 @@
 #ifndef _LINUX_LIST_H
 #define _LINUX_LIST_H
 
-#ifdef __KERNEL__
+#if defined(__KERNEL__) || defined(_LVM_H_INCLUDE)
 
 /*
  * Simple doubly linked list implementation.
@@ -149,6 +149,6 @@
 #define list_for_each(pos, head) \
 	for (pos = (head)->next; pos != (head); pos = pos->next)
 
-#endif /* __KERNEL__ */
+#endif /* __KERNEL__ || _LVM_H_INCLUDE */
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/linux/lvm.h linux/include/linux/lvm.h
--- v2.4.1/linux/include/linux/lvm.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/lvm.h	Fri Feb 16 16:06:17 2001
@@ -95,15 +95,8 @@
  */
 #endif				/* #ifdef __KERNEL__ */
 
-#ifndef __KERNEL__
-#define __KERNEL__
 #include <linux/kdev_t.h>
 #include <linux/list.h>
-#undef __KERNEL__
-#else
-#include <linux/kdev_t.h>
-#include <linux/list.h>
-#endif				/* #ifndef __KERNEL__ */
 
 #include <asm/types.h>
 #include <linux/major.h>
diff -u --recursive --new-file v2.4.1/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.4.1/linux/include/linux/mm.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/mm.h	Wed Feb 21 16:09:58 2001
@@ -200,8 +200,8 @@
 					smp_mb__before_clear_bit(); \
 					if (!test_and_clear_bit(PG_locked, &(page)->flags)) BUG(); \
 					smp_mb__after_clear_bit(); \
-					if (waitqueue_active(&page->wait)) \
-						wake_up(&page->wait); \
+					if (waitqueue_active(&(page)->wait)) \
+						wake_up(&(page)->wait); \
 				} while (0)
 #define PageError(page)		test_bit(PG_error, &(page)->flags)
 #define SetPageError(page)	set_bit(PG_error, &(page)->flags)
diff -u --recursive --new-file v2.4.1/linux/include/linux/module.h linux/include/linux/module.h
--- v2.4.1/linux/include/linux/module.h	Thu Jan  4 14:50:46 2001
+++ linux/include/linux/module.h	Wed Feb 21 16:09:57 2001
@@ -249,12 +249,6 @@
   __attribute__ ((unused)) = name
 #define MODULE_DEVICE_TABLE(type,name)		\
   MODULE_GENERIC_TABLE(type##_device,name)
-/* not put to .modinfo section to avoid section type conflicts */
-
-/* The attributes of a section are set the first time the section is
-   seen; we want .modinfo to not be allocated.  */
-
-__asm__(".section .modinfo\n\t.previous");
 
 /* Define the module variable, and usage macros.  */
 extern struct module __this_module;
diff -u --recursive --new-file v2.4.1/linux/include/linux/mtd/ftl.h linux/include/linux/mtd/ftl.h
--- v2.4.1/linux/include/linux/mtd/ftl.h	Tue Jul  4 10:10:52 2000
+++ linux/include/linux/mtd/ftl.h	Sun Feb  4 10:05:30 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/linux/mtd/map.h linux/include/linux/mtd/map.h
--- v2.4.1/linux/include/linux/mtd/map.h	Fri Dec 29 14:07:24 2000
+++ linux/include/linux/mtd/map.h	Fri Feb  9 11:29:44 2001
@@ -1,6 +1,6 @@
 
 /* Overhauled routines for dealing with different mmap regions of flash */
-/* $Id: map.h,v 1.10 2000/12/04 13:18:33 dwmw2 Exp $ */
+/* $Id: map.h,v 1.10.2.2 2001/01/09 00:44:51 dwmw2 Exp $ */
 
 #ifndef __LINUX_MTD_MAP_H__
 #define __LINUX_MTD_MAP_H__
@@ -8,7 +8,7 @@
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 /* The map stuff is very simple. You fill in your struct map_info with
    a handful of routines for accessing the device, making sure they handle
@@ -44,7 +44,7 @@
 	void (*write32)(struct map_info *, __u32, unsigned long);
 	void (*copy_to)(struct map_info *, unsigned long, const void *, ssize_t);
 
-	void (*set_vpp)(int);
+	void (*set_vpp)(struct map_info *, int);
 	/* We put these two here rather than a single void *map_priv, 
 	   because we want mappers to be able to have quickly-accessible
 	   cache for the 'currently-mapped page' without the _extra_
@@ -108,7 +108,7 @@
 	kfree(mtd);
 }
 
-#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(1); } while(0)
-#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(0); } while(0)
+#define ENABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 1); } while(0)
+#define DISABLE_VPP(map) do { if(map->set_vpp) map->set_vpp(map, 0); } while(0)
 
 #endif /* __LINUX_MTD_MAP_H__ */
diff -u --recursive --new-file v2.4.1/linux/include/linux/ncp_fs.h linux/include/linux/ncp_fs.h
--- v2.4.1/linux/include/linux/ncp_fs.h	Mon Dec 11 13:26:24 2000
+++ linux/include/linux/ncp_fs.h	Fri Feb  9 11:29:44 2001
@@ -196,7 +196,7 @@
 
 #ifdef DEBUG_NCP_MALLOC
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 extern int ncp_malloced;
 extern int ncp_current_malloced;
diff -u --recursive --new-file v2.4.1/linux/include/linux/nubus.h linux/include/linux/nubus.h
--- v2.4.1/linux/include/linux/nubus.h	Sat Sep  4 13:10:30 1999
+++ linux/include/linux/nubus.h	Tue Feb 13 14:13:45 2001
@@ -319,4 +319,4 @@
 	return (void *)(0xF0000000|(slot<<24));
 }
 
-#endif LINUX_NUBUS_H
+#endif /* LINUX_NUBUS_H */
diff -u --recursive --new-file v2.4.1/linux/include/linux/parport.h linux/include/linux/parport.h
--- v2.4.1/linux/include/linux/parport.h	Mon Dec 11 12:50:09 2000
+++ linux/include/linux/parport.h	Thu Feb  8 10:40:25 2001
@@ -229,7 +229,7 @@
 	unsigned long int time;
 	unsigned long int timeslice;
 	volatile long int timeout;
-	unsigned int waiting;
+	unsigned long waiting;		 /* long req'd for set_bit --RR */
 	struct pardevice *waitprev;
 	struct pardevice *waitnext;
 	void * sysctl_table;
diff -u --recursive --new-file v2.4.1/linux/include/linux/pci.h linux/include/linux/pci.h
--- v2.4.1/linux/include/linux/pci.h	Thu Jan  4 14:51:32 2001
+++ linux/include/linux/pci.h	Wed Feb 21 16:10:37 2001
@@ -565,9 +565,9 @@
 { 	return PCIBIOS_DEVICE_NOT_FOUND; }
 
 #define _PCI_NOP(o,s,t) \
-	static inline int pcibios_##o##_config_##s## (u8 bus, u8 dfn, u8 where, t val) \
+	static inline int pcibios_##o##_config_##s (u8 bus, u8 dfn, u8 where, t val) \
 		{ return PCIBIOS_FUNC_NOT_SUPPORTED; } \
-	static inline int pci_##o##_config_##s## (struct pci_dev *dev, int where, t val) \
+	static inline int pci_##o##_config_##s (struct pci_dev *dev, int where, t val) \
 		{ return PCIBIOS_FUNC_NOT_SUPPORTED; }
 #define _PCI_NOP_ALL(o,x)	_PCI_NOP(o,byte,u8 x) \
 				_PCI_NOP(o,word,u16 x) \
diff -u --recursive --new-file v2.4.1/linux/include/linux/pci_ids.h linux/include/linux/pci_ids.h
--- v2.4.1/linux/include/linux/pci_ids.h	Tue Jan  2 16:58:45 2001
+++ linux/include/linux/pci_ids.h	Sat Feb  3 12:48:00 2001
@@ -141,6 +141,7 @@
 #define PCI_DEVICE_ID_COMPAQ_NETEL100PI	0xae43
 #define PCI_DEVICE_ID_COMPAQ_NETEL100I	0xb011
 #define PCI_DEVICE_ID_COMPAQ_CISS	0xb060
+#define PCI_DEVICE_ID_COMPAQ_CISSB	0xb178
 #define PCI_DEVICE_ID_COMPAQ_THUNDER	0xf130
 #define PCI_DEVICE_ID_COMPAQ_NETFLEX3B	0xf150
 
@@ -688,13 +689,23 @@
 #define PCI_DEVICE_ID_CERN_HIPPI_DST	0x0021
 #define PCI_DEVICE_ID_CERN_HIPPI_SRC	0x0022
 
-#define PCI_VENDOR_ID_NVIDIA		0x10de
-#define PCI_DEVICE_ID_NVIDIA_TNT	0x0020
-#define PCI_DEVICE_ID_NVIDIA_TNT2	0x0028
-#define PCI_DEVICE_ID_NVIDIA_UTNT2	0x0029
-#define PCI_DEVICE_ID_NVIDIA_VTNT2	0x002C
-#define PCI_DEVICE_ID_NVIDIA_UVTNT2	0x002D
-#define PCI_DEVICE_ID_NVIDIA_ITNT2	0x00A0
+#define PCI_VENDOR_ID_NVIDIA			0x10de
+#define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
+#define PCI_DEVICE_ID_NVIDIA_TNT2		0x0028
+#define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
+#define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
+#define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
+#define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
+#define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX	0x0110
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
+#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
+#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
+#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
 
 #define PCI_VENDOR_ID_IMS		0x10e0
 #define PCI_DEVICE_ID_IMS_8849		0x8849
diff -u --recursive --new-file v2.4.1/linux/include/linux/proc_fs.h linux/include/linux/proc_fs.h
--- v2.4.1/linux/include/linux/proc_fs.h	Thu Jan  4 14:50:54 2001
+++ linux/include/linux/proc_fs.h	Wed Feb 21 16:10:01 2001
@@ -2,7 +2,7 @@
 #define _LINUX_PROC_FS_H
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 /*
  * The proc filesystem constants/structures
diff -u --recursive --new-file v2.4.1/linux/include/linux/raid/raid5.h linux/include/linux/raid/raid5.h
--- v2.4.1/linux/include/linux/raid/raid5.h	Fri Dec 29 14:07:24 2000
+++ linux/include/linux/raid/raid5.h	Thu Feb  8 19:38:38 2001
@@ -57,9 +57,9 @@
  *
  * Buffers for the md device that arrive via make_request are attached
  * to the appropriate stripe in one of two lists linked on b_reqnext.
- * One list for read requests, one for write.  There should never be
- * more than one buffer on the two lists together, but we are not
- * guaranteed of that so we allow for more.
+ * One list (bh_read) for read requests, one (bh_write) for write.
+ * There should never be more than one buffer on the two lists
+ * together, but we are not guaranteed of that so we allow for more.
  *
  * If a buffer is on the read list when the associated cache buffer is
  * Uptodate, the data is copied into the read buffer and it's b_end_io
@@ -70,16 +70,18 @@
  * that the Uptodate bit is set.  Once they have checked that they may
  * take buffers off the read queue.
  *
- * When a buffer on the write_list is committed for write, it is
- * marked clean, copied into the cache buffer, which is then marked
- * dirty, and moved onto a third list, the written list.  Once both
- * the parity block and the cached buffer are successfully written,
- * any buffer on a written list can be returned with b_end_io.
+ * When a buffer on the write list is committed for write is it copied
+ * into the cache buffer, which is then marked dirty, and moved onto a
+ * third list, the written list (bh_written).  Once both the parity
+ * block and the cached buffer are successfully written, any buffer on
+ * a written list can be returned with b_end_io.
  *
- * The write_list and read_list lists act as fifos.  They are protected by the
- * device_lock which can be claimed when a stripe_lock is held.
- * The device_lock is only for list manipulations and will only be held for a very
- * short time.  It can be claimed from interrupts.
+ * The write list and read list both act as fifos.  The read list is
+ * protected by the device_lock.  The write and written lists are
+ * protected by the stripe lock.  The device_lock, which can be
+ * claimed while the stipe lock is held, is only for list
+ * manipulations and will only be held for a very short time.  It can
+ * be claimed from interrupts.
  *
  *
  * Stripes in the stripe cache can be on one of two lists (or on
diff -u --recursive --new-file v2.4.1/linux/include/linux/reiserfs_fs.h linux/include/linux/reiserfs_fs.h
--- v2.4.1/linux/include/linux/reiserfs_fs.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/reiserfs_fs.h	Fri Feb  9 11:29:44 2001
@@ -15,7 +15,7 @@
 
 #include <linux/types.h>
 #ifdef __KERNEL__
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/tqueue.h>
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/sched.h linux/include/linux/sched.h
--- v2.4.1/linux/include/linux/sched.h	Sat Feb  3 19:51:32 2001
+++ linux/include/linux/sched.h	Wed Feb 21 16:09:58 2001
@@ -551,7 +551,7 @@
 extern void FASTCALL(interruptible_sleep_on(wait_queue_head_t *q));
 extern long FASTCALL(interruptible_sleep_on_timeout(wait_queue_head_t *q,
 						    signed long timeout));
-extern void FASTCALL(wake_up_process(struct task_struct * tsk));
+extern int FASTCALL(wake_up_process(struct task_struct * tsk));
 
 #define wake_up(x)			__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, 1)
 #define wake_up_nr(x, nr)		__wake_up((x),TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE, nr)
diff -u --recursive --new-file v2.4.1/linux/include/linux/serial.h linux/include/linux/serial.h
--- v2.4.1/linux/include/linux/serial.h	Thu Jan  4 14:50:47 2001
+++ linux/include/linux/serial.h	Wed Feb 21 16:09:57 2001
@@ -139,8 +139,9 @@
 #define ASYNC_CHECK_CD		0x02000000 /* i.e., CLOCAL */
 #define ASYNC_SHARE_IRQ		0x01000000 /* for multifunction cards
 					     --- no longer used */
+#define ASYNC_NO_FLOW		0x00800000 /* No flow control serial console */
 
-#define ASYNC_INTERNAL_FLAGS	0xFF000000 /* Internal flags */
+#define ASYNC_INTERNAL_FLAGS	0xFF800000 /* Internal flags */
 
 /*
  * Multiport serial configuration structure --- external structure
@@ -177,5 +178,7 @@
 extern int register_serial(struct serial_struct *req);
 extern void unregister_serial(int line);
 
+/* Allow complicated architectures to specify rs_table[] at run time */
+extern int early_serial_setup(struct serial_struct *req);
 #endif /* __KERNEL__ */
 #endif /* _LINUX_SERIAL_H */
diff -u --recursive --new-file v2.4.1/linux/include/linux/skbuff.h linux/include/linux/skbuff.h
--- v2.4.1/linux/include/linux/skbuff.h	Thu Jan  4 14:51:10 2001
+++ linux/include/linux/skbuff.h	Wed Feb 21 16:10:12 2001
@@ -153,7 +153,7 @@
 /*
  *	Handling routines are only of interest to the kernel
  */
-#include <linux/malloc.h>
+#include <linux/slab.h>
 
 #include <asm/system.h>
 
@@ -878,26 +878,45 @@
 }
 
 /**
- *	dev_alloc_skb - allocate an skbuff for sending
+ *	__dev_alloc_skb - allocate an skbuff for sending
  *	@length: length to allocate
+ *	@gfp_mask: get_free_pages mask, passed to alloc_skb
  *
  *	Allocate a new &sk_buff and assign it a usage count of one. The
  *	buffer has unspecified headroom built in. Users should allocate
  *	the headroom they think they need without accounting for the
  *	built in space. The built in space is used for optimisations.
  *
- *	%NULL is returned in there is no free memory. Although this function
- *	allocates memory it can be called from an interrupt.
+ *	%NULL is returned in there is no free memory.
  */
  
-static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+static inline struct sk_buff *__dev_alloc_skb(unsigned int length,
+					      int gfp_mask)
 {
 	struct sk_buff *skb;
 
-	skb = alloc_skb(length+16, GFP_ATOMIC);
+	skb = alloc_skb(length+16, gfp_mask);
 	if (skb)
 		skb_reserve(skb,16);
 	return skb;
+}
+
+/**
+ *	dev_alloc_skb - allocate an skbuff for sending
+ *	@length: length to allocate
+ *
+ *	Allocate a new &sk_buff and assign it a usage count of one. The
+ *	buffer has unspecified headroom built in. Users should allocate
+ *	the headroom they think they need without accounting for the
+ *	built in space. The built in space is used for optimisations.
+ *
+ *	%NULL is returned in there is no free memory. Although this function
+ *	allocates memory it can be called from an interrupt.
+ */
+ 
+static inline struct sk_buff *dev_alloc_skb(unsigned int length)
+{
+	return __dev_alloc_skb(length, GFP_ATOMIC);
 }
 
 /**
diff -u --recursive --new-file v2.4.1/linux/include/linux/smb.h linux/include/linux/smb.h
--- v2.4.1/linux/include/linux/smb.h	Thu Jan  4 14:50:46 2001
+++ linux/include/linux/smb.h	Wed Feb 21 16:09:56 2001
@@ -93,14 +93,6 @@
 	unsigned long	f_blocks;
 };
 
-struct smb_dirent {
-	struct smb_fattr attr;
-
-	int f_pos;
-	int len;
-	__u8 name[SMB_MAXNAMELEN];
-};
-
 enum smb_conn_state {
         CONN_VALID,             /* everything's fine */
         CONN_INVALID,           /* Something went wrong, but did not
@@ -120,11 +112,13 @@
 
 #define SMB_HEADER_LEN   37     /* includes everything up to, but not
                                  * including smb_bcc */
-#define SMB_DEF_MAX_XMIT 32768
-#define SMB_INITIAL_PACKET_SIZE 4000
 
-/* Allocate max. 1 page */
-#define TRANS2_MAX_TRANSFER (4096-17)
+#define SMB_INITIAL_PACKET_SIZE		4000
+#define SMB_MAX_PACKET_SIZE		32768
+
+/* reserve this much space for trans2 parameters. Shouldn't have to be more
+   than 10 or so, but OS/2 seems happier like this. */
+#define SMB_TRANS2_MAX_PARAM 64
 
 #endif
 #endif
diff -u --recursive --new-file v2.4.1/linux/include/linux/smb_fs.h linux/include/linux/smb_fs.h
--- v2.4.1/linux/include/linux/smb_fs.h	Mon Dec 11 13:26:20 2000
+++ linux/include/linux/smb_fs.h	Fri Feb 16 16:03:24 2001
@@ -20,23 +20,31 @@
 /* __kernel_uid_t can never change, so we have to use __kernel_uid32_t */
 #define	SMB_IOC_GETMOUNTUID32		_IOR('u', 3, __kernel_uid32_t)
 
+
 #ifdef __KERNEL__
 
+#include <linux/pagemap.h>
+#include <linux/vmalloc.h>
+#include <linux/smb_mount.h>
 #include <asm/unaligned.h>
 
+
+/* macro names are short for word, double-word, long value (?) */
 #define WVAL(buf,pos) \
-(le16_to_cpu(get_unaligned((__u16 *)((__u8 *)(buf) + (pos)))))
+	(le16_to_cpu(get_unaligned((u16 *)((u8 *)(buf) + (pos)))))
 #define DVAL(buf,pos) \
-(le32_to_cpu(get_unaligned((__u32 *)((__u8 *)(buf) + (pos)))))
+	(le32_to_cpu(get_unaligned((u32 *)((u8 *)(buf) + (pos)))))
+#define LVAL(buf,pos) \
+	(le64_to_cpu(get_unaligned((u64 *)((u8 *)(buf) + (pos)))))
 #define WSET(buf,pos,val) \
-put_unaligned(cpu_to_le16((__u16)(val)), (__u16 *)((__u8 *)(buf) + (pos)))
+	put_unaligned(cpu_to_le16((u16)(val)), (u16 *)((u8 *)(buf) + (pos)))
 #define DSET(buf,pos,val) \
-put_unaligned(cpu_to_le32((__u32)(val)), (__u32 *)((__u8 *)(buf) + (pos)))
+	put_unaligned(cpu_to_le32((u32)(val)), (u32 *)((u8 *)(buf) + (pos)))
+#define LSET(buf,pos,val) \
+	put_unaligned(cpu_to_le64((u64)(val)), (u64 *)((u8 *)(buf) + (pos)))
 
 /* where to find the base of the SMB packet proper */
-#define smb_base(buf) ((__u8 *)(((__u8 *)(buf))+4))
-
-#include <linux/vmalloc.h>
+#define smb_base(buf) ((u8 *)(((u8 *)(buf))+4))
 
 #ifdef DEBUG_SMB_MALLOC
 
@@ -70,7 +78,6 @@
 /*
  * Flags for the in-memory inode
  */
-#define SMB_F_CACHEVALID	0x01	/* directory cache valid */
 #define SMB_F_LOCALWRITE	0x02	/* file modified locally */
 
 
@@ -89,8 +96,54 @@
 #define SMB_CAP_LARGE_READX      0x4000
 
 
-/* linux/fs/smbfs/mmap.c */
-int smb_mmap(struct file *, struct vm_area_struct *);
+/*
+ * This is the time we allow an inode, dentry or dir cache to live. It is bad
+ * for performance to have shorter ttl on an inode than on the cache. It can
+ * cause refresh on each inode for a dir listing ... one-by-one
+ */
+#define SMB_MAX_AGE(server) (((server)->mnt->ttl * HZ) / 1000)
+
+static inline void
+smb_age_dentry(struct smb_sb_info *server, struct dentry *dentry)
+{
+	dentry->d_time = jiffies - SMB_MAX_AGE(server);
+}
+
+struct smb_cache_head {
+	time_t		mtime;	/* unused */
+	unsigned long	time;	/* cache age */
+	unsigned long	end;	/* last valid fpos in cache */
+	int		eof;
+};
+
+#define SMB_DIRCACHE_SIZE	((int)(PAGE_CACHE_SIZE/sizeof(struct dentry *)))
+union smb_dir_cache {
+	struct smb_cache_head   head;
+	struct dentry           *dentry[SMB_DIRCACHE_SIZE];
+};
+
+#define SMB_FIRSTCACHE_SIZE	((int)((SMB_DIRCACHE_SIZE * \
+	sizeof(struct dentry *) - sizeof(struct smb_cache_head)) / \
+	sizeof(struct dentry *)))
+
+#define SMB_DIRCACHE_START      (SMB_DIRCACHE_SIZE - SMB_FIRSTCACHE_SIZE)
+
+struct smb_cache_control {
+	struct  smb_cache_head		head;
+	struct  page			*page;
+	union   smb_dir_cache		*cache;
+	unsigned long			fpos, ofs;
+	int				filled, valid, idx;
+};
+
+static inline int
+smb_is_open(struct inode *i)
+{
+	return (i->u.smbfs_i.open == SMB_SERVER(i)->generation);
+}
+
+
+/* FIXME! the prototype list is probably not correct. Automate? */
 
 /* linux/fs/smbfs/file.c */
 extern struct inode_operations smb_file_inode_operations;
@@ -100,6 +153,7 @@
 /* linux/fs/smbfs/dir.c */
 extern struct inode_operations smb_dir_inode_operations;
 extern struct file_operations smb_dir_operations;
+void smb_new_dentry(struct dentry *dentry);
 void smb_renew_times(struct dentry *);
 
 /* linux/fs/smbfs/ioctl.c */
@@ -108,16 +162,15 @@
 /* linux/fs/smbfs/inode.c */
 struct super_block *smb_read_super(struct super_block *, void *, int);
 void smb_get_inode_attr(struct inode *, struct smb_fattr *);
+void smb_set_inode_attr(struct inode *, struct smb_fattr *);
 void smb_invalidate_inodes(struct smb_sb_info *);
 int  smb_revalidate_inode(struct dentry *);
 int  smb_notify_change(struct dentry *, struct iattr *);
-unsigned long smb_invent_inos(unsigned long);
 struct inode *smb_iget(struct super_block *, struct smb_fattr *);
 
 /* linux/fs/smbfs/proc.c */
 int smb_setcodepage(struct smb_sb_info *server, struct smb_nls_codepage *cp);
 __u32 smb_len(unsigned char *);
-__u8 *smb_encode_smb_length(__u8 *, __u32);
 __u8 *smb_setup_header(struct smb_sb_info *, __u8, __u16, __u16);
 int smb_get_rsize(struct smb_sb_info *);
 int smb_get_wsize(struct smb_sb_info *);
@@ -133,32 +186,21 @@
 int smb_proc_mkdir(struct dentry *);
 int smb_proc_rmdir(struct dentry *);
 int smb_proc_unlink(struct dentry *);
-int smb_proc_readdir(struct dentry *, int, void *);
+int smb_proc_readdir(struct file *filp, void *dirent, filldir_t filldir,
+		     struct smb_cache_control *ctl);
 int smb_proc_getattr(struct dentry *, struct smb_fattr *);
 int smb_proc_setattr(struct dentry *, struct smb_fattr *);
 int smb_proc_settime(struct dentry *, struct smb_fattr *);
 int smb_proc_dskattr(struct super_block *, struct statfs *);
-int smb_proc_reconnect(struct smb_sb_info *);
-int smb_proc_connect(struct smb_sb_info *);
 int smb_proc_disconnect(struct smb_sb_info *);
 int smb_proc_trunc(struct smb_sb_info *, __u16, __u32);
 void smb_init_root_dirent(struct smb_sb_info *, struct smb_fattr *);
 
-static inline int
-smb_is_open(struct inode *i)
-{
-	return (i->u.smbfs_i.open == SMB_SERVER(i)->generation);
-}
-
 /* linux/fs/smbfs/sock.c */
 int smb_round_length(int);
 int smb_valid_socket(struct inode *);
 void smb_close_socket(struct smb_sb_info *);
-int smb_release(struct smb_sb_info *server);
-int smb_connect(struct smb_sb_info *server);
 int smb_request(struct smb_sb_info *server);
-int smb_request_read_raw(struct smb_sb_info *, unsigned char *, int);
-int smb_request_write_raw(struct smb_sb_info *, unsigned const char *, int);
 int smb_catch_keepalive(struct smb_sb_info *server);
 int smb_dont_catch_keepalive(struct smb_sb_info *server);
 int smb_trans2_request(struct smb_sb_info *server, __u16 trans2_command,
@@ -169,69 +211,14 @@
 
 /* fs/smbfs/cache.c */
 
-/*
- * The cache index describes the pages mapped starting
- * at offset PAGE_SIZE.  We keep only a minimal amount
- * of information here.
- */
-struct cache_index {
-	unsigned short num_entries;
-	unsigned short space;
-	struct cache_block * block;
-};
-
-#define NINDEX (PAGE_SIZE-64)/sizeof(struct cache_index)
-/*
- * The cache head is mapped as the page at offset 0.
- */
-struct cache_head {
-	int	valid;
-	int	status;		/* error code or 0 */
-	int	entries;	/* total entries */
-	int	pages;		/* number of data pages */
-	int	idx;		/* index of current data page */
-	struct cache_index index[NINDEX];
-};
-
-/*
- * An array of cache_entry structures holds information
- * for each object in the cache_block.
- */
-struct cache_entry {
-	ino_t ino;
-	unsigned short namelen;
-	unsigned short offset;
-};
-
-/*
- * The cache blocks hold the actual data.  The entry table grows up
- * while the names grow down, and we have space until they meet.
- */
-struct cache_block {
-	union {
-		struct cache_entry table[1];
-		char	names[PAGE_SIZE];
-	} cb_data;
-};
-
-/*
- * To return an entry, we can pass a reference to the
- * name instead of having to copy it.
- */
-struct cache_dirent {
-	ino_t ino;
-	unsigned long pos;
-	int len;
-	char * name;
-};
+void smb_invalid_dir_cache(struct inode * dir);
+void smb_invalidate_dircache_entries(struct dentry *parent);
+struct dentry * smb_dget_fpos(struct dentry *dentry, struct dentry *parent, 
+			      unsigned long fpos);
+int smb_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+		   struct smb_cache_control *ctrl, struct qstr *qname,
+		   struct smb_fattr *entry);
 
-struct cache_head * smb_get_dircache(struct dentry *);
-void smb_init_dircache(struct cache_head *);
-void smb_free_dircache(struct cache_head *);
-int  smb_refill_dircache(struct cache_head *, struct dentry *);
-void smb_add_to_cache(struct cache_head *, struct cache_dirent *, off_t);
-int  smb_find_in_cache(struct cache_head *, off_t, struct cache_dirent *);
-void smb_invalid_dir_cache(struct inode *);
 
 #endif /* __KERNEL__ */
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/smb_fs_i.h linux/include/linux/smb_fs_i.h
--- v2.4.1/linux/include/linux/smb_fs_i.h	Thu Jan  4 14:50:46 2001
+++ linux/include/linux/smb_fs_i.h	Wed Feb 21 16:09:56 2001
@@ -26,7 +26,7 @@
 	__u16 attr;		/* Attribute fields, DOS value */
 
 	__u16 access;		/* Access mode */
-	__u16 cache_valid;	/* dircache valid? */
+	__u16 flags;		/* status flags */
 	unsigned long oldmtime;	/* last time refreshed */
 	unsigned long closed;	/* timestamp when closed */
 	unsigned openers;	/* number of fileid users */
diff -u --recursive --new-file v2.4.1/linux/include/linux/smb_mount.h linux/include/linux/smb_mount.h
--- v2.4.1/linux/include/linux/smb_mount.h	Mon Dec 11 13:26:20 2000
+++ linux/include/linux/smb_mount.h	Fri Feb 16 16:03:24 2001
@@ -50,6 +50,9 @@
 
 	u32 flags;
 
+        /* maximum age in jiffies (inode, dentry and dircache) */
+	int ttl;
+
 	struct smb_nls_codepage codepage;
 };
 
diff -u --recursive --new-file v2.4.1/linux/include/linux/telephony.h linux/include/linux/telephony.h
--- v2.4.1/linux/include/linux/telephony.h	Sat Dec 30 18:16:13 2000
+++ linux/include/linux/telephony.h	Sun Feb  4 10:05:29 2001
@@ -43,6 +43,11 @@
  *  the telephony products they support under Linux)
  *
  *****************************************************************************/
+#define QTI_PHONEJACK		100
+#define QTI_LINEJACK		300
+#define QTI_PHONEJACK_LITE	400
+#define QTI_PHONEJACK_PCI	500
+#define QTI_PHONECARD		600
 
 /******************************************************************************
 *
@@ -91,7 +96,7 @@
         int namelen;
         char name[80];
 } PHONE_CID;
-
+ 
 #define PHONE_RING			_IO  ('q', 0x83)
 #define PHONE_HOOKSTATE			_IO  ('q', 0x84)
 #define PHONE_MAXRINGS			_IOW ('q', 0x85, char)
diff -u --recursive --new-file v2.4.1/linux/include/linux/wait.h linux/include/linux/wait.h
--- v2.4.1/linux/include/linux/wait.h	Thu Jan  4 14:50:46 2001
+++ linux/include/linux/wait.h	Wed Feb 21 16:09:57 2001
@@ -19,30 +19,10 @@
 #include <asm/processor.h>
 
 /*
- * Temporary debugging help until all code is converted to the new
- * waitqueue usage.
+ * Debug control.  Slow but useful.
  */
 #define WAITQUEUE_DEBUG 0
 
-#if WAITQUEUE_DEBUG
-extern int printk(const char *fmt, ...);
-#define WQ_BUG() do { \
-	printk("wq bug, forcing oops.\n"); \
-	BUG(); \
-} while (0)
-
-#define CHECK_MAGIC(x) if (x != (long)&(x)) \
-	{ printk("bad magic %lx (should be %lx), ", (long)x, (long)&(x)); WQ_BUG(); }
-
-#define CHECK_MAGIC_WQHEAD(x) do { \
-	if (x->__magic != (long)&(x->__magic)) { \
-		printk("bad magic %lx (should be %lx, creator %lx), ", \
-			x->__magic, (long)&(x->__magic), x->__creator); \
-		WQ_BUG(); \
-	} \
-} while (0)
-#endif
-
 struct __wait_queue {
 	unsigned int flags;
 #define WQ_FLAG_EXCLUSIVE	0x01
@@ -99,24 +79,70 @@
 };
 typedef struct __wait_queue_head wait_queue_head_t;
 
+
+/*
+ * Debugging macros.  We eschew `do { } while (0)' because gcc can generate
+ * spurious .aligns.
+ */
+#if WAITQUEUE_DEBUG
+#define WQ_BUG()	BUG()
+#define CHECK_MAGIC(x)							\
+	do {									\
+		if ((x) != (long)&(x)) {					\
+			printk("bad magic %lx (should be %lx), ",		\
+				(long)x, (long)&(x));				\
+			WQ_BUG();						\
+		}								\
+	} while (0)
+#define CHECK_MAGIC_WQHEAD(x)							\
+	do {									\
+		if ((x)->__magic != (long)&((x)->__magic)) {			\
+			printk("bad magic %lx (should be %lx, creator %lx), ",	\
+			(x)->__magic, (long)&((x)->__magic), (x)->__creator);	\
+			WQ_BUG();						\
+		}								\
+	} while (0)
+#define WQ_CHECK_LIST_HEAD(list) 						\
+	do {									\
+		if (!list->next || !list->prev)					\
+			WQ_BUG();						\
+	} while(0)
+#define WQ_NOTE_WAKER(tsk)							\
+	do {									\
+		tsk->__waker = (long)__builtin_return_address(0);		\
+	} while (0)
+#else
+#define WQ_BUG()
+#define CHECK_MAGIC(x)
+#define CHECK_MAGIC_WQHEAD(x)
+#define WQ_CHECK_LIST_HEAD(list)
+#define WQ_NOTE_WAKER(tsk)
+#endif
+
+/*
+ * Macros for declaration and initialisaton of the datatypes
+ */
+
 #if WAITQUEUE_DEBUG
-# define __WAITQUEUE_DEBUG_INIT(name) \
-		, (long)&(name).__magic, 0
-# define __WAITQUEUE_HEAD_DEBUG_INIT(name) \
-		, (long)&(name).__magic, (long)&(name).__magic
+# define __WAITQUEUE_DEBUG_INIT(name) (long)&(name).__magic, 0
+# define __WAITQUEUE_HEAD_DEBUG_INIT(name) (long)&(name).__magic, (long)&(name).__magic
 #else
 # define __WAITQUEUE_DEBUG_INIT(name)
 # define __WAITQUEUE_HEAD_DEBUG_INIT(name)
 #endif
 
-#define __WAITQUEUE_INITIALIZER(name,task) \
-	{ 0x0, task, { NULL, NULL } __WAITQUEUE_DEBUG_INIT(name)}
-#define DECLARE_WAITQUEUE(name,task) \
-	wait_queue_t name = __WAITQUEUE_INITIALIZER(name,task)
-
-#define __WAIT_QUEUE_HEAD_INITIALIZER(name) \
-{ WAITQUEUE_RW_LOCK_UNLOCKED, { &(name).task_list, &(name).task_list } \
-		__WAITQUEUE_HEAD_DEBUG_INIT(name)}
+#define __WAITQUEUE_INITIALIZER(name, tsk) {				\
+	task:		tsk,						\
+	task_list:	{ NULL, NULL },					\
+			 __WAITQUEUE_DEBUG_INIT(name)}
+
+#define DECLARE_WAITQUEUE(name, tsk)					\
+	wait_queue_t name = __WAITQUEUE_INITIALIZER(name, tsk)
+
+#define __WAIT_QUEUE_HEAD_INITIALIZER(name) {				\
+	lock:		WAITQUEUE_RW_LOCK_UNLOCKED,			\
+	task_list:	{ &(name).task_list, &(name).task_list },	\
+			__WAITQUEUE_HEAD_DEBUG_INIT(name)}
 
 #define DECLARE_WAIT_QUEUE_HEAD(name) \
 	wait_queue_head_t name = __WAIT_QUEUE_HEAD_INITIALIZER(name)
@@ -135,8 +161,7 @@
 #endif
 }
 
-static inline void init_waitqueue_entry(wait_queue_t *q,
-				 struct task_struct *p)
+static inline void init_waitqueue_entry(wait_queue_t *q, struct task_struct *p)
 {
 #if WAITQUEUE_DEBUG
 	if (!q || !p)
diff -u --recursive --new-file v2.4.1/linux/include/math-emu/op-2.h linux/include/math-emu/op-2.h
--- v2.4.1/linux/include/math-emu/op-2.h	Thu Dec  2 15:28:54 1999
+++ linux/include/math-emu/op-2.h	Mon Feb 19 11:36:34 2001
@@ -79,7 +79,7 @@
     else								\
       {									\
 	X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) |			\
-		  (((X##_f1 << (sz - (N))) | X##_f0) != 0));		\
+		(((X##_f1 << (2*_FP_W_TYPE_SIZE - (N))) | X##_f0) != 0)); \
 	X##_f1 = 0;							\
       }									\
   } while (0)
diff -u --recursive --new-file v2.4.1/linux/include/net/ip_fib.h linux/include/net/ip_fib.h
--- v2.4.1/linux/include/net/ip_fib.h	Mon Dec 11 13:30:49 2000
+++ linux/include/net/ip_fib.h	Fri Feb  9 11:34:13 2001
@@ -276,4 +276,4 @@
 }
 
 
-#endif  _NET_FIB_H
+#endif  /* _NET_FIB_H */
diff -u --recursive --new-file v2.4.1/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.4.1/linux/include/net/irda/irda.h	Thu Jan  4 14:51:21 2001
+++ linux/include/net/irda/irda.h	Wed Feb 21 16:10:24 2001
@@ -177,9 +177,10 @@
  */
 struct irda_skb_cb {
 	magic_t magic;       /* Be sure that we can trust the information */
-	__u32   speed;       /* The Speed this frame should be sent with */
+	__u32   next_speed;  /* The Speed to be set *after* this frame */
 	__u16   mtt;         /* Minimum turn around time */
 	__u16   xbofs;       /* Number of xbofs required, used by SIR mode */
+	__u16   next_xbofs;  /* Number of xbofs required *after* this frame */
 	void    *context;    /* May be used by drivers */
 	void    (*destructor)(struct sk_buff *skb); /* Used for flow control */
 	__u16   xbofs_delay; /* Number of xbofs used for generating the mtt */
diff -u --recursive --new-file v2.4.1/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.4.1/linux/include/net/irda/irda_device.h	Thu Jan  4 14:50:45 2001
+++ linux/include/net/irda/irda_device.h	Wed Feb 21 16:09:52 2001
@@ -218,29 +218,54 @@
 #endif
 
 /*
- * Function irda_get_speed (skb)
+ * Function irda_get_next_speed (skb)
  *
- *    Extact the speed this frame should be sent out with from the skb
+ *    Extract the speed that should be set *after* this frame from the skb
  *
+ * Note : return -1 for user space frames
  */
-#define irda_get_speed(skb) (	                                        \
+#define irda_get_next_speed(skb) (	                                        \
 	(((struct irda_skb_cb*) skb->cb)->magic == LAP_MAGIC) ? 	\
-                  ((struct irda_skb_cb *)(skb->cb))->speed : 9600 	\
+                  ((struct irda_skb_cb *)(skb->cb))->next_speed : -1 	\
 )
 
 #if 0
-extern inline __u32 irda_get_speed(struct sk_buff *skb)
+extern inline __u32 irda_get_next_speed(struct sk_buff *skb)
 {
 	__u32 speed;
 
 	if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC)
-		speed = 9600;
+		speed = -1;
 	else
-		speed = ((struct irda_skb_cb *)(skb->cb))->speed;
+		speed = ((struct irda_skb_cb *)(skb->cb))->next_speed;
 
 	return speed;
 }
 #endif
+
+/*
+ * Function irda_get_next_xbofs (skb)
+ *
+ *    Extract the xbofs that should be set for this frame from the skb
+ *
+ * Note : default to 10 for user space frames
+ */
+#define irda_get_xbofs(skb) (	                                        \
+	(((struct irda_skb_cb*) skb->cb)->magic == LAP_MAGIC) ? 	\
+                  ((struct irda_skb_cb *)(skb->cb))->xbofs : 10 	\
+)
+
+/*
+ * Function irda_get_next_xbofs (skb)
+ *
+ *    Extract the xbofs that should be set *after* this frame from the skb
+ *
+ * Note : return -1 for user space frames
+ */
+#define irda_get_next_xbofs(skb) (	                                        \
+	(((struct irda_skb_cb*) skb->cb)->magic == LAP_MAGIC) ? 	\
+                  ((struct irda_skb_cb *)(skb->cb))->next_xbofs : -1 	\
+)
 
 #endif /* IRDA_DEVICE_H */
 
diff -u --recursive --new-file v2.4.1/linux/include/net/irda/irlap.h linux/include/net/irda/irlap.h
--- v2.4.1/linux/include/net/irda/irlap.h	Thu Jan  4 14:50:45 2001
+++ linux/include/net/irda/irlap.h	Wed Feb 21 16:09:52 2001
@@ -168,7 +168,7 @@
 	hashbin_t   *discovery_log;
  	discovery_t *discovery_cmd;
 
-	__u32 speed; 
+	__u32 speed;		/* Link speed */
 
 	struct qos_info  qos_tx;   /* QoS requested by peer */
 	struct qos_info  qos_rx;   /* QoS requested by self */
@@ -179,6 +179,7 @@
 	int    mtt_required;  /* Minumum turnaround time required */
 	int    xbofs_delay;   /* Nr of XBOF's used to MTT */
 	int    bofs_count;    /* Negotiated extra BOFs */
+	int    next_bofs;     /* Negotiated extra BOFs after next frame */
 
 #ifdef CONFIG_IRDA_COMPRESSION
 	struct irda_compressor compressor;
@@ -237,7 +238,7 @@
 
 void irlap_init_qos_capabilities(struct irlap_cb *, struct qos_info *);
 void irlap_apply_default_connection_parameters(struct irlap_cb *self);
-void irlap_apply_connection_parameters(struct irlap_cb *self);
+void irlap_apply_connection_parameters(struct irlap_cb *self, int now);
 void irlap_set_local_busy(struct irlap_cb *self, int status);
 
 #define IRLAP_GET_HEADER_SIZE(self) 2 /* Will be different when we get VFIR */
diff -u --recursive --new-file v2.4.1/linux/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h
--- v2.4.1/linux/include/net/irda/irlap_frame.h	Thu Jan  4 14:50:45 2001
+++ linux/include/net/irda/irlap_frame.h	Wed Feb 21 16:09:52 2001
@@ -110,6 +110,7 @@
 	__u8  ncaddr;
 } PACK;
 
+void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb);
 void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s, 
 				    __u8 command, discovery_t *discovery);
 void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *);
diff -u --recursive --new-file v2.4.1/linux/include/net/irda/qos.h linux/include/net/irda/qos.h
--- v2.4.1/linux/include/net/irda/qos.h	Thu Jan  4 14:51:20 2001
+++ linux/include/net/irda/qos.h	Wed Feb 21 16:10:20 2001
@@ -100,10 +100,19 @@
 
 __u32 irlap_max_line_capacity(__u32 speed, __u32 max_turn_time);
 __u32 irlap_requested_line_capacity(struct qos_info *qos);
-__u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time);
 
 int msb_index(__u16 byte);
 void irda_qos_bits_to_value(struct qos_info *qos);
+
+/* So simple, how could we not inline those two ?
+ * Note : one byte is 10 bits if you include start and stop bits
+ * Jean II */
+#define irlap_min_turn_time_in_bytes(speed, min_turn_time) (	\
+	speed * min_turn_time / 10000000			\
+)
+#define irlap_xbofs_in_usec(speed, xbofs) (			\
+	xbofs * 10000000 / speed				\
+)
 
 #endif
 
diff -u --recursive --new-file v2.4.1/linux/include/net/scm.h linux/include/net/scm.h
--- v2.4.1/linux/include/net/scm.h	Tue Oct 27 09:57:19 1998
+++ linux/include/net/scm.h	Fri Feb 16 16:02:37 2001
@@ -63,5 +63,5 @@
 }
 
 
-#endif __LINUX_NET_SCM_H
+#endif /* __LINUX_NET_SCM_H */
 
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/bulkmem.h linux/include/pcmcia/bulkmem.h
--- v2.4.1/linux/include/pcmcia/bulkmem.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/bulkmem.h	Fri Feb 16 16:02:37 2001
@@ -18,7 +18,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/bus_ops.h linux/include/pcmcia/bus_ops.h
--- v2.4.1/linux/include/pcmcia/bus_ops.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/bus_ops.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/ciscode.h linux/include/pcmcia/ciscode.h
--- v2.4.1/linux/include/pcmcia/ciscode.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/ciscode.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/cisreg.h linux/include/pcmcia/cisreg.h
--- v2.4.1/linux/include/pcmcia/cisreg.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/cisreg.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/cistpl.h linux/include/pcmcia/cistpl.h
--- v2.4.1/linux/include/pcmcia/cistpl.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/cistpl.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/cs.h linux/include/pcmcia/cs.h
--- v2.4.1/linux/include/pcmcia/cs.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/cs.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/cs_types.h linux/include/pcmcia/cs_types.h
--- v2.4.1/linux/include/pcmcia/cs_types.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/cs_types.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/driver_ops.h linux/include/pcmcia/driver_ops.h
--- v2.4.1/linux/include/pcmcia/driver_ops.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/driver_ops.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/ds.h linux/include/pcmcia/ds.h
--- v2.4.1/linux/include/pcmcia/ds.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/ds.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/ftl.h linux/include/pcmcia/ftl.h
--- v2.4.1/linux/include/pcmcia/ftl.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/ftl.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/mem_op.h linux/include/pcmcia/mem_op.h
--- v2.4.1/linux/include/pcmcia/mem_op.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/mem_op.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/memory.h linux/include/pcmcia/memory.h
--- v2.4.1/linux/include/pcmcia/memory.h	Sat Sep  2 00:13:49 2000
+++ linux/include/pcmcia/memory.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/include/pcmcia/ss.h linux/include/pcmcia/ss.h
--- v2.4.1/linux/include/pcmcia/ss.h	Fri Sep 15 16:31:09 2000
+++ linux/include/pcmcia/ss.h	Fri Feb 16 16:02:37 2001
@@ -16,7 +16,7 @@
  * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
  *
  * Alternatively, the contents of this file may be used under the
- * terms of the GNU Public License version 2 (the "GPL"), in which
+ * terms of the GNU General Public License version 2 (the "GPL"), in which
  * case the provisions of the GPL are applicable instead of the
  * above.  If you wish to allow the use of your version of this file
  * only under the terms of the GPL and not to allow others to use
diff -u --recursive --new-file v2.4.1/linux/ipc/msg.c linux/ipc/msg.c
--- v2.4.1/linux/ipc/msg.c	Tue Jan 11 21:49:26 2000
+++ linux/ipc/msg.c	Mon Feb 19 10:18:18 2001
@@ -16,7 +16,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/msg.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
@@ -473,7 +473,7 @@
 		int success_return;
 		if (!buf)
 			return -EFAULT;
-		if(cmd == MSG_STAT && msqid > msg_ids.size)
+		if(cmd == MSG_STAT && msqid >= msg_ids.size)
 			return -EINVAL;
 
 		memset(&tbuf,0,sizeof(tbuf));
diff -u --recursive --new-file v2.4.1/linux/ipc/sem.c linux/ipc/sem.c
--- v2.4.1/linux/ipc/sem.c	Thu Oct 12 14:19:32 2000
+++ linux/ipc/sem.c	Mon Feb 19 10:18:18 2001
@@ -56,7 +56,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <linux/proc_fs.h>
@@ -467,7 +467,7 @@
 		struct semid64_ds tbuf;
 		int id;
 
-		if(semid > sem_ids.size)
+		if(semid >= sem_ids.size)
 			return -EINVAL;
 
 		memset(&tbuf,0,sizeof(tbuf));
@@ -922,7 +922,7 @@
 
 		tmp = sem_lock(semid);
 		if(tmp==NULL) {
-			if(queue.status != -EIDRM)
+			if(queue.prev != NULL)
 				BUG();
 			current->semsleeping = NULL;
 			error = -EIDRM;
diff -u --recursive --new-file v2.4.1/linux/ipc/shm.c linux/ipc/shm.c
--- v2.4.1/linux/ipc/shm.c	Sat Feb  3 19:51:32 2001
+++ linux/ipc/shm.c	Fri Feb  9 11:29:44 2001
@@ -16,7 +16,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/init.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/ipc/util.c linux/ipc/util.c
--- v2.4.1/linux/ipc/util.c	Fri Dec 29 14:07:24 2000
+++ linux/ipc/util.c	Mon Feb 19 10:18:18 2001
@@ -17,7 +17,7 @@
 #include <linux/msg.h>
 #include <linux/smp_lock.h>
 #include <linux/vmalloc.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/highuid.h>
 
 #if defined(CONFIG_SYSVIPC)
@@ -185,7 +185,7 @@
 {
 	struct kern_ipc_perm* p;
 	int lid = id % SEQ_MULTIPLIER;
-	if(lid > ids->size)
+	if(lid >= ids->size)
 		BUG();
 	p = ids->entries[lid].p;
 	ids->entries[lid].p = NULL;
diff -u --recursive --new-file v2.4.1/linux/ipc/util.h linux/ipc/util.h
--- v2.4.1/linux/ipc/util.h	Thu Jun 22 07:09:45 2000
+++ linux/ipc/util.h	Mon Feb 19 10:18:18 2001
@@ -54,7 +54,7 @@
 {
 	struct kern_ipc_perm* out;
 	int lid = id % SEQ_MULTIPLIER;
-	if(lid > ids->size)
+	if(lid >= ids->size)
 		return NULL;
 
 	out = ids->entries[lid].p;
@@ -69,7 +69,7 @@
 {
 	struct kern_ipc_perm* out;
 	int lid = id % SEQ_MULTIPLIER;
-	if(lid > ids->size)
+	if(lid >= ids->size)
 		return NULL;
 
 	spin_lock(&ids->ary);
diff -u --recursive --new-file v2.4.1/linux/kernel/acct.c linux/kernel/acct.c
--- v2.4.1/linux/kernel/acct.c	Sat Jul  8 19:43:35 2000
+++ linux/kernel/acct.c	Fri Feb  9 11:29:44 2001
@@ -53,6 +53,7 @@
 #include <linux/acct.h>
 #include <linux/smp_lock.h>
 #include <linux/file.h>
+#include <linux/tty.h>
 
 #include <asm/uaccess.h>
 
diff -u --recursive --new-file v2.4.1/linux/kernel/dma.c linux/kernel/dma.c
--- v2.4.1/linux/kernel/dma.c	Tue Dec  5 12:29:39 2000
+++ linux/kernel/dma.c	Tue Feb 13 14:14:06 2001
@@ -116,9 +116,8 @@
 	return -EINVAL;
 }
 
-int free_dma(unsigned int dmanr)
+void free_dma(unsigned int dmanr)
 {
-	return -EINVAL;
 }
 
 int get_dma_list(char *buf)
diff -u --recursive --new-file v2.4.1/linux/kernel/exit.c linux/kernel/exit.c
--- v2.4.1/linux/kernel/exit.c	Thu Jan  4 01:00:35 2001
+++ linux/kernel/exit.c	Fri Feb  9 11:29:44 2001
@@ -5,10 +5,11 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/module.h>
+#include <linux/tty.h>
 #ifdef CONFIG_BSD_PROCESS_ACCT
 #include <linux/acct.h>
 #endif
diff -u --recursive --new-file v2.4.1/linux/kernel/fork.c linux/kernel/fork.c
--- v2.4.1/linux/kernel/fork.c	Sat Feb  3 19:51:32 2001
+++ linux/kernel/fork.c	Fri Feb  9 11:29:44 2001
@@ -12,7 +12,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/unistd.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.4.1/linux/kernel/ksyms.c	Sat Feb  3 19:51:32 2001
+++ linux/kernel/ksyms.c	Fri Feb  9 11:29:44 2001
@@ -10,7 +10,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/blkdev.h>
 #include <linux/cdrom.h>
@@ -45,6 +45,7 @@
 #include <linux/highuid.h>
 #include <linux/brlock.h>
 #include <linux/fs.h>
+#include <linux/tty.h>
 
 #if defined(CONFIG_PROC_FS)
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/kernel/module.c linux/kernel/module.c
--- v2.4.1/linux/kernel/module.c	Mon Nov 27 17:38:07 2000
+++ linux/kernel/module.c	Fri Feb 16 16:02:37 2001
@@ -23,6 +23,7 @@
  * Fix sys_init_module race, Andrew Morton <andrewm@uow.edu.au> Oct 2000
  *     http://www.uwsg.iu.edu/hypermail/linux/kernel/0008.3/0379.html
  * Replace xxx_module_symbol with inter_module_xxx.  Keith Owens <kaos@ocs.com.au> Oct 2000
+ * Add a module list lock for kernel fault race fixing. Alan Cox <alan@redhat.com>
  *
  * This source is covered by the GNU GPL, the same as all kernel sources.
  */
@@ -65,6 +66,17 @@
 static spinlock_t ime_lock = SPIN_LOCK_UNLOCKED;
 static int kmalloc_failed;
 
+/*
+ *	This lock prevents modifications that might race the kernel fault
+ *	fixups. It does not prevent reader walks that the modules code
+ *	does. The kernel lock does that.
+ *
+ *	Since vmalloc fault fixups occur in any context this lock is taken
+ *	irqsave at all times.
+ */
+ 
+spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
+
 /**
  * inter_module_register - register a new set of inter module data.
  * @im_name: an arbitrary string to identify the data, must be unique
@@ -283,6 +295,7 @@
 	char *name;
 	long namelen, error;
 	struct module *mod;
+	unsigned long flags;
 
 	if (!capable(CAP_SYS_MODULE))
 		return -EPERM;
@@ -306,14 +319,16 @@
 
 	memset(mod, 0, sizeof(*mod));
 	mod->size_of_struct = sizeof(*mod);
-	mod->next = module_list;
 	mod->name = (char *)(mod + 1);
 	mod->size = size;
 	memcpy((char*)(mod+1), name, namelen+1);
 
 	put_mod_name(name);
 
+	spin_lock_irqsave(&modlist_lock, flags);
+	mod->next = module_list;
 	module_list = mod;	/* link it in */
+	spin_unlock_irqrestore(&modlist_lock, flags);
 
 	error = (long) mod;
 	goto err0;
@@ -628,6 +643,7 @@
 	/* Do automatic reaping */
 restart:
 	something_changed = 0;
+	
 	for (mod = module_list; mod != &kernel_module; mod = next) {
 		next = mod->next;
 		spin_lock(&unload_lock);
@@ -651,10 +667,13 @@
 			spin_unlock(&unload_lock);
 		}
 	}
+	
 	if (something_changed)
 		goto restart;
+		
 	for (mod = module_list; mod != &kernel_module; mod = mod->next)
 		mod->flags &= ~MOD_JUST_FREED;
+	
 	error = 0;
 out:
 	unlock_kernel();
@@ -1018,6 +1037,7 @@
 {
 	struct module_ref *dep;
 	unsigned i;
+	unsigned long flags;
 
 	/* Let the module clean up.  */
 
@@ -1041,6 +1061,7 @@
 
 	/* And from the main module list.  */
 
+	spin_lock_irqsave(&modlist_lock, flags);
 	if (mod == module_list) {
 		module_list = mod->next;
 	} else {
@@ -1049,6 +1070,7 @@
 			continue;
 		p->next = mod->next;
 	}
+	spin_unlock_irqrestore(&modlist_lock, flags);
 
 	/* And free the memory.  */
 
diff -u --recursive --new-file v2.4.1/linux/kernel/printk.c linux/kernel/printk.c
--- v2.4.1/linux/kernel/printk.c	Sat Dec 30 18:16:13 2000
+++ linux/kernel/printk.c	Tue Feb 13 13:15:05 2001
@@ -15,6 +15,7 @@
  */
 
 #include <linux/mm.h>
+#include <linux/tty.h>
 #include <linux/tty_driver.h>
 #include <linux/smp_lock.h>
 #include <linux/console.h>
@@ -125,9 +126,8 @@
 	unsigned long i, j, limit, count;
 	int do_clear = 0;
 	char c;
-	int error = -EPERM;
+	int error = 0;
 
-	error = 0;
 	switch (type) {
 	case 0:		/* Close log */
 		break;
diff -u --recursive --new-file v2.4.1/linux/kernel/resource.c linux/kernel/resource.c
--- v2.4.1/linux/kernel/resource.c	Wed Nov  8 17:09:50 2000
+++ linux/kernel/resource.c	Fri Feb  9 11:29:44 2001
@@ -11,7 +11,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/init.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <asm/io.h>
 
diff -u --recursive --new-file v2.4.1/linux/kernel/sched.c linux/kernel/sched.c
--- v2.4.1/linux/kernel/sched.c	Sat Feb  3 19:51:32 2001
+++ linux/kernel/sched.c	Fri Feb  9 11:37:03 2001
@@ -326,9 +326,10 @@
  * "current->state = TASK_RUNNING" to mark yourself runnable
  * without the overhead of this.
  */
-inline void wake_up_process(struct task_struct * p)
+static inline int try_to_wake_up(struct task_struct * p, int synchronous)
 {
 	unsigned long flags;
+	int success = 0;
 
 	/*
 	 * We want the common case fall through straight, thus the goto.
@@ -338,25 +339,17 @@
 	if (task_on_runqueue(p))
 		goto out;
 	add_to_runqueue(p);
-	reschedule_idle(p);
+	if (!synchronous)
+		reschedule_idle(p);
+	success = 1;
 out:
 	spin_unlock_irqrestore(&runqueue_lock, flags);
+	return success;
 }
 
-static inline void wake_up_process_synchronous(struct task_struct * p)
+inline int wake_up_process(struct task_struct * p)
 {
-	unsigned long flags;
-
-	/*
-	 * We want the common case fall through straight, thus the goto.
-	 */
-	spin_lock_irqsave(&runqueue_lock, flags);
-	p->state = TASK_RUNNING;
-	if (task_on_runqueue(p))
-		goto out;
-	add_to_runqueue(p);
-out:
-	spin_unlock_irqrestore(&runqueue_lock, flags);
+	return try_to_wake_up(p, 0);
 }
 
 static void process_timeout(unsigned long __data)
@@ -689,64 +682,59 @@
 	return;
 }
 
+/*
+ * The core wakeup function.  Non-exclusive wakeups (nr_exclusive == 0) just wake everything
+ * up.  If it's an exclusive wakeup (nr_exclusive == small +ve number) then we wake all the
+ * non-exclusive tasks and one exclusive task.
+ *
+ * There are circumstances in which we can try to wake a task which has already
+ * started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns zero
+ * in this (rare) case, and we handle it by contonuing to scan the queue.
+ */
 static inline void __wake_up_common (wait_queue_head_t *q, unsigned int mode,
 			 	     int nr_exclusive, const int sync)
 {
 	struct list_head *tmp, *head;
 	struct task_struct *p;
-	unsigned long flags;
 
-	if (!q)
-		goto out;
-
-	wq_write_lock_irqsave(&q->lock, flags);
-
-#if WAITQUEUE_DEBUG
 	CHECK_MAGIC_WQHEAD(q);
-#endif
-
 	head = &q->task_list;
-#if WAITQUEUE_DEBUG
-        if (!head->next || !head->prev)
-                WQ_BUG();
-#endif
+	WQ_CHECK_LIST_HEAD(head);
 	tmp = head->next;
 	while (tmp != head) {
 		unsigned int state;
                 wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list);
 
 		tmp = tmp->next;
-
-#if WAITQUEUE_DEBUG
 		CHECK_MAGIC(curr->__magic);
-#endif
 		p = curr->task;
 		state = p->state;
 		if (state & mode) {
-#if WAITQUEUE_DEBUG
-			curr->__waker = (long)__builtin_return_address(0);
-#endif
-			if (sync)
-				wake_up_process_synchronous(p);
-			else
-				wake_up_process(p);
-			if ((curr->flags & WQ_FLAG_EXCLUSIVE) && !--nr_exclusive)
+			WQ_NOTE_WAKER(curr);
+			if (try_to_wake_up(p, sync) && curr->flags && !--nr_exclusive)
 				break;
 		}
 	}
-	wq_write_unlock_irqrestore(&q->lock, flags);
-out:
-	return;
 }
 
 void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr)
 {
-	__wake_up_common(q, mode, nr, 0);
+	if (q) {
+		unsigned long flags;
+		wq_read_lock_irqsave(&q->lock, flags);
+		__wake_up_common(q, mode, nr, 0);
+		wq_read_unlock_irqrestore(&q->lock, flags);
+	}
 }
 
 void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr)
 {
-	__wake_up_common(q, mode, nr, 1);
+	if (q) {
+		unsigned long flags;
+		wq_read_lock_irqsave(&q->lock, flags);
+		__wake_up_common(q, mode, nr, 1);
+		wq_read_unlock_irqrestore(&q->lock, flags);
+	}
 }
 
 #define	SLEEP_ON_VAR				\
@@ -1127,11 +1115,11 @@
 	else
 		printk("\n");
 
-#ifdef CONFIG_X86
-/* This is very useful, but only works on x86 right now */
+#if defined(CONFIG_X86) || defined(CONFIG_SPARC64)
+/* This is very useful, but only works on x86 and sparc64 right now */
 	{
-		extern void show_trace(unsigned long);
-		show_trace(p->thread.esp);
+		extern void show_trace_task(struct task_struct *tsk);
+		show_trace_task(p);
 	}
 #endif
 }
diff -u --recursive --new-file v2.4.1/linux/kernel/sysctl.c linux/kernel/sysctl.c
--- v2.4.1/linux/kernel/sysctl.c	Fri Dec 29 14:07:24 2000
+++ linux/kernel/sysctl.c	Fri Feb 16 16:02:37 2001
@@ -19,7 +19,7 @@
  */
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/sysctl.h>
 #include <linux/swapctl.h>
 #include <linux/proc_fs.h>
@@ -75,6 +75,14 @@
 extern char reboot_command [];
 extern int stop_a_enabled;
 #endif
+
+#ifdef CONFIG_ARCH_S390
+#ifdef CONFIG_IEEEFPU_EMULATION
+extern int sysctl_ieee_emulation_warnings;
+#endif
+extern int sysctl_userprocess_debug;
+#endif
+
 #ifdef __powerpc__
 extern unsigned long htab_reclaim_on, zero_paged_on, powersave_nap;
 int proc_dol2crvec(ctl_table *table, int write, struct file *filp,
@@ -130,9 +138,6 @@
 static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
 #endif
 
-extern int inodes_stat[];
-extern int dentry_stat[];
-
 /* The default sysctl tables: */
 
 static ctl_table root_table[] = {
@@ -236,6 +241,14 @@
 	{KERN_OVERFLOWGID, "overflowgid", &overflowgid, sizeof(int), 0644, NULL,
 	 &proc_dointvec_minmax, &sysctl_intvec, NULL,
 	 &minolduid, &maxolduid},
+#ifdef CONFIG_ARCH_S390
+#ifdef CONFIG_IEEEFPU_EMULATION
+	{KERN_IEEE_EMULATION_WARNINGS,"ieee_emulation_warnings",
+	 &sysctl_ieee_emulation_warnings,sizeof(int),0644,NULL,&proc_dointvec},
+#endif
+	{KERN_S390_USER_DEBUG_LOGGING,"userprocess_debug",
+	 &sysctl_userprocess_debug,sizeof(int),0644,NULL,&proc_dointvec},
+#endif
 	{0}
 };
 
@@ -321,7 +334,7 @@
 {
 	struct list_head *tmp;
 
-	if (nlen == 0 || nlen >= CTL_MAXNAME)
+	if (nlen <= 0 || nlen >= CTL_MAXNAME)
 		return -ENOTDIR;
 	if (oldval) {
 		int old_len;
@@ -426,7 +439,8 @@
 			void *oldval, size_t *oldlenp,
 			void *newval, size_t newlen, void **context)
 {
-	int op = 0, rc, len;
+	int op = 0, rc;
+	size_t len;
 
 	if (oldval)
 		op |= 004;
@@ -469,13 +483,82 @@
 	return 0;
 }
 
+/**
+ * register_sysctl_table - register a sysctl heirarchy
+ * @table: the top-level table structure
+ * @insert_at_head: whether the entry should be inserted in front or at the end
+ *
+ * Register a sysctl table heirarchy. @table should be a filled in ctl_table
+ * array. An entry with a ctl_name of 0 terminates the table. 
+ *
+ * The members of the &ctl_table structure are used as follows:
+ *
+ * ctl_name - This is the numeric sysctl value used by sysctl(2). The number
+ *            must be unique within that level of sysctl
+ *
+ * procname - the name of the sysctl file under /proc/sys. Set to %NULL to not
+ *            enter a sysctl file
+ *
+ * data - a pointer to data for use by proc_handler
+ *
+ * maxlen - the maximum size in bytes of the data
+ *
+ * mode - the file permissions for the /proc/sys file, and for sysctl(2)
+ *
+ * child - a pointer to the child sysctl table if this entry is a directory, or
+ *         %NULL.
+ *
+ * proc_handler - the text handler routine (described below)
+ *
+ * strategy - the strategy routine (described below)
+ *
+ * de - for internal use by the sysctl routines
+ *
+ * extra1, extra2 - extra pointers usable by the proc handler routines
+ *
+ * Leaf nodes in the sysctl tree will be represented by a single file
+ * under /proc; non-leaf nodes will be represented by directories.
+ *
+ * sysctl(2) can automatically manage read and write requests through
+ * the sysctl table.  The data and maxlen fields of the ctl_table
+ * struct enable minimal validation of the values being written to be
+ * performed, and the mode field allows minimal authentication.
+ *
+ * More sophisticated management can be enabled by the provision of a
+ * strategy routine with the table entry.  This will be called before
+ * any automatic read or write of the data is performed.
+ *
+ * The strategy routine may return
+ *
+ * < 0 - Error occurred (error is passed to user process)
+ *
+ * 0   - OK - proceed with automatic read or write.
+ *
+ * > 0 - OK - read or write has been done by the strategy routine, so
+ *       return immediately.
+ *
+ * There must be a proc_handler routine for any terminal nodes
+ * mirrored under /proc/sys (non-terminals are handled by a built-in
+ * directory handler).  Several default handlers are available to
+ * cover common cases -
+ *
+ * proc_dostring(), proc_dointvec(), proc_dointvec_jiffies(),
+ * proc_dointvec_minmax(), proc_doulongvec_ms_jiffies_minmax(),
+ * proc_doulongvec_minmax()
+ *
+ * It is the handler's job to read the input buffer from user memory
+ * and process it. The handler should return 0 on success.
+ *
+ * This routine returns %NULL on a failure to register, and a pointer
+ * to the table header on success.
+ */
 struct ctl_table_header *register_sysctl_table(ctl_table * table, 
 					       int insert_at_head)
 {
 	struct ctl_table_header *tmp;
 	tmp = kmalloc(sizeof(struct ctl_table_header), GFP_KERNEL);
 	if (!tmp)
-		return 0;
+		return NULL;
 	tmp->ctl_table = table;
 	INIT_LIST_HEAD(&tmp->ctl_entry);
 	if (insert_at_head)
@@ -488,8 +571,12 @@
 	return tmp;
 }
 
-/*
- * Unlink and free a ctl_table.
+/**
+ * unregister_sysctl_table - unregister a sysctl table heirarchy
+ * @header: the header returned from register_sysctl_table
+ *
+ * Unregisters the sysctl table and all children. proc entries may not
+ * actually be removed until they are no longer used by anyone.
  */
 void unregister_sysctl_table(struct ctl_table_header * header)
 {
@@ -633,10 +720,27 @@
 	return test_perm(inode->i_mode, op);
 }
 
+/**
+ * proc_dostring - read a string sysctl
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes a string from/to the user buffer. If the kernel
+ * buffer provided is not large enough to hold the string, the
+ * string is truncated. The copied string is %NULL-terminated.
+ * If the string is being read by the user process, it is copied
+ * and a newline '\n' is added. It is truncated if the buffer is
+ * not large enough.
+ *
+ * Returns 0 on success.
+ */
 int proc_dostring(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
 {
-	int len;
+	size_t len;
 	char *p, c;
 	
 	if (!table->data || !table->maxlen || !*lenp ||
@@ -712,7 +816,9 @@
 static int do_proc_dointvec(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp, int conv, int op)
 {
-	int *i, vleft, first=1, len, left, neg, val;
+	int *i, vleft, first=1, neg, val;
+	size_t left, len;
+	
 	#define TMPBUFLEN 20
 	char buf[TMPBUFLEN], *p;
 	
@@ -810,6 +916,19 @@
 	return 0;
 }
 
+/**
+ * proc_dointvec - read a vector of integers
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
+ * values from/to the user buffer, treated as an ASCII string. 
+ *
+ * Returns 0 on success.
+ */
 int proc_dointvec(ctl_table *table, int write, struct file *filp,
 		     void *buffer, size_t *lenp)
 {
@@ -830,10 +949,27 @@
 				(current->pid == 1) ? OP_SET : OP_AND);
 }
 
+/**
+ * proc_dointvec_minmax - read a vector of integers with min/max values
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
+ * values from/to the user buffer, treated as an ASCII string.
+ *
+ * This routine will ensure the values are within the range specified by
+ * table->extra1 (min) and table->extra2 (max).
+ *
+ * Returns 0 on success.
+ */
 int proc_dointvec_minmax(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
 {
-	int *i, *min, *max, vleft, first=1, len, left, neg, val;
+	int *i, *min, *max, vleft, first=1, neg, val;
+	size_t len, left;
 	#define TMPBUFLEN 20
 	char buf[TMPBUFLEN], *p;
 	
@@ -928,10 +1064,6 @@
 	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,
@@ -940,7 +1072,8 @@
 {
 #define TMPBUFLEN 20
 	unsigned long *i, *min, *max, val;
-	int vleft, first=1, len, left, neg;
+	int vleft, first=1, neg;
+	size_t len, left;
 	char buf[TMPBUFLEN], *p;
 	
 	if (!table->data || !table->maxlen || !*lenp ||
@@ -1037,12 +1170,45 @@
 #undef TMPBUFLEN
 }
 
+/**
+ * proc_doulongvec_minmax - read a vector of long integers with min/max values
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
+ * values from/to the user buffer, treated as an ASCII string.
+ *
+ * This routine will ensure the values are within the range specified by
+ * table->extra1 (min) and table->extra2 (max).
+ *
+ * Returns 0 on success.
+ */
 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);
 }
 
+/**
+ * proc_doulongvec_ms_jiffies_minmax - read a vector of millisecond values with min/max values
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned long) unsigned long
+ * values from/to the user buffer, treated as an ASCII string. The values
+ * are treated as milliseconds, and converted to jiffies when they are stored.
+ *
+ * This routine will ensure the values are within the range specified by
+ * table->extra1 (min) and table->extra2 (max).
+ *
+ * Returns 0 on success.
+ */
 int proc_doulongvec_ms_jiffies_minmax(ctl_table *table, int write,
 				      struct file *filp,
 				      void *buffer, size_t *lenp)
@@ -1052,7 +1218,21 @@
 }
 
 
-/* Like proc_dointvec, but converts seconds to jiffies */
+/**
+ * proc_dointvec_jiffies - read a vector of integers as seconds
+ * @table: the sysctl table
+ * @write: %TRUE if this is a write to the sysctl file
+ * @filp: the file structure
+ * @buffer: the user buffer
+ * @lenp: the size of the user buffer
+ *
+ * Reads/writes up to table->maxlen/sizeof(unsigned int) integer
+ * values from/to the user buffer, treated as an ASCII string. 
+ * The values read are assumed to be in seconds, and are converted into
+ * jiffies.
+ *
+ * Returns 0 on success.
+ */
 int proc_dointvec_jiffies(ctl_table *table, int write, struct file *filp,
 			  void *buffer, size_t *lenp)
 {
@@ -1123,7 +1303,7 @@
 		  void *oldval, size_t *oldlenp,
 		  void *newval, size_t newlen, void **context)
 {
-	int l, len;
+	size_t l, len;
 	
 	if (!table->data || !table->maxlen) 
 		return -ENOTDIR;
@@ -1166,7 +1346,8 @@
 		void *oldval, size_t *oldlenp,
 		void *newval, size_t newlen, void **context)
 {
-	int i, length, *vec, *min, *max;
+	int i, *vec, *min, *max;
+	size_t length;
 
 	if (newval && newlen) {
 		if (newlen % sizeof(int) != 0)
diff -u --recursive --new-file v2.4.1/linux/mm/filemap.c linux/mm/filemap.c
--- v2.4.1/linux/mm/filemap.c	Sat Feb  3 19:51:32 2001
+++ linux/mm/filemap.c	Fri Feb 16 16:06:17 2001
@@ -9,7 +9,7 @@
  * most "normal" filesystems (but you don't /have/ to use this:
  * the NFS filesystem used to do this differently, for example)
  */
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/shm.h>
 #include <linux/mman.h>
 #include <linux/locks.h>
@@ -19,7 +19,6 @@
 #include <linux/blkdev.h>
 #include <linux/file.h>
 #include <linux/swapctl.h>
-#include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/mm.h>
 
@@ -397,7 +396,7 @@
 	retval |= do_buffer_fdatasync(&inode->i_mapping->locked_pages, start_idx, end_idx, writeout_one_page);
 
 	/* now wait for locked buffers on pages from both clean and dirty lists */
-	retval |= do_buffer_fdatasync(&inode->i_mapping->dirty_pages, start_idx, end_idx, writeout_one_page);
+	retval |= do_buffer_fdatasync(&inode->i_mapping->dirty_pages, start_idx, end_idx, waitfor_one_page);
 	retval |= do_buffer_fdatasync(&inode->i_mapping->clean_pages, start_idx, end_idx, waitfor_one_page);
 	retval |= do_buffer_fdatasync(&inode->i_mapping->locked_pages, start_idx, end_idx, waitfor_one_page);
 
diff -u --recursive --new-file v2.4.1/linux/mm/memory.c linux/mm/memory.c
--- v2.4.1/linux/mm/memory.c	Sat Feb  3 19:51:32 2001
+++ linux/mm/memory.c	Tue Feb  6 22:49:21 2001
@@ -858,6 +858,8 @@
 		UnlockPage(old_page);
 		/* FallThrough */
 	case 1:
+		if (PageReserved(old_page))
+			break;
 		flush_cache_page(vma, address);
 		establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
 		spin_unlock(&mm->page_table_lock);
@@ -1200,6 +1202,7 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 
+	current->state = TASK_RUNNING;
 	pgd = pgd_offset(mm, address);
 	pmd = pmd_alloc(pgd, address);
 
diff -u --recursive --new-file v2.4.1/linux/mm/mmap.c linux/mm/mmap.c
--- v2.4.1/linux/mm/mmap.c	Sat Feb  3 19:51:32 2001
+++ linux/mm/mmap.c	Tue Feb  6 22:04:12 2001
@@ -12,6 +12,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/file.h>
+#include <linux/fs.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -63,6 +64,15 @@
 	free += atomic_read(&page_cache_size);
 	free += nr_free_pages();
 	free += nr_swap_pages;
+	/*
+	 * The code below doesn't account for free space in the inode
+	 * and dentry slab cache, slab cache fragmentation, inodes and
+	 * dentries which will become freeable under VM load, etc.
+	 * Lets just hope all these (complex) factors balance out...
+	 */
+	free += (dentry_stat.nr_unused * sizeof(struct dentry)) >> PAGE_SHIFT;
+	free += (inodes_stat.nr_unused * sizeof(struct inode)) >> PAGE_SHIFT;
+
 	return free > pages;
 }
 
diff -u --recursive --new-file v2.4.1/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.4.1/linux/mm/swapfile.c	Fri Dec 29 14:07:24 2000
+++ linux/mm/swapfile.c	Fri Feb  9 11:29:44 2001
@@ -5,7 +5,7 @@
  *  Swap reorganised 29.12.95, Stephen Tweedie
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/kernel_stat.h>
 #include <linux/swap.h>
diff -u --recursive --new-file v2.4.1/linux/mm/vmalloc.c linux/mm/vmalloc.c
--- v2.4.1/linux/mm/vmalloc.c	Sat Feb  3 19:51:32 2001
+++ linux/mm/vmalloc.c	Fri Feb  9 11:29:44 2001
@@ -6,7 +6,7 @@
  *  SMP-safe vmalloc/vfree/ioremap, Tigran Aivazian <tigran@veritas.com>, May 2000
  */
 
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h>
 #include <linux/spinlock.h>
 #include <linux/highmem.h>
diff -u --recursive --new-file v2.4.1/linux/net/802/cl2llc.c linux/net/802/cl2llc.c
--- v2.4.1/linux/net/802/cl2llc.c	Sat Nov 29 10:41:10 1997
+++ linux/net/802/cl2llc.c	Fri Feb  9 11:34:13 2001
@@ -28,7 +28,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/p8022.h>
@@ -96,7 +96,7 @@
 				else
 					llc_interpret_pseudo_code(lp, REJECT1, skb, NO_FRAME);
 				break;
-			default:
+			default:;
 		}
 		if(lp->llc_callbacks)
 		{
@@ -497,7 +497,7 @@
 				else
 					lp->f_flag = fr->i_hdr.i_pflag;
 				break;
-			default:
+			default:;
 		}
 		pc++;	
 	}
diff -u --recursive --new-file v2.4.1/linux/net/802/llc_macinit.c linux/net/802/llc_macinit.c
--- v2.4.1/linux/net/802/llc_macinit.c	Mon Oct 16 12:42:53 2000
+++ linux/net/802/llc_macinit.c	Fri Feb  9 11:34:13 2001
@@ -24,7 +24,7 @@
 #include <linux/module.h>
 #include <linux/version.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/unistd.h>
 #include <linux/string.h>
 #include <linux/netdevice.h>
@@ -125,7 +125,7 @@
 				free=0;
 				break;
 
-			default:
+			default:;
 				/*
 				 *	All other type 1 pdus ignored for now
 				 */
diff -u --recursive --new-file v2.4.1/linux/net/802/llc_sendpdu.c linux/net/802/llc_sendpdu.c
--- v2.4.1/linux/net/802/llc_sendpdu.c	Tue Feb 10 13:07:49 1998
+++ linux/net/802/llc_sendpdu.c	Fri Feb  9 11:29:44 2001
@@ -19,7 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/p8022.h>
diff -u --recursive --new-file v2.4.1/linux/net/Changes linux/net/Changes
--- v2.4.1/linux/net/Changes	Fri Feb 18 14:51:22 2000
+++ linux/net/Changes	Wed Dec 31 16:00:00 1969
@@ -1,44 +0,0 @@
---------------- Things That Need Doing Before 2.2 ------------------
-
-o	insw_and_csum
-
--------------------------- Bugs to fix ------------------------------
-
-o	Should unix domain connect never block ?
-o	Screend loadable firewall module
-o	Remove kernel RARP and replace with user mode daemon.
-o	Merge ARM half word trap fixes for ethernet headers
-o	Stop route addition to downed interfaces
-o	Make sure route add window functionality is back or documented
-	equivalences are clear
-o	Merge ATM 
-o	Merge IRDA
-
-Possible projects for victim^H^H^H^H^Holunteers
-
-9.	Implementing streams. Not as a blind slow SYS5.4 style copy but actually
-working out how to do it so it runs like greased lightning. Quite a big
-problem. [See the LiS project]
-
-11.	IP over SCSI. [worked on]
-
-14.	Bidirectional PLIP. Also PLIP for the newer style parallel ports.
-
-15.	802.2LLC and thus Netbeui sockets. Becoming less important since the
-rumour is microsoft are phasing out netbeui for netbios/IP. Microsoft have
-gone for netbios/funny-ipx-variant it seems in Win95, but TCP is selectable.
-
-17.	PPP multilink. Another nasty job.
-
-19.	IPv4 IP-AH and IP-ESP.
-
-20.	(userspace) GUI interface to the bandwidth allocators so mere
-	mortals can do this
-
-
-BTW: Don't let the magic words 'kernel programming' worry you. Its like DOS
-- you make a mistake you have to reboot. You do at least get dumps and a
-kernel logger that is reliable. There is now a loadable module allowing
-use of gdb on the kernel (no breakpoints though!). No magic involved.
-
-Alan
diff -u --recursive --new-file v2.4.1/linux/net/Config.in linux/net/Config.in
--- v2.4.1/linux/net/Config.in	Tue Oct 10 10:33:52 2000
+++ linux/net/Config.in	Fri Feb  9 11:34:13 2001
@@ -77,15 +77,15 @@
    tristate 'WAN router' CONFIG_WAN_ROUTER
    bool 'Fast switching (read help!)' CONFIG_NET_FASTROUTE
    bool 'Forwarding between high speed interfaces' CONFIG_NET_HW_FLOWCONTROL
-   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      mainmenu_option next_comment
-      comment 'QoS and/or fair queueing'
-      bool 'QoS and/or fair queueing (EXPERIMENTAL)' CONFIG_NET_SCHED
-      if [ "$CONFIG_NET_SCHED" = "y" ]; then
-	 source net/sched/Config.in
-      fi
-#      bool 'Network code profiler' CONFIG_NET_PROFILE
-      endmenu
-   fi
 fi
+
+mainmenu_option next_comment
+comment 'QoS and/or fair queueing'
+bool 'QoS and/or fair queueing (EXPERIMENTAL)' CONFIG_NET_SCHED
+if [ "$CONFIG_NET_SCHED" = "y" ]; then
+   source net/sched/Config.in
+fi
+#bool 'Network code profiler' CONFIG_NET_PROFILE
+endmenu
+
 endmenu
diff -u --recursive --new-file v2.4.1/linux/net/appletalk/Makefile linux/net/appletalk/Makefile
--- v2.4.1/linux/net/appletalk/Makefile	Fri Dec 29 14:07:24 2000
+++ linux/net/appletalk/Makefile	Fri Feb  9 11:34:13 2001
@@ -18,5 +18,3 @@
 
 include $(TOPDIR)/Rules.make
 
-tar:
-		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.4.1/linux/net/atm/common.c linux/net/atm/common.c
--- v2.4.1/linux/net/atm/common.c	Mon Jan  1 09:54:07 2001
+++ linux/net/atm/common.c	Fri Feb  9 11:34:13 2001
@@ -26,6 +26,7 @@
 #include <asm/uaccess.h>
 #include <asm/atomic.h>
 #include <asm/poll.h>
+#include <asm/ioctls.h>
 
 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
 #include <linux/atmlec.h>
@@ -376,6 +377,8 @@
 	if (error <= 0) return error;
 	vcc->timestamp = skb->stamp;
 	eff_len = skb->len > size ? size : skb->len;
+	if (skb->len > size) /* Not fit ?  Report it... */
+		m->msg_flags |= MSG_TRUNC;
 	if (vcc->dev->ops->feedback)
 		vcc->dev->ops->feedback(vcc,skb,(unsigned long) skb->data,
 		    (unsigned long) buff,eff_len);
diff -u --recursive --new-file v2.4.1/linux/net/atm/lec.h linux/net/atm/lec.h
--- v2.4.1/linux/net/atm/lec.h	Sat Feb  3 19:51:33 2001
+++ linux/net/atm/lec.h	Fri Feb  9 11:34:13 2001
@@ -72,7 +72,7 @@
  * 2. LLC Data frames whose total length, including LLC field and data,
  *    but not padding required to meet the minimum data frame length, 
  *    is less than 1536(0x0600) MUST be encoded by placing that length
- *    in the the h_type field. The LLC field follows header immediatelly.
+ *    in the h_type field. The LLC field follows header immediatelly.
  * 3. LLC data frames longer than this maximum MUST be encoded by placing
  *    the value 0 in the h_type field.
  *
@@ -154,5 +154,5 @@
 
 void atm_lane_init(void);
 void atm_lane_init_ops(struct atm_lane_ops *ops);
-#endif _LEC_H_
+#endif /* _LEC_H_ */
 
diff -u --recursive --new-file v2.4.1/linux/net/ax25/Makefile linux/net/ax25/Makefile
--- v2.4.1/linux/net/ax25/Makefile	Fri Dec 29 14:07:24 2000
+++ linux/net/ax25/Makefile	Fri Feb  9 11:34:13 2001
@@ -23,5 +23,3 @@
 
 include $(TOPDIR)/Rules.make
 
-tar:
-		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.4.1/linux/net/ax25/af_ax25.c linux/net/ax25/af_ax25.c
--- v2.4.1/linux/net/ax25/af_ax25.c	Fri Dec 29 14:35:47 2000
+++ linux/net/ax25/af_ax25.c	Fri Feb  9 11:34:13 2001
@@ -1782,10 +1782,9 @@
 	return(len);
 }
 
-static struct net_proto_family ax25_family_ops =
-{
-	PF_AX25,
-	ax25_create
+static struct net_proto_family ax25_family_ops = {
+	family:		PF_AX25,
+	create:		ax25_create,
 };
 
 static struct proto_ops SOCKOPS_WRAPPED(ax25_proto_ops) = {
@@ -1814,18 +1813,13 @@
 /*
  *	Called by socket.c on kernel start up
  */
-static struct packet_type ax25_packet_type =
-{
-	0,	/* MUTTER ntohs(ETH_P_AX25),*/
-	0,		/* copy */
-	ax25_kiss_rcv,
-	NULL,
-	NULL,
+static struct packet_type ax25_packet_type = {
+	type:		__constant_htons(ETH_P_AX25),
+	func:		ax25_kiss_rcv,
 };
 
 static struct notifier_block ax25_dev_notifier = {
-	ax25_device_event,
-	0
+	notifier_call:	ax25_device_event,
 };
 
 EXPORT_SYMBOL(ax25_encapsulate);
@@ -1846,10 +1840,11 @@
 EXPORT_SYMBOL(null_ax25_address);
 EXPORT_SYMBOL(ax25_display_timer);
 
+static const char banner[] __initdata = KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n";
+
 static int __init ax25_init(void)
 {
 	sock_register(&ax25_family_ops);
-	ax25_packet_type.type = htons(ETH_P_AX25);
 	dev_add_pack(&ax25_packet_type);
 	register_netdevice_notifier(&ax25_dev_notifier);
 	ax25_register_sysctl();
@@ -1858,7 +1853,7 @@
 	proc_net_create("ax25", 0, ax25_get_info);
 	proc_net_create("ax25_calls", 0, ax25_uid_get_info);
 
-	printk(KERN_INFO "NET4: G4KLX/GW4PTS AX.25 for Linux. Version 0.37 for Linux NET4.0\n");
+	printk(banner);
 	return 0;
 }
 module_init(ax25_init);
@@ -1879,7 +1874,6 @@
 	ax25_unregister_sysctl();
 	unregister_netdevice_notifier(&ax25_dev_notifier);
 
-	ax25_packet_type.type = htons(ETH_P_AX25);
 	dev_remove_pack(&ax25_packet_type);
 
 	sock_unregister(PF_AX25);
diff -u --recursive --new-file v2.4.1/linux/net/ax25/ax25_in.c linux/net/ax25/ax25_in.c
--- v2.4.1/linux/net/ax25/ax25_in.c	Fri Dec 29 14:35:47 2000
+++ linux/net/ax25/ax25_in.c	Fri Feb  9 11:30:57 2001
@@ -36,6 +36,7 @@
  *	AX.25 036	Jonathan(G4KLX)	Move DAMA code into own file.
  *			Joerg(DL1BKE)	Fixed DAMA Slave.
  *	AX.25 037	Jonathan(G4KLX)	New timer architecture.
+ *			Thomas(DL9SAU)  Fixed missing initialization of skb->protocol.
  */
 
 #include <linux/config.h>
@@ -158,6 +159,7 @@
 		skb->nh.raw   = skb->data;
 		skb->dev      = ax25->ax25_dev->dev;
 		skb->pkt_type = PACKET_HOST;
+		skb->protocol = htons(ETH_P_IP);
 		ip_rcv(skb, skb->dev, NULL);	/* Wrong ptype */
 		return 1;
 	}
@@ -287,6 +289,7 @@
 				skb->nh.raw   = skb->data;
 				skb->dev      = dev;
 				skb->pkt_type = PACKET_HOST;
+				skb->protocol = htons(ETH_P_IP);
 				ip_rcv(skb, dev, ptype);	/* Note ptype here is the wrong one, fix me later */
 				break;
 
@@ -296,6 +299,7 @@
 				skb->nh.raw   = skb->data;
 				skb->dev      = dev;
 				skb->pkt_type = PACKET_HOST;
+				skb->protocol = htons(ETH_P_ARP);
 				arp_rcv(skb, dev, ptype);	/* Note ptype here is wrong... */
 				break;
 #endif
diff -u --recursive --new-file v2.4.1/linux/net/ax25/sysctl_net_ax25.c linux/net/ax25/sysctl_net_ax25.c
--- v2.4.1/linux/net/ax25/sysctl_net_ax25.c	Sun Nov 12 20:37:17 2000
+++ linux/net/ax25/sysctl_net_ax25.c	Fri Feb  9 11:34:13 2001
@@ -27,8 +27,8 @@
 
 static struct ctl_table_header *ax25_table_header;
 
-static ctl_table *ax25_table = NULL;
-static int ax25_table_size   = 0;
+static ctl_table *ax25_table;
+static int ax25_table_size;
 
 static ctl_table ax25_dir_table[] = {
 	{NET_AX25, "ax25", NULL, 0, 0555, NULL},
diff -u --recursive --new-file v2.4.1/linux/net/bridge/br_private.h linux/net/bridge/br_private.h
--- v2.4.1/linux/net/bridge/br_private.h	Sat Feb  3 19:51:33 2001
+++ linux/net/bridge/br_private.h	Fri Feb  9 11:34:13 2001
@@ -4,7 +4,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_private.h,v 1.4 2001/01/19 04:51:48 davem Exp $
+ *	$Id: br_private.h,v 1.5 2001/02/05 06:03:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -116,83 +116,83 @@
 extern unsigned char bridge_ula[6];
 
 /* br.c */
-void br_dec_use_count(void);
-void br_inc_use_count(void);
+extern void br_dec_use_count(void);
+extern void br_inc_use_count(void);
 
 /* br_device.c */
-void br_dev_setup(struct net_device *dev);
+extern void br_dev_setup(struct net_device *dev);
 
 /* br_fdb.c */
-void br_fdb_changeaddr(struct net_bridge_port *p,
+extern void br_fdb_changeaddr(struct net_bridge_port *p,
 		       unsigned char *newaddr);
-void br_fdb_cleanup(struct net_bridge *br);
-void br_fdb_delete_by_port(struct net_bridge *br,
+extern void br_fdb_cleanup(struct net_bridge *br);
+extern void br_fdb_delete_by_port(struct net_bridge *br,
 			   struct net_bridge_port *p);
-struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
+extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br,
 					unsigned char *addr);
-void br_fdb_put(struct net_bridge_fdb_entry *ent);
-int  br_fdb_get_entries(struct net_bridge *br,
+extern void br_fdb_put(struct net_bridge_fdb_entry *ent);
+extern int  br_fdb_get_entries(struct net_bridge *br,
 			unsigned char *_buf,
 			int maxnum,
 			int offset);
-void br_fdb_insert(struct net_bridge *br,
+extern void br_fdb_insert(struct net_bridge *br,
 		   struct net_bridge_port *source,
 		   unsigned char *addr,
 		   int is_local);
 
 /* br_forward.c */
-void br_forward(struct net_bridge_port *to,
+extern void br_forward(struct net_bridge_port *to,
 		struct sk_buff *skb);
-void br_flood(struct net_bridge *br,
+extern void br_flood(struct net_bridge *br,
 	      struct sk_buff *skb,
 	      int clone);
 
 /* br_if.c */
-int br_add_bridge(char *name);
-int br_del_bridge(char *name);
-int br_add_if(struct net_bridge *br,
+extern int br_add_bridge(char *name);
+extern int br_del_bridge(char *name);
+extern int br_add_if(struct net_bridge *br,
 	      struct net_device *dev);
-int br_del_if(struct net_bridge *br,
+extern int br_del_if(struct net_bridge *br,
 	      struct net_device *dev);
-int br_get_bridge_ifindices(int *indices,
+extern int br_get_bridge_ifindices(int *indices,
 			    int num);
-void br_get_port_ifindices(struct net_bridge *br,
+extern void br_get_port_ifindices(struct net_bridge *br,
 			   int *ifindices);
 
 /* br_input.c */
-void br_handle_frame(struct sk_buff *skb);
+extern void br_handle_frame(struct sk_buff *skb);
 
 /* br_ioctl.c */
-void br_call_ioctl_atomic(void (*fn)(void));
-int br_ioctl(struct net_bridge *br,
+extern void br_call_ioctl_atomic(void (*fn)(void));
+extern int br_ioctl(struct net_bridge *br,
 	     unsigned int cmd,
 	     unsigned long arg0,
 	     unsigned long arg1,
 	     unsigned long arg2);
-int br_ioctl_deviceless_stub(unsigned long arg);
+extern int br_ioctl_deviceless_stub(unsigned long arg);
 
 /* br_stp.c */
-int br_is_root_bridge(struct net_bridge *br);
-struct net_bridge_port *br_get_port(struct net_bridge *br,
+extern int br_is_root_bridge(struct net_bridge *br);
+extern struct net_bridge_port *br_get_port(struct net_bridge *br,
 				    int port_no);
-void br_init_port(struct net_bridge_port *p);
-port_id br_make_port_id(struct net_bridge_port *p);
-void br_become_designated_port(struct net_bridge_port *p);
+extern void br_init_port(struct net_bridge_port *p);
+extern port_id br_make_port_id(struct net_bridge_port *p);
+extern void br_become_designated_port(struct net_bridge_port *p);
 
 /* br_stp_if.c */
-void br_stp_enable_bridge(struct net_bridge *br);
-void br_stp_disable_bridge(struct net_bridge *br);
-void br_stp_enable_port(struct net_bridge_port *p);
-void br_stp_disable_port(struct net_bridge_port *p);
-void br_stp_recalculate_bridge_id(struct net_bridge *br);
-void br_stp_set_bridge_priority(struct net_bridge *br,
+extern void br_stp_enable_bridge(struct net_bridge *br);
+extern void br_stp_disable_bridge(struct net_bridge *br);
+extern void br_stp_enable_port(struct net_bridge_port *p);
+extern void br_stp_disable_port(struct net_bridge_port *p);
+extern void br_stp_recalculate_bridge_id(struct net_bridge *br);
+extern void br_stp_set_bridge_priority(struct net_bridge *br,
 				int newprio);
-void br_stp_set_port_priority(struct net_bridge_port *p,
+extern void br_stp_set_port_priority(struct net_bridge_port *p,
 			      int newprio);
-void br_stp_set_path_cost(struct net_bridge_port *p,
+extern void br_stp_set_path_cost(struct net_bridge_port *p,
 			  int path_cost);
 
 /* br_stp_bpdu.c */
-void br_stp_handle_bpdu(struct sk_buff *skb);
+extern void br_stp_handle_bpdu(struct sk_buff *skb);
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/net/bridge/br_private_stp.h linux/net/bridge/br_private_stp.h
--- v2.4.1/linux/net/bridge/br_private_stp.h	Mon Oct 30 14:34:12 2000
+++ linux/net/bridge/br_private_stp.h	Fri Feb  9 11:34:13 2001
@@ -4,7 +4,7 @@
  *	Authors:
  *	Lennert Buytenhek		<buytenh@gnu.org>
  *
- *	$Id: br_private_stp.h,v 1.2 2000/10/30 22:03:20 davem Exp $
+ *	$Id: br_private_stp.h,v 1.3 2001/02/05 06:03:47 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *	modify it under the terms of the GNU General Public License
@@ -33,21 +33,21 @@
 };
 
 /* br_stp.c */
-void br_become_root_bridge(struct net_bridge *br);
-void br_config_bpdu_generation(struct net_bridge *);
-void br_configuration_update(struct net_bridge *);
-int  br_is_designated_port(struct net_bridge_port *p);
-int  br_is_root_bridge(struct net_bridge *br);
-void br_port_state_selection(struct net_bridge *);
-void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu);
-void br_received_tcn_bpdu(struct net_bridge_port *p);
-void br_tick(unsigned long __data);
-void br_transmit_config(struct net_bridge_port *p);
-void br_transmit_tcn(struct net_bridge *br);
-void br_topology_change_detection(struct net_bridge *br);
+extern void br_become_root_bridge(struct net_bridge *br);
+extern void br_config_bpdu_generation(struct net_bridge *);
+extern void br_configuration_update(struct net_bridge *);
+extern int  br_is_designated_port(struct net_bridge_port *p);
+extern int  br_is_root_bridge(struct net_bridge *br);
+extern void br_port_state_selection(struct net_bridge *);
+extern void br_received_config_bpdu(struct net_bridge_port *p, struct br_config_bpdu *bpdu);
+extern void br_received_tcn_bpdu(struct net_bridge_port *p);
+extern void br_tick(unsigned long __data);
+extern void br_transmit_config(struct net_bridge_port *p);
+extern void br_transmit_tcn(struct net_bridge *br);
+extern void br_topology_change_detection(struct net_bridge *br);
 
 /* br_stp_bpdu.c */
-void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
-void br_send_tcn_bpdu(struct net_bridge_port *);
+extern void br_send_config_bpdu(struct net_bridge_port *, struct br_config_bpdu *);
+extern void br_send_tcn_bpdu(struct net_bridge_port *);
 
 #endif
diff -u --recursive --new-file v2.4.1/linux/net/core/datagram.c linux/net/core/datagram.c
--- v2.4.1/linux/net/core/datagram.c	Sat Nov 11 19:02:40 2000
+++ linux/net/core/datagram.c	Sat Feb  3 10:39:12 2001
@@ -72,19 +72,19 @@
 	/* Socket errors? */
 	error = sock_error(sk);
 	if (error)
-		goto out;
+		goto out_err;
 
 	if (!skb_queue_empty(&sk->receive_queue))
 		goto ready;
 
 	/* Socket shut down? */
 	if (sk->shutdown & RCV_SHUTDOWN)
-		goto out;
+		goto out_noerr;
 
 	/* Sequenced packets can come disconnected. If so we report the problem */
 	error = -ENOTCONN;
 	if(connection_based(sk) && !(sk->state==TCP_ESTABLISHED || sk->state==TCP_LISTEN))
-		goto out;
+		goto out_err;
 
 	/* handle signals */
 	if (signal_pending(current))
@@ -99,11 +99,16 @@
 
 interrupted:
 	error = sock_intr_errno(*timeo_p);
+out_err:
+	*err = error;
 out:
 	current->state = TASK_RUNNING;
 	remove_wait_queue(sk->sleep, &wait);
-	*err = error;
 	return error;
+out_noerr:
+	*err = 0;
+	error = 1;
+	goto out;
 }
 
 /*
diff -u --recursive --new-file v2.4.1/linux/net/core/iovec.c linux/net/core/iovec.c
--- v2.4.1/linux/net/core/iovec.c	Sat Jan 22 11:54:57 2000
+++ linux/net/core/iovec.c	Fri Feb  9 11:29:44 2001
@@ -21,7 +21,7 @@
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/in6.h>
 #include <asm/uaccess.h>
diff -u --recursive --new-file v2.4.1/linux/net/core/skbuff.c linux/net/core/skbuff.c
--- v2.4.1/linux/net/core/skbuff.c	Fri Dec 29 14:07:24 2000
+++ linux/net/core/skbuff.c	Fri Feb 16 16:06:17 2001
@@ -44,11 +44,10 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/inet.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
-#include <linux/slab.h>
 #include <linux/cache.h>
 #include <linux/init.h>
 
diff -u --recursive --new-file v2.4.1/linux/net/core/sock.c linux/net/core/sock.c
--- v2.4.1/linux/net/core/sock.c	Fri Dec 29 14:07:24 2000
+++ linux/net/core/sock.c	Sat Feb  3 11:26:44 2001
@@ -7,7 +7,7 @@
  *		handler for protocols to use and generic option handler.
  *
  *
- * Version:	$Id: sock.c,v 1.102 2000/12/11 23:00:24 davem Exp $
+ * Version:	$Id: sock.c,v 1.104 2001/01/30 07:48:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -549,6 +549,13 @@
 				return -EFAULT;
 			goto lenout;
 		}
+
+		/* Dubious BSD thing... Probably nobody even uses it, but
+		 * the UNIX standard wants it for whatever reason... -DaveM
+		 */
+		case SO_ACCEPTCONN:
+			v.val = (sk->state == TCP_LISTEN);
+			break;
 
 		default:
 			return(-ENOPROTOOPT);
diff -u --recursive --new-file v2.4.1/linux/net/decnet/af_decnet.c linux/net/decnet/af_decnet.c
--- v2.4.1/linux/net/decnet/af_decnet.c	Sat Feb  3 19:51:33 2001
+++ linux/net/decnet/af_decnet.c	Fri Feb  9 11:29:44 2001
@@ -114,6 +114,7 @@
 #include <net/sock.h>
 #include <asm/segment.h>
 #include <asm/system.h>
+#include <asm/ioctls.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/proc_fs.h>
diff -u --recursive --new-file v2.4.1/linux/net/decnet/sysctl_net_decnet.c linux/net/decnet/sysctl_net_decnet.c
--- v2.4.1/linux/net/decnet/sysctl_net_decnet.c	Sun Nov 12 20:37:17 2000
+++ linux/net/decnet/sysctl_net_decnet.c	Fri Feb  9 11:34:13 2001
@@ -127,7 +127,7 @@
 				void *newval, size_t newlen,
 				void **context)
 {
-	int len;
+	size_t len;
 	dn_address addr;
 
 	if (oldval && oldlenp) {
@@ -161,7 +161,7 @@
 				void *buffer, size_t *lenp)
 {
 	char addr[DN_ASCBUF_LEN];
-	int len;
+	size_t len;
 	dn_address dnaddr;
 
 	if (!*lenp || (filp->f_pos && !write)) {
@@ -265,7 +265,7 @@
 				struct file * filp,
 				void *buffer, size_t *lenp)
 {
-	int len;
+	size_t len;
 	struct net_device *dev = decnet_default_device;
 	char devname[17];
 
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/arp.c linux/net/ipv4/arp.c
--- v2.4.1/linux/net/ipv4/arp.c	Mon Jan  1 10:23:21 2001
+++ linux/net/ipv4/arp.c	Fri Feb  9 11:34:13 2001
@@ -65,19 +65,9 @@
  *					clean up the APFDDI & gen. FDDI bits.
  *		Alexey Kuznetsov:	new arp state machine;
  *					now it is in net/core/neighbour.c.
+ *		Krzysztof Halasa:	Added Frame Relay ARP support.
  */
 
-/* RFC1122 Status:
-   2.3.2.1 (ARP Cache Validation):
-     MUST provide mechanism to flush stale cache entries (OK)
-     SHOULD be able to configure cache timeout (OK)
-     MUST throttle ARP retransmits (OK)
-   2.3.2.2 (ARP Packet Queue):
-     SHOULD save at least one packet from each "conversation" with an
-       unresolved IP address.  (OK)
-   950727 -- MS
-*/
-      
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
@@ -647,6 +637,20 @@
 			goto out;
 		break;
 #endif
+#ifdef CONFIG_NET_FC
+	case ARPHRD_IEEE802:
+		/*
+		 * According to RFC 2625, Fibre Channel devices (which are IEEE
+		 * 802 devices) should accept ARP hardware types of 6 (IEEE 802)
+		 * and 1 (Ethernet).
+		 */
+		if (arp->ar_hrd != __constant_htons(ARPHRD_ETHER) &&
+		    arp->ar_hrd != __constant_htons(ARPHRD_IEEE802))
+			goto out;
+		if (arp->ar_pro != __constant_htons(ETH_P_IP))
+			goto out;
+		break;
+#endif
 #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
 	case ARPHRD_AX25:
 		if (arp->ar_pro != __constant_htons(AX25_P_IP))
@@ -687,6 +691,12 @@
  */
 	if (LOOPBACK(tip) || MULTICAST(tip))
 		goto out;
+
+/*
+ *     Special case: We must set Frame Relay source Q.922 address
+ */
+	if (dev_type == ARPHRD_DLCI)
+		sha = dev->broadcast;
 
 /*
  *  Process entry.  The idea here is we want to send a reply if it is a
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/devinet.c linux/net/ipv4/devinet.c
--- v2.4.1/linux/net/ipv4/devinet.c	Mon Dec 11 12:37:04 2000
+++ linux/net/ipv4/devinet.c	Fri Feb  9 11:34:13 2001
@@ -1,7 +1,7 @@
 /*
  *	NET3	IP device support routines.
  *
- *	Version: $Id: devinet.c,v 1.39 2000/12/10 22:24:11 davem Exp $
+ *	Version: $Id: devinet.c,v 1.40 2001/02/05 06:03:47 davem Exp $
  *
  *		This program is free software; you can redistribute it and/or
  *		modify it under the terms of the GNU General Public License
@@ -50,9 +50,7 @@
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
-#ifdef CONFIG_KMOD
 #include <linux/kmod.h>
-#endif
 
 #include <net/ip.h>
 #include <net/route.h>
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/ipconfig.c linux/net/ipv4/ipconfig.c
--- v2.4.1/linux/net/ipv4/ipconfig.c	Fri Dec 29 14:35:47 2000
+++ linux/net/ipv4/ipconfig.c	Fri Feb  9 11:34:13 2001
@@ -1,5 +1,5 @@
 /*
- *  $Id: ipconfig.c,v 1.34 2000/07/26 01:04:18 davem Exp $
+ *  $Id: ipconfig.c,v 1.35 2000/12/30 06:46:36 davem Exp $
  *
  *  Automatic Configuration of IP -- use BOOTP or RARP or user-supplied
  *  information to configure own IP address and routes.
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/netfilter/ip_fw_compat.c linux/net/ipv4/netfilter/ip_fw_compat.c
--- v2.4.1/linux/net/ipv4/netfilter/ip_fw_compat.c	Mon Sep 18 15:09:55 2000
+++ linux/net/ipv4/netfilter/ip_fw_compat.c	Fri Feb  9 11:34:13 2001
@@ -9,6 +9,7 @@
 #include <linux/inetdevice.h>
 #include <linux/netdevice.h>
 #include <linux/module.h>
+#include <asm/uaccess.h>
 #include <net/ip.h>
 #include <net/route.h>
 #include <linux/netfilter_ipv4/compat_firewall.h>
@@ -132,7 +133,7 @@
 		if (ret == FW_ACCEPT || ret == FW_SKIP) {
 			if (fwops->fw_acct_out)
 				fwops->fw_acct_out(fwops, PF_INET,
-						   (struct net_device *)in,
+						   (struct net_device *)out,
 						   (*pskb)->nh.raw, &redirpt,
 						   pskb);
 			confirm_connection(*pskb);
@@ -197,14 +198,28 @@
 	return NF_ACCEPT;
 }
 
-extern int ip_fw_ctl(int optval, void *user, unsigned int len);
+extern int ip_fw_ctl(int optval, void *m, unsigned int len);
 
 static int sock_fn(struct sock *sk, int optval, void *user, unsigned int len)
 {
+	/* MAX of:
+	   2.2: sizeof(struct ip_fwtest) (~14x4 + 3x4 = 17x4)
+	   2.2: sizeof(struct ip_fwnew) (~1x4 + 15x4 + 3x4 + 3x4 = 22x4)
+	   2.0: sizeof(struct ip_fw) (~25x4)
+
+	   We can't include both 2.0 and 2.2 headers, they conflict.
+	   Hence, 200 is a good number. --RR */
+	char tmp_fw[200];
 	if (!capable(CAP_NET_ADMIN))
 		return -EPERM;
 
-	return -ip_fw_ctl(optval, user, len);
+	if (len > sizeof(tmp_fw) || len < 1)
+		return -EINVAL;
+
+	if (copy_from_user(&tmp_fw, user, len))
+		return -EFAULT;
+
+	return -ip_fw_ctl(optval, &tmp_fw, len);
 }
 
 static struct nf_hook_ops preroute_ops
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/netfilter/ip_nat_standalone.c linux/net/ipv4/netfilter/ip_nat_standalone.c
--- v2.4.1/linux/net/ipv4/netfilter/ip_nat_standalone.c	Mon Oct 30 14:27:49 2000
+++ linux/net/ipv4/netfilter/ip_nat_standalone.c	Sat Feb  3 11:45:55 2001
@@ -330,11 +330,9 @@
 module_init(init);
 module_exit(fini);
 
-#ifdef MODULE
 EXPORT_SYMBOL(ip_nat_setup_info);
 EXPORT_SYMBOL(ip_nat_helper_register);
 EXPORT_SYMBOL(ip_nat_helper_unregister);
 EXPORT_SYMBOL(ip_nat_expect_register);
 EXPORT_SYMBOL(ip_nat_expect_unregister);
 EXPORT_SYMBOL(ip_nat_cheat_check);
-#endif
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/netfilter/ipt_TOS.c linux/net/ipv4/netfilter/ipt_TOS.c
--- v2.4.1/linux/net/ipv4/netfilter/ipt_TOS.c	Thu Apr 27 15:43:15 2000
+++ linux/net/ipv4/netfilter/ipt_TOS.c	Fri Feb  9 11:34:13 2001
@@ -19,11 +19,11 @@
 	const struct ipt_tos_target_info *tosinfo = targinfo;
 
 	if ((iph->tos & IPTOS_TOS_MASK) != tosinfo->tos) {
-		u_int8_t diffs[2];
+		u_int16_t diffs[2];
 
-		diffs[0] = iph->tos;
+		diffs[0] = htons(iph->tos) ^ 0xFFFF;
 		iph->tos = (iph->tos & IPTOS_PREC_MASK) | tosinfo->tos;
-		diffs[1] = iph->tos;
+		diffs[1] = htons(iph->tos);
 		iph->check = csum_fold(csum_partial((char *)diffs,
 		                                    sizeof(diffs),
 		                                    iph->check^0xFFFF));
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
--- v2.4.1/linux/net/ipv4/raw.c	Tue Nov 28 21:53:45 2000
+++ linux/net/ipv4/raw.c	Fri Feb  9 11:29:44 2001
@@ -41,6 +41,7 @@
 #include <linux/config.h> 
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/syncookies.c linux/net/ipv4/syncookies.c
--- v2.4.1/linux/net/ipv4/syncookies.c	Fri Aug  4 18:18:49 2000
+++ linux/net/ipv4/syncookies.c	Fri Feb  9 11:29:44 2001
@@ -17,7 +17,7 @@
 #include <linux/config.h>
 #if defined(CONFIG_SYN_COOKIES) 
 #include <linux/tcp.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/random.h>
 #include <net/tcp.h>
 
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/tcp.c linux/net/ipv4/tcp.c
--- v2.4.1/linux/net/ipv4/tcp.c	Sat Feb  3 19:51:33 2001
+++ linux/net/ipv4/tcp.c	Fri Feb  9 11:34:13 2001
@@ -245,175 +245,6 @@
  *	TCP_CLOSE		socket is finished
  */
 
-/*
- * RFC1122 status:
- * NOTE: I'm not going to be doing comments in the code for this one except
- * for violations and the like.  tcp.c is just too big... If I say something
- * "does?" or "doesn't?", it means I'm not sure, and will have to hash it out
- * with Alan. -- MS 950903
- * [Note: Most of the TCP code has been rewriten/redesigned since this 
- *  RFC1122 check. It is probably not correct anymore. It should be redone 
- *  before 2.2. -AK]
- *
- * Use of PSH (4.2.2.2)
- *   MAY aggregate data sent without the PSH flag. (does)
- *   MAY queue data received without the PSH flag. (does)
- *   SHOULD collapse successive PSH flags when it packetizes data. (doesn't)
- *   MAY implement PSH on send calls. (doesn't, thus:)
- *     MUST NOT buffer data indefinitely (doesn't [1 second])
- *     MUST set PSH on last segment (does)
- *   MAY pass received PSH to application layer (doesn't)
- *   SHOULD send maximum-sized segment whenever possible. (almost always does)
- *
- * Window Size (4.2.2.3, 4.2.2.16)
- *   MUST treat window size as an unsigned number (does)
- *   SHOULD treat window size as a 32-bit number (does not)
- *   MUST NOT shrink window once it is offered (does not normally)
- *
- * Urgent Pointer (4.2.2.4)
- * **MUST point urgent pointer to last byte of urgent data (not right
- *     after). (doesn't, to be like BSD. That's configurable, but defaults
- *	to off)
- *   MUST inform application layer asynchronously of incoming urgent
- *     data. (does)
- *   MUST provide application with means of determining the amount of
- *     urgent data pending. (does)
- * **MUST support urgent data sequence of arbitrary length. (doesn't, but
- *   it's sort of tricky to fix, as urg_ptr is a 16-bit quantity)
- *	[Follows BSD 1 byte of urgent data]
- *
- * TCP Options (4.2.2.5)
- *   MUST be able to receive TCP options in any segment. (does)
- *   MUST ignore unsupported options (does)
- *
- * Maximum Segment Size Option (4.2.2.6)
- *   MUST implement both sending and receiving MSS. (does, but currently
- *	only uses the smaller of both of them)
- *   SHOULD send an MSS with every SYN where receive MSS != 536 (MAY send
- *     it always). (does, even when MSS == 536, which is legal)
- *   MUST assume MSS == 536 if no MSS received at connection setup (does)
- *   MUST calculate "effective send MSS" correctly:
- *     min(physical_MTU, remote_MSS+20) - sizeof(tcphdr) - sizeof(ipopts)
- *     (does - but allows operator override)
- *
- * TCP Checksum (4.2.2.7)
- *   MUST generate and check TCP checksum. (does)
- *
- * Initial Sequence Number Selection (4.2.2.8)
- *   MUST use the RFC 793 clock selection mechanism.  (doesn't, but it's
- *     OK: RFC 793 specifies a 250KHz clock, while we use 1MHz, which is
- *     necessary for 10Mbps networks - and harder than BSD to spoof!
- *     With syncookies we don't)
- *
- * Simultaneous Open Attempts (4.2.2.10)
- *   MUST support simultaneous open attempts (does)
- *
- * Recovery from Old Duplicate SYN (4.2.2.11)
- *   MUST keep track of active vs. passive open (does)
- *
- * RST segment (4.2.2.12)
- *   SHOULD allow an RST segment to contain data (does, but doesn't do
- *     anything with it, which is standard)
- *
- * Closing a Connection (4.2.2.13)
- *   MUST inform application of whether connection was closed by RST or
- *     normal close. (does)
- *   MAY allow "half-duplex" close (treat connection as closed for the
- *     local app, even before handshake is done). (does)
- *   MUST linger in TIME_WAIT for 2 * MSL (does)
- *
- * Retransmission Timeout (4.2.2.15)
- *   MUST implement Jacobson's slow start and congestion avoidance
- *     stuff. (does)
- *
- * Probing Zero Windows (4.2.2.17)
- *   MUST support probing of zero windows. (does)
- *   MAY keep offered window closed indefinitely. (does)
- *   MUST allow remote window to stay closed indefinitely. (does)
- *
- * Passive Open Calls (4.2.2.18)
- *   MUST NOT let new passive open affect other connections. (doesn't)
- *   MUST support passive opens (LISTENs) concurrently. (does)
- *
- * Time to Live (4.2.2.19)
- *   MUST make TCP TTL configurable. (does - IP_TTL option)
- *
- * Event Processing (4.2.2.20)
- *   SHOULD queue out-of-order segments. (does)
- *   MUST aggregate ACK segments whenever possible. (does but badly)
- *
- * Retransmission Timeout Calculation (4.2.3.1)
- *   MUST implement Karn's algorithm and Jacobson's algorithm for RTO
- *     calculation. (does, or at least explains them in the comments 8*b)
- *  SHOULD initialize RTO to 0 and RTT to 3. (does)
- *
- * When to Send an ACK Segment (4.2.3.2)
- *   SHOULD implement delayed ACK. (does)
- *   MUST keep ACK delay < 0.5 sec. (does)
- *
- * When to Send a Window Update (4.2.3.3)
- *   MUST implement receiver-side SWS. (does)
- *
- * When to Send Data (4.2.3.4)
- *   MUST implement sender-side SWS. (does)
- *   SHOULD implement Nagle algorithm. (does)
- *
- * TCP Connection Failures (4.2.3.5)
- *  MUST handle excessive retransmissions "properly" (see the RFC). (does)
- *   SHOULD inform application layer of soft errors. (does)
- *
- * TCP Keep-Alives (4.2.3.6)
- *   MAY provide keep-alives. (does)
- *   MUST make keep-alives configurable on a per-connection basis. (does)
- *   MUST default to no keep-alives. (does)
- *   MUST make keep-alive interval configurable. (does)
- *   MUST make default keep-alive interval > 2 hours. (does)
- *   MUST NOT interpret failure to ACK keep-alive packet as dead
- *     connection. (doesn't)
- *   SHOULD send keep-alive with no data. (does)
- *
- * TCP Multihoming (4.2.3.7)
- *   MUST get source address from IP layer before sending first
- *     SYN. (does)
- *   MUST use same local address for all segments of a connection. (does)
- *
- * IP Options (4.2.3.8)
- *   MUST ignore unsupported IP options. (does)
- *   MAY support Time Stamp and Record Route. (does)
- *   MUST allow application to specify a source route. (does)
- *   MUST allow received Source Route option to set route for all future
- *     segments on this connection. (does not (security issues))
- *
- * ICMP messages (4.2.3.9)
- *   MUST act on ICMP errors. (does)
- *   MUST slow transmission upon receipt of a Source Quench. (doesn't anymore 
- *   because that is deprecated now by the IETF, can be turned on)
- *   MUST NOT abort connection upon receipt of soft Destination
- *     Unreachables (0, 1, 5), Time Exceededs and Parameter
- *     Problems. (doesn't)
- *   SHOULD report soft Destination Unreachables etc. to the
- *     application. (does, except during SYN_RECV and may drop messages
- *     in some rare cases before accept() - ICMP is unreliable)	
- *   SHOULD abort connection upon receipt of hard Destination Unreachable
- *     messages (2, 3, 4). (does, but see above)
- *
- * Remote Address Validation (4.2.3.10)
- *   MUST reject as an error OPEN for invalid remote IP address. (does)
- *   MUST ignore SYN with invalid source address. (does)
- *   MUST silently discard incoming SYN for broadcast/multicast
- *     address. (does)
- *
- * Asynchronous Reports (4.2.4.1)
- * MUST provide mechanism for reporting soft errors to application
- *     layer. (does)
- *
- * Type of Service (4.2.4.2)
- *   MUST allow application layer to set Type of Service. (does IP_TOS)
- *
- * (Whew. -- MS 950903)
- * (Updated by AK, but not complete yet.)
- **/
-
 #include <linux/config.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
@@ -425,6 +256,7 @@
 #include <net/tcp.h>
 
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 
 int sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
 
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.4.1/linux/net/ipv4/tcp_input.c	Sat Feb  3 19:51:33 2001
+++ linux/net/ipv4/tcp_input.c	Fri Feb  9 11:34:13 2001
@@ -600,7 +600,7 @@
 /* Increase initial CWND conservatively: if estimated
  * RTT is low enough (<20msec) or if we have some preset ssthresh.
  *
- * Numbers are taken from RFC1414.
+ * Numbers are taken from RFC2414.
  */
 __u32 tcp_init_cwnd(struct tcp_opt *tp)
 {
@@ -2164,43 +2164,23 @@
 		!tcp_disordered_ack(tp, skb));
 }
 
-static int __tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
-{
-	u32 end_window = tp->rcv_wup + tp->rcv_wnd;
-#ifdef TCP_FORMAL_WINDOW
-	u32 rcv_wnd = tcp_receive_window(tp);
-#else
-	u32 rcv_wnd = tp->rcv_wnd;
-#endif
-
-	if (rcv_wnd &&
-	    after(end_seq, tp->rcv_nxt) &&
-	    before(seq, end_window))
-		return 1;
-	if (seq != end_window)
-		return 0;
-	return (seq == end_seq);
-}
-
-/* This functions checks to see if the tcp header is actually acceptable.
+/* Check segment sequence number for validity.
+ *
+ * Segment controls are considered valid, if the segment
+ * fits to the window after truncation to the window. Acceptability
+ * of data (and SYN, FIN, of course) is checked separately.
+ * See tcp_data_queue(), for example.
  *
- * Actually, our check is seriously broken, we must accept RST,ACK,URG
- * even on zero window effectively trimming data. It is RFC, guys.
- * But our check is so beautiful, that I do not want to repair it
- * now. However, taking into account those stupid plans to start to
- * send some texts with RST, we have to handle at least this case. --ANK
+ * Also, controls (RST is main one) are accepted using RCV.WUP instead
+ * of RCV.NXT. Peer still did not advance his SND.UNA when we
+ * delayed ACK, so that hisSND.UNA<=ourRCV.WUP.
+ * (borrowed from freebsd)
  */
-extern __inline__ int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq, int rst)
-{
-#ifdef TCP_FORMAL_WINDOW
-	u32 rcv_wnd = tcp_receive_window(tp);
-#else
-	u32 rcv_wnd = tp->rcv_wnd;
-#endif
-	if (seq == tp->rcv_nxt)
-		return (rcv_wnd || (end_seq == seq) || rst);
 
-	return __tcp_sequence(tp, seq, end_seq);
+static inline int tcp_sequence(struct tcp_opt *tp, u32 seq, u32 end_seq)
+{
+	return	!before(end_seq, tp->rcv_wup) &&
+		!after(seq, tp->rcv_nxt + tcp_receive_window(tp));
 }
 
 /* When we get a reset we do this. */
@@ -2541,7 +2521,10 @@
 	 *  Out of sequence packets to the out_of_order_queue.
 	 */
 	if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) {
-		/* Ok. In sequence. */
+		if (tcp_receive_window(tp) == 0)
+			goto out_of_window;
+
+		/* Ok. In sequence. In window. */
 		if (tp->ucopy.task == current &&
 		    tp->copied_seq == tp->rcv_nxt &&
 		    tp->ucopy.len &&
@@ -2601,20 +2584,27 @@
 		return;
 	}
 
-#ifdef TCP_DEBUG
-	/* An old packet, either a retransmit or some packet got lost. */
 	if (!after(TCP_SKB_CB(skb)->end_seq, tp->rcv_nxt)) {
-		/* A retransmit, 2nd most common case.  Force an imediate ack.
-		 * 
-		 * It is impossible, seq is checked by top level.
-		 */
-		printk("BUG: retransmit in tcp_data_queue: seq %X\n", TCP_SKB_CB(skb)->seq);
+		/* A retransmit, 2nd most common case.  Force an immediate ack. */
+		NET_INC_STATS_BH(DelayedACKLost);
 		tcp_enter_quickack_mode(tp);
+		tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq);
+
+out_of_window:
 		tcp_schedule_ack(tp);
 		__kfree_skb(skb);
 		return;
 	}
-#endif
+
+	/* Out of window. F.e. zero window probe.
+	 *
+	 * Note: it is highly possible that we may open window and enqueue
+	 * this segment now. However, this will be known only after we queue
+	 * it, which will result in queue full of successive 1 byte BSD
+	 * window probes, it is SWS in fact. So, always reject it and send ACK.
+	 */
+	if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt+tcp_receive_window(tp)))
+		goto out_of_window;
 
 	tcp_enter_quickack_mode(tp);
 
@@ -2625,6 +2615,12 @@
 			   TCP_SKB_CB(skb)->end_seq);
 
 		tcp_dsack_set(tp, TCP_SKB_CB(skb)->seq, tp->rcv_nxt);
+		
+		/* If window is closed, drop tail of packet. But after
+		 * remembering D-SACK for its head made in previous line.
+		 */
+		if (!tcp_receive_window(tp))
+			goto out_of_window;
 		goto queue_and_out;
 	}
 
@@ -3333,7 +3329,7 @@
 	 *	Standard slow path.
 	 */
 
-	if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, th->rst)) {
+	if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
 		/* RFC793, page 37: "In all states except SYN-SENT, all reset
 		 * (RST) segments are validated by checking their SEQ-fields."
 		 * And page 69: "If an incoming segment is not acceptable,
@@ -3669,7 +3665,7 @@
 	}
 
 	/* step 1: check sequence number */
-	if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, th->rst)) {
+	if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
 		if (!th->rst)
 			tcp_send_dupack(sk, skb);
 		goto discard;
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.4.1/linux/net/ipv4/tcp_timer.c	Mon Jan  1 11:01:58 2001
+++ linux/net/ipv4/tcp_timer.c	Fri Feb  9 11:34:13 2001
@@ -5,7 +5,7 @@
  *
  *		Implementation of the Transmission Control Protocol(TCP).
  *
- * Version:	$Id: tcp_timer.c,v 1.80 2000/10/03 07:29:01 anton Exp $
+ * Version:	$Id: tcp_timer.c,v 1.81 2001/01/01 02:38:30 davem Exp $
  *
  * Authors:	Ross Biro, <bir7@leland.Stanford.Edu>
  *		Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff -u --recursive --new-file v2.4.1/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
--- v2.4.1/linux/net/ipv4/udp.c	Mon Jan  1 11:01:58 2001
+++ linux/net/ipv4/udp.c	Fri Feb  9 11:34:13 2001
@@ -69,31 +69,9 @@
  *		2 of the License, or (at your option) any later version.
  */
  
-/* RFC1122 Status:
-   4.1.3.1 (Ports):
-     SHOULD send ICMP_PORT_UNREACHABLE in response to datagrams to 
-       an un-listened port. (OK)
-   4.1.3.2 (IP Options)
-     MUST pass IP options from IP -> application (OK)
-     MUST allow application to specify IP options (OK)
-   4.1.3.3 (ICMP Messages)
-     MUST pass ICMP error messages to application (OK -- except when SO_BSDCOMPAT is set)
-   4.1.3.4 (UDP Checksums)
-     MUST provide facility for checksumming (OK)
-     MAY allow application to control checksumming (OK)
-     MUST default to checksumming on (OK)
-     MUST discard silently datagrams with bad csums (OK, except during debugging)
-   4.1.3.5 (UDP Multihoming)
-     MUST allow application to specify source address (OK)
-     SHOULD be able to communicate the chosen src addr up to application
-       when application doesn't choose (DOES - use recvmsg cmsgs)
-   4.1.3.6 (Invalid Addresses)
-     MUST discard invalid source addresses (OK -- done in the new routing code)
-     MUST only send datagrams with one of our addresses (OK)
-*/
-
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 #include <linux/types.h>
 #include <linux/fcntl.h>
 #include <linux/socket.h>
@@ -161,7 +139,7 @@
 		next:;
 		}
 		result = best;
-		for(;; result += UDP_HTABLE_SIZE) {
+		for(i = 0; i < (1 << 16) / UDP_HTABLE_SIZE; i++, result += UDP_HTABLE_SIZE) {
 			if (result > sysctl_local_port_range[1])
 				result = sysctl_local_port_range[0]
 					+ ((result - sysctl_local_port_range[0]) &
@@ -169,6 +147,8 @@
 			if (!udp_lport_inuse(result))
 				break;
 		}
+		if (i >= (1 << 16) / UDP_HTABLE_SIZE)
+			goto fail;
 gotit:
 		udp_port_rover = snum = result;
 	} else {
diff -u --recursive --new-file v2.4.1/linux/net/ipv6/addrconf.c linux/net/ipv6/addrconf.c
--- v2.4.1/linux/net/ipv6/addrconf.c	Mon Jan  1 11:01:58 2001
+++ linux/net/ipv6/addrconf.c	Fri Feb  9 11:34:13 2001
@@ -6,7 +6,7 @@
  *	Pedro Roque		<roque@di.fc.ul.pt>	
  *	Alexey Kuznetsov	<kuznet@ms2.inr.ac.ru>
  *
- *	$Id: addrconf.c,v 1.59 2000/11/28 11:39:43 davem Exp $
+ *	$Id: addrconf.c,v 1.60 2001/01/01 02:38:30 davem Exp $
  *
  *	This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.4.1/linux/net/ipv6/raw.c linux/net/ipv6/raw.c
--- v2.4.1/linux/net/ipv6/raw.c	Tue Nov 28 21:53:45 2000
+++ linux/net/ipv6/raw.c	Fri Feb  9 11:29:44 2001
@@ -29,6 +29,7 @@
 #include <linux/if_arp.h>
 #include <linux/icmpv6.h>
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 
 #include <net/sock.h>
 #include <net/snmp.h>
diff -u --recursive --new-file v2.4.1/linux/net/ipx/af_ipx.c linux/net/ipx/af_ipx.c
--- v2.4.1/linux/net/ipx/af_ipx.c	Sat Feb  3 19:51:33 2001
+++ linux/net/ipx/af_ipx.c	Mon Feb 19 14:45:41 2001
@@ -64,6 +64,7 @@
  *	Revision 043:	Shared SKBs, don't mangle packets, some cleanups
  *			Arnaldo Carvalho de Melo <acme@conectiva.com.br>,
  *			December, 2000
+ *	Revision 044:	Call ipxitf_hold on NETDEV_UP (acme)
  *
  *	Protect the module by a MOD_INC_USE_COUNT/MOD_DEC_USE_COUNT
  *	pair. Also, now usage count is managed this way
@@ -443,19 +444,21 @@
 	struct net_device *dev = ptr;
 	ipx_interface *i, *tmp;
 
-	if (event != NETDEV_DOWN)
-		return NOTIFY_DONE;
+	if (event != NETDEV_DOWN && event != NETDEV_UP)
+		goto out;
 
 	spin_lock_bh(&ipx_interfaces_lock);
 	for (i = ipx_interfaces; i;) {
 		tmp = i->if_next;
 		if (i->if_dev == dev)
-			__ipxitf_put(i);
+			if (event == NETDEV_UP)
+				ipxitf_hold(i);
+			else
+				__ipxitf_put(i);
 		i = tmp;
-
 	}
 	spin_unlock_bh(&ipx_interfaces_lock);
-	return NOTIFY_DONE;
+out:	return NOTIFY_DONE;
 }
 
 static void ipxitf_def_skb_handler(struct sock *sock, struct sk_buff *skb)
@@ -1067,7 +1070,7 @@
 		intrfc->if_sklist 	= NULL;
 		intrfc->if_sknum 	= IPX_MIN_EPHEMERAL_SOCKET;
 		/* Setup primary if necessary */
-		if ((idef->ipx_special == IPX_PRIMARY))
+		if (idef->ipx_special == IPX_PRIMARY)
 			ipx_primary_net = intrfc;
 		intrfc->if_internal 	= 0;
 		intrfc->if_ipx_offset 	= dev->hard_header_len + datalink->header_length;
@@ -1191,6 +1194,7 @@
 		atomic_set(&intrfc->refcnt, 1);
 		MOD_INC_USE_COUNT;
 		ipxitf_insert(intrfc);
+		dev_hold(dev);
 	}
 
 	return intrfc;
@@ -1832,6 +1836,10 @@
 		return -EFAULT;
 
 	len = min(len, sizeof(int));
+	
+	if(len < 0)
+		return -EINVAL;
+		
 	if (put_user(len, optlen))
 		return -EFAULT;
 
@@ -2407,8 +2415,8 @@
  */
 
 static struct net_proto_family ipx_family_ops = {
-	PF_IPX,
-	ipx_create
+	family:		PF_IPX,
+	create:		ipx_create,
 };
 
 static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
@@ -2423,7 +2431,7 @@
 	poll:		datagram_poll,
 	ioctl:		ipx_ioctl,
 	listen:		sock_no_listen,
-	shutdown:	sock_no_shutdown, /* FIXME: We have to really support shutdown. */
+	shutdown:	sock_no_shutdown, /* FIXME: have to support shutdown */
 	setsockopt:	ipx_setsockopt,
 	getsockopt:	ipx_getsockopt,
 	sendmsg:	ipx_sendmsg,
@@ -2437,26 +2445,20 @@
 static struct packet_type ipx_8023_packet_type =
 
 {
-	__constant_htons(ETH_P_802_3),
-	NULL,		/* All devices */
-	ipx_rcv,
-	(void *) 1,	/* yap, I understand shared skbs :-) */
-	NULL,
+	type:		__constant_htons(ETH_P_802_3),
+	func:		ipx_rcv,
+	data:		(void *) 1,	/* yap, I understand shared skbs :-) */
 };
 
 static struct packet_type ipx_dix_packet_type =
 {
-	__constant_htons(ETH_P_IPX),
-	NULL,		/* All devices */
-	ipx_rcv,
-	(void *) 1,	/* yap, I understand shared skbs :-) */
-	NULL,
+	type:		__constant_htons(ETH_P_IPX),
+	func:		ipx_rcv,
+	data:		(void *) 1,	/* yap, I understand shared skbs :-) */
 };
 
-static struct notifier_block ipx_dev_notifier={
-	ipxitf_device_event,
-	NULL,
-	0
+static struct notifier_block ipx_dev_notifier = {
+	notifier_call:	ipxitf_device_event,
 };
 
 
@@ -2492,7 +2494,7 @@
 	proc_net_create("ipx_interface", 0, ipx_interface_get_info);
 	proc_net_create("ipx_route", 0, ipx_rt_get_info);
 #endif
-	printk(KERN_INFO "NET4: Linux IPX 0.43 for NET4.0\n");
+	printk(KERN_INFO "NET4: Linux IPX 0.44 for NET4.0\n");
 	printk(KERN_INFO "IPX Portions Copyright (c) 1995 Caldera, Inc.\n");
 	printk(KERN_INFO "IPX Portions Copyright (c) 2000 Conectiva, Inc.\n");
 	return 0;
diff -u --recursive --new-file v2.4.1/linux/net/irda/compressors/irda_deflate.c linux/net/irda/compressors/irda_deflate.c
--- v2.4.1/linux/net/irda/compressors/irda_deflate.c	Sat Nov 11 18:11:22 2000
+++ linux/net/irda/compressors/irda_deflate.c	Fri Feb  9 11:29:44 2001
@@ -51,7 +51,7 @@
 #include <linux/ptrace.h>
 #include <linux/ioport.h>
 #include <linux/in.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/vmalloc.h> 
 #include <linux/errno.h>
 #include <linux/string.h>	/* used in new tty drivers */
diff -u --recursive --new-file v2.4.1/linux/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c
--- v2.4.1/linux/net/irda/irlan/irlan_client.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/irlan/irlan_client.c	Thu Feb  8 13:08:38 2001
@@ -120,8 +120,9 @@
 			return;
 	}
 
-	/* Address may have changed! */
+	/* Addresses may have changed! */
 	self->saddr = saddr;
+	self->daddr = daddr;
 
 	if (self->disconnect_reason == LM_USER_REQUEST) {
 			IRDA_DEBUG(0, __FUNCTION__ "(), still stopped by user\n");
diff -u --recursive --new-file v2.4.1/linux/net/irda/irlan/irlan_eth.c linux/net/irda/irlan/irlan_eth.c
--- v2.4.1/linux/net/irda/irlan/irlan_eth.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/irlan/irlan_eth.c	Thu Feb  8 13:08:38 2001
@@ -61,6 +61,7 @@
 	dev->hard_start_xmit    = irlan_eth_xmit; 
 	dev->get_stats	        = irlan_eth_get_stats;
 	dev->set_multicast_list = irlan_eth_set_multicast_list;
+	dev->features          |= NETIF_F_DYNALLOC;
 
 	ether_setup(dev);
 	
diff -u --recursive --new-file v2.4.1/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.4.1/linux/net/irda/irlap.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/irlap.c	Fri Feb  9 11:29:44 2001
@@ -29,7 +29,7 @@
  ********************************************************************/
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/delay.h>
@@ -998,7 +998,7 @@
 }
 
 /*
- * Function irlap_apply_default_connection_parameters (void)
+ * Function irlap_apply_default_connection_parameters (void, now)
  *
  *    Use the default connection and transmission parameters
  * 
@@ -1010,14 +1010,16 @@
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
+	/* xbofs : Default value in NDM */
+	self->next_bofs   = 12;
+	self->bofs_count  = 12;
+
+	/* NDM Speed is 9600 */
 	irlap_change_speed(self, 9600, TRUE);
 
 	/* Set mbusy when going to NDM state */
 	irda_device_set_media_busy(self->netdev, TRUE);
 
-	/* Default value in NDM */
-	self->bofs_count = 12;
-
 	/* 
 	 * Generate random connection address for this session, which must
 	 * be 7 bits wide and different from 0x00 and 0xfe 
@@ -1056,23 +1058,31 @@
 }
 
 /*
- * Function irlap_apply_connection_parameters (qos)
+ * Function irlap_apply_connection_parameters (qos, now)
  *
  *    Initialize IrLAP with the negotiated QoS values
  *
+ * If 'now' is false, the speed and xbofs will be changed after the next
+ * frame is sent.
+ * If 'now' is true, the speed and xbofs is changed immediately
  */
-void irlap_apply_connection_parameters(struct irlap_cb *self) 
+void irlap_apply_connection_parameters(struct irlap_cb *self, int now) 
 {
 	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == LAP_MAGIC, return;);
 
-	irlap_change_speed(self, self->qos_tx.baud_rate.value, FALSE);
+	/* Set the negociated xbofs value */
+	self->next_bofs   = self->qos_tx.additional_bofs.value;
+	if(now)
+		self->bofs_count = self->next_bofs;
+
+	/* Set the negociated link speed (may need the new xbofs value) */
+	irlap_change_speed(self, self->qos_tx.baud_rate.value, now);
 
 	self->window_size = self->qos_tx.window_size.value;
 	self->window      = self->qos_tx.window_size.value;
-	self->bofs_count  = self->qos_tx.additional_bofs.value;
 
 	/*
 	 *  Calculate how many bytes it is possible to transmit before the
diff -u --recursive --new-file v2.4.1/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.4.1/linux/net/irda/irlap_event.c	Mon Nov 27 18:07:31 2000
+++ linux/net/irda/irlap_event.c	Thu Feb  8 15:14:08 2001
@@ -684,25 +684,26 @@
 
 		irlap_initiate_connection_state(self);
 
-#if 0
 		/* 
-		 * We are allowed to send two frames, but this may increase
-		 * the connect latency, so lets not do it for now.
+		 * Applying the parameters now will make sure we change speed
+		 * *after* we have sent the next frame
 		 */
-		irlap_send_ua_response_frame(self, &self->qos_rx);
-#endif
+		irlap_apply_connection_parameters(self, FALSE);
 
 		/* 
-		 * Applying the parameters now will make sure we change speed
-		 * after we have sent the next frame
+		 * Sending this frame will force a speed change after it has
+		 * been sent (i.e. the frame will be sent at 9600).
 		 */
-		irlap_apply_connection_parameters(self);
+		irlap_send_ua_response_frame(self, &self->qos_rx);
 
+#if 0
 		/* 
-		 * Sending this frame will force a speed change after it has
-		 * been sent
+		 * We are allowed to send two frames, but this may increase
+		 * the connect latency, so lets not do it for now.
 		 */
+		/* What the hell is this ? - Jean II */
 		irlap_send_ua_response_frame(self, &self->qos_rx);
+#endif
 
 		/*
 		 *  The WD-timer could be set to the duration of the P-timer 
@@ -794,8 +795,9 @@
 
 			irlap_qos_negotiate(self, skb);
 			
+			/* Send UA frame and then change link settings */
+			irlap_apply_connection_parameters(self, FALSE);
 			irlap_send_ua_response_frame(self, &self->qos_rx);
-			irlap_apply_connection_parameters(self);
 
 			irlap_next_state(self, LAP_NRM_S);
 			irlap_connect_confirm(self, skb);
@@ -827,10 +829,19 @@
 
 		irlap_qos_negotiate(self, skb);
 
-		irlap_apply_connection_parameters(self);
+		/* Set the new link setting *now* (before the rr frame) */
+		irlap_apply_connection_parameters(self, TRUE);
 		self->retry_count = 0;
 		
-		/* This frame will actually force the speed change */
+		/* Wait for turnaround time to give a chance to the other
+		 * device to be ready to receive us.
+		 * Note : the time to switch speed is typically larger
+		 * than the turnaround time, but as we don't have the other
+		 * side speed switch time, that's our best guess...
+		 * Jean II */
+		irlap_wait_min_turn_around(self, &self->qos_tx);
+
+		/* This frame will actually be sent at the new speed */
 		irlap_send_rr_frame(self, CMD_FRAME);
 
 		irlap_start_final_timer(self, self->final_timeout/2);
@@ -991,7 +1002,8 @@
 	case RECV_UA_RSP: /* FALLTHROUGH */
 	case RECV_DM_RSP:
 		del_timer(&self->final_timer);
-		
+
+		/* Set new link parameters */
 		irlap_apply_default_connection_parameters(self);
 
 		/* Always switch state before calling upper layers */
@@ -1944,10 +1956,13 @@
 		/* Always switch state before calling upper layers */
 		irlap_next_state(self, LAP_NDM);
 
+		/* Send disconnect response */
 		irlap_wait_min_turn_around(self, &self->qos_tx);
 		irlap_send_ua_response_frame(self, NULL);
+
 		del_timer(&self->wd_timer);
 		irlap_flush_all_queues(self);
+		/* Set default link parameters */
 		irlap_apply_default_connection_parameters(self);
 
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
@@ -2000,10 +2015,13 @@
 	case RECV_DISC_CMD:
 		/* Always switch state before calling upper layers */
 		irlap_next_state(self, LAP_NDM);
-		
+
+		/* Send disconnect response */
 		irlap_wait_min_turn_around(self, &self->qos_tx);
 		irlap_send_ua_response_frame(self, NULL);
+
 		del_timer(&self->wd_timer);
+		/* Set default link parameters */
 		irlap_apply_default_connection_parameters(self);
 
 		irlap_disconnect_indication(self, LAP_DISC_INDICATION);
diff -u --recursive --new-file v2.4.1/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.4.1/linux/net/irda/irlap_frame.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/irlap_frame.c	Thu Feb  8 15:14:08 2001
@@ -60,7 +60,7 @@
 	 */
 	cb->magic = LAP_MAGIC;
 	cb->mtt = self->mtt_required;
-	cb->speed = self->speed;
+	cb->next_speed = self->speed;
 
 	/* Reset */
 	self->mtt_required = 0;
@@ -70,10 +70,13 @@
 	 * force the negotiated minimum turnaround time 
 	 */
 	cb->xbofs = self->bofs_count;
+	cb->next_xbofs = self->next_bofs;
 	cb->xbofs_delay = self->xbofs_delay;
 	
 	/* Reset XBOF's delay (used only for getting min turn time) */
 	self->xbofs_delay = 0;
+	/* Put the correct xbofs value for the next packet */
+	self->bofs_count = self->next_bofs;
 }
 
 /*
diff -u --recursive --new-file v2.4.1/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.4.1/linux/net/irda/irlmp.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/irlmp.c	Fri Feb  9 11:29:44 2001
@@ -24,7 +24,7 @@
  ********************************************************************/
 
 #include <linux/config.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/skbuff.h>
 #include <linux/types.h>
diff -u --recursive --new-file v2.4.1/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.4.1/linux/net/irda/irttp.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/irttp.c	Thu Feb  8 15:14:08 2001
@@ -139,6 +139,15 @@
 	ASSERT(irttp != NULL, return NULL;);
 	ASSERT(irttp->magic == TTP_MAGIC, return NULL;);
 
+	/* The IrLMP spec (IrLMP 1.1 p10) says that we have the right to
+	 * use only 0x01-0x6F. Of course, we can use LSAP_ANY as well.
+	 * JeanII */
+	if((stsap_sel != LSAP_ANY) &&
+	   ((stsap_sel < 0x01) || (stsap_sel >= 0x70))) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), invalid tsap!\n");
+		return NULL;
+	}
+
 	self = kmalloc(sizeof(struct tsap_cb), GFP_ATOMIC);
 	if (self == NULL) {
 		IRDA_DEBUG(0, __FUNCTION__ "(), unable to kmalloc!\n");
@@ -1564,9 +1573,9 @@
 			       self->remote_credit);
 		len += sprintf(buf+len, "send credit: %d\n",
 			       self->send_credit);
-		len += sprintf(buf+len, "  tx packets: %d, ",
+		len += sprintf(buf+len, "  tx packets: %ld, ",
 			       self->stats.tx_packets);
-		len += sprintf(buf+len, "rx packets: %d, ",
+		len += sprintf(buf+len, "rx packets: %ld, ",
 			       self->stats.rx_packets);
 		len += sprintf(buf+len, "tx_queue len: %d ", 
 			       skb_queue_len(&self->tx_queue));
diff -u --recursive --new-file v2.4.1/linux/net/irda/qos.c linux/net/irda/qos.c
--- v2.4.1/linux/net/irda/qos.c	Sat Nov 11 18:11:23 2000
+++ linux/net/irda/qos.c	Thu Feb  8 15:14:08 2001
@@ -70,10 +70,6 @@
 				       int get);
 static int irlap_param_min_turn_time(void *instance, irda_param_t *param, 
 				     int get);
-static int value_index(__u32 value, __u32 *array, int size);
-static __u32 byte_value(__u8 byte, __u32 *array);
-static __u32 index_value(int index, __u32 *array);
-static int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field);
 
 __u32 min_turn_times[]  = { 10000, 5000, 1000, 500, 100, 50, 10, 0 }; /* us */
 __u32 baud_rates[]      = { 2400, 9600, 19200, 38400, 57600, 115200, 576000, 
@@ -130,6 +126,98 @@
 
 static pi_param_info_t irlap_param_info = { pi_major_call_table, 2, 0x7f, 7 };
 
+/* ---------------------- LOCAL SUBROUTINES ---------------------- */
+/* Note : we start with a bunch of local subroutines.
+ * As the compiler is "one pass", this is the only way to get them to
+ * inline properly...
+ * Jean II
+ */
+/*
+ * Function value_index (value, array, size)
+ *
+ *    Returns the index to the value in the specified array
+ */
+static inline int value_index(__u32 value, __u32 *array, int size)
+{
+	int i;
+	
+	for (i=0; i < size; i++)
+		if (array[i] == value)
+			break;
+	return i;
+}
+
+/*
+ * Function index_value (index, array)
+ *
+ *    Returns value to index in array, easy!
+ *
+ */
+static inline __u32 index_value(int index, __u32 *array) 
+{
+	return array[index];
+}
+
+/*
+ * Function msb_index (word)
+ *
+ *    Returns index to most significant bit (MSB) in word
+ *
+ */
+int msb_index (__u16 word) 
+{
+	__u16 msb = 0x8000;
+	int index = 15;   /* Current MSB */
+	
+	while (msb) {
+		if (word & msb)
+			break;   /* Found it! */
+		msb >>=1;
+		index--;
+	}
+	return index;
+}
+
+static inline __u32 byte_value(__u8 byte, __u32 *array) 
+{
+	int index;
+
+	ASSERT(array != NULL, return -1;);
+
+	index = msb_index(byte);
+
+	return index_value(index, array);
+}
+
+/*
+ * Function value_lower_bits (value, array)
+ *
+ *    Returns a bit field marking all possibility lower than value.
+ *    We may need a "value_higher_bits" in the future...
+ */
+static inline int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
+{
+	int	i;
+	__u16	mask = 0x1;
+	__u16	result = 0x0;
+
+	for (i=0; i < size; i++) {
+		/* Add the current value to the bit field, shift mask */
+		result |= mask;
+		mask <<= 1;
+		/* Finished ? */
+		if (array[i] >= value)
+			break;
+	}
+	/* Send back a valid index */
+	if(i >= size)
+	  i = size - 1;	/* Last item */
+	*field = result;
+	return i;
+}
+
+/* -------------------------- MAIN CALLS -------------------------- */
+
 /*
  * Function irda_qos_compute_intersection (qos, new)
  *
@@ -594,99 +682,6 @@
 		   line_capacity);
 	
 	return line_capacity;			       		  
-}
-
-__u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time)
-{
-	__u32 bytes;
-	
-	bytes = speed * min_turn_time / 10000000;
-	
-	return bytes;
-}
-
-static __u32 byte_value(__u8 byte, __u32 *array) 
-{
-	int index;
-
-	ASSERT(array != NULL, return -1;);
-
-	index = msb_index(byte);
-
-	return index_value(index, array);
-}
-
-/*
- * Function msb_index (word)
- *
- *    Returns index to most significant bit (MSB) in word
- *
- */
-int msb_index (__u16 word) 
-{
-	__u16 msb = 0x8000;
-	int index = 15;   /* Current MSB */
-	
-	while (msb) {
-		if (word & msb)
-			break;   /* Found it! */
-		msb >>=1;
-		index--;
-	}
-	return index;
-}
-
-/*
- * Function value_index (value, array, size)
- *
- *    Returns the index to the value in the specified array
- */
-static int value_index(__u32 value, __u32 *array, int size)
-{
-	int i;
-	
-	for (i=0; i < size; i++)
-		if (array[i] == value)
-			break;
-	return i;
-}
-
-/*
- * Function index_value (index, array)
- *
- *    Returns value to index in array, easy!
- *
- */
-static __u32 index_value(int index, __u32 *array) 
-{
-	return array[index];
-}
-
-/*
- * Function value_lower_bits (value, array)
- *
- *    Returns a bit field marking all possibility lower than value.
- *    We may need a "value_higher_bits" in the future...
- */
-static int value_lower_bits(__u32 value, __u32 *array, int size, __u16 *field)
-{
-	int	i;
-	__u16	mask = 0x1;
-	__u16	result = 0x0;
-
-	for (i=0; i < size; i++) {
-		/* Add the current value to the bit field, shift mask */
-		result |= mask;
-		mask <<= 1;
-		/* Finished ? */
-		if (array[i] >= value)
-			break;
-	}
-	/* Send back a valid index */
-	if(i >= size)
-	  i = size - 1;	/* Last item */
-	*field = result;
-	return i;
 }
 
 void irda_qos_bits_to_value(struct qos_info *qos)
diff -u --recursive --new-file v2.4.1/linux/net/khttpd/misc.c linux/net/khttpd/misc.c
--- v2.4.1/linux/net/khttpd/misc.c	Thu Sep  2 11:47:20 1999
+++ linux/net/khttpd/misc.c	Fri Feb  9 11:29:44 2001
@@ -26,7 +26,7 @@
 
 #include <linux/ctype.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.4.1/linux/net/khttpd/rfc.c linux/net/khttpd/rfc.c
--- v2.4.1/linux/net/khttpd/rfc.c	Mon Aug 23 10:41:25 1999
+++ linux/net/khttpd/rfc.c	Fri Feb  9 11:29:44 2001
@@ -28,7 +28,7 @@
 
 #include <linux/ctype.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.4.1/linux/net/khttpd/rfc_time.c linux/net/khttpd/rfc_time.c
--- v2.4.1/linux/net/khttpd/rfc_time.c	Wed Aug 18 09:51:31 1999
+++ linux/net/khttpd/rfc_time.c	Fri Feb  9 11:29:44 2001
@@ -27,7 +27,7 @@
 
 #include <linux/time.h>
 #include <linux/kernel.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/ctype.h>
 
 
diff -u --recursive --new-file v2.4.1/linux/net/khttpd/security.c linux/net/khttpd/security.c
--- v2.4.1/linux/net/khttpd/security.c	Wed Jul  5 11:31:02 2000
+++ linux/net/khttpd/security.c	Fri Feb  9 11:29:44 2001
@@ -27,7 +27,7 @@
 #include <linux/kernel.h>
 
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.4.1/linux/net/khttpd/sysctl.c linux/net/khttpd/sysctl.c
--- v2.4.1/linux/net/khttpd/sysctl.c	Mon Aug 23 13:44:03 1999
+++ linux/net/khttpd/sysctl.c	Fri Feb  9 11:34:13 2001
@@ -25,7 +25,7 @@
 
 #include <linux/kernel.h>
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
@@ -259,7 +259,7 @@
 static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
 		  void *buffer, size_t *lenp)
 {
-	int len;
+	size_t len;
 	char *p, c=0;
 	char String[256];
 	
diff -u --recursive --new-file v2.4.1/linux/net/khttpd/userspace.c linux/net/khttpd/userspace.c
--- v2.4.1/linux/net/khttpd/userspace.c	Wed Feb  9 20:08:09 2000
+++ linux/net/khttpd/userspace.c	Fri Feb  9 11:29:44 2001
@@ -35,7 +35,7 @@
 #include <linux/kernel.h>
 
 #include <linux/errno.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/net.h>
 #include <linux/sched.h>
 #include <linux/skbuff.h>
diff -u --recursive --new-file v2.4.1/linux/net/lapb/Makefile linux/net/lapb/Makefile
--- v2.4.1/linux/net/lapb/Makefile	Fri Dec 29 14:07:24 2000
+++ linux/net/lapb/Makefile	Fri Feb  9 11:34:13 2001
@@ -17,5 +17,3 @@
 
 include $(TOPDIR)/Rules.make
 
-tar:
-		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.4.1/linux/net/lapb/lapb_iface.c linux/net/lapb/lapb_iface.c
--- v2.4.1/linux/net/lapb/lapb_iface.c	Sat Nov 11 19:02:40 2000
+++ linux/net/lapb/lapb_iface.c	Fri Feb 16 16:06:17 2001
@@ -16,7 +16,6 @@
  */
  
 #include <linux/config.h>
-#if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -41,7 +40,7 @@
 #include <linux/init.h>
 #include <net/lapb.h>
 
-static lapb_cb *volatile lapb_list = NULL;
+static lapb_cb *volatile lapb_list /* = NULL initially */;
 
 /*
  *	Free an allocated lapb control block. This is done to centralise
@@ -271,7 +270,7 @@
 
 	return LAPB_OK;
 }
-	
+
 int lapb_disconnect_request(void *token)
 {
 	lapb_cb *lapb;
@@ -399,18 +398,15 @@
 EXPORT_SYMBOL(lapb_data_request);
 EXPORT_SYMBOL(lapb_data_received);
 
+static const char banner[] __initdata = KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n";
+
 static int __init lapb_init(void)
 {
-	printk(KERN_INFO "NET4: LAPB for Linux. Version 0.01 for NET4.0\n");
+	printk(banner);
 	return 0;
 }
 
-#ifdef MODULE
 MODULE_AUTHOR("Jonathan Naylor <g4klx@g4klx.demon.co.uk>");
 MODULE_DESCRIPTION("The X.25 Link Access Procedure B link layer protocol");
-#endif
-
 
 module_init(lapb_init);
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/net/lapb/lapb_in.c linux/net/lapb/lapb_in.c
--- v2.4.1/linux/net/lapb/lapb_in.c	Sat Nov 11 19:02:40 2000
+++ linux/net/lapb/lapb_in.c	Fri Feb  9 11:34:13 2001
@@ -15,8 +15,6 @@
  *	2000-10-29	Henner Eisen	lapb_data_indication() return status.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -641,5 +639,3 @@
 
 	lapb_kick(lapb);
 }
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/net/lapb/lapb_out.c linux/net/lapb/lapb_out.c
--- v2.4.1/linux/net/lapb/lapb_out.c	Tue Feb 10 13:07:49 1998
+++ linux/net/lapb/lapb_out.c	Fri Feb  9 11:34:13 2001
@@ -14,8 +14,6 @@
  *	LAPB 002	Jonathan Naylor	New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -223,5 +221,3 @@
 	if (type == LAPB_COMMAND && pf)
 		lapb_enquiry_response(lapb);
 }
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/net/lapb/lapb_subr.c linux/net/lapb/lapb_subr.c
--- v2.4.1/linux/net/lapb/lapb_subr.c	Tue Feb 10 13:07:49 1998
+++ linux/net/lapb/lapb_subr.c	Fri Feb  9 11:34:13 2001
@@ -13,8 +13,6 @@
  *	LAPB 001	Jonathan Naylor	Started Coding
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -281,5 +279,3 @@
 
 	lapb_transmit_buffer(lapb, skb, LAPB_RESPONSE);
 }
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/net/lapb/lapb_timer.c linux/net/lapb/lapb_timer.c
--- v2.4.1/linux/net/lapb/lapb_timer.c	Thu May  4 11:26:52 2000
+++ linux/net/lapb/lapb_timer.c	Fri Feb  9 11:34:13 2001
@@ -14,8 +14,6 @@
  *	LAPB 002	Jonathan Naylor	New timer architecture.
  */
 
-#include <linux/config.h>
-#if defined(CONFIG_LAPB) || defined(CONFIG_LAPB_MODULE)
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/socket.h>
@@ -189,5 +187,3 @@
 
 	lapb_start_t1timer(lapb);
 }
-
-#endif
diff -u --recursive --new-file v2.4.1/linux/net/netlink/af_netlink.c linux/net/netlink/af_netlink.c
--- v2.4.1/linux/net/netlink/af_netlink.c	Sat Nov 11 19:02:41 2000
+++ linux/net/netlink/af_netlink.c	Fri Feb  9 11:29:44 2001
@@ -29,7 +29,7 @@
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
diff -u --recursive --new-file v2.4.1/linux/net/netlink/netlink_dev.c linux/net/netlink/netlink_dev.c
--- v2.4.1/linux/net/netlink/netlink_dev.c	Mon Oct 16 12:58:51 2000
+++ linux/net/netlink/netlink_dev.c	Fri Feb  9 11:29:44 2001
@@ -20,7 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/major.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/skbuff.h>
 #include <linux/netlink.h>
 #include <linux/poll.h>
diff -u --recursive --new-file v2.4.1/linux/net/netrom/Makefile linux/net/netrom/Makefile
--- v2.4.1/linux/net/netrom/Makefile	Fri Dec 29 14:07:24 2000
+++ linux/net/netrom/Makefile	Fri Feb  9 11:34:13 2001
@@ -17,5 +17,3 @@
 
 include $(TOPDIR)/Rules.make
 
-tar:
-		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.4.1/linux/net/netsyms.c linux/net/netsyms.c
--- v2.4.1/linux/net/netsyms.c	Fri Oct 27 11:03:14 2000
+++ linux/net/netsyms.c	Fri Feb  9 11:29:44 2001
@@ -17,6 +17,7 @@
 #include <linux/trdevice.h>
 #include <linux/fcdevice.h>
 #include <linux/ioport.h>
+#include <linux/tty.h>
 #include <net/neighbour.h>
 #include <net/snmp.h>
 #include <net/dst.h>
diff -u --recursive --new-file v2.4.1/linux/net/packet/af_packet.c linux/net/packet/af_packet.c
--- v2.4.1/linux/net/packet/af_packet.c	Mon Jan  1 11:01:58 2001
+++ linux/net/packet/af_packet.c	Fri Feb  9 11:29:44 2001
@@ -62,6 +62,7 @@
 #include <linux/timer.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 #include <linux/proc_fs.h>
 #include <linux/poll.h>
 #include <linux/module.h>
diff -u --recursive --new-file v2.4.1/linux/net/rose/Makefile linux/net/rose/Makefile
--- v2.4.1/linux/net/rose/Makefile	Fri Dec 29 14:07:24 2000
+++ linux/net/rose/Makefile	Fri Feb  9 11:34:13 2001
@@ -17,5 +17,3 @@
 
 include $(TOPDIR)/Rules.make
 
-tar:
-		tar -cvf /dev/f1 .
diff -u --recursive --new-file v2.4.1/linux/net/sched/sch_atm.c linux/net/sched/sch_atm.c
--- v2.4.1/linux/net/sched/sch_atm.c	Tue Mar 21 23:38:27 2000
+++ linux/net/sched/sch_atm.c	Fri Feb  9 11:34:13 2001
@@ -5,6 +5,8 @@
 
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/string.h>
+#include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/interrupt.h>
 #include <linux/atmdev.h>
diff -u --recursive --new-file v2.4.1/linux/net/sched/sch_dsmark.c linux/net/sched/sch_dsmark.c
--- v2.4.1/linux/net/sched/sch_dsmark.c	Sat Feb  3 19:51:33 2001
+++ linux/net/sched/sch_dsmark.c	Fri Feb  9 11:34:13 2001
@@ -6,6 +6,8 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/string.h>
+#include <linux/errno.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h> /* for pkt_sched */
 #include <linux/rtnetlink.h>
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/auth.c linux/net/sunrpc/auth.c
--- v2.4.1/linux/net/sunrpc/auth.c	Sat Feb  3 19:51:33 2001
+++ linux/net/sunrpc/auth.c	Fri Feb  9 11:29:44 2001
@@ -8,7 +8,7 @@
 
 #include <linux/types.h>
 #include <linux/sched.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 #include <linux/socket.h>
 #include <linux/sunrpc/clnt.h>
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/auth_null.c linux/net/sunrpc/auth_null.c
--- v2.4.1/linux/net/sunrpc/auth_null.c	Fri Oct 13 12:11:26 2000
+++ linux/net/sunrpc/auth_null.c	Fri Feb  9 11:29:44 2001
@@ -7,7 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/utsname.h>
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/auth_unix.c linux/net/sunrpc/auth_unix.c
--- v2.4.1/linux/net/sunrpc/auth_unix.c	Mon Sep 25 13:13:53 2000
+++ linux/net/sunrpc/auth_unix.c	Fri Feb  9 11:29:44 2001
@@ -7,7 +7,7 @@
  */
 
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/socket.h>
 #include <linux/in.h>
 #include <linux/sunrpc/clnt.h>
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/clnt.c linux/net/sunrpc/clnt.c
--- v2.4.1/linux/net/sunrpc/clnt.c	Tue Nov 28 22:34:01 2000
+++ linux/net/sunrpc/clnt.c	Fri Feb  9 11:29:44 2001
@@ -25,7 +25,7 @@
 
 #include <linux/types.h>
 #include <linux/mm.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/in.h>
 #include <linux/utsname.h>
 
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/sched.c linux/net/sunrpc/sched.c
--- v2.4.1/linux/net/sunrpc/sched.c	Tue Dec  5 12:29:39 2000
+++ linux/net/sunrpc/sched.c	Fri Feb  9 11:29:44 2001
@@ -14,7 +14,7 @@
 #define __KERNEL_SYSCALLS__
 #include <linux/sched.h>
 #include <linux/interrupt.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/unistd.h>
 #include <linux/smp.h>
 #include <linux/smp_lock.h>
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/svcsock.c linux/net/sunrpc/svcsock.c
--- v2.4.1/linux/net/sunrpc/svcsock.c	Mon Oct 30 14:41:41 2000
+++ linux/net/sunrpc/svcsock.c	Fri Feb  9 11:29:44 2001
@@ -28,13 +28,14 @@
 #include <linux/udp.h>
 #include <linux/version.h>
 #include <linux/unistd.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <net/checksum.h>
 #include <net/ip.h>
 #include <asm/uaccess.h>
+#include <asm/ioctls.h>
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
diff -u --recursive --new-file v2.4.1/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.4.1/linux/net/sunrpc/xprt.c	Tue Nov 28 22:34:01 2000
+++ linux/net/sunrpc/xprt.c	Fri Feb  9 11:29:44 2001
@@ -47,7 +47,7 @@
 
 #include <linux/version.h>
 #include <linux/types.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/capability.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
diff -u --recursive --new-file v2.4.1/linux/net/unix/af_unix.c linux/net/unix/af_unix.c
--- v2.4.1/linux/net/unix/af_unix.c	Sat Feb  3 19:51:33 2001
+++ linux/net/unix/af_unix.c	Fri Feb  9 11:34:13 2001
@@ -8,7 +8,7 @@
  *		as published by the Free Software Foundation; either version
  *		2 of the License, or (at your option) any later version.
  *
- * Version:	$Id: af_unix.c,v 1.109 2001/01/06 00:42:23 davem Exp $
+ * Version:	$Id: af_unix.c,v 1.111 2001/02/02 11:37:28 davem Exp $
  *
  * Fixes:
  *		Linus Torvalds	:	Assorted bug cures.
@@ -96,7 +96,7 @@
 #include <linux/net.h>
 #include <linux/in.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <asm/uaccess.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
@@ -1316,9 +1316,12 @@
 		size=len-sent;
 
 		/* Keep two messages in the pipe so it schedules better */
-		if (size > sk->sndbuf/2 - 16)
-			size = sk->sndbuf/2 - 16;
+		if (size > sk->sndbuf/2 - 64)
+			size = sk->sndbuf/2 - 64;
 
+		if (size > (128 * 1024) / 2)
+			size = (128 * 1024) / 2;
+			
 		/*
 		 *	Keep to page sized kmalloc()'s as various people
 		 *	have suggested. Big mallocs stress the vm too
diff -u --recursive --new-file v2.4.1/linux/net/unix/garbage.c linux/net/unix/garbage.c
--- v2.4.1/linux/net/unix/garbage.c	Fri Nov 17 11:36:27 2000
+++ linux/net/unix/garbage.c	Fri Feb  9 11:29:44 2001
@@ -71,7 +71,7 @@
 #include <linux/un.h>
 #include <linux/net.h>
 #include <linux/fs.h>
-#include <linux/malloc.h>
+#include <linux/slab.h>
 #include <linux/skbuff.h>
 #include <linux/netdevice.h>
 #include <linux/file.h>
diff -u --recursive --new-file v2.4.1/linux/net/wanrouter/wanmain.c linux/net/wanrouter/wanmain.c
--- v2.4.1/linux/net/wanrouter/wanmain.c	Thu Feb 17 09:18:47 2000
+++ linux/net/wanrouter/wanmain.c	Fri Feb  9 11:29:44 2001
@@ -41,7 +41,7 @@
 #include <linux/errno.h>	/* return codes */
 #include <linux/kernel.h>
 #include <linux/module.h>	/* support for loadable modules */
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/mm.h>		/* verify_area(), etc. */
 #include <linux/string.h>	/* inline mem*, str* functions */
 #include <linux/vmalloc.h>	/* vmalloc, vfree */
diff -u --recursive --new-file v2.4.1/linux/net/wanrouter/wanproc.c linux/net/wanrouter/wanproc.c
--- v2.4.1/linux/net/wanrouter/wanproc.c	Sat Feb 26 20:33:10 2000
+++ linux/net/wanrouter/wanproc.c	Fri Feb  9 11:34:13 2001
@@ -13,6 +13,7 @@
 *		as published by the Free Software Foundation; either version
 *		2 of the License, or (at your option) any later version.
 * ============================================================================
+* Jan 20, 2001  Arnaldo C.Melo  Fix leak on error in router_proc_read, cleanups
 * Jun 02, 1999  Gideon Hack	Updates for Linux 2.2.X kernels.
 * Jun 29, 1997	Alan Cox	Merged with 1.0.3 vendor code
 * Jan 29, 1997	Gene Kozin	v1.0.1. Implemented /proc read routines
@@ -25,7 +26,7 @@
 #include <linux/stddef.h>	/* offsetof(), etc. */
 #include <linux/errno.h>	/* return codes */
 #include <linux/kernel.h>
-#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#include <linux/slab.h>	/* kmalloc(), kfree() */
 #include <linux/mm.h>		/* verify_area(), etc. */
 #include <linux/string.h>	/* inline mem*, str* functions */
 #include <linux/init.h>		/* __init et al. */
@@ -43,23 +44,9 @@
 #ifndef	min
 #define min(a,b) (((a)<(b))?(a):(b))
 #endif
-#ifndef	max
-#define max(a,b) (((a)>(b))?(a):(b))
-#endif
 
 #define	PROC_BUFSZ	4000	/* buffer size for printing proc info */
 
-
-/****** Data Types **********************************************************/
-
-typedef struct wan_stat_entry
-{
-	struct wan_stat_entry *next;
-	char *description;		/* description string */
-	void *data;			/* -> data */
-	unsigned data_type;		/* data type */
-} wan_stat_entry_t;
-
 /****** Function Prototypes *************************************************/
 
 #ifdef CONFIG_PROC_FS
@@ -78,7 +65,7 @@
 
 /*
  *	Structures for interfacing with the /proc filesystem.
- *	Router creates its own directory /proc/net/router with the folowing
+ *	Router creates its own directory /proc/net/wanrouter with the folowing
  *	entries:
  *	config		device configuration
  *	status		global device statistics
@@ -86,7 +73,7 @@
  */
 
 /*
- *	Generic /proc/net/router/<file> file and inode operations 
+ *	Generic /proc/net/wanrouter/<file> file and inode operations 
  */
 static struct file_operations router_fops =
 {
@@ -99,7 +86,7 @@
 };
 
 /*
- *	/proc/net/router/<device> file operations
+ *	/proc/net/wanrouter/<device> file operations
  */
 
 static struct file_operations wandev_fops =
@@ -109,7 +96,7 @@
 };
 
 /*
- *	/proc/net/router 
+ *	/proc/net/wanrouter 
  */
 
 static struct proc_dir_entry *proc_router;
@@ -251,13 +238,15 @@
 	offs = file->f_pos;
 	if (offs < pos) {
 		len = min(pos - offs, count);
-		if(copy_to_user(buf, (page + offs), len))
-			return -EFAULT;
+		if(copy_to_user(buf, (page + offs), len)) {
+			len = -EFAULT;
+			goto out;
+		}
 		file->f_pos += len;
 	}
 	else
 		len = 0;
-	kfree(page);
+out:	kfree(page);
 	return len;
 }
 
diff -u --recursive --new-file v2.4.1/linux/scripts/Lindent linux/scripts/Lindent
--- v2.4.1/linux/scripts/Lindent	Wed Dec 31 16:00:00 1969
+++ linux/scripts/Lindent	Thu Feb  8 16:32:44 2001
@@ -0,0 +1,2 @@
+#!/bin/bash
+indent -kr -i8 -ts8 -br -ce -bap -sob -l80 -pcs -cs -ss -bs -di1 -nbc -lp -psl $@
diff -u --recursive --new-file v2.4.1/linux/scripts/lxdialog/checklist.c linux/scripts/lxdialog/checklist.c
--- v2.4.1/linux/scripts/lxdialog/checklist.c	Mon Feb  1 12:03:20 1999
+++ linux/scripts/lxdialog/checklist.c	Sun Feb  4 10:05:30 2001
@@ -51,6 +51,10 @@
     mvwaddch(win, choice, item_x, item[0]);
     wattrset (win, selected ? item_selected_attr : item_attr);
     waddstr (win, (char *)item+1);
+    if (selected) {
+    	wmove (win, choice, check_x+1);
+    	wrefresh (win);
+    }
 }
 
 /*
diff -u --recursive --new-file v2.4.1/linux/scripts/lxdialog/menubox.c linux/scripts/lxdialog/menubox.c
--- v2.4.1/linux/scripts/lxdialog/menubox.c	Mon Feb  1 12:03:20 1999
+++ linux/scripts/lxdialog/menubox.c	Sun Feb  4 10:05:30 2001
@@ -91,6 +91,10 @@
     	wattrset (win, selected ? tag_key_selected_attr : tag_key_attr);
     	mvwaddch(win, choice, item_x+j, menu_item[j]);
     }
+    if (selected) {
+	wmove (win, choice, item_x+1);
+	wrefresh (win);
+    }
 }
 
 /*
@@ -267,9 +271,11 @@
 		 box_y, box_x+item_x+1, menu_height);
 
     print_buttons (dialog, height, width, 0);
+    wmove (menu, choice, item_x+1);
+    wrefresh (menu);
 
     while (key != ESC) {
-	key = wgetch(dialog);
+	key = wgetch(menu);
 
 	if (key < 256 && isalpha(key)) key = tolower(key);
 
@@ -372,8 +378,8 @@
             print_arrows(dialog, item_no, scroll,
                          box_y, box_x+item_x+1, menu_height);
 
-            wnoutrefresh (menu);
-            wrefresh (dialog);
+            wnoutrefresh (dialog);
+            wrefresh (menu);
 
 	    continue;		/* wait for another key press */
         }
@@ -386,7 +392,7 @@
 			? 2 : (button > 2 ? 0 : button);
 
 	    print_buttons(dialog, height, width, button);
-	    wrefresh (dialog);
+	    wrefresh (menu);
 	    break;
 	case ' ':
 	case 's':
diff -u --recursive --new-file v2.4.1/linux/scripts/makelst linux/scripts/makelst
--- v2.4.1/linux/scripts/makelst	Mon Sep 18 14:59:23 2000
+++ linux/scripts/makelst	Thu Feb  8 16:32:44 2001
@@ -2,7 +2,8 @@
 # A script to dump mixed source code & assembly
 # with correct relocations from System.map
 # Requires the following lines in Rules.make.
-#
+# Author(s): DJ Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) 
+#            William Stearns <wstearns@pobox.com>
 #%.lst: %.c
 #	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(CFLAGS_$@) -g -c -o $*.o $<
 #	$(TOPDIR)/scripts/makelst $* $(TOPDIR) $(OBJDUMP)
@@ -16,6 +17,6 @@
 t3=`grep $t2 $2/System.map`
 t4=`echo $t3 | gawk '{ print $1 }'`
 t5=`echo $t1 | gawk '{ print $1 }'`
-t6=`echo $t4 - $t5 | sed s/a/A/g | sed s/b/B/g | sed s/c/C/g | sed s/d/D/g | sed s/e/E/g | sed s/f/F/g`
+t6=`echo $t4 - $t5 | sed -e s/a/A/g -e s/b/B/g -e s/c/C/g -e s/d/D/g -e s/e/E/g -e s/f/F/g`
 t7=`( echo  ibase=16 ; echo $t6 ) | bc`
 $3 --source --adjust-vma=$t7 $2/$1.o > $2/$1.lst
