lines    added  deleted
linux/CREDITS                             :      14        8        0
linux/Documentation/Changes               :     315       88       50
linux/Documentation/Configure.help        :     104       52        8
linux/Documentation/sgi-visws.txt         :      13       13        0
linux/MAINTAINERS                         :      13        7        0
linux/Makefile                            :       8        1        1
linux/arch/alpha/kernel/osf_sys.c         :     105       44       22
linux/arch/alpha/kernel/process.c         :      13        1        5
linux/arch/alpha/kernel/time.c            :      62       19        8
linux/arch/arm/kernel/time.c              :      23        6        4
linux/arch/i386/config.in                 :      17       11        0
linux/arch/i386/defconfig                 :       9        3        0
linux/arch/i386/kernel/Makefile           :      16        9        1
linux/arch/i386/kernel/bios32.c           :      19        5        1
linux/arch/i386/kernel/entry.S            :       8        1        1
linux/arch/i386/kernel/i386_ksyms.c       :       7        1        0
linux/arch/i386/kernel/irq.c              :     477      223      128
linux/arch/i386/kernel/irq.h              :      42        7        7
linux/arch/i386/kernel/process.c          :      21       15        0
linux/arch/i386/kernel/setup.c            :     151      131        0
linux/arch/i386/kernel/smp.c              :      92       22        2
linux/arch/i386/kernel/time.c             :      87       35        7
linux/arch/i386/kernel/traps.c            :     135      105        3
linux/arch/i386/kernel/visws_apic.c       :     407      407        0
linux/arch/m68k/Makefile                  :      21        9        2
linux/arch/m68k/amiga/config.c            :      15        0        2
linux/arch/m68k/atari/atakeyb.c           :       8        0        5
linux/arch/m68k/atari/config.c            :      15        0        2
linux/arch/m68k/config.in                 :      50       11       10
linux/arch/m68k/defconfig                 :      86       28        4
linux/arch/m68k/fpsp040/skeleton.S        :      23        4        3
linux/arch/m68k/hp300/config.c            :      19        0        6
linux/arch/m68k/ifpsp060/iskeleton.S      :      23        4        3
linux/arch/m68k/kernel/entry.S            :     287       53       48
linux/arch/m68k/kernel/head.S             :    4275     3002      889
linux/arch/m68k/kernel/m68k_defs.c        :      81       67        3
linux/arch/m68k/kernel/m68k_ksyms.c       :      33        5        3
linux/arch/m68k/kernel/process.c          :     109       56       13
linux/arch/m68k/kernel/ptrace.c           :      18        6        3
linux/arch/m68k/kernel/setup.c            :      36        4        4
linux/arch/m68k/kernel/sys_m68k.c         :     133       37       48
linux/arch/m68k/kernel/time.c             :      92       33       16
linux/arch/m68k/mac/config.c              :      36        1        8
linux/arch/m68k/mac/debug.c               :       8        1        1
linux/arch/m68k/mac/mackeyb.c             :       8        0        5
linux/arch/m68k/mm/init.c                 :     406      127      160
linux/arch/m68k/mm/kmap.c                 :     801      239      457
linux/arch/m68k/mm/memory.c               :     191       27      109
linux/arch/mips/kernel/time.c             :      63       21        8
linux/arch/ppc/kernel/time.c              :      21        8        0
linux/arch/sparc/kernel/time.c            :      61       22        8
linux/arch/sparc/mm/srmmu.c               :      44        5        5
linux/arch/sparc64/kernel/time.c          :      29        9        7
linux/drivers/block/ide-cd.c              :      70       28        5
linux/drivers/block/ide-cd.h              :      82       39        9
linux/drivers/cdrom/mcdx.h                :       7        0        1
linux/drivers/char/console.c              :      17        3        1
linux/drivers/char/cyclades.c             :     108       19       25
linux/drivers/char/mem.c                  :      21        1        8
linux/drivers/char/pc_keyb.c              :       8        1        1
linux/drivers/char/tty_ioctl.c            :      13        2        1
linux/drivers/char/videodev.c             :       7        1        0
linux/drivers/isdn/isdn_common.c          :     447      130       78
linux/drivers/isdn/isdn_common.h          :      19        5        1
linux/drivers/isdn/isdn_net.c             :     106       29       13
linux/drivers/isdn/isdn_ppp.c             :      68       14       11
linux/drivers/misc/parport_ieee1284.c     :      33       13        8
linux/drivers/net/3c59x.c                 :       8        1        1
linux/drivers/net/Config.in               :      19        2        4
linux/drivers/net/at1700.c                :     424      142       74
linux/drivers/net/fmv18x.c                :     200       62       32
linux/drivers/net/irda/Config.in          :       5        1        0
linux/drivers/net/irda/Makefile           :      14        8        0
linux/drivers/net/irda/actisys.c          :      78        9        9
linux/drivers/net/irda/esi.c              :      72        9       10
linux/drivers/net/irda/irport.c           :     401      143      100
linux/drivers/net/irda/irtty.c            :      35        3        3
linux/drivers/net/irda/pc87108.c          :      67       13       11
linux/drivers/net/irda/tekram.c           :      59        8        6
linux/drivers/net/irda/uircc.c            :     915      915        0
linux/drivers/net/tulip.c                 :      16        1        2
linux/drivers/pci/pci.c                   :      21        8        0
linux/drivers/pnp/parport_probe.c         :      15        2        2
linux/drivers/scsi/aha152x.c              :       7        1        0
linux/drivers/scsi/ini9100u.c             :     102       31       55
linux/drivers/scsi/ini9100u.h             :       7        1        0
linux/drivers/sound/ad1848.c              :       8        1        1
linux/drivers/video/Config.in             :      91       19        9
linux/drivers/video/Makefile              :      23        5        5
linux/drivers/video/amifb.c               :      65       18        6
linux/drivers/video/atafb.c               :      78       10       11
linux/drivers/video/atyfb.c               :     380      119       41
linux/drivers/video/clgenfb.c             :      35        4        6
linux/drivers/video/creatorfb.c           :     122       24        9
linux/drivers/video/cvisionppc.h          :      51       51        0
linux/drivers/video/cvppcfb.c             :     606        0      606
linux/drivers/video/cyberfb.c             :       9        1        2
linux/drivers/video/fbcon-iplan2p2.c      :      24        2        2
linux/drivers/video/fbcon-iplan2p4.c      :      24        2        2
linux/drivers/video/fbcon-iplan2p8.c      :      24        2        2
linux/drivers/video/fbcon.c               :     107       27       13
linux/drivers/video/fbmem.c               :      21        4        4
linux/drivers/video/offb.c                :      11        3        1
linux/drivers/video/pm2fb.c               :    1494     1494        0
linux/drivers/video/pm2fb.h               :     181      181        0
linux/drivers/video/retz3fb.c             :       9        1        2
linux/drivers/video/sbusfb.c              :      80       11        7
linux/drivers/video/virgefb.c             :      87       34       12
linux/fs/Config.in                        :      12        5        1
linux/fs/namei.c                          :      17        9        1
linux/fs/proc/array.c                     :       9        1        2
linux/fs/select.c                         :      37       31        0
linux/fs/vfat/namei.c                     :       9        1        1
linux/include/asm-alpha/semaphore.h       :      25        4        4
linux/include/asm-i386/cobalt.h           :     116      116        0
linux/include/asm-i386/fixmap.h           :      30       12        3
linux/include/asm-i386/i82489.h           :      25       13        0
linux/include/asm-i386/lithium.h          :      40       40        0
linux/include/asm-i386/smp.h              :      49       11       22
linux/include/asm-i386/string.h           :      35        0       29
linux/include/asm-i386/unistd.h           :       8        1        1
linux/include/asm-m68k/bootinfo.h         :      27        0       14
linux/include/asm-m68k/entry.h            :     161       56       63
linux/include/asm-m68k/ide.h              :       8        1        1
linux/include/asm-m68k/init.h             :      19        3        3
linux/include/asm-m68k/io.h               :      35       29        0
linux/include/asm-m68k/keyboard.h         :      12        3        3
linux/include/asm-m68k/machdep.h          :       7        0        1
linux/include/asm-m68k/machw.h            :      24       12        0
linux/include/asm-m68k/page.h             :      17        2        2
linux/include/asm-m68k/pgtable.h          :     135       12       67
linux/include/asm-m68k/processor.h        :       8        2        0
linux/include/asm-m68k/semaphore.h        :      96       32        5
linux/include/asm-m68k/setup.h            :      80       10        8
linux/include/asm-m68k/system.h           :      22        3        6
linux/include/asm-m68k/traps.h            :      35        9        0
linux/include/asm-m68k/unistd.h           :      57        1       43
linux/include/asm-m68k/virtconvert.h      :       8        1        1
linux/include/asm-sparc64/pgtable.h       :       8        1        1
linux/include/linux/fs.h                  :       8        1        1
linux/include/linux/isdn.h                :      28        5        6
linux/include/linux/mm.h                  :      21        2        2
linux/include/linux/pagemap.h             :       8        1        1
linux/include/linux/poll.h                :      55        4       34
linux/include/linux/swap.h                :      22        9        0
linux/include/linux/timex.h               :      16        3        0
linux/include/net/irda/crc.h              :      17        2        2
linux/include/net/irda/irda.h             :      37        8        7
linux/include/net/irda/irda_device.h      :      20        4        3
linux/include/net/irda/irlap_event.h      :      24        3        1
linux/include/net/irda/irlpt_cli.h        :      47       47        0
linux/include/net/irda/irlpt_cli_fsm.h    :      34       34        0
linux/include/net/irda/irlpt_common.h     :     184      184        0
linux/include/net/irda/irlpt_server.h     :      42       42        0
linux/include/net/irda/irlpt_server_fsm.h :      30       30        0
linux/include/net/irda/irmod.h            :      21        4        2
linux/include/net/irda/irobex.h           :      67       12       11
linux/include/net/irda/irport.h           :      17        2        2
linux/include/net/irda/uircc.h            :     121      121        0
linux/include/net/sock.h                  :      16        2        1
linux/include/video/font.h                :      27        0       15
linux/init/main.c                         :       8        1        1
linux/kernel/ksyms.c                      :      15        2        0
linux/kernel/sched.c                      :     142       38       36
linux/kernel/time.c                       :     287      137       86
linux/mm/filemap.c                        :       8        1        1
linux/mm/page_alloc.c                     :      58        8        8
linux/mm/swapfile.c                       :      15        4        4
linux/mm/vmscan.c                         :      74       26       23
linux/net/ipv4/ip_output.c                :      97       37        6
linux/net/ipv4/tcp_input.c                :      30        6        3
linux/net/ipv4/tcp_output.c               :      30        6        3
linux/net/ipv4/tcp_timer.c                :      16        2        1
linux/net/ipv6/af_inet6.c                 :       8        1        1
linux/net/irda/Config.in                  :      15        2        0
linux/net/irda/Makefile                   :      24       10        1
linux/net/irda/af_irda.c                  :      26        3        3
linux/net/irda/irda_device.c              :      82       20       10
linux/net/irda/iriap.c                    :      48        6        8
linux/net/irda/irias_object.c             :      14        2        2
linux/net/irda/irlan/irlan_cli.c          :      43        5        7
linux/net/irda/irlan/irlan_common.c       :      17        2        2
linux/net/irda/irlap.c                    :     320       39       78
linux/net/irda/irlap_event.c              :     349       74       43
linux/net/irda/irlap_frame.c              :     111        7       21
linux/net/irda/irlmp.c                    :     104       13       23
linux/net/irda/irlmp_event.c              :     202       26       29
linux/net/irda/irlmp_frame.c              :     264       68       49
linux/net/irda/irlpt/Config.in            :       7        7        0
linux/net/irda/irlpt/Makefile             :      48       48        0
linux/net/irda/irlpt/irlpt_cli.c          :     599      599        0
linux/net/irda/irlpt/irlpt_cli_fsm.c      :     374      374        0
linux/net/irda/irlpt/irlpt_common.c       :     512      512        0
linux/net/irda/irlpt/irlpt_srvr.c         :     545      545        0
linux/net/irda/irlpt/irlpt_srvr_fsm.c     :     182      182        0
linux/net/irda/irmod.c                    :     102       38        2
linux/net/irda/irobex/irobex.c            :     762      167      158
linux/net/irda/irproc.c                   :      16        1        2
linux/net/irda/irqueue.c                  :      41        6        6
linux/net/irda/irsysctl.c                 :      40       12        2
linux/net/irda/irttp.c                    :      73        5       15
linux/net/irda/wrapper.c                  :     225       49       57
linux/net/sunrpc/xprt.c                   :      11        1        4
linux/scripts/tkcond.c                    :     830      286      471
linux/scripts/tkgen.c                     :    1936      841      966
linux/scripts/tkparse.c                   :    1292      515      670
linux/scripts/tkparse.h                   :     174       92       62
-- 
Thomas Koenig, Thomas...@ciw.uni-karlsruhe.de, ig...@dkauni2.bitnet.
The joy of engineering is to find a straight line on a double
logarithmic diagram.
#!/bin/sh
# This is a shell archive
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
# existing files will NOT be overwritten unless -c is specified
#
# This is part 01 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
#
if test -r _shar_seq_.tmp; then
        echo 'Must unpack archives in sequence!'
        echo Please unpack part `cat _shar_seq_.tmp` next
        exit 1
fi
# ============= patch-2.2.0-pre9 ==============
if test -f 'patch-2.2.0-pre9' -a X"$1" != X"-c"; then
        echo 'x - skipping patch-2.2.0-pre9 (File already exists)'
        rm -f _shar_wnt_.tmp
else
> _shar_wnt_.tmp
echo 'x - extracting patch-2.2.0-pre9 (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'patch-2.2.0-pre9' &&
diff -u --recursive --new-file v2.2.0-pre8/linux/CREDITS linux/CREDITS
--- v2.2.0-pre8/linux/CREDITS	Tue Jan 19 11:32:50 1999
+++ linux/CREDITS	Tue Jan 19 10:19:31 1999
@@ -2095,6 +2095,14 @@
X S: 6525 EZ Nijmegen
X S: The Netherlands
X 
+N: Ulrich Windl
+E: Ulrich...@rz.uni-regensburg.de
+P: 1024/E843660D CF D7 43 A1 5A 49 14 25  7C 04 A0 6E 4C 3A AC 6D
+D: Supports NTP on Linux.  Added PPS code.  Fixed bugs in adjtimex().
+S: Alte Regensburger Str. 11a
+S: 93149 Nittenau
+S: Germany
+
X N: Lars Wirzenius
X E: l...@iki.fi
X D: Linux System Administrator's Guide
diff -u --recursive --new-file v2.2.0-pre8/linux/Documentation/Changes linux/Documentation/Changes
--- v2.2.0-pre8/linux/Documentation/Changes	Tue Jan 19 11:32:50 1999
+++ linux/Documentation/Changes	Tue Jan 19 09:48:01 1999
@@ -2,13 +2,13 @@
X =====
X 
X This document is designed to provide a list of the minimum levels of
-software necessary to run the 2.1.x kernels, as well as provide brief
+software necessary to run the 2.2 kernels, as well as provide brief
X instructions regarding any other "Gotchas" users may encounter when
X trying life on the Bleeding Edge.  If upgrading from a pre-2.0.x
X kernel, please consult the Changes file included with 2.0.x kernels for
X additional information; most of that information will not be repeated
X here.  Basically, this document assumes that your system is already
-functional and running at least 2.0.x.
+functional and running at least 2.0.x kernels.
X 
X    It is originally based on my "Changes" file for 2.0.x kernels and
X therefore owes credit to the same people as that file (Jared Mauch,
@@ -33,7 +33,7 @@
X    Also, don't forget http://www.linuxhq.com/ for all your Linux kernel
X needs.
X 
-Last updated: December 12, 1998
+Last updated: January 18, 1999
X Current Author: Chris Ricker (kab...@gatech.edu or chris....@m.cc.utah.edu).
X 
X Current Minimal Requirements
@@ -57,12 +57,12 @@
X - Loadlin                1.6a
X - Sh-utils               1.16                    ; basename --v
X - Autofs                 3.1.1                   ; automount --version
-- NFS                    2.2beta37               ; showmount --version
+- NFS                    2.2beta40               ; showmount --version
X - Bash                   1.14.7                  ; bash -version
X - Ncpfs                  2.2.0                   ; ncpmount -v
-- Pcmcia-cs              3.0.6                   ; cardmgr -V
+- Pcmcia-cs              3.0.7                   ; cardmgr -V
X - PPP                    2.3.5                   ; pppd -v
-- Util-linux             2.9                     ; chsh -v
+- Util-linux             2.9g                    ; chsh -v
X 
X Upgrade notes
X *************
@@ -81,19 +81,21 @@
X ttyS1, etc.).
X 
X    In addition, some software still works, but needs to be compiled
-against 2.1 headers for complete functionality.  Fdutils binaries
+against 2.2 headers for complete functionality.  Fdutils binaries
X compiled under 2.0 or earlier kernels should be replaced with ones
-compiled under 2.1, for example.
+compiled under 2.2, for example.
X 
-   As of 2.1.115, support for the deprecated major 4 /dev/ttyp* devices 
-was removed.  If necessary (eg, you get "out of pty" error messages when 
-you obviously are not out of pty's), create major 3 /dev/tty* and major 2 
-/dev/pty* devices (see Documentation/devices.txt for more information).  
+   As of 2.1.115, support for the deprecated major 4 /dev/ttyp* devices
+was removed.  If necessary (eg, you get "out of pty" error messages when
+you obviously are not out of pty's), create major 3 /dev/tty* and major
+2 /dev/pty* devices (see Documentation/devices.txt for more
+information).  In general, you should make sure that your /dev
+directory is up-to-date if you are experiencing any problems.
X 
X    Optional support for Unix98 pty devices has also been added. If you
-want to use the Unix98 ptys, you should be running at least glibc-2.0.9x, 
-and you must switch completely to Unix98 pty's.  The general procedure 
-for configuring Unix98 pty support is:
+want to use the Unix98 ptys, you should be running at least
+glibc-2.0.9x, and you must switch completely to Unix98 pty's.  The
+general procedure for configuring Unix98 pty support is:
X 
X - Compile your kernel with CONFIG_UNIX98_PTYS and CONFIG_DEVPTS_FS.
X - mknod /dev/ptmx c 5 2
@@ -119,7 +121,7 @@
X Libc (libc5)
X ============
X 
-   Linux-2.1.x is ELF-only.  You can still compile a.out apps if you
+   Linux-2.2 is ELF-only.  You can still compile a.out apps if you
X really want, but your kernel must be compiled ELF.  If you can't
X currently compile ELF, consult the ELF howto at
X http://metalab.unc.edu/mdw/HOWTO/ELF-HOWTO.html and upgrade your system
@@ -163,8 +165,8 @@
X Modules
X =======
X 
-   You need to upgrade to the latest version of modutils-2.1.x for
-development kernels.  This version will also work with 2.0.x kernels.
+   You need to upgrade to the latest version of modutils for the Linux
+2.2 kernel.  This version will also work with your 2.0 kernel.
X 
X    As of 2.1.90-pre1, kerneld has been replaced by a kernel thread,
X kmod.  See Documentation/kmod.txt for more information.  The main
@@ -199,7 +201,7 @@
X    Note that the latest compilers (egcs, pgcc, gcc 2.8) may do Bad
X Things while compiling your kernel, particularly if absurd
X optimizations (like -O9) are used.  Caveat emptor.  Currently, the only
-C compiler available in a binary distribution is egcs.  Version 1.0.2
+C compiler available in a binary distribution is egcs.  Version 1.0.3
X seems okay; if you have to have a binary, you may be successful using
X that.  In general, however, gcc-2.7.2.3 is known to be stable, while
X egcs and others have not been as thoroughly tested yet.
@@ -240,7 +242,13 @@
X ipfwadm.
X 
X    To use masq forwarding you will need to obtain "ipmasqadm,"
-available from http://juanjox.linuxhq.com/
+available from http://juanjox.linuxhq.com/ .
+
+   DHCP clients for 2.0 do not work with the new networking code in the
+2.2 kernel.  You will need to upgrade your dhcpcd / dhcpclient.
+
+   The ISDN code in the stock 2.0 kernel may not work for you.  If it
+doesn't, look in ftp://ftp.suse.com/pub/isdn4linux for updated versions.
X 
X Memory
X ======
@@ -261,10 +269,10 @@
X Util-linux (including mount)
X ============================
X 
-   Among other changes in the 2.1.x development, the 128 meg limit on
-IA32 swap partition sizes has been eliminated.  To use larger swap
-spaces, you need the new mkswap found in util-linux.  You also need to
-upgrade this to get the latest version of mount.
+   Among other changes made in the development of Linux kernel 2.2, the
+128 meg limit on IA32 swap partition sizes has been eliminated.  To use
+larger swap spaces, you need the new mkswap found in util-linux.  You
+also need to upgrade util-linux to get the latest version of mount.
X 
X RPM
X ===
@@ -275,7 +283,7 @@
X DOSEMU
X ======
X 
-   A new "stable" version of DOSEMU is available for 2.1.x kernels.
+   A new "stable" version of DOSEMU is available for 2.2 kernels.
X Upgrade to 0.98.4 or later.
X 
X Loadlin
@@ -325,6 +333,15 @@
X cause problems when compiling modules.  Upgrade to at least 1.14 to fix
X this problem.
X 
+Sysklogd
+========
+
+   Older versions of sysklogd sometimes segfault under 2.2 kernels.
+Upgrading to the latest release fixes that problem as well as adding
+support for new features like system power-off on halt (with
+appropriate incantations of halt; see the man page) and automatic
+decoding of kernel oopses.
+
X Ncpfs
X =====
X 
@@ -335,10 +352,10 @@
X =====
X 
X    To mount SMB (Samba / Windows) shares, you'll need to use the
-smbmount utility included with recent Samba releases.
+smbmount utility included with release 2.0 of Samba.
X Documentation/filesystems/smbfs.txt has more information about this.
-Note that smbmount must have been built against 2.1.x headers to work
-with 2.1.x; if all else fails, recompile it and hope it works ;-).  In
+Note that smbmount must have been built against 2.2 headers to work
+with 2.2; if all else fails, recompile it and hope it works ;-).  In
X addition, Mike Warfield has a script and some information at
X http://www.wittsend.com/mhw/smbmount.html that you will probably find
X useful.
@@ -358,19 +375,19 @@
X iBCS
X ====
X 
-   A new version of iBCS is necessary for 2.1 kernels.
+   A new version of iBCS is necessary for 2.2 kernels.
X 
X AppleTalk
X =========
X 
X    Use the Asun version of netatalk for AppleTalk support, as Umich's
-version is not compatible with 2.1 kernels.
+version is not compatible with 2.2 kernels.
X 
X Psmisc
X ======
X 
X    fuser, which comes with psmisc, reads /proc/*/fd/* to do its job.
-Upgrade psmisc if 2.1 changes to /proc broke the version you're using.
+Upgrade psmisc if 2.2 changes to /proc broke the version you're using.
X 
X Tunelp
X ======
@@ -405,6 +422,15 @@
X 
X    If you're lucky, you'll then have sound....
X 
+   You may also need to edit it with
+
+   dd if=/dev/zero of=rvplayer bs=1 count=1 seek=702554 conv=notrunc
+
+   as well.  Alternately, download rpopen from
+http://onramp.i2k.com/~jeffd/rpopen/ and pre-load it before you run
+rvplayer (it's a shared object which blocks rvplayer from doing the
+NONBLOCKing open of /dev/dsp).
+
X Quotas
X ======
X 
@@ -553,7 +579,7 @@
X ==========
X 
X The 2.9 release:
-ftp://ftp.win.tue.nl/pub/linux/util/util-linux-2.9.tar.gz
+ftp://ftp.win.tue.nl/pub/linux/util/util-linux-2.9g.tar.gz
X 
X Autofs
X ======
@@ -564,9 +590,9 @@
X NFS
X ===
X 
-The user-land 2.2beta37 release:
-ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta37.tar.gz
-ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta37.tar.gz
+The user-land 2.2beta40 release:
+ftp://ftp.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta40.tar.gz
+ftp://linux.nrao.edu/mirrors/fb0429.mathematik.th-darmstadt.de/pub/linux/okir/nfs-server-2.2beta40.tar.gz
X 
X The kernel-level 12/04/98 release:
X ftp://ftp.yggdrasil.com/private/hjl/knfsd-981204.tar.gz
@@ -585,6 +611,12 @@
X The 3.3 release:
X ftp://ftp.uni-paderborn.de/pub/linux/local/yp/ypbind-3.3.tar.gz
X 
+Sysklogd
+========
+
+The 1.3-30 release:
+ftp://metalab.unc.edu/pub/Linux/system/daemons/sysklogd-1.3-30.tar.gz
+
X Bash
X ====
X 
@@ -603,14 +635,14 @@
X SMBfs
X =====
X 
-The 1.9.18p10 release of Samba:
-ftp://ftp.samba.org/pub/samba/samba-1.9.18p10.tar.gz
+The 2.0.0 release of Samba:
+ftp://ftp.samba.org/pub/samba/samba-2.0.0.tar.gz
X 
X Pcmcia-cs
X =========
X 
-The 3.0.6 release:
-ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.6.tar.gz
+The 3.0.7 release:
+ftp://hyper.stanford.edu/pub/pcmcia/pcmcia-cs.3.0.7.tar.gz
X 
X Setserial
X =========
@@ -638,6 +670,15 @@
X The 0.4.2 release:
X http://juanjox.linuxhq.com/ipmasqadm-0.4.2.tar.gz
X 
+DHCP clients
+============
+
+The 2.0b1p18 ISC dhcpclient release:
+ftp://ftp.isc.org/isc/dhcp/test/dhcp-2.0b1pl8.tar.gz
+
+The 1.3.17-pl2 PhysTech dhcpcd release:
+ftp://ftp.phystech.com/pub/dhcpcd-1.3.17-pl2.tar.gz
+
X iBCS
X ====
X 
@@ -693,7 +734,7 @@
X 
X    Please remember that most of these utils are available on your
X favorite local linux mirror.  If you can, please get them from a closer
-site before checking metalab.
+site before checking metalab or tsx-11.
X 
X    You may also want to check for updated versions of this software in a
X package format for the distribution you use.
@@ -702,20 +743,17 @@
X distribution), most of these are available in RPM format.  Check around
X your favorite Red Hat mirror site before installing the non-RPM
X version.  Remember, you might need to use the --force option to get the
-upgrade to install.  ftp://contrib.redhat.com/ will have almost
-everything you need, and Red Hat 5.2 ships with most necessary software.
+upgrade to install.  ftp://contrib.redhat.com/ ,
+ftp://developer.redhat.com/ , or ftp://rawhide.redhat.com/  will have
+almost everything you need, and Red Hat 5.2 ships with most necessary
+software.
X 
X    Those of you running Debian (or a different distribution that
X supports .deb packages) can look in the "unstable" and
X "project/experimental" directories of your favorite Debian mirror.  The
X Debian 2.0 release ships with most packages you need as well.
X 
-   For others, David Bourgin has put together a package of everything
-necessary to quickly and easily upgrade to 2.1.x.  See
-ftp://ftp.wsc.com/pub/freeware/linux/update.linux/kernel-v2.1.x/ for
-more information and the files.
-
-Please send info about any other packages that 2.1.x "broke" or about
-any new features of 2.1.x that require extra or new packages for use to
-Chris Ricker (kab...@gatech.edu or chris....@m.cc.utah.edu).
+Please send info about any other packages that 2.2 "broke" or about any
+new features of 2.2 that require extra or new packages for use to Chris
+Ricker (kab...@gatech.edu or chris....@m.cc.utah.edu).
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/Documentation/Configure.help linux/Documentation/Configure.help
--- v2.2.0-pre8/linux/Documentation/Configure.help	Tue Jan 19 11:32:50 1999
+++ linux/Documentation/Configure.help	Wed Jan 20 11:05:32 1999
@@ -1398,6 +1398,15 @@
X   Documentation/mca.txt (and especially the web page given there)
X   before attempting to build an MCA bus kernel.
X 
+SGI Visal Workstation support
+CONFIG_VISWS
+  The SGI Visual Workstation series is an IA32-based workstation
+  based on SGI systems chips with some legacy PC hardware attached.
+  Say Y here to create a kernel to run on the SGI 320 or 540.
+  A kernel compiled for the Visual Workstation will not run on other
+  PC boards and vice versa.
+  See Documentation/sgi-visws.txt for more.
+
X System V IPC
X CONFIG_SYSVIPC
X   Inter Process Communication is a suite of library functions and
@@ -7111,24 +7120,19 @@
X 
X   If unsure, say N.
X 
-/dev/pts filesystem (experimental)
+/dev/pts filesystem for Unix98 PTYs
X CONFIG_DEVPTS_FS
X   You should say Y here if you said Y to "Unix98 PTY support" above.
X   You'll then get a virtual filesystem which can be mounted on
X   /dev/pts with "mount -t devpts". This, together with the pseudo
X   terminal master multiplexer /dev/ptmx, is used for pseudo terminal
-  support as described in the Open Group's Unix98 standard: in order
+  support as described in The Open Group's Unix98 standard: in order
X   to acquire a pseudo terminal, a process opens /dev/ptmx; the number
X   of the pseudo terminal is then made available to the process and the
X   pseudo terminal slave can be accessed as /dev/pts/<number>. What was
X   traditionally /dev/ttyp2 will then be /dev/pts/2, for example. The
X   GNU C library glibc 2.1 contains the requisite support for this mode
-  of operation.
-
-  This code is also available as a module called devpts.o ( = code
-  which can be inserted in and removed from the running kernel
-  whenever you want). If you want to compile it as a module, say M
-  here and read Documentation/modules.txt.
+  of operation; you also need clients that use the Unix98 API.
X 
X Unixware slices support (EXPERIMENTAL)
X CONFIG_UNIXWARE_DISKLABEL
@@ -10594,6 +10598,14 @@
X 
X   If unsure, say Y.
X 
+IrDA Debug
+CONFIG_IRDA_DEBUG
+  Say Y here if you want the IrDA subsystem to write debug information to
+  your syslog. You can change the debug level in
+  /proc/sys/net/irda/debug
+
+  If unsure, say Y (since it makes it easier to find the bugs).
+
X IrLAP Compression support
X CONFIG_IRDA_COMPRESSION
X   Compression is _not_ part of the IrDA(tm) protocol specification,
@@ -10659,6 +10671,31 @@
X   will create two modules called ircomm and ircomm_tty. For more
X   information go to http://www.pluto.dti.ne.jp/~thiguchi/irda/
X 
+IrLPT Protocol
+CONFIG_IRLPT
+  Say Y here if you want to build support for the IrLPT protocol. If
+  you want to compile it as a module, say M here and read
+  Documentation/modules.txt. IrLPT makes it possible to print
+  documents to IrDA capable printers.
+
+IrLPT Client Protocol 
+CONFIG_IRLPT_CLIENT
+  Say Y here if you want to build support for the IrLPT client
+  protocol. If you want to compile it as a module, say M here and read
+  Documentation/modules.txt. The IrLPT client protocol can be used to
+  print documents to IrDA compatible printers like the HP-5MP, or
+  IrLPT printer adapters like the ACTiSYS IR-100M.
+
+IrLPT Server Protocol 
+CONFIG_IRLPT_SERVER
+  Say Y here if you want to build support for the IrLPT server
+  protocol. If you want to compile it as a module, say M here and read
+  Documentation/modules.txt. The IrLPT server protocol makes it
+  possible to use a Linux machine as an infrared printer server for
+  other laptops. So if your Linux machine has a cable connection to a
+  printer, then other laptops can use the Linux machine to print out 
+  documents using infrared communication.
+
X IrTTY IrDA Device Driver
X CONFIG_IRTTY_SIR
X   Say Y here if you want to build support for the IrTTY line
@@ -10686,6 +10723,13 @@
X   read Documentation/modules.txt. This drivers currently only supports
X   the ACTiSYS IR2000B ISA card and supports SIR, MIR and FIR (4Mbps)
X   speeds.
+
+Sharp UIRCC IrDA Device Driver
+CONFIG_SHARP_FIR
+  Say Y here if you want to build support for the Sharp UIRCC IrDA
+  chipset. If you want to compile it as a module, say M here and
+  read Documentation/modules.txt. This chipset is used by the Toshiba
+  Tecra laptops.
X 
X ESI JetEye PC Dongle
X CONFIG_ESI_DONGLE
diff -u --recursive --new-file v2.2.0-pre8/linux/Documentation/sgi-visws.txt linux/Documentation/sgi-visws.txt
--- v2.2.0-pre8/linux/Documentation/sgi-visws.txt	Wed Dec 31 16:00:00 1969
+++ linux/Documentation/sgi-visws.txt	Wed Jan 20 10:18:53 1999
@@ -0,0 +1,13 @@
+
+The SGI Visual Workstations (models 320 and 540) are based around
+the Cobalt, Lithium, and Arsenic ASICs.  The Cobalt ASIC is the
+main system ASIC which interfaces the 1-4 IA32 cpus, the memory
+system, and the I/O system in the Lithium ASIC.  The Cobalt ASIC
+also contains the 3D gfx rendering engine which renders to main
+system memory -- part of which is used as the frame buffer which
+is DMA'ed to a video connector using the Arsenic ASIC.  A PIIX4
+chip and NS87307 are used to provide legacy device support (IDE,
+serial, floppy, and parallel).
+
+The Visual Workstation chipset largely conforms to the PC architecture
+with some notable exceptions such as interrupt handling.
diff -u --recursive --new-file v2.2.0-pre8/linux/MAINTAINERS linux/MAINTAINERS
--- v2.2.0-pre8/linux/MAINTAINERS	Tue Jan 19 11:32:50 1999
+++ linux/MAINTAINERS	Wed Jan 20 13:27:17 1999
@@ -641,6 +641,13 @@
X L:	linux...@vger.rutgers.edu
X S:	Maintained
X 
+SGI VISUAL WORKSTATION 320 AND 540
+P:	Bent Hagemark
+M:	b...@sgi.com
+P:	Ingo Molnar
+M:	mi...@redhat.com
+S:	Maintained
+
X SMB FILESYSTEM
X P:	Volker Lendecke
X M:	v...@kki.org
diff -u --recursive --new-file v2.2.0-pre8/linux/Makefile linux/Makefile
--- v2.2.0-pre8/linux/Makefile	Tue Jan 19 11:32:50 1999
+++ linux/Makefile	Wed Jan 20 22:27:22 1999
@@ -1,7 +1,7 @@
X VERSION = 2
X PATCHLEVEL = 2
X SUBLEVEL = 0
-EXTRAVERSION =-pre8
+EXTRAVERSION =-final
X 
X ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/alpha/kernel/osf_sys.c linux/arch/alpha/kernel/osf_sys.c
--- v2.2.0-pre8/linux/arch/alpha/kernel/osf_sys.c	Thu Nov 12 16:21:17 1998
+++ linux/arch/alpha/kernel/osf_sys.c	Wed Jan 20 16:07:26 1999
@@ -1128,11 +1128,16 @@
X 	return ret;
X }
X 
+#define MAX_SELECT_SECONDS \
+	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)
+
X asmlinkage int
X osf_select(int n, fd_set *inp, fd_set *outp, fd_set *exp,
X 	   struct timeval32 *tvp)
X {
-	fd_set_buffer *fds;
+	fd_set_bits fds;
+	char *bits;
+	size_t size;
X 	unsigned long timeout;
X 	int ret;
X 
@@ -1145,28 +1150,46 @@
X 		    || (ret = __get_user(usec, &tvp->tv_usec)))
X 			goto out_nofds;
X 
-		timeout = (usec + 1000000/HZ - 1) / (1000000/HZ);
-		timeout += sec * HZ;
+		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;
+		}
X 	}
X 
+	ret = -EINVAL;
+	if (n < 0 || n > KFDS_NR)
+		goto out_nofds;
+
+	/*
+	 * 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. 
+	 */
X 	ret = -ENOMEM;
-	fds = (fd_set_buffer *) __get_free_page(GFP_KERNEL);
-	if (!fds)
+	size = FDS_BYTES(n);
+	bits = kmalloc(6 * size, GFP_KERNEL);
+	if (!bits)
X 		goto out_nofds;
-	ret = -EINVAL;
-	if (n < 0)
-		goto out;
-	if (n > KFDS_NR)
-		n = KFDS_NR;
-	if ((ret = get_fd_set(n, inp->fds_bits, fds->in)) ||
-	    (ret = get_fd_set(n, outp->fds_bits, fds->out)) ||
-	    (ret = get_fd_set(n, exp->fds_bits, fds->ex)))
+	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);
+
+	if ((ret = get_fd_set(n, inp->fds_bits, fds.in)) ||
+	    (ret = get_fd_set(n, outp->fds_bits, fds.out)) ||
+	    (ret = get_fd_set(n, exp->fds_bits, fds.ex)))
X 		goto out;
-	zero_fd_set(n, fds->res_in);
-	zero_fd_set(n, fds->res_out);
-	zero_fd_set(n, fds->res_ex);
+	zero_fd_set(n, fds.res_in);
+	zero_fd_set(n, fds.res_out);
+	zero_fd_set(n, fds.res_ex);
X 
-	ret = do_select(n, fds, &timeout);
+	ret = do_select(n, &fds, &timeout);
X 
X 	/* OSF does not copy back the remaining time.  */
X 
@@ -1179,12 +1202,12 @@
X 		ret = 0;
X 	}
X 
-	set_fd_set(n, inp->fds_bits, fds->res_in);
-	set_fd_set(n, outp->fds_bits, fds->res_out);
-	set_fd_set(n, exp->fds_bits, fds->res_ex);
+	set_fd_set(n, inp->fds_bits, fds.res_in);
+	set_fd_set(n, outp->fds_bits, fds.res_out);
+	set_fd_set(n, exp->fds_bits, fds.res_ex);
X 
X out:
-	free_page((unsigned long) fds);
+	kfree(bits);
X out_nofds:
X 	return ret;
X }
@@ -1304,7 +1327,6 @@
X {
X 	struct timeval tmp;
X 	unsigned long ticks;
-	unsigned long tmp_timeout;
X 
X 	if (get_tv32(&tmp, sleep))
X 		goto fault;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/alpha/kernel/process.c linux/arch/alpha/kernel/process.c
--- v2.2.0-pre8/linux/arch/alpha/kernel/process.c	Tue Jan 19 11:32:50 1999
+++ linux/arch/alpha/kernel/process.c	Wed Jan 20 11:08:43 1999
@@ -266,12 +266,8 @@
X 
X int alpha_vfork(struct switch_stack * swstack)
X {
-	int child;
-
-	child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
X 			(struct pt_regs *) (swstack+1));
-
-	return child;
X }
X 
X extern void ret_from_sys_call(void);
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/alpha/kernel/time.c linux/arch/alpha/kernel/time.c
--- v2.2.0-pre8/linux/arch/alpha/kernel/time.c	Wed Jan 13 15:00:41 1999
+++ linux/arch/alpha/kernel/time.c	Tue Jan 19 10:19:38 1999
@@ -10,6 +10,8 @@
X  * 1995-03-26    Markus Kuhn
X  *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887
X  *      precision CMOS clock update
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
X  * 1997-01-09    Adrian Sun
X  *      use interval timer if CONFIG_RTC=y
X  * 1997-10-29    John Bowman (bow...@math.ualberta.ca)
@@ -112,10 +114,10 @@
X 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
X 	 * called as close as possible to 500 ms before the new second starts.
X 	 */
-	if (time_state != TIME_BAD
+	if ((time_status & STA_UNSYNC) == 0
X 	    && xtime.tv_sec > state.last_rtc_update + 660
-	    && xtime.tv_usec >= 500000 - (tick >> 1)
-	    && xtime.tv_usec <= 500000 + (tick >> 1)) {
+	    && xtime.tv_usec >= 500000 - ((unsigned) tick) / 2
+	    && xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
X 		int tmp = set_rtc_mmss(xtime.tv_sec);
X 		state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0);
X 	}
@@ -353,9 +355,11 @@
X {
X 	cli();
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = 0x70000000;
-	time_esterror = 0x70000000;
+	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;
X 	sti();
X }
X 
@@ -366,6 +370,9 @@
X  * nowtime is written into the registers of the CMOS clock, it will
X  * jump to the next second precisely 500 ms later. Check the Motorola
X  * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
X  */
X static int
X set_rtc_mmss(unsigned long nowtime)
@@ -407,8 +414,12 @@
X 		}
X 		CMOS_WRITE(real_seconds,RTC_SECONDS);
X 		CMOS_WRITE(real_minutes,RTC_MINUTES);
-	} else
-		retval = -1;
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+ 		retval = -1;
+	}
X 
X 	/* The following flags have to be released exactly in this order,
X 	 * otherwise the DS12887 (popular MC146818A clone with integrated
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/arm/kernel/time.c linux/arch/arm/kernel/time.c
--- v2.2.0-pre8/linux/arch/arm/kernel/time.c	Wed Sep  9 14:51:04 1998
+++ linux/arch/arm/kernel/time.c	Tue Jan 19 10:19:41 1999
@@ -9,7 +9,7 @@
X  *
X  * 1994-07-02  Alan Modra
X  *             fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
- * 1997-09-10  Updated NTP code according to technical memorandum Jan '96
+ * 1998-12-20  Updated NTP code according to technical memorandum Jan '96
X  *             "A Kernel Model for Precision Timekeeping" by Dave Mills
X  */
X #include <linux/errno.h>
@@ -125,9 +125,11 @@
X 	}
X 
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = MAXPHASE;
-	time_esterror = MAXPHASE;
+	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;
X 	sti ();
X }
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/config.in linux/arch/i386/config.in
--- v2.2.0-pre8/linux/arch/i386/config.in	Tue Jan 19 11:32:51 1999
+++ linux/arch/i386/config.in	Wed Jan 20 10:18:53 1999
@@ -70,6 +70,17 @@
X   bool '   Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
X fi
X bool 'MCA support' CONFIG_MCA
+bool 'SGI Visual Workstation support' CONFIG_VISWS
+if [ "$CONFIG_VISWS" = "y" ]; then
+  define_bool CONFIG_X86_VISWS_APIC y
+  define_bool CONFIG_X86_LOCAL_APIC y
+else
+  if [ "$CONFIG_SMP" = "y" ]; then
+    define_bool CONFIG_X86_IO_APIC y
+    define_bool CONFIG_X86_LOCAL_APIC y
+  fi
+fi
+
X bool 'System V IPC' CONFIG_SYSVIPC
X bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
X bool 'Sysctl support' CONFIG_SYSCTL
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/defconfig linux/arch/i386/defconfig
--- v2.2.0-pre8/linux/arch/i386/defconfig	Tue Jan 19 11:32:51 1999
+++ linux/arch/i386/defconfig	Wed Jan 20 11:33:56 1999
@@ -45,6 +45,9 @@
X CONFIG_PCI_QUIRKS=y
X CONFIG_PCI_OLD_PROC=y
X # CONFIG_MCA is not set
+# CONFIG_VISWS is not set
+CONFIG_X86_IO_APIC=y
+CONFIG_X86_LOCAL_APIC=y
X CONFIG_SYSVIPC=y
X # CONFIG_BSD_PROCESS_ACCT is not set
X CONFIG_SYSCTL=y
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/Makefile linux/arch/i386/kernel/Makefile
--- v2.2.0-pre8/linux/arch/i386/kernel/Makefile	Tue Dec 22 14:16:53 1998
+++ linux/arch/i386/kernel/Makefile	Wed Jan 20 10:18:53 1999
@@ -39,7 +39,15 @@
X endif
X 
X ifdef CONFIG_SMP
-O_OBJS += io_apic.o smp.o trampoline.o
+O_OBJS += smp.o trampoline.o
+endif
+
+ifdef CONFIG_X86_IO_APIC
+O_OBJS += io_apic.o
+endif
+
+ifdef CONFIG_X86_VISWS_APIC
+O_OBJS += visws_apic.o
X endif
X 
X head.o: head.S $(TOPDIR)/include/linux/tasks.h
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/bios32.c linux/arch/i386/kernel/bios32.c
--- v2.2.0-pre8/linux/arch/i386/kernel/bios32.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/i386/kernel/bios32.c	Wed Jan 20 10:18:53 1999
@@ -352,6 +352,10 @@
X {
X 	u16 dfn, x;
X 
+#ifdef CONFIG_VISWS
+	return 1;       /* Lithium PCI Bridges are non-standard */
+#endif
+
X 	if (pci_probe & PCI_NO_CHECKS)
X 		return 1;
X 	for(dfn=0; dfn < 0x100; dfn++)
@@ -1051,7 +1055,7 @@
X 				pci_write_config_word(dev, PCI_COMMAND, cmd);
X 			}
X 		}
-#ifdef __SMP__
+#if defined(CONFIG_X86_IO_APIC)
X 		/*
X 		 * Recalculate IRQ numbers if we use the I/O APIC
X 		 */
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
--- v2.2.0-pre8/linux/arch/i386/kernel/entry.S	Tue Jan 19 11:32:51 1999
+++ linux/arch/i386/kernel/entry.S	Wed Jan 20 11:05:59 1999
@@ -559,7 +559,7 @@
X 	.long SYMBOL_NAME(sys_sendfile)
X 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
X 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
-	.long SYMBOL_NAME(sys_ni_syscall)            /* 190 */
+	.long SYMBOL_NAME(sys_vfork)            /* 190 */
X 
X 	/*
X 	 * NOTE!! This doesn't have to be exact - we just have
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/i386_ksyms.c linux/arch/i386/kernel/i386_ksyms.c
--- v2.2.0-pre8/linux/arch/i386/kernel/i386_ksyms.c	Thu Dec 31 10:28:59 1998
+++ linux/arch/i386/kernel/i386_ksyms.c	Tue Jan 19 11:02:59 1999
@@ -60,6 +60,7 @@
X 
X EXPORT_SYMBOL(strtok);
X EXPORT_SYMBOL(strpbrk);
+EXPORT_SYMBOL(strstr);
X 
X EXPORT_SYMBOL(strncpy_from_user);
X EXPORT_SYMBOL(__strncpy_from_user);
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/irq.c linux/arch/i386/kernel/irq.c
--- v2.2.0-pre8/linux/arch/i386/kernel/irq.c	Thu Dec 31 10:28:59 1998
+++ linux/arch/i386/kernel/irq.c	Wed Jan 20 13:00:17 1999
@@ -15,6 +15,7 @@
X  * Naturally it's not a 1:1 relation, but there are similarities.
X  */
X 
+#include <linux/config.h>
X #include <linux/ptrace.h>
X #include <linux/errno.h>
X #include <linux/kernel_stat.h>
@@ -47,46 +48,28 @@
X atomic_t nmi_counter;
X 
X /*
- * About the IO-APIC, the architecture is 'merged' into our
- * current irq architecture, seemlessly. (i hope). It is only
- * visible through a few more more hardware interrupt lines, but 
- * otherwise drivers are unaffected. The main code is believed
- * to be NR_IRQS-safe (nothing anymore thinks we have 16
- * irq lines only), but there might be some places left ...
+ * Linux has a controller-independent x86 interrupt architecture.
+ * every controller has a 'controller-template', that is used
+ * by the main code to do the right thing. Each driver-visible
+ * interrupt source is transparently wired to the apropriate
+ * controller. Thus drivers need not be aware of the
+ * interrupt-controller.
+ *
+ * Various interrupt controllers we handle: 8259 PIC, SMP IO-APIC,
+ * PIIX4's internal 8259 PIC and SGI's Visual Workstation Cobalt (IO-)APIC.
+ * (IO-APICs assumed to be messaging to Pentium local-APICs)
+ *
+ * the code is designed to be easily extended with new/different
+ * interrupt controllers, without having to do assembly magic.
X  */
X 
X /*
- * This contains the irq mask for both 8259A irq controllers,
+ * Micro-access to controllers is serialized over the whole
+ * system. We never hold this lock when we call the actual
+ * IRQ handler.
X  */
-static unsigned int cached_irq_mask = 0xffff;
-
-#define __byte(x,y) (((unsigned char *)&(y))[x])
-#define __word(x,y) (((unsigned short *)&(y))[x])
-#define __long(x,y) (((unsigned int *)&(y))[x])
-
-#define cached_21	(__byte(0,cached_irq_mask))
-#define cached_A1	(__byte(1,cached_irq_mask))
-
X spinlock_t irq_controller_lock;
X 
-/*
- * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
- * boards the timer interrupt is not connected to any IO-APIC pin, it's
- * fed to the CPU IRQ line directly.
- *
- * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
- * this 'mixed mode' IRQ handling costs us one more branch in do_IRQ,
- * but we have _much_ higher compatibility and robustness this way.
- */
-unsigned long long io_apic_irqs = 0;
-
-static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs);
-static void enable_8259A_irq(unsigned int irq);
-void disable_8259A_irq(unsigned int irq);
-
-/* startup is the same as "enable", shutdown is same as "disable" */
-#define startup_8259A_irq	enable_8259A_irq
-#define shutdown_8259A_irq	disable_8259A_irq
X 
X /*
X  * Dummy controller type for unused interrupts
@@ -108,6 +91,19 @@
X 	disable_none
X };
X 
+/*
+ * This is the 'legacy' 8259A Programmable Interrupt Controller,
+ * present in the majority of PC/AT boxes.
+ */
+
+static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs);
+static void enable_8259A_irq(unsigned int irq);
+void disable_8259A_irq(unsigned int irq);
+
+/* startup is the same as "enable", shutdown is same as "disable" */
+#define startup_8259A_irq	enable_8259A_irq
+#define shutdown_8259A_irq	disable_8259A_irq
+
X static struct hw_interrupt_type i8259A_irq_type = {
X 	"XT-PIC",
X 	startup_8259A_irq,
@@ -117,11 +113,38 @@
X 	disable_8259A_irq
X };
X 
-irq_desc_t irq_desc[NR_IRQS] = {
-	[0 ... 15] = { 0, &i8259A_irq_type, },		/* default to standard ISA IRQs */
-	[16 ... NR_IRQS-1] = { 0, &no_irq_type, },	/* 'high' PCI IRQs filled in on demand */
-};
+/*
+ * Controller mappings for all interrupt sources:
+ */
+irq_desc_t irq_desc[NR_IRQS] = { [0 ... NR_IRQS-1] = { 0, &no_irq_type, }};
+
+
+/*
+ * 8259A PIC functions to handle ISA devices:
+ */
+
+/*
+ * This contains the irq mask for both 8259A irq controllers,
+ */
+static unsigned int cached_irq_mask = 0xffff;
+
+#define __byte(x,y) (((unsigned char *)&(y))[x])
+#define __word(x,y) (((unsigned short *)&(y))[x])
+#define __long(x,y) (((unsigned int *)&(y))[x])
+
+#define cached_21	(__byte(0,cached_irq_mask))
+#define cached_A1	(__byte(1,cached_irq_mask))
X 
+/*
+ * Not all IRQs can be routed through the IO-APIC, eg. on certain (older)
+ * boards the timer interrupt is not connected to any IO-APIC pin, it's
+ * fed to the CPU IRQ line directly.
+ *
+ * Any '1' bit in this mask means the IRQ is routed through the IO-APIC.
+ * this 'mixed mode' IRQ handling costs us one more branch in do_IRQ,
+ * but we have _much_ higher compatibility and robustness this way.
+ */
+unsigned long long io_apic_irqs = 0;
X 
X /*
X  * These have to be protected by the irq controller spinlock
@@ -149,6 +172,77 @@
X 	}
X }
X 
+int i8259A_irq_pending(unsigned int irq)
+{
+	unsigned int mask = 1<<irq;
+
+	if (irq < 8)
+                return (inb(0x20) & mask);
+        return (inb(0xA0) & (mask >> 8));
+}
+
+void make_8259A_irq(unsigned int irq)
+{
+	disable_irq(irq);
+	__long(0,io_apic_irqs) &= ~(1<<irq);
+	irq_desc[irq].handler = &i8259A_irq_type;
+	enable_irq(irq);
+}
+
+/*
+ * Careful! The 8259A is a fragile beast, it pretty
+ * much _has_ to be done exactly like this (mask it
+ * first, _then_ send the EOI, and the order of EOI
+ * to the two 8259s is important!
+ */
+static inline void mask_and_ack_8259A(unsigned int irq)
+{
+	cached_irq_mask |= 1 << irq;
+	if (irq & 8) {
+		inb(0xA1);	/* DUMMY */
+		outb(cached_A1,0xA1);
+		outb(0x62,0x20);	/* Specific EOI to cascade */
+		outb(0x20,0xA0);
+	} else {
+		inb(0x21);	/* DUMMY */
+		outb(cached_21,0x21);
+		outb(0x20,0x20);
+	}
+}
+
+static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs)
+{
+	struct irqaction * action;
+	irq_desc_t *desc = irq_desc + irq;
+
+	spin_lock(&irq_controller_lock);
+	{
+		unsigned int status;
+		mask_and_ack_8259A(irq);
+		status = desc->status & ~IRQ_REPLAY;
+		action = NULL;
+		if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+			action = desc->action;
+		desc->status = status | IRQ_INPROGRESS;
+	}
+	spin_unlock(&irq_controller_lock);
+
+	/* Exit early if we had no action or it was disabled */
+	if (!action)
+		return;
+
+	handle_IRQ_event(irq, regs, action);
+
+	spin_lock(&irq_controller_lock);
+	{
+		unsigned int status = desc->status & ~IRQ_INPROGRESS;
+		desc->status = status;
+		if (!(status & IRQ_DISABLED))
+			enable_8259A_irq(irq);
+	}
+	spin_unlock(&irq_controller_lock);
+}
+
X /*
X  * This builds up the IRQ handler stubs using some ugly macros in irq.h
X  *
@@ -168,8 +262,7 @@
X BUILD_IRQ(8)  BUILD_IRQ(9)  BUILD_IRQ(10) BUILD_IRQ(11)
X BUILD_IRQ(12) BUILD_IRQ(13) BUILD_IRQ(14) BUILD_IRQ(15)
X 
-#ifdef __SMP__
-
+#ifdef CONFIG_X86_IO_APIC
X /*
X  * The IO-APIC gives us many more interrupt sources..
X  */
@@ -185,7 +278,9 @@
X BUILD_IRQ(52) BUILD_IRQ(53) BUILD_IRQ(54) BUILD_IRQ(55)
X BUILD_IRQ(56) BUILD_IRQ(57) BUILD_IRQ(58) BUILD_IRQ(59)
X BUILD_IRQ(60) BUILD_IRQ(61) BUILD_IRQ(62) BUILD_IRQ(63)
+#endif
X 
+#ifdef __SMP__
X /*
X  * The following vectors are part of the Linux architecture, there
X  * is no hardware IRQ pin equivalent for them, they are triggered
@@ -213,7 +308,7 @@
X 	IRQ4_interrupt, IRQ5_interrupt, IRQ6_interrupt, IRQ7_interrupt,
X 	IRQ8_interrupt, IRQ9_interrupt, IRQ10_interrupt, IRQ11_interrupt,
X 	IRQ12_interrupt, IRQ13_interrupt, IRQ14_interrupt, IRQ15_interrupt
-#ifdef __SMP__
+#ifdef CONFIG_X86_IO_APIC
X 	,IRQ16_interrupt, IRQ17_interrupt, IRQ18_interrupt, IRQ19_interrupt,
X 	IRQ20_interrupt, IRQ21_interrupt, IRQ22_interrupt, IRQ23_interrupt,
X 	IRQ24_interrupt, IRQ25_interrupt, IRQ26_interrupt, IRQ27_interrupt,
@@ -231,12 +326,16 @@
X #endif
X };
X 
+
X /*
X  * Initial irq handlers.
X  */
X 
-static void no_action(int cpl, void *dev_id, struct pt_regs *regs) { }
+void no_action(int cpl, void *dev_id, struct pt_regs *regs)
+{
+}
X 
+#ifndef CONFIG_VISWS
X /*
X  * Note that on a 486, we don't want to do a SIGFPE on an irq13
X  * as the irq is unreliable, and exception 16 works correctly
@@ -262,7 +361,13 @@
X /*
X  * IRQ2 is cascade interrupt to second interrupt controller
X  */
+
X static struct irqaction irq2  = { no_action, 0, 0, "cascade", NULL, NULL};
+#endif
+
+/*
+ * Generic, controller-independent functions:
+ */
X 
X int get_irq_list(char *buf)
X {
@@ -351,7 +456,6 @@
X 	}
X }
X 	
-
X #define MAXCOUNT 100000000
X 
X static inline void wait_on_bh(void)
@@ -608,79 +712,6 @@
X 	return status;
X }
X 
-int i8259A_irq_pending(unsigned int irq)
-{
-	unsigned int mask = 1<<irq;
-
-	if (irq < 8)
-                return (inb(0x20) & mask);
-        return (inb(0xA0) & (mask >> 8));
-}
-
-
-void make_8259A_irq(unsigned int irq)
-{
-	disable_irq(irq);
-	__long(0,io_apic_irqs) &= ~(1<<irq);
-	irq_desc[irq].handler = &i8259A_irq_type;
-	enable_irq(irq);
-}
-
-/*
- * Careful! The 8259A is a fragile beast, it pretty
- * much _has_ to be done exactly like this (mask it
- * first, _then_ send the EOI, and the order of EOI
- * to the two 8259s is important!
- */
-static inline void mask_and_ack_8259A(unsigned int irq)
-{
-	cached_irq_mask |= 1 << irq;
-	if (irq & 8) {
-		inb(0xA1);	/* DUMMY */
-		outb(cached_A1,0xA1);
-		outb(0x62,0x20);	/* Specific EOI to cascade */
-		outb(0x20,0xA0);
-	} else {
-		inb(0x21);	/* DUMMY */
-		outb(cached_21,0x21);
-		outb(0x20,0x20);
-	}
-}
-
-static void do_8259A_IRQ(unsigned int irq, struct pt_regs * regs)
-{
-	struct irqaction * action;
-	irq_desc_t *desc = irq_desc + irq;
-
-	spin_lock(&irq_controller_lock);
-	{
-		unsigned int status;
-		mask_and_ack_8259A(irq);
-		status = desc->status & ~IRQ_REPLAY;
-		action = NULL;
-		if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-			action = desc->action;
-		desc->status = status | IRQ_INPROGRESS;
-	}
-	spin_unlock(&irq_controller_lock);
-
-	/* Exit early if we had no action or it was disabled */
-	if (!action)
-		return;
-
-	handle_IRQ_event(irq, regs, action);
-
-	spin_lock(&irq_controller_lock);
-	{
-		unsigned int status = desc->status & ~IRQ_INPROGRESS;
-		desc->status = status;
-		if (!(status & IRQ_DISABLED))
-			enable_8259A_irq(irq);
-	}
-	spin_unlock(&irq_controller_lock);
-}
-
-
X /*
X  * Generic enable/disable code: this just calls
X  * down into the PIC-specific version for the actual
@@ -955,21 +986,75 @@
X 	return irq_found;
X }
X 
-__initfunc(void init_IRQ(void))
+/*
+ * Silly, horrible hack
+ */
+static char uglybuffer[10*256];
+
+__asm__("\n" __ALIGN_STR"\n"
+	"common_unexpected:\n\t"
+	SAVE_ALL
+	"pushl $ret_from_intr\n\t"
+	"jmp strange_interrupt");
+
+void strange_interrupt(int irqnum)
+{
+	printk("Unexpected interrupt %d\n", irqnum & 255);
+	for (;;);
+}
+
+extern int common_unexpected;
+__initfunc(void init_unexpected_irq(void))
X {
X 	int i;
+	for (i = 0; i < 256; i++) {
+		char *code = uglybuffer + 10*i;
+		unsigned long jumpto = (unsigned long) &common_unexpected;
+
+		jumpto -= (unsigned long)(code+10);
+		code[0] = 0x68;		/* pushl */
+		*(int *)(code+1) = i - 512;
+		code[5] = 0xe9;		/* jmp */
+		*(int *)(code+6) = jumpto;
+
+		set_intr_gate(i,code);
+	}
+}
X 
-	/* set the clock to 100 Hz */
-	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
-	outb_p(LATCH & 0xff , 0x40);	/* LSB */
-	outb(LATCH >> 8 , 0x40);	/* MSB */
X 
-	for (i=0; i<NR_IRQS; i++)
+void init_ISA_irqs (void)
+{
+	int i;
+
+	for (i = 0; i < NR_IRQS; i++) {
X 		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 0;
+
+		if (i < 16) {
+			/*
+			 * 16 old-style INTA-cycle interrupt gates:
+			 */
+			irq_desc[i].handler = &i8259A_irq_type;
+		} else {
+			/*
+			 * 'high' PCI IRQs filled in on demand
+			 */
+			irq_desc[i].handler = &no_irq_type;
+		}
+	}
+}
+
+__initfunc(void init_IRQ(void))
+{
+	int i;
+
+#ifndef CONFIG_X86_VISWS_APIC
+	init_ISA_irqs();
+#else
+	init_VISWS_APIC_irqs();
+#endif
X 
-	/*
-	 * 16 old-style INTA-cycle interrupt gates:
-	 */
X 	for (i = 0; i < 16; i++)
X 		set_intr_gate(0x20+i,interrupt[i]);
X 
@@ -1008,12 +1093,22 @@
X #endif	
X 	request_region(0x20,0x20,"pic1");
X 	request_region(0xa0,0x20,"pic2");
+
+	/*
+	 * Set the clock to 100 Hz, we already have a valid
+	 * vector now:
+	 */
+	outb_p(0x34,0x43);		/* binary, mode 2, LSB/MSB, ch 0 */
+	outb_p(LATCH & 0xff , 0x40);	/* LSB */
+	outb(LATCH >> 8 , 0x40);	/* MSB */
+
+#ifndef CONFIG_VISWS
X 	setup_x86_irq(2, &irq2);
X 	setup_x86_irq(13, &irq13);
+#endif
X }
X 
-#ifdef __SMP__
-
+#ifdef CONFIG_X86_IO_APIC
X __initfunc(void init_IRQ_SMP(void))
X {
X 	int i;
@@ -1021,5 +1116,5 @@
X 		if (IO_APIC_VECTOR(i) > 0)
X 			set_intr_gate(IO_APIC_VECTOR(i), interrupt[i]);
X }
-
X #endif
+
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/irq.h linux/arch/i386/kernel/irq.h
--- v2.2.0-pre8/linux/arch/i386/kernel/irq.h	Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/kernel/irq.h	Wed Jan 20 16:23:00 1999
@@ -69,6 +69,7 @@
X 
X extern void init_IRQ_SMP(void);
X extern int handle_IRQ_event(unsigned int, struct pt_regs *, struct irqaction *);
+extern int setup_x86_irq(unsigned int, struct irqaction *);
X 
X /*
X  * Various low-level irq details needed by irq.c, process.c,
@@ -77,16 +78,19 @@
X  * Interrupt entry/exit code at both C and assembly level
X  */
X 
+extern void no_action(int cpl, void *dev_id, struct pt_regs *regs);
X extern void mask_irq(unsigned int irq);
X extern void unmask_irq(unsigned int irq);
X extern void disable_8259A_irq(unsigned int irq);
X extern int i8259A_irq_pending(unsigned int irq);
X extern void ack_APIC_irq(void);
+extern void FASTCALL(send_IPI_self(int vector));
+extern void smp_send_mtrr(void);
+extern void init_VISWS_APIC_irqs(void);
X extern void setup_IO_APIC(void);
X extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn);
X extern void make_8259A_irq(unsigned int irq);
-extern void FASTCALL(send_IPI_self(int vector));
-extern void smp_send_mtrr(void);
+extern void send_IPI(int dest, int vector);
X extern void init_pic_mode(void);
X extern void print_IO_APIC(void);
X 
@@ -103,11 +107,7 @@
X extern char ioapic_OEM_ID [16];
X extern char ioapic_Product_ID [16];
X 
-extern spinlock_t irq_controller_lock; /*
-					* Protects both the 8259 and the
-					* IO-APIC
-					*/
-
+extern spinlock_t irq_controller_lock;
X 
X #ifdef __SMP__
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c
--- v2.2.0-pre8/linux/arch/i386/kernel/process.c	Tue Jan 19 11:32:51 1999
+++ linux/arch/i386/kernel/process.c	Wed Jan 20 11:08:24 1999
@@ -785,6 +785,21 @@
X }
X 
X /*
+ * 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.esp, ®s);
+}
+
+/*
X  * sys_execve() executes a new program.
X  */
X asmlinkage int sys_execve(struct pt_regs regs)
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/setup.c linux/arch/i386/kernel/setup.c
--- v2.2.0-pre8/linux/arch/i386/kernel/setup.c	Fri Jan  8 22:36:01 1999
+++ linux/arch/i386/kernel/setup.c	Wed Jan 20 10:18:53 1999
@@ -38,6 +38,7 @@
X #include <asm/system.h>
X #include <asm/io.h>
X #include <asm/smp.h>
+#include <asm/cobalt.h>
X 
X /*
X  * Machine setup..
@@ -107,6 +108,132 @@
X #define RAMDISK_PROMPT_FLAG		0x8000
X #define RAMDISK_LOAD_FLAG		0x4000	
X 
+#ifdef	CONFIG_VISWS
+char visws_board_type = -1;
+char visws_board_rev = -1;
+
+#define	PIIX_PM_START		0x0F80
+
+#define	SIO_GPIO_START		0x0FC0
+
+#define	SIO_PM_START		0x0FC8
+
+#define	PMBASE			PIIX_PM_START
+#define	GPIREG0			(PMBASE+0x30)
+#define	GPIREG(x)		(GPIREG0+((x)/8))
+#define	PIIX_GPI_BD_ID1		18
+#define	PIIX_GPI_BD_REG		GPIREG(PIIX_GPI_BD_ID1)
+
+#define	PIIX_GPI_BD_SHIFT	(PIIX_GPI_BD_ID1 % 8)
+
+#define	SIO_INDEX	0x2e
+#define	SIO_DATA	0x2f
+
+#define	SIO_DEV_SEL	0x7
+#define	SIO_DEV_ENB	0x30
+#define	SIO_DEV_MSB	0x60
+#define	SIO_DEV_LSB	0x61
+
+#define	SIO_GP_DEV	0x7
+
+#define	SIO_GP_BASE	SIO_GPIO_START
+#define	SIO_GP_MSB	(SIO_GP_BASE>>8)
+#define	SIO_GP_LSB	(SIO_GP_BASE&0xff)
+
+#define	SIO_GP_DATA1	(SIO_GP_BASE+0)
+
+#define	SIO_PM_DEV	0x8
+
+#define	SIO_PM_BASE	SIO_PM_START
+#define	SIO_PM_MSB	(SIO_PM_BASE>>8)
+#define	SIO_PM_LSB	(SIO_PM_BASE&0xff)
+#define	SIO_PM_INDEX	(SIO_PM_BASE+0)
+#define	SIO_PM_DATA	(SIO_PM_BASE+1)
+
+#define	SIO_PM_FER2	0x1
+
+#define	SIO_PM_GP_EN	0x80
+
+static void
+visws_get_board_type_and_rev(void)
+{
+	int raw;
+
+	visws_board_type = (char)(inb_p(PIIX_GPI_BD_REG) & PIIX_GPI_BD_REG)
+							 >> PIIX_GPI_BD_SHIFT;
+/*
+ * Get Board rev.
+ * First, we have to initialize the 307 part to allow us access
+ * to the GPIO registers.  Let's map them at 0x0fc0 which is right
+ * after the PIIX4 PM section.
+ */
+	outb_p(SIO_DEV_SEL, SIO_INDEX);
+	outb_p(SIO_GP_DEV, SIO_DATA);	/* Talk to GPIO regs. */
+    
+	outb_p(SIO_DEV_MSB, SIO_INDEX);
+	outb_p(SIO_GP_MSB, SIO_DATA);	/* MSB of GPIO base address */
+
+	outb_p(SIO_DEV_LSB, SIO_INDEX);
+	outb_p(SIO_GP_LSB, SIO_DATA);	/* LSB of GPIO base address */
+
+	outb_p(SIO_DEV_ENB, SIO_INDEX);
+	outb_p(1, SIO_DATA);		/* Enable GPIO registers. */
+    
+/*
+ * Now, we have to map the power management section to write
+ * a bit which enables access to the GPIO registers.
+ * What lunatic came up with this shit?
+ */
+	outb_p(SIO_DEV_SEL, SIO_INDEX);
+	outb_p(SIO_PM_DEV, SIO_DATA);	/* Talk to GPIO regs. */
+
+	outb_p(SIO_DEV_MSB, SIO_INDEX);
+	outb_p(SIO_PM_MSB, SIO_DATA);	/* MSB of PM base address */
+    
+	outb_p(SIO_DEV_LSB, SIO_INDEX);
+	outb_p(SIO_PM_LSB, SIO_DATA);	/* LSB of PM base address */
+
+	outb_p(SIO_DEV_ENB, SIO_INDEX);
+	outb_p(1, SIO_DATA);		/* Enable PM registers. */
+    
+/*
+ * Now, write the PM register which enables the GPIO registers.
+ */
+	outb_p(SIO_PM_FER2, SIO_PM_INDEX);
+	outb_p(SIO_PM_GP_EN, SIO_PM_DATA);
+    
+/*
+ * Now, initialize the GPIO registers.
+ * We want them all to be inputs which is the
+ * power on default, so let's leave them alone.
+ * So, let's just read the board rev!
+ */
+	raw = inb_p(SIO_GP_DATA1);
+	raw &= 0x7f;	/* 7 bits of valid board revision ID. */
+
+	if (visws_board_type == VISWS_320) {
+		if (raw < 0x6) {
+			visws_board_rev = 4;
+		} else if (raw < 0xc) {
+			visws_board_rev = 5;
+		} else {
+			visws_board_rev = 6;
+	
+		}
+	} else if (visws_board_type == VISWS_540) {
+			visws_board_rev = 2;
+		} else {
+			visws_board_rev = raw;
+		}
+
+		printk("Silicon Graphics %s (rev %d)\n",
+			visws_board_type == VISWS_320 ? "320" :
+			(visws_board_type == VISWS_540 ? "540" :
+					"unknown"),
+					visws_board_rev);
+	}
+#endif
+
X 
X static char command_line[COMMAND_LINE_SIZE] = { 0, };
X        char saved_command_line[COMMAND_LINE_SIZE];
@@ -122,6 +249,10 @@
X 	if (smptrap)
X 		return;
X 	smptrap=1;
+
+#ifdef CONFIG_VISWS
+	visws_get_board_type_and_rev();
+#endif
X 
X  	ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
X  	drive_info = DRIVE_INFO;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
--- v2.2.0-pre8/linux/arch/i386/kernel/smp.c	Thu Jan  7 15:11:35 1999
+++ linux/arch/i386/kernel/smp.c	Wed Jan 20 10:18:53 1999
@@ -36,7 +36,6 @@
X #include <linux/kernel_stat.h>
X #include <linux/delay.h>
X #include <linux/mc146818rtc.h>
-#include <asm/i82489.h>
X #include <linux/smp_lock.h>
X #include <linux/interrupt.h>
X #include <linux/init.h>
@@ -198,6 +197,19 @@
X 	apic_write(APIC_EOI, 0);
X }
X 
+#ifdef CONFIG_X86_VISWS_APIC
+/*
+ * hacky!
+ */
+int __init smp_scan_config(unsigned long base, unsigned long length)
+{
+	cpu_present_map |= 2; /* or in id 1 */
+	apic_version[1] |= 0x10; /* integrated APIC */
+	num_processors = 2;
+
+	return 1;
+} 
+#else
X /*
X  *	Checksum an MP configuration block.
X  */
@@ -567,6 +579,7 @@
X 
X 	return 0;
X }
+#endif
X 
X /*
X  *	Trampoline 80x86 program as an array.
@@ -673,7 +686,9 @@
X 	memory_start = PAGE_ALIGN(memory_start);
X 	if (smp_found_config) {
X 		apic_phys = mp_lapic_addr;
+#ifdef CONFIG_X86_IO_APIC
X 		ioapic_phys = mp_ioapic_addr;
+#endif
X 	} else {
X 		/*
X 		 * set up a fake all zeroes page to simulate the
@@ -687,11 +702,13 @@
X 		memory_start += 2*PAGE_SIZE;
X 	}
X 
+#ifdef CONFIG_X86_IO_APIC
X 	set_fixmap(FIX_APIC_BASE,apic_phys);
X 	set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
X 
X 	printk("mapped APIC to %08lx (%08lx)\n", APIC_BASE, apic_phys);
X 	printk("mapped IOAPIC to %08lx (%08lx)\n", fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
+#endif
X 
X 	return memory_start;
X }
@@ -1117,6 +1134,7 @@
X 
X 	cpu_number_map[boot_cpu_id] = 0;
X 
+#ifdef CONFIG_X86_IO_APIC
X 	/*
X 	 *	If we don't conform to the Intel MPS standard, get out
X 	 *	of here now!
@@ -1129,6 +1147,7 @@
X 		cpu_online_map = cpu_present_map;
X 		goto smp_done;
X 	}
+#endif
X 
X 	/*
X 	 *	If SMP should be disabled, then really disable it!
@@ -1282,14 +1301,15 @@
X 	SMP_PRINTK(("Boot done.\n"));
X 
X 	cache_APIC_registers();
+#ifdef CONFIG_X86_IO_APIC
X 	/*
X 	 * Here we can be sure that there is an IO-APIC in the system. Let's
X 	 * go and set it up:
X 	 */
X 	if (!skip_ioapic_setup) 
X 		setup_IO_APIC();
-
X smp_done:
+#endif
X }
X 
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/time.c linux/arch/i386/kernel/time.c
--- v2.2.0-pre8/linux/arch/i386/kernel/time.c	Fri Jan  1 12:58:19 1999
+++ linux/arch/i386/kernel/time.c	Wed Jan 20 10:18:53 1999
@@ -12,6 +12,8 @@
X  *      precision CMOS clock update
X  * 1996-05-03    Ingo Molnar
X  *      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
X  * 1998-09-05    (Various)
X  *	More robust do_fast_gettimeoffset() algorithm implemented
X  *	(works with APM, Cyrix 6x86MX and Centaur C6),
@@ -63,12 +65,14 @@
X #include <linux/timex.h>
X #include <linux/config.h>
X 
+#include <asm/fixmap.h>
+#include <asm/cobalt.h>
+
X /*
X  * for x86_do_profile()
X  */
X #include "irq.h"
X 
-extern int setup_x86_irq(int, struct irqaction *);
X 
X unsigned long cpu_hz;	/* Detected as we calibrate the TSC */
X 
@@ -286,9 +290,11 @@
X 	}
X 
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = MAXPHASE;
-	time_esterror = MAXPHASE;
+	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;
X 	write_unlock_irq(&xtime_lock);
X }
X 
@@ -366,6 +372,10 @@
X  */
X static inline void do_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
X {
+#ifdef CONFIG_VISWS
+	/* Clear the interrupt */
+	co_cpu_write(CO_CPU_STAT,co_cpu_read(CO_CPU_STAT) & ~CO_STAT_TIMEINTR);
+#endif
X 	do_timer(regs);
X /*
X  * In the SMP case we use the local APIC timer interrupt to do the
@@ -385,9 +395,10 @@
X 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
X 	 * called as close as possible to 500 ms before the new second starts.
X 	 */
-	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 500000 - (tick >> 1) &&
-	    xtime.tv_usec < 500000 + (tick >> 1)) {
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
X 		if (set_rtc_mmss(xtime.tv_sec) == 0)
X 			last_rtc_update = xtime.tv_sec;
X 		else
@@ -663,5 +674,22 @@
X 			printk("Detected %ld Hz processor.\n", cpu_hz);
X 		}
X 	}
+
+#ifdef CONFIG_VISWS
+	printk("Starting Cobalt Timer system clock\n");
+
+	/* Set the countdown value */
+	co_cpu_write(CO_CPU_TIMEVAL, CO_TIME_HZ/HZ);
+
+	/* Start the timer */
+	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) | CO_CTRL_TIMERUN);
+
+	/* Enable (unmask) the timer interrupt */
+	co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
+
+	/* Wire cpu IDT entry to s/w handler (and Cobalt APIC to IDT) */
+	setup_x86_irq(CO_IRQ_TIMER, &irq0);
+#else
X 	setup_x86_irq(0, &irq0);
+#endif
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
--- v2.2.0-pre8/linux/arch/i386/kernel/traps.c	Mon Dec 28 15:00:52 1998
+++ linux/arch/i386/kernel/traps.c	Wed Jan 20 10:18:53 1999
@@ -34,6 +34,14 @@
X #include <asm/debugreg.h>
X #include <asm/desc.h>
X 
+#include <asm/smp.h>
+
+#ifdef CONFIG_X86_VISWS_APIC
+#include <asm/fixmap.h>
+#include <asm/cobalt.h>
+#include <asm/lithium.h>
+#endif
+
X asmlinkage int system_call(void);
X asmlinkage void lcall7(void);
X 
@@ -569,9 +577,100 @@
X 	_set_tssldt_desc(gdt_table+FIRST_LDT_ENTRY+(n<<1), (int)addr, ((size << 3) - 1), 0x82);
X }
X 
+#ifdef CONFIG_X86_VISWS_APIC
+
+/*
+ * On Rev 005 motherboards legacy device interrupt lines are wired directly
+ * to Lithium from the 307.  But the PROM leaves the interrupt type of each
+ * 307 logical device set appropriate for the 8259.  Later we'll actually use
+ * the 8259, but for now we have to flip the interrupt types to
+ * level triggered, active lo as required by Lithium.
+ */
+
+#define	REG	0x2e	/* The register to read/write */
+#define	DEV	0x07	/* Register: Logical device select */
+#define	VAL	0x2f	/* The value to read/write */
+
+static void
+superio_outb(int dev, int reg, int val)
+{
+	outb(DEV, REG);
+	outb(dev, VAL);
+	outb(reg, REG);
+	outb(val, VAL);
+}
+
+static int __attribute__ ((unused))
+superio_inb(int dev, int reg)
+{
+	outb(DEV, REG);
+	outb(dev, VAL);
+	outb(reg, REG);
+	return inb(VAL);
+}
+
+#define	FLOP	3	/* floppy logical device */
+#define	PPORT	4	/* parallel logical device */
+#define	UART5	5	/* uart2 logical device (not wired up) */
+#define	UART6	6	/* uart1 logical device (THIS is the serial port!) */
+#define	IDEST	0x70	/* int. destination (which 307 IRQ line) reg. */
+#define	ITYPE	0x71	/* interrupt type register */
+
+/* interrupt type bits */
+#define	LEVEL	0x01	/* bit 0, 0 == edge triggered */
+#define	ACTHI	0x02	/* bit 1, 0 == active lo */
+
+static void
+superio_init(void)
+{
+	if (visws_board_type == VISWS_320 && visws_board_rev == 5) {
+		superio_outb(UART6, IDEST, 0);	/* 0 means no intr propagated */
+		printk("SGI 320 rev 5: disabling 307 uart1 interrupt\n");
+	}
+}
+
+static void
+lithium_init(void)
+{
+	set_fixmap(FIX_LI_PCIA, LI_PCI_A_PHYS);
+	printk("Lithium PCI Bridge A, Bus Number: %d\n",
+				li_pcia_read16(LI_PCI_BUSNUM) & 0xff);
+	set_fixmap(FIX_LI_PCIB, LI_PCI_B_PHYS);
+	printk("Lithium PCI Bridge B (PIIX4), Bus Number: %d\n",
+				li_pcib_read16(LI_PCI_BUSNUM) & 0xff);
+
+	/* XXX blindly enables all interrupts */
+	li_pcia_write16(LI_PCI_INTEN, 0xffff);
+	li_pcib_write16(LI_PCI_INTEN, 0xffff);
+}
+
+static void
+cobalt_init(void)
+{
+	/*
+	 * On normal SMP PC this is used only with SMP, but we have to
+	 * use it and set it up here to start the Cobalt clock
+	 */
+	set_fixmap(FIX_APIC_BASE, APIC_PHYS_BASE);
+	printk("Local APIC ID %lx\n", apic_read(APIC_ID));
+	printk("Local APIC Version %lx\n", apic_read(APIC_VERSION));
+
+	set_fixmap(FIX_CO_CPU, CO_CPU_PHYS);
+	printk("Cobalt Revision %lx\n", co_cpu_read(CO_CPU_REV));
+
+	set_fixmap(FIX_CO_APIC, CO_APIC_PHYS);
+	printk("Cobalt APIC ID %lx\n", co_apic_read(CO_APIC_ID));
+
+	/* Enable Cobalt APIC being careful to NOT change the ID! */
+	co_apic_write(CO_APIC_ID, co_apic_read(CO_APIC_ID)|CO_APIC_ENABLE);
+
+	printk("Cobalt APIC enabled: ID reg %lx\n", co_apic_read(CO_APIC_ID));
+}
+#endif
X void __init trap_init(void)
X {
-	int i;
+	/* Initially up all of the IDT to jump to unexpected */
+	init_unexpected_irq();
X 
X 	if (readl(0x0FFFD9) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
X 		EISA_bus = 1;
@@ -594,8 +693,6 @@
X 	set_trap_gate(15,&spurious_interrupt_bug);
X 	set_trap_gate(16,&coprocessor_error);
X 	set_trap_gate(17,&alignment_check);
-	for (i=18;i<48;i++)
-		set_trap_gate(i,&reserved);
X 	set_system_gate(0x80,&system_call);
X 
X 	/* set up GDT task & ldt entries */
@@ -606,4 +703,9 @@
X 	__asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl");
X 	load_TR(0);
X 	load_ldt(0);
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 01'
echo 'File patch-2.2.0-pre9 is continued in part 02'
echo 02 > _shar_seq_.tmp
exit 0
#!/bin/sh
# this is part 02 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 02; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
+#ifdef CONFIG_X86_VISWS_APIC
+	superio_init();
+	lithium_init();
+	cobalt_init();
+#endif
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/i386/kernel/visws_apic.c linux/arch/i386/kernel/visws_apic.c
--- v2.2.0-pre8/linux/arch/i386/kernel/visws_apic.c	Wed Dec 31 16:00:00 1969
+++ linux/arch/i386/kernel/visws_apic.c	Wed Jan 20 10:18:53 1999
@@ -0,0 +1,407 @@
+/*
+ *	linux/arch/i386/kernel/visws_apic.c
+ *
+ *	Copyright (C) 1999 Bent Hagemark, Ingo Molnar
+ *
+ *  SGI Visual Workstation interrupt controller
+ *
+ *  The Cobalt system ASIC in the Visual Workstation contains a "Cobalt" APIC
+ *  which serves as the main interrupt controller in the system.  Non-legacy
+ *  hardware in the system uses this controller directly.  Legacy devices
+ *  are connected to the PIIX4 which in turn has its 8259(s) connected to
+ *  a of the Cobalt APIC entry.
+ */
+
+#include <linux/ptrace.h>
+#include <linux/errno.h>
+#include <linux/kernel_stat.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/timex.h>
+#include <linux/malloc.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/tasks.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+
+#include <asm/system.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/smp.h>
+#include <asm/pgtable.h>
+#include <asm/delay.h>
+#include <asm/desc.h>
+
+#include <asm/cobalt.h>
+
+#include "irq.h"
+
+/*
+ * This is the PIIX4-based 8259 that is wired up indirectly to Cobalt
+ * -- not the manner expected by the normal 8259 code in irq.c.
+ *
+ * there is a 'master' physical interrupt source that gets sent to
+ * the CPU. But in the chipset there are various 'virtual' interrupts
+ * waiting to be handled. We represent this to Linux through a 'master'
+ * interrupt controller type, and through a special virtual interrupt-
+ * controller. Device drivers only see the virtual interrupt sources.
+ */
+
+#define	CO_IRQ_BASE	0x20	/* This is the 0x20 in init_IRQ()! */
+
+static void startup_piix4_master_irq(unsigned int irq);
+static void shutdown_piix4_master_irq(unsigned int irq);
+static void do_piix4_master_IRQ(unsigned int irq, struct pt_regs * regs);
+#define enable_piix4_master_irq startup_piix4_master_irq
+#define disable_piix4_master_irq shutdown_piix4_master_irq
+
+static struct hw_interrupt_type piix4_master_irq_type = {
+	"PIIX4-master",
+	startup_piix4_master_irq,
+	shutdown_piix4_master_irq,
+	do_piix4_master_IRQ,
+	enable_piix4_master_irq,
+	disable_piix4_master_irq
+};
+
+static void enable_piix4_virtual_irq(unsigned int irq);
+static void disable_piix4_virtual_irq(unsigned int irq);
+#define startup_piix4_virtual_irq enable_piix4_virtual_irq
+#define shutdown_piix4_virtual_irq disable_piix4_virtual_irq
+
+static struct hw_interrupt_type piix4_virtual_irq_type = {
+	"PIIX4-virtual",
+	startup_piix4_virtual_irq,
+	shutdown_piix4_virtual_irq,
+	0, /* no handler, it's never called physically */
+	enable_piix4_virtual_irq,
+	disable_piix4_virtual_irq
+};
+
+/*
+ * This is the SGI Cobalt (IO-)APIC:
+ */
+
+static void do_cobalt_IRQ(unsigned int irq, struct pt_regs * regs);
+static void enable_cobalt_irq(unsigned int irq);
+static void disable_cobalt_irq(unsigned int irq);
+static void startup_cobalt_irq(unsigned int irq);
+#define shutdown_cobalt_irq disable_cobalt_irq
+
+static struct hw_interrupt_type cobalt_irq_type = {
+	"Cobalt-APIC",
+	startup_cobalt_irq,
+	shutdown_cobalt_irq,
+	do_cobalt_IRQ,
+	enable_cobalt_irq,
+	disable_cobalt_irq
+};
+
+
+/*
+ * Not an initfunc, needed by the reboot code
+ */
+void init_pic_mode(void)
+{
+	/* Nop on Cobalt */
+} 
+
+/*
+ * Cobalt (IO)-APIC functions to handle PCI devices.
+ */
+
+static void disable_cobalt_irq(unsigned int irq)
+{
+	/* XXX undo the APIC entry here? */
+
+	/*
+	 * definitely, we do not want to have IRQ storms from
+	 * unused devices --mingo
+	 */
+}
+
+static void enable_cobalt_irq(unsigned int irq)
+{
+}
+
+/*
+ * Set the given Cobalt APIC Redirection Table entry to point
+ * to the given IDT vector/index.
+ */
+static void co_apic_set(int entry, int idtvec)
+{
+	co_apic_write(CO_APIC_LO(entry), CO_APIC_LEVEL | (CO_IRQ_BASE+idtvec));
+	co_apic_write(CO_APIC_HI(entry), 0);
+
+	printk("Cobalt APIC Entry %d IDT Vector %d\n", entry, idtvec);
+}
+
+/*
+ * "irq" really just serves to identify the device.  Here is where we
+ * map this to the Cobalt APIC entry where it's physically wired.
+ * This is called via request_irq -> setup_x86_irq -> irq_desc->startup()
+ */
+static void startup_cobalt_irq(unsigned int irq)
+{
+	/*
+	 * These "irq"'s are wired to the same Cobalt APIC entries
+	 * for all (known) motherboard types/revs
+	 */
+	switch (irq) {
+	case CO_IRQ_TIMER:	co_apic_set(CO_APIC_CPU, CO_IRQ_TIMER);
+				return;
+
+	case CO_IRQ_ENET:	co_apic_set(CO_APIC_ENET, CO_IRQ_ENET);
+				return;
+
+	case CO_IRQ_SERIAL:	return; /* XXX move to piix4-8259 "virtual" */
+
+	case CO_IRQ_8259:	co_apic_set(CO_APIC_8259, CO_IRQ_8259);
+				return;
+
+	case CO_IRQ_IDE:
+		switch (visws_board_type) {
+		case VISWS_320:
+			switch (visws_board_rev) {
+			case 5:
+				co_apic_set(CO_APIC_0_5_IDE0, CO_IRQ_IDE);
+				co_apic_set(CO_APIC_0_5_IDE1, CO_IRQ_IDE);
+					return;
+			case 6:
+				co_apic_set(CO_APIC_0_6_IDE0, CO_IRQ_IDE);
+				co_apic_set(CO_APIC_0_6_IDE1, CO_IRQ_IDE);
+					return;
+			}
+		case VISWS_540:
+			switch (visws_board_rev) {
+			case 2:
+				co_apic_set(CO_APIC_1_2_IDE0, CO_IRQ_IDE);
+					return;
+			}
+		}
+		break;
+	default:
+		panic("huh?");
+	}
+}
+
+/*
+ * This is the handle() op in do_IRQ()
+ */
+static void do_cobalt_IRQ(unsigned int irq, struct pt_regs * regs)
+{
+	struct irqaction * action;
+	irq_desc_t *desc = irq_desc + irq;
+
+	spin_lock(&irq_controller_lock);
+	{
+		unsigned int status;
+ /* XXX APIC EOI? */
+		status = desc->status & ~IRQ_REPLAY;
+		action = NULL;
+		if (!(status & (IRQ_DISABLED | IRQ_INPROGRESS)))
+			action = desc->action;
+		desc->status = status | IRQ_INPROGRESS;
+	}
+	spin_unlock(&irq_controller_lock);
+
+	/* Exit early if we had no action or it was disabled */
+	if (!action)
+		return;
+
+	handle_IRQ_event(irq, regs, action);
+
+	(void)co_cpu_read(CO_CPU_REV); /* Sync driver ack to its h/w */
+	apic_write(APIC_EOI, APIC_EIO_ACK); /* Send EOI to Cobalt APIC */
+
+	spin_lock(&irq_controller_lock);
+	{
+		unsigned int status = desc->status & ~IRQ_INPROGRESS;
+		desc->status = status;
+		if (!(status & IRQ_DISABLED))
+ enable_cobalt_irq(irq);
+	}
+	spin_unlock(&irq_controller_lock);
+}
+
+/*
+ * PIIX4-8259 master/virtual functions to handle:
+ *
+ *	floppy
+ *	parallel
+ *	serial
+ *	audio (?)
+ *
+ * None of these get Cobalt APIC entries, neither do they have IDT
+ * entries. These interrupts are purely virtual and distributed from
+ * the 'master' interrupt source: CO_IRQ_8259.
+ *
+ * When the 8259 interrupts its handler figures out which of these
+ * devices is interrupting and dispatches to it's handler.
+ *
+ * CAREFUL: devices see the 'virtual' interrupt only. Thus disable/
+ * enable_irq gets the right irq. This 'master' irq is never directly
+ * manipulated by any driver.
+ */
+
+static void startup_piix4_master_irq(unsigned int irq)
+{
+	/* ICW1 */
+	outb(0x11, 0x20);
+	outb(0x11, 0xa0);
+
+	/* ICW2 */
+	outb(0x08, 0x21);
+	outb(0x70, 0xa1);
+
+	/* ICW3 */
+	outb(0x04, 0x21);
+	outb(0x02, 0xa1);
+
+	/* ICW4 */
+	outb(0x01, 0x21);
+	outb(0x01, 0xa1);
+
+	/* OCW1 - disable all interrupts in both 8259's */
+	outb(0xff, 0x21);
+	outb(0xff, 0xa1);
+
+	startup_cobalt_irq(irq);
+}
+
+static void shutdown_piix4_master_irq(unsigned int irq)
+{
+	/*
+	 * [we skip the 8259 magic here, not strictly necessary]
+	 */
+
+	shutdown_cobalt_irq(irq);
+}
+
+static void do_piix4_master_IRQ(unsigned int irq, struct pt_regs * regs)
+{
+	int realirq, mask;
+
+	/* Find out what's interrupting in the PIIX4 8259 */
+
+	spin_lock(&irq_controller_lock);
+	outb(0x0c, 0x20);		/* OCW3 Poll command */
+	realirq = inb(0x20);
+
+	if (!(realirq & 0x80)) {
+		/*
+		 * Bit 7 == 0 means invalid/spurious
+		 */
+		goto out_unlock;
+	}
+	realirq &= 0x7f;
+
+	/*
+	 * mask and ack the 8259
+	 */
+	mask = inb(0x21);
+	if ((mask >> realirq) & 0x01)
+		/*
+		 * This IRQ is masked... ignore
+		 */
+		goto out_unlock;
+
+	outb(mask | (1<<realirq), 0x21);
+	/*
+	 * OCW2 - non-specific EOI
+	 */
+	outb(0x20, 0x20);
+
+	spin_unlock(&irq_controller_lock);
+
+	/*
+	 * handle this 'virtual interrupt' as a Cobalt one now.
+	 */
+	kstat.irqs[smp_processor_id()][irq]++;
+	do_cobalt_IRQ(realirq, regs);
+
+	spin_lock(&irq_controller_lock);
+	{
+		irq_desc_t *desc = irq_desc + realirq;
+
+		if (!(desc->status & IRQ_DISABLED))
+			enable_piix4_virtual_irq(realirq);
+	}
+	spin_unlock(&irq_controller_lock);
+	return;
+
+out_unlock:
+	spin_unlock(&irq_controller_lock);
+	return;
+}
+
+static void enable_piix4_virtual_irq(unsigned int irq)
+{
+	/*
+	 * assumes this irq is one of the legacy devices
+	 */
+
+	unsigned int mask = inb(0x21);
+ 	mask &= ~(1 << irq);
+	outb(mask, 0x21);
+	enable_cobalt_irq(irq);
+}
+
+/*
+ * assumes this irq is one of the legacy devices
+ */
+static void disable_piix4_virtual_irq(unsigned int irq)
+{
+	unsigned int mask;
+
+	disable_cobalt_irq(irq);
+
+	mask = inb(0x21);
+ 	mask &= ~(1 << irq);
+	outb(mask, 0x21);
+}
+
+static struct irqaction master_action =
+		{ no_action, 0, 0, "PIIX4-8259", NULL, NULL };
+
+void init_VISWS_APIC_irqs(void)
+{
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		irq_desc[i].status = IRQ_DISABLED;
+		irq_desc[i].action = 0;
+		irq_desc[i].depth = 0;
+
+		/*
+		 * Cobalt IRQs are mapped to standard ISA
+		 * interrupt vectors:
+		 */
+		switch (i) {
+			/*
+			 * Only CO_IRQ_8259 will be raised
+			 * externally.
+			 */
+		case CO_IRQ_8259:
+			irq_desc[i].handler = &piix4_master_irq_type;
+			break;
+		case CO_IRQ_FLOPPY:
+		case CO_IRQ_PARLL:
+			irq_desc[i].handler = &piix4_virtual_irq_type;
+			break;
+		default:
+			irq_desc[i].handler = &cobalt_irq_type;
+			break;
+		}
+	}
+
+	/*
+	 * The master interrupt is always present:
+	 */
+	setup_x86_irq(CO_IRQ_8259, &master_action);
+}
+
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/Makefile linux/arch/m68k/Makefile
--- v2.2.0-pre8/linux/arch/m68k/Makefile	Thu Jan  7 15:11:36 1999
+++ linux/arch/m68k/Makefile	Tue Jan 19 10:58:26 1999
@@ -29,12 +29,19 @@
X # without -fno-strength-reduce the 53c7xx.c driver fails ;-(
X CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
X 
-ifdef CONFIG_OPTIMIZE_040
+# enable processor switch if compiled only for a single cpu
+ifndef CONFIG_M68020
+ifndef CONFIG_M68030
+
+ifndef CONFIG_M68060
X CFLAGS := $(CFLAGS) -m68040
X endif
X 
-ifdef CONFIG_OPTIMIZE_060
+ifndef CONFIG_M68040
X CFLAGS := $(CFLAGS) -m68060
+endif
+
+endif
X endif
X 
X ifdef CONFIG_KGDB
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/amiga/config.c linux/arch/m68k/amiga/config.c
--- v2.2.0-pre8/linux/arch/m68k/amiga/config.c	Fri Oct  9 13:27:05 1998
+++ linux/arch/m68k/amiga/config.c	Tue Jan 19 10:58:26 1999
@@ -52,7 +52,6 @@
X /* amiga specific keyboard functions */
X extern int amiga_keyb_init(void);
X extern int amiga_kbdrate (struct kbd_repeat *);
-extern void amiga_kbd_reset_setup(char*, int);
X /* amiga specific irq functions */
X extern void amiga_init_IRQ (void);
X extern void (*amiga_default_handler[]) (int, void *, struct pt_regs *);
@@ -343,7 +342,6 @@
X   mach_sched_init      = amiga_sched_init;
X   mach_keyb_init       = amiga_keyb_init;
X   mach_kbdrate         = amiga_kbdrate;
-  kbd_reset_setup      = amiga_kbd_reset_setup;
X   mach_init_IRQ        = amiga_init_IRQ;
X   mach_default_handler = &amiga_default_handler;
X   mach_request_irq     = amiga_request_irq;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/atari/atakeyb.c linux/arch/m68k/atari/atakeyb.c
--- v2.2.0-pre8/linux/arch/m68k/atari/atakeyb.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/m68k/atari/atakeyb.c	Tue Jan 19 10:58:26 1999
@@ -861,8 +861,3 @@
X 	
X 	return( 0 );
X }
-
-/* for "kbd-reset" cmdline param */
-__initfunc(void atari_kbd_reset_setup(char *str, int *ints))
-{
-}
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/atari/config.c linux/arch/m68k/atari/config.c
--- v2.2.0-pre8/linux/arch/m68k/atari/config.c	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/atari/config.c	Tue Jan 19 10:58:26 1999
@@ -60,7 +60,6 @@
X extern int atari_keyb_init(void);
X extern int atari_kbdrate (struct kbd_repeat *);
X extern void atari_kbd_leds (unsigned int);
-extern void atari_kbd_reset_setup(char*, int);
X /* atari specific irq functions */
X extern void atari_init_IRQ (void);
X extern int atari_request_irq (unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
@@ -251,7 +250,6 @@
X     mach_keyb_init       = atari_keyb_init;
X     mach_kbdrate         = atari_kbdrate;
X     mach_kbd_leds        = atari_kbd_leds;
-    kbd_reset_setup      = atari_kbd_reset_setup;
X     mach_init_IRQ        = atari_init_IRQ;
X     mach_request_irq     = atari_request_irq;
X     mach_free_irq        = atari_free_irq;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/config.in linux/arch/m68k/config.in
--- v2.2.0-pre8/linux/arch/m68k/config.in	Tue Jan 19 11:32:51 1999
+++ linux/arch/m68k/config.in	Tue Jan 19 10:58:26 1999
@@ -44,6 +44,7 @@
X if [ "$CONFIG_HP300" = "y" ]; then
X   bool 'DIO bus support' CONFIG_DIO
X fi
+define_bool CONFIG_SUN3 n
X if [ "$CONFIG_PCI" = "y" ]; then
X   bool 'Backward-compatible /proc/pci' CONFIG_PCI_OLD_PROC
X fi
@@ -129,24 +130,24 @@
X comment 'SCSI low-level drivers'
X 
X if [ "$CONFIG_AMIGA" = "y" ]; then
-  tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI
+  dep_tristate 'A3000 WD33C93A support' CONFIG_A3000_SCSI $CONFIG_SCSI
X   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X     bool 'A4000T SCSI support' CONFIG_A4000T_SCSI
X   fi
X fi
X if [ "$CONFIG_ZORRO" = "y" ]; then
-  tristate 'A2091 WD33C93A support' CONFIG_A2091_SCSI
-  tristate 'GVP Series II WD33C93A support' CONFIG_GVP11_SCSI
-  bool 'CyberStorm SCSI support' CONFIG_CYBERSTORM_SCSI
-  bool 'CyberStorm Mk II SCSI support' CONFIG_CYBERSTORMII_SCSI
-  bool 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI
-  bool 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI
-  bool 'Fastlane SCSI support' CONFIG_FASTLANE_SCSI
+  dep_tristate 'A2091 WD33C93A support' CONFIG_A2091_SCSI $CONFIG_SCSI
+  dep_tristate 'GVP Series II WD33C93A support' CONFIG_GVP11_SCSI $CONFIG_SCSI
+  dep_tristate 'CyberStorm SCSI support' CONFIG_CYBERSTORM_SCSI $CONFIG_SCSI
+  dep_tristate 'CyberStorm Mk II SCSI support' CONFIG_CYBERSTORMII_SCSI $CONFIG_SCSI
+  dep_tristate 'Blizzard 2060 SCSI support' CONFIG_BLZ2060_SCSI $CONFIG_SCSI
+  dep_tristate 'Blizzard 1230IV/1260 SCSI support' CONFIG_BLZ1230_SCSI $CONFIG_SCSI
+  dep_tristate 'Fastlane SCSI support' CONFIG_FASTLANE_SCSI $CONFIG_SCSI
X   if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X     bool 'A4091 SCSI support' CONFIG_A4091_SCSI
X     bool 'WarpEngine SCSI support' CONFIG_WARPENGINE_SCSI
X     bool 'Blizzard PowerUP 603e+ SCSI' CONFIG_BLZ603EPLUS_SCSI
-#    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
+    bool 'Cyberstorm Mk III SCSI support' CONFIG_CYBERSTORMIII_SCSI
X #    bool 'GVP Turbo 040/060 SCSI support' CONFIG_GVP_TURBO_SCSI
X   fi
X fi
@@ -162,7 +163,7 @@
X fi
X if [ "$CONFIG_MAC" = "y" ]; then
X   bool 'MAC NCR5380 SCSI' CONFIG_MAC_SCSI
-  bool 'MAC NCR53c9[46] SCSI' CONFIG_SCSI_MAC_ESP
+  dep_tristate 'MAC NCR53c9[46] SCSI' CONFIG_SCSI_MAC_ESP $CONFIG_SCSI
X fi
X #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/defconfig linux/arch/m68k/defconfig
--- v2.2.0-pre8/linux/arch/m68k/defconfig	Tue Dec 22 14:16:54 1998
+++ linux/arch/m68k/defconfig	Tue Jan 19 10:58:26 1999
@@ -75,21 +75,26 @@
X #
X # Networking options
X #
+CONFIG_PACKET=y
X # CONFIG_NETLINK is not set
X # CONFIG_FIREWALL is not set
X # CONFIG_NET_ALIAS is not set
+# CONFIG_FILTER is not set
+CONFIG_UNIX=y
X CONFIG_INET=y
X # CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ACCT is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+# CONFIG_IP_PNP is not set
X # CONFIG_IP_ROUTER is not set
X # CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_IP_ALIAS is not set
+# CONFIG_SYN_COOKIES is not set
X 
X #
X # (it is safe to leave these untouched)
X #
-# CONFIG_INET_PCTCP is not set
X # CONFIG_INET_RARP is not set
-CONFIG_PATH_MTU_DISCOVERY=y
X CONFIG_IP_NOSR=y
X # CONFIG_SKB_LARGE is not set
X # CONFIG_IPV6 is not set
@@ -99,8 +104,20 @@
X #
X # CONFIG_IPX is not set
X # CONFIG_ATALK is not set
-# CONFIG_AX25 is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
X # CONFIG_BRIDGE 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
+# CONFIG_CPU_IS_SLOW is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
X 
X #
X # SCSI support
@@ -113,12 +130,15 @@
X CONFIG_BLK_DEV_SD=y
X CONFIG_CHR_DEV_ST=y
X CONFIG_BLK_DEV_SR=y
+# CONFIG_BLK_DEV_SR_VENDOR is not set
X # CONFIG_CHR_DEV_SG is not set
X 
X #
X # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
X #
X # CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_CONSTANTS=y
+# CONFIG_SCSI_LOGGING is not set
X 
X #
X # SCSI low-level drivers
@@ -147,6 +167,7 @@
X # CONFIG_SLIP is not set
X # CONFIG_PPP is not set
X # CONFIG_ARIADNE is not set
+# CONFIG_ARIADNE2 is not set
X # CONFIG_A2065 is not set
X # CONFIG_HYDRA is not set
X # CONFIG_APNE is not set
@@ -184,7 +205,10 @@
X CONFIG_FB_AMIGA_ECS=y
X CONFIG_FB_AMIGA_AGA=y
X # CONFIG_FB_CYBER is not set
+# CONFIG_FB_VIRGE is not set
+# CONFIG_FB_CVPPC is not set
X # CONFIG_FB_RETINAZ3 is not set
+# CONFIG_FB_CLGEN is not set
X # CONFIG_FB_ATARI is not set
X # CONFIG_FB_VIRTUAL is not set
X # CONFIG_FBCON_ADVANCED is not set
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/fpsp040/skeleton.S linux/arch/m68k/fpsp040/skeleton.S
--- v2.2.0-pre8/linux/arch/m68k/fpsp040/skeleton.S	Tue Aug 18 22:02:03 1998
+++ linux/arch/m68k/fpsp040/skeleton.S	Tue Jan 19 10:58:26 1999
@@ -40,6 +40,7 @@
X 
X #include <linux/linkage.h>
X #include <asm/entry.h>
+#include "../kernel/m68k_defs.h"
X 
X |SKELETON	idnt    2,1 | Motorola 040 Floating Point Software Package
X 
@@ -375,12 +376,12 @@
X 	.global	fpsp_done
X fpsp_done:
X 	btst	#0x5,%sp@		| supervisor bit set in saved SR?
-	beq	Lnotkern
+	beq	.Lnotkern
X 	rte
-Lnotkern:
+.Lnotkern:
X 	SAVE_ALL_INT
X 	GET_CURRENT(%d0)
-	tstl	%curptr@(LTASK_NEEDRESCHED)
+	tstl	%curptr@(TASK_NEEDRESCHED)
X 	jne	SYMBOL_NAME(ret_from_exception)	| deliver signals,
X 						| reschedule etc..
X 	RESTORE_ALL
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/hp300/config.c linux/arch/m68k/hp300/config.c
--- v2.2.0-pre8/linux/arch/m68k/hp300/config.c	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/hp300/config.c	Tue Jan 19 10:58:26 1999
@@ -55,11 +55,6 @@
X {
X }
X 
-/* for "kbd-reset" cmdline param */
-__initfunc(void hp300_kbd_reset_setup(char *str, int i))
-{
-}
-
X static void hp300_get_model(char *model)
X {
X   strcpy(model, "HP9000/300");
@@ -74,7 +69,6 @@
X   mach_init_IRQ        = hp300_init_IRQ;
X   mach_request_irq     = hp300_request_irq;
X   mach_free_irq        = hp300_free_irq;
-  kbd_reset_setup      = hp300_kbd_reset_setup;
X   mach_get_model       = hp300_get_model;
X   mach_get_irq_list    = hp300_get_irq_list;
X   mach_gettimeoffset   = hp300_gettimeoffset;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/ifpsp060/iskeleton.S linux/arch/m68k/ifpsp060/iskeleton.S
--- v2.2.0-pre8/linux/arch/m68k/ifpsp060/iskeleton.S	Mon Aug  3 12:45:44 1998
+++ linux/arch/m68k/ifpsp060/iskeleton.S	Tue Jan 19 10:58:26 1999
@@ -36,6 +36,7 @@
X 
X #include <linux/linkage.h>
X #include <asm/entry.h>
+#include "../kernel/m68k_defs.h"
X 
X 
X |################################
@@ -69,12 +70,12 @@
X 	.global		_060_isp_done
X _060_isp_done:
X 	btst	#0x5,%sp@		| supervisor bit set in saved SR?
-	beq	Lnotkern
+	beq	.Lnotkern
X 	rte
-Lnotkern:
+.Lnotkern:
X 	SAVE_ALL_INT
X 	GET_CURRENT(%d0)
-	tstl	%curptr@(LTASK_NEEDRESCHED)
+	tstl	%curptr@(TASK_NEEDRESCHED)
X 	jne	SYMBOL_NAME(ret_from_exception)	| deliver signals,
X 						| reschedule etc..
X 	RESTORE_ALL
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/entry.S linux/arch/m68k/kernel/entry.S
--- v2.2.0-pre8/linux/arch/m68k/kernel/entry.S	Fri Oct  9 13:27:05 1998
+++ linux/arch/m68k/kernel/entry.S	Tue Jan 19 10:58:26 1999
@@ -34,8 +34,10 @@
X #include <linux/config.h>
X #include <linux/linkage.h>
X #include <asm/entry.h>
+#include <asm/errno.h>
X #include <asm/setup.h>
X #include <asm/segment.h>
+#include <asm/traps.h>
X 
X #include "m68k_defs.h"
X 
@@ -43,7 +45,7 @@
X .globl SYMBOL_NAME(resume), SYMBOL_NAME(ret_from_exception)
X .globl SYMBOL_NAME(ret_from_signal)
X .globl SYMBOL_NAME(inthandler), SYMBOL_NAME(sys_call_table)
-.globl SYMBOL_NAME(sys_fork), SYMBOL_NAME(sys_clone)
+.globl SYMBOL_NAME(sys_fork), SYMBOL_NAME(sys_clone), SYMBOL_NAME(sys_vfork)
X .globl SYMBOL_NAME(ret_from_interrupt), SYMBOL_NAME(bad_interrupt)
X 
X .text
@@ -65,24 +67,24 @@
X 
X ENTRY(reschedule)
X 	| save top of frame
-	movel	%sp,%curptr@(TS_ESP0)
+	movel	%sp,%curptr@(TASK_TSS+TSS_ESP0)
X 
X 	pea	SYMBOL_NAME(ret_from_exception)
X 	jmp	SYMBOL_NAME(schedule)
X 
X badsys:
-	movel	#-LENOSYS,LPT_OFF_D0(%sp)
+	movel	#-ENOSYS,PT_D0(%sp)
X 	jra	SYMBOL_NAME(ret_from_exception)
X 
X do_trace:
-	movel	#-LENOSYS,LPT_OFF_D0(%sp)	| needed for strace
+	movel	#-ENOSYS,PT_D0(%sp)	| needed for strace
X 	subql	#4,%sp
X 	SAVE_SWITCH_STACK
X 	jbsr	SYMBOL_NAME(syscall_trace)
X 	RESTORE_SWITCH_STACK
X 	addql	#4,%sp
X 	jbsr	@(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
-	movel	%d0,%sp@(LPT_OFF_D0)	| save the return value
+	movel	%d0,%sp@(PT_D0)		| save the return value
X 	subql	#4,%sp			| dummy return address
X 	SAVE_SWITCH_STACK
X 	jbsr	SYMBOL_NAME(syscall_trace)
@@ -98,34 +100,34 @@
X 
X 	GET_CURRENT(%d0)
X 	| save top of frame
-	movel	%sp,%curptr@(TS_ESP0)
+	movel	%sp,%curptr@(TASK_TSS+TSS_ESP0)
X 
X 	cmpl	#NR_syscalls,%d2
X 	jcc	badsys
-	btst	#LPF_TRACESYS_BIT,%curptr@(LTASK_FLAGS+LPF_TRACESYS_OFF)
+	btst	#PF_TRACESYS_BIT,%curptr@(TASK_FLAGS+PF_TRACESYS_OFF)
X 	jne	do_trace
X 	jbsr	@(SYMBOL_NAME(sys_call_table),%d2:l:4)@(0)
-	movel	%d0,%sp@(LPT_OFF_D0)	| save the return value
+	movel	%d0,%sp@(PT_D0)		| save the return value
X 
X SYMBOL_NAME_LABEL(ret_from_exception)
-	btst	#5,%sp@(LPT_OFF_SR)	| check if returning to kernel
+	btst	#5,%sp@(PT_SR)		| check if returning to kernel
X 	bnes	2f			| if so, skip resched, signals
X 	| only allow interrupts when we are really the last one on the
X 	| kernel stack, otherwise stack overflow can occur during
X 	| heavy interupt load
X 	andw	#ALLOWINT,%sr
-	tstl	%curptr@(LTASK_NEEDRESCHED)
+	tstl	%curptr@(TASK_NEEDRESCHED)
X 	jne	SYMBOL_NAME(reschedule)
X 	cmpl	#SYMBOL_NAME(task),%curptr	| task[0] cannot have signals
X 	jeq	2f
X 					| check for delayed trace
-	bclr	#LPF_DTRACE_BIT,%curptr@(LTASK_FLAGS+LPF_DTRACE_OFF)
+	bclr	#PF_DTRACE_BIT,%curptr@(TASK_FLAGS+PF_DTRACE_OFF)
X 	jne	do_delayed_trace
X 5:
-	tstl	%curptr@(LTASK_STATE)	| state
+	tstl	%curptr@(TASK_STATE)	| state
X 	jne	SYMBOL_NAME(reschedule)
X 
-	tstl	%curptr@(LTASK_SIGPENDING)
+	tstl	%curptr@(TASK_SIGPENDING)
X 	jne	Lsignal_return
X 2:	RESTORE_ALL
X 
@@ -141,7 +143,7 @@
X 	RESTORE_ALL
X 
X do_delayed_trace:
-	bclr	#7,%sp@(LPT_OFF_SR)	| clear trace bit in SR
+	bclr	#7,%sp@(PT_SR)		| clear trace bit in SR
X 	pea	1			| send SIGTRAP
X 	movel	%curptr,%sp@-
X 	pea	LSIGTRAP
@@ -158,7 +160,7 @@
X 	GET_CURRENT(%d0)
X 	addql	#1,SYMBOL_NAME(local_irq_count)
X 					|  put exception # in d0
-	bfextu %sp@(LPT_OFF_FORMATVEC){#4,#10},%d0
+	bfextu %sp@(PT_VECTOR){#4,#10},%d0
X 
X 	movel	%sp,%sp@-
X 	movel	%d0,%sp@- 		|  put vector # on stack
@@ -172,7 +174,7 @@
X 	RESTORE_ALL
X 1:
X #if 1
-	bfextu  %sp@(LPT_OFF_SR){#5,#3},%d0	| Check for nested interrupt.
+	bfextu  %sp@(PT_SR){#5,#3},%d0	| Check for nested interrupt.
X #if MAX_NOINT_IPL > 0
X 	cmpiw	#MAX_NOINT_IPL,%d0
X #endif
@@ -210,6 +212,14 @@
X 	RESTORE_SWITCH_STACK
X 	rts
X 
+ENTRY(sys_vfork)
+	SAVE_SWITCH_STACK	
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	SYMBOL_NAME(m68k_vfork)
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
X ENTRY(sys_sigsuspend)
X 	SAVE_SWITCH_STACK
X 	pea	%sp@(SWITCH_STACK_SIZE)
@@ -240,37 +250,31 @@
X 
X SYMBOL_NAME_LABEL(resume)
X 	/*
-	 * Beware - when entering resume, offset of tss is in d1,
-	 * prev (the current task) is in a0, next (the new task)
-	 * is in a1 and d2.b is non-zero if the mm structure is
-	 * shared between the tasks, so don't change these
+	 * Beware - when entering resume, prev (the current task) is
+	 * in a0, next (the new task) is in a1,so don't change these
X 	 * registers until their contents are no longer needed.
X 	 */
X 
-	/* offset of tss struct (processor state) from beginning
-	   of task struct */
-	addl	%d1,%a0
-
X 	/* save sr */
-	movew	%sr,%a0@(LTSS_SR)
+	movew	%sr,%a0@(TASK_TSS+TSS_SR)
X 
X 	/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
X 	movec	%sfc,%d0
-	movew	%d0,%a0@(LTSS_FS)
+	movew	%d0,%a0@(TASK_TSS+TSS_FS)
X 
X 	/* save usp */
X 	/* it is better to use a movel here instead of a movew 8*) */
X 	movec	%usp,%d0
-	movel	%d0,%a0@(LTSS_USP)
+	movel	%d0,%a0@(TASK_TSS+TSS_USP)
X 
X 	/* save non-scratch registers on stack */
X 	SAVE_SWITCH_STACK
X 
X 	/* save current kernel stack pointer */
-	movel	%sp,%a0@(LTSS_KSP)
+	movel	%sp,%a0@(TASK_TSS+TSS_KSP)
X 
X 	/* save floating point context */
-	fsave	%a0@(LTSS_FPCTXT+27*4)
+	fsave	%a0@(TASK_TSS+TSS_FPSTATE)
X 
X #if defined(CONFIG_M68060)
X #if !defined(CPU_M68060_ONLY)
@@ -278,27 +282,27 @@
X 	beqs	1f
X #endif
X 	/* The 060 FPU keeps status in bits 15-8 of the first longword */
-	tstb	%a0@(LTSS_FPCTXT+27*4+2)
+	tstb	%a0@(TASK_TSS+TSS_FPSTATE+2)
X 	jeq	3f
X #if !defined(CPU_M68060_ONLY)
X 	jra	2f
X #endif
X #endif /* CONFIG_M68060 */
X #if !defined(CPU_M68060_ONLY)
-1:	tstb	%a0@(LTSS_FPCTXT+27*4)
+1:	tstb	%a0@(TASK_TSS+TSS_FPSTATE)
X 	jeq	3f
X #endif
-2:	fmovemx	%fp0-%fp7,%a0@(LTSS_FPCTXT)
-	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(LTSS_FPCTXT+24*4)
+2:	fmovemx	%fp0-%fp7,%a0@(TASK_TSS+TSS_FPREG)
+	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(TASK_TSS+TSS_FPCNTL)
X 3:
X 
-	/* get pointer to tss struct (a1 contains new task) */
+	/* switch to new task (a1 contains new task) */
X 	movel	%a1,%curptr
-	addl	%d1,%a1
X 
X 	/* Skip address space switching if they are the same. */
-	tstb	%d2
-	jne	4f
+	movel	%a0@(TASK_MM),%d0
+	cmpl	%a1@(TASK_MM),%d0
+	jeq	4f
X 
X #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
X 	/* 68040 or 68060 ? */
@@ -316,7 +320,7 @@
X 	movec	%d0,%cacr
X 
X 	/* switch the root pointer */
-	pmove	%a1@(LTSS_CRP),%crp
+	pmove	%a1@(TASK_TSS+TSS_CRP),%crp
X #endif
X 
X #if defined(CPU_M68020_OR_M68030) && defined(CPU_M68040_OR_M68060)
@@ -333,7 +337,7 @@
X 	pflushan
X 
X 	/* switch the root pointer */
-	movel	%a1@(LTSS_CRP+4),%d0
+	movel	%a1@(TASK_TSS+TSS_CRP+4),%d0
X 	movec	%d0,%urp
X 
X #if defined (CONFIG_M68060)
@@ -359,37 +363,37 @@
X 	beqs	1f
X #endif
X 	/* The 060 FPU keeps status in bits 15-8 of the first longword */
-	tstb	%a1@(LTSS_FPCTXT+27*4+2)
+	tstb	%a1@(TASK_TSS+TSS_FPSTATE+2)
X 	jeq	3f
X #if !defined(CPU_M68060_ONLY)
X 	jra	2f
X #endif
X #endif /* CONFIG_M68060 */
X #if !defined(CPU_M68060_ONLY)
-1:	tstb	%a1@(LTSS_FPCTXT+27*4)
+1:	tstb	%a1@(TASK_TSS+TSS_FPSTATE)
X 	jeq	3f
X #endif	
-2:	fmovemx	%a1@(LTSS_FPCTXT),%fp0-%fp7
-	fmoveml	%a1@(LTSS_FPCTXT+24*4),%fpcr/%fpsr/%fpiar
-3:	frestore %a1@(LTSS_FPCTXT+27*4)
+2:	fmovemx	%a1@(TASK_TSS+TSS_FPREG),%fp0-%fp7
+	fmoveml	%a1@(TASK_TSS+TSS_FPCNTL),%fpcr/%fpsr/%fpiar
+3:	frestore %a1@(TASK_TSS+TSS_FPSTATE)
X 
X 	/* restore the kernel stack pointer */
-	movel	%a1@(LTSS_KSP),%sp
+	movel	%a1@(TASK_TSS+TSS_KSP),%sp
X 
X 	/* restore non-scratch registers */
X 	RESTORE_SWITCH_STACK
X 
X 	/* restore user stack pointer */
-	movel	%a1@(LTSS_USP),%a0
+	movel	%a1@(TASK_TSS+TSS_USP),%a0
X 	movel	%a0,%usp
X 
X 	/* restore fs (sfc,%dfc) */
-	movew	%a1@(LTSS_FS),%a0
+	movew	%a1@(TASK_TSS+TSS_FS),%a0
X 	movec	%a0,%sfc
X 	movec	%a0,%dfc
X 
X 	/* restore status register */
-	movew	%a1@(LTSS_SR),%sr
+	movew	%a1@(TASK_TSS+TSS_SR),%sr
X 
X 	rts
X 
@@ -586,6 +590,7 @@
X 	.long SYMBOL_NAME(sys_sendfile)
X 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams1 */
X 	.long SYMBOL_NAME(sys_ni_syscall)		/* streams2 */
+	.long SYMBOL_NAME(sys_vfork)            /* 190 */
X 
X 	.rept NR_syscalls-(.-SYMBOL_NAME(sys_call_table))/4
X 		.long SYMBOL_NAME(sys_ni_syscall)
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/head.S linux/arch/m68k/kernel/head.S
--- v2.2.0-pre8/linux/arch/m68k/kernel/head.S	Tue Jun 23 10:01:21 1998
+++ linux/arch/m68k/kernel/head.S	Tue Jan 19 10:58:26 1999
@@ -7,9 +7,12 @@
X **
X ** 68040 fixes by Michael Rausch
X ** 68060 fixes by Roman Hodek
+** MMU cleanup by Randy Thelen
+** Final MMU cleanup by Roman Zippel
X **
X ** Atari support by Andreas Schwab, using ideas of Robert de Vries
X ** and Bjoern Brauel
+** VME Support by Richard Hirst
X **
X ** 94/11/14 Andreas Schwab: put kernel at PAGESIZE
X ** 94/11/18 Andreas Schwab: remove identity mapping of STRAM for Atari
@@ -18,6 +21,8 @@
X ** 96/04/26 Guenther Kelleter: fixed identity mapping for Falcon with
X ** 			      Magnum- and FX-alternate ram
X ** 98/04/25 Phil Blundell: added HP300 support
+** 1998/08/30 David Kilzer: Added support for fbcon_font_desc structures
+**            for linux-2.1.115
X **
X ** This file is subject to the terms and conditions of the GNU General Public
X ** License. See the file README.legal in the main directory of this archive
@@ -34,69 +39,275 @@
X  * Put us in supervisor state.
X  *
X  * The kernel setup code takes the following steps:
- *   Raise interrupt level
- *   Set up initial kernel memory mapping.
- *	This sets up a mapping of the 4M of memory the kernel
- *	is located in.	It also does a mapping of any initial
- *	machine specific areas.
- * Note that the kernel is located at virtual address 0x1000 == _start
- *   Enable cache memories
- *   Jump to kernel startup
- *
- * Register d6 contains the CPU flags and d4 the machine type
- * from the boot_info information for most of this file.
- * The upper word of d6 contains a bit for '040 or '060, since these two
- * are quite similar for initial mm setup. Another bit in d6 allows
- * distinction of the '060. The lower word of d6 contains the cache mode
- * that should be applied to pages containing descriptors. This mode is
- * non-cached/non-serialized for the '040 and cacheable/write-through for
- * the '060.
- *
- * General register usage:
- *   a6 - start of unused memory
- *	  new pages can be allocated from here
- *   a5 - mmu root table
- *   a4 - mmu pointer table
- *   a3 - mmu page tables
- *   a2 - points to the page table entry for a6
- *	  cache status can be changed (used for '0[46]0)
- *	  you must increase a2 if alloc a new page
- *   d7 - used for debug output and some macros
- *   d6 - cpu type and cache mode
- *   d5 - physical start address of kernel
- *   d4 - machine type
+ * .  Raise interrupt level
+ * .  Set up initial kernel memory mapping.
+ *    .  This sets up a mapping of the 4M of memory the kernel is located in.
+ *    .  It also does a mapping of any initial machine specific areas.
+ * .  Enable the MMU
+ * .  Enable cache memories
+ * .  Jump to kernel startup
+ *
+ * Much of the file restructuring was to accomplish:
+ * 1) Remove register dependency through-out the file.
+ * 2) Increase use of subroutines to perform functions
+ * 3) Increase readability of the code
+ *
+ * Of course, readability is a subjective issue, so it will never be
+ * argued that that goal was accomplished.  It was merely a goal.
+ * A key way to help make code more readable is to give good
+ * documentation.  So, the first thing you will find is exaustive
+ * write-ups on the structure of the file, and the features of the
+ * functional subroutines.
+ *
+ * General Structure:
+ * ------------------
+ *	Without a doubt the single largest chunk of head.S is spent
+ * mapping the kernel and I/O physical space into the logical range
+ * for the kernel.
+ *	There are new subroutines and data structures to make MMU
+ * support cleaner and easier to understand.
+ * 	First, you will find a routine call "mmu_map" which maps
+ * a logical to a physical region for some length given a cache
+ * type on behalf of the caller.  This routine makes writing the
+ * actual per-machine specific code very simple.
+ *	A central part of the code, but not a subroutine in itself,
+ * is the mmu_init code which is broken down into mapping the kernel
+ * (the same for all machines) and mapping machine-specific I/O
+ * regions.
+ *	Also, there will be a description of engaging the MMU and
+ * caches.
+ *	You will notice that there is a chunk of code which
+ * can emit the entire MMU mapping of the machine.  This is present
+ * only in debug modes and can be very helpful.
+ *	Further, there is a new console driver in head.S that is
+ * also only engaged in debug mode.  Currently, it's only supported
+ * on the Macintosh class of machines.  However, it is hoped that
+ * others will plug-in support for specific machines.
+ *
+ * ######################################################################
+ *
+ * mmu_map
+ * -------
+ *	mmu_map was written for two key reasons.  First, it was clear
+ * that it was very difficult to read the previous code for mapping
+ * regions of memory.  Second, the Macintosh required such extensive
+ * memory allocations that it didn't make sense to propogate the
+ * existing code any further.
+ *	mmu_map requires some parameters:
+ *
+ *	mmu_map (logical, physical, length, cache_type)
+ *
+ *	While this essentially describes the function in the abstract, you'll
+ * find more indepth description of other parameters at the implementation site.
+ * 
+ * mmu_get_root_table_entry
+ * ------------------------
+ * mmu_get_ptr_table_entry
+ * -----------------------
+ * mmu_get_page_table_entry
+ * ------------------------
+ * 
+ *	These routines are used by other mmu routines to get a pointer into
+ * a table, if necessary a new table is allocated. These routines are working
+ * basically like pmd_alloc() and pte_alloc() in <asm/pgtable.h>. The root
+ * table needs of course only to be allocated once in mmu_get_root_table_entry,
+ * so that here also some mmu specific initialization is done. The second page
+ * at the start of the kernel (the first page is unmapped later) is used for
+ * the kernel_pg_dir. It must be at a position known at link time (as it's used
+ * to initialize the init task struct) and since it needs special cache
+ * settings, it's the easiest to use this page, the rest of the page is used
+ * for further pointer tables.
+ * mmu_get_page_table_entry allocates always a whole page for page tables, this
+ * means 1024 pages and so 4MB of memory can be mapped. It doesn't make sense
+ * to manage page tables in smaller pieces as nearly all mappings have that
+ * size.
+ *
+ * ######################################################################
+ *
+ *
+ * ######################################################################
+ *
+ * mmu_engage
+ * ----------
+ *	Thanks to a small helping routine enabling the mmu got quiet simple
+ * and there is only one way left. mmu_engage makes a complete a new mapping
+ * that only includes the absolute necessary to be able to jump to the final
+ * postion and to restore the original mapping.
+ * As this code doesn't need a transparent translation register anymore this
+ * means all registers are free to be used by machines that needs them for
+ * other purposes.
+ *
+ * ######################################################################
+ *
+ * mmu_print
+ * ---------
+ *	This algorithm will print out the page tables of the system as
+ * appropriate for an 030 or an 040.  This is useful for debugging purposes
+ * and as such is enclosed in #ifdef MMU_PRINT/#endif clauses.
+ *
+ * ######################################################################
+ *
+ * console_init
+ * ------------
+ *	The console is also able to be turned off.  The console in head.S
+ * is specifically for debugging and can be very useful.  It is surrounded by
+ * #ifdef CONSOLE/#endif clauses so it doesn't have to ship in known-good
+ * kernels.  It's basic algorithm is to determine the size of the screen
+ * (in height/width and bit depth) and then use that information for
+ * displaying an 8x8 font or an 8x16 (widthxheight).  I prefer the 8x8 for
+ * debugging so I can see more good data.  But it was trivial to add support
+ * for both fonts, so I included it.
+ *	Also, the algorithm for plotting pixels is abstracted so that in
+ * theory other platforms could add support for different kinds of frame
+ * buffers.  This could be very useful.
+ *
+ * console_put_penguin
+ * -------------------
+ *	An important part of any Linux bring up is the penguin and there's
+ * nothing like getting the Penguin on the screen!  This algorithm will work
+ * on any machine for which there is a console_plot_pixel.
+ *
+ * console_scroll
+ * --------------
+ *	My hope is that the scroll algorithm does the right thing on the
+ * various platforms, but it wouldn't be hard to add the test conditions
+ * and new code if it doesn't.
+ *
+ * console_putc
+ * -------------
+ *
+ * ######################################################################
+ *
+ *	Register usage has greatly simplified within head.S. Every subroutine
+ * saves and restores all registers that it modifies (except it returns a
+ * value in there of course). So the only register that needs to be initialized
+ * is the stack pointer.
+ * All other init code and data is now placed in the init section, so it will
+ * be automatically freed at the end of the kernel initialization.
+ *
+ * ######################################################################
+ *
+ * options
+ * -------
+ *	There are many options availble in a build of this file.  I've
+ * taken the time to describe them here to save you the time of searching
+ * for them and trying to understand what they mean.
+ *
+ * CONFIG_xxx:	These are the obvious machine configuration defines created
+ * during configuration.  These are defined in include/linux/autoconf.h.
+ *
+ * CONSOLE:	There is support for head.S console in this file.  This
+ * console can talk to a Mac frame buffer, but could easily be extrapolated
+ * to extend it to support other platforms.
+ *
+ * TEST_MMU:	This is a test harness for running on any given machine but
+ * getting an MMU dump for another class of machine.  The classes of machines
+ * that can be tested are any of the makes (Atari, Amiga, Mac, VME, etc.)
+ * and any of the models (030, 040, 060, etc.).
+ *
+ *	NOTE:	TEST_MMU is NOT permanent!  It is scheduled to be removed
+ *		When head.S boots on Atari, Amiga, Macintosh, and VME
+ *		machines.  At that point the underlying logic will be
+ *		believed to be solid enough to be trusted, and TEST_MMU
+ *		can be dropped.  Do note that that will clean up the
+ *		head.S code significantly as large blocks of #if/#else
+ *		clauses can be removed.
+ *
+ * MMU_NOCACHE_KERNEL:	On the Macintosh platform there was an inquiry into
+ * determing why devices don't appear to work.  A test case was to remove
+ * the cacheability of the kernel bits.
+ *
+ * MMU_PRINT:	There is a routine built into head.S that can display the
+ * MMU data structures.  It outputs its result through the serial_putc
+ * interface.  So where ever that winds up driving data, that's where the
+ * mmu struct will appear.  On the Macintosh that's typically the console.
+ *
+ * SERIAL_DEBUG:	There are a series of putc() macro statements
+ * scattered through out the code to give progress of status to the
+ * person sitting at the console.  This constant determines whether those
+ * are used.
+ *
+ * DEBUG:	This is the standard DEBUG flag that can be set for building
+ *		the kernel.  It has the effect adding additional tests into
+ *		the code.
+ *
+ * FONT_6x11:
+ * FONT_8x8:
+ * FONT_8x16:
+ *		In theory these could be determined at run time or handed
+ *		over by the booter.  But, let's be real, it's a fine hard
+ *		coded value.  (But, you will notice the code is run-time
+ *		flexible!)  A pointer to the font's struct fbcon_font_desc
+ *		is kept locally in Lconsole_font.  It is used to determine
+ *		font size information dynamically.
+ *
+ * Atari constants:
+ * USE_PRINTER:	Use the printer port for serial debug.
+ * USE_SCC_B:	Use the SCC port A (Serial2) for serial debug.
+ * USE_SCC_A:	Use the SCC port B (Modem2) for serial debug.
+ * USE_MFP:	Use the ST-MFP port (Modem1) for serial debug.
+ *
+ * Macintosh constants:
+ * MAC_SERIAL_DEBUG:	Turns on serial debug output for the Macintosh.
+ * MAC_USE_SCC_A:	Use the SCC port A (modem) for serial debug.
+ * MAC_USE_SCC_B:	Use the SCC port B (printer) for serial debug (default).
X  */
X 
X #include <linux/config.h>
X #include <linux/linkage.h>
+#include <linux/init.h>
X #include <asm/bootinfo.h>
X #include <asm/setup.h>
X #include <asm/pgtable.h>
+#include "m68k_defs.h"
X 
-.globl SYMBOL_NAME(kernel_pg_dir), SYMBOL_NAME(kpt)
-.globl SYMBOL_NAME(availmem)
-.globl SYMBOL_NAME(m68k_pgtable_cachemode)
-.globl SYMBOL_NAME(kernel_pmd_table), SYMBOL_NAME(swapper_pg_dir)
+#ifdef CONFIG_MAC
X 
-#if defined(CONFIG_MVME16x)
-.globl SYMBOL_NAME(mvme_bdid_ptr)
-#endif
+#include <asm/machw.h>
X 
X /*
- * Added m68k_supervisor_cachemode for 68060 boards where some drivers
- * need writethrough caching for supervisor accesses.  Drivers known to
- * be effected are 53c7xx.c and apricot.c (when used on VME boards).
- * Richard Hirst.
+ * Macintosh console support
X  */
X 
-#ifdef CONFIG_060_WRITETHROUGH
+#define CONSOLE
+
+/*
+ * Macintosh serial debug support; outputs boot info to the printer
+ *   and/or modem serial ports
+ */
+#undef MAC_SERIAL_DEBUG
+
+/*
+ * Macintosh serial debug port selection; define one or both;
+ *   requires MAC_SERIAL_DEBUG to be defined
+ */
+#define MAC_USE_SCC_A		/* Macintosh modem serial port */
+#define MAC_USE_SCC_B		/* Macintosh printer serial port */
+
+#endif	/* CONFIG_MAC */
+
+#undef MMU_PRINT
+#undef MMU_NOCACHE_KERNEL
+#define SERIAL_DEBUG
+#undef DEBUG
+
+/*
+ * For the head.S console, there are three supported fonts, 6x11, 8x16 and 8x8.
+ * The 8x8 font is harder to read but fits more on the screen.
+ */
+#define FONT_8x8 	/* default */
+/* #define FONT_8x16 */	/* 2nd choice */
+/* #define FONT_6x11 */	/* 3rd choice */
+
+.globl SYMBOL_NAME(kernel_pg_dir)
+.globl SYMBOL_NAME(availmem)
+.globl SYMBOL_NAME(m68k_pgtable_cachemode)
X .globl SYMBOL_NAME(m68k_supervisor_cachemode)
-#endif
X 
-D6B_0460 = 16		/* indicates 680[46]0 in d6 */
-D6B_060  = 17		/* indicates 68060 in d6 */
-D6F_040  = 1<<D6B_0460
-D6F_060  = (1<<D6B_0460)+(1<<D6B_060)
+CPUTYPE_040	= 1	/* indicates an 040 */
+CPUTYPE_060	= 2	/* indicates an 060 */
+CPUTYPE_0460	= 3	/* if either above are set, this is set */
+CPUTYPE_020	= 4	/* indicates an 020 */
X 
X /* Translation control register */
X TC_ENABLE = 0x8000
@@ -144,6 +355,7 @@
X 
X /* Miscellaneous definitions */
X PAGESIZE	= 4096
+PAGESHIFT	= 12
X 
X ROOT_TABLE_SIZE	= 128
X PTR_TABLE_SIZE	= 128
@@ -152,32 +364,182 @@
X PTR_INDEX_SHIFT  = 18
X PAGE_INDEX_SHIFT = 12
X 
-TABLENR_4MB	= 16	/* # of page tables needed to page 4 MB */
-TABLENR_16MB	= 64	/* same for 16 MB */
+#ifdef DEBUG
+/* When debugging use readable names for labels */
+#ifdef __STDC__
+#define L(name) .head.S.##name
+#else
+#define L(name) .head.S./**/name
+#endif
+#else
+#ifdef __STDC__
+#define L(name) .L##name
+#else
+#define L(name) .L/**/name
+#endif
+#endif
+
+/* Several macros to make the writing of subroutines easier:
+ * - func_start marks the beginning of the routine which setups the frame
+ *   register and saves the registers, it also defines another macro
+ *   to automatically restore the registers again.
+ * - func_return marks the end of the routine and simply calls the prepared
+ *   macro to restore registers and jump back to the caller.
+ * - func_define generates another macro to automatically put arguments
+ *   onto the stack call the subroutine and cleanup the stack again.
+ */
+
+/* Within subroutines these macros can be used to access the arguments
+ * on the stack. With STACK some allocated memory on the stack can be
+ * accessed and ARG0 points to the return address (used by mmu_engage).
+ */
+#define	STACK	%a6@(stackstart)
+#define ARG0	%a6@(4)
+#define ARG1	%a6@(8)
+#define ARG2	%a6@(12)
+#define ARG3	%a6@(16)
+#define ARG4	%a6@(20)
+
+.macro	func_start	name,saveregs,stack=0
+L(\name):
+	linkw	%a6,#-\stack
+	moveml	\saveregs,%sp@-
+.set	stackstart,-\stack	
+
+.macro	func_return_\name
+	moveml	%sp@+,\saveregs
+	unlk	%a6
+	rts
+.endm
+.endm
+
+.macro	func_return	name
+	func_return_\name
+.endm
+
+.macro	func_call	name
+	jbsr	L(\name)
+.endm
+
+.macro	move_stack	nr,arg1,arg2,arg3,arg4
+.if	\nr
+	move_stack	"(\nr-1)",\arg2,\arg3,\arg4
+	movel	\arg1,%sp@-
+.endif
+.endm
+
+.macro	func_define	name,nr=0
+.macro	\name	arg1,arg2,arg3,arg4
+	move_stack	\nr,\arg1,\arg2,\arg3,\arg4
+	func_call	\name
+.if	\nr
+	lea	%sp@(\nr*4),%sp
+.endif
+.endm
+.endm
+
+func_define	mmu_map,4
+func_define	mmu_map_tt,4
+func_define	mmu_fixup_page_mmu_cache,1
+func_define	mmu_temp_map,2
+func_define	mmu_engage
+func_define	mmu_get_root_table_entry,1
+func_define	mmu_get_ptr_table_entry,2
+func_define	mmu_get_page_table_entry,2
+func_define	mmu_print
+func_define	get_new_page
+#ifdef CONFIG_HP300
+func_define	set_leds
+#endif
+
+.macro	mmu_map_eq	arg1,arg2,arg3
+	mmu_map	\arg1,\arg1,\arg2,\arg3
+.endm
+
+.macro	get_bi_record	record
+	pea	\record
+	func_call	get_bi_record
+	addql	#4,%sp
+.endm
+
+func_define	serial_putc,1
+func_define	console_putc,1
+
+.macro	putc	ch
+#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+	pea	\ch
+#endif
+#ifdef CONSOLE
+	func_call	console_putc
+#endif
+#ifdef SERIAL_DEBUG
+	func_call	serial_putc
+#endif
+#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+	addql	#4,%sp
+#endif
+.endm
+
+.macro	dputc	ch
+#ifdef DEBUG
+	putc	\ch
+#endif
+.endm
+
+func_define	putn,1
+
+.macro	dputn	nr
+#ifdef DEBUG
+	putn	\nr
+#endif
+.endm
+
+.macro	puts		string
+#if defined(CONSOLE) || defined(SERIAL_DEBUG)
+	__INITDATA
+.Lstr\@:
+	.string	"\string"
+	__FINIT
+	pea	%pc@(.Lstr\@)
+	func_call	puts
+	addql	#4,%sp
+#endif
+.endm
+
+.macro	dputs	string
+#ifdef DEBUG
+	puts	"\string"
+#endif
+.endm
+
X 
-#define putc(ch) moveq &ch,%d7; jbsr Lserial_putc
-#define putr() putc(13); putc(10)
-#define putn(nr) movel nr,%d7; jbsr Lserial_putnum
-
-#define is_not_amiga(lab) moveq &MACH_AMIGA,%d7; cmpl %d4,%d7; jne lab
-#define is_not_atari(lab) moveq &MACH_ATARI,%d7; cmpl %d4,%d7; jne lab
-#define is_not_mvme16x(lab) moveq &MACH_MVME16x,%d7; cmpl %d4,%d7; jne lab
-#define is_not_bvme6000(lab) moveq &MACH_BVME6000,%d7; cmpl %d4,%d7; jne lab
-#define is_not_hp300(lab) moveq &MACH_HP300,%d7	;  cmpl %d4,%d7; jne lab
-
-#define is_040_or_060(lab) btst &D6B_0460,%d6; jne lab
-#define is_not_040_or_060(lab) btst &D6B_0460,%d6; jeq lab
-#define is_060(lab) btst &D6B_060,%d6; jne lab
-#define is_not_060(lab) btst &D6B_060,%d6; jeq lab
+#define is_not_amiga(lab) cmpl &MACH_AMIGA,%pc@(m68k_machtype); jne lab
+#define is_not_atari(lab) cmpl &MACH_ATARI,%pc@(m68k_machtype); jne lab
+#define is_not_mac(lab) cmpl &MACH_MAC,%pc@(m68k_machtype); jne lab
+#define is_not_mvme16x(lab) cmpl &MACH_MVME16x,%pc@(m68k_machtype); jne lab
+#define is_not_bvme6000(lab) cmpl &MACH_BVME6000,%pc@(m68k_machtype); jne lab
+#define is_not_hp300(lab) cmpl &MACH_HP300,%pc@(m68k_machtype); jne lab
+
+#define is_040_or_060(lab)	btst &CPUTYPE_0460,%pc@(L(cputype)+3); jne lab
+#define is_not_040_or_060(lab)	btst &CPUTYPE_0460,%pc@(L(cputype)+3); jeq lab
+#define is_040(lab)		btst &CPUTYPE_040,%pc@(L(cputype)+3); jne lab
+#define is_060(lab)		btst &CPUTYPE_060,%pc@(L(cputype)+3); jne lab
+#define is_not_060(lab)		btst &CPUTYPE_060,%pc@(L(cputype)+3); jeq lab
+#define is_020(lab)		btst &CPUTYPE_020,%pc@(L(cputype)+3); jne lab
+#define is_not_020(lab)		btst &CPUTYPE_020,%pc@(L(cputype)+3); jeq lab
X 
X /* On the HP300 we use the on-board LEDs for debug output before
X    the console is running.  Writing a 1 bit turns the corresponding LED
X    _off_ - on the 340 bit 7 is towards the back panel of the machine.  */
+.macro	leds	mask
X #ifdef CONFIG_HP300
-#define leds(x) is_not_hp300(42f) ; moveb #(x),%d7 ; jbsr Lset_leds; 42:
-#else
-#define leds(x)
+	is_not_hp300(.Lled\@)
+	pea	\mask
+	func_call	set_leds
+	addql	#4,%sp
+.Lled\@:
X #endif
+.endm
X 
X .text
X ENTRY(_stext)
@@ -192,81 +554,193 @@
X 	.long	MACH_ATARI, ATARI_BOOTI_VERSION
X 	.long	MACH_MVME16x, MVME16x_BOOTI_VERSION
X 	.long	MACH_BVME6000, BVME6000_BOOTI_VERSION
+	.long	MACH_MAC, MAC_BOOTI_VERSION
X 	.long	0
-1:	jra	SYMBOL_NAME(_start)
+1:	jra	SYMBOL_NAME(__start)
X 
-.equ	SYMBOL_NAME(kernel_pmd_table),SYMBOL_NAME(_stext)
-.equ	SYMBOL_NAME(kernel_pg_dir),SYMBOL_NAME(kernel_pmd_table)
-.equ	SYMBOL_NAME(swapper_pg_dir),SYMBOL_NAME(kernel_pg_dir)+(ROOT_TABLE_SIZE<<2)
-.equ	Lavail_pmd_table,SYMBOL_NAME(swapper_pg_dir)+(ROOT_TABLE_SIZE<<2)
+.equ	SYMBOL_NAME(kernel_pg_dir),SYMBOL_NAME(_stext)
X 
X .equ	.,SYMBOL_NAME(_stext)+PAGESIZE
X 
X ENTRY(_start)
+	jra	SYMBOL_NAME(__start)
+__INIT
+ENTRY(__start)
X 
X /*
X  * Setup initial stack pointer
X  */
-	lea	%pc@(SYMBOL_NAME(_stext):w),%sp
+	lea	%pc@(SYMBOL_NAME(_stext)),%sp
X 
X /*
X  * Record the CPU and machine type.
X  */
X 
-	movew	#BI_MACHTYPE,%d0
-	jbsr	Lget_bi_record
-	movel	%a0@,%d4
-	lea	%pc@(SYMBOL_NAME(m68k_machtype)),%a0
-	movel	%d4,%a0@
-	movew	#BI_FPUTYPE,%d0
-	jbsr	Lget_bi_record
-	movel	%a0@,%d0
-	lea	%pc@(SYMBOL_NAME(m68k_fputype)),%a0
-	movel	%d0,%a0@
-	movew	#BI_MMUTYPE,%d0
-	jbsr	Lget_bi_record
-	movel	%a0@,%d0
-	lea	%pc@(SYMBOL_NAME(m68k_mmutype)),%a0
-	movel	%d0,%a0@
-	movew	#BI_CPUTYPE,%d0
-	jbsr	Lget_bi_record
+	get_bi_record	BI_MACHTYPE
+	lea	%pc@(SYMBOL_NAME(m68k_machtype)),%a1
+	movel	%a0@,%a1@
+
+	get_bi_record	BI_FPUTYPE
+	lea	%pc@(SYMBOL_NAME(m68k_fputype)),%a1
+	movel	%a0@,%a1@
+
+	get_bi_record	BI_MMUTYPE
+	lea	%pc@(SYMBOL_NAME(m68k_mmutype)),%a1
+	movel	%a0@,%a1@
+
+	get_bi_record	BI_CPUTYPE
+	lea	%pc@(SYMBOL_NAME(m68k_cputype)),%a1
+	movel	%a0@,%a1@
+
+#ifdef CONFIG_MAC
+/*
+ * For Macintosh, we need to determine the display parameters early (at least
+ * while debugging it).
+ */
+
+	is_not_mac(L(test_notmac))
+
+	get_bi_record	BI_MAC_VADDR
+	lea	%pc@(L(mac_videobase)),%a1
+	movel	%a0@,%a1@
+
+	get_bi_record	BI_MAC_VDEPTH
+	lea	%pc@(L(mac_videodepth)),%a1
+	movel	%a0@,%a1@
+
+	get_bi_record	BI_MAC_VDIM
+	lea	%pc@(L(mac_dimensions)),%a1
+	movel	%a0@,%a1@
+
+	get_bi_record	BI_MAC_VROW
+	lea	%pc@(L(mac_rowbytes)),%a1
+	movel	%a0@,%a1@
+
+#ifdef MAC_SERIAL_DEBUG
+	get_bi_record	BI_MAC_SCCBASE
+	lea	%pc@(L(mac_sccbase)),%a1
+	movel	%a0@,%a1@
+#endif /* MAC_SERIAL_DEBUG */
+
+#if 0
+	/*
+	 * Clear the screen
+	 */
+	lea	%pc@(L(mac_videobase)),%a0
+	movel	%a0@,%a1
+	lea	%pc@(L(mac_dimensions)),%a0
+	movel	%a0@,%d1
+	swap	%d1		/* #rows is high bytes */
+	andl	#0xFFFF,%d1	/* rows */
+	subl	#10,%d1
+	lea	%pc@(L(mac_rowbytes)),%a0
+loopy2:
X 	movel	%a0@,%d0
-	lea	%pc@(SYMBOL_NAME(m68k_cputype)),%a0
-	movel	%d0,%a0@
+	subql	#1,%d0
+loopx2:
+	moveb	#0x55, %a1@+
+	dbra	%d0,loopx2
+	dbra	%d1,loopy2
+#endif
+
+L(test_notmac):
+#endif /* CONFIG_MAC */
+
+
+/*
+ * There are ultimately two pieces of information we want for all kinds of
+ * processors CpuType and CacheBits.  The CPUTYPE was passed in from booter
+ * and is converted here from a booter type definition to a separate bit
+ * number which allows for the standard is_0x0 macro tests.
+ */
+	movel	%pc@(SYMBOL_NAME(m68k_cputype)),%d0
+	/*
+	 * Assume it's an 030
+	 */
+	clrl	%d1
X 
+	/*
+	 * Test the BootInfo cputype for 060
+	 */
X 	btst	#CPUB_68060,%d0
X 	jeq	1f
-	/* '060: d6 := BIT0460|BIT060, cache mode 0x60 (no-cache/non-ser) */
-	movel	#D6F_060+_PAGE_CACHE040W,%d6
-	jra	2f
-1:	btst	#CPUB_68040,%d0
-	jeq	1f
-	/* '040: d6 := BIT0460, cache mode 0x00 (write-through) */
-	movel	#D6F_040+_PAGE_CACHE040W,%d6
-	jra	2f
-1:	/* '020 or '030: d6 := no CPU bit, cache mode unused */
-	moveq	#0,%d6
+	bset	#CPUTYPE_060,%d1
+	bset	#CPUTYPE_0460,%d1
+	jra	3f
+1:
+	/*
+	 * Test the BootInfo cputype for 040
+	 */
+	btst	#CPUB_68040,%d0
+	jeq	2f
+	bset	#CPUTYPE_040,%d1
+	bset	#CPUTYPE_0460,%d1
+	jra	3f
+2:
+	/*
+	 * Test the BootInfo cputype for 020
+	 */
+	btst	#CPUB_68020,%d0
+	jeq	3f
+	bset	#CPUTYPE_020,%d1
+	jra	3f
+3:
+	/*
+	 * Record the cpu type
+	 */
+	lea	%pc@(L(cputype)),%a0
+	movel	%d1,%a0@
X 
-2:	lea	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
-	moveq	#0,%d0
-	movew	%d6,%d0
-	movel	%d0,%a0@		/* save cache mode for page tables */
+	/*
+	 * NOTE:
+	 *
+	 * Now the macros are valid:
+	 *	is_040_or_060
+	 *	is_not_040_or_060
+	 *	is_040
+	 *	is_060
+	 *	is_not_060
+	 */
+
+	/*
+	 * Determine the cache mode for pages holding MMU tables
+	 * and for supervisor mode, unused for '020 and '030
+	 */
+	clrl	%d0
+	clrl	%d1
+
+	is_not_040_or_060(L(save_cachetype))
X 
X 	/*
+	 * '040 or '060
+	 * d1 := cacheable write-through
+	 * NOTE: The 68040 manual strongly recommends non-cached for MMU tables,
+	 * but we have been using write-through since at least 2.0.29 so I
+	 * guess it is OK.
+	 */
+#ifdef CONFIG_060_WRITETHROUGH
+	/*
X 	 * If this is a 68060 board using drivers with cache coherency
X 	 * problems, then supervisor memory accesses need to be write-through
-         * also; otherwise, we want copyback.
+	 * also; otherwise, we want copyback.
X 	 */
X 
-#if defined(CONFIG_060_WRITETHROUGH)
-	is_not_060(Lset_norm)
-	jra	1f
-Lset_norm:
-	move.w	#_PAGE_CACHE040,%d0
+	is_not_060(1f)
+	movel	#_PAGE_CACHE040W,%d0
+	jra	L(save_cachetype)
+#endif /* CONFIG_060_WRITETHROUGH */
X 1:
-  	lea	%pc@(SYMBOL_NAME(m68k_supervisor_cachemode)),%a0
+	movew	#_PAGE_CACHE040,%d0
+
+	movel	#_PAGE_CACHE040W,%d1
+
+L(save_cachetype):
+	/* Save cache mode for supervisor mode and page tables
+	 */
+	lea	%pc@(SYMBOL_NAME(m68k_supervisor_cachemode)),%a0
X 	movel	%d0,%a0@
-#endif
+	lea	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%a0
+	movel	%d1,%a0@
X 
X /*
X  * raise interrupt level
@@ -293,288 +767,120 @@
X  */
X 
X #ifdef CONFIG_ATARI
-	is_not_atari(Lnotypetest)
+	is_not_atari(L(notypetest))
X 
X 	/* get special machine type (Medusa/Hades/AB40) */
X 	moveq	#0,%d3 /* default if tag doesn't exist */
-	movew	#BI_ATARI_MCH_TYPE,%d0
-	jbsr	Lget_bi_record
+	get_bi_record	BI_ATARI_MCH_TYPE
X 	tstl	%d0
X 	jbmi	1f
X 	movel	%a0@,%d3
-1:	
-	/* %d3 is not clobbered until Atari page tables are set up,
-	 * where it is used again. */
-
+	lea	%pc@(SYMBOL_NAME(atari_mch_type)),%a0
+	movel	%d3,%a0@
+1:
X 	/* On the Hades, the iobase must be set up before opening the
X 	 * serial port. There are no I/O regs at 0x00ffxxxx at all. */
X 	moveq	#0,%d0
X 	cmpl	#ATARI_MACH_HADES,%d3
X 	jbne	1f
X 	movel	#0xff000000,%d0		/* Hades I/O base addr: 0xff000000 */
-1:	lea     %pc@(Liobase),%a0
+1:	lea     %pc@(L(iobase)),%a0
X 	movel   %d0,%a0@
-Lnotypetest:
+
+L(notypetest):
X #endif
X 
X /*
X  * Initialize serial port
X  */
-
-	jbsr Lserial_init
-
-	putr()
-	putc('A')
+	jbsr	L(serial_init)
X 
X /*
- * Get address at end of bootinfo and mask off at a page boundary.
+ * Initialize console
X  */
-	moveq	#0,%d0
-	jbsr	Lget_bi_record
-	addw	#PAGESIZE-1,%a0
-	movel	%a0,%d0
-	andl	#-PAGESIZE,%d0
-	movel	%d0,%a6
-
-	putc('B')
+#ifdef CONFIG_MAC
+	is_not_mac(L(nocon))
+#ifdef CONSOLE
+	jbsr	L(console_init)
+#ifdef CONSOLE_PENGUIN
+	jbsr	L(console_put_penguin)
+#endif	/* CONSOLE_PENGUIN */
+	jbsr	L(console_put_stats)
+#endif	/* CONSOLE */
+L(nocon):
+#endif	/* CONFIG_MAC */
+
+
+	putc	'\n'
+	putc	'A'
+	dputn	%pc@(L(cputype))
+	dputn	%pc@(SYMBOL_NAME(m68k_supervisor_cachemode))
+	dputn	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode))
+	dputc	'\n'
X 
X /*
X  * Save physical start address of kernel
X  */
-	lea	%pc@(SYMBOL_NAME(_stext)-PAGESIZE:w),%a0
-	movel	%a0,%d5
-
-/*
- * initialize the kernel root table.
- */
-	lea	%pc@(SYMBOL_NAME(kernel_pg_dir):w),%a5
-	movel	%a5,%a0
-	moveq	#ROOT_TABLE_SIZE-1,%d1
-1:	clrl	%a0@+
-	dbra	%d1,1b
+	lea	%pc@(L(phys_kernel_start)),%a0
+	lea	%pc@(SYMBOL_NAME(_stext)),%a1
+	subl	#SYMBOL_NAME(_stext),%a1
+	movel	%a1,%a0@
X 
-	/*
-	 * Initialize root table descriptor pointing to the kernel pointer
-	 * table.
-	 */
-	lea	%pc@(Lavail_pmd_table:w),%a4
-	moveq	#_PAGE_TABLE,%d0
-	addl	%a4,%d0
-	movel	%d0,%a5@
+	putc	'B'
X 
-	putc('C')
+	leds	0x4
X 
X /*
- * Initialize the pointer tables referred to above.  They either point
- * to page tables in the case of the 680[46]0 or contain early
- * termination page descriptors in the case of the 68851 or 68030.
+ *	mmu_init
X  *
- * Each pointer table entry points to a 64 entry page table.  16 of these
- * page tables are grouped to form a single 1024 entry page table which
- * fits in a single 4096 byte page.
- *
- * Some register usages:
- *    a0 -> pointer table descriptor address
- *    a1 -> pointer table descriptor
- *    d1 -> counter
- *    d2 -> pointer table descriptor increment (varies according to CPU)
+ *	This block of code does what's necessary to map in the various kinds
+ *	of machines for execution of Linux.
+ *	First map the first 4 MB of kernel code & data
X  */
X 
-	/* clear the kernel pointer table */
-	movel	%a4,%a0
-	moveq	#PTR_TABLE_SIZE-1,%d1
-1:	clrl	%a0@+
-	dbra	%d1,1b
-
-	movel	%a4,%a0
-	moveq	#15,%d1
-
-	/*
-	 * base value of pointer table descriptor is either
-	 * the address of the first page table (680[46]0)
-	 * or the base address of physical memory (68030).
-	 */
-	is_040_or_060(1f)
-
-	/* 680[23]0 */
-	movel	%d5,%a1				/* base address */
-	addql	#_PAGE_PRESENT,%a1		/* descriptor type */
-	movel	#PAGE_TABLE_SIZE*PAGESIZE,%d2	/* increment */
-	jra	2f
-
-1:	/* 680[46]0 */
-	movel	%a6,%a3			/* base address */
-	addw	#PAGESIZE,%a6		/* allocate page for 16 page tables */
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 02'
echo 'File patch-2.2.0-pre9 is continued in part 03'
echo 03 > _shar_seq_.tmp
#!/bin/sh
# this is part 03 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 03; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
-	lea	%pc@(SYMBOL_NAME(kpt)),%a1
-	movel	%a3,%a1@		/* save address of page table */
-	movel	%a3,%a1
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a1	/* descriptor type */
-	movel	#PAGE_TABLE_SIZE<<2,%d2 /* increment */
-
-2:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,2b
-
-	putc('D')
-
-/*
- * If we are running on a 680[46]0, we have a kernel page table and
- * must initialize it.	Make the entries point to the first
- * 4M of physical memory (the memory we are residing in).
- * Set the cache mode bits to Cacheable, Copyback.  Set the Global bits
- * in the descriptors also.
- */
-	is_not_040_or_060(Lnot040)
-
-	putc('F')
-
-	movel	%a3,%a0
-	movel	%d5,%a1
-#if defined(CONFIG_060_WRITETHROUGH)
-	addw	#_PAGE_GLOBAL040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-	addl	m68k_supervisor_cachemode,%a1
-#else
-	addw    #_PAGE_GLOBAL040+_PAGE_CACHE040+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-#endif
-	movew	#(PAGE_TABLE_SIZE*TABLENR_4MB)-1,%d1
-	movel	#PAGESIZE,%d2
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
-
-	/*
-	 * on the 68040, pages used to hold mmu tables should
-	 * be initialized as noncachable; the '060 allows write-through.
-	 * Do this for the root table page (which also contains
-	 * all pointer tables utilized thus far) and the
-	 * kernel page table.
-	 */
-	movel	%a5,%d0
-	subl	%d5,%d0
-	moveq	#PAGE_INDEX_SHIFT,%d2
-	lsrl	%d2,%d0
-	lea	%a3@(%d0:l:4),%a2
-	movel	%a2@,%d1
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@
+	mmu_map	#0,%pc@(L(phys_kernel_start)),#4*1024*1024,\
+		%pc@(SYMBOL_NAME(m68k_supervisor_cachemode))
X 
-	movel	%a3,%d0
-	subl	%d5,%d0
-	lsrl	%d2,%d0
-	lea	%a3@(%d0:l:4),%a2
-	movel	%a2@,%d1
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@+
-	/*
-	 * %a2 points now to the page table entry for available pages at %a6,
-	 * hence caching modes for new pages can easily set unless increasing
-	 * of %a2 are forgotten.
-	 */
-Lnot040:
+	putc	'C'
X 
-	leds(0x4)
-	
-/*
- * Do any machine specific page table initializations.
- */
X #ifdef CONFIG_AMIGA
-	is_not_amiga(Lnotami)
X 
+L(mmu_init_amiga):
+
+	is_not_amiga(L(mmu_init_not_amiga))
X /*
- * Setup a mapping of the first 16M of physical address space at virtual
- * address 0x80000000, using early termination page descriptors for the
- * 68030, and proper page tables for the 680[46]0.  Set this area as
- * non-cacheable.
+ * mmu_init_amiga
X  */
X 
-	putc('H')
-
-	is_040_or_060(Lspami68040)
-
-	/*
-	 * for the 68030, just setup a translation to map in the first
-	 * 32M of physical address space at virtual address 0x80000000
-         * using an early termination page descriptor.
-	 */
-
-	putc('I')
-
-	movel	#_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0
-	movel	%d0,%a5@(0x40<<2)
-
-	jra	Lmapphys
+	putc	'D'
X 
-Lspami68040:
+	is_not_040_or_060(1f)
X 
X 	/*
-	 * for the 680[46]0, use another pointer table, and allocate 4 more
-	 * page tables.  Initialize the pointer table to point to the
-	 * page tables.  Then initialize the page tables to point to
-	 * the first 16M of memory, with no caching (noncachable/serialized).
+	 * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
X 	 */
+	mmu_map	#0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
X 
-	/* clear the amiga pointer table */
-	lea	%a4@(PTR_TABLE_SIZE<<2),%a4
-	moveq	#PTR_TABLE_SIZE-1,%d1
-1:	clrl	%a0@+
-	dbra	%d1,1b
-
-	/* allocate 4 pages for 64 page tables */
-	movel	%a6,%a3
-	addw	#4*PAGESIZE,%a6
-
-	/* initialize the pointer table */
-	movel	%a4,%a0
-	movel	%a3,%a1
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a1	/* base descriptor */
-	movel	#PAGE_TABLE_SIZE<<2,%d2 /* increment */
-	moveq	#TABLENR_16MB-1,%d1
-
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
-
-	/* ensure that the root table points to the pointer table */
-	movel	%a4,%a0
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a0
-	movel	%a0,%a5@(0x40<<2)
+	jbra	L(mmu_init_done)
X 
+1:
X 	/*
-	 * initialize the page tables
-	 * descriptor bits include noncachable/serialized and global bits.
+	 * 030:	Map the 32Meg range physical 0x0 upto logical 0x8000.0000
X 	 */
-	movel	%a3,%a0
-	movew	#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-	movel	#PAGESIZE,%d2
-	movew	#(PAGE_TABLE_SIZE*TABLENR_16MB)-1,%d1
-
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
-
-	/*
-	 * Finally, since we just allocated 4 page tables, make sure that
-	 * the virtual mapping of the 4 page tables indicates
-	 * noncachable/serialized.
-	 */
-	moveq	#3,%d0
-1:	movel	%a2@,%d1	/* a2 already points to root table offset */
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@+
-	dbra	%d0,1b
+	mmu_map	#0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
X 
-	jra	Lmapphys
+	jbra	L(mmu_init_done)
X 
-Lnotami:
+L(mmu_init_not_amiga):
X #endif
X 
X #ifdef CONFIG_ATARI
-	is_not_atari(Lnotatari)
X 
-	move.w	#PAGESIZE,%sp
+L(mmu_init_atari):
+
+	is_not_atari(L(mmu_init_not_atari))
+
+	putc	'E'
X 
X /* On the Atari, we map the I/O region (phys. 0x00ffxxxx) by mapping
X    the last 16 MB of virtual address space to the first 16 MB (i.e.
@@ -591,103 +897,57 @@
X 
X 	/* I/O base addr for non-Medusa, non-Hades: 0x00000000 */
X 	moveq	#0,%d0
+	movel	%pc@(SYMBOL_NAME(atari_mch_type)),%d3
X 	cmpl	#ATARI_MACH_MEDUSA,%d3
X 	jbeq	2f
X 	cmpl	#ATARI_MACH_HADES,%d3
X 	jbne	1f
X 2:	movel	#0xff000000,%d0 /* Medusa/Hades base addr: 0xff000000 */
X 1:	movel	%d0,%d3
-	
-	/* Let the root table point to the new pointer table */
-	lea	%a4@(PTR_TABLE_SIZE<<2),%a4
-	movel	%a4,%a0
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a0
-	movel	%a0,%a5@(0x7f<<2)       /* 0xFE000000 - 0xFFFFFFFF */
X 
-	/* clear lower half of the pointer table (0xfexxxxxx) */
-	movel	%a4,%a0
-	movel	#(PTR_TABLE_SIZE/2)-1,%d2
-1:	clrl	%a0@+
-	dbra	%d2,1b
-
-	is_040_or_060(Lspata68040)
-
-/* Mapping of the last 16M of virtual address space to the first 16M
-   for efficient addressing of hardware registers */
-	movel	#PAGE_TABLE_SIZE*PAGESIZE,%d1
-	movel	#(PTR_TABLE_SIZE/2)-1,%d2
-	movel	%d3,%d0
-	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d0
-1:	movel	%d0,%a0@+
-	addl	%d1,%d0
-	dbra	%d2,1b
-	moveq	#_PAGE_NOCACHE030,%d0	/* make non-cachable */
-	addl	%d0,%a4@(0x7f<<2)	/* 0xFFFC0000-0xFFFFFFFF (I/O space) */
-/* GK: 0xFFF00000-0xFFF3FFFF (IDE-bus) has to be non-cachable too */
-	addl	%d0,%a4@(0x7c<<2)
-
-	jra	Lmapphys
-
-Lspata68040:
-	/* allocate 4 page tables */
-	movel	%a6,%a3
-	addw	#4*PAGESIZE,%a6
-
-	/* Initialize the upper half of the pointer table (a0 is still valid) */
-	movel	%a3,%a1
-	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a1
-	movel	#PAGE_TABLE_SIZE<<2,%d2
-	moveq	#TABLENR_16MB-1,%d1
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra 	%d1,1b
-
-	/* Initialize the page tables as noncacheable/serialized! */
-	movel	%a3,%a0
-	movel	%d3,%a1
-	addw	#_PAGE_GLOBAL040+_PAGE_NOCACHE_S+_PAGE_PRESENT+_PAGE_ACCESSED,%a1
-	movel	#PAGESIZE,%d2
-	movew	#(PAGE_TABLE_SIZE*TABLENR_16MB)-1,%d1
-1:	movel	%a1,%a0@+
-	addl	%d2,%a1
-	dbra	%d1,1b
+	is_040_or_060(L(spata68040))
X 
-	/*
-	 * Finally, since we just allocated 4 page tables, make sure that
-	 * the virtual mapping of the 4 page tables indicates
-	 * noncachable or write-through.
-	 */
-	moveq	#3,%d0
-1:	movel	%a2@,%d1	/* a2 already points to root table offset */
-	andw	#_CACHEMASK040,%d1
-	orw	%d6,%d1
-	movel	%d1,%a2@+
-	dbra	%d0,1b
+	/* Map everything non-cacheable, though not all parts really
+	 * need to disable caches (crucial only for 0xff8000..0xffffff
+	 * (standard I/O) and 0xf00000..0xf3ffff (IDE)). The remainder
+	 * isn't really used, except for sometimes peeking into the
+	 * ROMs (mirror at phys. 0x0), so caching isn't necessary for
+	 * this. */
+	mmu_map	#0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE030
+
+	jbra	L(mmu_init_done)
+
+L(spata68040):
X 
-Lnotatari:
+	mmu_map	#0xff000000,%d3,#0x01000000,#_PAGE_NOCACHE_S
+
+	jbra	L(mmu_init_done)
+
+L(mmu_init_not_atari):
X #endif
X 
X #ifdef CONFIG_HP300
-	is_not_hp300(Lnothp300)
+	is_not_hp300(L(nothp300))
X 
X /* On the HP300, we map the ROM, INTIO and DIO regions (phys. 0x00xxxxxx)
-   by mapping 32MB from 0xf0xxxxxx -> 0x00xxxxxx) using an 030 early 
-   termination page descriptor.  The ROM mapping is needed because the LEDs 
+   by mapping 32MB from 0xf0xxxxxx -> 0x00xxxxxx) using an 030 early
+   termination page descriptor.  The ROM mapping is needed because the LEDs
X    are mapped there too.  */
X 
-	movel	#_PAGE_NOCACHE030+_PAGE_PRESENT+_PAGE_ACCESSED,%d0
-	movel	%d0,%a5@(0x78<<2)
+	mmu_map	#0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030
+
+L(nothp300):
X 
-Lnothp300:
-	
X #endif
X 
-#if defined(CONFIG_MVME16x)
-	is_not_mvme16x(Lnot16x)
+#ifdef CONFIG_MVME16x
+
+	is_not_mvme16x(L(not16x))
X 
X 	/* Get pointer to board ID data */
X 	movel	%d2,%sp@-
-	.long	0x4e4f0070		/* trap 0x70 - .BRD_ID */
+	trap	#15
+	.word	0x70		/* trap 0x70 - .BRD_ID */
X 	movel	%sp@+,%d2
X 	lea	%pc@(SYMBOL_NAME(mvme_bdid_ptr)),%a0
X 	movel	%d2,%a0@
@@ -696,415 +956,1542 @@
X 	 * On MVME16x we have already created kernel page tables for
X 	 * 4MB of RAM at address 0, so now need to do a transparent
X 	 * mapping of the top of memory space.  Make it 0.5GByte for now.
+	 * Supervisor only access, so transparent mapping doesn't
+	 * clash with User code virtual address space.
+	 * this covers IO devices, PROM and SRAM.  The PROM and SRAM
+	 * mapping is needed to allow 167Bug to run.
+	 * IO is in the range 0xfff00000 to 0xfffeffff.
+	 * PROM is 0xff800000->0xffbfffff and SRAM is
+	 * 0xffe00000->0xffe1ffff.
X 	 */
X 
-	movel	#0xe01f0000,%d2		/* logical address base */
-	orw	#0xa040,%d2		/* add in magic bits */
-	.long	0x4e7b2005		/* movec d2,ittr1 */
-	.long	0x4e7b2007		/* movec d2,dttr1 */
+	mmu_map_tt	1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
X 
-Lnot16x:
-#endif
+	jbra	L(mmu_init_done)
+
+L(not16x):
+#endif	/* CONFIG_MVME162 | CONFIG_MVME167 */
+
+#ifdef CONFIG_BVME6000
X 
-#if defined(CONFIG_BVME6000)
-	is_not_bvme6000(Lnotbvm)
+	is_not_bvme6000(L(not6000))
X 
X 	/*
X 	 * On BVME6000 we have already created kernel page tables for
X 	 * 4MB of RAM at address 0, so now need to do a transparent
-	 * mapping of the top of memory space.  Make it 0.5GByte for now.
+	 * mapping of the top of memory space.  Make it 0.5GByte for now,
+	 * so we can access on-board i/o areas.
+	 * Supervisor only access, so transparent mapping doesn't
+	 * clash with User code virtual address space.
X 	 */
X 
-	movel	#0xe01f0000,%d2		/* logical address base */
-	orw	#0xa040,%d2		/* add in magic bits */
-	.long	0x4e7b2005		/* movec d2,ittr1 */
-	.long	0x4e7b2007		/* movec d2,dttr1 */
-	.long	0x4e7b2004		/* movec d2,ittr0 */
-	.long	0x4e7b2006		/* movec d2,dttr0 */
+	mmu_map_tt	1,#0xe0000000,#0x20000000,#_PAGE_NOCACHE_S
X 
-Lnotbvm:
-#endif
+	jbra	L(mmu_init_done)
+
+L(not6000):
+#endif /* CONFIG_BVME6000 */
X 
X /*
- * Setup a transparent mapping of the physical memory we are executing in.
+ * mmu_init_mac
+ *
+ * The Macintosh mappings are less clear.
+ *
+ * Even as of this writing, it is unclear how the
+ * Macintosh mappings will be done.  However, as
+ * the first author of this code I'm proposing the
+ * following model:
+ *
+ * Map the kernel (that's already done),
+ * Map the I/O (on most machines that's the
+ * 0x5000.0000 ... 0x5200.0000 range,
+ * Map the video frame buffer using as few pages
+ * as absolutely (this requirement mostly stems from
+ * the fact that when the frame buffer is at
+ * 0x0000.0000 then we know there is valid RAM just
+ * above the screen that we don't want to waste!).
+ *
+ * By the way, if the frame buffer is at 0x0000.0000
+ * then the Macintosh is known as an RBV based Mac.
X  *
- * Only do this if the physical memory is not in the first 16M Meg, or not on
- * an Amiga since the first 16M is already identity mapped on the Amiga.
+ * By the way 2, the code currently maps in a bunch of
+ * regions.  But I'd like to cut that out.  (And move most
+ * of the mappings up into the kernel proper ... or only
+ * map what's necessary.)
X  */
-Lmapphys:
-	putc('J')
-	leds(0x8)
X 
-#ifdef CONFIG_AMIGA
-	is_not_amiga(Lmapphysnotamiga)
+#ifdef CONFIG_MAC
X 
-/*
- * The virtual address of the start of the kernel is 0x1000. We transparently
- * translate the memory where we running in and can enable then the MMU. Hence
- * we have now two locations of the kernel in memory and can jump to the final
- * place. Except if the physical location is in the first 16MB, translation
- * will overlap later virtual location, but as we already mapped the first
- * 16MB to 0x80000000, we can jump there after translation and MMU is enabled
- * and then we can switch off translation and go to the final place.
- * On 020/030 we must emulate transparant translation, since 020 doesn't know
- * it, but due to early termination pointer this is easy to do.
- * When MMU is enabled, stack pointer and Lcustom will become again valid and
- * stack points to the unused first page.
- */
+L(mmu_init_mac):
X 
-/*
- * Setup Supervisor Root Pointer register to point to page directory,
- * setup translation register contents and enable translation.
- */
-	putc('K')
+	is_not_mac(L(mmu_init_not_mac))
X 
-	movew	#PAGESIZE,%sp
+	putc	'F'
X 
-	/* fixup the Amiga custom register location before printing */
-	lea	%pc@(Lcustom),%a0
-	movel	#0x80000000,%a0@
+	lea	%pc@(L(mac_videobase)),%a0
+	lea	%pc@(L(console_video_virtual)),%a1
+	movel	%a0@,%a1@
X 
-	is_040_or_060(Lamimmu68040)
+	is_not_040_or_060(1f)
X 
-	moveq	#ROOT_INDEX_SHIFT,%d2
-	movel	%d5,%d0
-	lsrl	%d2,%d0
-	movel	%d0,%d1
-	lsll	%d2,%d1
-	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d1
-	lsll	#2,%d0
-	movel	%a5@(%d0:w),%d2
-	movel	%d1,%a5@(%d0:w)
-	lea	%pc@(Lmmu),%a3
-	/* no limit, 4byte descriptors */
-	movel	#0x80000002,%a3@
-	movel	%a5,%a3@(4)
-	pmove	%a3@,%srp
-	pmove	%a3@,%crp
-	pflusha
+	moveq	#_PAGE_NOCACHE_S,%d3
+	jbra	2f
+1:
+	moveq	#_PAGE_NOCACHE030,%d3
+2:
X 	/*
-	 * enable,super root enable,4096 byte pages,7 bit root index,
-	 * 7 bit pointer index, 6 bit page table index.
+	 * Mac Note: screen address of logical 0xF000.0000 -> <screen physical>
+	 *	     we simply map the 4MB that contains the videomem
X 	 */
-	movel	#0x82c07760,%a3@
-	pmove	%a3@,%tc	/* enable the MMU */
-	tstl	%d0
-	jne	1f
-	jmp	%pc@(2f+0x80000000)
-1:	jmp	2f:w
-2:	movel	%d2,%a5@(%d0:w)
-	pflusha
-	jmp	LdoneMMUenable:w
X 
-Lamimmu68040:
+	movel	#VIDEOMEMMASK,%d0
+	andl	L(mac_videobase),%d0
X 
-	.chip	68040
-	lea	2f:w,%a0
-	movel	%d5,%d0
-	andl	#0xff000000,%d0
-	jne	1f
-	lea	%pc@(2f+0x80000000),%a0
-1:	orw	#TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
-	movec	%d0,%itt0
-	movec	%a5,%urp
-	movec	%a5,%srp
-	pflusha
-	movel	#TC_ENABLE+TC_PAGE4K,%d0
-	/*
-	 * this value is also ok for the 68060, we don`t use the cache
-	 * mode/protection defaults
-	 */
-	movec	%d0,%tc		/* enable the MMU */
-	jmp	%a0@
-2:	moveq	#0,%d0
-	movec	%d0,%itt0
-	jmp	LdoneMMUenable:w
-	.chip	68k
+	mmu_map		#VIDEOMEMBASE,%d0,#VIDEOMEMSIZE,%d3
+	mmu_map_eq	#0x40800000,#0x02000000,%d3	/* rom ? */
+	mmu_map_eq	#0x50000000,#0x02000000,%d3
+	mmu_map_eq	#0x60000000,#0x00400000,%d3
+	mmu_map_eq	#0x9c000000,#0x00400000,%d3
+	mmu_map_tt	1,#0xf8000000,#0x08000000,%d3
X 
-Lmapphysnotamiga:
+	jbra	L(mmu_init_done)
+
+L(mmu_init_not_mac):
X #endif
X 
-#ifdef CONFIG_ATARI
-	is_not_atari(Lmapphysnotatari)
+L(mmu_init_done):
+
+	putc	'G'
+	leds	0x8
X 
X /*
- * If the kernel physical address is different from its virtual address, we
- * will temporarily set up an identity mapping of the 16MB chunk with
- * transparent translation where the kernel is executing.
+ * mmu_fixup
+ *
+ * On the 040 class machines, all pages that are used for the
+ * mmu have to be fixed up. According to Motorola, pages holding mmu
+ * tables should be non-cacheable on a '040 and write-through on a
+ * '060. But analysis of the reasons for this, and practical
+ * experience, showed that write-through also works on a '040.
+ *
+ * Allocated memory so far goes from kernel_end to memory_start that
+ * is used for all kind of tables, for that the cache attributes
+ * are now fixed.
X  */
-	putc('L')
+L(mmu_fixup):
X 
-	/* fixup the  Atari iobase register location before printing */
-	lea	%pc@(Liobase),%a0
-	movel	#0xff000000,%a0@
+	is_not_040_or_060(L(mmu_fixup_done))
X 
-	is_040_or_060(Latarimmu68040)
+#ifdef MMU_NOCACHE_KERNEL
+	jbra	L(mmu_fixup_done)
+#endif
X 
-	.chip	68030
-	lea	%pc@(Lmmu),%a3
-	movel	%d5,%d0
-	jne	1f
-	lea	LdoneMMUenable:w,%a0
-	jra	3f
-1:	lea	4f:w,%a0
-	andl	#0xff000000,%d0 /* logical address base */
-	jeq	2f
-	orw	#TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
-	movel	%d0,%a3@
-	pmove	%a3@,%tt0
-	jra	3f
-	/* tt0 doesn't work if physical and virtual address of kernel is in
-	 * the same 16M area (Falcon with Magnum/FX, kernel in alternate ram)
-	 * Transparent translation through kernel pointer table
-	 * Requires that this code until after MMU enabling lies in
-	 * the 256K page around %d5
-	 */
-2:	movel	%a5@,%d1
-	andw	#0xfff0,%d1
-	movel	%d1,%a1
-	movel	%d5,%d1
-	moveq	#PTR_INDEX_SHIFT,%d0
-	lsrl	%d0,%d1
-	lea	%a1@(%d1:l:4),%a1
-	movel	%d5,%d1
-	orw	#_PAGE_PRESENT+_PAGE_ACCESSED,%d1
-	movel	%a1@,%d2
-	movel	%d1,%a1@
-	lea	5f:w,%a0
-	/* no limit, 4byte descriptors */
-3:	movel	#0x80000002,%a3@
-	movel	%a5,%a3@(4)
-	pmove	%a3@,%srp
-	pmove	%a3@,%crp
-	pflusha
-	/*
-	 * enable,super root enable,4096 byte pages,7 bit root index,
-	 * 7 bit pointer index, 6 bit page table index.
-	 */
-	movel	#0x82c07760,%a3@
-	pmove	%a3@,%tc	/* enable the MMU */
-	jmp	%a0@
-4:	clrl	%a3@
-	pmove	%a3@,%tt0
-	jra	LdoneMMUenable
-5:	movel	%d2,%a1@
-	jra	LdoneMMUenable
-	.chip	68k
-
-Latarimmu68040:
-	.chip	68040
-	movel	%d5,%d0
-	jne	1f
-	lea	LdoneMMUenable:w,%a0
-	jra	2f
-1:	lea	3f:w,%a0
-	andl	#0xff000000,%d0 /* logical address base */
-	orw	#TTR_ENABLE+TTR_KERNELMODE+_PAGE_NOCACHE_S,%d0
-	movec	%d0,%itt0
-2:	nop
-	pflusha
-	movec	%a5,%srp
-	movec	%a5,%urp
-	movel	#TC_ENABLE+TC_PAGE4K,%d0
-	/*
-	 * this value is also ok for the 68060, we don`t use the cache
-	 * mode/protection defaults
+	/* first fix the page at the start of the kernel, that
+         * contains also kernel_pg_dir.
X 	 */
-	movec	%d0,%tc		/* enable the MMU */
-	jmp	%a0@
-3:	moveq	#0,%d0
-	movec	%d0,%itt0
-	jra	LdoneMMUenable
-	.chip	68k
-
-Lmapphysnotatari:
-#endif
+	movel	%pc@(L(phys_kernel_start)),%d0
+	lea	%pc@(SYMBOL_NAME(_stext)),%a0
+	subl	%d0,%a0
+	mmu_fixup_page_mmu_cache	%a0
X 
-#if defined(CONFIG_MVME16x)
-	is_not_mvme16x(Lmapphysnot16x)
-	/*
-	 * save physaddr of phys mem in register a3
-	 */
-	moveq	#'L',%d7
-	jbsr	Lserial_putc
-
-	.word	0xf4d8		/* CINVA I/D    */
-	.word	0xf518		/* pflusha      */
-	.long	0x4e7bd807	/* movec a5,srp */
-	.long	0x4e7bd806	/* movec a5,urp */
-	movel	#(TC_ENABLE+TC_PAGE4K),%d0
-	.long	0x4e7b0003	/* movec d0,tc  (enable the MMU) */
-	jra	LdoneMMUenable	/* branch to continuation of startup */
+	movel	%pc@(L(kernel_end)),%a0
+	subl	%d0,%a0
+	movel	%pc@(L(memory_start)),%a1
+	subl	%d0,%a1
+	bra	2f
+1:
+	mmu_fixup_page_mmu_cache	%a0
+	addw	#PAGESIZE,%a0
+2:
+	cmpl	%a0,%a1
+	jgt	1b
X 
-Lmapphysnot16x:
+L(mmu_fixup_done):
X 
+#ifdef MMU_PRINT
+	mmu_print
X #endif
X 
-#if defined(CONFIG_HP300)
-	is_not_hp300(Lmapphysnothp300)
-
X /*
- * Physical RAM is at 0xff000000.  We want to map the kernel at 0x00000000.
- * In order to avoid disaster when we enable the MMU we need to make a
- * transparent mapping of the RAM we're executing out of as well.
+ * mmu_engage
+ *
+ * This chunk of code performs the gruesome task of engaging the MMU.
+ * The reason its gruesome is because when the MMU becomes engaged it
+ * maps logical addresses to physical addresses.  The Program Counter
+ * register is then passed through the MMU before the next instruction
+ * is fetched (the instruction following the engage MMU instruction).
+ * This may mean one of two things:
+ * 1. The Program Counter falls within the logical address space of
+ *    the kernel of which there are two sub-possibilities:
+ *    A. The PC maps to the correct instruction (logical PC == physical
+ *       code location), or
+ *    B. The PC does not map through and the processor will read some
+ *       data (or instruction) which is not the logically next instr.
+ *    As you can imagine, A is good and B is bad.
+ * Alternatively,
+ * 2. The Program Counter does not map through the MMU.  The processor
+ *    will take a Bus Error.
+ * Clearly, 2 is bad.
+ * It doesn't take a wiz kid to figure you want 1.A.
+ * This code creates that possibility.
+ * There are two possible 1.A. states (we now ignore the other above states):
+ * A. The kernel is located at physical memory addressed the same as
+ *    the logical memory for the kernel, i.e., 0x01000.
+ * B. The kernel is located some where else.  e.g., 0x0400.0000
+ *
+ *    Under some conditions the Macintosh can look like A or B.
+ * [A friend and I once noted that Apple hardware engineers should be
+ * wacked twice each day: once when they show up at work (as in, Whack!,
+ * "This is for the screwy hardware we know you're going to design today."),
+ * and also at the end of the day (as in, Whack! "I don't know what
+ * you designed today, but I'm sure it wasn't good."). -- rst]
+ *
+ * This code works on the following premise:
+ * If the kernel start (%d5) is within the first 16 Meg of RAM,
+ * then create a mapping for the kernel at logical 0x8000.0000 to
+ * the physical location of the pc.  And, create a transparent
+ * translation register for the first 16 Meg.  Then, after the MMU
+ * is engaged, the PC can be moved up into the 0x8000.0000 range
+ * and then the transparent translation can be turned off and then
+ * the PC can jump to the correct logical location and it will be
+ * home (finally).  This is essentially the code that the Amiga used
+ * to use.  Now, it's generalized for all processors.  Which means
+ * that a fresh (but temporary) mapping has to be created.  The mapping
+ * is made in page 0 (an as of yet unused location -- except for the
+ * stack!).  This temporary mapping will only require 1 pointer table
+ * and a single page table (it can map 256K).
+ *
+ * OK, alternatively, imagine that the Program Counter is not within
+ * the first 16 Meg.  Then, just use Transparent Translation registers
+ * to do the right thing.
+ *
+ * Last, if _start is already at 0x01000, then there's nothing special
+ * to do (in other words, in a degenerate case of the first case above,
+ * do nothing).
+ *
+ * Let's do it.
+ *
+ *
X  */
-	/*
-	 * save physaddr of phys mem in register a3
-	 */
X 
-	.chip	68030
-	lea	%pc@(Lmmu),%a3
-	movel	%d5,%d0
-	andl	#0xff000000,%d0 /* logical address base */
-	orw	#TTR_ENABLE+TTR_CI+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d0
-	movel	%d0,%a3@
-	pmove	%a3@,%tt0
-	/* no limit, 4byte descriptors */
-	movel	#0x80000002,%a3@
-	movel	%a5,%a3@(4)
-	pmove	%a3@,%srp
-	pmove	%a3@,%crp
-	pflusha
-	/*
-	 * enable,super root enable,4096 byte pages,7 bit root index,
-	 * 7 bit pointer index, 6 bit page table index.
-	 */
-	movel	#0x82c07760,%a3@
-	pmove	%a3@,%tc	/* enable the MMU */
-	jmp	1f
-1:	
-	.chip	68k
+	putc	'H'
X 
-	/*
-	 * Fix up the custom register to point to the new location of the LEDs.
-	 */
-	lea	%pc@(Lcustom),%a1
-	movel	#0xf0000000,%a1@
+	mmu_engage
X 
-	/*
-	 * Energise the FPU and caches.
-	 */
-	orl	#0x64, 0xf05f400c 
-	
-Lmapphysnothp300:
+#ifdef CONFIG_AMIGA
+	is_not_amiga(1f)
+	/* fixup the Amiga custom register location before printing */
+	clrl	L(custom)
+1:
+#endif
X 
+#ifdef CONFIG_ATARI
+	is_not_atari(1f)
+	/* fixup the Atari iobase register location before printing */
+	movel	#0xff000000,L(iobase)
+1:
+#endif
+
+#ifdef CONFIG_MAC
+	is_not_mac(1f)
+	movel	#~VIDEOMEMMASK,%d0
+	andl	L(mac_videobase),%d0
+	addl	#VIDEOMEMBASE,%d0
+	movel	%d0,L(mac_videobase)
+1:
X #endif
X 
-#if defined(CONFIG_BVME6000)
-	is_not_bvme6000(Lmapphysnotbvm)
+#ifdef CONFIG_HP300
+	is_not_hp300(1f)
X 	/*
-	 * save physaddr of phys mem in register a3
+	 * Fix up the custom register to point to the new location of the LEDs.
X 	 */
-	moveq	#'L',%d7
-	jbsr	Lserial_putc
+	movel	#0xf0000000,L(custom)
X 
-	.word	0xf4d8		/* CINVA I/D    */
-	.word	0xf518		/* pflusha      */
-	.long	0x4e7bd807	/* movec a5,srp */
-	.long	0x4e7bd806	/* movec a5,urp */
-	movel	#(TC_ENABLE+TC_PAGE4K),%d0
X 	/*
-	 * this value is also ok for the 68060, we don`t use the cache
-	 * mode/protection defaults
+	 * Energise the FPU and caches.
X 	 */
-	.long	0x4e7b0003	/* movec d0,tc  (enable the MMU) */
-	jra	LdoneMMUenable	/* branch to continuation of startup */
-
-Lmapphysnotbvm:
-
+	movel	#0x60,0xf05f400c
+1:
X #endif
X 
-LdoneMMUenable:
-
X /*
X  * Fixup the addresses for the kernel pointer table and availmem.
X  * Convert them from physical addresses to virtual addresses.
X  */
X 
-	putc('M')
-	leds(0x10)
+	putc	'I'
+	leds	0x10
X 
-	/*
-	 * d5 contains physaddr of kernel start
-	 */
-	subl	%d5,SYMBOL_NAME(kpt)
-
-	/*
-	 * do the same conversion on the first available memory
+	/* do the same conversion on the first available memory
X 	 * address (in a6).
X 	 */
-	subl	%d5,%a6
-	movel	%a6,SYMBOL_NAME(availmem) /* first available memory address */
-
-	putc('N')
+	movel	L(memory_start),%d0
+	movel	%d0,SYMBOL_NAME(availmem)
X 
X /*
X  * Enable caches
X  */
-	is_040_or_060(Lcache680460)
X 
-	movel	#CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
-	movec	%d0,%cacr
-	jra	1f
+	is_not_040_or_060(L(cache_not_680460))
X 
-Lcache680460:
+L(cache680460):
X 	.chip	68040
+	nop
X 	cpusha	%bc
-	.chip	68k
+	nop
X 
-	is_060(Lcache68060)
+	is_060(L(cache68060))
X 
X 	movel	#CC6_ENABLE_D+CC6_ENABLE_I,%d0
X 	/* MMU stuff works in copyback mode now, so enable the cache */
X 	movec	%d0,%cacr
-	jra	1f
+	jra	L(cache_done)
X 
-Lcache68060:
-	.chip	68060
+L(cache68060):
X 	movel	#CC6_ENABLE_D+CC6_ENABLE_I+CC6_ENABLE_SB+CC6_PUSH_DPI+CC6_ENABLE_B+CC6_CLRA_B,%d0
X 	/* MMU stuff works in copyback mode now, so enable the cache */
X 	movec	%d0,%cacr
X 	/* enable superscalar dispatch in PCR */
X 	moveq	#1,%d0
+	.chip	68060
X 	movec	%d0,%pcr
+
+	jbra	L(cache_done)
+L(cache_not_680460):
+L(cache68030):
+	.chip	68030
+	movel	#CC3_ENABLE_DB+CC3_CLR_D+CC3_ENABLE_D+CC3_ENABLE_IB+CC3_CLR_I+CC3_ENABLE_I,%d0
+	movec	%d0,%cacr
+
+	jra	L(cache_done)
X 	.chip	68k
-1:
+L(cache_done):
+
+	putc	'J'
X 
X /*
X  * Setup initial stack pointer
- * We need to get current loaded up with our first task...
X  */
X 	lea	SYMBOL_NAME(init_task_union),%a2
-	lea	8192(%a2),%sp
+	lea	0x2000(%a2),%sp
X 
X /* jump to the kernel start */
-	putr()
-	leds(0x55)
+	putc	'\n'
+	leds	0x55
X 
-	subl	%a6,%a6 /* clear a6 for gdb */
+	subl	%a6,%a6		/* clear a6 for gdb */
X 	jbsr	SYMBOL_NAME(start_kernel)
X 
-/*
- * Find a tag record in the bootinfo structure
- * The bootinfo structure is located right after the kernel bss
- * Returns: d0: size (-1 if not found)
- *          a0: data pointer (end-of-records if not found)
- */
-Lget_bi_record:
-	lea	%pc@(SYMBOL_NAME(_end)),%a0
-1:	tstw	%a0@(BIR_tag)
-	jeq	3f
-	cmpw	%a0@(BIR_tag),%d0
-	jeq	2f
-	addw	%a0@(BIR_size),%a0
-	jra	1b
-2:	moveq	#0,%d0
-	movew	%a0@(BIR_size),%d0
-	lea	%a0@(BIR_data),%a0
-	rts
-3:	moveq	#-1,%d0
-	lea	%a0@(BIR_size),%a0
-	rts
+/*
+ * Find a tag record in the bootinfo structure
+ * The bootinfo structure is located right after the kernel bss
+ * Returns: d0: size (-1 if not found)
+ *          a0: data pointer (end-of-records if not found)
+ */
+func_start	get_bi_record,%d1
+
+	movel	ARG1,%d0
+	lea	%pc@(SYMBOL_NAME(_end)),%a0
+1:	tstw	%a0@(BIR_TAG)
+	jeq	3f
+	cmpw	%a0@(BIR_TAG),%d0
+	jeq	2f
+	addw	%a0@(BIR_SIZE),%a0
+	jra	1b
+2:	moveq	#0,%d0
+	movew	%a0@(BIR_SIZE),%d0
+	lea	%a0@(BIR_DATA),%a0
+	jra	4f
+3:	moveq	#-1,%d0
+	lea	%a0@(BIR_SIZE),%a0
+4:
+func_return	get_bi_record
+
+
+/*
+ *	MMU Initialization Begins Here
+ *
+ *	The structure of the MMU tables on the 68k machines
+ *	is thus:
+ *	Root Table
+ *		Logical addresses are translated through
+ *	a hierarchical translation mechanism where the high-order
+ *	seven bits of the logical address (LA) are used as an
+ *	index into the "root table."  Each entry in the root
+ *	table has a bit which specifies if it's a valid pointer to a
+ *	pointer table.  Each entry defines a 32KMeg range of memory.
+ *	If an entry is invalid then that logical range of 32M is
+ *	invalid and references to that range of memory (when the MMU
+ *	is enabled) will fault.  If the entry is valid, then it does
+ *	one of two things.  On 040/060 class machines, it points to
+ *	a pointer table which then describes more finely the memory
+ *	within that 32M range.  On 020/030 class machines, a technique
+ *	called "early terminating descriptors" are used.  This technique
+ *	allows an entire 32Meg to be described by a single entry in the
+ *	root table.  Thus, this entry in the root table, contains the
+ *	physical address of the memory or I/O at the logical address
+ *	which the entry represents and it also contains the necessary
+ *	cache bits for this region.
+ *
+ *	Pointer Tables
+ *		Per the Root Table, there will be one or more
+ *	pointer tables.  Each pointer table defines a 32M range.
+ *	Not all of the 32M range need be defined.  Again, the next
+ *	seven bits of the logical address are used an index into
+ *	the pointer table to point to page tables (if the pointer
+ *	is valid).  There will undoubtedly be more than one
+ *	pointer table for the kernel because each pointer table
+ *	defines a range of only 32M.  Valid pointer table entries
+ *	point to page tables, or are early terminating entries
+ *	themselves.
+ *
+ *	Page Tables
+ *		Per the Pointer Tables, each page table entry points
+ *	to the physical page in memory that supports the logical
+ *	address that translates to the particular index.
+ *
+ *	In short, the Logical Address gets translated as follows:
+ *		bits 31..26 - index into the Root Table
+ *		bits 25..18 - index into the Pointer Table
+ *		bits 17..12 - index into the Page Table
+ *		bits 11..0  - offset into a particular 4K page
+ *
+ *	The algorithms which follows do one thing: they abstract
+ *	the MMU hardware.  For example, there are three kinds of
+ *	cache settings that are relevant.  Either, memory is
+ *	being mapped in which case it is either Kernel Code (or
+ *	the RamDisk) or it is MMU data.  On the 030, the MMU data
+ *	option also describes the kernel.  Or, I/O is being mapped
+ *	in which case it has its own kind of cache bits.  There
+ *	are constants which abstract these notions from the code that
+ *	actually makes the call to map some range of memory.
+ *
+ *
+ *
+ */
+
+#ifdef MMU_PRINT
+/*
+ *	mmu_print
+ *
+ *	This algorithm will print out the current MMU mappings.
+ *
+ *	Input:
+ *		%a5 points to the root table.  Everything else is calculated
+ *			from this.
+ */
+
+#define mmu_next_valid		0
+#define mmu_start_logical	4
+#define mmu_next_logical	8
+#define mmu_start_physical	12
+#define mmu_next_physical	16
+
+#define MMU_PRINT_INVALID		-1
+#define MMU_PRINT_VALID			1
+#define MMU_PRINT_UNINITED		0
+
+#define putZc(z,n)		jbne 1f; putc z; jbra 2f; 1: putc n; 2:
+
+func_start	mmu_print,%a0-%a6/%d0-%d7
+
+	movel	%pc@(L(kernel_pgdir_ptr)),%a5
+	lea	%pc@(L(mmu_print_data)),%a0
+	movel	#MMU_PRINT_UNINITED,%a0@(mmu_next_valid)
+
+	is_not_040_or_060(mmu_030_print)
+
+mmu_040_print:
+	puts	"\nMMU040\n"
+	puts	"rp:"
+	putn	%a5
+	putc	'\n'
+#if 0
+	/*
+	 * The following #if/#endif block is a tight algorithm for dumping the 040
+	 * MMU Map in gory detail.  It really isn't that practical unless the
+	 * MMU Map algorithm appears to go awry and you need to debug it at the
+	 * entry per entry level.
+	 */
+	movel	#ROOT_TABLE_SIZE,%d5
+#if 0
+	movel	%a5@+,%d7		| Burn an entry to skip the kernel mappings,
+	subql	#1,%d5			| they (might) work
+#endif
+1:	tstl	%d5
+	jbeq	mmu_print_done
+	subq	#1,%d5
+	movel	%a5@+,%d7
+	btst	#1,%d7
+	jbeq	1b
+
+2:	putn	%d7
+	andil	#0xFFFFFE00,%d7
+	movel	%d7,%a4
+	movel	#PTR_TABLE_SIZE,%d4
+	putc	' '
+3:	tstl	%d4
+	jbeq	11f
+	subq	#1,%d4
+	movel	%a4@+,%d7
+	btst	#1,%d7
+	jbeq	3b
+
+4:	putn	%d7
+	andil	#0xFFFFFF00,%d7
+	movel	%d7,%a3
+	movel	#PAGE_TABLE_SIZE,%d3
+5:	movel	#8,%d2
+6:	tstl	%d3
+	jbeq	31f
+	subq	#1,%d3
+	movel	%a3@+,%d6
+	btst	#0,%d6
+	jbeq	6b
+7:	tstl	%d2
+	jbeq	8f
+	subq	#1,%d2
+	putc	' '
+	jbra	91f
+8:	putc	'\n'
+	movel	#8+1+8+1+1,%d2
+9:	putc	' '
+	dbra	%d2,9b
+	movel	#7,%d2
+91:	putn	%d6
+	jbra	6b
+
+31:	putc	'\n'
+	movel	#8+1,%d2
+32:	putc	' '
+	dbra	%d2,32b
+	jbra	3b
+
+11:	putc	'\n'
+	jbra	1b
+#endif /* MMU 040 Dumping code that's gory and detailed */
+
+	lea	%pc@(SYMBOL_NAME(kernel_pg_dir)),%a5
+	movel	%a5,%a0			/* a0 has the address of the root table ptr */
+	movel	#0x00000000,%a4		/* logical address */
+	moveql	#0,%d0
+40:
+	/* Increment the logical address and preserve in d5 */
+	movel	%a4,%d5
+	addil	#PAGESIZE<<13,%d5
+	movel	%a0@+,%d6
+	btst	#1,%d6
+	jbne	41f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	48f
+41:
+	movel	#0,%d1
+	andil	#0xfffffe00,%d6
+	movel	%d6,%a1
+42:
+	movel	%a4,%d5
+	addil	#PAGESIZE<<6,%d5
+	movel	%a1@+,%d6
+	btst	#1,%d6
+	jbne	43f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	47f
+43:
+	movel	#0,%d2
+	andil	#0xffffff00,%d6
+	movel	%d6,%a2
+44:
+	movel	%a4,%d5
+	addil	#PAGESIZE,%d5
+	movel	%a2@+,%d6
+	btst	#0,%d6
+	jbne	45f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	46f
+45:
+	moveml	%d0-%d1,%sp@-
+	movel	%a4,%d0
+	movel	%d6,%d1
+	andil	#0xfffff4e0,%d1
+	lea	%pc@(mmu_040_print_flags),%a6
+	jbsr	mmu_print_tuple
+	moveml	%sp@+,%d0-%d1
+46:
+	movel	%d5,%a4
+	addq	#1,%d2
+	cmpib	#64,%d2
+	jbne	44b
+47:
+	movel	%d5,%a4
+	addq	#1,%d1
+	cmpib	#128,%d1
+	jbne	42b
+48:
+	movel	%d5,%a4			/* move to the next logical address */
+	addq	#1,%d0
+	cmpib	#128,%d0
+	jbne	40b
+
+	.chip	68040
+	movec	%dtt1,%d0
+	movel	%d0,%d1
+	andiw	#0x8000,%d1		/* is it valid ? */
+	jbeq	1f			/* No, bail out */
+
+	movel	%d0,%d1
+	andil	#0xff000000,%d1		/* Get the address */
+	putn	%d1
+	puts	"=="
+	putn	%d1
+
+	movel	%d0,%d6
+	jbsr	mmu_040_print_flags_tt
+1:
+	movec	%dtt0,%d0
+	movel	%d0,%d1
+	andiw	#0x8000,%d1		/* is it valid ? */
+	jbeq	1f			/* No, bail out */
+
+	movel	%d0,%d1
+	andil	#0xff000000,%d1		/* Get the address */
+	putn	%d1
+	puts	"=="
+	putn	%d1
+
+	movel	%d0,%d6
+	jbsr	mmu_040_print_flags_tt
+1:
+	.chip	68k
+
+	jbra	mmu_print_done
+
+mmu_040_print_flags:
+	btstl	#10,%d6
+	putZc(' ','G')	/* global bit */
+	btstl	#7,%d6
+	putZc(' ','S')	/* supervisor bit */
+mmu_040_print_flags_tt:
+	btstl	#6,%d6
+	jbne	3f
+	putc	'C'
+	btstl	#5,%d6
+	putZc('w','c')	/* write through or copy-back */
+	jbra	4f
+3:
+	putc	'N'
+	btstl	#5,%d6
+	putZc('s',' ')	/* serialized non-cacheable, or non-cacheable */
+4:
+	rts
+
+mmu_030_print_flags:
+	btstl	#6,%d6
+	putZc('C','I')	/* write through or copy-back */
+	rts
+
+mmu_030_print:
+	puts	"\nMMU030\n"
+	puts	"\nrp:"
+	putn	%a5
+	putc	'\n'
+	movel	%a5,%d0
+	andil	#0xfffffff0,%d0
+	movel	%d0,%a0
+	movel	#0x00000000,%a4		/* logical address */
+	movel	#0,%d0
+30:
+	movel	%a4,%d5
+	addil	#PAGESIZE<<13,%d5
+	movel	%a0@+,%d6
+	btst	#1,%d6			/* is it a ptr? */
+	jbne	31f			/* yes */
+	btst	#0,%d6			/* is it early terminating? */
+	jbeq	1f			/* no */
+	jbsr	mmu_030_print_helper
+	jbra	38f
+1:
+	jbsr	mmu_print_tuple_invalidate
+	jbra	38f
+31:
+	movel	#0,%d1
+	andil	#0xfffffff0,%d6
+	movel	%d6,%a1
+32:
+	movel	%a4,%d5
+	addil	#PAGESIZE<<6,%d5
+	movel	%a1@+,%d6
+	btst	#1,%d6
+	jbne	33f
+	btst	#0,%d6
+	jbeq	1f			/* no */
+	jbsr	mmu_030_print_helper
+	jbra	37f
+1:
+	jbsr	mmu_print_tuple_invalidate
+	jbra	37f
+33:
+	movel	#0,%d2
+	andil	#0xfffffff0,%d6
+	movel	%d6,%a2
+34:
+	movel	%a4,%d5
+	addil	#PAGESIZE,%d5
+	movel	%a2@+,%d6
+	btst	#0,%d6
+	jbne	35f
+	jbsr	mmu_print_tuple_invalidate
+	jbra	36f
+35:
+	jbsr	mmu_030_print_helper
+36:
+	movel	%d5,%a4
+	addq	#1,%d2
+	cmpib	#64,%d2
+	jbne	34b
+37:
+	movel	%d5,%a4
+	addq	#1,%d1
+	cmpib	#128,%d1
+	jbne	32b
+38:
+	movel	%d5,%a4			/* move to the next logical address */
+	addq	#1,%d0
+	cmpib	#128,%d0
+	jbne	30b
+
+mmu_print_done:
+	puts	"\n\n"
+
+func_return	mmu_print
+
+
+mmu_030_print_helper:
+	moveml	%d0-%d1,%sp@-
+	movel	%a4,%d0
+	movel	%d6,%d1
+	lea	%pc@(mmu_030_print_flags),%a6
+	jbsr	mmu_print_tuple
+	moveml	%sp@+,%d0-%d1
+	rts
+
+mmu_print_tuple_invalidate:
+	moveml	%a0/%d7,%sp@-
+
+	lea	%pc@(L(mmu_print_data)),%a0
+	tstl	%a0@(mmu_next_valid)
+	jbmi	mmu_print_tuple_invalidate_exit
+
+	movel	#MMU_PRINT_INVALID,%a0@(mmu_next_valid)
+
+	putn	%a4
+
+	puts	"##\n"
+
+mmu_print_tuple_invalidate_exit:
+	moveml	%sp@+,%a0/%d7
+	rts
+
+
+mmu_print_tuple:
+	moveml	%d0-%d7/%a0,%sp@-
+
+	lea	%pc@(L(mmu_print_data)),%a0
+
+	tstl	%a0@(mmu_next_valid)
+	jble	mmu_print_tuple_print
+
+	cmpl	%a0@(mmu_next_physical),%d1
+	jbeq	mmu_print_tuple_increment
+
+mmu_print_tuple_print:
+	putn	%d0
+	puts	"->"
+	putn	%d1
+
+	movel	%d1,%d6
+	jbsr	%a6@
+
+mmu_print_tuple_record:
+	movel	#MMU_PRINT_VALID,%a0@(mmu_next_valid)
+
+	movel	%d1,%a0@(mmu_next_physical)
+
+mmu_print_tuple_increment:
+	movel	%d5,%d7
+	subl	%a4,%d7
+	addl	%d7,%a0@(mmu_next_physical)
+
+mmu_print_tuple_exit:
+	moveml	%sp@+,%d0-%d7/%a0
+	rts
+
+mmu_print_machine_cpu_types:
+	puts	"machine: "
+
+	is_not_amiga(1f)
+	puts	"amiga"
+	jbra	9f
+1:
+	is_not_atari(2f)
+	puts	"atari"
+	jbra	9f
+2:
+	is_not_mac(3f)
+	puts	"macintosh"
+	jbra	9f
+3:	puts	"unknown"
+9:	putc	'\n'
+
+	puts	"cputype: 0"
+	is_not_060(1f)
+	putc	'6'
+	jbra	9f
+1:
+	is_not_040_or_060(2f)
+	putc	'4'
+	jbra	9f
+2:	putc	'3'
+9:	putc	'0'
+	putc	'\n'
+
+	rts
+#endif /* MMU_PRINT */
+
+/*
+ * mmu_map_tt
+ *
+ * This is a specific function which works on all 680x0 machines.
+ * On 030, 040 & 060 it will attempt to use Transparent Translation
+ * registers (tt1).
+ * On 020 it will call the standard mmu_map which will use early
+ * terminating descriptors.
+ */
+func_start	mmu_map_tt,%d0/%d1/%a0,4
+
+	dputs	"mmu_map_tt:"
+	dputn	ARG1
+	dputn	ARG2
+	dputn	ARG3
+	dputn	ARG4
+	dputc	'\n'
+
+	is_020(L(do_map))
+
+	/* Extract the highest bit set
+	 */
+	bfffo	ARG3{#0,#32},%d1
+	cmpw	#8,%d0
+	jcc	L(do_map)
+
+	/* And get the mask
+	 */
+	moveq	#-1,%d0
+	lsrl	%d1,%d0
+	lsrl	#1,%d0
+
+	/* Mask the address
+	 */
+	movel	%d0,%d1
+	notl	%d1
+	andl	ARG2,%d1
+
+	/* Generate the upper 16bit of the tt register
+	 */
+	lsrl	#8,%d0
+	orl	%d0,%d1
+	clrw	%d1
+
+	is_040_or_060(L(mmu_map_tt_040))
+
+	/* set 030 specific bits (read/write access for supervisor mode
+	 * (highest function code set, lower two bits masked))
+	 */
+	orw	#TTR_ENABLE+TTR_RWM+TTR_FCB2+TTR_FCM1+TTR_FCM0,%d1
+	movel	ARG4,%d0
+	btst	#6,%d0
+	jeq	1f
+	orw	#TTR_CI,%d1
+
+1:	lea	STACK,%a0
+	dputn	%d1
+	movel	%d1,%a0@
+	.chip	68030
+	tstl	ARG1
+	jne	1f
+	pmove	%a0@,%tt0
+	jra	2f
+1:	pmove	%a0@,%tt1
+2:	.chip	68k
+	jra	L(mmu_map_tt_done)
+
+	/* set 040 specific bits
+	 */
+L(mmu_map_tt_040):
+	orw	#TTR_ENABLE+TTR_KERNELMODE,%d1
+	orl	ARG4,%d1
+	dputn	%d1
+
+	.chip	68040
+	tstl	ARG1
+	jne	1f
+	movec	%d1,%itt0
+	movec	%d1,%dtt0
+	jra	2f
+1:	movec	%d1,%itt1
+	movec	%d1,%dtt1
+2:	.chip	68k
+
+	jra	L(mmu_map_tt_done)
+
+L(do_map):
+	mmu_map_eq	ARG2,ARG3,ARG4
+
+L(mmu_map_tt_done):
+
+func_return	mmu_map_tt
+
+/*
+ *	mmu_map
+ *
+ *	This routine will map a range of memory using a pointer
+ *	table and allocating the pages on the fly from the kernel.
+ *	The pointer table does not have to be already linked into
+ *	the root table, this routine will do that if necessary.
+ *
+ *	NOTE
+ *	This routine will assert failure and use the serial_putc
+ *	routines in the case of a run-time error.  For example,
+ *	if the address is already mapped.
+ *
+ *	NOTE-2
+ *	This routine will use early terminating descriptors
+ *	where possible for the 68020+68851 and 68030 type
+ *	processors.
+ */
+func_start	mmu_map,%d0-%d4/%a0-%a4
+
+	dputs	"\nmmu_map:"
+	dputn	ARG1
+	dputn	ARG2
+	dputn	ARG3
+	dputn	ARG4
+	dputc	'\n'
+
+	/* Get logical address and round it down to 256KB
+	 */
+	movel	ARG1,%d0
+	andl	#-(PAGESIZE*PAGE_TABLE_SIZE),%d0
+	movel	%d0,%a3
+
+	/* Get the end address
+	 */
+	movel	ARG1,%a4
+	addl	ARG3,%a4
+	subql	#1,%a4
+
+	/* Get physical address and round it down to 256KB
+	 */
+	movel	ARG2,%d0
+	andl	#-(PAGESIZE*PAGE_TABLE_SIZE),%d0
+	movel	%d0,%a2
+
+	/* Add page attributes to the physical address
+	 */
+	movel	ARG4,%d0
+	orw	#_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0
+	addw	%d0,%a2
+
+	dputn	%a2
+	dputn	%a3
+	dputn	%a4
+
+	is_not_040_or_060(L(mmu_map_030))
+
+	addw	#_PAGE_GLOBAL040,%a2
+/*
+ *	MMU 040 & 060 Support
+ *
+ *	The MMU usage for the 040 and 060 is different enough from
+ *	the 030 and 68851 that there is separate code.  This comment
+ *	block describes the data structures and algorithms built by
+ *	this code.
+ *
+ *	The 040 does not support early terminating descriptors, as
+ *	the 030 does.  Therefore, a third level of table is needed
+ *	for the 040, and that would be the page table.  In Linux,
+ *	page tables are allocated directly from the memory above the
+ *	kernel.
+ *
+ */
+
+L(mmu_map_040):
+	/* Calculate the offset into the root table
+	 */
+	movel	%a3,%d0
+	moveq	#ROOT_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	mmu_get_root_table_entry	%d0
+
+	/* Calculate the offset into the pointer table
+	 */
+	movel	%a3,%d0
+	moveq	#PTR_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PTR_TABLE_SIZE-1,%d0
+	mmu_get_ptr_table_entry		%a0,%d0
+
+	/* Calculate the offset into the page table
+	 */
+	movel	%a3,%d0
+	moveq	#PAGE_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PAGE_TABLE_SIZE-1,%d0
+	mmu_get_page_table_entry	%a0,%d0
+
+	/* The page table entry must not no be busy
+	 */
+	tstl	%a0@
+	jne	L(mmu_map_error)
+
+	/* Do the mapping and advance the pointers
+	 */
+	movel	%a2,%a0@
+2:
+	addw	#PAGESIZE,%a2
+	addw	#PAGESIZE,%a3
+
+	/* Ready with mapping?
+	 */
+	lea	%a3@(-1),%a0
+	cmpl	%a0,%a4
+	jhi	L(mmu_map_040)
+	jra	L(mmu_map_done)
+
+L(mmu_map_030):
+	/* Calculate the offset into the root table
+	 */
+	movel	%a3,%d0
+	moveq	#ROOT_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	mmu_get_root_table_entry	%d0
+
+	/* Check if logical address 32MB aligned,
+	 * so we can try to map it once
+	 */
+	movel	%a3,%d0
+	andl	#(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1)&(-ROOT_TABLE_SIZE),%d0
+	jne	1f
+
+	/* Is there enough to map for 32MB at once
+	 */
+	lea	%a3@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE-1),%a1
+	cmpl	%a1,%a4
+	jcs	1f
+
+	addql	#1,%a1
+
+	/* The root table entry must not no be busy
+	 */
+	tstl	%a0@
+	jne	L(mmu_map_error)
+
+	/* Do the mapping and advance the pointers
+	 */
+	dputs	"early term1"
+	dputn	%a2
+	dputn	%a3
+	dputn	%a1
+	dputc	'\n'
+	movel	%a2,%a0@
+
+	movel	%a1,%a3
+	lea	%a2@(PTR_TABLE_SIZE*PAGE_TABLE_SIZE*PAGESIZE),%a2
+	jra	L(mmu_mapnext_030)
+1:
+	/* Calculate the offset into the pointer table
+	 */
+	movel	%a3,%d0
+	moveq	#PTR_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PTR_TABLE_SIZE-1,%d0
+	mmu_get_ptr_table_entry		%a0,%d0
+
+	/* The pointer table entry must not no be busy
+	 */
+	tstl	%a0@
+	jne	L(mmu_map_error)
+
+	/* Do the mapping and advance the pointers
+	 */
+	dputs	"early term2"
+	dputn	%a2
+	dputn	%a3
+	dputc	'\n'
+	movel	%a2,%a0@
+
+	addl	#PAGE_TABLE_SIZE*PAGESIZE,%a2
+	addl	#PAGE_TABLE_SIZE*PAGESIZE,%a3
+
+L(mmu_mapnext_030):
+	/* Ready with mapping?
+	 */
+	lea	%a3@(-1),%a0
+	cmpl	%a0,%a4
+	jhi	L(mmu_map_030)
+	jra	L(mmu_map_done)
+
+L(mmu_map_error):
+
+	dputs	"mmu_map error:"
+	dputn	%a2
+	dputn	%a3
+	dputc	'\n'
+
+L(mmu_map_done):
+
+func_return	mmu_map
+
+/*
+ *	mmu_fixup
+ *
+ *	On the 040 class machines, all pages that are used for the
+ *	mmu have to be fixed up.
+ */
+
+func_start	mmu_fixup_page_mmu_cache,%d0/%a0
+
+	dputs	"mmu_fixup_page_mmu_cache"
+	dputn	ARG1
+
+	/* Calculate the offset into the root table
+	 */
+	movel	ARG1,%d0
+	moveq	#ROOT_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	mmu_get_root_table_entry	%d0
+
+	/* Calculate the offset into the pointer table
+	 */
+	movel	ARG1,%d0
+	moveq	#PTR_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PTR_TABLE_SIZE-1,%d0
+	mmu_get_ptr_table_entry		%a0,%d0
+
+	/* Calculate the offset into the page table
+	 */
+	movel	ARG1,%d0
+	moveq	#PAGE_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PAGE_TABLE_SIZE-1,%d0
+	mmu_get_page_table_entry	%a0,%d0
+
+	movel	%a0@,%d0
+	andil	#_CACHEMASK040,%d0
+	orl	%pc@(SYMBOL_NAME(m68k_pgtable_cachemode)),%d0
+	movel	%d0,%a0@
+
+	dputc	'\n'
+
+func_return	mmu_fixup_page_mmu_cache
+
+/*
+ *	mmu_temp_map
+ *
+ *	create a temporary mapping to enable the mmu,
+ *	this we don't need any transparation translation tricks.
+ */
+
+func_start	mmu_temp_map,%d0/%d1/%a0/%a1
+
+	dputs	"mmu_temp_map"
+	dputn	ARG1
+	dputn	ARG2
+	dputc	'\n'
+
+	lea	%pc@(L(temp_mmap_mem)),%a1
+
+	/* Calculate the offset in the root table
+	 */
+	movel	ARG2,%d0
+	moveq	#ROOT_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	mmu_get_root_table_entry	%d0
+
+	/* Check if the table is temporary allocated, so we have to reuse it
+	 */
+	movel	%a0@,%d0
+	cmpl	%pc@(L(memory_start)),%d0
+	jcc	1f
+
+	/* Temporary allocate a ptr table and insert it into the root table
+	 */
+	movel	%a1@,%d0
+	addl	#PTR_TABLE_SIZE*4,%a1@
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d0
+	movel	%d0,%a0@
+	dputs	" (new)"
+1:
+	dputn	%d0
+	/* Mask the root table entry for the ptr table
+	 */
+	andw	#-ROOT_TABLE_SIZE,%d0
+	movel	%d0,%a0
+
+	/* Calculate the offset into the pointer table
+	 */
+	movel	ARG2,%d0
+	moveq	#PTR_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PTR_TABLE_SIZE-1,%d0
+	lea	%a0@(%d0*4),%a0
+	dputn	%a0
+
+	/* Check if a temporary page table is already allocated
+	 */
+	movel	%a0@,%d0
+	jne	1f
+
+	/* Temporary allocate a page table and insert it into the ptr table
+	 */
+	movel	%a1@,%d0
+	addl	#PTR_TABLE_SIZE*4,%a1@
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d0
+	movel	%d0,%a0@
+	dputs	" (new)"
+1:
+	dputn	%d0
+	/* Mask the ptr table entry for the page table
+	 */
+	andw	#-PTR_TABLE_SIZE,%d0
+	movel	%d0,%a0
+
+	/* Calculate the offset into the page table
+	 */
+	movel	ARG2,%d0
+	moveq	#PAGE_INDEX_SHIFT,%d1
+	lsrl	%d1,%d0
+	andl	#PAGE_TABLE_SIZE-1,%d0
+	lea	%a0@(%d0*4),%a0
+	dputn	%a0
+
+	/* Insert the address into the page table
+	 */
+	movel	ARG1,%d0
+	andw	#-PAGESIZE,%d0
+	orw	#_PAGE_PRESENT+_PAGE_ACCESSED+_PAGE_DIRTY,%d0
+	movel	%d0,%a0@
+	dputn	%d0
+
+	dputc	'\n'
+
+func_return	mmu_temp_map
+
+func_start	mmu_engage,%d0-%d2/%a0-%a3
+
+	moveq	#ROOT_TABLE_SIZE-1,%d0
+	/* Temporarily use a different root table.  */
+	lea	%pc@(L(kernel_pgdir_ptr)),%a0
+	movel	%a0@,%a2
+	movel	%pc@(L(memory_start)),%a1
+	movel	%a1,%a0@
+	movel	%a2,%a0
+1:
+	movel	%a0@+,%a1@+
+	dbra	%d0,1b
+
+	lea	%pc@(L(temp_mmap_mem)),%a0
+	movel	%a1,%a0@
+
+	movew	#PAGESIZE-1,%d0
+1:
+	clrl	%a1@+
+	dbra	%d0,1b
+
+	lea	%pc@(1b),%a0
+	movel	#1b,%a1
+	/* Skip temp mappings if phys == virt */
+	cmpl	%a0,%a1
+	jeq	1f
+
+	mmu_temp_map	%a0,%a0
+	mmu_temp_map	%a0,%a1
+
+	addw	#PAGESIZE,%a0
+	addw	#PAGESIZE,%a1
+	mmu_temp_map	%a0,%a0
+	mmu_temp_map	%a0,%a1
+1:
+	movel	%pc@(L(memory_start)),%a3
+	movel	%pc@(L(phys_kernel_start)),%d2
+
+	is_not_040_or_060(L(mmu_engage_030))
+
+L(mmu_engage_040):
+	.chip	68040
+	nop
+	cinva	%bc
+	nop
+	pflusha
+	nop
+	movec	%a3,%srp
+	movel	#TC_ENABLE+TC_PAGE4K,%d0
+	movec	%d0,%tc		/* enable the MMU */
+	jmp	1f:l
+1:	nop
+	movec	%a2,%srp
+	nop
+	cinva	%bc
+	nop
+	pflusha
+	.chip	68k
+	jra	L(mmu_engage_cleanup)
+
+L(mmu_engage_030_temp):
+	.space	12
+L(mmu_engage_030):
+	.chip	68030
+	lea	%pc@(L(mmu_engage_030_temp)),%a0
+	movel	#0x80000002,%a0@
+	movel	%a3,%a0@(4)
+	movel	#0x0808,%d0
+	movec	%d0,%cacr
+	pmove	%a0@,%srp
+	pflusha
+	/*
+	 * enable,super root enable,4096 byte pages,7 bit root index,
+	 * 7 bit pointer index, 6 bit page table index.
+	 */
+	movel	#0x82c07760,%a0@(8)
+	pmove	%a0@(8),%tc	/* enable the MMU */
+	jmp	1f:l
+1:	movel	%a2,%a0@(4)
+	movel	#0x0808,%d0
+	movec	%d0,%cacr
+	pmove	%a0@,%srp
+	pflusha
+	.chip	68k
+
+L(mmu_engage_cleanup):
+	subl	%d2,%a2
+	movel	%a2,L(kernel_pgdir_ptr)
+	subl	%d2,%fp
+	subl	%d2,%sp
+	subl	%d2,ARG0
+	subl	%d2,L(memory_start)
+
+func_return	mmu_engage
+
+func_start	mmu_get_root_table_entry,%d0/%a1
+
+#if 0
+	dputs	"mmu_get_root_table_entry:"
+	dputn	ARG1
+	dputs	" ="
+#endif
+
+	movel	%pc@(L(kernel_pgdir_ptr)),%a0
+	tstl	%a0
+	jne	2f
+
+	dputs	"\nmmu_init:"
+
+	/* Find the start of free memory, get_bi_record does this for us,
+	 * as the bootinfo structure is located directly behind the kernel
+	 * and and we simply search for the last entry.
+	 */
+	get_bi_record	BI_LAST
+	addw	#PAGESIZE-1,%a0
+	movel	%a0,%d0
+	andw	#-PAGESIZE,%d0
+
+	dputn	%d0
+
+	lea	%pc@(L(memory_start)),%a0
+	movel	%d0,%a0@
+	lea	%pc@(L(kernel_end)),%a0
+	movel	%d0,%a0@
+
+	/* we have to return the first page at _stext since the init code
+	 * in mm/init.c simply expects kernel_pg_dir there, the rest of
+	 * page is used for further ptr tables in get_ptr_table.
+	 */
+	lea	%pc@(SYMBOL_NAME(_stext)),%a0
+	lea	%pc@(L(mmu_cached_pointer_tables)),%a1
+	movel	%a0,%a1@
+	addl	#ROOT_TABLE_SIZE*4,%a1@
+
+	lea	%pc@(L(mmu_num_pointer_tables)),%a1
+	addql	#1,%a1@
+
+	/* clear the page
+	 */
+	movel	%a0,%a1
+	movew	#PAGESIZE/4-1,%d0
+1:
+	clrl	%a1@+
+	dbra	%d0,1b
+
+	lea	%pc@(L(kernel_pgdir_ptr)),%a1
+	movel	%a0,%a1@
+
+	dputn	%a0
+	dputc	'\n'
+2:
+	movel	ARG1,%d0
+	lea	%a0@(%d0*4),%a0
+
+#if 0
+	dputn	%a0
+	dputc	'\n'
+#endif
+
+func_return	mmu_get_root_table_entry
+
+
+
+func_start	mmu_get_ptr_table_entry,%d0/%a1
+
+#if 0
+	dputs	"mmu_get_ptr_table_entry:"
+	dputn	ARG1
+	dputn	ARG2
+	dputs	" ="
+#endif
+
+	movel	ARG1,%a0
+	movel	%a0@,%d0
+	jne	2f
+
+	/* Keep track of the number of pointer tables we use
+	 */
+	dputs	"\nmmu_get_new_ptr_table:"
+	lea	%pc@(L(mmu_num_pointer_tables)),%a0
+	movel	%a0@,%d0
+	addql	#1,%a0@
+
+	/* See if there is a free pointer table in our cache of pointer tables
+	 */
+	lea	%pc@(L(mmu_cached_pointer_tables)),%a1
+	andw	#7,%d0
+	jne	1f
+
+	/* Get a new pointer table page from above the kernel memory
+	 */
+	get_new_page
+	movel	%a0,%a1@
+1:
+	/* There is an unused pointer table in our cache... use it
+	 */
+	movel	%a1@,%d0
+	addl	#PTR_TABLE_SIZE*4,%a1@
+
+	dputn	%d0
+	dputc	'\n'
+
+	/* Insert the new pointer table into the root table
+	 */
+	movel	ARG1,%a0
+	orw	#_PAGE_TABLE+_PAGE_ACCESSED,%d0
+	movel	%d0,%a0@
+2:
+	/* Extract the pointer table entry
+	 */
+	andw	#-PTR_TABLE_SIZE,%d0
+	movel	%d0,%a0
+	movel	ARG2,%d0
+	lea	%a0@(%d0*4),%a0
+
+#if 0
+	dputn	%a0
+	dputc	'\n'
+#endif
+
+func_return	mmu_get_ptr_table_entry
+
+
+func_start	mmu_get_page_table_entry,%d0/%a1
+
+#if 0
+	dputs	"mmu_get_page_table_entry:"
+	dputn	ARG1
+	dputn	ARG2
+	dputs	" ="
+#endif
+
+	movel	ARG1,%a0
+	movel	%a0@,%d0
+	jne	2f
+
+	/* If the page table entry doesn't exist, we allocate a complete new
+	 * page and use it as one continues big page table which can cover
+	 * 4MB of memory, nearly almost all mappings have that alignment.
+	 */
+	get_new_page
+	addw	#_PAGE_TABLE+_PAGE_ACCESSED,%a0
+
+	/* align pointer table entry for a page of page tables
+	 */
+	movel	ARG1,%d0
+	andw	#-(PAGESIZE/PAGE_TABLE_SIZE),%d0
+	movel	%d0,%a1
+
+	/* Insert the page tables into the pointer entries
+	 */
+	moveq	#PAGESIZE/PAGE_TABLE_SIZE/4-1,%d0
+1:
+	movel	%a0,%a1@+
+	lea	%a0@(PAGE_TABLE_SIZE*4),%a0
+	dbra	%d0,1b
+
+	/* Now we can get the initialized pointer table entry
+	 */
+	movel	ARG1,%a0
+	movel	%a0@,%d0
+2:
+	/* Extract the page table entry
+	 */
+	andw	#-PAGE_TABLE_SIZE,%d0
+	movel	%d0,%a0
+	movel	ARG2,%d0
+	lea	%a0@(%d0*4),%a0
+
+#if 0
+	dputn	%a0
+	dputc	'\n'
+#endif
+
+func_return	mmu_get_page_table_entry
+
+/*
+ *	get_new_page
+ *
+ *	Return a new page from the memory start and clear it.
+ */
+func_start	get_new_page,%d0/%a1
+
+	dputs	"\nget_new_page:"
+
+	/* allocate the page and adjust memory_start
+	 */
+	lea	%pc@(L(memory_start)),%a0
+	movel	%a0@,%a1
+	addl	#PAGESIZE,%a0@
+
+	/* clear the new page
+	 */
+	movel	%a1,%a0
+	movew	#PAGESIZE/4-1,%d0
+1:
+	clrl	%a1@+
+	dbra	%d0,1b
+
+	dputn	%a0
+	dputc	'\n'
+
+func_return	get_new_page
+
+
X 
X /*
X  * Debug output support
@@ -1112,11 +2499,49 @@
X  * from the MFP or a serial port of the SCC
X  */
X 
+#ifdef CONFIG_MAC
+
+L(scc_initable_mac):
+	.byte	9,12		/* Reset */
+	.byte	4,0x44		/* x16, 1 stopbit, no parity */
+	.byte	3,0xc0		/* receiver: 8 bpc */
+	.byte	5,0xe2		/* transmitter: 8 bpc, assert dtr/rts */
+	.byte	9,0		/* no interrupts */
+	.byte	10,0		/* NRZ */
+	.byte	11,0x50		/* use baud rate generator */
+	.byte	12,10,13,0	/* 9600 baud */
+	.byte	14,1		/* Baud rate generator enable */
+	.byte	3,0xc1		/* enable receiver */
+	.byte	5,0xea		/* enable transmitter */
+	.byte	-1
+	.even
+#endif
+
X #ifdef CONFIG_ATARI
X /* #define USE_PRINTER */
-/* #define USE_SCC */
+/* #define USE_SCC_B */
+/* #define USE_SCC_A */
X #define USE_MFP
X 
+#if defined(USE_SCC_A) || defined(USE_SCC_B)
+#define USE_SCC
+/* Initialisation table for SCC */
+L(scc_initable):
+	.byte	9,12		/* Reset */
+	.byte	4,0x44		/* x16, 1 stopbit, no parity */
+	.byte	3,0xc0		/* receiver: 8 bpc */
+	.byte	5,0xe2		/* transmitter: 8 bpc, assert dtr/rts */
+	.byte	9,0		/* no interrupts */
+	.byte	10,0		/* NRZ */
+	.byte	11,0x50		/* use baud rate generator */
+	.byte	12,24,13,0	/* 9600 baud */
+	.byte	14,2,14,3	/* use master clock for BRG, enable */
+	.byte	3,0xc1		/* enable receiver */
+	.byte	5,0xea		/* enable transmitter */
+	.byte	-1
+	.even
+#endif
+
X #ifdef USE_PRINTER
X 
X LPSG_SELECT	= 0xff8800
@@ -1129,13 +2554,18 @@
X LSTMFP_DDR	= 0xfffa05
X LSTMFP_IERB	= 0xfffa09
X 
-#elif defined(USE_SCC)
- 
-LSCC_CTRL_B	= 0xff8c85
-LSCC_DATA_B	= 0xff8c87
+#elif defined(USE_SCC_B)
+
+LSCC_CTRL	= 0xff8c85
+LSCC_DATA	= 0xff8c87
+
+#elif defined(USE_SCC_A)
+
+LSCC_CTRL	= 0xff8c81
+LSCC_DATA	= 0xff8c83
X 
X /* Initialisation table for SCC */
-scc_initable:
+L(scc_initable):
X 	.byte	9,12		/* Reset */
X 	.byte	4,0x44		/* x16, 1 stopbit, no parity */
X 	.byte	3,0xc0		/* receiver: 8 bpc */
@@ -1159,45 +2589,48 @@
X LMFP_UDR     = 0xfffa2f
X 
X #endif
-#endif
-
-#if defined (CONFIG_BVME6000)
-BVME_SCC_CTRL_A = 0xffb0000b
-BVME_SCC_DATA_A = 0xffb0000f
-#endif
+#endif	/* CONFIG_ATARI */
X 
X /*
X  * Serial port output support.
X  */
-LSERPER		= 0xdff032
-LSERDAT		= 0xdff030
-LSERDATR	= 0xdff018
-LSERIAL_CNTRL	= 0xbfd000
-LSERIAL_DTR	= 7
X 
X /*
X  * Initialize serial port hardware for 9600/8/1
- * a0 thrashed
- * Amiga d0 trashed
- * Atari d0 trashed (a1 in case of SCC)
X  */
-	.even
-Lserial_init:
+func_start	serial_init,%d0/%d1/%a0/%a1
+	/*
+	 *	Some of the register usage that follows
+	 *	CONFIG_AMIGA
+	 *		a0 = pointer to boot info record
+	 *		d0 = boot info offset
+	 *	CONFIG_ATARI
+	 *		a0 = address of SCC
+	 *		a1 = Liobase address/address of scc_initable
+	 *		d0 = init data for serial port
+	 *	CONFIG_MAC
+	 *		a0 = address of SCC
+	 *		a1 = address of scc_initable_mac
+	 *		d0 = init data for serial port
+	 */
+
X #ifdef CONFIG_AMIGA
-	cmpil	#MACH_AMIGA,%d4
-	jne	1f
-	bclr	#LSERIAL_DTR,LSERIAL_CNTRL
-	movew	#BI_AMIGA_SERPER,%d0
-	jbsr	Lget_bi_record
-	movew	%a0@,LSERPER
-	jra	9f
+#define SERIAL_DTR	7
+#define SERIAL_CNTRL	CIABBASE+C_PRA
+
+	is_not_amiga(1f)
+	lea	%pc@(L(custom)),%a0
+	movel	#-ZTWOBASE,%a0@
+	bclr	#SERIAL_DTR,SERIAL_CNTRL-ZTWOBASE
+	get_bi_record	BI_AMIGA_SERPER
+	movew	%a0@,CUSTOMBASE+C_SERPER-ZTWOBASE
+|	movew	#61,CUSTOMBASE+C_SERPER-ZTWOBASE
X 1:
X #endif
X #ifdef CONFIG_ATARI
-	cmpil   #MACH_ATARI,%d4
-	jne	4f
-	movel	%pc@(Liobase),%a1
-#ifdef USE_PRINTER
+	is_not_atari(4f)
+	movel	%pc@(L(iobase)),%a1
+#if defined(USE_PRINTER)
X 	bclr	#0,%a1@(LSTMFP_IERB)
X 	bclr	#0,%a1@(LSTMFP_DDR)
X 	moveb	#LPSG_CONTROL,%a1@(LPSG_SELECT)
@@ -1209,8 +2642,8 @@
X 	bset	#5,%d0
X 	moveb	%d0,%a1@(LPSG_WRITE)
X #elif defined(USE_SCC)
-	lea	%a1@(LSCC_CTRL_B),%a0
-	lea	%pc@(scc_initable:w),%a1
+	lea	%a1@(LSCC_CTRL),%a0
+	lea	%pc@(L(scc_initable)),%a1
X 2:	moveb	%a1@+,%d0
X 	jmi	3f
X 	moveb	%d0,%a0@
@@ -1225,174 +2658,854 @@
X 	orb	#1,%a1@(LMFP_TDCDR)
X 	bset	#1,%a1@(LMFP_TSR)
X #endif
+	jra	L(serial_init_done)
X 4:
X #endif
-9:
-	rts
+#ifdef CONFIG_MAC
+	is_not_mac(L(serial_init_not_mac))
+#ifdef MAC_SERIAL_DEBUG
+#if !defined(MAC_USE_SCC_A) && !defined(MAC_USE_SCC_B)
+#define MAC_USE_SCC_B
+#endif
+#define mac_scc_cha_b_ctrl_offset	0x0
+#define mac_scc_cha_a_ctrl_offset	0x2
+#define mac_scc_cha_b_data_offset	0x4
+#define mac_scc_cha_a_data_offset	0x6
+
+#ifdef MAC_USE_SCC_A
+	/* Initialize channel A */
+	movel	%pc@(L(mac_sccbase)),%a0
+	lea	%pc@(L(scc_initable_mac)),%a1
+5:	moveb	%a1@+,%d0
+	jmi	6f
+	moveb	%d0,%a0@(mac_scc_cha_a_ctrl_offset)
+	moveb	%a1@+,%a0@(mac_scc_cha_a_ctrl_offset)
+	jra	5b
+6:
+#endif	/* MAC_USE_SCC_A */
+
+#ifdef MAC_USE_SCC_B
+	/* Initialize channel B */
+#ifndef MAC_USE_SCC_A	/* Load mac_sccbase only if needed */
+	movel	%pc@(L(mac_sccbase)),%a0
+#endif	/* MAC_USE_SCC_A */
+	lea	%pc@(L(scc_initable_mac)),%a1
+7:	moveb	%a1@+,%d0
+	jmi	8f
+	moveb	%d0,%a0@(mac_scc_cha_b_ctrl_offset)
+	moveb	%a1@+,%a0@(mac_scc_cha_b_ctrl_offset)
+	jra	7b
+8:
+#endif	/* MAC_USE_SCC_B */
+#endif	/* MAC_SERIAL_DEBUG */
+
+	jra	L(serial_init_done)
+L(serial_init_not_mac):
+#endif	/* CONFIG_MAC */
+
+L(serial_init_done):
+func_return	serial_init
X 
-#ifdef CONFIG_HP300
-/* Set LEDs to %d7 */
-	.even
-Lset_leds:
-	moveml	%a0/%a1,%sp@-
-	movel	%pc@(Lcustom),%a1
-	moveb	%d7,%a1@(0x1ffff)
-	moveml	%sp@+,%a0/%a1
-	rts
-#endif
-	
X /*
- * Output character in d7 on serial port.
- * d7 thrashed.
+ * Output character on serial port.
X  */
-Lserial_putc:
-	moveml	%a0/%a1,%sp@-
-#if defined(CONFIG_MVME16x)
-	cmpil	#MACH_MVME16x,%d4
-	jne	2f
-	moveb	%d7,%sp@-
-	.long	0x4e4f0020
-	jra	9f
-2:
-#endif
-#ifdef CONFIG_BVME6000
-	cmpil	#MACH_BVME6000,%d4
-	jne	2f
-1:	btst	#2,BVME_SCC_CTRL_A
-	jeq	1b
-	moveb	%d7,BVME_SCC_DATA_A
-	jra	9f
-2:
-#endif
+func_start	serial_putc,%d0/%d1/%a0/%a1
+
+	movel	ARG1,%d0
+	cmpib	#'\n',%d0
+	jbne	1f
+
+	/* A little safe recursion is good for the soul */
+	serial_putc	#'\r'
+1:
+
X #ifdef CONFIG_AMIGA
-	cmpil	#MACH_AMIGA,%d4
-	jne	2f
-	andw	#0x00ff,%d7
-	oriw	#0x0100,%d7
-	movel	%pc@(Lcustom),%a1
-	movew	%d7,%a1@(LSERDAT)
-1:	movew	%a1@(LSERDATR),%d7
-	andw	#0x2000,%d7
+	is_not_amiga(2f)
+	andw	#0x00ff,%d0
+	oriw	#0x0100,%d0
+	movel	%pc@(L(custom)),%a0
+	movew	%d0,%a0@(CUSTOMBASE+C_SERDAT)
+1:	movew	%a0@(CUSTOMBASE+C_SERDATR),%d0
+	andw	#0x2000,%d0
X 	jeq	1b
-	jra	9f
+	jra	L(serial_putc_done)
X 2:
X #endif
+
+#ifdef CONFIG_MAC
+	is_not_mac(5f)
+
+#ifdef CONSOLE
+	console_putc	%d0
+#endif /* CONSOLE */
+
+#ifdef MAC_SERIAL_DEBUG
+
+#ifdef MAC_USE_SCC_A
+	movel	%pc@(L(mac_sccbase)),%a1
+3:	btst	#2,%a1@(mac_scc_cha_a_ctrl_offset)
+	jeq	3b
+	moveb	%d0,%a1@(mac_scc_cha_a_data_offset)
+#endif	/* MAC_USE_SCC_A */
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 03'
echo 'File patch-2.2.0-pre9 is continued in part 04'
echo 04 > _shar_seq_.tmp
#!/bin/sh
# this is part 04 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 04; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
+
+#ifdef MAC_USE_SCC_B
+#ifndef MAC_USE_SCC_A	/* Load mac_sccbase only if needed */
+	movel	%pc@(L(mac_sccbase)),%a1
+#endif	/* MAC_USE_SCC_A */
+4:	btst	#2,%a1@(mac_scc_cha_b_ctrl_offset)
+	jeq	4b
+	moveb	%d0,%a1@(mac_scc_cha_b_data_offset)
+#endif	/* MAC_USE_SCC_B */
+
+#endif	/* MAC_SERIAL_DEBUG */
+
+	jra	L(serial_putc_done)
+5:
+#endif	/* CONFIG_MAC */
+
X #ifdef CONFIG_ATARI
-	cmpil   #MACH_ATARI,%d4
-	jne	4f
-	movel	%pc@(Liobase),%a1
-#ifdef USE_PRINTER
+	is_not_atari(4f)
+	movel	%pc@(L(iobase)),%a1
+#if defined(USE_PRINTER)
X 3:	btst	#0,%a1@(LSTMFP_GPIP)
X 	jne	3b
X 	moveb	#LPSG_IO_B,%a1@(LPSG_SELECT)
-	moveb	%d7,%a1@(LPSG_WRITE)
+	moveb	%d0,%a1@(LPSG_WRITE)
X 	moveb	#LPSG_IO_A,%a1@(LPSG_SELECT)
-	moveb	%a1@(LPSG_READ),%d7
-	bclr	#5,%d7
-	moveb	%d7,%a1@(LPSG_WRITE)
+	moveb	%a1@(LPSG_READ),%d0
+	bclr	#5,%d0
+	moveb	%d0,%a1@(LPSG_WRITE)
X 	nop
X 	nop
-	bset	#5,%d7
-	moveb	%d7,%a1@(LPSG_WRITE)
+	bset	#5,%d0
+	moveb	%d0,%a1@(LPSG_WRITE)
X #elif defined(USE_SCC)
-3:	btst	#2,%a1@(LSCC_CTRL_B)
+3:	btst	#2,%a1@(LSCC_CTRL)
X 	jeq	3b
-	moveb	%d7,%a1@(LSCC_DATA_B)
+	moveb	%d0,%a1@(LSCC_DATA)
X #elif defined(USE_MFP)
X 3:	btst	#7,%a1@(LMFP_TSR)
X 	jeq	3b
-	moveb	%d7,%a1@(LMFP_UDR)
+	moveb	%d0,%a1@(LMFP_UDR)
X #endif
+	jra	L(serial_putc_done)
X 4:
+#endif	/* CONFIG_ATARI */
+
+#ifdef CONFIG_MVME16x
+	is_not_mvme16x(2f)
+	/*
+	 * The VME 16x class has PROM support for serial output
+	 * of some kind;  the TRAP table is still valid.
+	 */
+	moveml	%d0-%d7/%a2-%a6,%sp@-
+	moveb	%d0,%sp@-
+	trap	#15
+	.word	0x0020	/* TRAP 0x020 */
+	moveml	%sp@+,%d0-%d7/%a2-%a6
+	jbra	L(serial_putc_done)
+2:
+#endif CONFIG_MVME162 | CONFIG_MVME167
+
+#ifdef CONFIG_BVME6000
+	is_not_bvme6000(2f)
+	/*
+	 * The BVME6000 machine has a serial port ...
+	 */
+1:	btst	#2,BVME_SCC_CTRL_A
+	jeq	1b
+	moveb	%d0,BVME_SCC_DATA_A
+	jbra	L(serial_putc_done)
+2:
X #endif
-9:
-	moveml	%sp@+,%a0/%a1
-	rts
+
+L(serial_putc_done):
+func_return	serial_putc
X 
X /*
- * Output string pointed to by a0 to serial port.
- * a0 trashed.
+ * Output a string.
X  */
-Lserial_puts:
-	movel	%d7,%sp@-
-1:	moveb	%a0@+,%d7
-	jeq	2f
-	jbsr	Lserial_putc
-	jra	1b
-2:	movel	%sp@+,%d7
-	rts
+func_start	puts,%d0/%a0
+
+	movel	ARG1,%a0
+	jra	2f
+1:
+#ifdef CONSOLE
+	console_putc	%d0
+#endif 
+#ifdef SERIAL_DEBUG
+	serial_putc	%d0
+#endif
+2:	moveb	%a0@+,%d0
+	jne	1b
+
+func_return	puts
X 
X /*
- * Output number in d7 in hex notation on serial port.
+ * Output number in hex notation.
X  */
X 
-Lserial_putnum:
-	moveml	%d0-%d2/%d7,%sp@-
-	movel	%d7,%d1
-	moveq	#4,%d0
-	moveq	#7,%d2
-L1:	roll	%d0,%d1
-	moveb	%d1,%d7
-	andb	#0x0f,%d7
-	cmpb	#0x0a,%d7
-	jcc	1f
-	addb	#'0',%d7
+func_start	putn,%d0-%d2
+
+	putc	' '
+
+	movel	ARG1,%d0
+	moveq	#7,%d1
+1:	roll	#4,%d0
+	move	%d0,%d2
+	andb	#0x0f,%d2
+	addb	#'0',%d2
+	cmpb	#'9',%d2
+	jls	2f
+	addb	#'A'-('9'+1),%d2
+2:
+#ifdef CONSOLE
+	console_putc	%d2
+#endif 
+#ifdef SERIAL_DEBUG
+	serial_putc	%d2
+#endif
+	dbra	%d1,1b
+
+func_return	putn
+
+#ifdef CONFIG_MAC
+/*
+ *	mac_serial_print
+ *
+ *	This routine takes its parameters on the stack.  It then
+ *	turns around and calls the internal routine.  This routine
+ *	is used until the Linux console driver initializes itself.
+ *
+ *	The calling parameters are:
+ *		void mac_serial_print(const char *str);
+ *
+ *	This routine does NOT understand variable arguments only
+ *	simple strings!
+ */
+ENTRY(mac_serial_print)
+	moveml	%d0/%a0,%sp@-
+#if 1
+	move	%sr,%sp@-
+	ori	#0x0700,%sr
+#endif
+	movel	%sp@(10),%a0		/* fetch parameter */
X 	jra	2f
-1:	addb	#'A'-10,%d7
-2:	jbsr	Lserial_putc
-	dbra	%d2,L1
-	moveq	#32,%d7
-	jbsr	Lserial_putc
-	moveml	%sp@+,%d0-%d2/%d7
+1:	serial_putc	%d0
+2:	moveb	%a0@+,%d0
+	jne	1b
+#if 1
+	move	%sp@+,%sr
+#endif
+	moveml	%sp@+,%d0/%a0
+	rts
+#endif /* CONFIG_MAC */
+
+#ifdef CONFIG_HP300
+func_start	set_leds,%d0/%a0
+	movel	ARG1,%d0
+	movel	%pc@(Lcustom),%a0
+	moveb	%d0,%a0@(0x1ffff)
+func_return	set_leds
+#endif
+
+#ifdef CONSOLE
+/*
+ *	For continuity, see the data alignment
+ *	to which this structure is tied.
+ */
+#define Lconsole_struct_cur_column	0
+#define Lconsole_struct_cur_row		4
+#define Lconsole_struct_num_columns	8
+#define Lconsole_struct_num_rows	12
+#define Lconsole_struct_left_edge	16
+#define Lconsole_struct_penguin_putc	20
+
+L(console_init):
+	/*
+	 *	Some of the register usage that follows
+	 *		a0 = pointer to boot_info
+	 *		a1 = pointer to screen
+	 *		a2 = pointer to Lconsole_globals
+	 *		d3 = pixel width of screen
+	 *		d4 = pixel height of screen
+	 *		(d3,d4) ~= (x,y) of a point just below
+	 *			and to the right of the screen
+	 *			NOT on the screen!
+	 *		d5 = number of bytes per scan line
+	 *		d6 = number of bytes on the entire screen
+	 */
+	moveml	%a0-%a4/%d0-%d7,%sp@-
+
+	lea	%pc@(L(console_globals)),%a2
+	lea	%pc@(L(mac_videobase)),%a0
+	movel	%a0@,%a1
+	lea	%pc@(L(mac_rowbytes)),%a0
+	movel	%a0@,%d5
+	lea	%pc@(L(mac_dimensions)),%a0
+	movel	%a0@,%d3	/* -> low byte */
+	movel	%d3,%d4
+	swap	%d4		/* -> high byte */
+	andl	#0xffff,%d3	/* d3 = screen width in pixels */
+	andl	#0xffff,%d4	/* d4 = screen height in pixels */
+
+	movel	%d5,%d6
+	subl	#20,%d6
+	mulul	%d4,%d6		/* scan line bytes x num scan lines */
+	divul	#8,%d6		/* we'll clear 8 bytes at a time */
+	subq	#1,%d6
+
+console_clear_loop:
+	movel	#0xffffffff,%a1@+	/* Mac_black */
+	movel	#0xffffffff,%a1@+	/* Mac_black */
+	dbra	%d6,console_clear_loop
+
+	/* Calculate font size */
+
+#if   defined(FONT_8x8)
+	lea	%pc@(SYMBOL_NAME(font_vga_8x8)), %a0
+#elif defined(FONT_8x16)
+	lea	%pc@(SYMBOL_NAME(font_vga_8x16)),%a0
+#elif defined(FONT_6x11)
+	lea	%pc@(SYMBOL_NAME(font_vga_6x11)),%a0
+#else	/*   (FONT_8x8) default */
+	lea	%pc@(SYMBOL_NAME(font_vga_8x8)), %a0
+#endif
+
+	/*
+	 *	At this point we make a shift in register usage
+	 *	a1 = address of Lconsole_font pointer
+	 */
+	lea	%pc@(L(console_font)),%a1
+	movel	%a0,%a1@	/* store pointer to struct fbcon_font_desc in Lconsole_font */
+
+	/*
+	 *	Calculate global maxs
+	 *	Note - we can use either an
+	 *	8 x 16 or 8 x 8 character font
+	 *	6 x 11 also supported
+	 */
+		/* ASSERT: a0 = contents of Lconsole_font */
+	movel	%d3,%d0			/* screen width in pixels */
+	divul	%a0@(FBCON_FONT_DESC_WIDTH),%d0		/* d0 = max num chars per row */
+
+	movel	%d4,%d1			 /* screen height in pixels */
+	divul	%a0@(FBCON_FONT_DESC_HEIGHT),%d1	 /* d1 = max num rows */
+
+	movel	%d0,%a2@(Lconsole_struct_num_columns)
+	movel	%d1,%a2@(Lconsole_struct_num_rows)
+
+	/*
+	 *	Clear the current row and column
+	 */
+	clrl	%a2@(Lconsole_struct_cur_column)
+	clrl	%a2@(Lconsole_struct_cur_row)
+	clrl	%a2@(Lconsole_struct_left_edge)
+
+	/*
+	 * Initialization is complete
+	 */
+	moveml	%sp@+,%a0-%a4/%d0-%d7
+	rts
+
+L(console_put_stats):
+	/*
+	 *	Some of the register usage that follows
+	 *		a0 = pointer to boot_info
+	 *		d7 = value of boot_info fields
+	 */
+	moveml	%a0/%d7,%sp@-
+
+	puts	"\nMacLinux\n\n"
+
+#ifdef SERIAL_DEBUG
+	puts	" vidaddr:"
+	putn	%pc@(L(mac_videobase))		/* video addr. */
+
+	puts	"\n  _stext:"
+	lea	%pc@(SYMBOL_NAME(_stext)),%a0
+	putn	%a0
+
+	puts	"\nbootinfo:"
+	lea	%pc@(SYMBOL_NAME(_end)),%a0
+	putn	%a0
+
+	puts	"\ncpuid:"
+	putn	%pc@(L(cputype))
+	putc	'\n'
+
+#  if defined(MMU_PRINT)
+	jbsr	mmu_print_machine_cpu_types
+#  endif /* MMU_PRINT */
+#endif /* SERIAL_DEBUG */
+
+	moveml	%sp@+,%a0/%d7
+	rts
+
+#ifdef CONSOLE_PENGUIN
+L(console_put_penguin):
+	/*
+	 *	Get 'that_penguin' onto the screen in the upper right corner
+	 *	penguin is 64 x 74 pixels, align against right edge of screen
+	 */
+	moveml	%a0-%a1/%d0-%d7,%sp@-
+
+	lea	%pc@(L(mac_dimensions)),%a0
+	movel	%a0@,%d0
+	andil	#0xffff,%d0
+	subil	#64,%d0		/* snug up against the right edge */
+	clrl	%d1		/* start at the top */
+	movel	#73,%d7
+	lea	%pc@(SYMBOL_NAME(that_penguin)),%a1
+console_penguin_row:
+	movel	#31,%d6
+console_penguin_pixel_pair:
+	moveb	%a1@,%d2
+	lsrb	#4,%d2
+	jbsr	console_plot_pixel
+	addq	#1,%d0
+	moveb	%a1@+,%d2
+	jbsr	console_plot_pixel
+	addq	#1,%d0
+	dbra	%d6,console_penguin_pixel_pair
+
+	subil	#64,%d0
+	addq	#1,%d1
+	dbra	%d7,console_penguin_row
+
+	moveml	%sp@+,%a0-%a1/%d0-%d7
+	rts
+#endif
+
+console_scroll:
+	moveml	%a0-%a4/%d0-%d7,%sp@-
+
+	/*
+	 * Calculate source and destination addresses
+	 *	output	a1 = dest
+	 *		a2 = source
+	 */
+	lea	%pc@(L(mac_videobase)),%a0
+	movel	%a0@,%a1
+	movel	%a1,%a2
+	lea	%pc@(L(mac_rowbytes)),%a0
+	movel	%a0@,%d5
+	movel	%pc@(L(console_font)),%a0
+	mulul	%a0@(FBCON_FONT_DESC_HEIGHT),%d5	/* account for # scan lines per character */
+	addal	%d5,%a2
+
+	/*
+	 * Get dimensions
+	 */
+	lea	%pc@(L(mac_dimensions)),%a0
+	movel	%a0@,%d3
+	movel	%d3,%d4
+	swap	%d4
+	andl	#0xffff,%d3	/* d3 = screen width in pixels */
+	andl	#0xffff,%d4	/* d4 = screen height in pixels */
+
+	/*
+	 * Calculate number of bytes to move
+	 */
+	lea	%pc@(L(mac_rowbytes)),%a0
+	movel	%a0@,%d6
+	movel	%pc@(L(console_font)),%a0
+	subl	%a0@(FBCON_FONT_DESC_HEIGHT),%d4	/* we're not scrolling the top row! */
+	mulul	%d4,%d6		/* scan line bytes x num scan lines */
+	divul	#32,%d6		/* we'll move 8 longs at a time */
+	subq	#1,%d6
+
+console_scroll_loop:
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	movel	%a2@+,%a1@+
+	dbra	%d6,console_scroll_loop
+
+	lea	%pc@(L(mac_rowbytes)),%a0
+	movel	%a0@,%d6
+	movel	%pc@(L(console_font)),%a0
+	mulul	%a0@(FBCON_FONT_DESC_HEIGHT),%d6	/* scan line bytes x font height */
+	divul	#32,%d6			/* we'll move 8 words at a time */
+	subq	#1,%d6
+
+	moveq	#-1,%d0
+console_scroll_clear_loop:
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	movel	%d0,%a1@+
+	dbra	%d6,console_scroll_clear_loop
+
+	moveml	%sp@+,%a0-%a4/%d0-%d7
+	rts
+
+
+func_start	console_putc,%a0/%a1/%d0-%d7
+
+	is_not_mac(console_exit)
+
+	/* Output character in d7 on console.
+	 */
+	movel	ARG1,%d7
+	cmpib	#'\n',%d7
+	jbne	1f
+
+	/* A little safe recursion is good for the soul */
+	console_putc	#'\r'
+1:
+	lea	%pc@(L(console_globals)),%a0
+
+	cmpib	#10,%d7
+	jne	console_not_lf
+	movel	%a0@(Lconsole_struct_cur_row),%d0
+	addil	#1,%d0
+	movel	%d0,%a0@(Lconsole_struct_cur_row)
+	movel	%a0@(Lconsole_struct_num_rows),%d1
+	cmpl	%d1,%d0
+	jcs	1f
+	subil	#1,%d0
+	movel	%d0,%a0@(Lconsole_struct_cur_row)
+	jbsr	console_scroll
+1:
+	jra	console_exit
+
+console_not_lf:
+	cmpib	#13,%d7
+	jne	console_not_cr
+	clrl	%a0@(Lconsole_struct_cur_column)
+	jra	console_exit
+
+console_not_cr:
+	cmpib	#1,%d7
+	jne	console_not_home
+	clrl	%a0@(Lconsole_struct_cur_row)
+	clrl	%a0@(Lconsole_struct_cur_column)
+	jra	console_exit
+
+/*
+ *	At this point we know that the %d7 character is going to be
+ *	rendered on the screen.  Register usage is -
+ *		a0 = pointer to console globals
+ *		a1 = font data
+ *		d0 = cursor column
+ *		d1 = cursor row to draw the character
+ *		d7 = character number
+ */
+console_not_home:
+	movel	%a0@(Lconsole_struct_cur_column),%d0
+	addil	#1,%a0@(Lconsole_struct_cur_column)
+	movel	%a0@(Lconsole_struct_num_columns),%d1
+	cmpl	%d1,%d0
+	jcs	1f
+	putc	'\n'	/* recursion is OK! */
+1:
+	movel	%a0@(Lconsole_struct_cur_row),%d1
+
+	/*
+	 *	At this point we make a shift in register usage
+	 *	a0 = address of pointer to font data (fbcon_font_desc)
+	 */
+	movel	%pc@(L(console_font)),%a0
+	movel	%a0@(FBCON_FONT_DESC_DATA),%a1	/* Load fbcon_font_desc.data into a1 */
+	andl	#0x000000ff,%d7
+		/* ASSERT: a0 = contents of Lconsole_font */
+	mulul	%a0@(FBCON_FONT_DESC_HEIGHT),%d7	/* d7 = index into font data */
+	addl	%d7,%a1			/* a1 = points to char image */
+
+	/*
+	 *	At this point we make a shift in register usage
+	 *	d0 = pixel coordinate, x
+	 *	d1 = pixel coordinate, y
+	 *	d2 = (bit 0) 1/0 for white/black (!) pixel on screen
+	 *	d3 = font scan line data (8 pixels)
+	 *	d6 = count down for the font's pixel width (8)
+	 *	d7 = count down for the font's pixel count in height
+	 */
+		/* ASSERT: a0 = contents of Lconsole_font */
+	mulul	%a0@(FBCON_FONT_DESC_WIDTH),%d0
+	mulul	%a0@(FBCON_FONT_DESC_HEIGHT),%d1
+	movel	%a0@(FBCON_FONT_DESC_HEIGHT),%d7	/* Load fbcon_font_desc.height into d7 */
+	subq	#1,%d7
+console_read_char_scanline:
+	moveb	%a1@+,%d3
+
+		/* ASSERT: a0 = contents of Lconsole_font */
+	movel	%a0@(FBCON_FONT_DESC_WIDTH),%d6	/* Load fbcon_font_desc.width into d6 */
+	subql	#1,%d6
+
+console_do_font_scanline:
+	lslb	#1,%d3
+	scsb	%d2		/* convert 1 bit into a byte */
+	jbsr	console_plot_pixel
+	addq	#1,%d0
+	dbra	%d6,console_do_font_scanline
+
+		/* ASSERT: a0 = contents of Lconsole_font */
+	subl	%a0@(FBCON_FONT_DESC_WIDTH),%d0
+	addq	#1,%d1
+	dbra	%d7,console_read_char_scanline
+
+console_exit:
+
+func_return	console_putc
+
+console_plot_pixel:
+	/*
+	 *	Input:
+	 *		d0 = x coordinate
+	 *		d1 = y coordinate
+	 *		d2 = (bit 0) 1/0 for white/black (!)
+	 *	All registers are preserved
+	 */
+	moveml	%a0-%a1/%d0-%d4,%sp@-
+
+	lea	%pc@(L(mac_videobase)),%a0
+	movel	%a0@,%a1
+	lea	%pc@(L(mac_videodepth)),%a0
+	movel	%a0@,%d3
+	lea	%pc@(L(mac_rowbytes)),%a0
+	mulul	%a0@,%d1
+
+	/*
+	 *	Register usage:
+	 *		d0 = x coord becomes byte offset into frame buffer
+	 *		d1 = y coord
+	 *		d2 = black or white (0/1)
+	 *		d3 = video depth
+	 *		d4 = temp of x (d0) for many bit depths
+	 *		d5 = unused
+	 *		d6 = unused
+	 *		d7 = unused
+	 */
+test_1bit:
+	cmpb	#1,%d3
+	jbne	test_2bit
+	movel	%d0,%d4		/* we need the low order 3 bits! */
+	divul	#8,%d0
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#7,%d4
+	eorb	#7,%d4		/* reverse the x-coordinate w/ screen-bit # */
+	andb	#1,%d2
+	jbne	white_1
+	bsetb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+white_1:
+	bclrb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+
+test_2bit:
+	cmpb	#2,%d3
+	jbne	test_4bit
+	movel	%d0,%d4		/* we need the low order 2 bits! */
+	divul	#4,%d0
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#3,%d4
+	eorb	#3,%d4		/* reverse the x-coordinate w/ screen-bit # */
+	lsll	#1,%d4		/* ! */
+	andb	#1,%d2
+	jbne	white_2
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+white_2:
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+
+test_4bit:
+	cmpb	#4,%d3
+	jbne	test_8bit
+	movel	%d0,%d4		/* we need the low order bit! */
+	divul	#2,%d0
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#1,%d4
+	eorb	#1,%d4
+	lsll	#2,%d4		/* ! */
+	andb	#1,%d2
+	jbne	white_4
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	addq	#1,%d4
+	bsetb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+white_4:
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	addq	#1,%d4
+	bclrb	%d4,%a1@
+	jbra	console_plot_pixel_exit
+
+test_8bit:
+	cmpb	#8,%d3
+	jbne	test_16bit
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#1,%d2
+	jbne	white_8
+	moveb	#0xff,%a1@
+	jbra	console_plot_pixel_exit
+white_8:
+	clrb	%a1@
+	jbra	console_plot_pixel_exit
+
+test_16bit:
+	cmpb	#16,%d3
+	jbne	console_plot_pixel_exit
+	addal	%d0,%a1
+	addal	%d0,%a1
+	addal	%d1,%a1
+	andb	#1,%d2
+	jbne	white_16
+	clrw	%a1@
+	jbra	console_plot_pixel_exit
+white_16:
+	movew	#0x0fff,%a1@
+	jbra	console_plot_pixel_exit
+
+console_plot_pixel_exit:
+	moveml	%sp@+,%a0-%a1/%d0-%d4
X 	rts
+#endif /* CONSOLE */
X 
X #if 0
-Lshowtest:
+/*
+ * This is some old code lying around.  I don't believe
+ * it's used or important anymore.  My guess is it contributed
+ * to getting to this point, but it's done for now.
+ * It was still in the 2.1.77 head.S, so it's still here.
+ * (And still not used!)
+ */
+L(showtest):
X 	moveml	%a0/%d7,%sp@-
-	putc('A')
-	putc('=')
-	putn(%a1)
-
-	ptestr	#5,%a1@,#7,%a0
-
-	putc('D')
-	putc('A')
-	putc('=')
-	putn(%a0)
-
-	putc('D')
-	putc('=')
-	putn(%a0@)
-
-	putc('S')
-	putc('=')
-	lea	%pc@(Lmmu),%a0
-	pmove	%psr,%a0@
+	puts	"A="
+	putn	%a1
+
+	.long	0xf0119f15		| ptestr	#5,%a1@,#7,%a0
+
+	puts	"DA="
+	putn	%a0
+
+	puts	"D="
+	putn	%a0@
+
+	puts	"S="
+	lea	%pc@(L(mmu)),%a0
+	.long	0xf0106200		| pmove		%psr,%a0@
X 	clrl	%d7
X 	movew	%a0@,%d7
-	jbsr	Lserial_putnum
+	putn	%d7
X 
-	putr()
+	putc	'\n'
X 	moveml	%sp@+,%a0/%d7
X 	rts
+#endif	/* 0 */
+
+__INITDATA
+	.align	4
+
+#if defined(CONFIG_ATARI) || defined(CONFIG_AMIGA) || defined(CONFIG_HP300)
+L(custom):
+L(iobase):
+	.long 0
+#endif
+
+#ifdef CONFIG_MAC
+L(console_video_virtual):
+	.long	0
+#endif	/* CONFIG_MAC */
+
+#if defined(CONSOLE)
+L(console_globals):
+	.long	0		/* cursor column */
+	.long	0		/* cursor row */
+	.long	0		/* max num columns */
+	.long	0		/* max num rows */
+	.long	0		/* left edge */
+	.long	0		/* mac putc */
+L(console_font):
+	.long	0		/* pointer to console font (struct fbcon_font_desc) */
+#endif /* CONSOLE */
+
+#if defined(MMU_PRINT)
+L(mmu_print_data):
+	.long	0		/* valid flag */
+	.long	0		/* start logical */
+	.long	0		/* next logical */
+	.long	0		/* start physical */
+	.long	0		/* next physical */
+#endif /* MMU_PRINT */
+
+L(cputype):
+	.long	0
+L(mmu_cached_pointer_tables):
+	.long	0
+L(mmu_num_pointer_tables):
+	.long	0
+L(phys_kernel_start):
+	.long	0
+L(kernel_end):
+	.long	0
+L(memory_start):
+	.long	0
+L(kernel_pgdir_ptr):
+	.long	0
+L(temp_mmap_mem):
+	.long	0
+
+
+#if defined (CONFIG_BVME6000)
+BVME_SCC_CTRL_A	= 0xffb0000b
+BVME_SCC_DATA_A	= 0xffb0000f
+#endif
+
+#if defined(CONFIG_MAC)
+L(mac_booter_data):
+	.long	0
+L(mac_videobase):
+	.long	0
+L(mac_videodepth):
+	.long	0
+L(mac_dimensions):
+	.long	0
+L(mac_rowbytes):
+	.long	0
+#ifdef MAC_SERIAL_DEBUG
+L(mac_sccbase):
+	.long	0
+#endif /* MAC_SERIAL_DEBUG */
X #endif
+
+__FINIT
X 	.data
-	.even
-Lcustom:
-Liobase:
-	.long 0
-Lmmu:	.quad 0
-SYMBOL_NAME_LABEL(kpt)
-	.long 0
+	.align	4
+
X SYMBOL_NAME_LABEL(availmem)
-	.long 0
+	.long	0
X SYMBOL_NAME_LABEL(m68k_pgtable_cachemode)
-	.long 0
-#ifdef CONFIG_060_WRITETHROUGH
+	.long	0
X SYMBOL_NAME_LABEL(m68k_supervisor_cachemode)
-	.long 0
-#endif
+	.long	0
X #if defined(CONFIG_MVME16x)
X SYMBOL_NAME_LABEL(mvme_bdid_ptr)
-	.long 0
+	.long	0
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/m68k_defs.c linux/arch/m68k/kernel/m68k_defs.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/m68k_defs.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/m68k/kernel/m68k_defs.c	Tue Jan 19 10:58:26 1999
@@ -10,14 +10,78 @@
X 
X #include <linux/stddef.h>
X #include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <video/font.h>
X 
X #define DEFINE(sym, val) \
X 	asm volatile("\n#define " #sym " %c0" : : "i" (val))
X 
X int main(void)
X {
-	DEFINE(TS_TSS, offsetof(struct task_struct, tss));
-	DEFINE(TS_ESP0, offsetof(struct task_struct, tss.esp0));
-	DEFINE(TS_FPU, offsetof(struct task_struct, tss.fp));
+	/* offsets into the task struct */
+	DEFINE(TASK_STATE, offsetof(struct task_struct, state));
+	DEFINE(TASK_FLAGS, offsetof(struct task_struct, flags));
+	DEFINE(TASK_SIGPENDING, offsetof(struct task_struct, sigpending));
+	DEFINE(TASK_NEEDRESCHED, offsetof(struct task_struct, need_resched));
+	DEFINE(TASK_TSS, offsetof(struct task_struct, tss));
+	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+
+	/* offsets into the thread struct */
+	DEFINE(TSS_KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(TSS_USP, offsetof(struct thread_struct, usp));
+	DEFINE(TSS_SR, offsetof(struct thread_struct, sr));
+	DEFINE(TSS_FS, offsetof(struct thread_struct, fs));
+	DEFINE(TSS_CRP, offsetof(struct thread_struct, crp));
+	DEFINE(TSS_ESP0, offsetof(struct thread_struct, esp0));
+	DEFINE(TSS_FPREG, offsetof(struct thread_struct, fp));
+	DEFINE(TSS_FPCNTL, offsetof(struct thread_struct, fpcntl));
+	DEFINE(TSS_FPSTATE, offsetof(struct thread_struct, fpstate));
+
+	/* offsets into the pt_regs */
+	DEFINE(PT_D0, offsetof(struct pt_regs, d0));
+	DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+	DEFINE(PT_SR, offsetof(struct pt_regs, sr));
+
+	/* bitfields are a bit difficult */
+	DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4);
+
+	/* offsets into the irq_handler struct */
+	DEFINE(IRQ_HANDLER, offsetof(struct irq_node, handler));
+	DEFINE(IRQ_DEVID, offsetof(struct irq_node, dev_id));
+	DEFINE(IRQ_NEXT, offsetof(struct irq_node, next));
+
+	/* offsets into the kernel_stat struct */
+	DEFINE(STAT_IRQ, offsetof(struct kernel_stat, irqs));
+
+	/* offsets into the bi_record struct */
+	DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
+	DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
+	DEFINE(BIR_DATA, offsetof(struct bi_record, data));
+
+	/* offsets into fbcon_font_desc (video/font.h) */
+	DEFINE(FBCON_FONT_DESC_IDX, offsetof(struct fbcon_font_desc, idx));
+	DEFINE(FBCON_FONT_DESC_NAME, offsetof(struct fbcon_font_desc, name));
+	DEFINE(FBCON_FONT_DESC_WIDTH, offsetof(struct fbcon_font_desc, width));
+	DEFINE(FBCON_FONT_DESC_HEIGHT, offsetof(struct fbcon_font_desc, height));
+	DEFINE(FBCON_FONT_DESC_DATA, offsetof(struct fbcon_font_desc, data));
+	DEFINE(FBCON_FONT_DESC_PREF, offsetof(struct fbcon_font_desc, pref));
+
+	/* offsets into the custom struct */
+	DEFINE(CUSTOMBASE, &custom);
+	DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
+	DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
+	DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
+	DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
+	DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
+	DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
+	DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
+	DEFINE(CIAABASE, &ciaa);
+	DEFINE(CIABBASE, &ciab);
+	DEFINE(C_PRA, offsetof(struct CIA, pra));
+	DEFINE(ZTWOBASE, zTwoBase);
+
X 	return 0;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/m68k_ksyms.c linux/arch/m68k/kernel/m68k_ksyms.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/m68k_ksyms.c	Thu Jan  7 15:11:36 1999
+++ linux/arch/m68k/kernel/m68k_ksyms.c	Tue Jan 19 10:58:34 1999
@@ -13,6 +13,7 @@
X #include <asm/machdep.h>
X #include <asm/pgtable.h>
X #include <asm/irq.h>
+#include <asm/io.h>
X #include <asm/semaphore.h>
X #include <asm/checksum.h>
X #include <asm/hardirq.h>
@@ -37,21 +38,22 @@
X EXPORT_SYMBOL(mm_end_of_chunk);
X #endif
X EXPORT_SYMBOL(mm_vtop_fallback);
+EXPORT_SYMBOL(m68k_realnum_memory);
X EXPORT_SYMBOL(m68k_memory);
-EXPORT_SYMBOL(kernel_map);
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
X EXPORT_SYMBOL(m68k_debug_device);
X EXPORT_SYMBOL(dump_fpu);
X EXPORT_SYMBOL(dump_thread);
X EXPORT_SYMBOL(strnlen);
X EXPORT_SYMBOL(strrchr);
X EXPORT_SYMBOL(strstr);
-EXPORT_SYMBOL(strtok);
-EXPORT_SYMBOL(strpbrk);
X EXPORT_SYMBOL(local_irq_count);
X EXPORT_SYMBOL(local_bh_count);
X EXPORT_SYMBOL(enable_irq);
X EXPORT_SYMBOL(disable_irq);
X EXPORT_SYMBOL(kernel_set_cachemode);
+EXPORT_SYMBOL(kernel_thread);
X 
X /* Networking helper routines. */
X EXPORT_SYMBOL(csum_partial_copy);
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/process.c	Thu Jan  7 15:11:36 1999
+++ linux/arch/m68k/kernel/process.c	Tue Jan 19 10:58:34 1999
@@ -56,16 +56,13 @@
X  */
X asmlinkage int sys_idle(void)
X {
-	int ret = -EPERM;
-
-	lock_kernel();
X 	if (current->pid != 0)
-		goto out;
+		return -EPERM;
X 
X 	/* endless idle loop with no priority at all */
-	current->priority = -100;
+	current->priority = 0;
X 	current->counter = -100;
-	for (;;){
+	for (;;) {
X 		if (!current->need_resched)
X #if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
X 			/* block out HSYNC on the atari (falcon) */
@@ -73,14 +70,9 @@
X #else /* portable version */
X 			__asm__("stop #0x2000" : : : "cc");
X #endif /* machine compilation types */ 
-		check_pgt_cache();
-		run_task_queue(&tq_scheduler);
X 		schedule();
+		check_pgt_cache();
X 	}
-	ret = 0;
-out:
-	unlock_kernel();
-	return ret;
X }
X 
X void machine_restart(char * __unused)
@@ -115,6 +107,44 @@
X 		printk("USP: %08lx\n", rdusp());
X }
X 
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	int pid;
+	mm_segment_t fs;
+
+	fs = get_fs();
+	set_fs (KERNEL_DS);
+
+	{
+	register long retval __asm__ ("d0");
+	register long clone_arg __asm__ ("d1") = flags | CLONE_VM;
+
+	__asm__ __volatile__
+	  ("clrl %%d2\n\t"
+	   "trap #0\n\t"		/* Linux/m68k system call */
+	   "tstl %0\n\t"		/* child or parent */
+	   "jne 1f\n\t"			/* parent - jump */
+	   "lea %%sp@(-8192),%6\n\t"	/* reload current */
+	   "movel %3,%%sp@-\n\t"	/* push argument */
+	   "jsr %4@\n\t"		/* call fn */
+	   "movel %0,%%d1\n\t"		/* pass exit value */
+	   "movel %2,%0\n\t"		/* exit */
+	   "trap #0\n"
+	   "1:"
+	   : "=d" (retval)
+	   : "0" (__NR_clone), "i" (__NR_exit),
+	     "r" (arg), "a" (fn), "d" (clone_arg), "r" (current)
+	   : "d0", "d2");
+	pid = retval;
+	}
+
+	set_fs (fs);
+	return pid;
+}
+
X void flush_thread(void)
X {
X 	unsigned long zero = 0;
@@ -137,6 +167,19 @@
X 	return do_fork(SIGCHLD, rdusp(), regs);
X }
X 
+asmlinkage int m68k_vfork(struct pt_regs *regs)
+{
+	int     child;
+	struct semaphore sem = MUTEX_LOCKED;
+
+	child = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs);
+
+	if (child > 0)
+		down(&sem);
+
+	return child;
+}
+
X asmlinkage int m68k_clone(struct pt_regs *regs)
X {
X 	unsigned long clone_flags;
@@ -147,7 +190,7 @@
X 	newsp = regs->d2;
X 	if (!newsp)
X 		newsp = rdusp();
-	return do_fork(clone_flags, newsp, regs);
+	return do_fork(clone_flags & ~CLONE_VFORK, newsp, regs);
X }
X 
X int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/ptrace.c linux/arch/m68k/kernel/ptrace.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/ptrace.c	Thu Jan  7 15:11:36 1999
+++ linux/arch/m68k/kernel/ptrace.c	Tue Jan 19 10:58:34 1999
@@ -325,12 +325,15 @@
X 		ret = 0;
X 		goto out;
X 	}
-	if (pid == 1)		/* you may not mess with init */
-		goto out;
X 	ret = -ESRCH;
-	if (!(child = find_task_by_pid(pid)))
+	read_lock(&tasklist_lock);
+	child = find_task_by_pid(pid);
+	read_unlock(&tasklist_lock);	/* FIXME!!! */
+	if (!child)
X 		goto out;
X 	ret = -EPERM;
+	if (pid == 1)		/* you may not mess with init */
+		goto out;
X 	if (request == PTRACE_ATTACH) {
X 		if (child == current)
X 			goto out;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/setup.c linux/arch/m68k/kernel/setup.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/setup.c	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/kernel/setup.c	Tue Jan 19 10:58:34 1999
@@ -48,6 +48,7 @@
X extern unsigned long availmem;
X 
X int m68k_num_memory = 0;
+int m68k_realnum_memory = 0;
X struct mem_info m68k_memory[NUM_MEMINFO];
X 
X static struct mem_info m68k_ramdisk = { 0, 0 };
@@ -62,8 +63,6 @@
X int (*mach_keyb_init) (void) __initdata;
X int (*mach_kbdrate) (struct kbd_repeat *) = NULL;
X void (*mach_kbd_leds) (unsigned int) = NULL;
-/* machine dependent "kbd-reset" setup function */
-void (*kbd_reset_setup) (char *, int) __initdata = NULL;
X /* machine dependent irq functions */
X void (*mach_init_IRQ) (void) __initdata;
X void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *) = NULL;
@@ -159,6 +158,7 @@
X 	record = (struct bi_record *)((u_long)record+record->size);
X     }
X 
+    m68k_realnum_memory = m68k_num_memory;
X #ifdef CONFIG_SINGLE_MEMORY_CHUNK
X     if (m68k_num_memory > 1) {
X 	printk("Ignoring last %i chunks of physical memory\n",
@@ -398,9 +398,9 @@
X }
X #endif
X 
-__initfunc(unsigned long arch_kbd_init(void))
+/* for "kbd-reset" cmdline param */
+void __init kbd_reset_setup(char *str, int *ints)
X {
-	return mach_keyb_init();
X }
X 
X void arch_gettod(int *year, int *mon, int *day, int *hour,
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/sys_m68k.c linux/arch/m68k/kernel/sys_m68k.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/sys_m68k.c	Tue Aug 18 22:02:03 1998
+++ linux/arch/m68k/kernel/sys_m68k.c	Tue Jan 19 10:58:34 1999
@@ -112,7 +112,8 @@
X  *
X  * This is really horribly ugly.
X  */
-asmlinkage int sys_ipc (uint call, int first, int second, int third, void *ptr, long fifth)
+asmlinkage int sys_ipc (uint call, int first, int second,
+			int third, void *ptr, long fifth)
X {
X 	int version, ret;
X 
@@ -122,88 +123,76 @@
X 	if (call <= SEMCTL)
X 		switch (call) {
X 		case SEMOP:
-			ret = sys_semop (first, (struct sembuf *)ptr, second);
-			goto out;
+			return sys_semop (first, (struct sembuf *)ptr, second);
X 		case SEMGET:
-			ret = sys_semget (first, second, third);
-			goto out;
+			return sys_semget (first, second, third);
X 		case SEMCTL: {
X 			union semun fourth;
-			ret = -EINVAL;
X 			if (!ptr)
-				goto out;
-			if ((ret = get_user(fourth.__pad, (void **) ptr)))
-				goto out;
-			ret = sys_semctl (first, second, third, fourth);
-			goto out;
+				return -EINVAL;
+			if (get_user(fourth.__pad, (void **) ptr))
+				return -EFAULT;
+			return sys_semctl (first, second, third, fourth);
X 			}
X 		default:
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
X 		}
X 	if (call <= MSGCTL) 
X 		switch (call) {
X 		case MSGSND:
-			ret = sys_msgsnd (first, (struct msgbuf *) ptr, 
+			return sys_msgsnd (first, (struct msgbuf *) ptr, 
X 					  second, third);
-			goto out;
X 		case MSGRCV:
X 			switch (version) {
X 			case 0: {
X 				struct ipc_kludge tmp;
-				ret = -EINVAL;
X 				if (!ptr)
-					goto out;
-				ret = -EFAULT;
-				if (copy_from_user (&tmp, ptr, sizeof (tmp)))
-					goto out;
-				ret = sys_msgrcv (first, tmp.msgp, second, tmp.msgtyp, third);
-				goto out;
+					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);
X 				}
-			case 1: default:
-				ret = sys_msgrcv (first, (struct msgbuf *) ptr, second, fifth, third);
-				goto out;
+			default:
+				return sys_msgrcv (first,
+						   (struct msgbuf *) ptr,
+						   second, fifth, third);
X 			}
X 		case MSGGET:
-			ret = sys_msgget ((key_t) first, second);
-			goto out;
+			return sys_msgget ((key_t) first, second);
X 		case MSGCTL:
-			ret = sys_msgctl (first, second, (struct msqid_ds *) ptr);
-			goto out;
+			return sys_msgctl (first, second,
+					   (struct msqid_ds *) ptr);
X 		default:
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
X 		}
X 	if (call <= SHMCTL) 
X 		switch (call) {
X 		case SHMAT:
X 			switch (version) {
-			case 0: default: {
+			default: {
X 				ulong raddr;
-				ret = sys_shmat (first, (char *) ptr, second, &raddr);
+				ret = sys_shmat (first, (char *) ptr,
+						 second, &raddr);
X 				if (ret)
-					goto out;
-				ret = put_user (raddr, (ulong *) third);
-				goto out;
+					return ret;
+				return put_user (raddr, (ulong *) third);
X 			}
X 			}
X 		case SHMDT: 
-			ret = sys_shmdt ((char *)ptr);
-			goto out;
+			return sys_shmdt ((char *)ptr);
X 		case SHMGET:
-			ret = sys_shmget (first, second, third);
-			goto out;
+			return sys_shmget (first, second, third);
X 		case SHMCTL:
-			ret = sys_shmctl (first, second, (struct shmid_ds *) ptr);
-			goto out;
+			return sys_shmctl (first, second,
+					   (struct shmid_ds *) ptr);
X 		default:
-			ret = -EINVAL;
-			goto out;
+			return -EINVAL;
X 		}
-	ret = -EINVAL;
-out:
-	unlock_kernel();
-	return ret;
+
+	return -EINVAL;
X }
X 
X asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on)
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/kernel/time.c linux/arch/m68k/kernel/time.c
--- v2.2.0-pre8/linux/arch/m68k/kernel/time.c	Sun Jun  7 11:16:27 1998
+++ linux/arch/m68k/kernel/time.c	Tue Jan 19 10:58:34 1999
@@ -5,6 +5,9 @@
X  *
X  * This file contains the m68k-specific time handling details.
X  * Most of the stuff is located in the machine specific files.
+ *
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
X  */
X 
X #include <linux/config.h> /* CONFIG_HEARTBEAT */
@@ -65,9 +68,10 @@
X 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
X 	 * called as close as possible to 500 ms before the new second starts.
X 	 */
-	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 500000 - (tick >> 1) &&
-	    xtime.tv_usec < 500000 + (tick >> 1)) {
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
X 	  if (set_rtc_mmss(xtime.tv_sec) == 0)
X 	    last_rtc_update = xtime.tv_sec;
X 	  else
@@ -146,27 +150,38 @@
X 	mach_sched_init(timer_interrupt);
X }
X 
+extern rwlock_t xtime_lock;
+
X /*
X  * This version of gettimeofday has near microsecond resolution.
X  */
X void do_gettimeofday(struct timeval *tv)
X {
+	extern volatile unsigned long lost_ticks;
X 	unsigned long flags;
+	unsigned long usec, sec, lost;
X 
-	save_flags(flags);
-	cli();
-	*tv = xtime;
-	tv->tv_usec += mach_gettimeoffset();
-	if (tv->tv_usec >= 1000000) {
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
+	read_lock_irqsave(&xtime_lock, flags);
+	usec = mach_gettimeoffset();
+	lost = lost_ticks;
+	if (lost)
+		usec += lost * (1000000/HZ);
+	sec = xtime.tv_sec;
+	usec += xtime.tv_usec;
+	read_unlock_irqrestore(&xtime_lock, flags);
+
+	while (usec >= 1000000) {
+		usec -= 1000000;
+		sec++;
X 	}
-	restore_flags(flags);
+
+	tv->tv_sec = sec;
+	tv->tv_usec = usec;
X }
X 
X void do_settimeofday(struct timeval *tv)
X {
-	cli();
+	write_lock_irq(&xtime_lock);
X 	/* This is revolting. We need to set the xtime.tv_usec
X 	 * correctly. However, the value in this location is
X 	 * is value at the last tick.
@@ -175,14 +190,16 @@
X 	 */
X 	tv->tv_usec -= mach_gettimeoffset();
X 
-	if (tv->tv_usec < 0) {
+	while (tv->tv_usec < 0) {
X 		tv->tv_usec += 1000000;
X 		tv->tv_sec--;
X 	}
X 
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = MAXPHASE;
-	time_esterror = MAXPHASE;
+	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;
X 	sti();
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/mac/config.c linux/arch/m68k/mac/config.c
--- v2.2.0-pre8/linux/arch/m68k/mac/config.c	Thu Jan  7 15:11:36 1999
+++ linux/arch/m68k/mac/config.c	Tue Jan 19 10:58:34 1999
@@ -55,9 +55,6 @@
X 
X void *mac_env;		/* Loaded by the boot asm */
X 
-/* The logical video addr. determined by head.S - testing */
-extern unsigned long mac_videobase;
-
X /* The phys. video addr. - might be bogus on some machines */
X unsigned long mac_orig_videoaddr;
X 
@@ -65,7 +62,6 @@
X extern int mac_keyb_init(void);
X extern int mac_kbdrate(struct kbd_repeat *k);
X extern void mac_kbd_leds(unsigned int leds);
-extern void mac_kbd_reset_setup(char*, int);
X 
X /* Mac specific irq functions */
X extern void mac_init_IRQ (void);
@@ -241,9 +237,7 @@
X 	    mac_bi_data.id = *data;
X 	    break;
X 	case BI_MAC_VADDR:
-	    /* save booter supplied videobase; use the one mapped in head.S! */
-	    mac_orig_videoaddr = *data;
-	    mac_bi_data.videoaddr = mac_videobase;
+	    mac_bi_data.videoaddr = VIDEOMEMBASE + (*data & ~VIDEOMEMMASK);
X 	    break;
X 	case BI_MAC_VDEPTH:
X 	    mac_bi_data.videodepth = *data;
@@ -307,7 +301,6 @@
X     mach_keyb_init       = mac_keyb_init;
X     mach_kbdrate         = mac_kbdrate;
X     mach_kbd_leds        = mac_kbd_leds;
-    kbd_reset_setup      = mac_kbd_reset_setup;
X     mach_init_IRQ        = mac_init_IRQ;
X     mach_request_irq     = mac_request_irq;
X     mach_free_irq        = mac_free_irq;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/mac/debug.c linux/arch/m68k/mac/debug.c
--- v2.2.0-pre8/linux/arch/m68k/mac/debug.c	Thu Jan  7 15:11:36 1999
+++ linux/arch/m68k/mac/debug.c	Tue Jan 19 10:58:34 1999
@@ -39,7 +39,7 @@
X extern void mac_serial_print(char *);
X 
X #define DEBUG_HEADS
-#define DEBUG_SCREEN
+#undef DEBUG_SCREEN
X #define DEBUG_SERIAL
X 
X /*
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/mac/mackeyb.c linux/arch/m68k/mac/mackeyb.c
--- v2.2.0-pre8/linux/arch/m68k/mac/mackeyb.c	Tue Dec 22 14:16:54 1998
+++ linux/arch/m68k/mac/mackeyb.c	Tue Jan 19 10:58:34 1999
@@ -760,8 +760,3 @@
X 
X 	return 0;
X }
-
-/* for "kbd-reset" cmdline param */
-__initfunc(void mac_kbd_reset_setup(char *str, int *ints))
-{
-}
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/mm/init.c linux/arch/m68k/mm/init.c
--- v2.2.0-pre8/linux/arch/m68k/mm/init.c	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/mm/init.c	Tue Jan 19 10:58:34 1999
@@ -28,8 +28,9 @@
X #include <asm/atari_stram.h>
X #endif
X 
+#undef DEBUG
+
X extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void init_kpointer_table(void);
X extern void show_net_buffers(void);
X 
X int do_check_pgt_cache(int low, int high)
@@ -122,17 +123,14 @@
X unsigned long mm_cachebits = 0;
X #endif
X 
-pte_t *kernel_page_table (unsigned long *memavailp)
+static pte_t *__init kernel_page_table(unsigned long *memavailp)
X {
X 	pte_t *ptablep;
X 
-	if (memavailp) {
-		ptablep = (pte_t *)*memavailp;
-		*memavailp += PAGE_SIZE;
-	}
-	else
-		ptablep = (pte_t *)__get_free_page(GFP_KERNEL);
+	ptablep = (pte_t *)*memavailp;
+	*memavailp += PAGE_SIZE;
X 
+	clear_page((unsigned long)ptablep);
X 	flush_page_to_ram((unsigned long) ptablep);
X 	flush_tlb_kernel_page((unsigned long) ptablep);
X 	nocache_page ((unsigned long)ptablep);
@@ -140,199 +138,164 @@
X 	return ptablep;
X }
X 
-__initfunc(static unsigned long
-map_chunk (unsigned long addr, unsigned long size, unsigned long *memavailp))
-{
-#define ONEMEG	(1024*1024)
-#define L3TREESIZE (256*1024)
+static pmd_t *last_pgtable __initdata = NULL;
X 
-	static unsigned long mem_mapped = 0;
-	static unsigned long virtaddr = 0;
-	static pte_t *ktablep = NULL;
-	unsigned long *kpointerp;
-	unsigned long physaddr;
-	extern pte_t *kpt;
-	int pindex;   /* index into pointer table */
-	pgd_t *page_dir = pgd_offset_k (virtaddr);
-
-	if (!pgd_present (*page_dir)) {
-		/* we need a new pointer table */
-		kpointerp = (unsigned long *) get_kpointer_table ();
-		pgd_set (page_dir, (pmd_t *) kpointerp);
-		memset (kpointerp, 0, PTRS_PER_PMD * sizeof (pmd_t));
-	}
-	else
-		kpointerp = (unsigned long *) pgd_page (*page_dir);
+static pmd_t *__init kernel_ptr_table(unsigned long *memavailp)
+{
+	if (!last_pgtable) {
+		unsigned long pmd, last;
+		int i;
X 
-	/*
-	 * pindex is the offset into the pointer table for the
-	 * descriptors for the current virtual address being mapped.
-	 */
-	pindex = (virtaddr >> 18) & 0x7f;
+		last = (unsigned long)kernel_pg_dir;
+		for (i = 0; i < PTRS_PER_PGD; i++) {
+			if (!pgd_val(kernel_pg_dir[i]))
+				continue;
+			pmd = pgd_page(kernel_pg_dir[i]);
+			if (pmd > last)
+				last = pmd;
+		}
X 
+		last_pgtable = (pmd_t *)last;
X #ifdef DEBUG
-	printk ("mm=%ld, kernel_pg_dir=%p, kpointerp=%p, pindex=%d\n",
-		mem_mapped, kernel_pg_dir, kpointerp, pindex);
+		printk("kernel_ptr_init: %p\n", last_pgtable);
X #endif
+	}
X 
-	/*
-	 * if this is running on an '040, we already allocated a page
-	 * table for the first 4M.  The address is stored in kpt by
-	 * arch/head.S
-	 *
-	 */
-	if (CPU_IS_040_OR_060 && mem_mapped == 0)
-		ktablep = kpt;
-
-	for (physaddr = addr;
-	     physaddr < addr + size;
-	     mem_mapped += L3TREESIZE, virtaddr += L3TREESIZE) {
+	if (((unsigned long)(last_pgtable + PTRS_PER_PMD) & ~PAGE_MASK) == 0) {
+		last_pgtable = (pmd_t *)*memavailp;
+		*memavailp += PAGE_SIZE;
X 
-#ifdef DEBUG
-		printk ("pa=%#lx va=%#lx ", physaddr, virtaddr);
-#endif
+		clear_page((unsigned long)last_pgtable);
+		flush_page_to_ram((unsigned long)last_pgtable);
+		flush_tlb_kernel_page((unsigned long)last_pgtable);
+		nocache_page((unsigned long)last_pgtable);
+	} else
+		last_pgtable += PTRS_PER_PMD;
X 
-		if (pindex > 127 && mem_mapped >= 32*ONEMEG) {
-			/* we need a new pointer table every 32M */
-#ifdef DEBUG
-			printk ("[new pointer]");
-#endif
+	return last_pgtable;
+}
X 
-			kpointerp = (unsigned long *)get_kpointer_table ();
-			pgd_set(pgd_offset_k(virtaddr), (pmd_t *)kpointerp);
-			pindex = 0;
-		}
+static unsigned long __init
+map_chunk (unsigned long addr, long size, unsigned long *memavailp)
+{
+#define PTRTREESIZE (256*1024)
+#define ROOTTREESIZE (32*1024*1024)
+	static unsigned long virtaddr = 0;
+	unsigned long physaddr;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
X 
-		if (CPU_IS_040_OR_060) {
-			int i;
-			unsigned long ktable;
-
-			/* Don't map the first 4 MB again. The pagetables
-			 * for this range have already been initialized
-			 * in boot/head.S. Otherwise the pages used for
-			 * tables would be reinitialized to copyback mode.
-			 */
+	physaddr = (addr | m68k_supervisor_cachemode |
+		    _PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+	if (CPU_IS_040_OR_060)
+		physaddr |= _PAGE_GLOBAL040;
X 
-			if (mem_mapped < 4 * ONEMEG)
-			{
+	while (size > 0) {
X #ifdef DEBUG
-				printk ("Already initialized\n");
+		if (!(virtaddr & (PTRTREESIZE-1)))
+			printk ("\npa=%#lx va=%#lx ", physaddr & PAGE_MASK,
+				virtaddr);
X #endif
-				physaddr += L3TREESIZE;
-				pindex++;
+		pgd_dir = pgd_offset_k(virtaddr);
+		if (virtaddr && CPU_IS_020_OR_030) {
+			if (!(virtaddr & (ROOTTREESIZE-1)) &&
+			    size >= ROOTTREESIZE) {
+#ifdef DEBUG
+				printk ("[very early term]");
+#endif
+				pgd_val(*pgd_dir) = physaddr;
+				size -= ROOTTREESIZE;
+				virtaddr += ROOTTREESIZE;
+				physaddr += ROOTTREESIZE;
X 				continue;
X 			}
+		}
+		if (!pgd_present(*pgd_dir)) {
+			pmd_dir = kernel_ptr_table(memavailp);
X #ifdef DEBUG
-			printk ("[setup table]");
+			printk ("[new pointer %p]", pmd_dir);
X #endif
+			pgd_set(pgd_dir, pmd_dir);
+		} else
+			pmd_dir = pmd_offset(pgd_dir, virtaddr);
X 
-			/*
-			 * 68040, use page tables pointed to by the
-			 * kernel pointer table.
-			 */
-
-			if ((pindex & 15) == 0) {
-				/* Need new page table every 4M on the '040 */
+		if (CPU_IS_020_OR_030) {
+			if (virtaddr) {
X #ifdef DEBUG
-				printk ("[new table]");
+				printk ("[early term]");
X #endif
-				ktablep = kernel_page_table (memavailp);
-			}
-
-			ktable = virt_to_phys(ktablep);
-
-			/*
-			 * initialize section of the page table mapping
-			 * this 256K portion.
-			 */
-			for (i = 0; i < 64; i++) {
-				pte_val(ktablep[i]) = physaddr | _PAGE_PRESENT
-				  | m68k_supervisor_cachemode | _PAGE_GLOBAL040
-					| _PAGE_ACCESSED;
+				pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
+				physaddr += PTRTREESIZE;
+			} else {
+				int i;
+#ifdef DEBUG
+				printk ("[zero map]");
+#endif
+				pte_dir = (pte_t *)kernel_ptr_table(memavailp);
+				pmd_dir->pmd[0] = virt_to_phys(pte_dir) |
+					_PAGE_TABLE | _PAGE_ACCESSED;
+				pte_val(*pte_dir++) = 0;
X 				physaddr += PAGE_SIZE;
+				for (i = 1; i < 64; physaddr += PAGE_SIZE, i++)
+					pte_val(*pte_dir++) = physaddr;
X 			}
-			ktablep += 64;
-
-			/*
-			 * make the kernel pointer table point to the
-			 * kernel page table.  Each entries point to a
-			 * 64 entry section of the page table.
-			 */
-
-			kpointerp[pindex++] = ktable | _PAGE_TABLE | _PAGE_ACCESSED;
+			size -= PTRTREESIZE;
+			virtaddr += PTRTREESIZE;
X 		} else {
-			/*
-			 * 68030, use early termination page descriptors.
-			 * Each one points to 64 pages (256K).
-			 */
-#ifdef DEBUG
-			printk ("[early term] ");
-#endif
-			if (virtaddr == 0UL) {
-				/* map the first 256K using a 64 entry
-				 * 3rd level page table.
-				 * UNMAP the first entry to trap
-				 * zero page (NULL pointer) references
-				 */
-				int i;
-				unsigned long *tbl;
-				
-				tbl = (unsigned long *)get_kpointer_table();
-
-				kpointerp[pindex++] = virt_to_phys(tbl) | _PAGE_TABLE |_PAGE_ACCESSED;
-
-				for (i = 0; i < 64; i++, physaddr += PAGE_SIZE)
-					tbl[i] = physaddr | _PAGE_PRESENT | _PAGE_ACCESSED;
-				
-				/* unmap the zero page */
-				tbl[0] = 0;
-			} else {
-				/* not the first 256K */
-				kpointerp[pindex++] = physaddr | _PAGE_PRESENT | _PAGE_ACCESSED;
+			if (!pmd_present(*pmd_dir)) {
X #ifdef DEBUG
-				printk ("%lx=%lx ", virt_to_phys(&kpointerp[pindex-1]),
-					kpointerp[pindex-1]);
+				printk ("[new table]");
X #endif
-				physaddr += 64 * PAGE_SIZE;
+				pte_dir = kernel_page_table(memavailp);
+				pmd_set(pmd_dir, pte_dir);
X 			}
+			pte_dir = pte_offset(pmd_dir, virtaddr);
+
+			if (virtaddr) {
+				if (!pte_present(*pte_dir))
+					pte_val(*pte_dir) = physaddr;
+			} else
+				pte_val(*pte_dir) = 0;
+			size -= PAGE_SIZE;
+			virtaddr += PAGE_SIZE;
+			physaddr += PAGE_SIZE;
X 		}
+
+	}
X #ifdef DEBUG
-		printk ("\n");
+	printk("\n");
X #endif
-	}
X 
-	return mem_mapped;
+	return virtaddr;
X }
X 
X extern unsigned long free_area_init(unsigned long, unsigned long);
+extern void init_pointer_table(unsigned long ptable);
X 
X /* References to section boundaries */
X 
X extern char _text, _etext, _edata, __bss_start, _end;
X extern char __init_begin, __init_end;
X 
-extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
-
X /*
X  * paging_init() continues the virtual memory environment setup which
X  * was begun by the code in arch/head.S.
X  */
-__initfunc(unsigned long paging_init(unsigned long start_mem,
-				     unsigned long end_mem))
+unsigned long __init paging_init(unsigned long start_mem,
+				 unsigned long end_mem)
X {
X 	int chunk;
X 	unsigned long mem_avail = 0;
X 
X #ifdef DEBUG
X 	{
-		extern pte_t *kpt;
-		printk ("start of paging_init (%p, %p, %lx, %lx, %lx)\n",
-			kernel_pg_dir, kpt, availmem, start_mem, end_mem);
+		extern unsigned long availmem;
+		printk ("start of paging_init (%p, %lx, %lx, %lx)\n",
+			kernel_pg_dir, availmem, start_mem, end_mem);
X 	}
X #endif
X 
-	init_kpointer_table();
-
X 	/* Fix the cache mode in the page descriptors for the 680[46]0.  */
X 	if (CPU_IS_040_OR_060) {
X 		int i;
@@ -366,6 +329,7 @@
X 				       m68k_memory[chunk].size, &start_mem);
X 
X 	}
+
X 	flush_tlb_all();
X #ifdef DEBUG
X 	printk ("memory available is %ldKB\n", mem_avail >> 10);
@@ -385,21 +349,16 @@
X 	start_mem += PAGE_SIZE;
X 	memset((void *)empty_zero_page, 0, PAGE_SIZE);
X 
-#if 0
X 	/* 
X 	 * allocate the "swapper" page directory and
X 	 * record in task 0 (swapper) tss 
X 	 */
-	swapper_pg_dir = (pgd_t *)get_kpointer_table();
-
-	init_mm.pgd = swapper_pg_dir;
-#endif
-
-	memset (swapper_pg_dir, 0, sizeof(pgd_t)*PTRS_PER_PGD);
+	init_mm.pgd = (pgd_t *)kernel_ptr_table(&start_mem);
+	memset (init_mm.pgd, 0, sizeof(pgd_t)*PTRS_PER_PGD);
X 
X 	/* setup CPU root pointer for swapper task */
X 	task[0]->tss.crp[0] = 0x80000000 | _PAGE_TABLE;
-	task[0]->tss.crp[1] = virt_to_phys (swapper_pg_dir);
+	task[0]->tss.crp[1] = virt_to_phys(init_mm.pgd);
X 
X #ifdef DEBUG
X 	printk ("task 0 pagedir at %p virt, %#lx phys\n",
@@ -430,16 +389,16 @@
X #ifdef DEBUG
X 	printk ("before free_area_init\n");
X #endif
-
-	return PAGE_ALIGN(free_area_init (start_mem, end_mem));
+	return PAGE_ALIGN(free_area_init(start_mem, end_mem));
X }
X 
-__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
+void __init mem_init(unsigned long start_mem, unsigned long end_mem)
X {
X 	int codepages = 0;
X 	int datapages = 0;
X 	int initpages = 0;
X 	unsigned long tmp;
+	int i;
X 
X 	end_mem &= PAGE_MASK;
X 	high_memory = (void *) end_mem;
@@ -480,6 +439,14 @@
X #endif
X 			free_page(tmp);
X 	}
+
+	/* insert pointer tables allocated so far into the tablelist */
+	init_pointer_table((unsigned long)kernel_pg_dir);
+	for (i = 0; i < PTRS_PER_PGD; i++) {
+		if (pgd_val(kernel_pg_dir[i]))
+			init_pointer_table(pgd_page(kernel_pg_dir[i]));
+	}
+
X 	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
X 	       (unsigned long) nr_free_pages << (PAGE_SHIFT-10),
X 	       max_mapnr << (PAGE_SHIFT-10),
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/mm/kmap.c linux/arch/m68k/mm/kmap.c
--- v2.2.0-pre8/linux/arch/m68k/mm/kmap.c	Sat Sep  5 16:46:40 1998
+++ linux/arch/m68k/mm/kmap.c	Tue Jan 19 10:58:34 1999
@@ -2,6 +2,9 @@
X  *  linux/arch/m68k/mm/kmap.c
X  *
X  *  Copyright (C) 1997 Roman Hodek
+ *
+ *  10/01/99 cleaned up the code and changing to the same interface
+ *	     used by other architectures		/Roman Zippel
X  */
X 
X #include <linux/mm.h>
@@ -9,250 +12,88 @@
X #include <linux/string.h>
X #include <linux/types.h>
X #include <linux/malloc.h>
+#include <linux/vmalloc.h>
X 
X #include <asm/setup.h>
X #include <asm/segment.h>
X #include <asm/page.h>
X #include <asm/pgtable.h>
+#include <asm/io.h>
X #include <asm/system.h>
X 
+#undef DEBUG
X 
-extern pte_t *kernel_page_table (unsigned long *memavailp);
-
-/* Granularity of kernel_map() allocations */
-#define KMAP_STEP	(256*1024)
-
-/* Size of pool of KMAP structures; that is needed, because kernel_map() can
- * be called at times where kmalloc() isn't initialized yet. */
-#define	KMAP_POOL_SIZE	16
-
-/* structure for maintainance of kmap regions */
-typedef struct kmap {
-	struct kmap *next, *prev;	/* linking of list */
-	unsigned long addr;			/* start address of region */
-	unsigned long mapaddr;		/* address returned to user */
-	unsigned long size;			/* size of region */
-	unsigned free : 1;			/* flag whether free or allocated */
-	unsigned kmalloced : 1;		/* flag whether got this from kmalloc() */
-	unsigned pool_alloc : 1;	/* flag whether got this is alloced in pool */
-} KMAP;
-
-KMAP kmap_pool[KMAP_POOL_SIZE] = {
-	{ NULL, NULL, KMAP_START, KMAP_START, KMAP_END-KMAP_START, 1, 0, 1 },
-	{ NULL, NULL, 0, 0, 0, 0, 0, 0 },
-};
+#define PTRTREESIZE	(256*1024)
X 
X /*
- * anchor of kmap region list
- *
- * The list is always ordered by addresses, and regions are always adjacent,
- * i.e. there must be no holes between them!
+ * For 040/060 we can use the virtual memory area like other architectures,
+ * but for 020/030 we want to use early termination page descriptor and we
+ * can't mix this with normal page descriptors, so we have to copy that code
+ * (mm/vmalloc.c) and return appriorate aligned addresses.
X  */
-KMAP *kmap_regions = &kmap_pool[0];
-
-/* for protecting the kmap_regions list against races */
-static struct semaphore kmap_sem = MUTEX;
X 
+#ifdef CPU_M68040_OR_M68060_ONLY
X 
+#define IO_SIZE		PAGE_SIZE
X 
-/*
- * Low-level allocation and freeing of KMAP structures
- */
-static KMAP *alloc_kmap( int use_kmalloc )
+static inline struct vm_struct *get_io_area(unsigned long size)
X {
-	KMAP *p;
-	int i;
-
-	/* first try to get from the pool if possible */
-	for( i = 0; i < KMAP_POOL_SIZE; ++i ) {
-		if (!kmap_pool[i].pool_alloc) {
-			kmap_pool[i].kmalloced = 0;
-			kmap_pool[i].pool_alloc = 1;
-			return( &kmap_pool[i] );
-		}
-	}
-	
-	if (use_kmalloc && (p = (KMAP *)kmalloc( sizeof(KMAP), GFP_KERNEL ))) {
-		p->kmalloced = 1;
-		return( p );
-	}
-	
-	return( NULL );
-}
-
-static void free_kmap( KMAP *p )
-{
-	if (p->kmalloced)
-		kfree( p );
-	else
-		p->pool_alloc = 0;
+	return get_vm_area(size);
X }
X 
X 
-/*
- * Get a free region from the kmap address range
- */
-static KMAP *kmap_get_region( unsigned long size, int use_kmalloc )
+static inline void free_io_area(void *addr)
X {
-	KMAP *p, *q;
-
-	/* look for a suitable free region */
-	for( p = kmap_regions; p; p = p->next )
-		if (p->free && p->size >= size)
-			break;
-	if (!p) {
-		printk( KERN_ERR "kernel_map: address space for "
-				"allocations exhausted\n" );
-		return( NULL );
-	}
-	
-	if (p->size > size) {
-		/* if free region is bigger than we need, split off the rear free part
-		 * into a new region */
-		if (!(q = alloc_kmap( use_kmalloc ))) {
-			printk( KERN_ERR "kernel_map: out of memory\n" );
-			return( NULL );
-		}
-		q->addr = p->addr + size;
-		q->size = p->size - size;
-		p->size = size;
-		q->free = 1;
-
-		q->prev = p;
-		q->next = p->next;
-		p->next = q;
-		if (q->next) q->next->prev = q;
-	}
-	
-	p->free = 0;
-	return( p );
+	return vfree((void *)(PAGE_MASK & (unsigned long)addr));
X }
X 
+#else
X 
-/*
- * Free a kernel_map region again
- */
-static void kmap_put_region( KMAP *p )
-{
-	KMAP *q;
-
-	p->free = 1;
-
-	/* merge with previous region if possible */
-	q = p->prev;
-	if (q && q->free) {
-		if (q->addr + q->size != p->addr) {
-			printk( KERN_ERR "kernel_malloc: allocation list destroyed\n" );
-			return;
-		}
-		q->size += p->size;
-		q->next = p->next;
-		if (p->next) p->next->prev = q;
-		free_kmap( p );
-		p = q;
-	}
-
-	/* merge with following region if possible */
-	q = p->next;
-	if (q && q->free) {
-		if (p->addr + p->size != q->addr) {
-			printk( KERN_ERR "kernel_malloc: allocation list destroyed\n" );
-			return;
-		}
-		p->size += q->size;
-		p->next = q->next;
-		if (q->next) q->next->prev = p;
-		free_kmap( q );
-	}
-}
+#define IO_SIZE		(256*1024)
X 
+static struct vm_struct *iolist = NULL;
X 
-/*
- * kernel_map() helpers
- */
-static inline pte_t *
-pte_alloc_kernel_map(pmd_t *pmd, unsigned long address,
-		     unsigned long *memavailp)
+static struct vm_struct *get_io_area(unsigned long size)
X {
-	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
-	if (pmd_none(*pmd)) {
-		pte_t *page = kernel_page_table(memavailp);
-		if (pmd_none(*pmd)) {
-			if (page) {
-				pmd_set(pmd, page);
-				memset( page, 0, PAGE_SIZE );
-				return page + address;
-			}
-			pmd_set(pmd, BAD_PAGETABLE);
-			return NULL;
-		}
-		if (memavailp)
-			panic("kernel_map: slept during init?!?");
-		cache_page((unsigned long) page);
-		free_page((unsigned long) page);
-	}
-	if (pmd_bad(*pmd)) {
-		printk( KERN_ERR "Bad pmd in pte_alloc_kernel_map: %08lx\n",
-		       pmd_val(*pmd));
-		pmd_set(pmd, BAD_PAGETABLE);
+	unsigned long addr;
+	struct vm_struct **p, *tmp, *area;
+
+	area = (struct vm_struct *)kmalloc(sizeof(*area), GFP_KERNEL);
+	if (!area)
X 		return NULL;
+	addr = KMAP_START;
+	for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
+		if (size + addr < (unsigned long)tmp->addr)
+			break;
+		if (addr > KMAP_END-size)
+			return NULL;
+		addr = tmp->size + (unsigned long)tmp->addr;
X 	}
-	return (pte_t *) pmd_page(*pmd) + address;
+	area->addr = (void *)addr;
+	area->size = size + IO_SIZE;
+	area->next = *p;
+	*p = area;
+	return area;
X }
X 
-static inline void
-kernel_map_pte(pte_t *pte, unsigned long address, unsigned long size,
-	       unsigned long phys_addr, pgprot_t prot)
+static inline void free_io_area(void *addr)
X {
-	unsigned long end;
+	struct vm_struct **p, *tmp;
X 
-	address &= ~PMD_MASK;
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	do {
-		pte_val(*pte) = phys_addr + pgprot_val(prot);
-		address += PAGE_SIZE;
-		phys_addr += PAGE_SIZE;
-		pte++;
-	} while (address < end);
-}
-
-static inline int
-kernel_map_pmd (pmd_t *pmd, unsigned long address, unsigned long size,
-		unsigned long phys_addr, pgprot_t prot,
-		unsigned long *memavailp)
-{
-	unsigned long end;
-
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	phys_addr -= address;
-
-	if (CPU_IS_040_OR_060) {
-		do {
-			pte_t *pte = pte_alloc_kernel_map(pmd, address, memavailp);
-			if (!pte)
-				return -ENOMEM;
-			kernel_map_pte(pte, address, end - address,
-				       address + phys_addr, prot);
-			address = (address + PMD_SIZE) & PMD_MASK;
-			pmd++;
-		} while (address < end);
-	} else {
-		/* On the 68030 we use early termination page descriptors.
-		   Each one points to 64 pages (256K). */
-		int i = (address >> (PMD_SHIFT-4)) & 15;
-		do {
-			(&pmd_val(*pmd))[i++] = (address + phys_addr) | pgprot_val(prot);
-			address += PMD_SIZE / 16;
-		} while (address < end);
+	if (!addr)
+		return;
+	addr = (void *)((unsigned long)addr & -IO_SIZE);
+	for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
+		if (tmp->addr == addr) {
+			*p = tmp->next;
+			__iounmap(tmp->addr, tmp->size);
+			kfree(tmp);
+			return;
+		}
X 	}
-	return 0;
X }
X 
+#endif
X 
X /*
X  * Map some physical address range into the kernel address space. The
@@ -260,304 +101,245 @@
X  */
X /* Rewritten by Andreas Schwab to remove all races. */
X 
-unsigned long kernel_map(unsigned long phys_addr, unsigned long size,
-			 int cacheflag, unsigned long *memavailp)
+void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
X {
-	unsigned long retaddr, from, end;
-	pgd_t *dir;
-	pgprot_t prot;
-	KMAP *kmap;
-
-	/* Round down 'phys_addr' to 256 KB and adjust size */
-	retaddr = phys_addr & (KMAP_STEP-1);
-	size += retaddr;
-	phys_addr &= ~(KMAP_STEP-1);
-	/* Round up the size to 256 KB. It doesn't hurt if too much is
-	   mapped... */
-	size = (size + KMAP_STEP - 1) & ~(KMAP_STEP-1);
-	
-	down( &kmap_sem );
-	kmap = kmap_get_region(size, memavailp == NULL);
-	if (!kmap) {
-		up(&kmap_sem);
-		return 0;
-	}
-	from = kmap->addr;
-	retaddr += from;
-	kmap->mapaddr = retaddr;
-	end = from + size;
-	up( &kmap_sem );
+	struct vm_struct *area;
+	unsigned long virtaddr, retaddr;
+	long offset;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
+
+	/*
+	 * Don't allow mappings that wrap..
+	 */
+	if (!size || size > physaddr + size)
+		return NULL;
X 
+#ifdef DEBUG
+	printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
+#endif
+	/*
+	 * Mappings have to be aligned
+	 */
+	offset = physaddr & (IO_SIZE - 1);
+	physaddr &= -IO_SIZE;
+	size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_io_area(size);
+	if (!area)
+		return NULL;
+
+	virtaddr = (unsigned long)area->addr;
+	retaddr = virtaddr + offset;
+#ifdef DEBUG
+	printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
+#endif
+
+	/*
+	 * add cache and table flags to physical address
+	 */
X 	if (CPU_IS_040_OR_060) {
-		pgprot_val(prot) = (_PAGE_PRESENT | _PAGE_GLOBAL040 |
-				    _PAGE_ACCESSED | _PAGE_DIRTY);
+		physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
+			     _PAGE_ACCESSED | _PAGE_DIRTY);
X 		switch (cacheflag) {
-		case KERNELMAP_FULL_CACHING:
-			pgprot_val(prot) |= _PAGE_CACHE040;
+		case IOMAP_FULL_CACHING:
+			physaddr |= _PAGE_CACHE040;
X 			break;
-		case KERNELMAP_NOCACHE_SER:
+		case IOMAP_NOCACHE_SER:
X 		default:
-			pgprot_val(prot) |= _PAGE_NOCACHE_S;
+			physaddr |= _PAGE_NOCACHE_S;
X 			break;
-		case KERNELMAP_NOCACHE_NONSER:
-			pgprot_val(prot) |= _PAGE_NOCACHE;
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 04'
echo 'File patch-2.2.0-pre9 is continued in part 05'
echo 05 > _shar_seq_.tmp
#!/bin/sh
# this is part 05 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 05; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
+		case IOMAP_NOCACHE_NONSER:
+			physaddr |= _PAGE_NOCACHE;
X 			break;
-		case KERNELMAP_NO_COPYBACK:
-			pgprot_val(prot) |= _PAGE_CACHE040W;
+		case IOMAP_WRITETHROUGH:
+			physaddr |= _PAGE_CACHE040W;
X 			break;
X 		}
-	} else
-		pgprot_val(prot) = (_PAGE_PRESENT | _PAGE_ACCESSED |
-				    _PAGE_DIRTY |
-				    ((cacheflag == KERNELMAP_FULL_CACHING ||
-				      cacheflag == KERNELMAP_NO_COPYBACK)
-				     ? 0 : _PAGE_NOCACHE030));
-
-	phys_addr -= from;
-	dir = pgd_offset_k(from);
-	while (from < end) {
-		pmd_t *pmd = pmd_alloc_kernel(dir, from);
-
-		if (kernel_map_pmd(pmd, from, end - from, phys_addr + from,
-				   prot, memavailp)) {
-			printk( KERN_ERR "kernel_map: out of memory\n" );
-			return 0UL;
+	} else {
+		physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+		switch (cacheflag) {
+		case IOMAP_NOCACHE_SER:
+		case IOMAP_NOCACHE_NONSER:
+		default:
+			physaddr |= _PAGE_NOCACHE030;
+			break;
+		case IOMAP_FULL_CACHING:
+		case IOMAP_WRITETHROUGH:
+			break;
X 		}
-		from = (from + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
X 	}
X 
-	return retaddr;
-}
-
+	while (size > 0) {
+#ifdef DEBUG
+		if (!(virtaddr & (PTRTREESIZE-1)))
+			printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
+#endif
+		pgd_dir = pgd_offset_k(virtaddr);
+		pmd_dir = pmd_alloc_kernel(pgd_dir, virtaddr);
+		if (!pmd_dir) {
+			printk("ioremap: no mem for pmd_dir\n");
+			return NULL;
+		}
X 
-/*
- * kernel_unmap() helpers
- */
-static inline void pte_free_kernel_unmap( pmd_t *pmd )
-{
-	unsigned long page = pmd_page(*pmd);
-	mem_map_t *pagemap = &mem_map[MAP_NR(page)];
-	
-	pmd_clear(pmd);
-	cache_page(page);
-
-	if (PageReserved( pagemap )) {
-		/* need to unreserve pages that were allocated with memavailp != NULL;
-		 * this works only if 'page' is page-aligned */
-		if (page & ~PAGE_MASK)
-			return;
-		clear_bit( PG_reserved, &pagemap->flags );
-		atomic_set( &pagemap->count, 1 );
-	}
-	free_page( page );
-}
+		if (CPU_IS_020_OR_030) {
+			pmd_dir->pmd[(virtaddr/PTRTREESIZE)&-16] = physaddr;
+			physaddr += PTRTREESIZE;
+			virtaddr += PTRTREESIZE;
+			size -= PTRTREESIZE;
+		} else {
+			pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
+			if (!pte_dir) {
+				printk("ioremap: no mem for pte_dir\n");
+				return NULL;
+			}
X 
-/*
- * This not only unmaps the requested region, but also loops over the whole
- * pmd to determine whether the other pte's are clear (so that the page can be
- * freed.) If so, it returns 1, 0 otherwise.
- */
-static inline int
-kernel_unmap_pte_range(pmd_t * pmd, unsigned long address, unsigned long size)
-{
-	pte_t *pte;
-	unsigned long addr2, end, end2;
-	int all_clear = 1;
-
-	if (pmd_none(*pmd))
-		return( 0 );
-	if (pmd_bad(*pmd)) {
-		printk( KERN_ERR "kernel_unmap_pte_range: bad pmd (%08lx)\n",
-				pmd_val(*pmd) );
-		pmd_clear(pmd);
-		return( 0 );
-	}
-	address &= ~PMD_MASK;
-	addr2 = 0;
-	pte = pte_offset(pmd, addr2);
-	end = address + size;
-	if (end > PMD_SIZE)
-		end = PMD_SIZE;
-	end2 = addr2 + PMD_SIZE;
-	while( addr2 < end2 ) {
-		if (!pte_none(*pte)) {
-			if (address <= addr2 && addr2 < end)
-				pte_clear(pte);
-			else
-				all_clear = 0;
+			pte_val(*pte_dir) = physaddr;
+			virtaddr += PAGE_SIZE;
+			physaddr += PAGE_SIZE;
+			size -= PAGE_SIZE;
X 		}
-		++pte;
-		addr2 += PAGE_SIZE;
X 	}
-	return( all_clear );
-}
-
-static inline void
-kernel_unmap_pmd_range(pgd_t * dir, unsigned long address, unsigned long size)
-{
-	pmd_t * pmd;
-	unsigned long end;
+#ifdef DEBUG
+	printk("\n");
+#endif
+	flush_tlb_all();
X 
-	if (pgd_none(*dir))
-		return;
-	if (pgd_bad(*dir)) {
-		printk( KERN_ERR "kernel_unmap_pmd_range: bad pgd (%08lx)\n",
-				pgd_val(*dir) );
-		pgd_clear(dir);
-		return;
-	}
-	pmd = pmd_offset(dir, address);
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-	
-	if (CPU_IS_040_OR_060) {
-		do {
-			if (kernel_unmap_pte_range(pmd, address, end - address))
-				pte_free_kernel_unmap( pmd );
-			address = (address + PMD_SIZE) & PMD_MASK;
-			pmd++;
-		} while (address < end);
-	} else {
- /* On the 68030 clear the early termination descriptors */
-		int i = (address >> (PMD_SHIFT-4)) & 15;
-		do {
- (&pmd_val(*pmd))[i++] = 0;
-			address += PMD_SIZE / 16;
-		} while (address < end);
-	}
+	return (void *)retaddr;
X }
X 
X /*
- * Unmap a kernel_map()ed region again
+ * Unmap a ioremap()ed region again
X  */
-void kernel_unmap( unsigned long addr )
+void iounmap(void *addr)
X {
-	unsigned long end;
-	pgd_t *dir;
-	KMAP *p;
-
-	down( &kmap_sem );
-	
- /* find region for 'addr' in list; must search for mapaddr! */
-	for( p = kmap_regions; p; p = p->next )
- if (!p->free && p->mapaddr == addr)
-			break;
-	if (!p) {
-		printk( KERN_ERR "kernel_unmap: trying to free invalid region\n" );
-		return;
-	}
-	addr = p->addr;
-	end = addr + p->size;
-	kmap_put_region( p );
-
-	dir = pgd_offset_k( addr );
-	while( addr < end ) {
-		kernel_unmap_pmd_range( dir, addr, end - addr );
-		addr = (addr + PGDIR_SIZE) & PGDIR_MASK;
-		dir++;
-	}
-	
-	up( &kmap_sem );
-	/* flushing for a range would do, but there's no such function for kernel
-	 * address space... */
-	flush_tlb_all();
+	free_io_area(addr);
X }
X 
-
X /*
- * kernel_set_cachemode() helpers
+ * __iounmap unmaps nearly everything, so be careful
+ * it doesn't free currently pointer/page tables anymore but it
+ * wans't used anyway and might be added later.
X  */
-static inline void set_cmode_pte( pmd_t *pmd, unsigned long address,
-				  unsigned long size, unsigned cmode )
-{	pte_t *pte;
-	unsigned long end;
-
-	if (pmd_none(*pmd))
-		return;
-
-	pte = pte_offset( pmd, address );
-	address &= ~PMD_MASK;
-	end = address + size;
- if (end >= PMD_SIZE)
-		end = PMD_SIZE;
-
-	for( ; address < end; pte++ ) {
-		pte_val(*pte) = (pte_val(*pte) & ~_PAGE_NOCACHE) | cmode;
-		address += PAGE_SIZE;
-	}
-}
+void __iounmap(void *addr, unsigned long size)
+{
+	unsigned long virtaddr = (unsigned long)addr;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
X 
+	while (size > 0) {
+		pgd_dir = pgd_offset_k(virtaddr);
+		if (pgd_bad(*pgd_dir)) {
+			printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
+			pgd_clear(pgd_dir);
+			return;
+		}
+		pmd_dir = pmd_offset(pgd_dir, virtaddr);
X 
-static inline void set_cmode_pmd( pgd_t *dir, unsigned long address,
-				  unsigned long size, unsigned cmode )
-{
-	pmd_t *pmd;
-	unsigned long end;
+		if (CPU_IS_020_OR_030) {
+			int pmd_off = (virtaddr/PTRTREESIZE) & -16;
X 
-	if (pgd_none(*dir))
-		return;
+			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
+				pmd_dir->pmd[pmd_off] = 0;
+				virtaddr += PTRTREESIZE;
+				size -= PTRTREESIZE;
+				continue;
+			}
+		}
X 
-	pmd = pmd_offset( dir, address );
-	address &= ~PGDIR_MASK;
-	end = address + size;
-	if (end > PGDIR_SIZE)
-		end = PGDIR_SIZE;
-
-	if ((pmd_val(*pmd) & _DESCTYPE_MASK) == _PAGE_PRESENT) {
-		/* 68030 early termination descriptor */
-		pmd_val(*pmd) = (pmd_val(*pmd) & ~_PAGE_NOCACHE) | cmode;
-		return;
-	}
-	else {
-		/* "normal" tables */
-		for( ; address < end; pmd++ ) {
-			set_cmode_pte( pmd, address, end - address, cmode );
-			address = (address + PMD_SIZE) & PMD_MASK;
+		if (pmd_bad(*pmd_dir)) {
+			printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
+			pmd_clear(pmd_dir);
+			return;
X 		}
+		pte_dir = pte_offset(pmd_dir, virtaddr);
+
+		pte_val(*pte_dir) = 0;
+		virtaddr += PAGE_SIZE;
+		size -= PAGE_SIZE;
X 	}
-}
X 
+	flush_tlb_all();
+}
X 
X /*
X  * Set new cache mode for some kernel address space.
X  * The caller must push data for that range itself, if such data may already
X  * be in the cache.
X  */
-void kernel_set_cachemode( unsigned long address, unsigned long size,
-						   unsigned cmode )
+void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
X {
-	pgd_t *dir = pgd_offset_k( address );
-	unsigned long end = address + size;
-	
+	unsigned long virtaddr = (unsigned long)addr;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
+
X 	if (CPU_IS_040_OR_060) {
-		switch( cmode ) {
-		  case KERNELMAP_FULL_CACHING:
+		switch (cmode) {
+		case IOMAP_FULL_CACHING:
X 			cmode = _PAGE_CACHE040;
X 			break;
-		  case KERNELMAP_NOCACHE_SER:
-		  default:
+		case IOMAP_NOCACHE_SER:
+		default:
X 			cmode = _PAGE_NOCACHE_S;
X 			break;
-		  case KERNELMAP_NOCACHE_NONSER:
+		case IOMAP_NOCACHE_NONSER:
X 			cmode = _PAGE_NOCACHE;
X 			break;
-		  case KERNELMAP_NO_COPYBACK:
+		case IOMAP_WRITETHROUGH:
X 			cmode = _PAGE_CACHE040W;
X 			break;
X 		}
-	} else
-		cmode = ((cmode == KERNELMAP_FULL_CACHING ||
-				  cmode == KERNELMAP_NO_COPYBACK)    ?
-			 0 : _PAGE_NOCACHE030);
-
-	for( ; address < end; dir++ ) {
-		set_cmode_pmd( dir, address, end - address, cmode );
-		address = (address + PGDIR_SIZE) & PGDIR_MASK;
+	} else {
+		switch (cmode) {
+		case IOMAP_NOCACHE_SER:
+		case IOMAP_NOCACHE_NONSER:
+		default:
+			cmode = _PAGE_NOCACHE030;
+			break;
+		case IOMAP_FULL_CACHING:
+		case IOMAP_WRITETHROUGH:
+			cmode = 0;
+		}
+	}
+
+	while (size > 0) {
+		pgd_dir = pgd_offset_k(virtaddr);
+		if (pgd_bad(*pgd_dir)) {
+			printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
+			pgd_clear(pgd_dir);
+			return;
+		}
+		pmd_dir = pmd_offset(pgd_dir, virtaddr);
+
+		if (CPU_IS_020_OR_030) {
+			int pmd_off = (virtaddr/PTRTREESIZE) & -16;
+
+			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
+				pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
+							 _CACHEMASK040) | cmode;
+				virtaddr += PTRTREESIZE;
+				size -= PTRTREESIZE;
+				continue;
+			}
+		}
+
+		if (pmd_bad(*pmd_dir)) {
+			printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
+			pmd_clear(pmd_dir);
+			return;
+		}
+		pte_dir = pte_offset(pmd_dir, virtaddr);
+
+		pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
+		virtaddr += PAGE_SIZE;
+		size -= PAGE_SIZE;
X 	}
-	/* flushing for a range would do, but there's no such function for kernel
-	 * address space... */
+
X 	flush_tlb_all();
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/m68k/mm/memory.c linux/arch/m68k/mm/memory.c
--- v2.2.0-pre8/linux/arch/m68k/mm/memory.c	Fri Oct  9 13:27:06 1998
+++ linux/arch/m68k/mm/memory.c	Tue Jan 19 10:58:34 1999
@@ -10,6 +10,7 @@
X #include <linux/string.h>
X #include <linux/types.h>
X #include <linux/malloc.h>
+#include <linux/init.h>
X 
X #include <asm/setup.h>
X #include <asm/segment.h>
@@ -97,6 +98,31 @@
X 
X #define PTABLE_SIZE (PTRS_PER_PMD * sizeof(pmd_t))
X 
+void __init init_pointer_table(unsigned long ptable)
+{
+	ptable_desc *dp;
+	unsigned long page = ptable & PAGE_MASK;
+	unsigned char mask = 1 << ((ptable - page)/PTABLE_SIZE);
+
+	dp = PAGE_PD(page);
+	if (!(PD_MARKBITS(dp) & mask)) {
+		PD_MARKBITS(dp) = 0xff;
+		(dp->prev = ptable_list.prev)->next = dp;
+		(dp->next = &ptable_list)->prev = dp;
+	}
+
+	PD_MARKBITS(dp) &= ~mask;
+#ifdef DEBUG
+	printk("init_pointer_table: %lx, %x\n", ptable, PD_MARKBITS(dp));
+#endif
+
+	/* unreserve the page so it's possible to free that page */
+	dp->flags &= ~(1 << PG_reserved);
+	atomic_set(&dp->count, 1);
+
+	return;
+}
+
X pmd_t *get_pointer_table (void)
X {
X 	ptable_desc *dp = ptable_list.next;
@@ -176,103 +202,6 @@
X 	return 0;
X }
X 
-/* maximum pages used for kpointer tables */
-#define KPTR_PAGES      4
-/* # of reserved slots */
-#define RESERVED_KPTR	4
-extern pmd_tablepage kernel_pmd_table; /* reserved in head.S */
-
-static struct kpointer_pages {
-        pmd_tablepage *page[KPTR_PAGES];
-        u_char alloced[KPTR_PAGES];
-} kptr_pages;
-
-void init_kpointer_table(void) {
-	short i = KPTR_PAGES-1;
-
-	/* first page is reserved in head.S */
-	kptr_pages.page[i] = &kernel_pmd_table;
-	kptr_pages.alloced[i] = ~(0xff>>RESERVED_KPTR);
-	for (i--; i>=0; i--) {
-		kptr_pages.page[i] = NULL;
-		kptr_pages.alloced[i] = 0;
-	}
-}
-
-pmd_t *get_kpointer_table (void)
-{
-	/* For pointer tables for the kernel virtual address space,
-	 * use the page that is reserved in head.S that can hold up to
-	 * 8 pointer tables. 3 of these tables are always reserved
-	 * (kernel_pg_dir, swapper_pg_dir and kernel pointer table for
-	 * the first 16 MB of RAM). In addition, the 4th pointer table
-	 * in this page is reserved. On Amiga and Atari, it is used to
-	 * map in the hardware registers. It may be used for other
-	 * purposes on other 68k machines. This leaves 4 pointer tables
-	 * available for use by the kernel. 1 of them are usually used
-	 * for the vmalloc tables. This allows mapping of 3 * 32 = 96 MB
-	 * of physical memory. But these pointer tables are also used
-	 * for other purposes, like kernel_map(), so further pages can
-	 * now be allocated.
-	 */
-	pmd_tablepage *page;
-	pmd_table *table;
-	long nr, offset = -8;
-	short i;
-
-	for (i=KPTR_PAGES-1; i>=0; i--) {
-		asm volatile("bfffo %1{%2,#8},%0"
-			: "=d" (nr)
-			: "d" ((u_char)~kptr_pages.alloced[i]), "d" (offset));
-		if (nr)
-			break;
-	}
-	if (i < 0) {
-		printk("No space for kernel pointer table!\n");
-		return NULL;
-	}
-	if (!(page = kptr_pages.page[i])) {
-		if (!(page = (pmd_tablepage *)get_free_page(GFP_KERNEL))) {
-			printk("No space for kernel pointer table!\n");
-			return NULL;
-		}
-		flush_tlb_kernel_page((unsigned long) page);
-		nocache_page((u_long)(kptr_pages.page[i] = page));
-	}
-	asm volatile("bfset %0@{%1,#1}"
-		: /* no output */
-		: "a" (&kptr_pages.alloced[i]), "d" (nr-offset));
-	table = &(*page)[nr-offset];
-	memset(table, 0, sizeof(pmd_table));
-	return ((pmd_t *)table);
-}
-
-void free_kpointer_table (pmd_t *pmdp)
-{
-	pmd_table *table = (pmd_table *)pmdp;
-	pmd_tablepage *page = (pmd_tablepage *)((u_long)table & PAGE_MASK);
-	long nr;
-	short i;
-
-	for (i=KPTR_PAGES-1; i>=0; i--) {
-		if (kptr_pages.page[i] == page)
-			break;
-	}
-	nr = ((u_long)table - (u_long)page) / sizeof(pmd_table);
-	if (!table || i < 0 || (i == KPTR_PAGES-1 && nr < RESERVED_KPTR)) {
-		printk("Attempt to free invalid kernel pointer table: %p\n", table);
-		return;
-	}
-	asm volatile("bfclr %0@{%1,#1}"
-		: /* no output */
-		: "a" (&kptr_pages.alloced[i]), "d" (nr));
-	if (!kptr_pages.alloced[i]) {
-		kptr_pages.page[i] = 0;
-		cache_page ((u_long)page);
-		free_page ((u_long)page);
-	}
-}
-
X static unsigned long transp_transl_matches( unsigned long regval,
X 					    unsigned long vaddr )
X {
@@ -308,7 +237,6 @@
X  */
X unsigned long mm_vtop (unsigned long vaddr)
X {
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
X 	int i=0;
X 	unsigned long voff = vaddr;
X 	unsigned long offset = 0;
@@ -324,10 +252,6 @@
X 			offset += m68k_memory[i].size;
X 		i++;
X 	}while (i < m68k_num_memory);
-#else
-	if (vaddr < m68k_memory[0].size)
-		return m68k_memory[0].addr + vaddr;
-#endif
X 
X 	return mm_vtop_fallback(vaddr);
X }
@@ -449,7 +373,6 @@
X #ifndef CONFIG_SINGLE_MEMORY_CHUNK
X unsigned long mm_ptov (unsigned long paddr)
X {
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
X 	int i = 0;
X 	unsigned long offset = 0;
X 
@@ -466,11 +389,6 @@
X 			offset += m68k_memory[i].size;
X 		i++;
X 	}while (i < m68k_num_memory);
-#else
-	unsigned long base = m68k_memory[0].addr;
-	if (paddr >= base && paddr < (base + m68k_memory[0].size))
-		return (paddr - base);
-#endif
X 
X 	/*
X 	 * assume that the kernel virtual address is the same as the
@@ -560,7 +478,7 @@
X  *	Jes was worried about performance (urhh ???) so its optional
X  */
X  
-extern void (*mach_l2_flush)(int) = NULL;
+void (*mach_l2_flush)(int) = NULL;
X #endif
X  
X /*
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/mips/kernel/time.c linux/arch/mips/kernel/time.c
--- v2.2.0-pre8/linux/arch/mips/kernel/time.c	Fri Oct 23 22:01:19 1998
+++ linux/arch/mips/kernel/time.c	Tue Jan 19 10:19:48 1999
@@ -6,6 +6,9 @@
X  * This file contains the time handling details for PC-style clocks as
X  * found in some MIPS systems.
X  *
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
+ *
X  * $Id: time.c,v 1.6 1998/08/17 13:57:44 ralf Exp $
X  */
X #include <linux/errno.h>
@@ -255,9 +258,11 @@
X 	}
X 
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = MAXPHASE;
-	time_esterror = MAXPHASE;
+	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;
X 	sti();
X }
X 
@@ -267,6 +272,9 @@
X  * nowtime is written into the registers of the CMOS clock, it will
X  * jump to the next second precisely 500 ms later. Check the Motorola
X  * MC146818A or Dallas DS12887 data sheet for details.
+ *
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
X  */
X static int set_rtc_mmss(unsigned long nowtime)
X {
@@ -303,8 +311,12 @@
X 		}
X 		CMOS_WRITE(real_seconds,RTC_SECONDS);
X 		CMOS_WRITE(real_minutes,RTC_MINUTES);
-	} else
-		retval = -1;
+	} else {
+		printk(KERN_WARNING
+		       "set_rtc_mmss: can't update from %d to %d\n",
+		       cmos_minutes, real_minutes);
+ 		retval = -1;
+	}
X 
X 	/* The following flags have to be released exactly in this order,
X 	 * otherwise the DS12887 (popular MC146818A clone with integrated
@@ -336,9 +348,10 @@
X 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
X 	 * called as close as possible to 500 ms before the new second starts.
X 	 */
-	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 500000 - (tick >> 1) &&
-	    xtime.tv_usec < 500000 + (tick >> 1))
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2)
X 	  if (set_rtc_mmss(xtime.tv_sec) == 0)
X 	    last_rtc_update = xtime.tv_sec;
X 	  else
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/ppc/kernel/time.c linux/arch/ppc/kernel/time.c
--- v2.2.0-pre8/linux/arch/ppc/kernel/time.c	Thu Dec 31 10:28:59 1998
+++ linux/arch/ppc/kernel/time.c	Tue Jan 19 10:19:50 1999
@@ -17,6 +17,9 @@
X  * This is then divided by 4, providing a 8192 Hz clock into the PIT.
X  * Since it is not possible to get a nice 100 Hz clock out of this, without
X  * creating a software PLL, I have set HZ to 128.  -- Dan
+ *
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
X  */
X 
X #include <linux/config.h>
@@ -195,6 +198,11 @@
X 	xtime.tv_sec = tv->tv_sec;
X 	xtime.tv_usec = tv->tv_usec - frac_tick;
X 	set_dec(frac_tick * count_period_den / count_period_num);
+	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;
X 	restore_flags(flags);
X }
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/sparc/kernel/time.c linux/arch/sparc/kernel/time.c
--- v2.2.0-pre8/linux/arch/sparc/kernel/time.c	Mon Oct  5 13:13:37 1998
+++ linux/arch/sparc/kernel/time.c	Tue Jan 19 10:19:52 1999
@@ -11,6 +11,9 @@
X  * Support for MicroSPARC-IIep, PCI CPU.
X  *
X  * This file handles the Sparc specific time handling details.
+ *
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
X  */
X #include <linux/config.h>
X #include <linux/errno.h>
@@ -89,9 +92,10 @@
X 	do_timer(regs);
X 
X 	/* Determine when to update the Mostek clock. */
-	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 500000 - (tick >> 1) &&
-	    xtime.tv_usec < 500000 + (tick >> 1)) {
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
X 	  if (set_rtc_mmss(xtime.tv_sec) == 0)
X 	    last_rtc_update = xtime.tv_sec;
X 	  else
@@ -495,12 +499,18 @@
X 	}
X #endif
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = 0x70000000;
-	time_esterror = 0x70000000;
+	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;
X 	sti();
X }
X 
+/*
+ * BUG: This routine does not handle hour overflow properly; it just
+ *      sets the minutes. Usually you won't notice until after reboot!
+ */
X static int set_rtc_mmss(unsigned long nowtime)
X {
X 	int real_seconds, real_minutes, mostek_minutes;
@@ -531,9 +541,13 @@
X 				iregs->clk.int_sec=real_seconds;
X 				iregs->clk.int_min=real_minutes;
X 				intersil_start(iregs);
-			} else 
+			} else {
+				printk(KERN_WARNING
+			       "set_rtc_mmss: can't update from %d to %d\n",
+				       cmos_minutes, real_minutes);
X 				return -1;
-
+			}
+			
X 			return 0;
X 		}
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/sparc/mm/srmmu.c linux/arch/sparc/mm/srmmu.c
--- v2.2.0-pre8/linux/arch/sparc/mm/srmmu.c	Mon Oct  5 13:13:37 1998
+++ linux/arch/sparc/mm/srmmu.c	Wed Jan 20 13:35:46 1999
@@ -470,7 +470,7 @@
X 		(unsigned int)ret->pprev_hash = mask & ~tmp;
X 		if (!(mask & ~tmp))
X 			pte_quicklist = (unsigned long *)ret->next_hash;
-		ret = (struct page *)(PAGE_OFFSET + (ret->map_nr << PAGE_SHIFT) + off);
+		ret = (struct page *)(page_address(ret) + off);
X 		pgtable_cache_size--;
X 	}
X 	spin_unlock(&pte_spinlock);
@@ -508,7 +508,7 @@
X 		(unsigned int)ret->pprev_hash = mask & ~tmp;
X 		if (!(mask & ~tmp))
X 			pgd_quicklist = (unsigned long *)ret->next_hash;
-		ret = (struct page *)(PAGE_OFFSET + (ret->map_nr << PAGE_SHIFT) + off);
+		ret = (struct page *)(page_address(ret) + off);
X 		pgd_cache_size--;
X 	}
X 	spin_unlock(&pgd_spinlock);
@@ -682,7 +682,7 @@
X 	spin_lock(&pgd_spinlock);
X 	address >>= SRMMU_PGDIR_SHIFT;
X 	for (page = (struct page *)pgd_quicklist; page; page = page->next_hash) {
-		pgd_t *pgd = (pgd_t *)(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+		pgd_t *pgd = (pgd_t *)page_address(page);
X 		unsigned int mask = (unsigned int)page->pprev_hash;
X 		
X 		if (mask & 1)
@@ -2817,7 +2817,7 @@
X 				page->next_hash = NULL;
X 				page->pprev_hash = NULL;
X 				pgtable_cache_size -= 16;
-				free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+				__free_page(page);
X 				freed++;
X 				if (page2)
X 					page = page2->next_hash;
@@ -2843,7 +2843,7 @@
X 				page->next_hash = NULL;
X 				page->pprev_hash = NULL;
X 				pgd_cache_size -= 4;
-				free_page(PAGE_OFFSET + (page->map_nr << PAGE_SHIFT));
+				__free_page(page);
X 				freed++;
X 				if (page2)
X 					page = page2->next_hash;
diff -u --recursive --new-file v2.2.0-pre8/linux/arch/sparc64/kernel/time.c linux/arch/sparc64/kernel/time.c
--- v2.2.0-pre8/linux/arch/sparc64/kernel/time.c	Mon Oct  5 13:13:38 1998
+++ linux/arch/sparc64/kernel/time.c	Tue Jan 19 10:19:54 1999
@@ -53,9 +53,10 @@
X 	static long last_rtc_update=0;
X 
X 	/* Determine when to update the Mostek clock. */
-	if (time_state != TIME_BAD && xtime.tv_sec > last_rtc_update + 660 &&
-	    xtime.tv_usec > 500000 - (tick >> 1) &&
-	    xtime.tv_usec < 500000 + (tick >> 1)) {
+	if ((time_status & STA_UNSYNC) == 0 &&
+	    xtime.tv_sec > last_rtc_update + 660 &&
+	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
+	    xtime.tv_usec <= 500000 + ((unsigned) tick) / 2) {
X 		if (set_rtc_mmss(xtime.tv_sec) == 0)
X 			last_rtc_update = xtime.tv_sec;
X 		else
@@ -458,10 +459,11 @@
X 	}
X 
X 	xtime = *tv;
-	time_state = TIME_BAD;
-	time_maxerror = 0x70000000;
-	time_esterror = 0x70000000;
-
+	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;
X 	sti();
X }
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/block/ide-cd.c linux/drivers/block/ide-cd.c
--- v2.2.0-pre8/linux/drivers/block/ide-cd.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/ide-cd.c	Tue Jan 19 11:10:07 1999
@@ -227,9 +227,12 @@
X  *                        "Ville Hallik" <ville....@mail.ee>.
X  *                      - other minor stuff.
X  *
+ * 4.52  Jan 19, 1999  -- Jens Axboe <ax...@image.dk>
+ *                      - Detect DVD-ROM/RAM drives
+ *
X  *************************************************************************/
X 
-#define IDECD_VERSION "4.51"
+#define IDECD_VERSION "4.52"
X 
X #include <linux/module.h>
X #include <linux/types.h>
@@ -2857,6 +2860,14 @@
X 		CDROM_CONFIG_FLAGS (drive)->cd_r = 1;
X 	if (buf.cap.cd_rw_write)
X 		CDROM_CONFIG_FLAGS (drive)->cd_rw = 1;
+	if (buf.cap.test_write)
+		CDROM_CONFIG_FLAGS (drive)->test_write = 1;
+	if (buf.cap.dvd_ram_read || buf.cap.dvd_r_read || buf.cap.dvd_rom)
+		CDROM_CONFIG_FLAGS (drive)->dvd = 1;
+	if (buf.cap.dvd_ram_write)
+		CDROM_CONFIG_FLAGS (drive)->dvd_r = 1;
+	if (buf.cap.dvd_r_write)
+		CDROM_CONFIG_FLAGS (drive)->dvd_rw = 1;
X 
X #if ! STANDARD_ATAPI
X 	if (CDROM_STATE_FLAGS (drive)->sanyo_slot > 0) {
@@ -2892,18 +2903,26 @@
X 			(ntohs(buf.cap.maxspeed) + (176/2)) / 176;
X 	}
X 
-        printk ("%s: ATAPI %dX CDROM", 
-        	drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed);
+	printk ("%s: ATAPI %dX %s", 
+        	drive->name, CDROM_CONFIG_FLAGS (drive)->max_speed,
+		(CDROM_CONFIG_FLAGS (drive)->dvd) ? "DVD-ROM" : "CD-ROM");
+
+	if (CDROM_CONFIG_FLAGS (drive)->dvd_r|CDROM_CONFIG_FLAGS (drive)->dvd_rw)
+        	printk (" DVD%s%s", 
+        	(CDROM_CONFIG_FLAGS (drive)->dvd_r)? "-RAM" : "", 
+        	(CDROM_CONFIG_FLAGS (drive)->dvd_rw)? "/RW" : "");
+
X         if (CDROM_CONFIG_FLAGS (drive)->cd_r|CDROM_CONFIG_FLAGS (drive)->cd_rw) 
X         	printk (" CD%s%s", 
X         	(CDROM_CONFIG_FLAGS (drive)->cd_r)? "-R" : "", 
X         	(CDROM_CONFIG_FLAGS (drive)->cd_rw)? "/RW" : "");
+
X         if (CDROM_CONFIG_FLAGS (drive)->is_changer) 
X         	printk (" changer w/%d slots", nslots);
X         else 	
X         	printk (" drive");
-	printk (", %dkB Cache\n", 
-        	ntohs(buf.cap.buffer_size) );
+
+	printk (", %dkB Cache\n", ntohs(buf.cap.buffer_size));
X 
X 	return nslots;
X }
@@ -2954,6 +2973,10 @@
X 	CDROM_CONFIG_FLAGS (drive)->is_changer = 0;
X 	CDROM_CONFIG_FLAGS (drive)->cd_r = 0;
X 	CDROM_CONFIG_FLAGS (drive)->cd_rw = 0;
+	CDROM_CONFIG_FLAGS (drive)->test_write = 0;
+	CDROM_CONFIG_FLAGS (drive)->dvd = 0;
+	CDROM_CONFIG_FLAGS (drive)->dvd_r = 0;
+	CDROM_CONFIG_FLAGS (drive)->dvd_rw = 0;
X 	CDROM_CONFIG_FLAGS (drive)->no_eject = 1;
X 	CDROM_CONFIG_FLAGS (drive)->supp_disc_present = 0;
X 	
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/block/ide-cd.h linux/drivers/block/ide-cd.h
--- v2.2.0-pre8/linux/drivers/block/ide-cd.h	Tue Jan 19 11:32:51 1999
+++ linux/drivers/block/ide-cd.h	Wed Jan 20 16:21:45 1999
@@ -128,6 +128,10 @@
X 	__u8 is_changer       : 1; /* Drive is a changer. */
X 	__u8 cd_r             : 1; /* Drive can write to CD-R media . */
X 	__u8 cd_rw            : 1; /* Drive can write to CD-R/W media . */
+	__u8 dvd              : 1; /* Drive is a DVD-ROM */
+	__u8 dvd_r            : 1; /* Drive can write DVD-RAM */
+	__u8 dvd_rw           : 1; /* Drive can write DVD-R/W */
+	__u8 test_write       : 1; /* Drive can fake writes */
X 	__u8 supp_disc_present: 1; /* Changer can report exact contents
X 				      of slots. */
X 	__u8 limit_nframes    : 1; /* Drive does not provide data in
@@ -294,7 +298,13 @@
X 	byte     page_length;
X 
X #if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved2           : 5;
+	__u8 reserved2           : 2;
+	/* Drive supports reading of DVD-RAM discs */
+	__u8 dvd_ram_read        : 1;
+	/* Drive supports reading of DVD-R discs */
+	__u8 dvd_r_read          : 1;
+	/* Drive supports reading of DVD-ROM discs */
+	__u8 dvd_rom             : 1;
X 	/* Drive supports reading CD-R discs with addressing method 2 */
X 	__u8 method2             : 1; /* reserved in 1.2 */
X 	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
@@ -303,28 +313,48 @@
X 	__u8 cd_r_read           : 1; /* reserved in 1.2 */
X #elif defined(__LITTLE_ENDIAN_BITFIELD)
X 	/* Drive supports read from CD-R discs (orange book, part II) */
-        __u8 cd_r_read           : 1; /* reserved in 1.2 */
+	__u8 cd_r_read           : 1; /* reserved in 1.2 */
X 	/* Drive can read from CD-R/W (CD-E) discs (orange book, part III) */
-        __u8 cd_rw_read          : 1; /* reserved in 1.2 */
+	__u8 cd_rw_read          : 1; /* reserved in 1.2 */
X 	/* Drive supports reading CD-R discs with addressing method 2 */
-	__u8 reserved2		 : 5;
+	__u8 method2             : 1;
+	/* Drive supports reading of DVD-ROM discs */
+	__u8 dvd_rom             : 1;
+	/* Drive supports reading of DVD-R discs */
+	__u8 dvd_r_read          : 1;
+	/* Drive supports reading of DVD-RAM discs */
+	__u8 dvd_ram_read        : 1;
+	__u8 reserved2		 : 2;
X #else
X #error "Please fix <asm/byteorder.h>"
X #endif
X 
X #if defined(__BIG_ENDIAN_BITFIELD)
-	__u8 reserved3           : 6;
+	__u8 reserved3           : 2;
+	/* Drive can fake writes */
+	__u8 test_write          : 1;
+	__u8 reserved3a          : 1;
+	/* Drive can write DVD-R discs */
+	__u8 dvd_r_write         : 1;
+	/* Drive can write DVD-RAM discs */
+	__u8 dvd_ram_write       : 1;
X 	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
X 	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
X 	/* Drive supports write to CD-R discs (orange book, part II) */
X 	__u8 cd_r_write          : 1; /* reserved in 1.2 */
X #elif defined(__LITTLE_ENDIAN_BITFIELD)
-
X 	/* Drive can write to CD-R discs (orange book, part II) */
-        __u8 cd_r_write          : 1; /* reserved in 1.2 */
+	__u8 cd_r_write          : 1; /* reserved in 1.2 */
X 	/* Drive can write to CD-R/W (CD-E) discs (orange book, part III) */
-        __u8 cd_rw_write	 : 1; /* reserved in 1.2 */
-	__u8 reserved3           : 6;
+	__u8 cd_rw_write	 : 1; /* reserved in 1.2 */
+	/* Drive can write DVD-RAM discs */
+	__u8 dvd_ram_write       : 1;
+	/* Drive can write DVD-R discs */
+	__u8 dvd_r_write         : 1;
+	__u8 reserved3a          : 1;
+	/* Drive can fake writes */
+	__u8 test_write          : 1;
+	__u8 reserved3           : 2;
X #else
X #error "Please fix <asm/byteorder.h>"
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/cdrom/mcdx.h linux/drivers/cdrom/mcdx.h
--- v2.2.0-pre8/linux/drivers/cdrom/mcdx.h	Tue Dec  2 11:41:44 1997
+++ linux/drivers/cdrom/mcdx.h	Wed Jan 20 10:20:16 1999
@@ -77,7 +77,6 @@
X /* *** make the following line uncommented, if you're sure,
X  * *** all configuration is done */
X /* #define I_WAS_HERE */
-#define I_WAS_HERE   /* delete this line, it's for heiko only */
X 
X /*	The name of the device */
X #define MCDX "mcdx"	
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/char/console.c linux/drivers/char/console.c
--- v2.2.0-pre8/linux/drivers/char/console.c	Fri Jan  8 22:36:05 1999
+++ linux/drivers/char/console.c	Tue Jan 19 10:10:23 1999
@@ -1221,6 +1221,8 @@
X 			break;
X 		case 8:	/* store colors as defaults */
X 			def_color = attr;
+			if (hi_font_mask == 0x100)
+				def_color >>= 1;
X 			default_attr(currcons);
X 			update_attr(currcons);
X 			break;
@@ -1894,7 +1896,7 @@
X 			if (decim)
X 				insert_char(currcons, 1);
X 			scr_writew(himask ?
-				     ((attr & ~himask) << 8) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
+				     ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
X 				     (attr << 8) + tc,
X 				   (u16 *) pos);
X 			if (DO_UPDATE && draw_x < 0) {
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/char/cyclades.c linux/drivers/char/cyclades.c
--- v2.2.0-pre8/linux/drivers/char/cyclades.c	Thu Jan  7 15:11:36 1999
+++ linux/drivers/char/cyclades.c	Wed Jan 20 13:26:20 1999
@@ -1,7 +1,7 @@
X #define BLOCKMOVE
X #define	Z_WAKE
X static char rcsid[] =
-"$Revision: 2.2.1.9 $$Date: 1998/12/30 18:18:30 $";
+"$Revision: 2.2.1.10 $$Date: 1999/01/20 16:14:29 $";
X 
X /*
X  *  linux/drivers/char/cyclades.c
@@ -31,6 +31,10 @@
X  *   void cleanup_module(void);
X  *
X  * $Log: cyclades.c,v $
+ * Revision 2.2.1.10 1999/01/20 16:14:29 ivan
+ * Removed all unnecessary page-alignement operations in ioremap calls
+ * (ioremap is currently safe for these operations).
+ *
X  * Revision 2.2.1.9  1998/12/30 18:18:30 ivan
X  * Changed access to PLX PCI bridge registers from I/O to MMIO, in 
X  * order to make PLX9050-based boards work with certain motherboards.
@@ -4461,8 +4465,7 @@
X                 /* probe for CD1400... */
X 
X #if !defined(__alpha__)
-		cy_isa_address = ioremap((unsigned int)cy_isa_address,
-                                                       CyISA_Ywin);
+		cy_isa_address = ioremap((ulong)cy_isa_address, CyISA_Ywin);
X #endif
X                 cy_isa_nchan = CyPORTS_PER_CHIP * 
X                      cyy_init_card(cy_isa_address,0);
@@ -4583,11 +4586,11 @@
X 		pdev->bus->number, pdev->devfn);
X             printk("rev_id=%d) IRQ%d\n",
X 		cyy_rev_id, (int)cy_pci_irq);
-            printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
-		(ulong)cy_pci_addr2, (ulong)cy_pci_addr1);
+            printk("Cyclom-Y/PCI:found  winaddr=0x%lx ctladdr=0x%lx\n",
+		(ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
X #endif
-                cy_pci_addr0  &= PCI_BASE_ADDRESS_MEM_MASK;
-                cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
+		cy_pci_addr0  &= PCI_BASE_ADDRESS_MEM_MASK;
+		cy_pci_addr2  &= PCI_BASE_ADDRESS_MEM_MASK;
X 
X #if defined(__alpha__)
X                 if (device_id  == PCI_DEVICE_ID_CYCLOM_Y_Lo) { /* below 1M? */
@@ -4595,21 +4598,21 @@
X 			pdev->bus->number, pdev->devfn);
X 		    printk("rev_id=%d) IRQ%d\n",
X 		        cyy_rev_id, (int)cy_pci_irq);
-                    printk("Cyclom-Y/PCI:found  winaddr=0x%lx ioaddr=0x%lx\n",
-		        (ulong)cy_pci_addr2, (ulong)cy_pci_addr1);
+                    printk("Cyclom-Y/PCI:found  winaddr=0x%lx ctladdr=0x%lx\n",
+		        (ulong)cy_pci_addr2, (ulong)cy_pci_addr0);
X 	            printk("Cyclom-Y/PCI not supported for low addresses in "
X                            "Alpha systems.\n");
X 		    i--;
X 	            continue;
X                 }
X #else
-		    cy_pci_addr0  = (ulong) ioremap(cy_pci_addr0, CyPCI_Yctl);
-		    cy_pci_addr2 = (ulong) ioremap(cy_pci_addr2, CyPCI_Ywin);
+		    cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Yctl);
+		    cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ywin);
X #endif
X 
X #ifdef CY_PCI_DEBUG
-            printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ioaddr=0x%lx\n",
-		(u_long)cy_pci_addr2, (u_long)cy_pci_addr1);
+            printk("Cyclom-Y/PCI: relocate winaddr=0x%lx ctladdr=0x%lx\n",
+		(u_long)cy_pci_addr2, (u_long)cy_pci_addr0);
X #endif
X                 cy_pci_nchan = (unsigned short)(CyPORTS_PER_CHIP * 
X                        cyy_init_card((volatile ucchar *)cy_pci_addr2, 1));
@@ -4708,20 +4711,14 @@
X #endif
X                 cy_pci_addr0 &= PCI_BASE_ADDRESS_MEM_MASK;
X #if !defined(__alpha__)
-                cy_pci_addr0 = (unsigned int) ioremap(
-                               cy_pci_addr0 & PAGE_MASK,
-                               PAGE_ALIGN(CyPCI_Zctl))
-                               + (cy_pci_addr0 & (PAGE_SIZE-1));
+                cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl);
X #endif
X 		mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) 
X 			   cy_pci_addr0)->mail_box_0);
X                 cy_pci_addr2 &= PCI_BASE_ADDRESS_MEM_MASK;
X 		if (mailbox == ZE_V1) {
X #if !defined(__alpha__)
-               	    cy_pci_addr2 = (unsigned int) ioremap(
-	            	cy_pci_addr2 & PAGE_MASK,
-	            	PAGE_ALIGN(CyPCI_Ze_win))
-	            	+ (cy_pci_addr2 & (PAGE_SIZE-1));
+               	    cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ze_win);
X #endif
X 		    if (ZeIndex == NR_CARDS) {
X 			printk("Cyclades-Ze/PCI found at 0x%lx ",
@@ -4737,10 +4734,7 @@
X 		    continue;
X 		} else {
X #if !defined(__alpha__)
-                    cy_pci_addr2 = (unsigned int) ioremap(
-			cy_pci_addr2 & PAGE_MASK,
-			PAGE_ALIGN(CyPCI_Zwin))
-			+ (cy_pci_addr2 & (PAGE_SIZE-1));
+                    cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Zwin);
X #endif
X 		}
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/char/mem.c linux/drivers/char/mem.c
--- v2.2.0-pre8/linux/drivers/char/mem.c	Thu Jan  7 15:11:36 1999
+++ linux/drivers/char/mem.c	Wed Jan 20 10:24:57 1999
@@ -4,20 +4,13 @@
X  *  Copyright (C) 1991, 1992  Linus Torvalds
X  */
X 
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/major.h>
-#include <linux/tty.h>
+#include <linux/mm.h>
X #include <linux/miscdevice.h>
X #include <linux/tpqic02.h>
X #include <linux/ftape.h>
X #include <linux/malloc.h>
X #include <linux/vmalloc.h>
X #include <linux/mman.h>
-#include <linux/mm.h>
X #include <linux/random.h>
X #include <linux/init.h>
X #include <linux/joystick.h>
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/char/pc_keyb.c linux/drivers/char/pc_keyb.c
--- v2.2.0-pre8/linux/drivers/char/pc_keyb.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/pc_keyb.c	Wed Jan 20 13:25:29 1999
@@ -744,7 +744,7 @@
X 
X 	if (status & KBD_STAT_OBF) {
X 		val = inb(KBD_DATA_REG);
-		if (val == 0x5a && (status & KBD_STAT_MOUSE_OBF)) {
+		if (status & KBD_STAT_MOUSE_OBF) {
X 			printk(KERN_INFO "Detected PS/2 Mouse Port.\n");
X 			retval = 1;
X 		}
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/char/tty_ioctl.c linux/drivers/char/tty_ioctl.c
--- v2.2.0-pre8/linux/drivers/char/tty_ioctl.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/char/tty_ioctl.c	Tue Jan 19 10:12:05 1999
@@ -209,11 +209,12 @@
X {
X 	int flags = 0;
X 
-	if (!(tty->termios->c_lflag & ICANON))
+	if (!(tty->termios->c_lflag & ICANON)) {
X 		if (tty->termios->c_lflag & ISIG)
X 			flags |= 0x02;		/* cbreak */
X 		else
X 			flags |= 0x20;		/* raw */
+	}
X 	if (tty->termios->c_lflag & ECHO)
X 		flags |= 0x08;			/* echo */
X 	if (tty->termios->c_oflag & OPOST)
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/char/videodev.c linux/drivers/char/videodev.c
--- v2.2.0-pre8/linux/drivers/char/videodev.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/char/videodev.c	Tue Jan 19 13:49:12 1999
@@ -15,6 +15,7 @@
X  */
X 
X #include <linux/config.h>
+#include <linux/version.h>
X #include <linux/module.h>
X #include <linux/types.h>
X #include <linux/kernel.h>
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/isdn/isdn_common.c linux/drivers/isdn/isdn_common.c
--- v2.2.0-pre8/linux/drivers/isdn/isdn_common.c	Thu Aug 27 19:56:29 1998
+++ linux/drivers/isdn/isdn_common.c	Tue Jan 19 11:06:52 1999
@@ -20,6 +20,10 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
X  * $Log: isdn_common.c,v $
X  * Revision 1.55  1998/02/23 23:35:32  fritz
X  * Eliminated some compiler warnings.
@@ -770,9 +774,18 @@
X /*
X  * isdn_readbchan() tries to get data from the read-queue.
X  * It MUST be called with interrupts off.
+ *
+ * Be aware that this is not an atomic operation when sleep != 0, even though 
+ * interrupts are turned off! Well, like that we are currently only called
+ * on behalf of a read system call on raw device files (which are documented
+ * to be dangerous and for for debugging purpose only). The inode semaphore
+ * takes care that this is not called for the same minor device number while
+ * we are sleeping, but access is not serialized against simultaneous read()
+ * from the corresponding ttyI device. Can other ugly events, like changes
+ * of the mapping (di,ch)<->minor, happen during the sleep? --he 
X  */
X int
-isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, int user)
+isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, struct wait_queue **sleep)
X {
X 	int left;
X 	int count;
@@ -785,8 +798,8 @@
X 	if (!dev->drv[di])
X 		return 0;
X 	if (skb_queue_empty(&dev->drv[di]->rpqueue[channel])) {
-		if (user)
-			interruptible_sleep_on(&dev->drv[di]->rcv_waitq[channel]);
+		if (sleep)
+			interruptible_sleep_on(sleep);
X 		else
X 			return 0;
X 	}
@@ -808,16 +821,10 @@
X 			count_pull = count_put = 0;
X 			while ((count_pull < skb->len) && (left-- > 0)) {
X 				if (dev->drv[di]->DLEflag & DLEmask) {
-					if (user)
-						put_user(DLE, cp++);
-					else
-						*cp++ = DLE;
+					*cp++ = DLE;
X 					dev->drv[di]->DLEflag &= ~DLEmask;
X 				} else {
-					if (user)
-						put_user(*p, cp++);
-					else
-						*cp++ = *p;
+					*cp++ = *p;
X 					if (*p == DLE) {
X 						dev->drv[di]->DLEflag |= DLEmask;
X 						(ISDN_AUDIO_SKB_DLECOUNT(skb))--;
@@ -838,10 +845,7 @@
X 				dflag = 0;
X 			}
X 			count_put = count_pull;
-			if (user)
-				copy_to_user(cp, skb->data, count_put);
-			else
-				memcpy(cp, skb->data, count_put);
+			memcpy(cp, skb->data, count_put);
X 			cp += count_put;
X 			left -= count_put;
X #ifdef CONFIG_ISDN_AUDIO
@@ -966,12 +970,12 @@
X 	ulong flags;
X 	int drvidx;
X 	int chidx;
+	char *p;
X 
X 	if (off != &file->f_pos)
X 		return -ESPIPE;
X 
X 	if (minor == ISDN_MINOR_STATUS) {
-		char *p;
X 		if (!file->private_data) {
X 			if (file->f_flags & O_NONBLOCK)
X 				return -EAGAIN;
@@ -996,11 +1000,15 @@
X 		if (!dev->drv[drvidx]->running)
X 			return -ENODEV;
X 		chidx = isdn_minor2chan(minor);
+		if(  ! (p = kmalloc(count,GFP_KERNEL))  ) return -ENOMEM;
X 		save_flags(flags);
X 		cli();
-		len = isdn_readbchan(drvidx, chidx, buf, 0, count, 1);
+		len = isdn_readbchan(drvidx, chidx, p, 0, count,
+				     &dev->drv[drvidx]->rcv_waitq[chidx]);
X 		*off += len;
X 		restore_flags(flags);
+		if( copy_to_user(buf,p,len) ) len = -EFAULT;
+		kfree(p);
X 		return len;
X 	}
X 	if (minor <= ISDN_MINOR_CTRLMAX) {
@@ -1124,6 +1132,11 @@
X 	return POLLERR;
X }
X 
+/* 
+ * This accesses user space with interrupts off, but is not needed by
+ * any of the isdn4k-util programs anyway. Thus, in contrast to your
+ * first impression after looking at the code, fixing is trival!*/
+#if 0 
X static int
X isdn_set_allcfg(char *src)
X {
@@ -1135,8 +1148,7 @@
X 
X 	if ((ret = isdn_net_rmall()))
X 		return ret;
-	if ((ret = copy_from_user((char *) &i, src, sizeof(int))))
-		 return ret;
+	if (copy_from_user((char *) &i, src, sizeof(int))) return -EFAULT;
X 	save_flags(flags);
X 	cli();
X 	src += sizeof(int);
@@ -1144,9 +1156,9 @@
X 		int phone_len;
X 		int out_flag;
X 
-		if ((ret = copy_from_user((char *) &cfg, src, sizeof(cfg)))) {
+		if (copy_from_user((char *) &cfg, src, sizeof(cfg))) {
X 			restore_flags(flags);
-			return ret;
+			return -EFAULT;
X 		}
X 		src += sizeof(cfg);
X 		if (!isdn_net_new(cfg.name, NULL)) {
@@ -1256,6 +1268,7 @@
X 	restore_flags(flags);
X 	return 0;
X }
+#endif
X 
X static int
X isdn_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
@@ -1319,59 +1332,83 @@
X 		return 0;
X 	}
X 	if (minor <= ISDN_MINOR_CTRLMAX) {
+/*
+ * isdn net devices manage lots of configuration variables as linked lists.
+ * Those lists must only be manipulated from user space. Some of the ioctl's
+ * service routines access user space and are not atomic. Therefor, ioctl's
+ * manipulating the lists and ioctl's sleeping while accessing the lists
+ * are serialized by means of a semaphore.
+ */
X 		switch (cmd) {
X #ifdef CONFIG_NETDEVICES
X 			case IIOCNETAIF:
X 				/* Add a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
-						return ret;
+					if (copy_from_user(name, (char *) arg, sizeof(name)))
+						return -EFAULT;
X 					s = name;
-				} else
+				} else {
X 					s = NULL;
+				}
+				ret = down_interruptible(&dev->sem);
+				if( ret ) return ret;
X 				if ((s = isdn_net_new(s, NULL))) {
-					if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
-						return ret;
-					return 0;
+					if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+						ret = -EFAULT;
+					} else {
+						ret = 0;
+					}
X 				} else
-					return -ENODEV;
+					ret = -ENODEV;
+				up(&dev->sem);
+				return ret;
X 			case IIOCNETASL:
X 				/* Add a slave to a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user(bname, (char *) arg, sizeof(bname) - 1)))
-						return ret;
+					if (copy_from_user(bname, (char *) arg, sizeof(bname) - 1))
+						return -EFAULT;
X 				} else
X 					return -EINVAL;
+				ret = down_interruptible(&dev->sem);
+				if( ret ) return ret;
X 				if ((s = isdn_net_newslave(bname))) {
-					if ((ret = copy_to_user((char *) arg, s, strlen(s) + 1)))
-						return ret;
-					return 0;
+					if (copy_to_user((char *) arg, s, strlen(s) + 1)){
+						ret = -EFAULT;
+					} else {
+						ret = 0;
+					}
X 				} else
-					return -ENODEV;
+					ret = -ENODEV;
+				up(&dev->sem);
+				return ret;
X 			case IIOCNETDIF:
X 				/* Delete a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
-						return ret;
-					return isdn_net_rm(name);
+					if (copy_from_user(name, (char *) arg, sizeof(name)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_rm(name);
+					up(&dev->sem);
+					return ret;
X 				} else
X 					return -EINVAL;
X 			case IIOCNETSCF:
X 				/* Set configurable parameters of a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
-						return ret;
+					if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+						return -EFAULT;
X 					return isdn_net_setcfg(&cfg);
X 				} else
X 					return -EINVAL;
X 			case IIOCNETGCF:
X 				/* Get configurable parameters of a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg))))
-						return ret;
+					if (copy_from_user((char *) &cfg, (char *) arg, sizeof(cfg)))
+						return -EFAULT;
X 					if (!(ret = isdn_net_getcfg(&cfg))) {
-						if ((ret = copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg))))
-							return ret;
+						if (copy_to_user((char *) arg, (char *) &cfg, sizeof(cfg)))
+							return -EFAULT;
X 					}
X 					return ret;
X 				} else
@@ -1379,32 +1416,44 @@
X 			case IIOCNETANM:
X 				/* Add a phone-number to a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
-						return ret;
-					return isdn_net_addphone(&phone);
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_addphone(&phone);
+					up(&dev->sem);
+					return ret;
X 				} else
X 					return -EINVAL;
X 			case IIOCNETGNM:
X 				/* Get list of phone-numbers of a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
-						return ret;
-					return isdn_net_getphones(&phone, (char *) arg);
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_getphones(&phone, (char *) arg);
+					up(&dev->sem);
+					return ret;
X 				} else
X 					return -EINVAL;
X 			case IIOCNETDNM:
X 				/* Delete a phone-number of a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user((char *) &phone, (char *) arg, sizeof(phone))))
-						return ret;
-					return isdn_net_delphone(&phone);
+					if (copy_from_user((char *) &phone, (char *) arg, sizeof(phone)))
+						return -EFAULT;
+					ret = down_interruptible(&dev->sem);
+					if( ret ) return ret;
+					ret = isdn_net_delphone(&phone);
+					up(&dev->sem);
+					return ret;
X 				} else
X 					return -EINVAL;
X 			case IIOCNETDIL:
X 				/* Force dialing of a network-interface */
X 				if (arg) {
-					if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
-						return ret;
+					if (copy_from_user(name, (char *) arg, sizeof(name)))
+						return -EFAULT;
X 					return isdn_net_force_dial(name);
X 				} else
X 					return -EINVAL;
@@ -1412,22 +1461,22 @@
X 			case IIOCNETALN:
X 				if (!arg)
X 					return -EINVAL;
-				if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
-					return ret;
+				if (copy_from_user(name, (char *) arg, sizeof(name)))
+					return -EFAULT;
X 				return isdn_ppp_dial_slave(name);
X 			case IIOCNETDLN:
X 				if (!arg)
X 					return -EINVAL;
-				if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
-					return ret;
+				if (copy_from_user(name, (char *) arg, sizeof(name)))
+					return -EFAULT;
X 				return isdn_ppp_hangup_slave(name);
X #endif
X 			case IIOCNETHUP:
X 				/* Force hangup of a network-interface */
X 				if (!arg)
X 					return -EINVAL;
-				if ((ret = copy_from_user(name, (char *) arg, sizeof(name))))
-					return ret;
+				if (copy_from_user(name, (char *) arg, sizeof(name)))
+					return -EFAULT;
X 				return isdn_net_force_hangup(name);
X 				break;
X #endif                          /* CONFIG_NETDEVICES */
@@ -1448,9 +1497,9 @@
X 				if (arg) {
X 					int i;
X 					char *p;
-					if ((ret = copy_from_user((char *) &iocts, (char *) arg,
-					     sizeof(isdn_ioctl_struct))))
-						return ret;
+					if (copy_from_user((char *) &iocts, (char *) arg,
+					     sizeof(isdn_ioctl_struct)))
+						return -EFAULT;
X 					if (strlen(iocts.drvid)) {
X 						if ((p = strchr(iocts.drvid, ',')))
X 							*p = 0;
@@ -1466,6 +1515,7 @@
X 					return -ENODEV;
X 				dev->drv[drvidx]->reject_bus = iocts.arg;
X 				return 0;
+#if 0
X 			case IIOCGETSET:
X 				/* Get complete setup (all network-interfaces and profile-
X 				   settings of all tty-devices */
@@ -1482,6 +1532,7 @@
X 				else
X 					return -EINVAL;
X 				break;
+#endif
X 			case IIOCSIGPRF:
X 				dev->profd = current;
X 				return 0;
@@ -1522,12 +1573,12 @@
X 						return ret;
X 
X 					for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
-						if ((ret = copy_from_user(dev->mdm.info[i].emu.profile, p,
-						     ISDN_MODEM_ANZREG)))
-							return ret;
+						if (copy_from_user(dev->mdm.info[i].emu.profile, p,
+						     ISDN_MODEM_ANZREG))
+							return -EFAULT;
X 						p += ISDN_MODEM_ANZREG;
-						if ((ret = copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN)))
-							return ret;
+						if (copy_from_user(dev->mdm.info[i].emu.pmsn, p, ISDN_MSNLEN))
+							return -EFAULT;
X 						p += ISDN_MSNLEN;
X 					}
X 					return 0;
@@ -1539,10 +1590,10 @@
X 				/* Set/Get MSN->EAZ-Mapping for a driver */
X 				if (arg) {
X 
-					if ((ret = copy_from_user((char *) &iocts,
+					if (copy_from_user((char *) &iocts,
X 							    (char *) arg,
-					     sizeof(isdn_ioctl_struct))))
-						return ret;
+					     sizeof(isdn_ioctl_struct)))
+						return -EFAULT;
X 					if (strlen(iocts.drvid)) {
X 						drvidx = -1;
X 						for (i = 0; i < ISDN_MAX_DRIVERS; i++)
@@ -1591,8 +1642,8 @@
X 								strlen(dev->drv[drvidx]->msn2eaz[i]) ?
X 								dev->drv[drvidx]->msn2eaz[i] : "-",
X 								(i < 9) ? "," : "\0");
-							if ((ret = copy_to_user(p, bname, strlen(bname) + 1)))
-								return ret;
+							if (copy_to_user(p, bname, strlen(bname) + 1))
+								return -EFAULT;
X 							p += strlen(bname);
X 						}
X 					}
@@ -1601,8 +1652,8 @@
X 					return -EINVAL;
X 			case IIOCDBGVAR:
X 				if (arg) {
-					if ((ret = copy_to_user((char *) arg, (char *) &dev, sizeof(ulong))))
-						return ret;
+					if (copy_to_user((char *) arg, (char *) &dev, sizeof(ulong)))
+						return -EFAULT;
X 					return 0;
X 				} else
X 					return -EINVAL;
@@ -1615,8 +1666,8 @@
X 				if (arg) {
X 					int i;
X 					char *p;
-					if ((ret = copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct))))
-						return ret;
+					if (copy_from_user((char *) &iocts, (char *) arg, sizeof(isdn_ioctl_struct)))
+						return -EFAULT;
X 					if (strlen(iocts.drvid)) {
X 						if ((p = strchr(iocts.drvid, ',')))
X 							*p = 0;
@@ -1639,7 +1690,7 @@
X 					memcpy(c.parm.num, (char *) &iocts.arg, sizeof(ulong));
X 					ret = isdn_command(&c);
X 					memcpy((char *) &iocts.arg, c.parm.num, sizeof(ulong));
-					if ((copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct))))
+					if (copy_to_user((char *) arg, &iocts, sizeof(isdn_ioctl_struct)))
X 						return -EFAULT;
X 					return ret;
X 				} else
@@ -2164,6 +2215,7 @@
X 	memset((char *) dev, 0, sizeof(isdn_dev));
X 	init_timer(&dev->timer);
X 	dev->timer.function = isdn_timer_funct;
+	dev->sem = MUTEX;
X 	for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
X 		dev->drvmap[i] = -1;
X 		dev->chanmap[i] = -1;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/isdn/isdn_common.h linux/drivers/isdn/isdn_common.h
--- v2.2.0-pre8/linux/drivers/isdn/isdn_common.h	Wed Apr  1 20:11:51 1998
+++ linux/drivers/isdn/isdn_common.h	Tue Jan 19 11:06:52 1999
@@ -20,6 +20,10 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
X  * $Log: isdn_common.h,v $
X  * Revision 1.9  1998/02/20 17:19:01  fritz
X  * Added common stub for sending commands to lowlevel.
@@ -86,7 +90,7 @@
X extern void isdn_timer_ctrl(int tf, int onoff);
X extern void isdn_unexclusive_channel(int di, int ch);
X extern int isdn_getnum(char **);
-extern int isdn_readbchan(int, int, u_char *, u_char *, int, int);
+extern int isdn_readbchan(int, int, u_char *, u_char *, int, struct wait_queue**);
X extern int isdn_get_free_channel(int, int, int, int, int);
X extern int isdn_writebuf_skb_stub(int, int, int, struct sk_buff *);
X extern int register_isdn(isdn_if * i);
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/isdn/isdn_net.c linux/drivers/isdn/isdn_net.c
--- v2.2.0-pre8/linux/drivers/isdn/isdn_net.c	Mon Oct  5 13:13:39 1998
+++ linux/drivers/isdn/isdn_net.c	Tue Jan 19 11:06:52 1999
@@ -20,6 +20,10 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
X  * $Log: isdn_net.c,v $
X  * Revision 1.55  1998/02/23 19:38:22  fritz
X  * Corrected check for modified feature-flags.
@@ -243,7 +247,7 @@
X #include <linux/module.h>
X #include <linux/isdn.h>
X #include <net/arp.h>
-#include <net/icmp.h>
+#include <net/dst.h>
X #ifndef DEV_NUMBUFFS
X #include <net/pkt_sched.h>
X #endif
@@ -277,9 +281,18 @@
X static void
X isdn_net_unreachable(struct device *dev, struct sk_buff *skb, char *reason)
X {
-	printk(KERN_DEBUG "isdn_net: %s: %s, send ICMP\n",
-	       dev->name, reason);
-	icmp_send(skb, ICMP_DEST_UNREACH, ICMP_HOST_UNREACH, 0);
+
+	if(skb) {
+
+		u_short proto = ntohs(skb->protocol);
+
+		printk(KERN_DEBUG "isdn_net: %s: %s, signalling dst_link_failure %s\n",
+		       dev->name,
+		       (reason != NULL) ? reason : "unknown",
+		       (proto != ETH_P_IP) ? "Protocol != ETH_P_IP" : "");
+		
+		dst_link_failure(skb);
+	}
X }
X 
X static void
@@ -610,6 +623,13 @@
X 							
X 							if (!(isdn_net_xmit(&p->dev, lp, lp->first_skb)))
X 								lp->first_skb = NULL;
+						} else {
+							/*
+							 * dev.tbusy is usually cleared implicitly by isdn_net_xmit(,,lp->first_skb).
+							 * With an empty lp->first_skb, we need to do this ourselves
+							 */
+							lp->netdev->dev.tbusy = 0;
+							mark_bh(NET_BH);
X 						}
X 						return 1;
X 				}
@@ -2696,7 +2716,8 @@
X }
X 
X /*
- * Return a string of all phone-numbers of an interface.
+ * Copy a string of all phone-numbers of an interface to user space.
+ * This might sleep and must be called with the isdn semaphore down.
X  */
X int
X isdn_net_getphones(isdn_net_ioctl_phone * phone, char *phones)
@@ -2706,22 +2727,17 @@
X 	int more = 0;
X 	int count = 0;
X 	isdn_net_phone *n;
-	int flags;
-	int ret;
X 
X 	if (!p)
X 		return -ENODEV;
-	save_flags(flags);
-	cli();
X 	inout &= 1;
X 	for (n = p->local->phone[inout]; n; n = n->next) {
X 		if (more) {
X 			put_user(' ', phones++);
X 			count++;
X 		}
-		if ((ret = copy_to_user(phones, n->num, strlen(n->num) + 1))) {
-			restore_flags(flags);
-			return ret;
+		if (copy_to_user(phones, n->num, strlen(n->num) + 1)) {
+			return -EFAULT;
X 		}
X 		phones += strlen(n->num);
X 		count += strlen(n->num);
@@ -2729,7 +2745,6 @@
X 	}
X 	put_user(0, phones);
X 	count++;
-	restore_flags(flags);
X 	return count;
X }
X 
@@ -2760,6 +2775,7 @@
X 				else
X 					p->local->phone[inout] = n->next;
X 				kfree(n);
+				restore_flags(flags);
X 				return 0;
X 			}
X 			m = n;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/isdn/isdn_ppp.c linux/drivers/isdn/isdn_ppp.c
--- v2.2.0-pre8/linux/drivers/isdn/isdn_ppp.c	Wed Apr  1 20:11:51 1998
+++ linux/drivers/isdn/isdn_ppp.c	Tue Jan 19 11:06:52 1999
@@ -18,6 +18,10 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
X  *
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
X  * $Log: isdn_ppp.c,v $
X  * Revision 1.33  1998/02/20 17:11:54  fritz
X  * Changes for recent kernels.
@@ -500,11 +504,10 @@
X static int
X get_arg(void *b, void *val, int len)
X {
-	int r;
X 	if (len <= 0)
X 		len = sizeof(unsigned long);
-	if ((r = copy_from_user((void *) val, b, len)))
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 05'
echo 'File patch-2.2.0-pre9 is continued in part 06'
echo 06 > _shar_seq_.tmp
#!/bin/sh
# this is part 06 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 06; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
-		return r;
+	if (copy_from_user((void *) val, b, len))
+		return -EFAULT;
X 	return 0;
X }
X 
@@ -514,13 +517,12 @@
X static int
X set_arg(void *b, unsigned long val, void *str)
X {
-	int r;
X 	if (!str) {
-		if ((r = copy_to_user(b, (void *) &val, 4)))
-			return r;
+		if (copy_to_user(b, (void *) &val, 4))
+			return -EFAULT;
X 	} else {
-		if ((r = copy_to_user(b, str, val)))
-			return r;
+		if (copy_to_user(b, str, val))
+			return -EFAULT;
X 	}
X 	return 0;
X }
@@ -1851,13 +1853,14 @@
X 		}
X #endif
X 	}
-	return copy_to_user(res, &t, sizeof(struct ppp_stats));
+	if( copy_to_user(res, &t, sizeof(struct ppp_stats))) return -EFAULT;
+	return 0;
X }
X 
X int
X isdn_ppp_dev_ioctl(struct device *dev, struct ifreq *ifr, int cmd)
X {
-	int error;
+	int error=0;
X 	char *r;
X 	int len;
X 	isdn_net_local *lp = (isdn_net_local *) dev->priv;
@@ -1873,7 +1876,7 @@
X 		case SIOCGPPPVER:
X 			r = (char *) ifr->ifr_ifru.ifru_data;
X 			len = strlen(PPP_VERSION) + 1;
-			error = copy_to_user(r, PPP_VERSION, len);
+			if(copy_to_user(r, PPP_VERSION, len)) error = -EFAULT;
X 			break;
X 		case SIOCGPPPSTATS:
X 			error = isdn_ppp_dev_ioctl_stats(lp->ppp_slot, ifr, dev);
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/misc/parport_ieee1284.c linux/drivers/misc/parport_ieee1284.c
--- v2.2.0-pre8/linux/drivers/misc/parport_ieee1284.c	Sun Nov  8 14:02:59 1998
+++ linux/drivers/misc/parport_ieee1284.c	Wed Jan 20 13:29:18 1999
@@ -47,8 +47,12 @@
X  */
X int parport_ieee1284_nibble_mode_ok(struct parport *port, unsigned char mode) 
X {
+	/* make sure it's a valid state, set nStrobe & nAutoFeed high */
+	parport_write_control(port, (parport_read_control(port) \
+		& ~1 ) & ~2);
+	udelay(1);
X 	parport_write_data(port, mode);
-	udelay(500);
+	udelay(1);
X 	/* nSelectIn high, nAutoFd low */
X 	parport_write_control(port, (parport_read_control(port) & ~8) | 2);
X 	if (parport_wait_peripheral(port, 0x78, 0x38)) {
@@ -58,11 +62,12 @@
X 	}
X 	/* nStrobe low */
X 	parport_write_control(port, parport_read_control(port) | 1);
-	udelay(5);				     /* Strobe wait */
-	/* nStrobe high */
-	parport_write_control(port, parport_read_control(port) & ~1);
-	udelay(5);
-	/* nAutoFd low */
-	parport_write_control(port, parport_read_control(port) & ~2);
-	return (parport_wait_peripheral(port, 0x20, 0))?2:1;
+	udelay(1);				     /* Strobe wait */
+	/* nStrobe high, nAutoFeed low, last step before transferring 
+	 *  reverse data */
+	parport_write_control(port, (parport_read_control(port) \
+		& ~1) & ~2);
+	udelay(1);
+	/* Data available? */
+	return (parport_wait_peripheral(port, 0x20, 0))?1:2;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/3c59x.c linux/drivers/net/3c59x.c
--- v2.2.0-pre8/linux/drivers/net/3c59x.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/net/3c59x.c	Tue Jan 19 14:47:15 1999
@@ -1245,7 +1245,7 @@
X 			printk(KERN_DEBUG "%s: Media selection failed, now trying "
X 				   "%s port.\n",
X 				   dev->name, media_tbl[dev->if_port].name);
-		  next_tick = RUN_AT(media_tbl[dev->if_port].wait);
+		  next_tick = media_tbl[dev->if_port].wait;
X 		}
X 		outw((media_status & ~(Media_10TP|Media_SQE)) |
X 			 media_tbl[dev->if_port].media_bits, ioaddr + Wn4_Media);
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/Config.in linux/drivers/net/Config.in
--- v2.2.0-pre8/linux/drivers/net/Config.in	Tue Jan 19 11:32:51 1999
+++ linux/drivers/net/Config.in	Tue Jan 19 10:13:13 1999
@@ -85,17 +85,15 @@
X   fi
X   bool 'Other ISA cards' CONFIG_NET_ISA
X   if [ "$CONFIG_NET_ISA" = "y" ]; then
-    if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
-      tristate 'AT1700/1720 support (EXPERIMENTAL)' CONFIG_AT1700
-    fi
+    tristate 'AT1700/1720 support' CONFIG_AT1700
X     tristate 'Cabletron E21xx support' CONFIG_E2100
X     tristate 'DEPCA, DE10x, DE200, DE201, DE202, DE422 support' CONFIG_DEPCA
X     tristate 'EtherWORKS 3 (DE203, DE204, DE205) support' CONFIG_EWRK3
X     tristate 'EtherExpress 16 support' CONFIG_EEXPRESS
X     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X       tristate 'EtherExpressPro support' CONFIG_EEXPRESS_PRO
-      tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
X     fi
+    tristate 'FMV-181/182/183/184 support' CONFIG_FMV18X
X     tristate 'HP PCLAN+ (27247B and 27252A) support' CONFIG_HPLAN_PLUS
X     tristate 'HP PCLAN (27245 and other 27xxx series) support' CONFIG_HPLAN
X     tristate 'HP 10/100VG PCLAN (ISA, EISA, PCI) support' CONFIG_HP100
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/at1700.c linux/drivers/net/at1700.c
--- v2.2.0-pre8/linux/drivers/net/at1700.c	Fri Jan  8 22:36:07 1999
+++ linux/drivers/net/at1700.c	Tue Jan 19 10:51:24 1999
@@ -12,8 +12,12 @@
X 	Center of Excellence in Space Data and Information Sciences
X 	   Code 930.5, Goddard Space Flight Center, Greenbelt MD 20771
X 
-	This is a device driver for the Allied Telesis AT1700, which is a
-	straight-forward Fujitsu MB86965 implementation.
+	This is a device driver for the Allied Telesis AT1700, and
+        Fujitsu FMV-181/182/181A/182A/183/184/183A/184A, which are
+	straight-forward Fujitsu MB86965 implementations.
+
+	Modification for Fujitsu FMV-18X cards is done by Yutaka Tamiya
+	(ta...@flab.fujitsu.co.jp). 
X 
X   Sources:
X     The Fujitsu MB86965 datasheet.
@@ -81,7 +85,7 @@
X /*
X  *	MCA
X  */
-
+#ifdef CONFIG_MCA	
X static int at1700_ioaddr_pattern[] = {
X 	0x00, 0x04, 0x01, 0x05, 0x02, 0x06, 0x03, 0x07
X };
@@ -94,6 +98,7 @@
X 	0x00, 0x00, 0x00, 0x30, 0x70, 0xb0, 0x00, 0x00,
X 	0x00, 0xf0, 0x34, 0x74, 0xb4, 0x00, 0x00, 0xf4, 0x00
X };
+#endif
X 
X /* use 0 for production, 1 for verification, >2 for debug */
X #ifndef NET_DEBUG
@@ -109,6 +114,8 @@
X 	unsigned char mc_filter[8];
X 	uint jumpered:1;			/* Set iff the board has jumper config. */
X 	uint tx_started:1;			/* Packets are on the Tx queue. */
+	uint tx_queue_ready:1;			/* Tx queue is ready to be sent. */
+	uint rx_started:1;			/* Packets are Rxing. */
X 	uint invalid_irq:1;
X 	uchar tx_queue;				/* Number of packet on the Tx queue. */
X 	char mca_slot;				/* -1 means ISA */
@@ -129,10 +136,13 @@
X /* Run-time register bank 2 definitions. */
X #define DATAPORT		8		/* Word-wide DMA or programmed-I/O dataport. */
X #define TX_START		10
+#define COL16CNTL		11		/* Controll Reg for 16 collisions */
X #define MODE13			13
X /* Configuration registers only on the '865A/B chips. */
X #define EEPROM_Ctrl 	16
X #define EEPROM_Data 	17
+#define CARDSTATUS	16			/* FMV-18x Card Status */
+#define CARDSTATUS1	17			/* FMV-18x Card Status */
X #define IOCONFIG		18		/* Either read the jumper, or move the I/O. */
X #define IOCONFIG1		19
X #define	SAPROM			20		/* The station address PROM, if no EEPROM. */
@@ -214,9 +224,9 @@
X int at1700_probe1(struct device *dev, int ioaddr)
X {
X 	char fmv_irqmap[4] = {3, 7, 10, 15};
+	char fmv_irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
X 	char at1700_irqmap[8] = {3, 4, 5, 9, 10, 11, 14, 15};
X 	unsigned int i, irq, is_fmv18x = 0, is_at1700 = 0;
-	int l_i;
X 	int slot;
X 	
X 		/* Resetting the chip doesn't reset the ISA interface, so don't bother.
@@ -238,16 +248,17 @@
X 	/* redone for multi-card detection by ZP Gu (z...@castle.net) */
X 	/* now works as a module */
X 
-	if( MCA_bus ) {
+	if (MCA_bus) {
X 		int j;
+		int l_i;
X 		u_char pos3, pos4;
X 
-		for( j = 0; at1720_mca_adapters[j].name != NULL; j ++ ) {
+		for (j = 0; at1720_mca_adapters[j].name != NULL; j ++) {
X 			slot = 0;
-			while( slot != MCA_NOTFOUND ) {
+			while (slot != MCA_NOTFOUND) {
X 				
X 				slot = mca_find_unused_adapter( at1720_mca_adapters[j].id, slot );
-				if( slot == MCA_NOTFOUND ) break;
+				if (slot == MCA_NOTFOUND) break;
X 
X 				/* if we get this far, an adapter has been detected and is
X 				enabled */
@@ -292,15 +303,16 @@
X 		&& read_eeprom(ioaddr, 4) == 0x0000
X 		&& (read_eeprom(ioaddr, 5) & 0xff00) == 0xF400)
X 		is_at1700 = 1;
-	else if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] == ioaddr
-		&& inb(ioaddr + SAPROM    ) == 0x00
+	else if (inb(ioaddr   + SAPROM    ) == 0x00
X 		&& inb(ioaddr + SAPROM + 1) == 0x00
X 		&& inb(ioaddr + SAPROM + 2) == 0x0e)
X 		is_fmv18x = 1;
X 	else
X 		return -ENODEV;
X 			
+#ifdef CONFIG_MCA
X found:
+#endif
X 
X 		/* Reset the internal state machines. */
X 	outb(0, ioaddr + RESET);
@@ -312,24 +324,46 @@
X 	if (is_at1700)
X 		irq = at1700_irqmap[(read_eeprom(ioaddr, 12)&0x04)
X 						   | (read_eeprom(ioaddr, 0)>>14)];
-	else
-		if (is_fmv18x)
+	else {
+		/* Check PnP mode for FMV-183/184/183A/184A. */
+		/* This PnP routine is very poor. IO and IRQ should be known. */
+		if (inb(ioaddr + CARDSTATUS1) & 0x20) {
+			irq = dev->irq;
+			for (i = 0; i < 8; i++) {
+				if (irq == fmv_irqmap_pnp[i])
+					break;
+			}
+			if (i == 8)
+				return -ENODEV;
+		} else {
+			if (fmv18x_probe_list[inb(ioaddr + IOCONFIG) & 0x07] != ioaddr)
+				return -ENODEV;
X 			irq = fmv_irqmap[(inb(ioaddr + IOCONFIG)>>6) & 0x03];
-	
+		}
+	}
+
X 	/* Grab the region so that we can find another board if the IRQ request
X 	   fails. */
X 	request_region(ioaddr, AT1700_IO_EXTENT, dev->name);
X 
-	printk("%s: AT1700 found at %#3x, IRQ %d, address ", dev->name,
-		   ioaddr, irq);
+	printk("%s: %s found at %#3x, IRQ %d, address ", dev->name,
+		   is_at1700 ? "AT1700" : "FMV-18X", ioaddr, irq);
X 
X 	dev->base_addr = ioaddr;
X 	dev->irq = irq;
X 
-	for(i = 0; i < 3; i++) {
-		unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
-		printk("%04x", eeprom_val);
-		((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
+	if (is_at1700) {
+		for(i = 0; i < 3; i++) {
+			unsigned short eeprom_val = read_eeprom(ioaddr, 4+i);
+			printk("%04x", eeprom_val);
+			((unsigned short *)dev->dev_addr)[i] = ntohs(eeprom_val);
+		}
+	} else {
+		for(i = 0; i < 6; i++) {
+			unsigned char val = inb(ioaddr + SAPROM + i);
+			printk("%02x", val);
+			dev->dev_addr[i] = val;
+		}
X 	}
X 
X 	/* The EEPROM word 12 bit 0x0400 means use regular 100 ohm 10baseT signals,
@@ -340,32 +374,44 @@
X 	   */
X 	{
X 		const char *porttype[] = {"auto-sense", "10baseT", "auto-sense", "10base2"};
-		ushort setup_value = read_eeprom(ioaddr, 12);
-
-		dev->if_port = setup_value >> 8;
+		if (is_at1700) {
+			ushort setup_value = read_eeprom(ioaddr, 12);
+			dev->if_port = setup_value >> 8;
+		} else {
+			ushort setup_value = inb(ioaddr + CARDSTATUS);
+			switch (setup_value & 0x07) {
+			case 0x01: /* 10base5 */
+			case 0x02: /* 10base2 */
+				dev->if_port = 0x18; break;
+			case 0x04: /* 10baseT */
+				dev->if_port = 0x08; break;
+			default:   /* auto-sense */
+				dev->if_port = 0x00; break;
+			}
+		}
X 		printk(" %s interface.\n", porttype[(dev->if_port>>3) & 3]);
X 	}
X 
+	/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
+	   bus access, two 4K Tx queues, and disabled Tx and Rx. */
+	outb(0xda, ioaddr + CONFIG_0);
+
X 	/* Set the station address in bank zero. */
-	outb(0xe0, ioaddr + CONFIG_1);
+	outb(0x00, ioaddr + CONFIG_1);
X 	for (i = 0; i < 6; i++)
X 		outb(dev->dev_addr[i], ioaddr + 8 + i);
X 
X 	/* Switch to bank 1 and set the multicast table to accept none. */
-	outb(0xe4, ioaddr + CONFIG_1);
+	outb(0x04, ioaddr + CONFIG_1);
X 	for (i = 0; i < 8; i++)
X 		outb(0x00, ioaddr + 8 + i);
X 
-	/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
-	   bus access, two 4K Tx queues, and disabled Tx and Rx. */
-	outb(0xda, ioaddr + CONFIG_0);
-
-	/* Switch to bank 2 and lock our I/O address. */
-	outb(0xe8, ioaddr + CONFIG_1);
-	outb(dev->if_port, MODE13);
X 
-	/* Power-down the chip.  Aren't we green! */
-	outb(0x00, ioaddr + CONFIG_1);
+	/* Switch to bank 2 */
+	/* Lock our I/O address, and set manual processing mode for 16 collisions. */
+	outb(0x08, ioaddr + CONFIG_1);
+	outb(dev->if_port, ioaddr + MODE13);
+	outb(0x00, ioaddr + COL16CNTL);
X 
X 	if (net_debug)
X 		printk(version);
@@ -456,35 +502,29 @@
X {
X 	struct net_local *lp = (struct net_local *)dev->priv;
X 	int ioaddr = dev->base_addr;
-	int i;
-
-	/* Powerup the chip, initialize config register 1, and select bank 0. */
-	outb(0xe0, ioaddr + CONFIG_1);
-
-	/* Set the station address in bank zero. */
-	for (i = 0; i < 6; i++)
-		outb(dev->dev_addr[i], ioaddr + 8 + i);
-
-	/* Switch to bank 1 and set the multicast table to accept none. */
-	outb(0xe4, ioaddr + CONFIG_1);
-	for (i = 0; i < 8; i++)
-		outb(0x00, ioaddr + 8 + i);
X 
X 	/* Set the configuration register 0 to 32K 100ns. byte-wide memory, 16 bit
X 	   bus access, and two 4K Tx queues. */
-	outb(0xda, ioaddr + CONFIG_0);
+	outb(0x5a, ioaddr + CONFIG_0);
X 
-	/* Switch to register bank 2, enable the Rx and Tx. */
-	outw(0xe85a, ioaddr + CONFIG_0);
+	/* Powerup, switch to register bank 2, and enable the Rx and Tx. */
+	outb(0xe8, ioaddr + CONFIG_1);
X 
X 	lp->tx_started = 0;
+	lp->tx_queue_ready = 1;
+	lp->rx_started = 0;
X 	lp->tx_queue = 0;
X 	lp->tx_queue_len = 0;
X 
-	/* Turn on Rx interrupts, leave Tx interrupts off until packet Tx. */
-	outb(0x00, ioaddr + TX_INTR);
+	/* Turn on hardware Tx and Rx interrupts. */
+	outb(0x82, ioaddr + TX_INTR);
X 	outb(0x81, ioaddr + RX_INTR);
X 
+	/* Enable the IRQ on boards of fmv18x it is feasible. */
+	if (lp->jumpered) {
+		outb(0x80, ioaddr + IOCONFIG1);
+	}
+
X 	dev->tbusy = 0;
X 	dev->interrupt = 0;
X 	dev->start = 1;
@@ -518,10 +558,14 @@
X 		outw(0xffff, ioaddr + 24);
X 		outw(0xffff, ioaddr + TX_STATUS);
X 		outw(0xe85a, ioaddr + CONFIG_0);
-		outw(0x8100, ioaddr + TX_INTR);
+		outw(0x8182, ioaddr + TX_INTR);
+		outb(0x00, ioaddr + TX_START);
+		outb(0x03, ioaddr + COL16CNTL);
X 		dev->tbusy=0;
X 		dev->trans_start = jiffies;
X 		lp->tx_started = 0;
+		lp->tx_queue_ready = 1;
+		lp->rx_started = 0;
X 		lp->tx_queue = 0;
X 		lp->tx_queue_len = 0;
X 	}
@@ -534,14 +578,20 @@
X 		short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
X 		unsigned char *buf = skb->data;
X 
-		/* Turn off the possible Tx interrupts. */
-		outb(0x00, ioaddr + TX_INTR);
-
-		outw(length, ioaddr + DATAPORT);
-		outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+		/* We may not start transmitting unless we finish transferring
+		   a packet into the Tx queue. During executing the following
+		   codes we possibly catch a Tx interrupt. Thus we flag off
+		   tx_queue_ready, so that we prevent the interrupt routine
+		   (net_interrupt) to start transmitting. */
+		lp->tx_queue_ready = 0;
+		{
+			outw(length, ioaddr + DATAPORT);
+			outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
X 
-		lp->tx_queue++;
-		lp->tx_queue_len += length + 2;
+			lp->tx_queue++;
+			lp->tx_queue_len += length + 2;
+		}
+		lp->tx_queue_ready = 1;
X 
X 		if (lp->tx_started == 0) {
X 			/* If the Tx is idle, always trigger a transmit. */
@@ -554,9 +604,6 @@
X 		} else if (lp->tx_queue_len < 4096 - 1502)
X 			/* Yes, there is room for one more packet. */
X 			dev->tbusy = 0;
-
-		/* Turn on Tx interrupts back on. */
-		outb(0x82, ioaddr + TX_INTR);
X 	}
X 	dev_kfree_skb (skb);
X 
@@ -585,14 +632,35 @@
X 
X 	if (net_debug > 4)
X 		printk("%s: Interrupt with status %04x.\n", dev->name, status);
-	if (status & 0xff00
-		||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {			/* Got a packet(s). */
+	if (lp->rx_started == 0 &&
+	    (status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
+		/* Got a packet(s).
+		   We cannot execute net_rx more than once at the same time for
+		   the same device. During executing net_rx, we possibly catch a
+		   Tx interrupt. Thus we flag on rx_started, so that we prevent
+		   the interrupt routine (net_interrupt) to dive into net_rx
+		   again. */
+		lp->rx_started = 1;
+		outb(0x00, ioaddr + RX_INTR);	/* Disable RX intr. */
X 		net_rx(dev);
+		outb(0x81, ioaddr + RX_INTR);	/* Enable  RX intr. */
+		lp->rx_started = 0;
X 	}
X 	if (status & 0x00ff) {
-		if (status & 0x80) {
+		if (status & 0x02) {
+			/* More than 16 collisions occurred */
+			if (net_debug > 4)
+				printk("%s: 16 Collision occur during Txing.\n", dev->name);
+			/* Cancel sending a packet. */
+			outb(0x03, ioaddr + COL16CNTL);
+			lp->stats.collisions++;
+		}
+		if (status & 0x82) {
X 			lp->stats.tx_packets++;
-			if (lp->tx_queue) {
+			/* The Tx queue has any packets and is not being
+			   transferred a packet from the host, start
+			   transmitting. */
+			if (lp->tx_queue && lp->tx_queue_ready) {
X 				outb(0x80 | lp->tx_queue, ioaddr + TX_START);
X 				lp->tx_queue = 0;
X 				lp->tx_queue_len = 0;
@@ -601,8 +669,6 @@
X 				mark_bh(NET_BH);	/* Inform upper layers. */
X 			} else {
X 				lp->tx_started = 0;
-				/* Turn on Tx interrupts off. */
-				outb(0x00, ioaddr + TX_INTR);
X 				dev->tbusy = 0;
X 				mark_bh(NET_BH);	/* Inform upper layers. */
X 			}
@@ -698,7 +764,7 @@
X /* The inverse routine to net_open(). */
X static int net_close(struct device *dev)
X {
-/*	struct net_local *lp = (struct net_local *)dev->priv;*/
+	struct net_local *lp = (struct net_local *)dev->priv;
X 	int ioaddr = dev->base_addr;
X 
X 	dev->tbusy = 1;
@@ -709,13 +775,11 @@
X 
X 	/* No statistic counters on the chip to update. */
X 
-#if 0
-	/* Disable the IRQ on boards where it is feasible. */
+	/* Disable the IRQ on boards of fmv18x where it is feasible. */
X 	if (lp->jumpered) {
X 		outb(0x00, ioaddr + IOCONFIG1);
X 		free_irq(dev->irq, dev);
X 	}
-#endif
X 
X 	/* Power-down the chip.  Green, green, green! */
X 	outb(0x00, ioaddr + CONFIG_1);
@@ -820,6 +884,10 @@
X static int io = 0x260;
X static int irq = 0;
X 
+MODULE_PARM(io, "i");
+MODULE_PARM(irq, "i");
+MODULE_PARM(net_debug, "i");
+
X int init_module(void)
X {
X 	if (io == 0)
@@ -836,14 +904,14 @@
X void
X cleanup_module(void)
X {
-	struct net_local *lp = dev_at1700.priv;
-	unregister_netdev(&dev_at1700);
X #ifdef CONFIG_MCA	
+	struct net_local *lp = dev_at1700.priv;
X 	if(lp->mca_slot)
X 	{
X 		mca_mark_as_unused(lp->mca_slot);
X 	}
X #endif	
+	unregister_netdev(&dev_at1700);
X 	kfree(dev_at1700.priv);
X 	dev_at1700.priv = NULL;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/fmv18x.c linux/drivers/net/fmv18x.c
--- v2.2.0-pre8/linux/drivers/net/fmv18x.c	Thu Feb 12 20:56:08 1998
+++ linux/drivers/net/fmv18x.c	Tue Jan 19 10:13:13 1999
@@ -32,7 +32,7 @@
X */
X 
X static const char *version =
-	"fmv18x.c:v1.3.71e 03/04/96  Yutaka TAMIYA (ta...@flab.fujitsu.co.jp)\n";
+	"fmv18x.c:v2.2.0 09/24/98  Yutaka TAMIYA (ta...@flab.fujitsu.co.jp)\n";
X 
X #include <linux/module.h>
X 
@@ -74,6 +74,8 @@
X 	struct net_device_stats stats;
X 	long open_time;				/* Useless example local info. */
X 	uint tx_started:1;			/* Number of packet on the Tx queue. */
+	uint tx_queue_ready:1;		/* Tx queue is ready to be sent. */
+	uint rx_started:1;			/* Packets are Rxing. */
X 	uchar tx_queue;				/* Number of packet on the Tx queue. */
X 	ushort tx_queue_len;		/* Current length of the Tx queue. */
X };
@@ -92,7 +94,7 @@
X /* Run-time register bank 2 definitions. */
X #define DATAPORT		8		/* Word-wide DMA or programmed-I/O dataport. */
X #define TX_START		10
-#define COL16CNTL		11
+#define COL16CNTL		11		/* Controll Reg for 16 collisions */
X #define MODE13			13
X /* Fujitsu FMV-18x Card Configuration */
X #define	FJ_STATUS0		0x10
@@ -164,6 +166,7 @@
X __initfunc(int fmv18x_probe1(struct device *dev, short ioaddr))
X {
X 	char irqmap[4] = {3, 7, 10, 15};
+	char irqmap_pnp[8] = {3, 4, 5, 7, 9, 10, 11, 15};
X 	unsigned int i, irq;
X 
X 	/* Resetting the chip doesn't reset the ISA interface, so don't bother.
@@ -171,13 +174,26 @@
X 	   */
X 
X 	/* Check I/O address configuration and Fujitsu vendor code */
-	if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr
- 	||  inb(ioaddr+FJ_MACADDR  ) != 0x00
+	if (inb(ioaddr+FJ_MACADDR  ) != 0x00
X 	||  inb(ioaddr+FJ_MACADDR+1) != 0x00
X 	||  inb(ioaddr+FJ_MACADDR+2) != 0x0e)
X 		return -ENODEV;
X 
-	irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
+	/* Check PnP mode for FMV-183/184/183A/184A. */
+	/* This PnP routine is very poor. IO and IRQ should be known. */
+	if (inb(ioaddr + FJ_STATUS1) & 0x20) {
+		irq = dev->irq;
+		for (i = 0; i < 8; i++) {
+			if (irq == irqmap_pnp[i])
+				break;
+		}
+		if (i == 8)
+			return -ENODEV;
+	} else {
+		if (fmv18x_probe_list[inb(ioaddr + FJ_CONFIG0) & 0x07] != ioaddr)
+			return -ENODEV;
+		irq = irqmap[(inb(ioaddr + FJ_CONFIG0)>>6) & 0x03];
+	}
X 
X 	/* Snarf the interrupt vector now. */
X 	if (request_irq(irq, &net_interrupt, 0, "fmv18x", dev)) {
@@ -247,6 +263,7 @@
X 	/* Switch to bank 2 and lock our I/O address. */
X 	outb(0x08, ioaddr + CONFIG_1);
X 	outb(dev->if_port, ioaddr + MODE13);
+	outb(0x00, ioaddr + COL16CNTL);
X 
X 	if (net_debug)
X 		printk(version);
@@ -283,6 +300,8 @@
X 	outb(0xe8, ioaddr + CONFIG_1);
X 
X 	lp->tx_started = 0;
+	lp->tx_queue_ready = 1;
+	lp->rx_started = 0;
X 	lp->tx_queue = 0;
X 	lp->tx_queue_len = 0;
X 
@@ -364,14 +383,20 @@
X 			printk("%s: Transmitting a packet of length %lu.\n", dev->name,
X 				   (unsigned long)skb->len);
X 
-		/* Disable both interrupts. */
-		outw(0x0000, ioaddr + TX_INTR);
-
-		outw(length, ioaddr + DATAPORT);
-		outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
+		/* We may not start transmitting unless we finish transferring
+		   a packet into the Tx queue. During executing the following
+		   codes we possibly catch a Tx interrupt. Thus we flag off
+		   tx_queue_ready, so that we prevent the interrupt routine
+		   (net_interrupt) to start transmitting. */
+		lp->tx_queue_ready = 0;
+		{
+			outw(length, ioaddr + DATAPORT);
+			outsw(ioaddr + DATAPORT, buf, (length + 1) >> 1);
X 
-		lp->tx_queue++;
-		lp->tx_queue_len += length + 2;
+			lp->tx_queue++;
+			lp->tx_queue_len += length + 2;
+		}
+		lp->tx_queue_ready = 1;
X 
X 		if (lp->tx_started == 0) {
X 			/* If the Tx is idle, always trigger a transmit. */
@@ -384,9 +409,6 @@
X 		} else if (lp->tx_queue_len < 4096 - 1502)
X 			/* Yes, there is room for one more packet. */
X 			dev->tbusy = 0;
-
-		/* Re-enable interrupts */
-		outw(0x8182, ioaddr + TX_INTR);
X 	}
X 	dev_kfree_skb (skb);
X 
@@ -410,23 +432,37 @@
X 
X 	ioaddr = dev->base_addr;
X 	lp = (struct net_local *)dev->priv;
-
-	/* Avoid multiple interrupts. */
-	outw(0x0000, ioaddr + TX_INTR);
-
-        status = inw(ioaddr + TX_STATUS);
+	status = inw(ioaddr + TX_STATUS);
X 	outw(status, ioaddr + TX_STATUS);
X 
X 	if (net_debug > 4)
X 		printk("%s: Interrupt with status %04x.\n", dev->name, status);
-	if (status & 0xff00
-		||  (inb(ioaddr + RX_MODE) & 0x40) == 0) {			/* Got a packet(s). */
+	if (lp->rx_started == 0 &&
+		(status & 0xff00 || (inb(ioaddr + RX_MODE) & 0x40) == 0)) {
+		/* Got a packet(s).
+		   We cannot execute net_rx more than once at the same time for
+		   the same device. During executing net_rx, we possibly catch a
+		   Tx interrupt. Thus we flag on rx_started, so that we prevent
+		   the interrupt routine (net_interrupt) to dive into net_rx
+		   again. */
+		lp->rx_started = 1;
+		outb(0x00, ioaddr + RX_INTR);	/* Disable RX intr. */
X 		net_rx(dev);
+		outb(0x81, ioaddr + RX_INTR);	/* Enable  RX intr. */
+		lp->rx_started = 0;
X 	}
X 	if (status & 0x00ff) {
-		if (status & 0x80) {
+		if (status & 0x02) {
+			/* More than 16 collisions occurred */
+			if (net_debug > 4)
+				printk("%s: 16 Collision occur during Txing.\n", dev->name);
+			/* Cancel sending a packet. */
+			outb(0x03, ioaddr + COL16CNTL);
+			lp->stats.collisions++;
+		}
+		if (status & 0x82) {
X 			lp->stats.tx_packets++;
-			if (lp->tx_queue) {
+			if (lp->tx_queue && lp->tx_queue_ready) {
X 				outb(0x80 | lp->tx_queue, ioaddr + TX_START);
X 				lp->tx_queue = 0;
X 				lp->tx_queue_len = 0;
@@ -439,16 +475,9 @@
X 				mark_bh(NET_BH);	/* Inform upper layers. */
X 			}
X 		}
-		if (status & 0x02 ) {
-			if (net_debug > 4)
-				printk("%s: 16 Collision occur during Txing.\n", dev->name);
-			/* Retry to send the packet */
-			outb(0x02, ioaddr + COL16CNTL);
-		}
X 	}
X 
X 	dev->interrupt = 0;
-	outw(0x8182, ioaddr + TX_INTR);
X 	return;
X }
X 
@@ -458,7 +487,7 @@
X {
X 	struct net_local *lp = (struct net_local *)dev->priv;
X 	int ioaddr = dev->base_addr;
-	int boguscount = 10;	/* 5 -> 10: by agy 19940922 */
+	int boguscount = 5;
X 
X 	while ((inb(ioaddr + RX_MODE) & 0x40) == 0) {
X 		/* Clear PKT_RDY bit: by agy 19940922 */
@@ -619,6 +648,7 @@
X 
X MODULE_PARM(io, "i");
X MODULE_PARM(irq, "i");
+MODULE_PARM(net_debug, "i");
X 
X int init_module(void)
X {
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/Config.in linux/drivers/net/irda/Config.in
--- v2.2.0-pre8/linux/drivers/net/irda/Config.in	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/Config.in	Wed Jan 20 11:05:33 1999
@@ -13,4 +13,5 @@
X fi
X dep_tristate '  NSC PC87108' CONFIG_NSC_FIR  $CONFIG_IRDA
X dep_tristate '  Winbond W83977AF (IR)' CONFIG_WINBOND_FIR $CONFIG_IRDA
+dep_tristate '  Sharp UIRCC' CONFIG_SHARP_FIR $CONFIG_IRDA
X endmenu
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/Makefile linux/drivers/net/irda/Makefile
--- v2.2.0-pre8/linux/drivers/net/irda/Makefile	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/Makefile	Wed Jan 20 11:05:33 1999
@@ -36,6 +36,14 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_SHARP_FIR),y)
+L_OBJS += uircc.o irport.o
+else
+  ifeq ($(CONFIG_SHARP_FIR),m)
+  M_OBJS += uircc.o irport.o
+  endif
+endif
+
X ifeq ($(CONFIG_ESI_DONGLE),y)
X L_OBJS += esi.o
X else
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c
--- v2.2.0-pre8/linux/drivers/net/irda/actisys.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/actisys.c	Wed Jan 20 11:05:33 1999
@@ -1,13 +1,13 @@
X /*********************************************************************
X  *                
X  * Filename:      actisys.c
- * Version:       0.3
+ * Version:       0.4
X  * Description:   Implementation for the ACTiSYS IR-220L and IR-220L+ 
X  *                dongles
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Dec 14 11:50:32 1998
+ * Modified at:   Mon Jan 18 11:30:25 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -95,7 +95,7 @@
X {
X         struct irtty_cb *self;
X         struct tty_struct *tty;
-        int arg = 0;
+        int arg;
X         struct termios old_termios;
X 	int cflag;
X         int current_baudrate;
@@ -132,7 +132,7 @@
X 		DEBUG( 0, __FUNCTION__ "(), Clearing RTS\n");
X 		
X 		/* Set DTR, clear RTS */
-		arg = TIOCM_DTR;
+		arg = TIOCM_DTR|TIOCM_OUT2;
X 		
X 		fs = get_fs();
X 		set_fs( get_ds());
@@ -149,7 +149,7 @@
X 		schedule_timeout(2);
X 
X 		/* Set DTR, Set RTS */
-                arg = TIOCM_DTR | TIOCM_RTS;
+                arg = TIOCM_DTR | TIOCM_RTS |TIOCM_OUT2;
X 
X 		fs = get_fs();
X 		set_fs( get_ds());
@@ -237,7 +237,7 @@
X 		return;
X 
X 	DEBUG( 0, __FUNCTION__ "(), Clearing DTR\n");
-	arg = TIOCM_RTS;
+	arg = TIOCM_RTS | TIOCM_OUT2;
X 
X 	fs = get_fs();
X 	set_fs( get_ds());
@@ -245,7 +245,7 @@
X 	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
X 				(unsigned long) &arg)) 
X 	{ 
-		DEBUG( 0, __FUNCTION__"(), Ioctl error!\n");
+		DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
X 	}
X 	set_fs(fs);
X 
@@ -254,7 +254,7 @@
X 	schedule_timeout(2);
X 	
X 	DEBUG( 0, __FUNCTION__ "(), Setting DTR\n");
-	arg = TIOCM_RTS | TIOCM_DTR;
+	arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
X 	
X 	fs = get_fs();
X 	set_fs( get_ds());
@@ -262,7 +262,7 @@
X 	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, 
X 				(unsigned long) &arg)) 
X 	{ 
-		DEBUG( 0, __FUNCTION__"(), Ioctl error!\n");
+		DEBUG( 0, __FUNCTION__"(), ioctl error!\n");
X 	}
X 	set_fs(fs);
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c
--- v2.2.0-pre8/linux/drivers/net/irda/esi.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/esi.c	Wed Jan 20 11:05:33 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X  * Filename:      esi.c
- * Version:       1.0
+ * Version:       1.1
X  * Description:   Driver for the Extended Systems JetEye PC
X  * Status:        Experimental.
X  * Author:        Thomas Davis, <rat...@radiks.net>
X  * Created at:    Sat Feb 21 18:54:38 1998
- * Modified at:   Mon Dec 14 11:48:22 1998
+ * Modified at:   Mon Jan 18 11:30:32 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:	  esi.c
X  *
@@ -68,7 +68,7 @@
X 
X static void esi_open( struct irda_device *idev, int type)
X {
-	strcat( idev->name, " <-> esi");
+	strcat( idev->description, " <-> esi");
X 
X 	idev->io.dongle_id = type;
X 
@@ -90,13 +90,11 @@
X {
X 	struct irtty_cb *self;
X 	struct tty_struct *tty;
-	int arg = 0;
+	int arg = TIOCM_OUT2;
X         struct termios old_termios;
X 	int cflag;
X 	mm_segment_t fs;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
X 	ASSERT( idev != NULL, return;);
X 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
X 	
@@ -118,16 +116,16 @@
X 	switch (baud) {
X 	case 19200:
X 		cflag |= B19200;
-		arg = TIOCM_DTR;
+		arg |= TIOCM_DTR;
X 		break;
X 	case 115200:
X 		cflag |= B115200;
-		arg = TIOCM_RTS | TIOCM_DTR;
+		arg |= TIOCM_RTS | TIOCM_DTR;
X 		break;
X 	case 9600:
X 	default:
X 		cflag |= B9600;
-		arg = TIOCM_RTS;
+		arg |= TIOCM_RTS;
X 		break;
X 	}
X 		
@@ -146,7 +144,7 @@
X 	set_fs( get_ds());
X 
X 	if ( tty->driver.ioctl( tty, NULL, TIOCMSET, (unsigned long) &arg)) { 
-		DEBUG(0, "error setting ESI speed!\n");
+		DEBUG( 0, __FUNCTION__ "(), error setting ESI speed!\n");
X 	}
X 	set_fs(fs);
X }
@@ -193,3 +191,4 @@
X }
X 
X #endif
+
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c
--- v2.2.0-pre8/linux/drivers/net/irda/irport.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/irport.c	Wed Jan 20 11:05:33 1999
@@ -1,10 +1,8 @@
X /*********************************************************************
X  *		  
X  * Filename:	  irport.c
- * Version:	  0.1
- * Description:   Serial driver for IrDA. The functions in this file
- *                may be used by FIR drivers, but this file knows
- *                nothing about FIR drivers!!!
+ * Version:	  0.8
+ * Description:   Serial driver for IrDA. 
X  * Status:	  Experimental.
X  * Author:	  Dag Brattli <da...@cs.uit.no>
X  * Created at:	  Sun Aug  3 13:49:59 1997
@@ -25,38 +23,91 @@
X  *     provide warranty for any of this software. This material is 
X  *     provided "AS-IS" and at no charge.
X  *
+ *     NOTICE:
+ *
+ *     This driver is ment to be a small serial driver to be used for
+ *     IR-chipsets that has a UART (16550) compatibility mode. If your
+ *     chipset is is UART only, you should probably use IrTTY instead since
+ *     the Linux serial driver is probably more robust and optimized.
+ *
+ *     The functions in this file may be used by FIR drivers, but this
+ *     driver knows nothing about FIR drivers so don't ever insert such
+ *     code into this file. Instead you should code your FIR driver in a
+ *     separate file, and then call the functions in this file if
+ *     necessary. This is becase it is difficult to use the Linux serial
+ *     driver with a FIR driver becase they must share interrupts etc. Most
+ *     FIR chipsets can function in advanced SIR mode, and you should
+ *     probably use that mode instead of the UART compatibility mode (and
+ *     then just forget about this file)
+ *
X  ********************************************************************/
X 
-/* #include <linux/module.h> */
+#include <linux/module.h>
X 
X #include <linux/kernel.h>
X #include <linux/types.h>
X #include <linux/ioport.h>
-#include <linux/in.h>
X #include <linux/malloc.h>
X #include <linux/string.h>
X #include <asm/system.h>
X #include <asm/bitops.h>
X #include <asm/io.h>
X #include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/init.h>
X 
X #include <linux/skbuff.h>
X #include <linux/serial_reg.h>
X 
-#include "irda.h"
-#include "ircompat.h"
-#include "irport.h"
-#include "timer.h"
-#include "crc.h"
-#include "wrapper.h"
-#include "irlap_frame.h"
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irport.h>
X 
-#define IO_EXTENT	8
+#define IO_EXTENT 8
+
+static unsigned int io[]  = { 0x3e8, ~0, ~0, ~0 };
+static unsigned int irq[] = { 11, 0, 0, 0 };
X 
X static void irport_write_wakeup( struct irda_device *idev);
-static int irport_write( int iobase, int fifo_size, __u8 *buf, int len);
+static int  irport_write( int iobase, int fifo_size, __u8 *buf, int len);
X static void irport_receive( struct irda_device *idev);
X 
+__initfunc(int irport_init(void))
+{
+/* 	int i; */
+
+/* 	for ( i=0; (io[i] < 2000) && (i < 4); i++) { */
+/* 		int ioaddr = io[i]; */
+/* 		if (check_region(ioaddr, IO_EXTENT)) */
+/* 			continue; */
+/* 		if (irport_open( i, io[i], io2[i], irq[i], dma[i]) == 0) */
+/* 			return 0; */
+/* 	} */
+/* 	return -ENODEV; */
+	return 0;
+}
+
+/*
+ * Function pc87108_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void irport_cleanup(void)
+{
+	int i;
+
+        DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* for ( i=0; i < 4; i++) { */
+/* 		if ( dev_self[i]) */
+/* 			irport_close( &(dev_self[i]->idev)); */
+/* 	} */
+}
+#endif /* MODULE */
+
X /*
X  * Function irport_open (void)
X  *
@@ -65,14 +116,14 @@
X  */
X int irport_open( int iobase)
X {
+	DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
X 	/* Initialize UART */
-	outb_p( UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
-	outb_p(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), 
-	       iobase+UART_MCR);
+	outb( UART_LCR_WLEN8, iobase+UART_LCR);  /* Reset DLAB */
+	outb(( UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
X 	
X 	/* Turn on interrups */
-	outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), 
-	       iobase+UART_IER); 
+	outb(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), iobase+UART_IER); 
X 	
X 	return 0;
X }
@@ -88,10 +139,10 @@
X 	DEBUG( 0, __FUNCTION__ "()\n");
X 
X 	/* Reset UART */
-	outb_p( 0, iobase+UART_MCR);
+	outb( 0, iobase+UART_MCR);
X 
X 	/* Turn off interrupts */
-	outb_p( 0, iobase+UART_IER); 
+	outb( 0, iobase+UART_IER); 
X }
X 
X /*
@@ -108,8 +159,10 @@
X 
X 	DEBUG( 0, __FUNCTION__ "(), Setting speed to: %d\n", speed);
X 
+	DEBUG( 0, __FUNCTION__ "(), iobase=%#x\n", iobase);
+
X 	/* Turn off interrupts */
-	outb_p( 0, iobase+UART_IER); 
+	outb( 0, iobase+UART_IER); 
X 
X 	divisor = SPEED_MAX/speed;
X 	
@@ -118,15 +171,14 @@
X 	/* IrDA ports use 8N1 */
X 	lcr = UART_LCR_WLEN8;
X 	
-	outb_p( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
-	outb_p( divisor & 0xff,      iobase+UART_DLL); /* Set speed	*/
-	outb_p( divisor >> 8,	     iobase+UART_DLM);
-	outb_p( lcr,		     iobase+UART_LCR); /* Set 8N1	*/
-	outb_p( fcr,		     iobase+UART_FCR); /* Enable FIFO's */
+	outb( UART_LCR_DLAB | lcr, iobase+UART_LCR); /* Set DLAB */
+	outb( divisor & 0xff,      iobase+UART_DLL); /* Set speed */
+	outb( divisor >> 8,	   iobase+UART_DLM);
+	outb( lcr,		   iobase+UART_LCR); /* Set 8N1	*/
+	outb( fcr,		   iobase+UART_FCR); /* Enable FIFO's */
X 
X 	/* Turn on interrups */
-	outb_p(( UART_IER_THRI |UART_IER_RLSI | UART_IER_RDI), 
-	       iobase+UART_IER); 
+	outb( UART_IER_THRI|UART_IER_RLSI|UART_IER_RDI, iobase+UART_IER); 
X }
X 
X /*
@@ -149,21 +201,25 @@
X 		return;
X 	}
X 
-	iobase = idev->io.iobase;
-	iir    = inb( iobase + UART_IIR);
+	idev->netdev.interrupt = 1;
+
+	iobase = idev->io.iobase2;
X 
+	iir = inb(iobase + UART_IIR);
X 	do {
X 		status = inb( iobase+UART_LSR);
X 		
-		if ( status & UART_LSR_DR) {
+		if (status & UART_LSR_DR) {
X 	       		/* Receive interrupt */
-			irport_receive( idev);
+			irport_receive(idev);
X 		}
-		if ( status & UART_LSR_THRE) {
+		if (status & UART_LSR_THRE) {
X 	       		/* Transmitter ready for data */
-			irport_write_wakeup( idev);
+			irport_write_wakeup(idev);
X 		}
-	} while ( !(inb( iobase+UART_IIR) & UART_IIR_NO_INT));
+	} while (!(inb(iobase+UART_IIR) & UART_IIR_NO_INT));
+
+	idev->netdev.interrupt = 0;
X }
X 
X /*
@@ -179,16 +235,11 @@
X 	
X 	DEBUG( 4, __FUNCTION__ "() <%ld>\n", jiffies);
X 	
-	/* 
-	 *  First make sure we're connected. 
-	 */
X 	ASSERT( idev != NULL, return;);
X 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
X 
-	/*
-	 *  Finished with frame?
-	 */
-	if ( idev->tx.ptr == idev->tx.len)  {
+	/* Finished with frame?  */
+	if ( idev->tx_buff.offset == idev->tx_buff.len)  {
X 
X 		/* 
X 		 *  Now serial buffer is almost free & we can start 
@@ -201,16 +252,16 @@
X 
X 		/* Schedule network layer, so we can get some more frames */
X 		mark_bh( NET_BH);
+
X 		return;
X 	}
-	/*
-	 *  Write data left in transmit buffer
-	 */
-	count = idev->tx.len - idev->tx.ptr;
-	actual = irport_write( idev->io.iobase, idev->io.fifo_size, 
-			       idev->tx.head, count);
-	idev->tx.ptr += actual;
-	idev->tx.head += actual;
+
+	/* Write data left in transmit buffer */
+	count = idev->tx_buff.len - idev->tx_buff.offset;
+	actual = irport_write( idev->io.iobase2, idev->io.fifo_size, 
+			       idev->tx_buff.head, count);
+	idev->tx_buff.offset += actual;
+	idev->tx_buff.head += actual;
X }
X 
X /*
@@ -223,7 +274,8 @@
X {
X 	int actual = 0;
X 
-	if (!(inb_p( iobase+UART_LSR) & UART_LSR_THRE)) {
+	/* Tx FIFO should be empty! */
+	if (!(inb( iobase+UART_LSR) & UART_LSR_THRE)) {
X 		DEBUG( 0, __FUNCTION__ "(), failed, fifo not empty!\n");
X 		return -1;
X 	}
@@ -265,19 +317,11 @@
X 		return -EBUSY;
X 	}
X 	
-	idev = (struct irda_device *)  dev->priv;
+	idev = (struct irda_device *) dev->priv;
X 
X 	ASSERT( idev != NULL, return -1;);
X 	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
X 
-	if ( skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), skb==NULL\n");
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,1,0)
-		dev_tint(dev); 
-#endif
-		return 0;
-	}
-
X 	/* Lock transmit buffer */
X 	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
X 		return -EBUSY;
@@ -285,18 +329,17 @@
X         /*  
X 	 *  Transfer skb to tx_buff while wrapping, stuffing and making CRC 
X 	 */
-	idev->tx.len = async_wrap_skb( skb, idev->tx.buff, idev->tx.buffsize);
-
-	actual = irport_write( idev->io.iobase, idev->io.fifo_size, 
-			       idev->tx.buff, idev->tx.len);
-
-	idev->tx.ptr = actual;
-	idev->tx.head = idev->tx.buff + actual;
-
-	IS_SKB( skb, return 0;);
-	FREE_SKB_MAGIC( skb);
-	DEV_KFREE_SKB( skb, FREE_WRITE);
-
+	idev->tx_buff.len = async_wrap_skb( skb, idev->tx_buff.data, 
+					    idev->tx_buff.truesize);
+	
+	actual = irport_write( idev->io.iobase2, idev->io.fifo_size, 
+			       idev->tx_buff.data, idev->tx_buff.len);
+	
+	idev->tx_buff.offset = actual;
+	idev->tx_buff.head = idev->tx_buff.data + actual;
+	
+	dev_kfree_skb( skb);
+	
X 	return 0;
X }
X         
@@ -308,54 +351,54 @@
X  */
X static void irport_receive( struct irda_device *idev) 
X {
-	__u8 byte = 0x00;
X 	int iobase;
X 
X 	if ( !idev)
X 		return;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-	iobase = idev->io.iobase;
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
-	if ( idev->rx.len == 0) {
-		idev->rx.head = idev->rx.buff;
-	}
+	iobase = idev->io.iobase2;
X 
-	/* 
-	 *  Receive all characters in FIFO 
+	if ( idev->rx_buff.len == 0)
+		idev->rx_buff.head = idev->rx_buff.data;
+	
+	/*  
+	 * Receive all characters in Rx FIFO, unwrap and unstuff them. 
+         * async_unwrap_char will deliver all found frames  
X 	 */
X 	do {
-		byte = inb_p( iobase+UART_RX);
-		async_unwrap_char( idev, byte);
+		async_unwrap_char( idev, inb( iobase+UART_RX));
X 		
-	} while ( inb_p( iobase+UART_LSR) & UART_LSR_DR);	
+	} while ( inb( iobase+UART_LSR) & UART_LSR_DR);	
X }
X 
+#ifdef MODULE
+
X /*
X  * Function cleanup_module (void)
X  *
X  *    
X  *
X  */
-/* void cleanup_module(void) */
-/* { */
-/* 	DEBUG( 3, "IrPORT: cleanup_module!\n"); */
-/* 	irport_cleanup(irport_drv); */
-/* } */
+void cleanup_module(void)
+{
+	irport_cleanup();
+}
X 
X /*
X  * Function init_module (void)
X  *
X  *    
- *
X  */
-/* int init_module(void) */
-/* { */
-/* 	if (irport_init() < 0) { */
-/* 		cleanup_module(); */
-/* 		return 1; */
-/* 	} */
-/* 	return(0); */
-/* } */
+int init_module(void)
+{
+	if (irport_init() < 0) {
+		cleanup_module();
+		return 1;
+	}
+	return(0);
+}
+
+#endif /* MODULE */
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c
--- v2.2.0-pre8/linux/drivers/net/irda/irtty.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/irtty.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Dec  9 21:18:38 1997
- * Modified at:   Mon Dec 14 20:09:42 1998
+ * Modified at:   Mon Jan 18 15:32:03 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       slip.c by Laurence Culhane,   <l...@holmes.demon.co.uk>
X  *                          Fred N. van Kempen, <wal...@uwalt.nl.mugnet.org>
@@ -205,6 +205,7 @@
X 	/* The only value we must override it the baudrate */
X 	self->idev.qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
X 		IR_115200;
+	self->idev.qos.min_turn_time.bits = 0x03;
X 	irda_qos_bits_to_value( &self->idev.qos);
X 
X 	/* Specify which buffer allocation policy we need */
@@ -468,7 +469,6 @@
X 		 */
X 		async_unwrap_char( &self->idev, *cp++);
X 		/* self->rx_over_errors++; */
-
X 	}
X }
X 
@@ -586,9 +586,9 @@
X 
X 		tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
X 
-
X 		idev->netdev.tbusy = 0; /* Unlock */
X 		idev->stats.tx_packets++;
+		idev->stats.tx_bytes += idev->tx_buff.len;
X 
X 		/* Tell network layer that we want more frames */
X 		mark_bh( NET_BH);
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/pc87108.c linux/drivers/net/irda/pc87108.c
--- v2.2.0-pre8/linux/drivers/net/irda/pc87108.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/pc87108.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Nov  7 21:43:15 1998
- * Modified at:   Mon Dec 14 11:40:24 1998
+ * Modified at:   Mon Dec 28 08:46:16 1998
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>
@@ -129,9 +129,6 @@
X {
X 	int i;
X 
-	DEBUG( 0, __FUNCTION__ "()\n");
-
-
X 	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
X 		int ioaddr = io[i];
X 		if (check_region(ioaddr, CHIP_IO_EXTENT))
@@ -369,12 +366,12 @@
X 
X 	/* Receiver frame length */
X 	switch_bank( iobase, BANK4);
-	outb( 4000 & 0xff, iobase+6);
-	outb(( 4000 >> 8) & 0x1f, iobase+7);
+	outb( 2048 & 0xff, iobase+6);
+	outb(( 2048 >> 8) & 0x1f, iobase+7);
X 
X 	/* Transmitter frame length */
-	outb( 4000 & 0xff, iobase+4);
-	outb(( 4000 >> 8) & 0x1f, iobase+5);
+	outb( 2048 & 0xff, iobase+4);
+	outb(( 2048 >> 8) & 0x1f, iobase+5);
X 	
X 	DEBUG( 0, "PC87108 driver loaded. Version: 0x%02x\n", version);
X 
@@ -676,7 +673,12 @@
X 
X 	/* Set FIFO threshold to TX17, RX16 */
X 	switch_bank( iobase, BANK0);
-	outb( FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR);
+	outb( FCR_RXTH|     /* Set Rx FIFO threshold */
+	      FCR_TXTH|     /* Set Tx FIFO threshold */
+	      FCR_TXSR|     /* Reset Tx FIFO */
+	      FCR_RXSR|     /* Reset Rx FIFO */
+	      FCR_FIFO_EN,  /* Enable FIFOs */
+	      iobase+FCR);
X 	/* outb( 0xa7, iobase+FCR); */
X 	
X 	/* Set FIFO size to 32 */
@@ -894,7 +896,7 @@
X 		idev->stats.tx_errors++;
X 		idev->stats.tx_fifo_errors++;
X 		
-		/* Clear bit, by writing 1 to it */
+		/* Clear bit, by writing 1 into it */
X 		outb( ASCR_TXUR, iobase+ASCR);
X 	} else {
X 		idev->stats.tx_packets++;
@@ -1049,7 +1051,7 @@
X 				/* Put this entry back in fifo */
X 				st_fifo->head--;
X 				st_fifo->len++;
-				st_fifo->entries[ st_fifo->head].status = status;
+				st_fifo->entries[st_fifo->head].status = status;
X 				st_fifo->entries[ st_fifo->head].len = len;
X 
X 				/* Restore bank register */
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c
--- v2.2.0-pre8/linux/drivers/net/irda/tekram.c	Tue Dec 22 14:16:55 1998
+++ linux/drivers/net/irda/tekram.c	Wed Jan 20 11:05:33 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X  * Filename:      tekram.c
- * Version:       0.3
+ * Version:       0.4
X  * Description:   Implementation of the Tekram IrMate IR-210B dongle
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Oct 21 20:02:35 1998
- * Modified at:   Mon Dec 14 11:48:37 1998
+ * Modified at:   Mon Jan 18 11:30:38 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -148,7 +148,7 @@
X 
X 	/* Set DTR, Clear RTS */
X 	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Clearing RTS\n");
-	arg = TIOCM_DTR;
+	arg = TIOCM_DTR | TIOCM_OUT2;
X 	
X 	fs = get_fs();
X 	set_fs( get_ds());
@@ -173,7 +173,7 @@
X         
X 	/* Set DTR, Set RTS */
X 	DEBUG( 0, __FUNCTION__ "(), Setting DTR, Setting RTS\n");
-	arg = TIOCM_DTR | TIOCM_RTS;
+	arg = TIOCM_DTR | TIOCM_RTS | TIOCM_OUT2;
X 	
X 	fs = get_fs();
X 	set_fs( get_ds());
@@ -226,7 +226,7 @@
X 		return;
X 
X 	DEBUG( 0, __FUNCTION__ "(), Power off dongle\n");
-	arg = TIOCM_RTS | TIOCM_DTR;
+	arg = TIOCM_RTS | TIOCM_DTR | TIOCM_OUT2;
X 	
X 	fs = get_fs();
X 	set_fs( get_ds());
@@ -244,7 +244,7 @@
X 	
X 	DEBUG( 0, __FUNCTION__ "(), Set DTR, clear RTS\n");
X 	/* Set DTR, clear RTS */
-	arg = TIOCM_DTR;
+	arg = TIOCM_DTR | TIOCM_OUT2;
X 	
X 	fs = get_fs();
X 	set_fs( get_ds());
@@ -261,6 +261,8 @@
X 
X 	DEBUG( 0, __FUNCTION__ "(), STATE3\n");
X 	/* Clear DTR, clear RTS */
+	arg = TIOCM_OUT2;
+
X 	fs = get_fs();
X 	set_fs( get_ds());
X 	
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/irda/uircc.c linux/drivers/net/irda/uircc.c
--- v2.2.0-pre8/linux/drivers/net/irda/uircc.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/net/irda/uircc.c	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,915 @@
+/*********************************************************************
+ *                
+ * Filename:      uircc.c
+ * Version:       0.1
+ * Description:   Driver for the Sharp Universal Infrared 
+ *                Communications Controller (UIRCC)
+ * Status:        Experimental.
+ * Author:        Dag Brattli <da...@cs.uit.no>
+ * Created at:    Sat Dec 26 10:59:03 1998
+ * Modified at:   Tue Jan 19 23:54:04 1999
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *      
+ *     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.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ *     Applicable Models : Tecra 510CDT, 500C Series, 530CDT, 520CDT,
+ *     740CDT, Portege 300CT, 660CDT, Satellite 220C Series, 
+ *     Satellite Pro, 440C Series, 470CDT, 460C Series, 480C Series
+ *
+ *     Notice that FIR mode is not working yet, since I don't know 
+ *     how to make the UIRCC drive the interrupt line, and not the
+ *     UART (which is used for SIR speeds). Please mail me if you know!
+ *
+ ********************************************************************/
+
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/malloc.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/config.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/dma.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/wrapper.h>
+#include <net/irda/irda.h>
+#include <net/irda/irmod.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#include <net/irda/uircc.h>
+#include <net/irda/irport.h>
+
+static char *driver_name = "uircc";
+
+#define CHIP_IO_EXTENT 16
+
+static unsigned int io[]  = { 0x300, ~0, ~0, ~0 };
+static unsigned int io2[] = { 0x3e8, 0, 0, 0};
+static unsigned int irq[] = { 11, 0, 0, 0 };
+static unsigned int dma[] = { 5, 0, 0, 0 };
+
+static struct uircc_cb *dev_self[] = { NULL, NULL, NULL, NULL};
+
+/* Some prototypes */
+static int  uircc_open( int i, unsigned int iobase, unsigned int board_addr, 
+			unsigned int irq, unsigned int dma);
+static int  uircc_close( struct irda_device *idev);
+static int  uircc_probe( int iobase, int board_addr, int irq, int dma);
+static int  uircc_dma_receive( struct irda_device *idev); 
+static int  uircc_dma_receive_complete(struct irda_device *idev, int iobase);
+static int  uircc_hard_xmit( struct sk_buff *skb, struct device *dev);
+static void uircc_dma_write( struct irda_device *idev, int iobase);
+static void uircc_change_speed( struct irda_device *idev, int baud);
+static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs);
+static void uircc_wait_until_sent( struct irda_device *idev);
+static int  uircc_is_receiving( struct irda_device *idev);
+
+static int  uircc_net_init( struct device *dev);
+static int  uircc_net_open( struct device *dev);
+static int  uircc_net_close( struct device *dev);
+
+/*
+ * Function uircc_init ()
+ *
+ *    Initialize chip. Just try to find out how many chips we are dealing with
+ *    and where they are
+ */
+__initfunc(int uircc_init(void))
+{
+	int i;
+
+	for ( i=0; (io[i] < 2000) && (i < 4); i++) {
+		int ioaddr = io[i];
+		if (check_region(ioaddr, CHIP_IO_EXTENT))
+			continue;
+		if (uircc_open( i, io[i], io2[i], irq[i], dma[i]) == 0)
+			return 0;
+	}
+	return -ENODEV;
+}
+
+/*
+ * Function uircc_cleanup ()
+ *
+ *    Close all configured chips
+ *
+ */
+#ifdef MODULE
+static void uircc_cleanup(void)
+{
+	int i;
+
+        DEBUG( 4, __FUNCTION__ "()\n");
+
+	for ( i=0; i < 4; i++) {
+		if ( dev_self[i])
+			uircc_close( &(dev_self[i]->idev));
+	}
+}
+#endif /* MODULE */
+
+/*
+ * Function uircc_open (iobase, irq)
+ *
+ *    Open driver instance
+ *
+ */
+static int uircc_open( int i, unsigned int iobase, unsigned int iobase2, 
+                       unsigned int irq, unsigned int dma)
+{
+	struct uircc_cb *self;
+	struct irda_device *idev;
+	int ret;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	if (( uircc_probe( iobase, iobase2, irq, dma)) == -1)
+		return -1;
+	
+	/*
+	 *  Allocate new instance of the driver
+	 */
+	self = kmalloc( sizeof(struct uircc_cb), GFP_KERNEL);
+	if ( self == NULL) {
+		printk( KERN_ERR "IrDA: Can't allocate memory for "
+			"IrDA control block!\n");
+		return -ENOMEM;
+	}
+	memset( self, 0, sizeof(struct uircc_cb));
+   
+	/* Need to store self somewhere */
+	dev_self[i] = self;
+
+	idev = &self->idev;
+
+	/* Initialize IO */
+	idev->io.iobase    = iobase;
+        idev->io.iobase2   = iobase2; /* Used by irport */
+        idev->io.irq       = irq;
+        idev->io.io_ext    = CHIP_IO_EXTENT;
+        idev->io.io_ext2   = 8;       /* Used by irport */
+        idev->io.dma       = dma;
+        idev->io.fifo_size = 16;
+
+	/* Lock the port that we need */
+	ret = check_region( idev->io.iobase, idev->io.io_ext);
+	if ( ret < 0) { 
+		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		       idev->io.iobase);
+		/* uircc_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	ret = check_region( idev->io.iobase2, idev->io.io_ext2);
+	if ( ret < 0) { 
+		DEBUG( 0, __FUNCTION__ "(), can't get iobase of 0x%03x\n",
+		       idev->io.iobase2);
+		/* uircc_cleanup( self->idev);  */
+		return -ENODEV;
+	}
+	request_region( idev->io.iobase, idev->io.io_ext, idev->name);
+        request_region( idev->io.iobase2, idev->io.io_ext2, idev->name);
+
+	/* Initialize QoS for this device */
+	irda_init_max_qos_capabilies( &idev->qos);
+	
+	/* The only value we must override it the baudrate */
+	idev->qos.baud_rate.bits = IR_9600|IR_19200|IR_38400|IR_57600|
+		IR_115200|IR_576000|IR_1152000|(IR_4000000 << 8);
+
+	idev->qos.min_turn_time.bits = 0x07;
+	irda_qos_bits_to_value( &idev->qos);
+	
+	/* Specify which buffer allocation policy we need */
+	idev->rx_buff.flags = GFP_KERNEL | GFP_DMA;
+	idev->tx_buff.flags = GFP_KERNEL | GFP_DMA;
+
+	/* Max DMA buffer size needed = (data_size + 6) * (window_size) + 6; */
+	idev->rx_buff.truesize = 4000; 
+	idev->tx_buff.truesize = 4000;
+	
+	/* Initialize callbacks */
+	idev->hard_xmit       = uircc_hard_xmit;
+	idev->change_speed    = uircc_change_speed;
+	idev->wait_until_sent = uircc_wait_until_sent;
+	idev->is_receiving    = uircc_is_receiving;
+     
+	/* Override the network functions we need to use */
+	idev->netdev.init            = uircc_net_init;
+	idev->netdev.hard_start_xmit = uircc_hard_xmit;
+	idev->netdev.open            = uircc_net_open;
+	idev->netdev.stop            = uircc_net_close;
+
+	irport_open( iobase2);
+
+	/* Open the IrDA device */
+	irda_device_open( idev, driver_name, self);
+	
+	return 0;
+}
+
+/*
+ * Function uircc_close (idev)
+ *
+ *    Close driver instance
+ *
+ */
+static int uircc_close( struct irda_device *idev)
+{
+	int iobase;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+        iobase = idev->io.iobase;
+
+	/* Disable modem */
+	outb( 0x00, iobase+UIRCC_CR10);
+
+	irport_close( idev->io.iobase2);
+
+	/* Release the PORT that this driver is using */
+	DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", idev->io.iobase);
+	release_region( idev->io.iobase, idev->io.io_ext);
+
+	if ( idev->io.iobase2) {
+		DEBUG( 4, __FUNCTION__ "(), Releasing Region %03x\n", 
+		       idev->io.iobase2);
+		release_region( idev->io.iobase2, idev->io.io_ext2);
+	}
+
+	irda_device_close( idev);
+
+	return 0;
+}
+
+/*
+ * Function uircc_probe (iobase, board_addr, irq, dma)
+ *
+ *    Returns non-negative on success.
+ *
+ */
+static int uircc_probe( int iobase, int iobase2, int irq, int dma) 
+{
+	int version;
+	int probe_irq=0;
+	unsigned long mask;
+	int i;
+	
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	/* read the chip version, should be 0x03 */
+	version = inb( iobase+UIRCC_SR8);
+
+	if ( version != 0x03) {
+		DEBUG( 0, __FUNCTION__ "(), Wrong chip version");	
+		return -1;
+	}
+        DEBUG( 0, "UIRCC driver loaded. Version: 0x%02x\n", version);
+
+	/* Reset chip */
+	outb( UIRCC_CR0_SYS_RST, iobase+UIRCC_CR0);
+
+	/* Initialize some registers */
+	outb( 0, iobase+UIRCC_CR11);
+	outb( 0, iobase+UIRCC_CR9);
+
+	/* Enable DMA single mode */
+	outb( UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, 
+	      iobase+UIRCC_CR1);
+
+	/* Disable interrupts */
+	outb( 0xff, iobase+UIRCC_CR2); 
+
+#if 0
+	irport_close( iobase2);
+
+	for (i=0;i<1;i++) {
+
+	/* Set appropriate speed mode */
+	outb( UIRCC_CR10_FIR, iobase+UIRCC_CR10);
+
+	/* Enable DMA single mode */
+	outb( UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, 
+	      iobase+UIRCC_CR1);
+
+	/* Set up timer */
+	outb( 0x01, iobase+UIRCC_CR12);
+	outb( 0x00, iobase+UIRCC_CR13);
+
+	/* Set interrupt mask */
+	outb( 0x82, iobase+UIRCC_CR2);
+
+	DEBUG( 0, __FUNCTION__ "(*), sr3=%#x, sr2=%#x, sr10=%#x, sr12=%#x\n", 
+	       inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2), 
+	       inb( iobase+UIRCC_SR10), inb( iobase+UIRCC_SR12));
+
+	mask = probe_irq_on();
+
+	/* Enable timer */
+	outb( 0x08, iobase+UIRCC_CR11);
+
+	udelay( 10000); /* Wait for interrupt! */
+
+	probe_irq = probe_irq_off( mask);
+
+	DEBUG( 0, "Found irq=%d\n", probe_irq);
+
+	DEBUG( 0, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x, sr12=%#x\n", 
+	       inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2), 
+	       inb( iobase+UIRCC_SR10), inb( iobase+UIRCC_SR12));
+	
+
+	/* Diable timer */
+	outb( 0x00, iobase+UIRCC_CR11);
+	}
+#endif
+
+	/* Set self poll address */
+
+	return 0;
+}
+
+/*
+ * Function uircc_change_speed (idev, baud)
+ *
+ *    Change the speed of the device
+ *
+ */
+static void uircc_change_speed( struct irda_device *idev, int speed)
+{
+	struct uircc_cb *self;
+	int iobase; 
+	int modem = UIRCC_CR10_SIR;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	self = idev->priv;
+	iobase = idev->io.iobase;
+
+	/* Update accounting for new speed */
+	idev->io.baudrate = speed;
+
+	/* Disable interrupts */	
+	outb( 0xff, iobase+UIRCC_CR2);
+
+	switch ( speed) {
+	case 9600:
+	case 19200:
+	case 37600:
+	case 57600:
+	case 115200:
+/* 		irport_open( idev->io.iobase2); */
+		irport_change_speed( idev->io.iobase2, speed);
+		modem = UIRCC_CR10_SIR;
+		break;
+	case 576000:		
+		
+		DEBUG(0, __FUNCTION__ "(), handling baud of 576000\n");
+		break;
+	case 1152000:
+
+		DEBUG(0, __FUNCTION__ "(), handling baud of 1152000\n");
+		break;
+	case 4000000:
+		irport_close( idev->io.iobase2);
+		modem = UIRCC_CR10_FIR;
+		DEBUG(0, __FUNCTION__ "(), handling baud of 4000000\n");
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), unknown baud rate of %d\n", speed);
+		break;
+	}
+
+	/* Set appropriate speed mode */
+	outb( modem, iobase+UIRCC_CR10);
+
+	idev->netdev.tbusy = 0;
+	
+	/* Enable some interrupts so we can receive frames */
+	if ( speed > 115200) {
+		/* Enable DMA single mode */
+		outb( UIRCC_CR1_RX_DMA|UIRCC_CR1_TX_DMA|UIRCC_CR1_MUST_SET, 
+		      iobase+UIRCC_CR1);
+
+ 		/* outb( UIRCC_CR2_RECV_MASK, iobase+UIRCC_CR2);  */
+		outb( 0, iobase+UIRCC_CR2); 
+ 		uircc_dma_receive( idev);
+ 	}    	
+}
+
+/*
+ * Function uircc_hard_xmit (skb, dev)
+ *
+ *    Transmit the frame!
+ *
+ */
+static int uircc_hard_xmit( struct sk_buff *skb, struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	int mtt;
+	
+	idev = (struct irda_device *) dev->priv;
+
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+
+	iobase = idev->io.iobase;
+
+	DEBUG(0, __FUNCTION__ "(%ld), skb->len=%d\n", jiffies, (int) skb->len);
+
+	/* Use irport for SIR speeds */
+	if ( idev->io.baudrate <= 115200) {
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 06'
echo 'File patch-2.2.0-pre9 is continued in part 07'
echo 07 > _shar_seq_.tmp
#!/bin/sh
# this is part 07 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 07; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
+		return irport_hard_xmit( skb, dev);
+	}
+
+	if ( dev->tbusy) {
+		__u8 sr3;
+
+		DEBUG( 4, __FUNCTION__ "(), tbusy==TRUE\n");
+			
+		return -EBUSY;
+	}
+	
+	/* Lock transmit buffer */
+	if ( irda_lock( (void *) &dev->tbusy) == FALSE)
+		return -EBUSY;
+
+	memcpy( idev->tx_buff.data, skb->data, skb->len);
+
+	/* Make sure that the length is a multiple of 16 bits */
+	if ( skb->len & 0x01)
+		skb->len++;
+
+	idev->tx_buff.len = skb->len;
+	idev->tx_buff.head = idev->tx_buff.data;
+	idev->tx_buff.offset = 0;
+	
+	mtt = irda_get_mtt( skb);
+	
+	/* Use udelay for delays less than 50 us. */
+	if (mtt)
+		udelay( mtt);
+	
+	/* Enable transmit interrupts */
+	/* outb( UIRCC_CR2_XMIT_MASK, iobase+UIRCC_CR2); */
+	outb( 0, iobase+UIRCC_CR2); 
+
+ uircc_dma_write( idev, iobase);
+	
+	dev_kfree_skb( skb);
+
+	return 0;
+}
+
+/*
+ * Function uircc_dma_xmit (idev, iobase)
+ *
+ *    Transmit data using DMA
+ *
+ */
+static void uircc_dma_write( struct irda_device *idev, int iobase)
+{
+	struct uircc_cb *self;
+	int i;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	self = idev->priv;
+
+	/* Receiving disable */
+	self->cr3 &= ~UIRCC_CR3_RECV_EN;
+	outb( self->cr3, iobase+UIRCC_CR3);
+
+	setup_dma( idev->io.dma, idev->tx_buff.data, idev->tx_buff.len, 
+		   DMA_MODE_WRITE);
+	
+	DEBUG( 0, __FUNCTION__ "residue=%d\n", 
+	       get_dma_residue( idev->io.dma));
+
+	idev->io.direction = IO_XMIT;
+
+	/* Set frame length */
+	outb( idev->tx_buff.len & 0xff, iobase+UIRCC_CR4); /* Low byte */
+	outb( idev->tx_buff.len >> 8, iobase+UIRCC_CR5);   /* High byte */
+
+	/* Enable transmit and transmit CRC */
+	self->cr3 |= (UIRCC_CR3_XMIT_EN|UIRCC_CR3_TX_CRC_EN);
+	outb( self->cr3, iobase+UIRCC_CR3);
+}
+
+/*
+ * Function uircc_dma_xmit_complete (idev)
+ *
+ *    The transfer of a frame in finished. This function will only be called 
+ *    by the interrupt handler
+ *
+ */
+static void uircc_dma_xmit_complete( struct irda_device *idev, int underrun)
+{
+	struct uircc_cb *self;
+	int iobase;
+ int len;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	ASSERT( idev != NULL, return;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return;);
+
+	self = idev->priv;
+
+	iobase = idev->io.iobase;
+
+	/* Select TX counter */
+	outb( UIRCC_CR0_CNT_SWT, iobase+UIRCC_CR0);
+
+	/* Read TX length counter */
+	len  = inb( iobase+UIRCC_SR4);      /* Low byte */
+	len |= inb( iobase+UIRCC_SR5) << 8; /* High byte */
+
+	/* Disable transmit */
+	self->cr3 &= ~UIRCC_CR3_XMIT_EN;
+	outb( self->cr3, iobase+UIRCC_CR3);
+	
+	/* Check for underrrun! */
+	if ( underrun) {
+		idev->stats.tx_errors++;
+		idev->stats.tx_fifo_errors++;		
+	} else {
+		idev->stats.tx_packets++;
+		idev->stats.tx_bytes +=  idev->tx_buff.len;
+	}
+
+	/* Unlock tx_buff and request another frame */
+	idev->netdev.tbusy = 0; /* Unlock */
+	idev->media_busy = FALSE;
+	
+	/* Tell the network layer, that we can accept more frames */
+	mark_bh( NET_BH);
+}
+
+/*
+ * Function uircc_dma_receive (idev)
+ *
+ *    Get ready for receiving a frame. The device will initiate a DMA
+ *    if it starts to receive a frame.
+ *
+ */
+static int uircc_dma_receive( struct irda_device *idev) 
+{
+	struct uircc_cb *self;
+	int iobase;
+
+	ASSERT( idev != NULL, return -1;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return -1;);
+
+ DEBUG( 0, __FUNCTION__ "\n");
+
+	self = idev->priv;
+	iobase= idev->io.iobase;
+
+	/* Disable DMA */
+	
+	setup_dma( idev->io.dma, idev->rx_buff.data, idev->rx_buff.truesize, 
+		   DMA_MODE_READ);
+	
+	/* driver->media_busy = FALSE; */
+	idev->io.direction = IO_RECV;
+	idev->rx_buff.head = idev->rx_buff.data;
+	idev->rx_buff.offset = 0;
+
+	/* Enable receiving with CRC */
+	self->cr3 |= (UIRCC_CR3_RECV_EN|UIRCC_CR3_RX_CRC_EN);
+	outb( self->cr3, iobase+UIRCC_CR3);
+	
+	/* Address check? */
+
+	DEBUG( 4, __FUNCTION__ "(), done!\n");	
+	
+	return 0;
+}
+
+/*
+ * Function uircc_dma_receive_complete (idev)
+ *
+ *    Finished with receiving frames
+ *
+ *    
+ */
+static int uircc_dma_receive_complete( struct irda_device *idev, int iobase)
+{
+	struct sk_buff *skb;
+	struct uircc_cb *self;
+	int len;
+
+	self = idev->priv;
+
+	DEBUG( 0, __FUNCTION__ "()\n");
+
+	/* Check for CRC or framing error */
+	if ( inb( iobase+UIRCC_SR0) & UIRCC_SR0_RX_CRCFRM) {
+		DEBUG( 0, __FUNCTION__ "(), crc or frm error\n");
+		return -1;
+	}
+
+	/* Select receive length counter */
+	outb( 0x00, iobase+UIRCC_CR0);
+
+	/* Read frame length */
+	len = inb( iobase+UIRCC_SR4);       /* Low byte */
+	len |= inb( iobase+UIRCC_SR5) << 8; /* High byte */
+
+	DEBUG( 0, __FUNCTION__ "(), len=%d\n", len);
+
+	/* Receiving disable */
+	self->cr3 &= ~UIRCC_CR3_RECV_EN;
+	outb( self->cr3, iobase+UIRCC_CR3);
+
+	skb = dev_alloc_skb( len+1);
+	if (skb == NULL)  {
+		printk( KERN_INFO __FUNCTION__ 
+			"(), memory squeeze, dropping frame.\n");
+				/* Restore bank register */
+		return FALSE;
+	}
+			
+	/* Make sure IP header gets aligned */
+	skb_reserve( skb, 1); 
+
+	/* Copy frame without CRC */
+	/* if ( idev->io.baudrate < 4000000) { */
+/* 		skb_put( skb, len-2); */
+/* 		memcpy( skb->data, idev->rx_buff.head, len-2); */
+/* 	} else { */
+/* 		skb_put( skb, len-4); */
+/* 		memcpy( skb->data, idev->rx_buff.head, len-4); */
+/* 	} */
+
+	skb_put( skb, len);
+	memcpy( skb->data, idev->rx_buff.head, len);
+	idev->stats.rx_packets++;
+
+	skb->dev = &idev->netdev;
+	skb->mac.raw  = skb->data;
+	skb->protocol = htons(ETH_P_IRDA);
+	netif_rx( skb);
+
+	return TRUE;
+}
+
+/*
+ * Function uircc_interrupt (irq, dev_id, regs)
+ *
+ *    An interrupt from the chip has arrived. Time to do some work
+ *
+ */
+static void uircc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	__u8 sr3;
+	int iobase;
+
+	struct irda_device *idev = (struct irda_device *) dev_id;
+
+	if (idev == NULL) {
+		printk( KERN_WARNING "%s: irq %d for unknown device.\n", 
+			driver_name, irq);
+		return;
+	}
+	
+	if (idev->io.baudrate <= 115200)
+		return irport_interrupt( irq, dev_id, regs);
+
+	iobase = idev->io.iobase;
+
+	/* Read interrupt status */
+	sr3 = inb( iobase+UIRCC_SR3); 
+	if (!sr3) {
+		return;
+	}
+
+	idev->netdev.interrupt = 1;
+
+	DEBUG( 4, __FUNCTION__ "(), sr3=%#x, sr2=%#x, sr10=%#x\n", 
+	       inb( iobase+UIRCC_SR3), inb( iobase+UIRCC_SR2), 
+	       inb( iobase+UIRCC_SR10));
+
+	/*
+	 *  Check what interrupt this is. The UIRCC will not report two
+	 *  different interrupts at the same time!
+	 */
+	switch( sr3) {
+	case UIRCC_SR3_RX_EOF: /* Check of end of frame */
+		uircc_dma_receive_complete( idev, iobase);
+		break;
+	case UIRCC_SR3_TXUR:   /* Check for transmit underrun */
+		uircc_dma_xmit_complete( idev, TRUE);
+		break;
+	case UIRCC_SR3_TX_DONE:
+		uircc_dma_xmit_complete( idev, FALSE);
+		break;
+	case UIRCC_SR3_TMR_OUT:
+		/* Disable timer */
+		outb( inb( iobase+UIRCC_CR11) & ~UIRCC_CR11_TMR_EN, 
+		      iobase+UIRCC_CR11);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), unknown interrupt status=%#x\n",
+		       sr3);
+		break;
+	}
+	
+	idev->netdev.interrupt = 0;
+}
+
+/*
+ * Function uircc_wait_until_sent (idev)
+ *
+ *    This function should put the current thread to sleep until all data 
+ *    have been sent, so it is safe to change the speed.
+ */
+static void uircc_wait_until_sent( struct irda_device *idev)
+{
+	/* Just delay 60 ms */
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(6);
+}
+
+/*
+ * Function uircc_is_receiving (idev)
+ *
+ *    Return TRUE is we are currently receiving a frame
+ *
+ */
+static int uircc_is_receiving( struct irda_device *idev)
+{
+	int status = FALSE;
+	/* int iobase; */
+
+	ASSERT( idev != NULL, return FALSE;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return FALSE;);
+
+	if ( idev->io.baudrate > 115200) {
+		
+	} else 
+		status = ( idev->rx_buff.state != OUTSIDE_FRAME);
+	
+	return status;
+}
+
+/*
+ * Function uircc_net_init (dev)
+ *
+ *    Initialize network device
+ *
+ */
+static int uircc_net_init( struct device *dev)
+{
+	DEBUG( 4, __FUNCTION__ "()\n");
+
+	/* Setup to be a normal IrDA network device driver */
+	irda_device_setup( dev);
+
+	/* Insert overrides below this line! */
+
+	return 0;
+}
+
+
+/*
+ * Function uircc_net_open (dev)
+ *
+ *    Start the device
+ *
+ */
+static int uircc_net_open( struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+	
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+ ASSERT( dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+	
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	
+	iobase = idev->io.iobase;
+
+	if (request_irq( idev->io.irq, uircc_interrupt, 0, idev->name, 
+			 (void *) idev)) {
+		return -EAGAIN;
+	}
+	/*
+	 * Always allocate the DMA channel after the IRQ,
+	 * and clean up on failure.
+	 */
+	if (request_dma(idev->io.dma, idev->name)) {
+		free_irq( idev->io.irq, idev);
+		return -EAGAIN;
+	}
+		
+	/* Ready to play! */
+	dev->tbusy = 0;
+	dev->interrupt = 0;
+	dev->start = 1;
+
+	/* turn on interrupts */
+	
+	MOD_INC_USE_COUNT;
+
+	return 0;
+}
+
+/*
+ * Function uircc_net_close (dev)
+ *
+ *    Stop the device
+ *
+ */
+static int uircc_net_close(struct device *dev)
+{
+	struct irda_device *idev;
+	int iobase;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
+	
+	/* Stop device */
+	dev->tbusy = 1;
+	dev->start = 0;
+
+	ASSERT( dev != NULL, return -1;);
+	idev = (struct irda_device *) dev->priv;
+	
+	ASSERT( idev != NULL, return 0;);
+	ASSERT( idev->magic == IRDA_DEVICE_MAGIC, return 0;);
+	
+	iobase = idev->io.iobase;
+
+ disable_dma( idev->io.dma);
+
+	/* Disable interrupts */
+       
+	free_irq( idev->io.irq, idev);
+	free_dma( idev->io.dma);
+
+	MOD_DEC_USE_COUNT;
+
+	return 0;
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *    
+ *
+ */
+int init_module(void)
+{
+	uircc_init();
+
+	return(0);
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    
+ *
+ */
+void cleanup_module(void)
+{
+	uircc_cleanup();
+}
+
+#endif
+
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/net/tulip.c linux/drivers/net/tulip.c
--- v2.2.0-pre8/linux/drivers/net/tulip.c	Wed Jan 13 15:00:42 1999
+++ linux/drivers/net/tulip.c	Tue Jan 19 13:18:45 1999
@@ -279,7 +279,7 @@
X 	HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM,
X 	tulip_timer },
X   { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_21142,
-	"Digital DS21142/3 Tulip", 256, 0x0801fbff,
+	"Digital DS21142/3 Tulip", 128, 0x0801fbff,
X 	HAS_MII | HAS_MEDIA_TABLE, t21142_timer },
X   { PCI_VENDOR_ID_LITEON, 0x0002,
X 	"Lite-On 82c168 PNIC", 256, 0x0001ebef, HAS_MII, pnic_timer },
@@ -2397,7 +2397,6 @@
X 				memcpy(skb_put(skb, pkt_len),
X 					   bus_to_virt(tp->rx_ring[entry].buffer1), pkt_len);
X #else
-#warning Code untested
X 				eth_copy_and_sum(skb, bus_to_virt(tp->rx_ring[entry].buffer1),
X 								 pkt_len, 0);
X 				skb_put(skb, pkt_len);
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/pci/pci.c linux/drivers/pci/pci.c
--- v2.2.0-pre8/linux/drivers/pci/pci.c	Wed Sep  9 14:51:08 1998
+++ linux/drivers/pci/pci.c	Wed Jan 20 10:18:53 1999
@@ -28,6 +28,9 @@
X #endif
X 
X struct pci_bus pci_root;
+#ifdef CONFIG_VISWS
+struct pci_bus pci_other;
+#endif
X struct pci_dev *pci_devices = NULL;
X static struct pci_dev **pci_last_dev_p = &pci_devices;
X static int pci_reverse __initdata = 0;
@@ -382,6 +385,11 @@
X 
X 	memset(&pci_root, 0, sizeof(pci_root));
X 	pci_root.subordinate = pci_scan_bus(&pci_root);
+#ifdef CONFIG_VISWS
+	pci_other.number = 1; /* XXX unless bridge(s) on pci_root */
+	pci_other.subordinate = pci_scan_bus(&pci_other);
+	pci_root.next = &pci_other;
+#endif
X 
X 	/* give BIOS a chance to apply platform specific fixes: */
X 	pcibios_fixup();
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/pnp/parport_probe.c linux/drivers/pnp/parport_probe.c
--- v2.2.0-pre8/linux/drivers/pnp/parport_probe.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/pnp/parport_probe.c	Wed Jan 20 13:29:18 1999
@@ -105,13 +105,13 @@
X 	parport_claim_or_block(dev);
X 
X 	switch (parport_ieee1284_nibble_mode_ok(port, 4)) {
-	case 1:
+	case 2:
X 		current->state=TASK_INTERRUPTIBLE;
X 		/* HACK: wait 10ms because printer seems to ack wrong */
X 		schedule_timeout((HZ+99)/100);	
X 		result = read_polled(port, buffer, len);
X 		break;
-	case 0:
+	default:
X 		result = -EIO;
X 		break;
X 	}
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/scsi/aha152x.c linux/drivers/scsi/aha152x.c
--- v2.2.0-pre8/linux/drivers/scsi/aha152x.c	Tue Jan 19 11:32:51 1999
+++ linux/drivers/scsi/aha152x.c	Tue Jan 19 11:01:04 1999
@@ -566,6 +566,7 @@
X   { "Adaptec BIOS:AVA-282X",         0xc, 21 },  /* Adaptec 282x */
X   { "Adaptec IBM Dock II SCSI",   0x2edd, 24 },  /* IBM Thinkpad Dock II */
X   { "Adaptec BIOS:AHA-1532P",       0x1c, 22 },  /* IBM Thinkpad Dock II SCSI */
+  { "DTC3520A Host Adapter BIOS", 0x318a, 26 },  /* DTC 3520A ISA SCSI */
X };
X #define SIGNATURE_COUNT (sizeof(signatures) / sizeof(struct signature))
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/scsi/ini9100u.c linux/drivers/scsi/ini9100u.c
--- v2.2.0-pre8/linux/drivers/scsi/ini9100u.c	Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/ini9100u.c	Tue Jan 19 11:23:23 1999
@@ -247,6 +247,19 @@
X 				/* ---- EXTERNAL VARIABLES ---- */
X extern HCS tul_hcs[];
X 
+struct id {
+  int vendor_id;
+  int device_id;
+};
+
+const struct id id_table[] = {
+  { INI_VENDOR_ID, I950_DEVICE_ID },
+  { INI_VENDOR_ID, I940_DEVICE_ID },
+  { INI_VENDOR_ID, I935_DEVICE_ID },
+  { INI_VENDOR_ID, 0x0002 },
+  { DMX_VENDOR_ID, 0x0002 },
+};
+
X /*
X  *  queue services:
X  */
@@ -338,64 +351,27 @@
X 	int iAdapters = 0;
X 	long dRegValue;
X 	WORD wBIOS;
+	const int iNumIdEntries = sizeof(id_table)/sizeof(id_table[0]);
+	int i = 0;
X 
X 	init_i91uAdapter_table();
X 
-	while ((pDev = pci_find_device(INI_VENDOR_ID, I950_DEVICE_ID, pDev)) != NULL) {
-		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
-		wBIOS = (UWORD) (dRegValue & 0xFF);
-		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
-			dRegValue = 0;
-		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
-		if (Addi91u_into_Adapter_table(wBIOS,
-					(pDev->base_address[0] & 0xFFFE),
-					       pDev->irq,
-					       pDev->bus->number,
-					       (pDev->devfn >> 3)
-		    ) == 0)
-			iAdapters++;
-	}
-	while ((pDev = pci_find_device(INI_VENDOR_ID, I940_DEVICE_ID, pDev)) != NULL) {
-		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
-		wBIOS = (UWORD) (dRegValue & 0xFF);
-		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
-			dRegValue = 0;
-		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
-		if (Addi91u_into_Adapter_table(wBIOS,
-					(pDev->base_address[0] & 0xFFFE),
-					       pDev->irq,
-					       pDev->bus->number,
-					       (pDev->devfn >> 3)
-		    ) == 0)
-			iAdapters++;
-	}
-	while ((pDev = pci_find_device(INI_VENDOR_ID, I935_DEVICE_ID, pDev)) != NULL) {
-		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
-		wBIOS = (UWORD) (dRegValue & 0xFF);
-		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
-			dRegValue = 0;
-		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
-		if (Addi91u_into_Adapter_table(wBIOS,
-					(pDev->base_address[0] & 0xFFFE),
-					       pDev->irq,
-					       pDev->bus->number,
-					       (pDev->devfn >> 3)
-		    ) == 0)
-			iAdapters++;
-	}
-	while ((pDev = pci_find_device(INI_VENDOR_ID, 0x0002, pDev)) != NULL) {
-		pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
-		wBIOS = (UWORD) (dRegValue & 0xFF);
-		if (((dRegValue & 0xFF00) >> 8) == 0xFF)
-			dRegValue = 0;
-		wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
-		if (Addi91u_into_Adapter_table(wBIOS,
-					(pDev->base_address[0] & 0xFFFE),
-					       pDev->irq,
-					       pDev->bus->number,
-					       (pDev->devfn >> 3)
-		    ) == 0)
-			iAdapters++;
+	for (i=0; i < iNumIdEntries; i++) {
+		struct id curId = id_table[i];
+		while ((pDev = pci_find_device(curId.vendor_id, curId.device_id, pDev)) != NULL) {
+			pci_read_config_dword(pDev, 0x44, (u32 *) & dRegValue);
+			wBIOS = (UWORD) (dRegValue & 0xFF);
+			if (((dRegValue & 0xFF00) >> 8) == 0xFF)
+				dRegValue = 0;
+			wBIOS = (wBIOS << 8) + ((UWORD) ((dRegValue & 0xFF00) >> 8));
+			if (Addi91u_into_Adapter_table(wBIOS,
+							(pDev->base_address[0] & 0xFFFE),
+						       	pDev->irq,
+						       	pDev->bus->number,
+					       		(pDev->devfn >> 3)
+		    		) == 0)
+				iAdapters++;
+		}
X 	}
X 
X 	return (iAdapters);
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/scsi/ini9100u.h linux/drivers/scsi/ini9100u.h
--- v2.2.0-pre8/linux/drivers/scsi/ini9100u.h	Wed Jan 13 15:00:42 1999
+++ linux/drivers/scsi/ini9100u.h	Wed Jan 20 16:22:57 1999
@@ -207,6 +207,7 @@
X #define SENSE_SIZE		14
X 
X #define INI_VENDOR_ID   0x1101	/* Initio's PCI vendor ID       */
+#define DMX_VENDOR_ID   0x134a	/* Domex's PCI vendor ID       */
X #define I950_DEVICE_ID	0x9500	/* Initio's inic-950 product ID   */
X #define I940_DEVICE_ID	0x9400	/* Initio's inic-940 product ID   */
X #define I935_DEVICE_ID	0x9401	/* Initio's inic-935 product ID   */
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/sound/ad1848.c linux/drivers/sound/ad1848.c
--- v2.2.0-pre8/linux/drivers/sound/ad1848.c	Tue Jan 19 11:32:52 1999
+++ linux/drivers/sound/ad1848.c	Tue Jan 19 14:47:48 1999
@@ -2420,7 +2420,7 @@
X 	ad1848_unload(hw_config->io_base + 4,
X 		      hw_config->irq,
X 		      hw_config->dma,
-		      hw_config->dma, 0);
+		      hw_config->dma2, 0);
X 	sound_unload_audiodev(hw_config->slots[0]);
X 	release_region(hw_config->io_base, 4);
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/Config.in linux/drivers/video/Config.in
--- v2.2.0-pre8/linux/drivers/video/Config.in	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/Config.in	Tue Jan 19 10:48:17 1999
@@ -4,6 +4,15 @@
X 
X if [ "$CONFIG_FB" = "y" ]; then
X   define_bool CONFIG_DUMMY_CONSOLE y
+  if [ "$CONFIG_APUS" = "y" ]; then
+    bool 'Permedia2 support' CONFIG_FB_PM2
+    if [ "$CONFIG_FB_PM2" = "y" ]; then
+      bool '  enable FIFO disconnect feature' CONFIG_FB_PM2_FIFO_DISCONNECT
+      if [ "$CONFIG_APUS" = "y" ]; then
+        bool '  Phase5 CVisionPPC/BVisionPPC support' CONFIG_FB_PM2_CVPPC
+      fi
+    fi
+  fi
X   if [ "$CONFIG_ARCH_ACORN" = "y" ]; then
X     bool 'Acorn VIDC support' CONFIG_FB_ACORN
X   fi
@@ -22,7 +31,6 @@
X     tristate 'Amiga CyberVision support' CONFIG_FB_CYBER
X     if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X       bool 'Amiga CyberVision3D support (experimental)' CONFIG_FB_VIRGE
-      bool 'Amiga CyberVisionPPC support (experimental)' CONFIG_FB_CVPPC
X       tristate 'Amiga RetinaZ3 support' CONFIG_FB_RETINAZ3
X       tristate 'Amiga CLgen driver' CONFIG_FB_CLGEN
X     fi
@@ -157,7 +165,7 @@
X 	 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
X 	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
X          "$CONFIG_FB_IGA" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
-         "$CONFIG_FB_CT65550" = "y" ]; then
+         "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
X       define_bool CONFIG_FBCON_CFB8 y
X     else
X       if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
@@ -170,7 +178,7 @@
X 	   "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
X 	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
X            "$CONFIG_FB_IGA" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
-           "$CONFIG_FB_CT65550" = "m" ]; then
+           "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
X 	define_bool CONFIG_FBCON_CFB8 m
X       fi
X     fi
@@ -180,7 +188,8 @@
X 	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
X 	 "$CONFIG_FB_VIRGE" = "y" -o "$CONFIG_FB_CYBER" = "y" -o \
X 	 "$CONFIG_FB_VALKYRIE" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
-	 "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" ]; then
+	 "$CONFIG_FB_CT65550" = "y" -o "$CONFIG_FB_MATROX" = "y" -o \
+	 "$CONFIG_FB_PM2" = "y" ]; then
X       define_bool CONFIG_FBCON_CFB16 y
X     else
X       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
@@ -189,18 +198,19 @@
X 	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
X 	   "$CONFIG_FB_VIRGE" = "m" -o "$CONFIG_FB_CYBER" = "m" -o \
X  	   "$CONFIG_FB_VALKYRIE" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
- 	   "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" ]; then
+ 	   "$CONFIG_FB_CT65550" = "m" -o "$CONFIG_FB_MATROX" = "m" -o \
+	   "$CONFIG_FB_PM2" = "m" ]; then
X 	define_bool CONFIG_FBCON_CFB16 m
X       fi
X     fi
X     if [ "$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
X 	 "$CONFIG_FB_CLGEN" = "y" -o "$CONFIG_FB_VESA" = "y" -o \
-	  "$CONFIG_FB_MATROX" = "y" ]; then
+	  "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
X       define_bool CONFIG_FBCON_CFB24 y
X     else
X       if [ "$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
X 	   "$CONFIG_FB_CLGEN" = "m" -o "$CONFIG_FB_VESA" = "m" -o \
-	   "$CONFIG_FB_MATROX" = "m" ]; then
+	   "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
X 	define_bool CONFIG_FBCON_CFB24 m
X       fi
X     fi
@@ -208,14 +218,14 @@
X 	 "$CONFIG_FB_VESA" = "y" -o "$CONFIG_FB_VIRTUAL" = "y" -o \
X 	 "$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
X 	 "$CONFIG_FB_TGA" = "y" -o "$CONFIG_FB_PLATINUM" = "y" -o \
-	 "$CONFIG_FB_MATROX" = "y" ]; then
+	 "$CONFIG_FB_MATROX" = "y" -o "$CONFIG_FB_PM2" = "y" ]; then
X       define_bool CONFIG_FBCON_CFB32 y
X     else
X       if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
X 	   "$CONFIG_FB_VESA" = "m" -o "$CONFIG_FB_VIRTUAL" = "m" -o \
X 	   "$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
X 	   "$CONFIG_FB_TGA" = "m" -o "$CONFIG_FB_PLATINUM" = "m" -o \
-	   "$CONFIG_FB_MATROX" = "m" ]; then
+	   "$CONFIG_FB_MATROX" = "m" -o "$CONFIG_FB_PM2" = "m" ]; then
X 	define_bool CONFIG_FBCON_CFB32 m
X       fi
X     fi
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/Makefile linux/drivers/video/Makefile
--- v2.2.0-pre8/linux/drivers/video/Makefile	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/Makefile	Tue Jan 19 10:48:17 1999
@@ -79,6 +79,11 @@
X   endif
X endif
X 
+ifeq ($(CONFIG_FB_PM2),y)
+L_OBJS += pm2fb.o
+CONFIG_FBGEN_BUILTIN = y
+endif
+
X ifeq ($(CONFIG_FB_APOLLO),y)
X L_OBJS += dnfb.o
X endif
@@ -121,11 +126,6 @@
X   ifeq ($(CONFIG_FB_CYBER),m)
X   M_OBJS += cyberfb.o
X   endif
-endif
-
-ifeq ($(CONFIG_FB_CVPPC),y)
-L_OBJS += cvppcfb.o
-CONFIG_FBGEN_BUILTIN = y
X endif
X 
X ifeq ($(CONFIG_FB_MAC),y)
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/amifb.c linux/drivers/video/amifb.c
--- v2.2.0-pre8/linux/drivers/video/amifb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/amifb.c	Tue Jan 19 10:47:48 1999
@@ -623,6 +623,7 @@
X 
X static u_long videomemory, spritememory;
X static u_long videomemorysize;
+static u_long videomemory_phys;
X 
X 	/*
X 	 * This is the earliest allowed start of fetching display data.
@@ -1479,8 +1480,7 @@
X 			struct fb_fix_screeninfo fix;
X 
X 			ami_encode_fix(&fix, &par);
-			display->screen_base = 
-				phys_to_virt ((unsigned long) fix.smem_start);
+			display->screen_base = (char *)videomemory;
X 			display->visual = fix.visual;
X 			display->type = fix.type;
X 			display->type_aux = fix.type_aux;
@@ -1877,6 +1877,18 @@
X 	assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
X 	assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
X 
+	/*
+	 * access the videomem with writethrough cache
+	 */
+	videomemory_phys = (u_long)ZTWO_PADDR(videomemory);
+#if 1
+	videomemory = (u_long)ioremap_writethrough(videomemory_phys, videomemorysize);
+#endif
+	if (!videomemory) {
+		printk("amifb: WARNING! unable to map videomem cached writethrough\n");
+		videomemory = ZTWO_VADDR(videomemory_phys);
+	}
+
X 	memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
X 
X 	/*
@@ -2126,7 +2138,7 @@
X {
X 	memset(fix, 0, sizeof(struct fb_fix_screeninfo));
X 	strcpy(fix->id, amifb_name);
-	fix->smem_start = (char*) virt_to_phys((void *)videomemory);
+	fix->smem_start = (char *)videomemory_phys;
X 	fix->smem_len = videomemorysize;
X 
X #ifdef FBCON_HAS_MFB
@@ -2742,16 +2754,16 @@
X 		par->bpl1mod = par->bpl2mod;
X 
X 	if (par->yoffset) {
-		par->bplpt0 = ZTWO_PADDR((u_long)videomemory + par->next_line*par->yoffset + move);
+		par->bplpt0 = videomemory_phys + par->next_line*par->yoffset + move;
X 		if (par->vmode & FB_VMODE_YWRAP) {
X 			if (par->yoffset > par->vyres-par->yres) {
-				par->bplpt0wrap = ZTWO_PADDR((u_long)videomemory + move);
+				par->bplpt0wrap = videomemory_phys + move;
X 				if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
X 					par->bplpt0wrap += par->next_line;
X 			}
X 		}
X 	} else
-		par->bplpt0 = ZTWO_PADDR((u_long)videomemory + move);
+		par->bplpt0 = videomemory_phys + move;
X 
X 	if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
X 		par->bplpt0 += par->next_line;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/atafb.c linux/drivers/video/atafb.c
--- v2.2.0-pre8/linux/drivers/video/atafb.c	Fri Oct  9 13:27:12 1998
+++ linux/drivers/video/atafb.c	Tue Jan 19 10:47:48 1999
@@ -62,6 +62,7 @@
X #include <asm/uaccess.h>
X #include <asm/pgtable.h>
X #include <asm/irq.h>
+#include <asm/io.h>
X 
X #include <asm/atarihw.h>
X #include <asm/atariints.h>
@@ -669,7 +670,7 @@
X 	addr = ((shifter.bas_hi & 0xff) << 16) |
X 	       ((shifter.bas_md & 0xff) << 8)  |
X 	       ((shifter.bas_lo & 0xff));
-	par->screen_base = PTOV(addr);
+	par->screen_base = phys_to_virt(addr);
X }
X 
X static void tt_set_par( struct atafb_par *par )
@@ -1502,7 +1503,7 @@
X 	addr = (shifter.bas_hi & 0xff) << 16 |
X 	       (shifter.bas_md & 0xff) << 8  |
X 	       (shifter.bas_lo & 0xff);
-	par->screen_base = PTOV(addr);
+	par->screen_base = phys_to_virt(addr);
X 
X 	/* derived parameters */
X 	hw->ste_mode = (hw->f_shift & 0x510)==0 && hw->st_shift==0x100;
@@ -1929,7 +1930,7 @@
X 	       ((shifter.bas_md & 0xff) << 8);
X 	if (ATARIHW_PRESENT(EXTD_SHIFTER))
X 		addr |= (shifter.bas_lo & 0xff);
-	par->screen_base = PTOV(addr);
+	par->screen_base = phys_to_virt(addr);
X }
X 
X static void stste_set_par( struct atafb_par *par )
@@ -2026,7 +2027,7 @@
X static void stste_set_screen_base(unsigned long s_base)
X {
X 	unsigned long addr;
-	addr= VTOP(s_base);
+	addr= virt_to_phys(s_base);
X 	/* Setup Screen Memory */
X 	shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
X   	shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
@@ -2297,7 +2298,7 @@
X static void set_screen_base(unsigned long s_base)
X {
X 	unsigned long addr;
-	addr= VTOP(s_base);
+	addr= virt_to_phys(s_base);
X 	/* Setup Screen Memory */
X 	shifter.bas_hi=(unsigned char) ((addr & 0xff0000) >> 16);
X   	shifter.bas_md=(unsigned char) ((addr & 0x00ff00) >> 8);
@@ -2819,9 +2820,9 @@
X 		if (CPU_IS_040_OR_060) {
X 			/* On a '040+, the cache mode of video RAM must be set to
X 			 * write-through also for internal video hardware! */
-			cache_push( VTOP(screen_base), screen_len );
+			cache_push( virt_to_phys(screen_base), screen_len );
X 			kernel_set_cachemode( screen_base, screen_len,
-								  KERNELMAP_NO_COPYBACK );
+					      IOMAP_WRITETHROUGH );
X 		}
X #ifdef ATAFB_EXT
X 	}
@@ -2829,11 +2830,9 @@
X 		/* Map the video memory (physical address given) to somewhere
X 		 * in the kernel address space.
X 		 */
-		external_addr = kernel_map(external_addr, external_len,
-					   KERNELMAP_NO_COPYBACK, NULL);
+		external_addr = ioremap_writethrough(external_addr, external_len);
X 		if (external_vgaiobase)
-			external_vgaiobase = kernel_map(external_vgaiobase,
-				0x10000, KERNELMAP_NOCACHE_SER, NULL);
+			external_vgaiobase = ioremap(external_vgaiobase, 0x10000 );
X 		screen_base      =
X 		real_screen_base = external_addr;
X 		screen_len       = external_len & PAGE_MASK;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
--- v2.2.0-pre8/linux/drivers/video/atyfb.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/video/atyfb.c	Tue Jan 19 10:47:48 1999
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.93 1998/12/18 18:33:13 geert Exp $
+/*  $Id: atyfb.c,v 1.98 1999/01/14 08:50:53 geert Exp $
X  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
X  *
X  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -222,6 +222,7 @@
X 	u32 cfb32[16];
X #endif
X     } fbcon_cmap;
+    u8 blitter_may_be_busy;
X #ifdef __sparc__
X     u8 open;
X     u8 mmaped;
@@ -320,8 +321,7 @@
X #endif
X 
X static void reset_engine(const struct fb_info_aty *info);
-static void init_engine(const struct atyfb_par *par,
-			const struct fb_info_aty *info);
+static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info);
X static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
X static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
X #if defined(__sparc__) || defined(DEBUG)
@@ -533,10 +533,11 @@
X 	   ((u32)(0x8000 >> entries)));
X }
X 
-static inline void wait_for_idle(const struct fb_info_aty *info)
+static inline void wait_for_idle(struct fb_info_aty *info)
X {
X     wait_for_fifo(16, info);
X     while ((aty_ld_le32(GUI_STAT, info) & 1)!= 0);
+    info->blitter_may_be_busy = 0;
X }
X 
X static void reset_engine(const struct fb_info_aty *info)
@@ -553,8 +554,7 @@
X 			  BUS_FIFO_ERR_ACK, info);
X }
X 
-static void init_engine(const struct atyfb_par *par,
-			const struct fb_info_aty *info)
+static void init_engine(const struct atyfb_par *par, struct fb_info_aty *info)
X {
X     u32 pitch_value;
X 
@@ -872,7 +872,8 @@
X 			    aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
X 			    fb);
X 	}
-	wait_for_idle(fb);
+	if (fb->blitter_may_be_busy)
+		wait_for_idle(fb);
X }
X 
X static void
@@ -1608,6 +1609,7 @@
X 	return err;
X 
X     if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
+	 (Gx == GV_CHIP_ID) || (Gx == GW_CHIP_ID) || (Gx == GZ_CHIP_ID) ||
X 	 (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
X 	 (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
X 	 (Gx == VU_CHIP_ID)) && (info->ram_type >= SDRAM))
@@ -1703,6 +1705,8 @@
X 
X     info->current_par = *par;
X 
+    if (info->blitter_may_be_busy)
+	wait_for_idle(info);
X     aty_set_crtc(info, &par->crtc);
X     aty_st_8(CLOCK_CNTL, 0, info);
X     aty_st_8(CLOCK_CNTL, CLOCK_STROBE, info);
@@ -1717,8 +1721,8 @@
X 		break;
X 	}
X 	aty_set_pll_gx(info, &par->pll.gx);
-	aty_st_le32(BUS_CNTL, 0x890e20f1, info);
-	aty_st_le32(DAC_CNTL, 0x47052100, info);
+	aty_st_le32(BUS_CNTL, 0x590e10ff, info);
+	aty_st_le32(DAC_CNTL, 0x47012100, info);
X 
X 	/* Don't forget MEM_CNTL */
X 	i = aty_ld_le32(MEM_CNTL, info) & 0xf0ffffff;
@@ -2472,9 +2476,13 @@
X 					       (Rev == 0x48))) ||
X 		       ((Gx == VT_CHIP_ID) && ((Rev == 0x01) ||
X 					       (Rev == 0x9a))) ||
-		       (Gx == VU_CHIP_ID)) {
+		       Gx == VU_CHIP_ID) {
X 		/* VTA4 or VTB */
X 		pll = 200;
+	    } else if (Gx == VV_CHIP_ID) {
+		/* VT4 */
+		pll = 230;
+		mclk = 83;
X 	    } else if (Gx == VT_CHIP_ID) {
X 		/* other VT */
X 		pll = 135;
@@ -2486,15 +2494,19 @@
X 		       (Gx == GU_CHIP_ID)) {
X 		/* RAGE II+ */
X 		pll = 200;
+	    } else if (Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
+		       Gx == GZ_CHIP_ID) {
+		/* RAGE IIC */
+		pll = 230;
+		mclk = 83;
X 	    } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
X 		       Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
-		       Gx == GQ_CHIP_ID || Gx == VV_CHIP_ID ||
-		       Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
-		       Gx == GZ_CHIP_ID || Gx == LD_CHIP_ID ||
-		       Gx == LG_CHIP_ID || Gx == LB_CHIP_ID ||
+		       Gx == GQ_CHIP_ID || Gx == LB_CHIP_ID ||
+		       Gx == LD_CHIP_ID || Gx == LG_CHIP_ID ||
X 		       Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
-		/* RAGE PRO or IIC */
+		/* RAGE PRO or LT PRO */
X 		pll = 230;
+		mclk = 100;
X 	    } else {
X 		/* other RAGE */
X 		pll = 135;
@@ -3023,12 +3035,9 @@
X 	 *  Map the video memory (physical address given) to somewhere in the
X 	 *  kernel address space.
X 	 */
-	info->frame_buffer = kernel_map(phys_vmembase[m64_num],
-					phys_size[m64_num],
-					KERNELMAP_NOCACHE_SER, NULL);
+	info->frame_buffer = ioremap(phys_vmembase[m64_num], phys_size[m64_num]);
X 	info->frame_buffer_phys = info->frame_buffer;
-	info->ati_regbase = kernel_map(phys_guiregbase[m64_num], 0x10000,
-				       KERNELMAP_NOCACHE_SER, NULL)+0xFC00ul;
+	info->ati_regbase = ioremap(phys_guiregbase[m64_num], 0x10000)+0xFC00ul;
X 	info->ati_regbase_phys = info->ati_regbase;
X 
X 	if (!aty_init(info, "ISA bus")) {
@@ -3416,6 +3425,7 @@
X     wait_for_fifo(2, info);
X     aty_st_le32(DST_Y_X, (x << 16) | y, info);
X     aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height, info);
+    info->blitter_may_be_busy = 1;
X }
X 
X static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
@@ -3578,14 +3588,15 @@
X static void fbcon_aty8_putc(struct vc_data *conp, struct display *p, int c,
X 			    int yy, int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb8_putc(conp, p, c, yy, xx);
X }
X 
@@ -3593,20 +3604,36 @@
X 			     const unsigned short *s, int count, int yy,
X 			     int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
X }
X 
+static void fbcon_aty8_clear_margins(struct vc_data *conp, struct display *p,
+				     int bottom_only)
+{
+    struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+    if (fb->mmaped && currcon == fb->vtconsole)
+	return;
+#endif
+
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
+    fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
X static struct display_switch fbcon_aty8 = {
X     fbcon_cfb8_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty8_putc,
-    fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+    fbcon_aty8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_aty8_clear_margins,
X     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
X };
X #endif
@@ -3615,14 +3642,15 @@
X static void fbcon_aty16_putc(struct vc_data *conp, struct display *p, int c,
X 			     int yy, int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb16_putc(conp, p, c, yy, xx);
X }
X 
@@ -3630,20 +3658,36 @@
X 			      const unsigned short *s, int count, int yy,
X 			      int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
X }
X 
+static void fbcon_aty16_clear_margins(struct vc_data *conp, struct display *p,
+				      int bottom_only)
+{
+    struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+    if (fb->mmaped && currcon == fb->vtconsole)
+	return;
+#endif
+
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
+    fbcon_cfb16_clear_margins(conp, p, bottom_only);
+}
+
X static struct display_switch fbcon_aty16 = {
X     fbcon_cfb16_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty16_putc,
-    fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+    fbcon_aty16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_aty16_clear_margins,
X     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
X };
X #endif
@@ -3652,14 +3696,15 @@
X static void fbcon_aty24_putc(struct vc_data *conp, struct display *p, int c,
X 			     int yy, int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb24_putc(conp, p, c, yy, xx);
X }
X 
@@ -3667,20 +3712,36 @@
X 			      const unsigned short *s, int count, int yy,
X 			      int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
X }
X 
+static void fbcon_aty24_clear_margins(struct vc_data *conp, struct display *p,
+				      int bottom_only)
+{
+    struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+    if (fb->mmaped && currcon == fb->vtconsole)
+	return;
+#endif
+
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
+    fbcon_cfb24_clear_margins(conp, p, bottom_only);
+}
+
X static struct display_switch fbcon_aty24 = {
-    fbcon_cfb24_setup, fbcon_cfb24_bmove, fbcon_cfb24_clear, fbcon_aty24_putc,
-    fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+    fbcon_cfb24_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty24_putc,
+    fbcon_aty24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_aty24_clear_margins,
X     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
X };
X #endif
@@ -3689,14 +3750,15 @@
X static void fbcon_aty32_putc(struct vc_data *conp, struct display *p, int c,
X 			     int yy, int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb32_putc(conp, p, c, yy, xx);
X }
X 
@@ -3704,20 +3766,36 @@
X 			      const unsigned short *s, int count, int yy,
X 			      int xx)
X {
-#ifdef __sparc__
X     struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
X 
+#ifdef __sparc__
X     if (fb->mmaped && currcon == fb->vtconsole)
X 	return;
X #endif
X 
-    wait_for_idle((struct fb_info_aty *)p->fb_info);
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
X     fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
X }
X 
+static void fbcon_aty32_clear_margins(struct vc_data *conp, struct display *p,
+				      int bottom_only)
+{
+    struct fb_info_aty *fb = (struct fb_info_aty *)(p->fb_info);
+
+#ifdef __sparc__
+    if (fb->mmaped && currcon == fb->vtconsole)
+	return;
+#endif
+
+    if (fb->blitter_may_be_busy)
+	wait_for_idle((struct fb_info_aty *)p->fb_info);
+    fbcon_cfb32_clear_margins(conp, p, bottom_only);
+}
+
X static struct display_switch fbcon_aty32 = {
X     fbcon_cfb32_setup, fbcon_aty_bmove, fbcon_aty_clear, fbcon_aty32_putc,
-    fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+    fbcon_aty32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_aty32_clear_margins,
X     FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
X };
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/clgenfb.c linux/drivers/video/clgenfb.c
--- v2.2.0-pre8/linux/drivers/video/clgenfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/clgenfb.c	Tue Jan 19 10:47:48 1999
@@ -16,6 +16,7 @@
X #include <asm/amigahw.h>
X #include <asm/pgtable.h>
X #include <asm/delay.h>
+#include <asm/io.h>
X 
X #include <video/fbcon.h>
X #include <video/fbcon-mfb.h>
@@ -1533,15 +1534,13 @@
X         /* begin of the board, but the begin of RAM. */
X 	/* for P4, map in its address space in 2 chunks (### TEST! ) */
X 	/* (note the ugly hardcoded 16M number) */
-	fb_info->regs = (unsigned char *)kernel_map(board_addr, 16777216, 
-	                                      KERNELMAP_NOCACHE_SER, NULL);
+	fb_info->regs = ioremap(board_addr, 16777216);
X         DEBUG printk(KERN_INFO "clgen: Virtual address for board set to: $%p\n", fb_info->regs);
X 	fb_info->regs += 0x600000;
X 	fb_info->fbregs_phys = board_addr + 0x600000;
X 
X 	fb_info->fbmem_phys = board_addr + 16777216;
-	fb_info->fbmem = kernel_map(fb_info->fbmem_phys, 16777216, 
-			      KERNELMAP_NOCACHE_SER, NULL);
+	fb_info->fbmem = ioremap(fb_info->fbmem_phys, 16777216);
X 	DEBUG printk(KERN_INFO "clgen: (RAM start set to: $%lx)\n", fb_info->fbmem);
X     }
X     else
@@ -1551,8 +1550,7 @@
X 
X 	fb_info->fbmem_phys = board_addr;
X         if (board_addr > 0x01000000)
-	    fb_info->fbmem = kernel_map(board_addr, board_size, 
-				  KERNELMAP_NOCACHE_SER, NULL);
+	    fb_info->fbmem = ioremap(board_addr, board_size);
X 	else
X 	    fb_info->fbmem = ZTWO_VADDR(board_addr);
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/creatorfb.c linux/drivers/video/creatorfb.c
--- v2.2.0-pre8/linux/drivers/video/creatorfb.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/creatorfb.c	Tue Jan 19 10:48:39 1999
@@ -1,4 +1,4 @@
-/* $Id: creatorfb.c,v 1.16 1998/12/21 05:14:39 davem Exp $
+/* $Id: creatorfb.c,v 1.17 1998/12/28 11:23:37 jj Exp $
X  * creatorfb.c: Creator/Creator3D frame buffer driver
X  *
X  * Copyright (C) 1997,1998 Jakub Jelinek (j...@ultra.linux.cz)
@@ -342,6 +342,7 @@
X 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
X 	int x, y, w, h;
X 	
+	FFBWait(fbc);
X 	FFBFifo(fbc, 6);
X 	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p,conp)];
X 	fbc->drawop = FFB_DRAWOP_RECTANGLE;
@@ -360,7 +361,6 @@
X 	fbc->bx = x + fb->x_margin;
X 	fbc->bh = h;
X 	fbc->bw = w;
-	FFBWait(fbc);
X }
X 
X static void ffb_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
@@ -368,6 +368,7 @@
X {
X 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
X 
+	FFBWait(fbc);
X 	FFBFifo(fbc, 2);
X 	fbc->fg = ((u32 *)p->dispsw_data)[attr_bgcol(p,s)];
X 	fbc->drawop = FFB_DRAWOP_RECTANGLE;
@@ -379,7 +380,6 @@
X 		fbc->bw = boxes[2] - boxes[0];
X 		boxes += 4;
X 	}
-	FFBWait(fbc);
X }
X 
X static void ffb_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
@@ -404,6 +404,7 @@
X 		xy += (xx << fontwidthlog(p)) + fb->s.ffb.xy_margin;
X 	else
X 		xy += (xx * fontwidth(p)) + fb->s.ffb.xy_margin;
+	FFBWait(fbc);
X 	FFBFifo(fbc, 5);
X 	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
X 	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
@@ -420,7 +421,6 @@
X 			fd += 2;
X 		}
X 	}
-	FFBWait(fbc);
X }
X 
X static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
@@ -431,6 +431,7 @@
X 	int i, xy;
X 	u8 *fd1, *fd2, *fd3, *fd4;
X 
+	FFBWait(fbc);
X 	FFBFifo(fbc, 2);
X 	fbc->fg = ((u32 *)p->dispsw_data)[attr_fgcol(p,*s)];
X 	fbc->bg = ((u32 *)p->dispsw_data)[attr_bgcol(p,*s)];
@@ -520,7 +521,6 @@
X 		}
X 		xy += fontwidth(p);
X 	}
-	FFBWait(fbc);
X }
X 
X static void ffb_revc(struct display *p, int xx, int yy)
@@ -618,6 +618,7 @@
X {
X 	register struct ffb_fbc *fbc = fb->s.ffb.fbc;
X 
+	FFBWait(fbc);
X 	FFBFifo(fbc, 4);
X 	fbc->ppc = FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE|FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST;
X 	fbc->fbc = 0x2000707f;
@@ -635,7 +636,9 @@
X 	struct display *disp = &fb->disp;
X 	struct fbtype *type = &fb->type;
X 	struct linux_prom64_registers regs[2*PROMREG_MAX];
-	int i;
+	int i, afb = 0;
+	unsigned int btype;
+	char name[64];
X 
X 	if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0)
X 		return NULL;
@@ -644,10 +647,22 @@
X 	if (!disp->dispsw_data)
X 		return NULL;
X 	memset(disp->dispsw_data, 0, 16 * sizeof(u32));
+
+	prom_getstring(fb->prom_node, "name", name, sizeof(name));
+	if (!strcmp(name, "SUNW,afb"))
+		afb = 1;
X 		
-	strcpy(fb->info.modename, "Creator");
+	btype = prom_getintdefault(fb->prom_node, "board_type", 0);
X 		
-	strcpy(fix->id, "Creator");
+	strcpy(fb->info.modename, "Creator");
+	if (!afb) {
+		if ((btype & 7) == 3)
+		    strcpy(fix->id, "Creator 3D");
+		else
+		    strcpy(fix->id, "Creator");
+	} else
+		strcpy(fix->id, "Elite 3D");
+	
X 	fix->visual = FB_VISUAL_TRUECOLOR;
X 	fix->line_length = 8192;
X 	fix->accel = FB_ACCEL_SUN_CREATOR;
@@ -693,7 +708,7 @@
X 	                
X 	i = prom_getintdefault (fb->prom_node, "board_type", 8);
X 	                                                        
-	sprintf(idstring, "Creator at %016lx type %d DAC %d", regs[0].phys_addr, i, fb->s.ffb.dac_rev);
+	sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev);
X 	
X 	return idstring;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/cvisionppc.h linux/drivers/video/cvisionppc.h
--- v2.2.0-pre8/linux/drivers/video/cvisionppc.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/cvisionppc.h	Tue Jan 19 10:48:17 1999
@@ -0,0 +1,51 @@
+/*
+ * Phase5 CybervisionPPC (TVP4020) definitions for the Permedia2 framebuffer
+ * driver.
+ *
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nard...@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * $Id: cvisionppc.h,v 1.1.2.1 1999/01/12 19:52:59 geert Exp $
+ * --------------------------------------------------------------------------
+ * 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.
+ */
+
+#ifndef CVISIONPPC_H
+#define CVISIONPPC_H
+
+#ifndef PM2FB_H
+#include "pm2fb.h"
+#endif
+
+struct cvppc_par {
+	unsigned char* pci_config;
+	unsigned char* pci_bridge;
+	unsigned long user_flags;
+};
+
+#define CSPPC_PCI_BRIDGE		0xfffe0000
+#define CSPPC_BRIDGE_ENDIAN		0x0000
+#define CSPPC_BRIDGE_INT		0x0010
+
+#define	CVPPC_PCI_CONFIG		0xfffc0000
+#define CVPPC_ROM_ADDRESS		0xe2000001
+#define CVPPC_REGS_REGION		0xef000000
+#define CVPPC_FB_APERTURE_ONE		0xe0000000
+#define CVPPC_FB_APERTURE_TWO		0xe1000000
+#define CVPPC_FB_SIZE			0x00800000
+#define CVPPC_MEM_CONFIG_OLD		0xed61fcaa	/* FIXME Fujitsu?? */
+#define CVPPC_MEM_CONFIG_NEW		0xed41c532	/* FIXME USA?? */
+#define CVPPC_MEMCLOCK			83000		/* in KHz */
+
+/* CVPPC_BRIDGE_ENDIAN */
+#define CSPPCF_BRIDGE_BIG_ENDIAN	0x02
+
+/* CVPPC_BRIDGE_INT */
+#define CSPPCF_BRIDGE_ACTIVE_INT2	0x01
+
+#endif	/* CVISIONPPC_H */
+
+/*****************************************************************************
+ * That's all folks!
+ *****************************************************************************/
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/cvppcfb.c linux/drivers/video/cvppcfb.c
--- v2.2.0-pre8/linux/drivers/video/cvppcfb.c	Thu Nov 19 09:56:28 1998
+++ linux/drivers/video/cvppcfb.c	Wed Dec 31 16:00:00 1969
@@ -1,606 +0,0 @@
-/*
- * CybervisionPPC (TVP4020) low level driver for the frame buffer device
- *                          ^^^^^^^^^
- *                          literally ;)
- *
- * Copyright (c) 1998 Ilario Nardinocchi (nard...@CS.UniBO.IT) (v124)
- * --------------------------------------------------------------------------
- * based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven
- * --------------------------------------------------------------------------
- * TODO h/w parameters detect/modify, 8-bit CLUT, acceleration
- * --------------------------------------------------------------------------
- * 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 <linux/config.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/malloc.h>
-#include <linux/delay.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/irq.h>
-#include <asm/pgtable.h>
-#include <asm/amigahw.h>
-#include <video/fbcon.h>
-#include <video/fbcon-cfb8.h>
-#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb32.h>
-#include <asm/setup.h>
-#include <asm/io.h>
-
-#define ISDIGIT(a) ((a)>='0' && (a)<='9')
-
-#undef CVPPCFB_MASTER_DEBUG
-#ifdef CVPPCFB_MASTER_DEBUG
-#define FBEGIN	if (usr_startup.debug>1)\
-			printk(__FUNCTION__ " {\n")
-#define FEND	if (usr_startup.debug>1)\
-			printk("} /* " __FUNCTION__ " */\n")
-#define DPRINTK(a,b...)	if (usr_startup.debug)\
-			printk("%s: " a, __FUNCTION__ , ## b)
-#else
-#define FBEGIN
-#define FEND
-#define DPRINTK(a,b...)
-#endif 
-
-static const char cvppcfb_name[16]="CybervisionPPC";
-
-struct cvppcfb_startup {		/* startup options */
-	char font[40];
-	u32 xres;
-	u32 yres;
-	u32 bpp;
-	unsigned long debug;
-	unsigned long YANW;			/* You Are Not Welcome */
-	struct fb_monspecs monitor;
-};
-static struct cvppcfb_startup usr_startup = {
-	"\0", 640, 480, 16, 0, 1, { 31, 32, 58, 62, 0 } };
-
-#define CVPPC_BASE	0xe0000000
-#define CVPPC_SIZE	0x00800000
-static char* video_base;	/* virtual address of board video memory */
-static unsigned long video_phys;/* physical address of board video memory */
-static u32 video_size;		/* size of board video memory */
-
-struct cvppcfb_par {		/* board parameters (sort of) */
-	u32 xres;
-	u32 yres;
-	u32 vxres;
-	u32 vyres;
-	u32 vxoff;
-	u32 vyoff;
-	u32 bpp;
-	u32 clock;
-	u32 sflags;
-	u32 left;
-	u32 right;
-	u32 top;
-	u32 bottom;
-	u32 hsynclen;
-	u32 vsynclen;
-};
-
-struct cvppcfb_info {
-	struct fb_info_gen gen;
-	struct cvppcfb_par current_par;
-	int current_par_valid;
-	struct display disp;
-	struct {
-		u8 transp;
-		u8 red;
-		u8 green;
-		u8 blue;
-	} palette[256];
-	union {
-#ifdef FBCON_HAS_CFB16
-		u16 cmap16[16];
-#endif
-#ifdef FBCON_HAS_CFB32
-		u32 cmap32[16];
-#endif
-	} cmap;
-};
-static struct cvppcfb_info fb_info;
-
-/*
- * declaration of hw switch functions
- */
-static void cvppcfb_detect(void);
-static int cvppcfb_encode_fix(struct fb_fix_screeninfo* fix,
-				const void* par, struct fb_info_gen* info);
-static int cvppcfb_decode_var(const struct fb_var_screeninfo* var,
-					void* par, struct fb_info_gen* info);
-static int cvppcfb_encode_var(struct fb_var_screeninfo* var,
-				const void* par, struct fb_info_gen* info);
-static void cvppcfb_get_par(void* par, struct fb_info_gen* info);
-static void cvppcfb_set_par(const void* par, struct fb_info_gen* info);
-static int cvppcfb_getcolreg(unsigned regno,
-			unsigned* red, unsigned* green, unsigned* blue,
-				unsigned* transp, struct fb_info* info);
-static int cvppcfb_setcolreg(unsigned regno,
-			unsigned red, unsigned green, unsigned blue,
-				unsigned transp, struct fb_info* info);
-static void cvppcfb_dispsw(const void* par, struct display* disp,
-						struct fb_info_gen* info);
-
-static struct fbgen_hwswitch cvppcfb_hwswitch={
-	cvppcfb_detect, cvppcfb_encode_fix, cvppcfb_decode_var,
-	cvppcfb_encode_var, cvppcfb_get_par, cvppcfb_set_par,
-	cvppcfb_getcolreg, cvppcfb_setcolreg, NULL /* pan_display() */,
-	NULL /* blank() */, cvppcfb_dispsw
-};
-
-/*
- * declaration of ops switch functions
- */
-static int cvppcfb_open(struct fb_info* info, int user);
-static int cvppcfb_release(struct fb_info* info, int user);
-
-static struct fb_ops cvppcfb_ops={
-	cvppcfb_open, cvppcfb_release, fbgen_get_fix, fbgen_get_var,
-	fbgen_set_var, fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display,
-	fbgen_ioctl, NULL /* fb_mmap() */
-};
-
-/*
- * the actual definition of the above mentioned functions follows
- */
-
-/*
- * private functions
- */
-
-static void cvppcfb_set_modename(struct cvppcfb_info* info,
-						struct cvppcfb_startup* s) {
-
-	strcpy(info->gen.info.modename, cvppcfb_name);
-}
-
-static void cvppcfb_decode_opt(struct cvppcfb_startup* s, void* par,
-						struct cvppcfb_info* info) {
-	struct cvppcfb_par* p=(struct cvppcfb_par* )par;
-
-	memset(p, 0, sizeof(struct cvppcfb_par));
-	p->xres=p->vxres=(s->xres+7)&~7;
-	p->yres=p->vyres=s->yres;
-	p->bpp=(s->bpp+7)&~7;
-	if (p->bpp==24)
-		p->bpp=32;
-	if (p->bpp<32)
-		p->clock=6666;
-	else
-		p->clock=10000;
-}
-
-static void cvppcfb_encode_mcap(char* options, struct fb_monspecs* mcap) {
-	char* next;
-	int i=0;
-
-	while (i<4 && options) {
-		if ((next=strchr(options, ';')))
-			*(next++)='\0';
-		switch (i++) {
-			case 0:				/* vmin */
-				mcap->vfmin=(__u16 )
-					simple_strtoul(options, NULL, 0);
-				break;
-			case 1:				/* vmax */
-				mcap->vfmax=(__u16 )
-					simple_strtoul(options, NULL, 0);
-				break;
-			case 2:				/* hmin */
-				mcap->hfmin=(__u32 )
-					simple_strtoul(options, NULL, 0);
-				break;
-			case 3:				/* hmax */
-				mcap->hfmax=(__u32 )
-					simple_strtoul(options, NULL, 0);
-				break;
-		}
-		options=next;
-	}
-}
-
-static void cvppcfb_encode_mode(char* options, struct cvppcfb_startup* s) {
-	char* next;
-	int i=0;
-
-	while (i<3 && options) {
-		if ((next=strchr(options, ';')))
-			*(next++)='\0';
-		switch (i++) {
-			case 0:
-				s->xres=(u32 )
-					simple_strtoul(options, NULL, 0);
-				break;
-			case 1:
-				s->yres=(u32 )
-					simple_strtoul(options, NULL, 0);
-				break;
-			case 2:
-				s->bpp=(u32 )
-					simple_strtoul(options, NULL, 0);
-				break;
-		}
-		options=next;
-	}
-}
-
-/*
- * protected functions
- */
-
-static void cvppcfb_detect(void) {
-
-	FBEGIN;
-	FEND;
-}
-
-static int cvppcfb_encode_fix(struct fb_fix_screeninfo* fix,
-			const void* par, struct fb_info_gen* info) {
-
-	FBEGIN;
-	strcpy(fix->id, cvppcfb_name);
-	fix->smem_start=(char* )video_phys;
-	fix->smem_len=(__u32 )video_size;
-	fix->type=FB_TYPE_PACKED_PIXELS;
-	if (((struct cvppcfb_par* )par)->bpp==8)
-		fix->visual=FB_VISUAL_PSEUDOCOLOR;
-	else
-		fix->visual=FB_VISUAL_TRUECOLOR;
-	fix->xpanstep=fix->ypanstep=fix->ywrapstep=0;
-	fix->line_length=0;			/* computed by fbcon */
-	fix->mmio_start=NULL;
-	fix->mmio_len=0;
-	fix->accel=FB_ACCEL_NONE;
-	FEND;
-	return 0;
-}
-
-static int cvppcfb_decode_var(const struct fb_var_screeninfo* var,
-				void* par, struct fb_info_gen* info) {
-	struct cvppcfb_par p;
-
-	FBEGIN;
-	memset(&p, 0, sizeof(struct cvppcfb_par));
-	p.bpp=(var->bits_per_pixel+7)&~7;
-	if (p.bpp==24)
-		p.bpp=32;
-	if (p.bpp>32) {
-		DPRINTK("depth too big (%lu)\n", p.bpp);
-		return -EINVAL;
-	}
-	p.xres=(var->xres+7)&~7;
-	p.yres=var->yres;
-	if (p.xres<320 || p.yres<200 || p.xres>2048 || p.yres>2048) {
-		DPRINTK("bad resolution (%lux%lu)\n", p.xres, p.yres);
-		return -EINVAL;
-	}
-	p.vxres=(var->xres_virtual+7)&~7;
-	p.vxoff=(var->xoffset+7)&~7;
-	p.vyres=var->yres_virtual;
-	p.vyoff=var->yoffset;
-	if (p.vxres<p.xres+p.vxoff)
-		p.vxres=p.xres+p.vxoff;
-	if (p.vyres<p.yres+p.vyoff)
-		p.vyres=p.yres+p.vyoff;
-	if (p.vxres*p.vyres*p.bpp/8>video_size) {
-		DPRINTK("no memory for screen (%lux%lux%lu)\n",
-						p.vxres, p.vyres, p.bpp);
-		return -EINVAL;
-	}
-	p.sflags=var->sync&(FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT);
-	p.clock=var->pixclock;
-	if (p.clock<6666) {
-		DPRINTK("pixclock too fast (%lu)\n", p.clock);
-		return -EINVAL;
-	}
-	p.left=var->left_margin;
-	p.top=var->upper_margin;
-	p.right=var->right_margin;
-	p.bottom=var->lower_margin;
-	p.hsynclen=var->hsync_len;
-	p.vsynclen=var->vsync_len;
-	*((struct cvppcfb_par* )par)=p;
-	FEND;
-	return 0;
-}
-
-static int cvppcfb_encode_var(struct fb_var_screeninfo* var,
-				const void* par, struct fb_info_gen* info) {
-	struct cvppcfb_par* p=(struct cvppcfb_par* )par;
-	struct fb_var_screeninfo v;
-
-	FBEGIN;
-	memset(&v, 0, sizeof(struct fb_var_screeninfo));
-	v.xres=p->xres;
-	v.yres=p->yres;
-	v.xres_virtual=p->vxres;
-	v.yres_virtual=p->vyres;
-	v.xoffset=p->vxoff;
-	v.yoffset=p->vyoff;
-	v.bits_per_pixel=p->bpp;
-	switch (p->bpp) {
-		case 16:
-			v.red.offset=11;
-			v.red.length=5;
-			v.green.offset=5;
-			v.green.length=6;
-			v.blue.length=5;
-			break;
-		case 32:
-			v.transp.offset=24;
-			v.red.offset=16;
-			v.green.offset=8;
-			v.transp.length=8;
-			/* fallback */
-		case 8:
-			v.red.length=v.green.length=v.blue.length=8;
-			break;
-	}
-	v.activate=FB_ACTIVATE_NOW;
-	v.height=v.width=-1;
-	v.pixclock=p->clock;
-	v.left_margin=p->left;
-	v.right_margin=p->right;
-	v.upper_margin=p->top;
-	v.lower_margin=p->bottom;
-	v.hsync_len=p->hsynclen;
-	v.vsync_len=p->vsynclen;
-	v.sync=p->sflags;
-	v.vmode=FB_VMODE_NONINTERLACED;
-	*var=v;
-	FEND;
-	return 0;
-}
-
-static void cvppcfb_get_par(void* par, struct fb_info_gen* info) {
-	struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-	
-	FBEGIN;
-	if (i->current_par_valid)
-		*((struct cvppcfb_par* )par)=i->current_par;
-	else
-		cvppcfb_decode_opt(&usr_startup, par, i);
-	FEND;
-}
-
-static void cvppcfb_set_par(const void* par, struct fb_info_gen* info) {
-	struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
-	FBEGIN;
-	i->current_par=*((struct cvppcfb_par* )par);
-	i->current_par_valid=1;
-	FEND;
-}
-
-static int cvppcfb_getcolreg(unsigned regno,
-			unsigned* red, unsigned* green, unsigned* blue,
-				unsigned* transp, struct fb_info* info) {
-	struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
-	if (regno<256) {
-		*red=i->palette[regno].red<<8|i->palette[regno].red;
-		*green=i->palette[regno].green<<8|i->palette[regno].green;
-		*blue=i->palette[regno].blue<<8|i->palette[regno].blue;
-		*transp=i->palette[regno].transp<<8|i->palette[regno].transp;
-	}
-	return regno>255;
-}
-
-static int cvppcfb_setcolreg(unsigned regno,
-			unsigned red, unsigned green, unsigned blue,
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 07'
echo 'File patch-2.2.0-pre9 is continued in part 08'
echo 08 > _shar_seq_.tmp
#!/bin/sh
# this is part 08 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 08; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
- unsigned transp, struct fb_info* info) {
-	struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-
-	if (regno<16) {
-		switch (i->current_par.bpp) {
-#ifdef FBCON_HAS_CFB8
-			case 8:
-				DPRINTK("8 bit depth not supported yet.\n");
-				return 1;
-#endif
-#ifdef FBCON_HAS_CFB16
-			case 16:
-				i->cmap.cmap16[regno]=
-					((u32 )red & 0xf800) |
-					(((u32 )green & 0xfc00)>>5) |
-					(((u32 )blue & 0xf800)>>11);
-				break;
-#endif
-#ifdef FBCON_HAS_CFB32
-			case 32:
-	   			i->cmap.cmap32[regno]=
-					(((u32 )transp & 0xff00) << 16) |
-		    			(((u32 )red & 0xff00) << 8) |
-					(((u32 )green & 0xff00)) |
-			 		(((u32 )blue & 0xff00) >> 8);
-				break;
-#endif
-		}
-	}
-	if (regno<256) {
-		i->palette[regno].red=red >> 8;
-		i->palette[regno].green=green >> 8;
-		i->palette[regno].blue=blue >> 8;
-		i->palette[regno].transp=transp >> 8;
-	}
-	return regno>255;
-}
-
-static void cvppcfb_dispsw(const void* par, struct display* disp,
-						struct fb_info_gen* info) {
-	struct cvppcfb_info* i=(struct cvppcfb_info* )info;
-	unsigned long flags;
-
-	FBEGIN;
-	save_flags(flags);
-	cli();
-	switch (((struct cvppcfb_par* )par)->bpp) {
-#ifdef FBCON_HAS_CFB8
-		case 8:
-			disp->dispsw=&fbcon_cfb8;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB16
-		case 16:
-			disp->dispsw=&fbcon_cfb16;
-			disp->dispsw_data=i->cmap.cmap16;
-			break;
-#endif
-#ifdef FBCON_HAS_CFB32
-		case 32:
-			disp->dispsw=&fbcon_cfb32;
-			disp->dispsw_data=i->cmap.cmap32;
-			break;
-#endif
-		default:
-			disp->dispsw=&fbcon_dummy;
-			break;
-	}
-	restore_flags(flags);
-	FEND;
-}
-
-static int cvppcfb_open(struct fb_info* info, int user) {
-
-	MOD_INC_USE_COUNT;
-	return 0;
-}
-
-static int cvppcfb_release(struct fb_info* info, int user) {
-
- MOD_DEC_USE_COUNT;
-	return 0;
-}
-
-/*
- * public functions
- */
-
-void cvppcfb_cleanup(struct fb_info* info) {
-
-	unregister_framebuffer(info);
-}
-
-__initfunc(void cvppcfb_init(void)) {
-
-	FBEGIN;
-#ifdef CVPPCFB_MASTER_DEBUG
-	printk("cvppcfb_init():\n");
-	printk("    resolution %ldx%ldx%ld\n", usr_startup.xres,
-					usr_startup.yres, usr_startup.bpp);
-	printk("    debug: %ld, YANW: %ld\n", usr_startup.debug,
-						usr_startup.YANW);
-	printk("    monitorcap: %ld,%ld,%ld,%ld\n",
-			usr_startup.monitor.vfmin, usr_startup.monitor.vfmax,
-			usr_startup.monitor.hfmin, usr_startup.monitor.hfmax);
-#endif
-	if (usr_startup.YANW)			/* cannot probe yet */
-		return;
-	memset(&fb_info, 0, sizeof(struct cvppcfb_info));
-	video_size=CVPPC_SIZE;
-	video_phys=CVPPC_BASE;
-#ifdef CONFIG_APUS
-	video_base=(char* )
-		kernel_map(video_phys, video_size, KERNELMAP_NOCACHE_SER, NULL);
-#else
-	video_base=ioremap(video_phys, video_size);
-#endif
-	DPRINTK("video_phys=%08lx, video_base=%08lx\n", video_phys, video_base);
-	DPRINTK("phys_to_virt(video_phys)=%08lx\n", phys_to_virt(video_phys));
-	DPRINTK("virt_to_phys(video_base)=%08lx\n", virt_to_phys(video_base));
-	fb_info.disp.scrollmode=SCROLL_YREDRAW;
-	fb_info.gen.parsize=sizeof(struct cvppcfb_par);
-	fb_info.gen.fbhw=&cvppcfb_hwswitch;
-	cvppcfb_set_modename(&fb_info, &usr_startup);
-	fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
-	fb_info.gen.info.fbops=&cvppcfb_ops;
-	fb_info.gen.info.monspecs=usr_startup.monitor;
-	fb_info.gen.info.disp=&fb_info.disp;
-	strcpy(fb_info.gen.info.fontname, usr_startup.font);
-	fb_info.gen.info.switch_con=&fbgen_switch;
-	fb_info.gen.info.updatevar=&fbgen_update_var;
-	fb_info.gen.info.blank=&fbgen_blank;
-	fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
-	if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0) {
-		printk(	"cvppcfb: bad startup configuration: "
-			"unable to register.\n");
-		return;
-	}
-	fbgen_set_disp(-1, &fb_info.gen);
-	fbgen_install_cmap(0, &fb_info.gen);
-	if (register_framebuffer(&fb_info.gen.info)<0) {
-		printk("cvppcfb: unable to register.\n");
-		return;
-	}
-	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
-		GET_FB_IDX(fb_info.gen.info.node), fb_info.gen.info.modename,
-					(unsigned long )(video_size>>10));
-	MOD_INC_USE_COUNT;
-	FEND;
-}
-
-__initfunc(void cvppcfb_setup(char* options, int* ints)) {
-	char* next;
-
-	usr_startup.YANW=0;
-	DPRINTK("options: '%s'\n", options);
-	while (options) {
-		if ((next=strchr(options, ',')))
-			*(next++)='\0';
-		if (!strncmp(options, "monitorcap:", 11))
-			cvppcfb_encode_mcap(options+11, &usr_startup.monitor);
-		else if (!strncmp(options, "debug:", 6)) {
-			if (ISDIGIT(options[6]))
-				usr_startup.debug=options[6]-'0';
-			else
-				usr_startup.debug=1;
-		}
-		else if (!strncmp(options, "mode:", 5))
-			cvppcfb_encode_mode(options+5, &usr_startup);
-		else if (!strncmp(options, "font:", 5))
-			strcpy(usr_startup.font, options+5);
-		else
-			DPRINTK("unrecognized option '%s'\n", options);
-		options=next;
-	}
-#ifdef CVPPCFB_MASTER_DEBUG
-	printk("cvppcfb_setup():\n");
-	printk("    resolution %ldx%ldx%ld\n", usr_startup.xres,
-					usr_startup.yres, usr_startup.bpp);
-	printk("    debug: %ld, YANW: %ld\n", usr_startup.debug,
-						usr_startup.YANW);
-	printk("    monitorcap: %ld,%ld,%ld,%ld\n",
-			usr_startup.monitor.vfmin, usr_startup.monitor.vfmax,
-			usr_startup.monitor.hfmin, usr_startup.monitor.hfmax);
-#endif
-}
-
-/*
- * modularization
- */
-
-#ifdef MODULE
-int init_module(void) {
-
-	cvppcfb_init();
-}
-
-void cleanup_module(void) {
-
-	cvppcfb_cleanup();
-}
-#endif /* MODULE */
-
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/cyberfb.c linux/drivers/video/cyberfb.c
--- v2.2.0-pre8/linux/drivers/video/cyberfb.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/cyberfb.c	Tue Jan 19 10:47:48 1999
@@ -1146,8 +1146,7 @@
X 	DPRINTK("board_addr=%08lx\n", board_addr);
X 	DPRINTK("board_size=%08lx\n", board_size);
X 
-	cv64_mem = kernel_map (board_addr, board_size, KERNELMAP_NOCACHE_SER,
-			       NULL);
+	cv64_mem = ioremap(board_addr, board_size);
X 	cv64_regs = (volatile char *)(cv64_mem + 0x02000000);
X 	cv64_fbmem = cv64_mem + 0x01400000;
X 	DPRINTK("cv64_mem=%08lx cv64_regs=%08lx cv64_fbmem=%08lx\n",
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/fbcon-iplan2p2.c linux/drivers/video/fbcon-iplan2p2.c
--- v2.2.0-pre8/linux/drivers/video/fbcon-iplan2p2.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/fbcon-iplan2p2.c	Tue Jan 19 10:47:48 1999
@@ -10,7 +10,6 @@
X  *  more details.
X  */
X 
-#include <linux/config.h>
X #include <linux/module.h>
X #include <linux/tty.h>
X #include <linux/console.h>
@@ -18,6 +17,7 @@
X #include <linux/fb.h>
X 
X #include <asm/byteorder.h>
+#include <asm/setup.h>
X 
X #include <video/fbcon.h>
X #include <video/fbcon-iplan2p2.h>
@@ -43,7 +43,7 @@
X /* Perform the m68k movepw operation.  */
X static inline void movepw(u8 *d, u16 val)
X {
-#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060
+#if defined __mc68000__ && !defined CPU_M68060_ONLY
X     asm volatile ("movepw %1,%0@(0)" : : "a" (d), "d" (val));
X #else
X     d[0] = (val >> 16) & 0xff;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/fbcon-iplan2p4.c linux/drivers/video/fbcon-iplan2p4.c
--- v2.2.0-pre8/linux/drivers/video/fbcon-iplan2p4.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/fbcon-iplan2p4.c	Tue Jan 19 10:47:48 1999
@@ -10,7 +10,6 @@
X  *  more details.
X  */
X 
-#include <linux/config.h>
X #include <linux/module.h>
X #include <linux/tty.h>
X #include <linux/console.h>
@@ -18,6 +17,7 @@
X #include <linux/fb.h>
X 
X #include <asm/byteorder.h>
+#include <asm/setup.h>
X 
X #include <video/fbcon.h>
X #include <video/fbcon-iplan2p4.h>
@@ -35,7 +35,7 @@
X /* Perform the m68k movepl operation.  */
X static inline void movepl(u8 *d, u32 val)
X {
-#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060
+#if defined __mc68000__ && !defined CPU_M68060_ONLY
X     asm volatile ("movepl %1,%0@(0)" : : "a" (d), "d" (val));
X #else
X     d[0] = (val >> 24) & 0xff;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/fbcon-iplan2p8.c linux/drivers/video/fbcon-iplan2p8.c
--- v2.2.0-pre8/linux/drivers/video/fbcon-iplan2p8.c	Fri Nov 27 13:09:27 1998
+++ linux/drivers/video/fbcon-iplan2p8.c	Tue Jan 19 10:47:48 1999
@@ -10,7 +10,6 @@
X  *  more details.
X  */
X 
-#include <linux/config.h>
X #include <linux/module.h>
X #include <linux/tty.h>
X #include <linux/console.h>
@@ -18,6 +17,7 @@
X #include <linux/fb.h>
X 
X #include <asm/byteorder.h>
+#include <asm/setup.h>
X 
X #include <video/fbcon.h>
X #include <video/fbcon-iplan2p8.h>
@@ -40,7 +40,7 @@
X /* Perform the m68k movepl operation extended to 64 bits.  */
X static inline void movepl2(u8 *d, u32 val1, u32 val2)
X {
-#if defined __mc68000__ && !defined CONFIG_OPTIMIZE_060
+#if defined __mc68000__ && !defined CPU_M68060_ONLY
X     asm volatile ("movepl %1,%0@(0); movepl %2,%0@(8)"
X 		  : : "a" (d), "d" (val1), "d" (val2));
X #else
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/fbcon.c linux/drivers/video/fbcon.c
--- v2.2.0-pre8/linux/drivers/video/fbcon.c	Tue Dec 22 14:16:56 1998
+++ linux/drivers/video/fbcon.c	Tue Jan 19 10:47:48 1999
@@ -536,13 +536,14 @@
X     conp->vc_can_do_color = p->var.bits_per_pixel != 1;
X     conp->vc_complement_mask = conp->vc_can_do_color ? 0x7700 : 0x0800;
X     if (charcnt == 256) {
-    	p->conp->vc_hi_font_mask = 0;
+    	conp->vc_hi_font_mask = 0;
X     	p->fgshift = 8;
X     	p->bgshift = 12;
X     	p->charmask = 0xff;
X     } else {
-    	p->conp->vc_hi_font_mask = 0x100;
-    	p->conp->vc_complement_mask <<= 1;
+    	conp->vc_hi_font_mask = 0x100;
+    	if (conp->vc_can_do_color)
+	    conp->vc_complement_mask <<= 1;
X     	p->fgshift = 9;
X     	p->bgshift = 13;
X     	p->charmask = 0x1ff;
@@ -1333,13 +1334,14 @@
X     p->_fontheight = h;
X     if (p->conp->vc_hi_font_mask && cnt == 256) {
X     	p->conp->vc_hi_font_mask = 0;
-    	p->conp->vc_complement_mask >>= 1;
+    	if (p->conp->vc_can_do_color)
+	    p->conp->vc_complement_mask >>= 1;
X     	p->fgshift--;
X     	p->bgshift--;
X     	p->charmask = 0xff;
X 
X 	/* ++Edmund: reorder the attribute bits */
-	{
+	if (p->conp->vc_can_do_color) {
X 	    struct vc_data *conp = p->conp;
X 	    unsigned short *cp = (unsigned short *) conp->vc_origin;
X 	    int count = conp->vc_screenbuf_size/2;
@@ -1355,7 +1357,8 @@
X 
X     } else if (!p->conp->vc_hi_font_mask && cnt == 512) {
X     	p->conp->vc_hi_font_mask = 0x100;
-    	p->conp->vc_complement_mask <<= 1;
+    	if (p->conp->vc_can_do_color)
+	    p->conp->vc_complement_mask <<= 1;
X     	p->fgshift++;
X     	p->bgshift++;
X     	p->charmask = 0x1ff;
@@ -1367,12 +1370,20 @@
X 	    int count = conp->vc_screenbuf_size/2;
X 	    unsigned short c;
X 	    for (; count > 0; count--, cp++) {
+	        unsigned short newc;
X 	        c = scr_readw(cp);
-		scr_writew(((c & 0xff00) << 1) | (c & 0xff), cp);
+		if (conp->vc_can_do_color)
+		    newc = ((c & 0xff00) << 1) | (c & 0xff);
+		else
+		    newc = c & ~0x100;
+		scr_writew(newc, cp);
X 	    }
X 	    c = conp->vc_video_erase_char;
-	    conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff);
-	    conp->vc_attr <<= 1;
+	    if (conp->vc_can_do_color) {
+		conp->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff);
+		conp->vc_attr <<= 1;
+	    } else
+	        conp->vc_video_erase_char = c & ~0x100;
X 	}
X 
X     }
@@ -1420,7 +1431,10 @@
X     int w = op->width;
X     int h = op->height;
X     int size = h;
-    int i, j, k;
+    int i, k;
+#ifndef CONFIG_FBCON_FONTWIDTH8_ONLY
+    int j;
+#endif
X     u8 *new_data, *data = op->data, *p;
X 
X #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY
@@ -1837,7 +1851,7 @@
X 	    int line_length = p->line_length;
X 
X 	    /* for support of Atari interleaved planes */
-#define MAP_X(x)	(line_length ? x : (x & ~1)*depth + (x & 1))
+#define MAP_X(x)	(line_length ? (x) : ((x) & ~1)*depth + ((x) & 1))
X #else
X #define MAP_X(x)	(x)
X #endif
@@ -1848,7 +1862,7 @@
X 	    src = logo;
X 	    for( y1 = 0; y1 < LOGO_H; y1++ ) {
X 		for( x1 = 0; x1 < LOGO_LINE; x1++, src += logo_depth ) {
-		    dst = fb + y1*line + MAP_X(x1);
+		    dst = fb + y1*line + MAP_X(x/8+x1);
X 		    for( bit = 0; bit < logo_depth; bit++ ) {
X 			val = 0;
X 			for( mask = 0x80, i = 0; i < 8; mask >>= 1, i++ ) {
@@ -1867,7 +1881,7 @@
X 	    if (depth > logo_depth) {
X 		for( y1 = 0; y1 < LOGO_H; y1++ ) {
X 		    for( x1 = 0; x1 < LOGO_LINE; x1++ ) {
-			dst = fb + y1*line + MAP_X(x1) + logo_depth*plane;
+			dst = fb + y1*line + MAP_X(x/8+x1) + logo_depth*plane;
X 			for( i = logo_depth; i < depth; i++, dst += plane )
X 			    *dst = (i == logo_depth && logo_depth == 4)
X 				   ? 0xff : 0x00;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/fbmem.c linux/drivers/video/fbmem.c
--- v2.2.0-pre8/linux/drivers/video/fbmem.c	Wed Jan 13 15:00:43 1999
+++ linux/drivers/video/fbmem.c	Tue Jan 19 10:48:17 1999
@@ -54,8 +54,8 @@
X extern void macfb_setup(char *options, int *ints);
X extern void cyberfb_init(void);
X extern void cyberfb_setup(char *options, int *ints);
-extern void cvppcfb_init(void);
-extern void cvppcfb_setup(char *options, int *ints);
+extern void pm2fb_init(void);
+extern void pm2fb_setup(char *options, int *ints);
X extern void retz3fb_init(void);
X extern void retz3fb_setup(char *options, int *ints);
X extern void clgenfb_init(void);
@@ -112,8 +112,8 @@
X #ifdef CONFIG_FB_CYBER
X 	{ "cyber", cyberfb_init, cyberfb_setup },
X #endif
-#ifdef CONFIG_FB_CVPPC
-	{ "cvppcfb", cvppcfb_init, cvppcfb_setup },
+#ifdef CONFIG_FB_PM2
+	{ "pm2fb", pm2fb_init, pm2fb_setup },
X #endif
X #ifdef CONFIG_FB_CLGEN
X 	{ "clgen", clgenfb_init, clgenfb_setup },
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/offb.c linux/drivers/video/offb.c
--- v2.2.0-pre8/linux/drivers/video/offb.c	Thu Jan  7 15:11:38 1999
+++ linux/drivers/video/offb.c	Tue Jan 19 10:48:41 1999
@@ -400,8 +400,10 @@
X     }
X #endif /* CONFIG_FB_ATY */
X #ifdef CONFIG_FB_S3TRIO
-    if (s3triofb_init_of(dp))
+    if (!strncmp(dp->name, "S3Trio", 6)) {
+    	s3triofb_init_of(dp);
X 	return 1;
+    }
X #endif /* CONFIG_FB_S3TRIO */
X #ifdef CONFIG_FB_IMSTT
X     if (!strncmp(dp->name, "IMS,tt", 6)) {
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/pm2fb.c linux/drivers/video/pm2fb.c
--- v2.2.0-pre8/linux/drivers/video/pm2fb.c	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/pm2fb.c	Tue Jan 19 10:48:17 1999
@@ -0,0 +1,1494 @@
+/*
+ * Permedia2 framebuffer driver.
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nard...@CS.UniBO.IT)
+ * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven.
+ * --------------------------------------------------------------------------
+ * $Id: pm2fb.c,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * --------------------------------------------------------------------------
+ * 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 <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/malloc.h>
+#include <linux/vmalloc.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/selection.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "pm2fb.h"
+#ifdef CONFIG_FB_PM2_CVPPC
+#include "cvisionppc.h"
+#endif
+
+#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)
+#error	"The endianness of the target host has not been defined."
+#endif
+
+#undef PM2FB_MASTER_DEBUG
+#ifdef PM2FB_MASTER_DEBUG
+#define DPRINTK(a,b...)	printk("pm2fb: %s: " a, __FUNCTION__ , ## b)
+#else
+#define DPRINTK(a,b...)
+#endif 
+
+#define PICOS2KHZ(a) (1000000000UL/(a))
+#define KHZ2PICOS(a) (1000000000UL/(a))
+
+#ifdef CONFIG_APUS
+#define MMAP(a,b)	(unsigned char* )kernel_map((unsigned long )(a), \
+					b, KERNELMAP_NOCACHE_SER, NULL)
+#else
+#define MMAP(a,b)	ioremap(a, b)
+#endif
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#ifndef __powerpc__
+#define eieio()
+#endif
+
+struct pm2fb_par {
+	unsigned long pixclock;		/* pixclock in KHz */
+	unsigned long width;		/* width of virtual screen */
+	unsigned long height;		/* height of virtual screen */
+	unsigned long hsstart;		/* horiz. sync start */
+	unsigned long hsend;		/* horiz. sync end */
+	unsigned long hbend;		/* horiz. blank end (also gate end) */
+	unsigned long htotal;		/* total width (w/ sync & blank) */
+	unsigned long vsstart;		/* vert. sync start */
+	unsigned long vsend;		/* vert. sync end */
+	unsigned long vbend;		/* vert. blank end */
+	unsigned long vtotal;		/* total height (w/ sync & blank) */
+	unsigned long stride;		/* screen stride */
+	unsigned long base;		/* screen base (xoffset+yoffset) */
+	unsigned long depth;		/* screen depth (8, 16, 24 or 32) */
+	unsigned long video;		/* video control (hsync,vsync) */
+};
+
+#define OPTF_OLD_MEM		0x00000001
+#define OPTF_YPAN		0x00000002
+static struct {
+	char font[40];
+	unsigned long flags;
+	struct pm2fb_par user_mode;
+} pm2fb_options;
+
+static const struct {
+	char name[16];
+	struct pm2fb_par par;
+} user_mode[] __initdata = {
+	{"640x480-60",
+		{25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}},
+	{"640x480-72",
+		{31199,640,480,6,16,48,207,8,10,39,518,80,0,8,121}},
+	{"640x480-75",
+		{31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}},
+	{"640x480-90",
+		{39909,640,480,8,18,48,207,24,38,53,532,80,0,8,121}},
+	{"640x480-100",
+		{44899,640,480,8,40,52,211,21,33,51,530,80,0,8,121}},
+	{"800x600-56",
+		{35999,800,600,6,24,56,255,0,2,25,624,100,0,8,41}},
+	{"800x600-60",
+		{40000,800,600,10,42,64,263,0,4,28,627,100,0,8,41}},
+	{"800x600-70",
+		{44899,800,600,6,42,52,251,8,20,36,635,100,0,8,105}},
+	{"800x600-72",
+		{50000,800,600,14,44,60,259,36,42,66,665,100,0,8,41}},
+	{"800x600-75",
+		{49497,800,600,4,24,64,263,0,3,25,624,100,0,8,41}},
+	{"800x600-90",
+		{56637,800,600,2,18,48,247,7,18,35,634,100,0,8,41}},
+	{"800x600-100",
+		{67499,800,600,0,16,70,269,6,10,25,624,100,0,8,41}},
+	{"1024x768-60",
+		{64998,1024,768,6,40,80,335,2,8,38,805,128,0,8,121}},
+	{"1024x768-70",
+		{74996,1024,768,6,40,76,331,2,8,38,805,128,0,8,121}},
+	{"1024x768-72",
+		{74996,1024,768,6,40,66,321,2,8,38,805,128,0,8,121}},
+	{"1024x768-75",
+		{78932,1024,768,4,28,72,327,0,3,32,799,128,0,8,41}},
+	{"1024x768-90",
+		{100000,1024,768,0,24,72,327,20,35,77,844,128,0,8,121}},
+	{"1024x768-100",
+		{109998,1024,768,0,22,92,347,0,7,24,791,128,0,8,121}},
+	{"1024x768-illo",
+		{120322,1024,768,12,48,120,375,3,7,32,799,128,0,8,41}},
+	{"1152x864-60",
+		{80000,1152,864,16,44,76,363,5,10,52,915,144,0,8,41}},
+	{"1152x864-70",
+		{100000,1152,864,10,48,90,377,12,23,81,944,144,0,8,41}},
+	{"1152x864-75",
+		{109998,1152,864,6,42,78,365,44,52,138,1001,144,0,8,41}},
+	{"1152x864-80",
+		{109998,1152,864,4,32,72,359,29,36,94,957,144,0,8,41}},
+	{"1280x1024-60",
+		{107991,1280,1024,12,40,102,421,0,3,42,1065,160,0,8,41}},
+	{"1280x1024-70",
+		{125992,1280,1024,20,48,102,421,0,5,42,1065,160,0,8,41}},
+	{"1280x1024-74",
+		{134989,1280,1024,8,44,108,427,0,29,40,1063,160,0,8,41}},
+	{"1280x1024-75",
+		{134989,1280,1024,4,40,102,421,0,3,42,1065,160,0,8,41}},
+	{"1600x1200-60",
+		{155981,1600,1200,8,48,112,511,9,17,70,1269,200,0,8,121}},
+	{"1600x1200-66",
+		{171998,1600,1200,10,44,120,519,2,5,53,1252,200,0,8,121}},
+	{"1600x1200-76",
+		{197980,1600,1200,10,44,120,519,2,7,50,1249,200,0,8,121}},
+	{"\0", },
+};
+
+static const char permedia2_name[16]="Permedia2";
+
+static struct pm2fb_info {
+	struct fb_info_gen gen;
+	int board;			/* Permedia2 board index (see
+					   board_table[] below) */
+	struct {
+		unsigned char* fb_base;	/* framebuffer memory base */
+		unsigned long  fb_size;	/* framebuffer memory size */
+		unsigned char* rg_base;	/* register memory base */
+		unsigned char* p_fb;	/* physical address of frame buffer */
+		unsigned char* v_fb;	/* virtual address of frame buffer */
+		unsigned char* p_regs;	/* physical address of registers
+					   region, must be rg_base or
+					   rg_base+PM2_REGS_SIZE depending on
+					   the host endianness */
+		unsigned char* v_regs;	/* virtual address of p_regs */
+	} regions;
+	union {				/* here, the per-board par structs */
+#ifdef CONFIG_FB_PM2_CVPPC
+		struct cvppc_par cvppc;	/* CVisionPPC data */
+#endif
+	} board_par;
+	struct pm2fb_par current_par;	/* displayed screen */
+	int current_par_valid;
+	unsigned long memclock;		/* memclock (set by the per-board
+					   		init routine) */
+	struct display disp;
+	struct {
+		u8 transp;
+		u8 red;
+		u8 green;
+		u8 blue;
+	} palette[256];
+	union {
+#ifdef FBCON_HAS_CFB16
+		u16 cmap16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+		u32 cmap24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+		u32 cmap32[16];
+#endif
+	} cmap;
+} fb_info;
+
+#ifdef CONFIG_FB_PM2_CVPPC
+static int cvppc_detect(struct pm2fb_info*);
+static void cvppc_init(struct pm2fb_info*);
+#endif
+
+/*
+ * Table of the supported Permedia2 based boards.
+ * Three hooks are defined for each board:
+ * detect(): should return 1 if the related board has been detected, 0
+ *           otherwise. It should also fill the fields 'regions.fb_base',
+ *           'regions.fb_size', 'regions.rg_base' and 'memclock' in the
+ *           passed pm2fb_info structure.
+ * init(): called immediately after the reset of the Permedia2 chip.
+ *         It should reset the memory controller if needed (the MClk
+ *         is set shortly afterwards by the caller).
+ * cleanup(): called after the driver has been unregistered.
+ *
+ * the init and cleanup pointers can be NULL.
+ */
+static const struct {
+	int (*detect)(struct pm2fb_info*);
+	void (*init)(struct pm2fb_info*);
+	void (*cleanup)(struct pm2fb_info*);
+	char name[32];
+} board_table[] = {
+#ifdef CONFIG_FB_PM2_CVPPC
+	{ cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" },
+#endif
+	{ NULL, }
+};
+
+/*
+ * partial products for the supported horizontal resolutions.
+ */
+#define PACKPP(p0,p1,p2)	(((p2)<<6)|((p1)<<3)|(p0))
+static const struct {
+	unsigned short width;
+	unsigned short pp;
+} pp_table[] = {
+	{ 32,	PACKPP(1, 0, 0) }, { 64,	PACKPP(1, 1, 0) },
+	{ 96,	PACKPP(1, 1, 1) }, { 128,	PACKPP(2, 1, 1) },
+	{ 160,	PACKPP(2, 2, 1) }, { 192,	PACKPP(2, 2, 2) },
+	{ 224,	PACKPP(3, 2, 1) }, { 256,	PACKPP(3, 2, 2) },
+	{ 288,	PACKPP(3, 3, 1) }, { 320,	PACKPP(3, 3, 2) },
+	{ 384,	PACKPP(3, 3, 3) }, { 416,	PACKPP(4, 3, 1) },
+	{ 448,	PACKPP(4, 3, 2) }, { 512,	PACKPP(4, 3, 3) },
+	{ 544,	PACKPP(4, 4, 1) }, { 576,	PACKPP(4, 4, 2) },
+	{ 640,	PACKPP(4, 4, 3) }, { 768,	PACKPP(4, 4, 4) },
+	{ 800,	PACKPP(5, 4, 1) }, { 832,	PACKPP(5, 4, 2) },
+	{ 896,	PACKPP(5, 4, 3) }, { 1024,	PACKPP(5, 4, 4) },
+	{ 1056,	PACKPP(5, 5, 1) }, { 1088,	PACKPP(5, 5, 2) },
+	{ 1152,	PACKPP(5, 5, 3) }, { 1280,	PACKPP(5, 5, 4) },
+	{ 1536,	PACKPP(5, 5, 5) }, { 1568,	PACKPP(6, 5, 1) },
+	{ 1600,	PACKPP(6, 5, 2) }, { 1664,	PACKPP(6, 5, 3) },
+	{ 1792,	PACKPP(6, 5, 4) }, { 2048,	PACKPP(6, 5, 5) },
+	{ 0,	0 } };
+
+static void pm2fb_detect(void);
+static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
+				const void* par, struct fb_info_gen* info);
+static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
+					void* par, struct fb_info_gen* info);
+static int pm2fb_encode_var(struct fb_var_screeninfo* var,
+				const void* par, struct fb_info_gen* info);
+static void pm2fb_get_par(void* par, struct fb_info_gen* info);
+static void pm2fb_set_par(const void* par, struct fb_info_gen* info);
+static int pm2fb_getcolreg(unsigned regno,
+			unsigned* red, unsigned* green, unsigned* blue,
+				unsigned* transp, struct fb_info* info);
+static int pm2fb_setcolreg(unsigned regno,
+			unsigned red, unsigned green, unsigned blue,
+				unsigned transp, struct fb_info* info);
+static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);
+static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
+					struct fb_info_gen* info);
+static void pm2fb_dispsw(const void* par, struct display* disp,
+						struct fb_info_gen* info);
+
+static struct fbgen_hwswitch pm2fb_hwswitch={
+	pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var,
+	pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par,
+	pm2fb_getcolreg, pm2fb_setcolreg, pm2fb_pan_display,
+	pm2fb_blank, pm2fb_dispsw
+};
+
+static int pm2fb_open(struct fb_info* info, int user);
+static int pm2fb_release(struct fb_info* info, int user);
+
+static struct fb_ops pm2fb_ops={
+	pm2fb_open, pm2fb_release, fbgen_get_fix, fbgen_get_var,
+	fbgen_set_var, fbgen_get_cmap, fbgen_set_cmap, fbgen_pan_display,
+	NULL /* fb_ioctl() */, NULL /* fb_mmap() */
+};
+
+/***************************************************************************
+ * Begin of Permedia2 specific functions
+ ***************************************************************************/
+
+inline static unsigned long RD32(unsigned char* base, long off) {
+
+	return *((volatile unsigned long* )(base+off));
+}
+
+inline static void WR32(unsigned char* base, long off, unsigned long v) {
+
+	*((volatile unsigned long* )(base+off))=v;
+}
+
+inline static unsigned long pm2_RD(struct pm2fb_info* p, long off) {
+
+	return RD32(p->regions.v_regs, off);
+}
+
+inline static void pm2_WR(struct pm2fb_info* p, long off, unsigned long v) {
+
+	WR32(p->regions.v_regs, off, v);
+}
+
+inline static unsigned long pm2_RDAC_RD(struct pm2fb_info* p, long idx) {
+
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+	eieio();
+	return pm2_RD(p, PM2R_RD_INDEXED_DATA);
+}
+
+inline static void pm2_RDAC_WR(struct pm2fb_info* p, long idx,
+						unsigned long v) {
+
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);
+	eieio();
+	pm2_WR(p, PM2R_RD_INDEXED_DATA, v);
+}
+
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+#define WAIT_FIFO(p,a)
+#else
+inline static void WAIT_FIFO(struct pm2fb_info* p, unsigned long a) {
+
+	while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a);
+	eieio();
+}
+#endif
+
+static unsigned long partprod(unsigned long xres) {
+	int i;
+
+	for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++);
+	if (!pp_table[i].width)
+		DPRINTK("invalid width %lu\n", xres);
+	return pp_table[i].pp;
+}
+
+static unsigned long to3264(unsigned long timing, int bpp, int is64) {
+
+	switch (bpp) {
+		case 8:
+			timing=timing>>(2+is64);
+			break;
+		case 16:
+			timing=timing>>(1+is64);
+			break;
+		case 24:
+			timing=(timing*3)>>(2+is64);
+			break;
+		case 32:
+			if (is64)
+				timing=timing>>1;
+			break;
+	}
+	return timing;
+}
+
+static unsigned long from3264(unsigned long timing, int bpp, int is64) {
+
+	switch (bpp) {
+		case 8:
+			timing=timing<<(2+is64);
+			break;
+		case 16:
+			timing=timing<<(1+is64);
+			break;
+		case 24:
+			timing=(timing<<(2+is64))/3;
+			break;
+		case 32:
+			if (is64)
+				timing=timing<<1;
+			break;
+	}
+	return timing;
+}
+
+static void mnp(unsigned long clk, unsigned char* mm, unsigned char* nn,
+							unsigned char* pp) {
+	unsigned char m;
+	unsigned char n;
+	unsigned char p;
+	unsigned long f;
+	long current;
+	long delta=100000;
+
+	*mm=*nn=*pp=0;
+	for (n=2; n<15; n++) {
+		for (m=2; m; m++) {
+			f=PM2_REFERENCE_CLOCK*m/n;
+			if (f>=150000 && f<=300000) {
+				for (p=0; p<5; p++, f>>=1) {
+					current=clk>f?clk-f:f-clk;
+					if (current<delta) {
+						delta=current;
+						*mm=m;
+						*nn=n;
+						*pp=p;
+					}
+				}
+			}
+		}
+	}
+}
+
+static void wait_pm2(struct pm2fb_info* i) {
+
+	WAIT_FIFO(i, 1);
+	pm2_WR(i, PM2R_SYNC, 0);
+	eieio();
+	do {
+		while (pm2_RD(i, PM2R_OUT_FIFO_WORDS)==0);
+		eieio();
+	} while (pm2_RD(i, PM2R_OUT_FIFO)!=PM2TAG(PM2R_SYNC));
+}
+
+static void set_memclock(struct pm2fb_info* info, unsigned long clk) {
+	int i;
+	unsigned char m, n, p;
+
+	mnp(clk, &m, &n, &p);
+	WAIT_FIFO(info, 5);
+	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 6);
+	eieio();
+	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_1, m);
+	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_2, n);
+	eieio();
+	pm2_RDAC_WR(info, PM2I_RD_MEMORY_CLOCK_3, 8|p);
+	eieio();
+	pm2_RDAC_RD(info, PM2I_RD_MEMORY_CLOCK_STATUS);
+	eieio();
+	for (i=256; i &&
+		!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
+}
+
+static void set_pixclock(struct pm2fb_info* info, unsigned long clk) {
+	int i;
+	unsigned char m, n, p;
+
+	mnp(clk, &m, &n, &p);
+	WAIT_FIFO(info, 5);
+	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 0);
+	eieio();
+	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A1, m);
+	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A2, n);
+	eieio();
+	pm2_RDAC_WR(info, PM2I_RD_PIXEL_CLOCK_A3, 8|p);
+	eieio();
+	pm2_RDAC_RD(info, PM2I_RD_PIXEL_CLOCK_STATUS);
+	eieio();
+	for (i=256; i &&
+		!(pm2_RD(info, PM2R_RD_INDEXED_DATA)&PM2F_PLL_LOCKED); i--);
+}
+
+static void set_color(struct pm2fb_info* p, unsigned char regno,
+			unsigned char r, unsigned char g, unsigned char b) {
+
+	WAIT_FIFO(p, 4);
+	eieio();
+	pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, regno);
+	eieio();
+	pm2_WR(p, PM2R_RD_PALETTE_DATA, r);
+	eieio();
+	pm2_WR(p, PM2R_RD_PALETTE_DATA, g);
+	eieio();
+	pm2_WR(p, PM2R_RD_PALETTE_DATA, b);
+}
+
+static void set_aperture(struct pm2fb_info* i, struct pm2fb_par* p) {
+
+	WAIT_FIFO(i, 2);
+#ifdef __LITTLE_ENDIAN
+	pm2_WR(i, PM2R_APERTURE_ONE, 0);	/* FIXME */
+	pm2_WR(i, PM2R_APERTURE_TWO, 0);
+#else
+	switch (p->depth) {
+		case 8:
+		case 24:
+			pm2_WR(i, PM2R_APERTURE_ONE, 0);
+			pm2_WR(i, PM2R_APERTURE_TWO, 1);
+			break;
+		case 16:
+			pm2_WR(i, PM2R_APERTURE_ONE, 2);
+			pm2_WR(i, PM2R_APERTURE_TWO, 1);
+			break;
+		case 32:
+			pm2_WR(i, PM2R_APERTURE_ONE, 1);
+			pm2_WR(i, PM2R_APERTURE_TWO, 1);
+			break;
+	}
+#endif
+}
+
+static void set_screen(struct pm2fb_info* i, struct pm2fb_par* p) {
+	unsigned long clrmode=0;
+	unsigned long txtmap=0;
+	unsigned long xres;
+
+	xres=(p->width+31)&~31;
+	set_aperture(i, p);
+	WAIT_FIFO(i, 22);
+	pm2_RDAC_WR(i, PM2I_RD_COLOR_KEY_CONTROL, p->depth==8?0:
+						PM2F_COLOR_KEY_TEST_OFF);
+	switch (p->depth) {
+		case 8:
+			pm2_WR(i, PM2R_FB_READ_PIXEL, 0);
+			break;
+		case 16:
+			pm2_WR(i, PM2R_FB_READ_PIXEL, 1);
+			clrmode=PM2F_RD_TRUECOLOR|0x06;
+			txtmap=PM2F_TEXTEL_SIZE_16;
+			break;
+		case 32:
+			pm2_WR(i, PM2R_FB_READ_PIXEL, 2);
+			clrmode=PM2F_RD_TRUECOLOR|0x08;
+			txtmap=PM2F_TEXTEL_SIZE_32;
+			break;
+		case 24:
+			pm2_WR(i, PM2R_FB_READ_PIXEL, 4);
+			clrmode=PM2F_RD_TRUECOLOR|0x09;
+			txtmap=PM2F_TEXTEL_SIZE_24;
+			break;
+	}
+	pm2_WR(i, PM2R_SCREEN_SIZE, (p->height<<16)|p->width);
+	pm2_WR(i, PM2R_SCISSOR_MODE, PM2F_SCREEN_SCISSOR_ENABLE);
+	pm2_WR(i, PM2R_FB_WRITE_MODE, PM2F_FB_WRITE_ENABLE);
+	pm2_WR(i, PM2R_FB_READ_MODE, partprod(xres));
+	pm2_WR(i, PM2R_LB_READ_MODE, partprod(xres));
+	pm2_WR(i, PM2R_TEXTURE_MAP_FORMAT, txtmap|partprod(xres));
+	pm2_WR(i, PM2R_H_TOTAL, p->htotal);
+	pm2_WR(i, PM2R_HS_START, p->hsstart);
+	pm2_WR(i, PM2R_HS_END, p->hsend);
+	pm2_WR(i, PM2R_HG_END, p->hbend);
+	pm2_WR(i, PM2R_HB_END, p->hbend);
+	pm2_WR(i, PM2R_V_TOTAL, p->vtotal);
+	pm2_WR(i, PM2R_VS_START, p->vsstart);
+	pm2_WR(i, PM2R_VS_END, p->vsend);
+	pm2_WR(i, PM2R_VB_END, p->vbend);
+	pm2_WR(i, PM2R_SCREEN_STRIDE, p->stride);
+	eieio();
+	pm2_WR(i, PM2R_SCREEN_BASE, p->base);
+	pm2_RDAC_WR(i, PM2I_RD_COLOR_MODE, PM2F_RD_COLOR_MODE_RGB|
+						PM2F_RD_GUI_ACTIVE|clrmode);
+	pm2_WR(i, PM2R_VIDEO_CONTROL, p->video);
+	set_pixclock(i, p->pixclock);
+};
+
+/***************************************************************************
+ * Begin of generic initialization functions
+ ***************************************************************************/
+
+static void pm2fb_reset(struct pm2fb_info* p) {
+
+	pm2_WR(p, PM2R_RESET_STATUS, 0);
+	eieio();
+	while (pm2_RD(p, PM2R_RESET_STATUS)&PM2F_BEING_RESET);
+	eieio();
+#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT
+	DPRINTK("FIFO disconnect enabled\n");
+	pm2_WR(p, PM2R_FIFO_DISCON, 1);
+#endif
+	eieio();
+	if (board_table[p->board].init)
+		board_table[p->board].init(p);
+	WAIT_FIFO(p, 48);
+	pm2_WR(p, PM2R_CHIP_CONFIG, pm2_RD(p, PM2R_CHIP_CONFIG)&
+					~(PM2F_VGA_ENABLE|PM2F_VGA_FIXED));
+	pm2_WR(p, PM2R_BYPASS_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FRAMEBUFFER_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FIFO_CONTROL, 0);
+	pm2_WR(p, PM2R_FILTER_MODE, PM2F_SYNCHRONIZATION);
+	pm2_WR(p, PM2R_APERTURE_ONE, 0);
+	pm2_WR(p, PM2R_APERTURE_TWO, 0);
+	pm2_WR(p, PM2R_LB_READ_FORMAT, 0);
+	pm2_WR(p, PM2R_LB_WRITE_FORMAT, 0); 
+	pm2_WR(p, PM2R_LB_READ_MODE, 0);
+	pm2_WR(p, PM2R_LB_SOURCE_OFFSET, 0);
+	pm2_WR(p, PM2R_FB_SOURCE_OFFSET, 0);
+	pm2_WR(p, PM2R_FB_PIXEL_OFFSET, 0);
+	pm2_WR(p, PM2R_WINDOW_ORIGIN, 0);
+	pm2_WR(p, PM2R_FB_WINDOW_BASE, 0);
+	pm2_WR(p, PM2R_LB_WINDOW_BASE, 0);
+	pm2_WR(p, PM2R_FB_SOFT_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FB_HARD_WRITE_MASK, ~(0L));
+	pm2_WR(p, PM2R_FB_READ_PIXEL, 0);
+	pm2_WR(p, PM2R_DITHER_MODE, 0);
+	pm2_WR(p, PM2R_AREA_STIPPLE_MODE, 0);
+	pm2_WR(p, PM2R_DEPTH_MODE, 0);
+	pm2_WR(p, PM2R_STENCIL_MODE, 0);
+	pm2_WR(p, PM2R_TEXTURE_ADDRESS_MODE, 0);
+	pm2_WR(p, PM2R_TEXTURE_READ_MODE, 0);
+	pm2_WR(p, PM2R_TEXEL_LUT_MODE, 0);
+	pm2_WR(p, PM2R_YUV_MODE, 0);
+	pm2_WR(p, PM2R_COLOR_DDA_MODE, 0);
+	pm2_WR(p, PM2R_TEXTURE_COLOR_MODE, 0);
+	pm2_WR(p, PM2R_FOG_MODE, 0);
+	pm2_WR(p, PM2R_ALPHA_BLEND_MODE, 0);
+	pm2_WR(p, PM2R_LOGICAL_OP_MODE, 0);
+	pm2_WR(p, PM2R_STATISTICS_MODE, 0);
+	pm2_WR(p, PM2R_SCISSOR_MODE, 0);
+	pm2_RDAC_WR(p, PM2I_RD_CURSOR_CONTROL, 0);
+	pm2_RDAC_WR(p, PM2I_RD_MISC_CONTROL, PM2F_RD_PALETTE_WIDTH_8);
+	pm2_RDAC_WR(p, PM2I_RD_COLOR_KEY_CONTROL, 0);
+	pm2_RDAC_WR(p, PM2I_RD_OVERLAY_KEY, 0);
+	pm2_RDAC_WR(p, PM2I_RD_RED_KEY, 0);
+	pm2_RDAC_WR(p, PM2I_RD_GREEN_KEY, 0);
+	pm2_RDAC_WR(p, PM2I_RD_BLUE_KEY, 0);
+	eieio();
+	set_memclock(p, p->memclock);
+}
+
+__initfunc(static int pm2fb_conf(struct pm2fb_info* p)) {
+
+	for (p->board=0; board_table[p->board].detect &&
+			!(board_table[p->board].detect(p)); p->board++);
+	if (!board_table[p->board].detect) {
+		DPRINTK("no board found.\n");
+		return 0;
+	}
+	DPRINTK("found board: %s\n", board_table[p->board].name);
+	p->regions.p_fb=p->regions.fb_base;
+	p->regions.v_fb=MMAP(p->regions.p_fb, p->regions.fb_size);
+#ifdef __LITTLE_ENDIAN
+	p->regions.p_regs=p->regions.rg_base;
+#else
+	p->regions.p_regs=p->regions.rg_base+PM2_REGS_SIZE;
+#endif
+	p->regions.v_regs=MMAP(p->regions.p_regs, PM2_REGS_SIZE);
+	return 1;
+}
+
+/***************************************************************************
+ * Begin of per-board initialization functions
+ ***************************************************************************/
+
+#ifdef CONFIG_FB_PM2_CVPPC
+static int cvppc_PCI_init(struct cvppc_par* p) {
+	extern unsigned long powerup_PCI_present;
+
+	if (!powerup_PCI_present) {
+		DPRINTK("no PCI bridge detected\n");
+		return 0;
+	}
+	if (!(p->pci_config=MMAP(CVPPC_PCI_CONFIG, 256))) {
+		DPRINTK("unable to map PCI config region\n");
+		return 0;
+	}
+	if (RD32(p->pci_config, PCI_VENDOR_ID)!=
+			((PCI_DEVICE_ID_TI_TVP4020<<16)|PCI_VENDOR_ID_TI)) {
+		DPRINTK("bad vendorID/deviceID\n");
+		return 0;
+	}
+	if (!(p->pci_bridge=MMAP(CSPPC_PCI_BRIDGE, 256))) {
+		DPRINTK("unable to map PCI bridge\n");
+		return 0;
+	}
+	WR32(p->pci_bridge, CSPPC_BRIDGE_ENDIAN, CSPPCF_BRIDGE_BIG_ENDIAN);
+	eieio();
+	if (pm2fb_options.flags & OPTF_OLD_MEM)
+		WR32(p->pci_config, PCI_CACHE_LINE_SIZE, 0xff00);
+	WR32(p->pci_config, PCI_BASE_ADDRESS_0, CVPPC_REGS_REGION);
+	WR32(p->pci_config, PCI_BASE_ADDRESS_1, CVPPC_FB_APERTURE_ONE);
+	WR32(p->pci_config, PCI_BASE_ADDRESS_2, CVPPC_FB_APERTURE_TWO);
+	WR32(p->pci_config, PCI_ROM_ADDRESS, CVPPC_ROM_ADDRESS);
+	eieio();
+	WR32(p->pci_config, PCI_COMMAND, 0xef000000 |
+						PCI_COMMAND_IO |
+						PCI_COMMAND_MEMORY |
+						PCI_COMMAND_MASTER);
+	return 1;
+}
+
+static int cvppc_detect(struct pm2fb_info* p) {
+
+	if (!cvppc_PCI_init(&p->board_par.cvppc))
+		return 0;
+	p->regions.fb_base=(unsigned char* )CVPPC_FB_APERTURE_ONE;
+	p->regions.fb_size=CVPPC_FB_SIZE;
+	p->regions.rg_base=(unsigned char* )CVPPC_REGS_REGION;
+	p->memclock=CVPPC_MEMCLOCK;
+	return 1;
+}
+
+static void cvppc_init(struct pm2fb_info* p) {
+
+	WAIT_FIFO(p, 3);
+	pm2_WR(p, PM2R_MEM_CONTROL, 0);
+	pm2_WR(p, PM2R_BOOT_ADDRESS, 0x30);
+	eieio();
+	if (pm2fb_options.flags & OPTF_OLD_MEM)
+		pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_OLD);
+	else
+		pm2_WR(p, PM2R_MEM_CONFIG, CVPPC_MEM_CONFIG_NEW);
+}
+#endif /* CONFIG_FB_PM2_CVPPC */
+
+/***************************************************************************
+ * Console hw acceleration
+ ***************************************************************************/
+
+/*
+ * copy with packed pixels (8/16bpp only).
+ */
+static void pm2fb_pp_copy(struct pm2fb_info* i, long xsrc, long ysrc,
+					long x, long y, long w, long h) {
+	long scale=i->current_par.depth==8?2:1;
+	long offset;
+
+	if (!w || !h)
+		return;
+	WAIT_FIFO(i, 7);
+	pm2_WR(i, PM2R_CONFIG,	PM2F_CONFIG_FB_WRITE_ENABLE|
+				PM2F_CONFIG_FB_PACKED_DATA|
+				PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+	pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+	pm2_WR(i, PM2R_FB_SOURCE_DELTA,	((ysrc-y)&0xfff)<<16|
+						((xsrc-x)&0xfff));
+	offset=(x&0x3)-(xsrc&0x3);
+	pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|(x>>scale));
+	pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|((w+7)>>scale));
+	pm2_WR(i, PM2R_PACKED_DATA_LIMITS, (offset<<29)|(x<<16)|(x+w));
+	eieio();
+	pm2_WR(i, PM2R_RENDER,	PM2F_RENDER_RECTANGLE|
+				(x<xsrc?PM2F_INCREASE_X:0)|
+				(y<ysrc?PM2F_INCREASE_Y:0));
+	wait_pm2(i);
+}
+
+/*
+ * block operation. copy=0: rectangle fill, copy=1: rectangle copy.
+ */
+static void pm2fb_block_op(struct pm2fb_info* i, int copy,
+					long xsrc, long ysrc,
+					long x, long y, long w, long h,
+					unsigned long color) {
+
+	if (!w || !h)
+		return;
+	WAIT_FIFO(i, 6);
+	pm2_WR(i, PM2R_CONFIG,	PM2F_CONFIG_FB_WRITE_ENABLE|
+				PM2F_CONFIG_FB_READ_SOURCE_ENABLE);
+	pm2_WR(i, PM2R_FB_PIXEL_OFFSET, 0);
+	if (copy)
+		pm2_WR(i, PM2R_FB_SOURCE_DELTA,	((ysrc-y)&0xfff)<<16|
+							((xsrc-x)&0xfff));
+	else
+		pm2_WR(i, PM2R_FB_BLOCK_COLOR, color);
+	pm2_WR(i, PM2R_RECTANGLE_ORIGIN, (y<<16)|x);
+	pm2_WR(i, PM2R_RECTANGLE_SIZE, (h<<16)|w);
+	eieio();
+	pm2_WR(i, PM2R_RENDER,	PM2F_RENDER_RECTANGLE|
+				(x<xsrc?PM2F_INCREASE_X:0)|
+				(y<ysrc?PM2F_INCREASE_Y:0)|
+				(copy?0:PM2F_RENDER_FASTFILL));
+	wait_pm2(i);
+}
+
+static int pm2fb_blank(int blank_mode, struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+	unsigned long video;
+
+	if (!i->current_par_valid)
+		return 1;
+	video=i->current_par.video;
+	if (blank_mode>0) {
+		switch (blank_mode-1) {
+			case VESA_NO_BLANKING:		/* FIXME */
+				video=video&~(PM2F_VIDEO_ENABLE);
+				break;
+			case VESA_HSYNC_SUSPEND:
+				video=video&~(PM2F_HSYNC_MASK|
+						PM2F_BLANK_LOW);
+				break;
+			case VESA_VSYNC_SUSPEND:
+				video=video&~(PM2F_VSYNC_MASK|
+						PM2F_BLANK_LOW);
+				break;
+			case VESA_POWERDOWN:
+				video=video&~(PM2F_VSYNC_MASK|
+						PM2F_HSYNC_MASK|
+						PM2F_BLANK_LOW);
+				break;
+		}
+	}
+	WAIT_FIFO(i, 1);
+	pm2_WR(i, PM2R_VIDEO_CONTROL, video);
+	return 0;
+}
+
+static int pm2fb_pan_display(const struct fb_var_screeninfo* var,
+					struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+	if (!i->current_par_valid)
+		return -EINVAL;
+	i->current_par.base=to3264(var->yoffset*i->current_par.width+
+				var->xoffset, i->current_par.depth, 1);
+	WAIT_FIFO(i, 1);
+	pm2_WR(i, PM2R_SCREEN_BASE, i->current_par.base);
+	return 0;
+}
+
+static void pm2fb_pp_bmove(struct display* p, int sy, int sx,
+				int dy, int dx, int height, int width) {
+
+	if (fontwidthlog(p)) {
+		sx=sx<<fontwidthlog(p);
+		dx=dx<<fontwidthlog(p);
+		width=width<<fontwidthlog(p);
+	}
+	else {
+		sx=sx*fontwidth(p);
+		dx=dx*fontwidth(p);
+		width=width*fontwidth(p);
+	}
+	sy=sy*fontheight(p);
+	dy=dy*fontheight(p);
+	height=height*fontheight(p);
+	pm2fb_pp_copy((struct pm2fb_info* )p->fb_info, sx, sy, dx,
+							dy, width, height);
+}
+
+static void pm2fb_bmove(struct display* p, int sy, int sx,
+				int dy, int dx, int height, int width) {
+
+	if (fontwidthlog(p)) {
+		sx=sx<<fontwidthlog(p);
+		dx=dx<<fontwidthlog(p);
+		width=width<<fontwidthlog(p);
+	}
+	else {
+		sx=sx*fontwidth(p);
+		dx=dx*fontwidth(p);
+		width=width*fontwidth(p);
+	}
+	sy=sy*fontheight(p);
+	dy=dy*fontheight(p);
+	height=height*fontheight(p);
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 1, sx, sy, dx, dy,
+							width, height, 0);
+}
+
+#ifdef FBCON_HAS_CFB8
+static void pm2fb_clear8(struct vc_data* conp, struct display* p,
+				int sy, int sx, int height, int width) {
+	unsigned long c;
+
+	sx=sx*fontwidth(p);
+	width=width*fontwidth(p);
+	sy=sy*fontheight(p);
+	height=height*fontheight(p);
+	c=attr_bgcol_ec(p, conp);
+	c|=c<<8;
+	c|=c<<16;
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
+							width, height, c);
+}
+
+static void pm2fb_clear_margins8(struct vc_data* conp, struct display* p,
+							int bottom_only) {
+	unsigned long c;
+	unsigned long sx;
+	unsigned long sy;
+
+	c=attr_bgcol_ec(p, conp);
+	c|=c<<8;
+	c|=c<<16;
+	sx=conp->vc_cols*fontwidth(p);
+	sy=conp->vc_rows*fontheight(p);
+	if (!bottom_only)
+		pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+			sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+				0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
+}
+
+static struct display_switch pm2_cfb8 = {
+	fbcon_cfb8_setup, pm2fb_pp_bmove, pm2fb_clear8,
+	fbcon_cfb8_putc, fbcon_cfb8_putcs, fbcon_cfb8_revc,
+	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_clear_margins8,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB8 */
+
+#ifdef FBCON_HAS_CFB16
+static void pm2fb_clear16(struct vc_data* conp, struct display* p,
+				int sy, int sx, int height, int width) {
+	unsigned long c;
+
+	sx=sx*fontwidth(p);
+	width=width*fontwidth(p);
+	sy=sy*fontheight(p);
+	height=height*fontheight(p);
+	c=((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+	c|=c<<16;
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
+							width, height, c);
+}
+
+static void pm2fb_clear_margins16(struct vc_data* conp, struct display* p,
+							int bottom_only) {
+	unsigned long c;
+	unsigned long sx;
+	unsigned long sy;
+
+	c = ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+	c|=c<<16;
+	sx=conp->vc_cols*fontwidth(p);
+	sy=conp->vc_rows*fontheight(p);
+	if (!bottom_only)
+		pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+			sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+				0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
+}
+
+static struct display_switch pm2_cfb16 = {
+	fbcon_cfb16_setup, pm2fb_pp_bmove, pm2fb_clear16,
+	fbcon_cfb16_putc, fbcon_cfb16_putcs, fbcon_cfb16_revc,
+	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_clear_margins16,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB16 */
+
+#ifdef FBCON_HAS_CFB24
+/*
+ * fast fill for 24bpp works only when red==green==blue
+ */
+static void pm2fb_clear24(struct vc_data* conp, struct display* p,
+				int sy, int sx, int height, int width) {
+	struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
+	unsigned long c;
+
+	c=attr_bgcol_ec(p, conp);
+	if (		i->palette[c].red==i->palette[c].green &&
+			i->palette[c].green==i->palette[c].blue) {
+		c=((u32 *)p->dispsw_data)[c];
+		c|=(c&0xff0000)<<8;
+		sx=sx*fontwidth(p);
+		width=width*fontwidth(p);
+		sy=sy*fontheight(p);
+		height=height*fontheight(p);
+		pm2fb_block_op(i, 0, 0, 0, sx, sy, width, height, c);
+	}
+	else
+		fbcon_cfb24_clear(conp, p, sy, sx, height, width);
+
+}
+
+static void pm2fb_clear_margins24(struct vc_data* conp, struct display* p,
+							int bottom_only) {
+	struct pm2fb_info* i=(struct pm2fb_info* )p->fb_info;
+	unsigned long c;
+	unsigned long sx;
+	unsigned long sy;
+
+	c=attr_bgcol_ec(p, conp);
+	if (		i->palette[c].red==i->palette[c].green &&
+			i->palette[c].green==i->palette[c].blue) {
+		c=((u32 *)p->dispsw_data)[c];
+		c|=(c&0xff0000)<<8;
+		sx=conp->vc_cols*fontwidth(p);
+		sy=conp->vc_rows*fontheight(p);
+		if (!bottom_only)
+		pm2fb_block_op(i, 0, 0, 0, sx, 0, (p->var.xres-sx),
+							p->var.yres_virtual, c);
+		pm2fb_block_op(i, 0, 0, 0, 0, p->var.yoffset+sy,
+						sx, p->var.yres-sy, c);
+	}
+	else
+		fbcon_cfb24_clear_margins(conp, p, bottom_only);
+
+}
+
+static struct display_switch pm2_cfb24 = {
+	fbcon_cfb24_setup, pm2fb_bmove, pm2fb_clear24,
+	fbcon_cfb24_putc, fbcon_cfb24_putcs, fbcon_cfb24_revc,
+	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_clear_margins24,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB24 */
+
+#ifdef FBCON_HAS_CFB32
+static void pm2fb_clear32(struct vc_data* conp, struct display* p,
+				int sy, int sx, int height, int width) {
+	unsigned long c;
+
+	sx=sx*fontwidth(p);
+	width=width*fontwidth(p);
+	sy=sy*fontheight(p);
+	height=height*fontheight(p);
+	c=((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0, sx, sy,
+							width, height, c);
+}
+
+static void pm2fb_clear_margins32(struct vc_data* conp, struct display* p,
+							int bottom_only) {
+	unsigned long c;
+	unsigned long sx;
+	unsigned long sy;
+
+	c = ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)];
+	sx=conp->vc_cols*fontwidth(p);
+	sy=conp->vc_rows*fontheight(p);
+	if (!bottom_only)
+		pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+			sx, 0, (p->var.xres-sx), p->var.yres_virtual, c);
+	pm2fb_block_op((struct pm2fb_info* )p->fb_info, 0, 0, 0,
+				0, p->var.yoffset+sy, sx, p->var.yres-sy, c);
+}
+
+static struct display_switch pm2_cfb32 = {
+	fbcon_cfb32_setup, pm2fb_bmove, pm2fb_clear32,
+	fbcon_cfb32_putc, fbcon_cfb32_putcs, fbcon_cfb32_revc,
+	NULL /* cursor() */, NULL /* set_font() */,
+	pm2fb_clear_margins32,
+	FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16) };
+#endif /* FBCON_HAS_CFB32 */
+
+/***************************************************************************
+ * Framebuffer functions
+ ***************************************************************************/
+
+static void pm2fb_detect(void) {}
+
+static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,
+			const void* par, struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+	struct pm2fb_par* p=(struct pm2fb_par* )par;
+
+	strcpy(fix->id, permedia2_name);
+	fix->smem_start=i->regions.p_fb;
+	fix->smem_len=i->regions.fb_size;
+	fix->mmio_start=i->regions.p_regs;
+	fix->mmio_len=PM2_REGS_SIZE;
+	fix->accel=FB_ACCEL_3DLABS_PERMEDIA2;
+	fix->type=FB_TYPE_PACKED_PIXELS;
+	fix->visual=p->depth==8?FB_VISUAL_PSEUDOCOLOR:FB_VISUAL_TRUECOLOR;
+	fix->line_length=0;
+	fix->xpanstep=p->depth==24?8:64/p->depth;
+	fix->ypanstep=1;
+	fix->ywrapstep=0;
+	return 0;
+}
+
+static int pm2fb_decode_var(const struct fb_var_screeninfo* var,
+				void* par, struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+	struct pm2fb_par p;
+	unsigned long xres;
+	int data64;
+
+	memset(&p, 0, sizeof(struct pm2fb_par));
+	p.width=(var->xres_virtual+7)&~7;
+	p.height=var->yres_virtual;
+	p.depth=(var->bits_per_pixel+7)&~7;
+	p.depth=p.depth>32?32:p.depth;
+	data64=p.depth>8;
+	xres=(var->xres+31)&~31;
+	if (p.width==~(0L))
+		p.width=xres;
+	if (p.height==~(0L))
+		p.height=var->yres;
+	if (p.width<xres+var->xoffset)
+		p.width=xres+var->xoffset;
+	if (p.height<var->yres+var->yoffset)
+		p.height=var->yres+var->yoffset;
+	if (!partprod(xres)) {
+		DPRINTK("width not supported: %lu\n", xres);
+		return -EINVAL;
+	}
+	if (p.width>2047) {
+		DPRINTK("virtual width not supported: %lu\n", p.width);
+		return -EINVAL;
+	}
+	if (var->yres<200) {
+		DPRINTK("height not supported: %lu\n",
+						(unsigned long )var->yres);
+		return -EINVAL;
+	}
+	if (p.height<200 || p.height>2047) {
+		DPRINTK("virtual height not supported: %lu\n", p.height);
+		return -EINVAL;
+	}
+	if (p.width*p.height*p.depth/8>i->regions.fb_size) {
+		DPRINTK("no memory for screen (%lux%lux%lu)\n",
+						xres, p.height, p.depth);
+		return -EINVAL;
+	}
+	p.pixclock=PICOS2KHZ(var->pixclock);
+	if (p.pixclock>PM2_MAX_PIXCLOCK) {
+		DPRINTK("pixclock too high (%luKHz)\n", p.pixclock);
+		return -EINVAL;
+	}
+	p.hsstart=to3264(var->right_margin, p.depth, data64);
+	p.hsend=p.hsstart+to3264(var->hsync_len, p.depth, data64);
+	p.hbend=p.hsend+to3264(var->left_margin, p.depth, data64);
+	p.htotal=to3264(xres, p.depth, data64)+p.hbend-1;
+	p.vsstart=var->lower_margin?var->lower_margin-1:0;	/* FIXME! */
+	p.vsend=var->lower_margin+var->vsync_len-1;
+	p.vbend=var->lower_margin+var->vsync_len+var->upper_margin;
+	p.vtotal=var->yres+p.vbend-1;
+	p.stride=to3264(p.width, p.depth, 1);
+	p.base=to3264(var->yoffset*xres+var->xoffset, p.depth, 1);
+	if (data64)
+		p.video|=PM2F_DATA_64_ENABLE;
+	if (var->sync & FB_SYNC_HOR_HIGH_ACT)
+		p.video|=PM2F_HSYNC_ACT_HIGH;
+	else
+		p.video|=PM2F_HSYNC_ACT_LOW;
+	if (var->sync & FB_SYNC_VERT_HIGH_ACT)
+		p.video|=PM2F_VSYNC_ACT_HIGH;
+	else
+		p.video|=PM2F_VSYNC_ACT_LOW;
+	if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_INTERLACED) {
+		DPRINTK("interlaced not supported\n");
+		return -EINVAL;
+	}
+	if ((var->vmode & FB_VMODE_MASK)==FB_VMODE_DOUBLE)
+		p.video|=PM2F_LINE_DOUBLE;
+	if (var->activate==FB_ACTIVATE_NOW)
+		p.video|=PM2F_VIDEO_ENABLE;
+	*((struct pm2fb_par* )par)=p;
+	return 0;
+}
+
+static int pm2fb_encode_var(struct fb_var_screeninfo* var,
+				const void* par, struct fb_info_gen* info) {
+	struct pm2fb_par* p=(struct pm2fb_par* )par;
+	struct fb_var_screeninfo v;
+	unsigned long base;
+
+	memset(&v, 0, sizeof(struct fb_var_screeninfo));
+	v.xres_virtual=p->width;
+	v.yres_virtual=p->height;
+	v.xres=(p->htotal+1)-p->hbend;
+	v.yres=(p->vtotal+1)-p->vbend;
+	v.right_margin=p->hsstart;
+	v.hsync_len=p->hsend-p->hsstart;
+	v.left_margin=p->hbend-p->hsend;
+	v.lower_margin=p->vsstart+1;
+	v.vsync_len=p->vsend-v.lower_margin+1;
+	v.upper_margin=p->vbend-v.lower_margin-v.vsync_len;
+	v.bits_per_pixel=p->depth;
+	if (p->video & PM2F_DATA_64_ENABLE) {
+		v.xres=v.xres<<1;
+		v.right_margin=v.right_margin<<1;
+		v.hsync_len=v.hsync_len<<1;
+		v.left_margin=v.left_margin<<1;
+	}
+	switch (p->depth) {
+		case 8:
+			v.red.length=v.green.length=v.blue.length=8;
+			v.xres=v.xres<<2;
+			v.right_margin=v.right_margin<<2;
+			v.hsync_len=v.hsync_len<<2;
+			v.left_margin=v.left_margin<<2;
+			break;
+		case 16:
+			v.red.offset=11;
+			v.red.length=5;
+			v.green.offset=5;
+			v.green.length=6;
+			v.blue.length=5;
+			v.xres=v.xres<<1;
+			v.right_margin=v.right_margin<<1;
+			v.hsync_len=v.hsync_len<<1;
+			v.left_margin=v.left_margin<<1;
+			break;
+		case 32:
+			v.transp.offset=24;
+			v.red.offset=16;
+			v.green.offset=8;
+			v.red.length=v.green.length=v.blue.length=
+							v.transp.length=8;
+			break;
+		case 24:
+			v.blue.offset=16;
+			v.green.offset=8;
+			v.red.length=v.green.length=v.blue.length=8;
+			v.xres=(v.xres<<2)/3;
+			v.right_margin=(v.right_margin<<2)/3;
+			v.hsync_len=(v.hsync_len<<2)/3;
+			v.left_margin=(v.left_margin<<2)/3;
+			break;
+	}
+	base=from3264(p->base, p->depth, 1);
+	v.xoffset=base%v.xres;
+	v.yoffset=base/v.xres;
+	v.height=v.width=-1;
+	v.pixclock=KHZ2PICOS(p->pixclock);
+	if ((p->video & PM2F_HSYNC_MASK)==PM2F_HSYNC_ACT_HIGH)
+		v.sync|=FB_SYNC_HOR_HIGH_ACT;
+	if ((p->video & PM2F_VSYNC_MASK)==PM2F_VSYNC_ACT_HIGH)
+		v.sync|=FB_SYNC_VERT_HIGH_ACT;
+	if (p->video & PM2F_LINE_DOUBLE)
+		v.vmode=FB_VMODE_DOUBLE;
+	*var=v;
+	return 0;
+}
+
+static void set_user_mode(struct pm2fb_info* i) {
+
+	memcpy(&i->current_par, &pm2fb_options.user_mode,
+						sizeof(i->current_par));
+	if (pm2fb_options.flags & OPTF_YPAN) {
+		i->current_par.height=i->regions.fb_size/
+			(i->current_par.width*i->current_par.depth/8);
+		i->current_par.height=MIN(i->current_par.height,2047);
+		i->current_par.height=MAX(i->current_par.height,
+						pm2fb_options.user_mode.height);
+	}
+}
+
+static void pm2fb_get_par(void* par, struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+	
+	if (!i->current_par_valid) {
+		set_user_mode(i);
+		pm2fb_reset(i);
+		set_screen(i, &i->current_par);
+		i->current_par_valid=1;
+	}
+	*((struct pm2fb_par* )par)=i->current_par;
+}
+
+static void pm2fb_set_par(const void* par, struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+	struct pm2fb_par* p;
+
+	p=(struct pm2fb_par* )par;
+	if (i->current_par_valid) {
+		i->current_par.base=p->base;
+		if (!memcmp(p, &i->current_par, sizeof(struct pm2fb_par))) {
+			WAIT_FIFO(i, 1);
+			pm2_WR(i, PM2R_SCREEN_BASE, p->base);
+			return;
+		}
+	}
+	i->current_par=*p;
+	i->current_par_valid=1;
+	set_screen(i, &i->current_par);
+}
+
+static int pm2fb_getcolreg(unsigned regno,
+			unsigned* red, unsigned* green, unsigned* blue,
+				unsigned* transp, struct fb_info* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+	if (regno<256) {
+		*red=i->palette[regno].red<<8|i->palette[regno].red;
+		*green=i->palette[regno].green<<8|i->palette[regno].green;
+		*blue=i->palette[regno].blue<<8|i->palette[regno].blue;
+		*transp=i->palette[regno].transp<<8|i->palette[regno].transp;
+	}
+	return regno>255;
+}
+
+static int pm2fb_setcolreg(unsigned regno,
+			unsigned red, unsigned green, unsigned blue,
+				unsigned transp, struct fb_info* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+	if (regno<16) {
+		switch (i->current_par.depth) {
+#ifdef FBCON_HAS_CFB8
+			case 8:
+				break;
+#endif
+#ifdef FBCON_HAS_CFB16
+			case 16:
+				i->cmap.cmap16[regno]=
+					((u32 )red & 0xf800) |
+					(((u32 )green & 0xfc00)>>5) |
+					(((u32 )blue & 0xf800)>>11);
+				break;
+#endif
+#ifdef FBCON_HAS_CFB24
+			case 24:
+				i->cmap.cmap24[regno]=
+					(((u32 )blue & 0xff00) << 8) |
+					((u32 )green & 0xff00) |
+					(((u32 )red & 0xff00) >> 8);
+				break;
+#endif
+#ifdef FBCON_HAS_CFB32
+			case 32:
+	   			i->cmap.cmap32[regno]=
+					(((u32 )transp & 0xff00) << 16) |
+		    			(((u32 )red & 0xff00) << 8) |
+					(((u32 )green & 0xff00)) |
+			 		(((u32 )blue & 0xff00) >> 8);
+				break;
+#endif
+			default:
+				DPRINTK("bad depth %lu\n",
+						i->current_par.depth);
+				break;
+		}
+	}
+	if (regno<256) {
+		i->palette[regno].red=red >> 8;
+		i->palette[regno].green=green >> 8;
+		i->palette[regno].blue=blue >> 8;
+		i->palette[regno].transp=transp >> 8;
+		if (i->current_par.depth==8)
+			set_color(i, regno, red>>8, green>>8, blue>>8);
+	}
+	return regno>255;
+}
+
+static void pm2fb_dispsw(const void* par, struct display* disp,
+						struct fb_info_gen* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+	unsigned long flags;
+	unsigned long depth;
+
+	save_flags(flags);
+	cli();
+	switch (depth=((struct pm2fb_par* )par)->depth) {
+#ifdef FBCON_HAS_CFB8
+		case 8:
+			disp->dispsw=&pm2_cfb8;
+			break;
+#endif
+#ifdef FBCON_HAS_CFB16
+		case 16:
+			disp->dispsw=&pm2_cfb16;
+			disp->dispsw_data=i->cmap.cmap16;
+			break;
+#endif
+#ifdef FBCON_HAS_CFB24
+		case 24:
+			disp->dispsw=&pm2_cfb24;
+			disp->dispsw_data=i->cmap.cmap24;
+			break;
+#endif
+#ifdef FBCON_HAS_CFB32
+		case 32:
+			disp->dispsw=&pm2_cfb32;
+			disp->dispsw_data=i->cmap.cmap32;
+			break;
+#endif
+		default:
+			disp->dispsw=&fbcon_dummy;
+			break;
+	}
+	restore_flags(flags);
+}
+
+static int pm2fb_open(struct fb_info* info, int user) {
+
+	MOD_INC_USE_COUNT;
+	return 0;
+}
+
+static int pm2fb_release(struct fb_info* info, int user) {
+
+	MOD_DEC_USE_COUNT;
+	return 0;
+}
+
+/***************************************************************************
+ * Begin of public functions
+ ***************************************************************************/
+
+void pm2fb_cleanup(struct fb_info* info) {
+	struct pm2fb_info* i=(struct pm2fb_info* )info;
+
+	unregister_framebuffer(info);
+	pm2fb_reset(i);
+	/* FIXME UNMAP()??? */
+	if (board_table[i->board].cleanup)
+		board_table[i->board].cleanup(i);
+}
+
+__initfunc(void pm2fb_init(void)) {
+
+	memset(&fb_info, 0, sizeof(fb_info));
+	if (!pm2fb_conf(&fb_info))
+		return;
+	fb_info.disp.scrollmode=SCROLL_YNOMOVE;
+	fb_info.gen.parsize=sizeof(struct pm2fb_par);
+	fb_info.gen.fbhw=&pm2fb_hwswitch;
+	strcpy(fb_info.gen.info.modename, permedia2_name);
+	fb_info.gen.info.flags=FBINFO_FLAG_DEFAULT;
+	fb_info.gen.info.fbops=&pm2fb_ops;
+	fb_info.gen.info.disp=&fb_info.disp;
+	strcpy(fb_info.gen.info.fontname, pm2fb_options.font);
+	fb_info.gen.info.switch_con=&fbgen_switch;
+	fb_info.gen.info.updatevar=&fbgen_update_var;
+	fb_info.gen.info.blank=&fbgen_blank;
+	fbgen_get_var(&fb_info.disp.var, -1, &fb_info.gen.info);
+	if (fbgen_do_set_var(&fb_info.disp.var, 1, &fb_info.gen)<0)
+		return;
+	fbgen_set_disp(-1, &fb_info.gen);
+	fbgen_install_cmap(0, &fb_info.gen);
+	if (register_framebuffer(&fb_info.gen.info)<0) {
+		printk("pm2fb: unable to register.\n");
+		return;
+	}
+	printk("fb%d: %s (%s), using %ldK of video memory.\n",
+				GET_FB_IDX(fb_info.gen.info.node),
+				board_table[fb_info.board].name,
+				permedia2_name,
+				(unsigned long )(fb_info.regions.fb_size>>10));
+	MOD_INC_USE_COUNT;
+}
+
+__initfunc(void pm2fb_mode_setup(char* options)) {
+	int i;
+
+	for (i=0; user_mode[i].name[0] &&
+		strcmp(options, user_mode[i].name); i++);
+	if (user_mode[i].name[0])
+		memcpy(&pm2fb_options.user_mode, &user_mode[i].par,
+					sizeof(pm2fb_options.user_mode));
+}
+
+__initfunc(void pm2fb_font_setup(char* options)) {
+
+	strncpy(pm2fb_options.font, options, sizeof(pm2fb_options.font));
+	pm2fb_options.font[sizeof(pm2fb_options.font)-1]='\0';
+}
+
+__initfunc(void pm2fb_setup(char* options, int* ints)) {
+	char* next;
+
+	memset(&pm2fb_options, 0, sizeof(pm2fb_options));
+	memcpy(&pm2fb_options.user_mode, &user_mode[0].par,
+				sizeof(pm2fb_options.user_mode));
+	while (options) {
+		if ((next=strchr(options, ',')))
+			*(next++)='\0';
+		if (!strncmp(options, "font:", 5))
+			pm2fb_font_setup(options+5);
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 08'
echo 'File patch-2.2.0-pre9 is continued in part 09'
echo 09 > _shar_seq_.tmp
#!/bin/sh
# this is part 09 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 09; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
+		else if (!strncmp(options, "mode:", 5))
+			pm2fb_mode_setup(options+5);
+		else if (!strcmp(options, "ypan"))
+			pm2fb_options.flags |= OPTF_YPAN;
+		else if (!strcmp(options, "oldmem"))
+			pm2fb_options.flags |= OPTF_OLD_MEM;
+		options=next;
+	}
+}
+
+/***************************************************************************
+ * Begin of module functions
+ ***************************************************************************/
+
+#ifdef MODULE
+int init_module(void) {
+
+	pm2fb_init();
+}
+
+void cleanup_module(void) {
+
+	pm2fb_cleanup();
+}
+#endif /* MODULE */
+
+/***************************************************************************
+ * That's all folks!
+ ***************************************************************************/
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/pm2fb.h linux/drivers/video/pm2fb.h
--- v2.2.0-pre8/linux/drivers/video/pm2fb.h	Wed Dec 31 16:00:00 1969
+++ linux/drivers/video/pm2fb.h	Tue Jan 19 10:48:17 1999
@@ -0,0 +1,181 @@
+/*
+ * Permedia2 framebuffer driver definitions.
+ * Copyright (c) 1998-1999 Ilario Nardinocchi (nard...@CS.UniBO.IT)
+ * --------------------------------------------------------------------------
+ * $Id: pm2fb.h,v 1.1.2.1 1999/01/12 19:53:02 geert Exp $
+ * --------------------------------------------------------------------------
+ * 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.
+ */
+
+#ifndef PM2FB_H
+#define PM2FB_H
+
+#define PM2_REFERENCE_CLOCK	14318			/* in KHz */
+#define PM2_MAX_PIXCLOCK	230000			/* in KHz */
+#define PM2_REGS_SIZE		0x10000
+
+#define PM2TAG(r) (unsigned long )(((r)-0x8000)>>3)
+
+/*****************************************************************************
+ * Permedia2 registers used in the framebuffer
+ *****************************************************************************/
+ 
+#define PM2R_RESET_STATUS				0x0000
+#define PM2R_IN_FIFO_SPACE				0x0018
+#define PM2R_OUT_FIFO_WORDS				0x0020
+#define PM2R_APERTURE_ONE				0x0050
+#define PM2R_APERTURE_TWO				0x0058
+#define PM2R_FIFO_DISCON				0x0068
+#define PM2R_CHIP_CONFIG				0x0070
+
+#define PM2R_REBOOT					0x1000
+#define PM2R_MEM_CONTROL				0x1040
+#define PM2R_BOOT_ADDRESS				0x1080
+#define PM2R_MEM_CONFIG					0x10c0
+#define PM2R_BYPASS_WRITE_MASK				0x1100
+#define PM2R_FRAMEBUFFER_WRITE_MASK			0x1140
+
+#define PM2R_OUT_FIFO					0x2000
+
+#define PM2R_SCREEN_BASE				0x3000
+#define PM2R_SCREEN_STRIDE				0x3008
+#define PM2R_H_TOTAL					0x3010
+#define PM2R_HG_END					0x3018
+#define PM2R_HB_END					0x3020
+#define PM2R_HS_START					0x3028
+#define PM2R_HS_END					0x3030
+#define PM2R_V_TOTAL					0x3038
+#define PM2R_VB_END					0x3040
+#define PM2R_VS_START					0x3048
+#define PM2R_VS_END					0x3050
+#define PM2R_VIDEO_CONTROL				0x3058
+#define PM2R_LINE_COUNT					0x3070
+#define PM2R_FIFO_CONTROL				0x3078
+
+#define PM2R_RD_PALETTE_WRITE_ADDRESS			0x4000
+#define PM2R_RD_PALETTE_DATA				0x4008
+#define PM2R_RD_PALETTE_READ_ADDRESS			0x4018
+#define PM2R_RD_INDEXED_DATA				0x4050
+
+#define PM2R_START_X_DOM				0x8000
+#define PM2R_D_X_DOM					0x8008
+#define PM2R_START_X_SUB				0x8010
+#define PM2R_D_X_SUB					0x8018
+#define PM2R_START_Y					0x8020
+#define PM2R_D_Y					0x8028
+#define PM2R_COUNT					0x8030
+#define PM2R_RENDER					0x8038
+#define PM2R_RECTANGLE_ORIGIN				0x80d0
+#define PM2R_RECTANGLE_SIZE				0x80d8
+#define PM2R_PACKED_DATA_LIMITS				0x8150
+#define PM2R_SCISSOR_MODE				0x8180
+#define PM2R_SCREEN_SIZE				0x8198
+#define PM2R_AREA_STIPPLE_MODE				0x81a0
+#define PM2R_WINDOW_ORIGIN				0x81c8
+#define PM2R_TEXTURE_ADDRESS_MODE			0x8380
+#define PM2R_TEXTURE_MAP_FORMAT				0x8588
+#define PM2R_TEXTURE_DATA_FORMAT			0x8590
+#define PM2R_TEXTURE_READ_MODE				0x8670
+#define PM2R_TEXEL_LUT_MODE				0x8678
+#define PM2R_TEXTURE_COLOR_MODE				0x8680
+#define PM2R_FOG_MODE					0x8690
+#define PM2R_COLOR_DDA_MODE				0x87e0
+#define PM2R_ALPHA_BLEND_MODE				0x8810
+#define PM2R_DITHER_MODE				0x8818
+#define PM2R_FB_SOFT_WRITE_MASK				0x8820
+#define PM2R_LOGICAL_OP_MODE				0x8828
+#define PM2R_LB_READ_MODE				0x8880
+#define PM2R_LB_READ_FORMAT				0x8888
+#define PM2R_LB_SOURCE_OFFSET				0x8890
+#define PM2R_LB_WINDOW_BASE				0x88b8
+#define PM2R_LB_WRITE_FORMAT				0x88c8
+#define PM2R_STENCIL_MODE				0x8988
+#define PM2R_DEPTH_MODE					0x89a0
+#define PM2R_FB_READ_MODE				0x8a80
+#define PM2R_FB_SOURCE_OFFSET				0x8a88
+#define PM2R_FB_PIXEL_OFFSET				0x8a90
+#define PM2R_FB_WINDOW_BASE				0x8ab0
+#define PM2R_FB_WRITE_MODE				0x8ab8
+#define PM2R_FB_HARD_WRITE_MASK				0x8ac0
+#define PM2R_FB_BLOCK_COLOR				0x8ac8
+#define PM2R_FB_READ_PIXEL				0x8ad0
+#define PM2R_FILTER_MODE				0x8c00
+#define PM2R_SYNC					0x8c40
+#define PM2R_YUV_MODE					0x8f00
+#define PM2R_STATISTICS_MODE				0x8c08
+#define PM2R_FB_SOURCE_DELTA				0x8d88
+#define PM2R_CONFIG					0x8d90
+
+/* Permedia2 RAMDAC indexed registers */
+#define PM2I_RD_CURSOR_CONTROL				0x06
+#define PM2I_RD_COLOR_MODE				0x18
+#define PM2I_RD_MODE_CONTROL				0x19
+#define PM2I_RD_MISC_CONTROL				0x1e
+#define PM2I_RD_PIXEL_CLOCK_A1				0x20
+#define PM2I_RD_PIXEL_CLOCK_A2				0x21
+#define PM2I_RD_PIXEL_CLOCK_A3				0x22
+#define PM2I_RD_PIXEL_CLOCK_STATUS			0x29
+#define PM2I_RD_MEMORY_CLOCK_1				0x30
+#define PM2I_RD_MEMORY_CLOCK_2				0x31
+#define PM2I_RD_MEMORY_CLOCK_3				0x32
+#define PM2I_RD_MEMORY_CLOCK_STATUS			0x33
+#define PM2I_RD_COLOR_KEY_CONTROL			0x40
+#define PM2I_RD_OVERLAY_KEY				0x41
+#define PM2I_RD_RED_KEY					0x42
+#define PM2I_RD_GREEN_KEY				0x43
+#define PM2I_RD_BLUE_KEY				0x44
+
+/* Fields and flags */
+#define PM2F_RENDER_AREASTIPPLE				(1<<0)
+#define PM2F_RENDER_FASTFILL				(1<<3)
+#define PM2F_RENDER_PRIMITIVE_MASK			(0x3<<6)
+#define PM2F_RENDER_LINE				0
+#define PM2F_RENDER_TRAPEZOID				(1<<6)
+#define PM2F_RENDER_POINT				(2<<6)
+#define PM2F_RENDER_RECTANGLE				(3<<6)
+#define PM2F_SYNCHRONIZATION				(1<<10)
+#define PM2F_PLL_LOCKED					0x10
+#define PM2F_BEING_RESET				(1<<31)
+#define PM2F_DATATYPE_COLOR				0x8000
+#define PM2F_VGA_ENABLE					0x02
+#define PM2F_VGA_FIXED					0x04
+#define PM2F_FB_WRITE_ENABLE				0x01
+#define PM2F_FB_READ_SOURCE_ENABLE			0x0200
+#define PM2F_RD_PALETTE_WIDTH_8				0x02
+#define PM2F_PART_PROD_MASK				0x01ff
+#define PM2F_SCREEN_SCISSOR_ENABLE			0x02
+#define PM2F_DATA_64_ENABLE				0x00010000
+#define PM2F_BLANK_LOW					0x02
+#define PM2F_HSYNC_MASK					0x18
+#define PM2F_VSYNC_MASK					0x60
+#define PM2F_HSYNC_ACT_HIGH				0x08
+#define PM2F_HSYNC_FORCED_LOW				0x10
+#define PM2F_HSYNC_ACT_LOW				0x18
+#define PM2F_VSYNC_ACT_HIGH				0x20
+#define PM2F_VSYNC_FORCED_LOW				0x40
+#define PM2F_VSYNC_ACT_LOW				0x60
+#define PM2F_LINE_DOUBLE				0x04
+#define PM2F_VIDEO_ENABLE				0x01
+#define PM2F_RD_GUI_ACTIVE				0x10
+#define PM2F_RD_COLOR_MODE_RGB				0x20
+#define PM2F_RD_TRUECOLOR				0x80
+#define PM2F_NO_ALPHA_BUFFER				0x10
+#define PM2F_TEXTEL_SIZE_16				0x00080000
+#define PM2F_TEXTEL_SIZE_32				0x00100000
+#define PM2F_TEXTEL_SIZE_4				0x00180000
+#define PM2F_TEXTEL_SIZE_24				0x00200000
+#define PM2F_INCREASE_X					(1<<21)
+#define PM2F_INCREASE_Y					(1<<22)
+#define PM2F_CONFIG_FB_WRITE_ENABLE			(1<<3)
+#define PM2F_CONFIG_FB_PACKED_DATA			(1<<2)
+#define PM2F_CONFIG_FB_READ_DEST_ENABLE			(1<<1)
+#define PM2F_CONFIG_FB_READ_SOURCE_ENABLE		(1<<0)
+#define PM2F_COLOR_KEY_TEST_OFF				(1<<4)
+
+#endif /* PM2FB_H */
+
+/*****************************************************************************
+ * That's all folks!
+ *****************************************************************************/
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/retz3fb.c linux/drivers/video/retz3fb.c
--- v2.2.0-pre8/linux/drivers/video/retz3fb.c	Wed Jan 13 15:00:43 1999
+++ linux/drivers/video/retz3fb.c	Tue Jan 19 10:47:48 1999
@@ -1455,8 +1455,7 @@
X 	board_addr = (unsigned long)cd->cd_BoardAddr;
X 	board_size = (unsigned long)cd->cd_BoardSize;
X 
-	zinfo->base = kernel_map (board_addr, board_size,
-				   KERNELMAP_NOCACHE_SER, NULL);
+	zinfo->base = ioremap(board_addr, board_size);
X 	zinfo->regs = (unsigned char *)(zinfo->base);
X 	zinfo->fbmem = zinfo->base + VIDEO_MEM_OFFSET;
X 	/* Get memory size - for now we asume its a 4MB board */
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/sbusfb.c linux/drivers/video/sbusfb.c
--- v2.2.0-pre8/linux/drivers/video/sbusfb.c	Tue Dec 22 14:16:57 1998
+++ linux/drivers/video/sbusfb.c	Tue Jan 19 10:48:41 1999
@@ -46,6 +46,9 @@
X 
X #define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)
X 
+#define CURSOR_SHAPE			1
+#define CURSOR_BLINK			2
+
X     /*
X      *  Interface used by the world
X      */
@@ -457,7 +460,7 @@
X         
X 	if (!fb->setcursor) return;
X                                 
-	if (fb->cursor.mode != 2) {
+	if (fb->cursor.mode & CURSOR_BLINK) {
X 		fb->cursor.enable ^= 1;
X 		fb->setcursor(fb);
X 	}
@@ -472,14 +475,14 @@
X 	
X 	switch (mode) {
X 	case CM_ERASE:
-		fb->cursor.mode = 2;
+		fb->cursor.mode &= ~CURSOR_BLINK;
X 		fb->cursor.enable = 0;
X 		(*fb->setcursor)(fb);
X 		break;
X 				  
X 	case CM_MOVE:
X 	case CM_DRAW:
-		if (fb->cursor.mode) {
+		if (fb->cursor.mode & CURSOR_SHAPE) {
X 			fb->cursor.size.fbx = fontwidth(p);
X 			fb->cursor.size.fby = fontheight(p);
X 			fb->cursor.chot.fbx = 0;
@@ -492,8 +495,8 @@
X 			fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p)));
X 			(*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap);
X 			(*fb->setcurshape) (fb);
-			fb->cursor.mode = 0;
X 		}
+		fb->cursor.mode = CURSOR_BLINK;
X 		if (fontwidthlog(p))
X 			fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin;
X 		else
@@ -684,7 +687,7 @@
X  			lastconsole = info->display_fg->vc_num; 
X  			if (vt_cons[lastconsole]->vc_mode == KD_TEXT)
X  				return -EINVAL; /* Don't let graphics programs hide our nice text cursor */
-			fb->cursor.mode = 2; /* Forget state of our text cursor */
+			fb->cursor.mode = CURSOR_SHAPE; /* Forget state of our text cursor */
X 		}
X 		return sbus_hw_scursor ((struct fbcursor *) arg, fb);
X 
@@ -761,7 +764,7 @@
X 		if (lastconsole != con && 
X 		    (fontwidth(&fb_display[lastconsole]) != fontwidth(&fb_display[con]) ||
X 		     fontheight(&fb_display[lastconsole]) != fontheight(&fb_display[con])))
-			fb->cursor.mode = 1;
+			fb->cursor.mode |= CURSOR_SHAPE;
X 	}
X 	x_margin = (fb_display[con].var.xres_virtual - fb_display[con].var.xres) / 2;
X 	y_margin = (fb_display[con].var.yres_virtual - fb_display[con].var.yres) / 2;
@@ -889,7 +892,7 @@
X 	p->var.xres = w - 2*x_margin;
X 	p->var.yres = h - 2*y_margin;
X 	
-	fb->cursor.mode = 1;
+	fb->cursor.mode |= CURSOR_SHAPE;
X 	
X 	if (fb->margins)
X 		fb->margins(fb, p, x_margin, y_margin);
@@ -1076,6 +1079,7 @@
X 			add_timer(&fb->cursor.timer);
X 		}
X 	}
+	fb->cursor.mode = CURSOR_SHAPE;
X 	fb->dispsw.set_font = sbusfb_set_font;
X 	fb->setup = fb->dispsw.setup;
X 	fb->dispsw.setup = sbusfb_disp_setup;
diff -u --recursive --new-file v2.2.0-pre8/linux/drivers/video/virgefb.c linux/drivers/video/virgefb.c
--- v2.2.0-pre8/linux/drivers/video/virgefb.c	Tue Dec 22 14:16:57 1998
+++ linux/drivers/video/virgefb.c	Tue Jan 19 10:47:48 1999
@@ -50,7 +50,15 @@
X 
X #if 1
X #define vgawb_3d(reg,dat) \
-                (*((unsigned char *)(CyberVGARegs + (reg ^ 3))) = dat)
+	if (cv3d_on_zorro2) { \
+	*((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x04)) = \
+	(0x01 & 0xffff); asm volatile ("nop"); \
+	} \
+	(*((unsigned char *)(CyberVGARegs + (reg ^ 3))) = dat); \
+	if (cv3d_on_zorro2) { \
+	*((unsigned char volatile *)((Cyber_vcode_switch_base) + 0x04)) = \
+	(0x02 & 0xffff); asm volatile ("nop"); \
+	}
X #define vgaww_3d(reg,dat) \
X                 (*((unsigned word *)(CyberVGARegs + (reg ^ 2))) = swab16(dat))
X #define vgawl_3d(reg,dat) \
@@ -155,6 +163,9 @@
X static volatile unsigned long CyberVGARegs; /* ++Andre: for CV64/3D, see macros at the beginning */
X static unsigned long CyberMem_phys;
X static unsigned long CyberRegs_phys;
+static unsigned long Cyber_register_base;
+static unsigned long Cyber_vcode_switch_base;
+static unsigned char cv3d_on_zorro2;
X  
X 
X /*
@@ -345,7 +356,11 @@
X 	memset ((char*)CyberMem, 0, 1600 * 1200);
X 
X 	/* Disable hardware cursor */
-	CyberSize = 0x00400000; /* 4 MB */
+	if (cv3d_on_zorro2) {
+		CyberSize = 0x00380000; /* 3.5 MB , we need some space for the registers? */
+	} else {
+		CyberSize = 0x00400000; /* 4 MB */
+	}
X 
X 	vgawb_3d(0x3c8, 255);
X 	vgawb_3d(0x3c9, 56);
@@ -1045,21 +1060,26 @@
X 
X 		CyberMem_phys = board_addr;
X 		CyberMem = ZTWO_VADDR(CyberMem_phys);
-		printk("CV3D detected running in Z2 mode ... not yet supported!\n");
-		return;
+		CyberVGARegs = (unsigned long) \
+			ZTWO_VADDR(board_addr + 0x003c0000);
+		CyberRegs_phys = (unsigned long)(board_addr + 0x003e0000);
+		CyberRegs = (unsigned char *)ZTWO_VADDR(CyberRegs_phys);
+		Cyber_register_base = (unsigned long) \
+			ZTWO_VADDR(board_addr + 0x003c8000);
+		Cyber_vcode_switch_base = (unsigned long) \
+			ZTWO_VADDR(board_addr + 0x003a0000);
+		cv3d_on_zorro2 = 1;
+		printk("CV3D detected running in Z2 mode.\n");
X 	}
X 	else
X 	{
-		CyberVGARegs = kernel_map(board_addr +0x0c000000, 0x00010000,
-					       KERNELMAP_NOCACHE_SER, NULL);
+		CyberVGARegs = ioremap(board_addr +0x0c000000, 0x00010000);
X 
X 		CyberRegs_phys = board_addr + 0x05000000;
X 		CyberMem_phys  = board_addr + 0x04800000;
-		CyberRegs = (char *)kernel_map(CyberRegs_phys,
-					       0x00010000,
-					       KERNELMAP_NOCACHE_SER, NULL);
-		CyberMem = kernel_map(CyberMem_phys, 0x00400000,
-				      KERNELMAP_NOCACHE_SER, NULL);
+		CyberRegs = ioremap(CyberRegs_phys, 0x00010000);
+		CyberMem = ioremap(CyberMem_phys, 0x00400000);
+		cv3d_on_zorro2 = 0;
X 		printk("CV3D detected running in Z3 mode\n");
X 	}
X 
@@ -1084,8 +1104,10 @@
X 	virgefb_set_disp(-1, &fb_info);
X 	do_install_cmap(0, &fb_info);
X 
-	if (register_framebuffer(&fb_info) < 0)
+	if (register_framebuffer(&fb_info) < 0) {
+		printk("virgefb.c: register_framebuffer failed\n");
X 		return;
+	}
X 
X 	printk("fb%d: %s frame buffer device, using %ldK of video memory\n",
X 	       GET_FB_IDX(fb_info.node), fb_info.modename, CyberSize>>10);
diff -u --recursive --new-file v2.2.0-pre8/linux/fs/Config.in linux/fs/Config.in
--- v2.2.0-pre8/linux/fs/Config.in	Tue Jan 19 11:32:52 1999
+++ linux/fs/Config.in	Tue Jan 19 11:07:53 1999
@@ -35,7 +35,11 @@
X tristate 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS
X bool '/proc filesystem support' CONFIG_PROC_FS
X if [ "$CONFIG_UNIX98_PTYS" = "y" ]; then
-  tristate '/dev/pts filesystem for Unix98 PTYs' CONFIG_DEVPTS_FS
+  # It compiles as a module for testing only.  It should not be used
+  # as a module in general.  If we make this "tristate", a bunch of people
+  # who don't know what they are doing turn it on and complain when it
+  # breaks.
+  bool '/dev/pts filesystem for Unix98 PTYs' CONFIG_DEVPTS_FS
X fi
X if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
X   tristate 'QNX filesystem support (EXPERIMENTAL)' CONFIG_QNX4FS_FS
diff -u --recursive --new-file v2.2.0-pre8/linux/fs/namei.c linux/fs/namei.c
--- v2.2.0-pre8/linux/fs/namei.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/namei.c	Tue Jan 19 10:26:33 1999
@@ -882,8 +882,16 @@
X 	if (IS_ERR(dentry))
X 		goto exit;
X 
+	/*
+	 * EEXIST is kind of a strange error code to
+	 * return, but basically if the dentry was moved
+	 * or unlinked while we locked the parent, we
+	 * do know that it _did_ exist before, and as
+	 * such it makes perfect sense.. In contrast,
+	 * ENOENT doesn't make sense for mkdir.
+	 */
X 	dir = lock_parent(dentry);
-	error = -ENOENT;
+	error = -EEXIST;
X 	if (!check_parent(dir, dentry))
X 		goto exit_lock;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/fs/proc/array.c linux/fs/proc/array.c
--- v2.2.0-pre8/linux/fs/proc/array.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/proc/array.c	Wed Jan 20 10:23:58 1999
@@ -1085,8 +1085,7 @@
X 			vma = vma->vm_next;
X 		}
X 		release_mm(mm); 
-	} else
-		return 0; 
+	}
X 	return sprintf(buffer,"%d %d %d %d %d %d %d\n",
X 		       size, resident, share, trs, lrs, drs, dt);
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/fs/select.c linux/fs/select.c
--- v2.2.0-pre8/linux/fs/select.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/select.c	Tue Jan 19 10:43:08 1999
@@ -58,6 +58,37 @@
X 	}
X }
X 
+void __pollwait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
+{
+	for (;;) {
+		if (p->nr < __MAX_POLL_TABLE_ENTRIES) {
+			struct poll_table_entry * entry;
+ok_table:
+		 	entry = p->entry + p->nr;
+		 	entry->filp = filp;
+		 	filp->f_count++;
+			entry->wait_address = wait_address;
+			entry->wait.task = current;
+			entry->wait.next = NULL;
+			add_wait_queue(wait_address,&entry->wait);
+			p->nr++;
+			return;
+		}
+		if (p->next == NULL) {
+			poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
+			if (!tmp)
+				return;
+			tmp->nr = 0;
+			tmp->entry = (struct poll_table_entry *)(tmp + 1);
+			tmp->next = NULL;
+			p->next = tmp;
+			p = tmp;
+			goto ok_table;
+		}
+		p = p->next;
+	}
+}
+
X #define __IN(fds, n)		(fds->in + n)
X #define __OUT(fds, n)		(fds->out + n)
X #define __EX(fds, n)		(fds->ex + n)
diff -u --recursive --new-file v2.2.0-pre8/linux/fs/vfat/namei.c linux/fs/vfat/namei.c
--- v2.2.0-pre8/linux/fs/vfat/namei.c	Tue Jan 19 11:32:52 1999
+++ linux/fs/vfat/namei.c	Wed Jan 20 12:57:57 1999
@@ -1656,8 +1656,8 @@
X 		} else {
X 			drop_aliases(new_dentry);
X 		}
+		res = vfat_remove_entry(new_dir,&sinfo,new_inode);
X 	}
-	res = vfat_remove_entry(new_dir,&sinfo,new_inode);
X 	if (res)
X 		goto rename_done;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-alpha/semaphore.h linux/include/asm-alpha/semaphore.h
--- v2.2.0-pre8/linux/include/asm-alpha/semaphore.h	Tue Jan 19 11:32:52 1999
+++ linux/include/asm-alpha/semaphore.h	Wed Jan 20 16:06:34 1999
@@ -72,13 +72,13 @@
X  *			count = -1, waking = 0, depth = 2;
X  *	up(&sem)
X  *		dec depth
- *			count = -1, waking = 0, depth = 0;
+ *			count = -1, waking = 0, depth = 1;
X  *		atomic inc and test sends us to slow path
- *			count = 0, waking = 0, depth = 0;
+ *			count = 0, waking = 0, depth = 1;
X  *		notice !(depth < 0) and don't call __up.
X  *	up(&sem)
X  *		dec depth
- *			count = 0, waking = 0, depth = -1;
+ *			count = 0, waking = 0, depth = 0;
X  *		atomic inc and test succeeds.
X  *			count = 1, waking = 0, depth = 0;
X  */
@@ -227,7 +227,7 @@
X 		".section .text2,\"ax\"\n"
X 		"2:	br	1b\n"
X 		"3:	lda	$24,%1\n"
-		"	bge	%2,4b\n"
+		"	bgt	%2,4b\n"
X 		"	jsr	$28,__up_wakeup\n"
X 		"	ldgp	$29,0($28)\n"
X 		"	br	4b\n"
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/cobalt.h linux/include/asm-i386/cobalt.h
--- v2.2.0-pre8/linux/include/asm-i386/cobalt.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/cobalt.h	Wed Jan 20 10:18:53 1999
@@ -0,0 +1,116 @@
+#ifndef __I386_COBALT_H
+#define __I386_COBALT_H
+
+/*
+ * Cobalt is the system ASIC on the SGI 320 and 540 Visual Workstations
+ */ 
+
+#define	CO_CPU_PHYS		0xc2000000
+#define	CO_APIC_PHYS		0xc4000000
+
+/* see set_fixmap() and asm/fixmap.h */
+#define	CO_CPU_VADDR		(fix_to_virt(FIX_CO_CPU))
+#define	CO_APIC_VADDR		(fix_to_virt(FIX_CO_APIC))
+
+/* Cobalt CPU registers -- relative to CO_CPU_VADDR, use co_cpu_*() */
+#define	CO_CPU_REV		0x08
+#define	CO_CPU_CTRL		0x10
+#define	CO_CPU_STAT		0x20
+#define	CO_CPU_TIMEVAL		0x30
+
+/* CO_CPU_CTRL bits */
+#define	CO_CTRL_TIMERUN		0x04	/* 0 == disabled */
+#define	CO_CTRL_TIMEMASK	0x08	/* 0 == unmasked */
+
+/* CO_CPU_STATUS bits */
+#define	CO_STAT_TIMEINTR	0x02	/* (r) 1 == int pend, (w) 0 == clear */
+
+/* CO_CPU_TIMEVAL value */
+#define	CO_TIME_HZ		100000000 /* Cobalt core rate */
+
+/* Cobalt APIC registers -- relative to CO_APIC_VADDR, use co_apic_*() */
+#define	CO_APIC_HI(n)		(((n) * 0x10) + 4)
+#define	CO_APIC_LO(n)		((n) * 0x10)
+#define	CO_APIC_ID		0x0ffc
+
+/* CO_APIC_ID bits */
+#define	CO_APIC_ENABLE		0x00000100
+
+/* CO_APIC_LO bits */
+#define	CO_APIC_LEVEL		0x08000		/* 0 = edge */
+
+/*
+ * Where things are physically wired to Cobalt
+ * #defines with no board _<type>_<rev>_ are common to all (thus far)
+ */
+#define CO_APIC_0_5_IDE0	5
+#define	CO_APIC_0_5_SERIAL	13	 /* XXX not really...h/w bug! */
+#define CO_APIC_0_5_PARLL	4
+#define CO_APIC_0_5_FLOPPY	6
+
+#define	CO_APIC_0_6_IDE0	4
+#define	CO_APIC_0_6_USB	7	/* PIIX4 USB */
+
+#define	CO_APIC_1_2_IDE0	4
+
+#define CO_APIC_0_5_IDE1	2
+#define CO_APIC_0_6_IDE1	2
+
+/* XXX */
+#define	CO_APIC_IDE0	CO_APIC_0_5_IDE0
+#define	CO_APIC_IDE1	CO_APIC_0_5_IDE1
+#define	CO_APIC_SERIAL	CO_APIC_0_5_SERIAL
+/* XXX */
+
+#define CO_APIC_ENET	3	/* Lithium PCI Bridge A, Device 3 */
+#define	CO_APIC_8259	12	/* serial, floppy, par-l-l, audio */
+
+#define	CO_APIC_VIDOUT0	16
+#define	CO_APIC_VIDOUT1	17
+#define	CO_APIC_VIDIN0	18
+#define	CO_APIC_VIDIN1	19
+
+#define CO_APIC_CPU	28	/* Timer and Cache interrupt */
+
+/*
+ * This is the "irq" arg to request_irq(), just a unique cookie.
+ */
+#define	CO_IRQ_TIMER	0
+#define CO_IRQ_ENET	3
+#define CO_IRQ_SERIAL	4
+#define CO_IRQ_FLOPPY	6	/* Same as drivers/block/floppy.c:FLOPPY_IRQ */
+#define	CO_IRQ_PARLL	7
+#define	CO_IRQ_POWER	9
+#define CO_IRQ_IDE	14
+#define	CO_IRQ_8259	12
+
+#ifdef CONFIG_X86_VISWS_APIC
+extern __inline void co_cpu_write(unsigned long reg, unsigned long v)
+{
+	*((volatile unsigned long *)(CO_CPU_VADDR+reg))=v;
+}
+
+extern __inline unsigned long co_cpu_read(unsigned long reg)
+{
+	return *((volatile unsigned long *)(CO_CPU_VADDR+reg));
+}            
+             
+extern __inline void co_apic_write(unsigned long reg, unsigned long v)
+{
+	*((volatile unsigned long *)(CO_APIC_VADDR+reg))=v;
+}            
+             
+extern __inline unsigned long co_apic_read(unsigned long reg)
+{
+	return *((volatile unsigned long *)(CO_APIC_VADDR+reg));
+}
+#endif
+
+extern char visws_board_type;
+
+#define	VISWS_320	0
+#define	VISWS_540	1
+
+extern char visws_board_rev;
+
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/fixmap.h linux/include/asm-i386/fixmap.h
--- v2.2.0-pre8/linux/include/asm-i386/fixmap.h	Mon Oct  5 13:13:42 1998
+++ linux/include/asm-i386/fixmap.h	Wed Jan 20 16:21:43 1999
@@ -11,8 +11,9 @@
X #ifndef _ASM_FIXMAP_H
X #define _ASM_FIXMAP_H
X 
-#include <asm/page.h>
+#include <linux/config.h>
X #include <linux/kernel.h>
+#include <asm/page.h>
X 
X /*
X  * Here we define all the compile-time 'special' virtual
@@ -40,9 +41,17 @@
X  * fix-mapped?
X  */
X enum fixed_addresses {
-#ifdef __SMP__
-	FIX_APIC_BASE,
+#ifdef CONFIG_X86_LOCAL_APIC
+	FIX_APIC_BASE,	/* local (CPU) APIC) -- required for SMP or not */
+#endif
+#ifdef CONFIG_X86_IO_APIC
X 	FIX_IO_APIC_BASE,
+#endif
+#ifdef CONFIG_X86_VISWS_APIC
+	FIX_CO_CPU,	/* Cobalt timer */
+	FIX_CO_APIC,	/* Cobalt APIC Redirection Table */ 
+	FIX_LI_PCIA,	/* Lithium PCI Bridge A */
+	FIX_LI_PCIB,	/* Lithium PCI Bridge B */
X #endif
X 	__end_of_fixed_addresses
X };
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/i82489.h linux/include/asm-i386/i82489.h
--- v2.2.0-pre8/linux/include/asm-i386/i82489.h	Mon Sep 11 10:15:45 1995
+++ linux/include/asm-i386/i82489.h	Wed Jan 20 10:18:53 1999
@@ -6,6 +6,7 @@
X  *
X  *	Alan Cox <Alan...@linux.org>, 1995.
X  */
+#define		APIC_PHYS_BASE	0xfee00000 /* IA s/w dev Vol 3, Section 7.4 */
X  
X #define		APIC_ID		0x20
X #define			GET_APIC_ID(x)		(((x)>>24)&0x0F)
@@ -84,5 +85,17 @@
X #define			APIC_TDR_DIV_32		0x8
X #define			APIC_TDR_DIV_64		0x9
X #define			APIC_TDR_DIV_128	0xA
+
+#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
+
+extern __inline void apic_write(unsigned long reg, unsigned long v)
+{
+	*((volatile unsigned long *)(APIC_BASE+reg))=v;
+}
+
+extern __inline unsigned long apic_read(unsigned long reg)
+{
+	return *((volatile unsigned long *)(APIC_BASE+reg));
+}
X 
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/lithium.h linux/include/asm-i386/lithium.h
--- v2.2.0-pre8/linux/include/asm-i386/lithium.h	Wed Dec 31 16:00:00 1969
+++ linux/include/asm-i386/lithium.h	Wed Jan 20 10:18:53 1999
@@ -0,0 +1,40 @@
+#ifndef __I386_LITHIUM_H
+#define __I386_LITHIUM_H
+
+/*
+ * Lithium is the I/O ASIC on the SGI 320 and 540 Visual Workstations
+ */
+
+#define	LI_PCI_A_PHYS		0xfc000000	/* Enet is dev 3 */
+#define	LI_PCI_B_PHYS		0xfd000000	/* PIIX4 is here */
+
+/* see set_fixmap() and asm/fixmap.h */
+#define LI_PCIA_VADDR   (fix_to_virt(FIX_LI_PCIA))
+#define LI_PCIB_VADDR   (fix_to_virt(FIX_LI_PCIB))
+
+/* Not a standard PCI? (not in linux/pci.h) */
+#define	LI_PCI_BUSNUM	0x44			/* lo8: primary, hi8: sub */
+#define LI_PCI_INTEN    0x46
+
+/* More special purpose macros... */
+extern __inline void li_pcia_write16(unsigned long reg, unsigned short v)
+{
+	*((volatile unsigned short *)(LI_PCIA_VADDR+reg))=v;
+}
+
+extern __inline unsigned short li_pcia_read16(unsigned long reg)
+{
+	 return *((volatile unsigned short *)(LI_PCIA_VADDR+reg));
+}
+
+extern __inline void li_pcib_write16(unsigned long reg, unsigned short v)
+{
+	*((volatile unsigned short *)(LI_PCIB_VADDR+reg))=v;
+}
+
+extern __inline unsigned short li_pcib_read16(unsigned long reg)
+{
+	return *((volatile unsigned short *)(LI_PCIB_VADDR+reg));
+}
+
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/smp.h linux/include/asm-i386/smp.h
--- v2.2.0-pre8/linux/include/asm-i386/smp.h	Thu Dec 31 10:29:02 1998
+++ linux/include/asm-i386/smp.h	Wed Jan 20 16:21:43 1999
@@ -1,12 +1,20 @@
X #ifndef __ASM_SMP_H
X #define __ASM_SMP_H
X 
-#ifdef __SMP__
+/*
+ * We need the APIC definitions automatically as part of 'smp.h'
+ */
+#include <linux/config.h>
+#ifdef CONFIG_X86_LOCAL_APIC
X #ifndef ASSEMBLY
-
+#include <asm/fixmap.h>
X #include <asm/i82489.h>
X #include <asm/bitops.h>
-#include <asm/fixmap.h>
+#endif
+#endif
+
+#ifdef __SMP__
+#ifndef ASSEMBLY
X 
X #include <linux/tasks.h>
X #include <linux/ptrace.h>
@@ -186,25 +194,6 @@
X extern void smp_callin(void);
X extern void smp_boot_cpus(void);
X extern void smp_store_cpu_info(int id);		/* Store per CPU info (like the initial udelay numbers */
-
-/*
- *	APIC handlers: Note according to the Intel specification update
- *	you should put reads between APIC writes.
- *	Intel Pentium processor specification update [11AP, pg 64]
- *	"Back to Back Assertions of HOLD May Cause Lost APIC Write Cycle"
- */
-
-#define APIC_BASE (fix_to_virt(FIX_APIC_BASE))
-
-extern __inline void apic_write(unsigned long reg, unsigned long v)
-{
-	*((volatile unsigned long *)(APIC_BASE+reg))=v;
-}
-
-extern __inline unsigned long apic_read(unsigned long reg)
-{
-	return *((volatile unsigned long *)(APIC_BASE+reg));
-}
X 
X /*
X  * This function is needed by all SMP systems. It must _always_ be valid
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/string.h linux/include/asm-i386/string.h
--- v2.2.0-pre8/linux/include/asm-i386/string.h	Tue Jan 19 11:32:53 1999
+++ linux/include/asm-i386/string.h	Tue Jan 19 11:03:29 1999
@@ -188,35 +188,6 @@
X return __res;
X }
X 
-#define __HAVE_ARCH_STRSTR
-extern inline char * strstr(const char * cs,const char * ct)
-{
-int d0, d1, d2, d3, d4;
-register char * __res;
-__asm__ __volatile__(
-	"cld\n\t" \
-	"movl %8,%%edi\n\t"
-	"repne\n\t"
-	"scasb\n\t"
-	"notl %%ecx\n\t"
-	"decl %%ecx\n\t"	/* NOTE! This also sets Z if searchstring='' */
-	"movl %%ecx,%%edx\n"
-	"1:\tmovl %8,%%edi\n\t"
-	"movl %%esi,%%eax\n\t"
-	"movl %%edx,%%ecx\n\t"
-	"repe\n\t"
-	"cmpsb\n\t"
-	"je 2f\n\t"		/* also works for empty string, see above */
-	"xchgl %%eax,%%esi\n\t"
-	"incl %%esi\n\t"
-	"cmpb $0,-1(%%eax)\n\t"
-	"jne 1b\n\t"
-	"xorl %%eax,%%eax\n\t"
-	"2:"
-	:"=a" (__res), "=&c" (d0), "=&S" (d1), "=&d" (d2), "=&D" (d3), "=&g" (d4) : "0" (0),"1" (0xffffffff),"2" (cs),"4" (ct));
-return __res;
-}
-
X #define __HAVE_ARCH_STRLEN
X extern inline size_t strlen(const char * s)
X {
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-i386/unistd.h linux/include/asm-i386/unistd.h
--- v2.2.0-pre8/linux/include/asm-i386/unistd.h	Fri Jan  8 22:36:23 1999
+++ linux/include/asm-i386/unistd.h	Wed Jan 20 11:06:24 1999
@@ -194,7 +194,7 @@
X #define __NR_sendfile		187
X #define __NR_getpmsg		188	/* some people actually want streams */
X #define __NR_putpmsg		189	/* some people actually want streams */
-#define __NR_vfork             190
+#define __NR_vfork		190
X 
X /* user-visible error numbers are in the range -1 - -122: see <asm-i386/errno.h> */
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/bootinfo.h linux/include/asm-m68k/bootinfo.h
--- v2.2.0-pre8/linux/include/asm-m68k/bootinfo.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-m68k/bootinfo.h	Tue Jan 19 10:58:34 1999
@@ -46,12 +46,6 @@
X     unsigned long data[0];		/* data */
X };
X 
-#else /* __ASSEMBLY__ */
-
-BIR_tag		= 0
-BIR_size	= BIR_tag+2
-BIR_data	= BIR_size+2
-
X #endif /* __ASSEMBLY__ */
X 
X 
@@ -287,14 +281,6 @@
X 	unsigned long adbdelay;
X 	unsigned long timedbra;
X };
-#else
-
-#define BI_videoaddr	BI_un
-#define BI_videorow	BI_videoaddr+4
-#define BI_videodepth	BI_videorow+4
-#define BI_dimensions	BI_videodepth+4
-#define BI_args		BI_dimensions+4
-#define BI_cpuid	BI_args+56
X 
X #endif
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/entry.h linux/include/asm-m68k/entry.h
--- v2.2.0-pre8/linux/include/asm-m68k/entry.h	Mon Aug  3 12:45:47 1998
+++ linux/include/asm-m68k/entry.h	Tue Jan 19 10:58:34 1999
@@ -37,25 +37,8 @@
X 
X #define curptr a2
X 
-/*
- * these are offsets into the task-struct
- */
-LTASK_STATE	 =  0
-LTASK_FLAGS	 =  4
-LTASK_SIGPENDING =  8
-LTASK_ADDRLIMIT	 = 12
-LTASK_EXECDOMAIN = 16
-LTASK_NEEDRESCHED = 20
-
-LTSS_KSP	= 0
-LTSS_USP	= 4
-LTSS_SR		= 8
-LTSS_FS		= 10
-LTSS_CRP	= 12
-LTSS_FPCTXT	= 24
-
X /* the following macro is used when enabling interrupts */
-#if defined(CONFIG_ATARI_ONLY) && !defined(CONFIG_HADES)
+#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
X 	/* block out HSYNC on the atari */
X #define ALLOWINT 0xfbff
X #define	MAX_NOINT_IPL	3
@@ -65,22 +48,20 @@
X #define	MAX_NOINT_IPL	0
X #endif /* machine compilation types */ 
X 
-LPT_OFF_D0	  = 0x20
-LPT_OFF_ORIG_D0	  = 0x24
-LPT_OFF_SR	  = 0x2C
-LPT_OFF_FORMATVEC = 0x32
-
X LFLUSH_I_AND_D = 0x00000808
-LENOSYS = 38
X LSIGTRAP = 5
X 
-LPF_TRACESYS_OFF = 3
-LPF_TRACESYS_BIT = 5
-LPF_PTRACED_OFF = 3
-LPF_PTRACED_BIT = 4
-LPF_DTRACE_OFF = 1
-LPF_DTRACE_BIT = 5
-
+/* process bits for task_struct.flags */
+PF_TRACESYS_OFF = 3
+PF_TRACESYS_BIT = 5
+PF_PTRACED_OFF = 3
+PF_PTRACED_BIT = 4
+PF_DTRACE_OFF = 1
+PF_DTRACE_BIT = 5
+
+#define SAVE_ALL_INT save_all_int
+#define SAVE_ALL_SYS save_all_sys
+#define RESTORE_ALL restore_all
X /*
X  * This defines the normal kernel pt-regs layout.
X  *
@@ -92,56 +73,68 @@
X  * a -1 in the orig_d0 field signifies
X  * that the stack frame is NOT for syscall
X  */
-#define SAVE_ALL_INT				\
-	clrl	%sp@-;		/* stk_adj */	\
-	pea	-1:w;		/* orig d0 */	\
-	movel	%d0,%sp@-;	/* d0 */	\
+.macro	save_all_int
+	clrl	%sp@-		| stk_adj
+	pea	-1:w		| orig d0
+	movel	%d0,%sp@-	| d0
X 	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+.endm
X 
-#define SAVE_ALL_SYS				\
-	clrl	%sp@-;		/* stk_adj */	\
-	movel	%d0,%sp@-;	/* orig d0 */	\
-	movel	%d0,%sp@-;	/* d0 */	\
-	moveml  %d1-%d5/%a0-%a1/%curptr,%sp@-
+.macro	save_all_sys
+	clrl	%sp@-		| stk_adj
+	movel	%d0,%sp@-	| orig d0
+	movel	%d0,%sp@-	| d0
+	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+.endm
X #else
X /* Need to save the "missing" registers for kgdb...
X  */
-#define SAVE_ALL_INT					\
-	clrl	%sp@-;		/* stk_adj */		\
-	pea	-1:w;		/* orig d0 */		\
-	movel	%d0,%sp@-;	/* d0 */		\
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-;		\
-	moveml	%d6-%d7,kgdb_registers+GDBOFFA_D6;	\
+.macro	save_all_int
+	clrl	%sp@-		| stk_adj
+	pea	-1:w		| orig d0
+	movel	%d0,%sp@-	| d0
+	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+	moveml	%d6-%d7,kgdb_registers+GDBOFFA_D6
X 	moveml	%a3-%a6,kgdb_registers+GDBOFFA_A3
+.endm
X 
-#define SAVE_ALL_SYS					\
-	clrl	%sp@-;		/* stk_adj */		\
-	movel	%d0,%sp@-;	/* orig d0 */		\
-	movel	%d0,%sp@-;	/* d0 */		\
-	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-;		\
-	moveml	%d6-%d7,kgdb_registers+GDBOFFA_D6;	\
+.macro	save_all_sys
+	clrl	%sp@-		| stk_adj
+	movel	%d0,%sp@-	| orig d0
+	movel	%d0,%sp@-	| d0
+	moveml	%d1-%d5/%a0-%a1/%curptr,%sp@-
+	moveml	%d6-%d7,kgdb_registers+GDBOFFA_D6
X 	moveml	%a3-%a6,kgdb_registers+GDBOFFA_A3
+.endm
X #endif
X 
-#define RESTORE_ALL			\
-	moveml	%sp@+,%a0-%a1/%curptr/%d1-%d5;	\
-	movel	%sp@+,%d0;		\
-	addql	#4,%sp;	 /* orig d0 */	\
-	addl	%sp@+,%sp; /* stk adj */	\
+.macro	restore_all
+	moveml	%sp@+,%a0-%a1/%curptr/%d1-%d5
+	movel	%sp@+,%d0
+	addql	#4,%sp		| orig d0
+	addl	%sp@+,%sp	| stk adj
X 	rte
+.endm
X 
X #define SWITCH_STACK_SIZE (6*4+4)	/* includes return address */
X 
-#define SAVE_SWITCH_STACK \
+#define SAVE_SWITCH_STACK save_switch_stack
+#define RESTORE_SWITCH_STACK restore_switch_stack
+#define GET_CURRENT(tmp) get_current tmp
+
+.macro	save_switch_stack
X 	moveml	%a3-%a6/%d6-%d7,%sp@-
+.endm
X 
-#define RESTORE_SWITCH_STACK \
+.macro	restore_switch_stack
X 	moveml	%sp@+,%a3-%a6/%d6-%d7
+.endm
X 
-#define GET_CURRENT(tmp) \
-	movel	%sp,tmp; \
-	andw	&-8192,tmp; \
-	movel	tmp,%curptr;
+.macro	get_current reg=%d0
+	movel	%sp,\reg
+	andw	#-8192,\reg
+	movel	\reg,%curptr
+.endm
X 
X #else /* C source */
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/ide.h linux/include/asm-m68k/ide.h
--- v2.2.0-pre8/linux/include/asm-m68k/ide.h	Thu Nov 12 16:21:24 1998
+++ linux/include/asm-m68k/ide.h	Tue Jan 19 10:58:34 1999
@@ -449,7 +449,7 @@
X  * an interrupt, and in that case it does nothing. Hope that is reasonable and
X  * works. (Roman)
X  */
-#ifdef CONFIG_ATARI_ONLY
+#ifdef MACH_ATARI_ONLY
X #define	ide__sti()					\
X     do {						\
X 	if (!in_interrupt()) __sti();			\
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/init.h linux/include/asm-m68k/init.h
--- v2.2.0-pre8/linux/include/asm-m68k/init.h	Thu Jan  7 15:11:40 1999
+++ linux/include/asm-m68k/init.h	Tue Jan 19 10:58:34 1999
@@ -16,7 +16,7 @@
X #define __INITDATA	.section	".data.init",#alloc,#write
X 
X #define __cacheline_aligned __attribute__ \
-			 ((__section__ (".data.cacheline_aligned")))
+		((__aligned__(16), __section__ (".data.cacheline_aligned")))
X 
X #else
X 
@@ -30,8 +30,8 @@
X #define __INIT
X #define __FINIT
X #define __INITDATA
-#define __cacheline_aligned
+#define __cacheline_aligned __attribute__ ((__aligned__(16)))
X 
X #endif /* CONFIG_KGDB */
-	
+
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/io.h linux/include/asm-m68k/io.h
--- v2.2.0-pre8/linux/include/asm-m68k/io.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/io.h	Tue Jan 19 10:58:34 1999
@@ -43,6 +43,35 @@
X #define outb(x,addr) ((void) writeb(x,addr))
X #define outb_p(x,addr) outb(x,addr)
X 
+
+/* Values for nocacheflag and cmode */
+#define IOMAP_FULL_CACHING		0
+#define IOMAP_NOCACHE_SER		1
+#define IOMAP_NOCACHE_NONSER		2
+#define IOMAP_WRITETHROUGH		3
+
+extern void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag);
+extern void __iounmap(void *addr, unsigned long size);
+
+extern inline void *ioremap(unsigned long physaddr, unsigned long size)
+{
+	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+}
+extern inline void *ioremap_nocache(unsigned long physaddr, unsigned long size)
+{
+	return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
+}
+extern inline void *ioremap_writethrough(unsigned long physaddr, unsigned long size)
+{
+	return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
+}
+extern inline void *ioremap_fullcache(unsigned long physaddr, unsigned long size)
+{
+	return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
+}
+
+extern void iounmap(void *addr);
+
X #endif /* __KERNEL__ */
X 
X #endif /* _M68K_IO_H */
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/keyboard.h linux/include/asm-m68k/keyboard.h
--- v2.2.0-pre8/linux/include/asm-m68k/keyboard.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-m68k/keyboard.h	Tue Jan 19 10:58:34 1999
@@ -52,9 +52,9 @@
X 
X #ifdef CONFIG_MAGIC_SYSRQ
X #define kbd_is_sysrq(keycode)	((keycode) == mach_sysrq_key && \
-								 (up_flag || \
-								  (shift_state & mach_sysrq_shift_mask) == \
-								  mach_sysrq_shift_state))
+				 (up_flag || \
+				  (shift_state & mach_sysrq_shift_mask) == \
+				  mach_sysrq_shift_state))
X #define kbd_sysrq_xlate			mach_sysrq_xlate
X #endif
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/machdep.h linux/include/asm-m68k/machdep.h
--- v2.2.0-pre8/linux/include/asm-m68k/machdep.h	Fri Oct  9 13:27:15 1998
+++ linux/include/asm-m68k/machdep.h	Tue Jan 19 10:58:34 1999
@@ -13,7 +13,6 @@
X extern int (*mach_keyb_init) (void);
X extern int (*mach_kbdrate) (struct kbd_repeat *);
X extern void (*mach_kbd_leds) (unsigned int);
-extern void (*kbd_reset_setup) (char *, int);
X /* machine dependent irq functions */
X extern void (*mach_init_IRQ) (void);
X extern void (*(*mach_default_handler)[]) (int, void *, struct pt_regs *);
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/machw.h linux/include/asm-m68k/machw.h
--- v2.2.0-pre8/linux/include/asm-m68k/machw.h	Tue Aug 18 22:02:07 1998
+++ linux/include/asm-m68k/machw.h	Tue Jan 19 10:58:34 1999
@@ -13,6 +13,16 @@
X #ifndef _ASM_MACHW_H_
X #define _ASM_MACHW_H_
X 
+/*
+ * head.S maps the videomem to VIDEOMEMBASE
+ */
+
+#define VIDEOMEMBASE	0xf0000000
+#define VIDEOMEMSIZE	(4096*1024)
+#define VIDEOMEMMASK	(-4096*1024)
+
+#ifndef __ASSEMBLY__
+
X #include <linux/types.h>
X 
X /* Mac SCSI Controller 5380 */
@@ -142,5 +152,7 @@
X } mac_hw_present;
X 
X /* extern struct mac_hw_present mac_hw_present; */
+
+#endif /* __ASSEMBLY__ */
X 
X #endif /* linux/machw.h */
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/page.h linux/include/asm-m68k/page.h
--- v2.2.0-pre8/linux/include/asm-m68k/page.h	Fri May  8 23:14:55 1998
+++ linux/include/asm-m68k/page.h	Tue Jan 19 10:58:34 1999
@@ -8,7 +8,7 @@
X 
X #ifdef __KERNEL__
X 
-#include<linux/config.h>
+#include <asm/setup.h>
X 
X #define STRICT_MM_TYPECHECKS
X 
@@ -18,7 +18,7 @@
X /*
X  * We don't need to check for alignment etc.
X  */
-#if defined(CONFIG_OPTIMIZE_040) || defined(CONFIG_OPTIMIZE_060)
+#ifdef CPU_M68040_OR_M68060_ONLY
X static inline void copy_page(unsigned long to, unsigned long from)
X {
X   unsigned long tmp;
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/pgtable.h linux/include/asm-m68k/pgtable.h
--- v2.2.0-pre8/linux/include/asm-m68k/pgtable.h	Tue Dec 22 14:16:58 1998
+++ linux/include/asm-m68k/pgtable.h	Tue Jan 19 10:58:34 1999
@@ -13,14 +13,7 @@
X  * the m68k page table tree.
X  */
X 
-/* For virtual address to physical address conversion */
-extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const));
-extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const));
-
-#include<asm/virtconvert.h>
-
-#define VTOP(addr)  (mm_vtop((unsigned long)(addr)))
-#define PTOV(addr)  (mm_ptov((unsigned long)(addr)))
+#include <asm/virtconvert.h>
X 
X /*
X  * Cache handling functions
@@ -436,34 +429,24 @@
X extern inline void pmd_set(pmd_t * pmdp, pte_t * ptep)
X {
X 	int i;
-
-	ptep = (pte_t *) virt_to_phys(ptep);
-	for (i = 0; i < 16; i++, ptep += PTRS_PER_PTE/16)
-		pmdp->pmd[i] = _PAGE_TABLE | _PAGE_ACCESSED | (unsigned long)ptep;
-}
-
-/* early termination version of the above */
-extern inline void pmd_set_et(pmd_t * pmdp, pte_t * ptep)
-{
-	int i;
-
-	ptep = (pte_t *) virt_to_phys(ptep);
-	for (i = 0; i < 16; i++, ptep += PTRS_PER_PTE/16)
-		pmdp->pmd[i] = _PAGE_PRESENT | _PAGE_ACCESSED | (unsigned long)ptep;
+	unsigned long ptbl;
+	ptbl = virt_to_phys(ptep);
+	for (i = 0; i < 16; i++, ptbl += sizeof(pte_table)/16)
+		pmdp->pmd[i] = _PAGE_TABLE | _PAGE_ACCESSED | ptbl;
X }
X 
X extern inline void pgd_set(pgd_t * pgdp, pmd_t * pmdp)
X { pgd_val(*pgdp) = _PAGE_TABLE | _PAGE_ACCESSED | virt_to_phys(pmdp); }
X 
X extern inline unsigned long pte_page(pte_t pte)
-{ return (unsigned long)phys_to_virt((unsigned long)(pte_val(pte) & PAGE_MASK)); }
+{ return (unsigned long)phys_to_virt(pte_val(pte) & PAGE_MASK); }
X 
X extern inline unsigned long pmd_page2(pmd_t *pmd)
-{ return (unsigned long)phys_to_virt((unsigned long)(pmd_val(*pmd) & _TABLE_MASK)); }
+{ return (unsigned long)phys_to_virt(pmd_val(*pmd) & _TABLE_MASK); }
X #define pmd_page(pmd) pmd_page2(&(pmd))
X 
X extern inline unsigned long pgd_page(pgd_t pgd)
-{ return (unsigned long)phys_to_virt((unsigned long)(pgd_val(pgd) & _TABLE_MASK)); }
+{ return (unsigned long)phys_to_virt(pgd_val(pgd) & _TABLE_MASK); }
X 
X extern inline int pte_none(pte_t pte)		{ return !pte_val(pte); }
X extern inline int pte_present(pte_t pte)	{ return pte_val(pte) & (_PAGE_PRESENT | _PAGE_FAKE_SUPER); }
@@ -547,7 +530,7 @@
X 	return mm->pgd + (address >> PGDIR_SHIFT);
X }
X 
-extern pgd_t swapper_pg_dir[128];
+#define swapper_pg_dir kernel_pg_dir
X extern pgd_t kernel_pg_dir[128];
X 
X extern inline pgd_t * pgd_offset_k(unsigned long address)
@@ -625,8 +608,6 @@
X 
X extern pmd_t *get_pointer_table(void);
X extern int free_pointer_table(pmd_t *);
-extern pmd_t *get_kpointer_table(void);
-extern void free_kpointer_table(pmd_t *);
X 
X extern __inline__ pte_t *get_pte_fast(void)
X {
@@ -754,29 +735,12 @@
X 
X extern inline void pmd_free_kernel(pmd_t * pmd)
X {
-	free_kpointer_table(pmd);
+	free_pmd_fast(pmd);
X }
X 
X extern inline pmd_t * pmd_alloc_kernel(pgd_t * pgd, unsigned long address)
X {
-	address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
-	if (pgd_none(*pgd)) {
-		pmd_t *page = get_kpointer_table();
-		if (pgd_none(*pgd)) {
-			if (page) {
-				pgd_set(pgd, page);
-				return page + address;
-			}
-			pgd_set(pgd, (pmd_t *)BAD_PAGETABLE);
-			return NULL;
-		}
-		free_kpointer_table(page);
-	}
-	if (pgd_bad(*pgd)) {
-		__bad_pmd(pgd);
-		return NULL;
-	}
-	return (pmd_t *) pgd_page(*pgd) + address;
+	return pmd_alloc(pgd, address);
X }
X 
X extern inline void pgd_free(pgd_t * pgd)
@@ -815,26 +779,7 @@
X int mm_end_of_chunk (unsigned long addr, int len);
X #endif
X 
-/*
- * Map some physical address range into the kernel address space.
- */
-extern unsigned long kernel_map(unsigned long paddr, unsigned long size,
-				int nocacheflag, unsigned long *memavailp );
-/*
- * Unmap a region alloced by kernel_map().
- */
-extern void kernel_unmap( unsigned long addr );
-/*
- * Change the cache mode of some kernel address range.
- */
-extern void kernel_set_cachemode( unsigned long address, unsigned long size,
-				  unsigned cmode );
-
-/* Values for nocacheflag and cmode */
-#define	KERNELMAP_FULL_CACHING		0
-#define	KERNELMAP_NOCACHE_SER		1
-#define	KERNELMAP_NOCACHE_NONSER	2
-#define	KERNELMAP_NO_COPYBACK		3
+extern void kernel_set_cachemode(void *addr, unsigned long size, int cmode);
X 
X /*
X  * The m68k doesn't have any external MMU info: the kernel page
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h
--- v2.2.0-pre8/linux/include/asm-m68k/processor.h	Tue Jan 19 11:32:53 1999
+++ linux/include/asm-m68k/processor.h	Tue Jan 19 10:58:34 1999
@@ -72,6 +72,8 @@
X {
X }
X 
+extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
+
X #define copy_segments(nr, tsk, mm)	do { } while (0)
X #define release_segments(mm)		do { } while (0)
X #define forget_segments()		do { } while (0)
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/semaphore.h linux/include/asm-m68k/semaphore.h
--- v2.2.0-pre8/linux/include/asm-m68k/semaphore.h	Tue Jan 19 11:32:53 1999
+++ linux/include/asm-m68k/semaphore.h	Tue Jan 19 10:58:34 1999
@@ -3,6 +3,7 @@
X 
X #include <linux/config.h>
X #include <linux/linkage.h>
+#include <asm/current.h>
X #include <asm/system.h>
X #include <asm/atomic.h>
X 
@@ -16,12 +17,23 @@
X 
X struct semaphore {
X 	atomic_t count;
+	unsigned long owner, owner_depth;
X 	atomic_t waking;
X 	struct wait_queue * wait;
X };
X 
-#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), ATOMIC_INIT(0), NULL })
-#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), ATOMIC_INIT(0), NULL })
+/*
+ * Because we want the non-contention case to be
+ * fast, we save the stack pointer into the "owner"
+ * field, and to get the true task pointer we have
+ * to do the bit masking. That moves the masking
+ * operation into the slow path.
+ */
+#define semaphore_owner(sem) \
+	((struct task_struct *)((2*PAGE_MASK) & (sem)->owner))
+
+#define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, 0, ATOMIC_INIT(0), NULL })
+#define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, 1, ATOMIC_INIT(0), NULL })
X 
X asmlinkage void __down_failed(void /* special register calling convention */);
X asmlinkage int  __down_failed_interruptible(void  /* params in registers */);
@@ -46,7 +58,9 @@
X 
X 	save_flags(flags);
X 	cli();
-	if (atomic_read(&sem->waking) > 0) {
+	if (atomic_read(&sem->waking) > 0 || (owner_depth && semaphore_owner(sem) == tsk)) {
+		sem->owner = (unsigned long)tsk;
+		sem->owner_depth++;
X 		atomic_dec(&sem->waking);
X 		ret = 1;
X 	}
@@ -56,7 +70,7 @@
X 
X 	__asm__ __volatile__
X 	  ("1:	movel	%2,%0\n"
-	   "	jeq	3f\n"
+	   "    jeq	3f\n"
X 	   "2:	movel	%0,%1\n"
X 	   "	subql	#1,%1\n"
X 	   "	casl	%0,%1,%2\n"
@@ -65,6 +79,13 @@
X 	   "	jne	2b\n"
X 	   "3:"
X 	   : "=d" (ret), "=d" (tmp), "=m" (sem->waking));
+
+	ret |= ((sem->owner_depth != 0) && (semaphore_owner(sem) == tsk));
+	if (ret) {
+		sem->owner = (unsigned long)tsk;
+		sem->owner_depth++;
+	}
+
X #endif
X 	return ret;
X }
@@ -80,7 +101,9 @@
X 	__asm__ __volatile__(
X 		"| atomic down operation\n\t"
X 		"subql #1,%0@\n\t"
-		"jmi 2f\n"
+		"jmi 2f\n\t"
+		"movel %%sp,4(%0)\n"
+		"movel #1,8(%0)\n\t"
X 		"1:\n"
X 		".section .text.lock,\"ax\"\n"
X 		".even\n"
@@ -101,6 +124,9 @@
X 		"| atomic interruptible down operation\n\t"
X 		"subql #1,%1@\n\t"
X 		"jmi 2f\n\t"
+		"movel %%sp,4(%1)\n"
+		"moveql #1,%0\n"
+		"movel %0,8(%1)\n"
X 		"clrl %0\n"
X 		"1:\n"
X 		".section .text.lock,\"ax\"\n"
@@ -125,6 +151,7 @@
X 	register struct semaphore *sem1 __asm__ ("%a1") = sem;
X 	__asm__ __volatile__(
X 		"| atomic up operation\n\t"
+		"subql #1,8(%0)\n\t"
X 		"addql #1,%0@\n\t"
X 		"jle 2f\n"
X 		"1:\n"
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/setup.h linux/include/asm-m68k/setup.h
--- v2.2.0-pre8/linux/include/asm-m68k/setup.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/setup.h	Tue Jan 19 10:58:34 1999
@@ -52,7 +52,7 @@
X 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
X #  define MACH_IS_AMIGA (m68k_machtype == MACH_AMIGA)
X #else
-#  define CONFIG_AMIGA_ONLY
+#  define MACH_AMIGA_ONLY
X #  define MACH_IS_AMIGA (1)
X #  define MACH_TYPE (MACH_AMIGA)
X #endif
@@ -63,7 +63,7 @@
X 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
X #  define MACH_IS_ATARI (m68k_machtype == MACH_ATARI)
X #else
-#  define CONFIG_ATARI_ONLY
+#  define MACH_ATARI_ONLY
X #  define MACH_IS_ATARI (1)
X #  define MACH_TYPE (MACH_ATARI)
X #endif
@@ -74,7 +74,7 @@
X 	|| defined(CONFIG_HP300) || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
X #  define MACH_IS_MAC (m68k_machtype == MACH_MAC)
X #else
-#  define CONFIG_MAC_ONLY
+#  define MACH_MAC_ONLY
X #  define MACH_IS_MAC (1)
X #  define MACH_TYPE (MACH_MAC)
X #endif
@@ -91,7 +91,7 @@
X 	|| defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
X #  define MACH_IS_APOLLO (m68k_machtype == MACH_APOLLO)
X #else
-#  define CONFIG_APOLLO_ONLY
+#  define MACH_APOLLO_ONLY
X #  define MACH_IS_APOLLO (1)
X #  define MACH_TYPE (MACH_APOLLO)
X #endif
@@ -102,7 +102,7 @@
X 	|| defined(CONFIG_APOLLO) || defined(CONFIG_BVME6000) || defined(CONFIG_HP300)
X #  define MACH_IS_MVME16x (m68k_machtype == MACH_MVME16x)
X #else
-#  define CONFIG_MVME16x_ONLY
+#  define MACH_MVME16x_ONLY
X #  define MACH_IS_MVME16x (1)
X #  define MACH_TYPE (MACH_MVME16x)
X #endif
@@ -113,7 +113,7 @@
X 	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) || defined(CONFIG_HP300)
X #  define MACH_IS_BVME6000 (m68k_machtype == MACH_BVME6000)
X #else
-#  define CONFIG_BVME6000_ONLY
+#  define MACH_BVME6000_ONLY
X #  define MACH_IS_BVME6000 (1)
X #  define MACH_TYPE (MACH_BVME6000)
X #endif
@@ -124,7 +124,7 @@
X 	|| defined(CONFIG_APOLLO) || defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
X #  define MAC_IS_HP300 (m68k_machtype == MACH_HP300)
X #else
-#  define CONFIG_HP300_ONLY
+#  define MACH_HP300_ONLY
X #  define MACH_IS_HP300 (1)
X #  define MACH_TYPE (MACH_HP300)
X #endif
@@ -260,6 +260,7 @@
X 
X #define CPU_TYPE (m68k_cputype)
X 
+
X     /*
X      *  Miscellaneous
X      */
@@ -268,7 +269,8 @@
X #define CL_SIZE		256
X 
X #ifndef __ASSEMBLY__
-extern int m68k_num_memory;		/* # of memory blocks found */
+extern int m68k_num_memory;		/* # of memory blocks found (and used) */
+extern int m68k_realnum_memory;		/* real # of memory blocks found */
X extern struct mem_info m68k_memory[NUM_MEMINFO];/* memory description */
X 
X struct mem_info {
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/system.h linux/include/asm-m68k/system.h
--- v2.2.0-pre8/linux/include/asm-m68k/system.h	Tue Jun 23 10:01:28 1998
+++ linux/include/asm-m68k/system.h	Tue Jan 19 10:58:34 1999
@@ -46,11 +46,8 @@
X #define switch_to(prev,next) { \
X   register void *_prev __asm__ ("a0") = (prev); \
X   register void *_next __asm__ ("a1") = (next); \
-  register int _tssoff __asm__ ("d1") = (int)&((struct task_struct *)0)->tss; \
-  register char _shared __asm__ ("d2") = ((prev)->mm == (next)->mm); \
-  __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume) "\n\t" \
-		       : : "a" (_prev), "a" (_next), "d" (_tssoff), \
-		           "d" (_shared) \
+  __asm__ __volatile__("jbsr " SYMBOL_NAME_STR(resume) \
+		       : : "a" (_prev), "a" (_next) \
X 		       : "d0", "d1", "d2", "d3", "d4", "d5", "a0", "a1"); \
X }
X 
@@ -60,7 +57,7 @@
X struct __xchg_dummy { unsigned long a[100]; };
X #define __xg(x) ((volatile struct __xchg_dummy *)(x))
X 
-#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) && !defined(CONFIG_HADES) && !defined(CONFIG_VME) && !defined(CONFIG_APOLLO)
+#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
X /* block out HSYNC on the atari */
X #define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
X #else /* portable version */
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/traps.h linux/include/asm-m68k/traps.h
--- v2.2.0-pre8/linux/include/asm-m68k/traps.h	Sun May 19 21:54:29 1996
+++ linux/include/asm-m68k/traps.h	Tue Jan 19 10:58:34 1999
@@ -11,10 +11,14 @@
X #ifndef _M68K_TRAPS_H
X #define _M68K_TRAPS_H
X 
+#ifndef __ASSEMBLY__
+
X typedef void (*e_vector)(void);
X 
X extern e_vector vectors[];
X 
+#endif
+
X #define VEC_BUSERR  (2)
X #define VEC_ADDRERR (3)
X #define VEC_ILLEGAL (4)
@@ -63,9 +67,12 @@
X #define VEC_FPUNSUP (55)
X #define	VEC_UNIMPEA (60)
X #define	VEC_UNIMPII (61)
+#define VEC_USER    (64)
X 
X #define VECOFF(vec) ((vec)<<2)
X 
+#ifndef __ASSEMBLY__
+
X /* Status register bits */
X #define PS_T  (0x8000)
X #define PS_S  (0x2000)
@@ -237,5 +244,7 @@
X 	    } fmtb;
X     } un;
X };
+
+#endif /* __ASSEMBLY__ */
X 
X #endif /* _M68K_TRAPS_H */
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/unistd.h linux/include/asm-m68k/unistd.h
--- v2.2.0-pre8/linux/include/asm-m68k/unistd.h	Fri Oct  9 13:27:15 1998
+++ linux/include/asm-m68k/unistd.h	Tue Jan 19 10:58:34 1999
@@ -193,6 +193,7 @@
X #define __NR_sendfile		187
X #define __NR_getpmsg		188	/* some people actually want streams */
X #define __NR_putpmsg		189	/* some people actually want streams */
+#define __NR_vfork		190
X 
X /* user-visible error numbers are in the range -1 - -122: see
X    <asm-m68k/errno.h> */
@@ -322,49 +323,6 @@
X static inline _syscall1(int,_exit,int,exitcode)
X static inline _syscall3(pid_t,waitpid,pid_t,pid,int *,wait_stat,int,options)
X static inline _syscall1(int,delete_module,const char *,name)
-
-/*
- * 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.
- */
-static inline pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	pid_t pid;
-	mm_segment_t fs;
-
-	fs = get_fs();
-	set_fs (KERNEL_DS);
-
-	{
-	register long retval __asm__ ("d0");
-	register long clone_arg __asm__ ("d1") = flags | CLONE_VM;
-
-	__asm__ __volatile__
-	  ("clrl %%d2\n\t"
-	   "trap #0\n\t"		/* Linux/m68k system call */
-	   "tstl %0\n\t"		/* child or parent */
-	   "jne 1f\n\t"			/* parent - jump */
-	   "lea %%sp@(-8192),%6\n\t"	/* reload current */
-	   "movel %3,%%sp@-\n\t"	/* push argument */
-	   "jsr %4@\n\t"		/* call fn */
-	   "movel %0,%%d1\n\t"		/* pass exit value */
-	   "movel %2,%0\n\t"		/* exit */
-	   "trap #0\n"
-	   "1:"
-	   : "=d" (retval)
-	   : "0" (__NR_clone), "i" (__NR_exit),
-	     "r" (arg), "a" (fn), "d" (clone_arg), "r" (current)
-	   : "d0", "d2");
-	pid = retval;
-	}
-
-	set_fs (fs);
-	return pid;
-}
X 
X static inline pid_t wait(int * wait_stat)
X {
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-m68k/virtconvert.h linux/include/asm-m68k/virtconvert.h
--- v2.2.0-pre8/linux/include/asm-m68k/virtconvert.h	Sat Sep  5 16:46:41 1998
+++ linux/include/asm-m68k/virtconvert.h	Tue Jan 19 10:58:34 1999
@@ -18,7 +18,7 @@
X  * Change virtual addresses to physical addresses and vv.
X  */
X extern unsigned long mm_vtop(unsigned long addr) __attribute__ ((const));
-extern unsigned long mm_vtop_fallback (unsigned long);
+extern unsigned long mm_vtop_fallback (unsigned long) __attribute__ ((const));
X extern unsigned long mm_ptov(unsigned long addr) __attribute__ ((const));
X 
X #ifdef CONFIG_SINGLE_MEMORY_CHUNK
diff -u --recursive --new-file v2.2.0-pre8/linux/include/asm-sparc64/pgtable.h linux/include/asm-sparc64/pgtable.h
--- v2.2.0-pre8/linux/include/asm-sparc64/pgtable.h	Thu Nov 19 09:56:29 1998
+++ linux/include/asm-sparc64/pgtable.h	Wed Jan 20 13:40:48 1999
@@ -371,7 +371,7 @@
X 		(unsigned long)ret->pprev_hash = mask;
X 		if (!mask)
X 			pgd_quicklist = (unsigned long *)ret->next_hash;
-                ret = (struct page *)(PAGE_OFFSET + (ret->map_nr << PAGE_SHIFT) + off);
+                ret = (struct page *) (page_address(ret) + off);
X                 pgd_cache_size--;
X         } else {
X 		ret = (struct page *) __get_free_page(GFP_KERNEL);
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/fs.h linux/include/linux/fs.h
--- v2.2.0-pre8/linux/include/linux/fs.h	Tue Jan 19 11:32:53 1999
+++ linux/include/linux/fs.h	Wed Jan 20 16:23:30 1999
@@ -420,7 +420,7 @@
X 	struct file_operations	*f_op;
X 	mode_t			f_mode;
X 	loff_t			f_pos;
-	unsigned short 		f_count, f_flags;
+	unsigned int 		f_count, f_flags;
X 	unsigned long 		f_reada, f_ramax, f_raend, f_ralen, f_rawin;
X 	struct fown_struct	f_owner;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/isdn.h linux/include/linux/isdn.h
--- v2.2.0-pre8/linux/include/linux/isdn.h	Wed Apr  1 20:11:54 1998
+++ linux/include/linux/isdn.h	Tue Jan 19 11:06:52 1999
@@ -1,9 +1,3 @@
-/* Changes for X.25 support:
-   Added ISDN_NET_ENCAP_X25IFACE macro.
-   Additional field in isdn_net_dev_s and isdn_net_local to support
-   generic encapsulation protocols. 
-*/
-
X /* $Id: isdn.h,v 1.37 1998/02/22 19:45:24 fritz Exp $
X  *
X  * Main header for the Linux ISDN subsystem (linklevel).
@@ -26,6 +20,10 @@
X  * along with this program; if not, write to the Free Software
X  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
X  *
+ * Note: This file differs from the corresponding revision as present in the
+ * isdn4linux CVS repository because some later bug fixes have been extracted
+ * from the repository and merged into this file. -- Henner Eisen
+ *
X  * $Log: isdn.h,v $
X  * Revision 1.37  1998/02/22 19:45:24  fritz
X  * Some changes regarding V.110
@@ -800,6 +798,7 @@
X   int               v110emu[ISDN_MAX_CHANNELS];/* V.110 emulator-mode 0=none */
X   atomic_t          v110use[ISDN_MAX_CHANNELS];/* Usage-Semaphore for stream */
X   isdn_v110_stream  *v110[ISDN_MAX_CHANNELS];  /* V.110 private data         */
+  struct semaphore  sem;                       /* serialize list access*/
X } isdn_dev;
X 
X extern isdn_dev *dev;
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/mm.h linux/include/linux/mm.h
--- v2.2.0-pre8/linux/include/linux/mm.h	Tue Jan 19 11:32:53 1999
+++ linux/include/linux/mm.h	Wed Jan 20 16:23:32 1999
@@ -125,12 +125,10 @@
X 	unsigned long offset;
X 	struct page *next_hash;
X 	atomic_t count;
-	unsigned int unused;
X 	unsigned long flags;	/* atomic flags, some possibly updated asynchronously */
X 	struct wait_queue *wait;
X 	struct page **pprev_hash;
X 	struct buffer_head * buffers;
-	unsigned long map_nr;	/* page->map_nr == page - mem_map */
X } mem_map_t;
X 
X /* Page flag bit values */
@@ -263,6 +261,8 @@
X 		clear_page(page);
X 	return page;
X }
+
+extern int low_on_memory;
X 
X /* memory.c & swap.c*/
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/pagemap.h linux/include/linux/pagemap.h
--- v2.2.0-pre8/linux/include/linux/pagemap.h	Thu Nov 19 09:56:29 1998
+++ linux/include/linux/pagemap.h	Wed Jan 20 16:23:33 1999
@@ -14,7 +14,7 @@
X 
X static inline unsigned long page_address(struct page * page)
X {
-	return PAGE_OFFSET + PAGE_SIZE * page->map_nr;
+	return PAGE_OFFSET + PAGE_SIZE * (page - mem_map);
X }
X 
X #define PAGE_HASH_BITS 11
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/poll.h linux/include/linux/poll.h
--- v2.2.0-pre8/linux/include/linux/poll.h	Tue Jan 19 11:32:53 1999
+++ linux/include/linux/poll.h	Wed Jan 20 16:23:35 1999
@@ -25,35 +25,14 @@
X 
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 09'
echo 'File patch-2.2.0-pre9 is continued in part 10'
echo 10 > _shar_seq_.tmp
#!/bin/sh
# this is part 10 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 10; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
X #define __MAX_POLL_TABLE_ENTRIES ((PAGE_SIZE - sizeof (poll_table)) / sizeof (struct poll_table_entry))
X 
+extern void __pollwait(struct file * filp, struct wait_queue ** wait_address, poll_table *p);
+
X extern inline void poll_wait(struct file * filp, struct wait_queue ** wait_address, poll_table *p)
X {
-	struct poll_table_entry * entry;
-
-	if (!p || !wait_address)
-		return;
-	while (p->nr >= __MAX_POLL_TABLE_ENTRIES && p->next != NULL)
-		p = p->next;
-	if (p->nr >= __MAX_POLL_TABLE_ENTRIES) {
-		poll_table *tmp = (poll_table *) __get_free_page(GFP_KERNEL);
-		if (!tmp)
-			return;
-		tmp->nr = 0;
-		tmp->entry = (struct poll_table_entry *)(tmp + 1);
-		tmp->next = NULL;
-		p->next = tmp;
-		p = tmp;
-	}
- 	entry = p->entry + p->nr;
- 	entry->filp = filp;
- 	filp->f_count++;
-	entry->wait_address = wait_address;
-	entry->wait.task = current;
-	entry->wait.next = NULL;
-	add_wait_queue(wait_address,&entry->wait);
-	p->nr++;
+	if (p && wait_address)
+		__pollwait(filp, wait_address, p);
X }
X 
-
X /*
X  * For the kernel fd_set we use a fixed set-size for allocation purposes.
X  * This set-size doesn't necessarily bear any relation to the size the user
@@ -70,15 +49,6 @@
X #define KFDS_64BLOCK ((PAGE_SIZE/(6*64))*64)
X #define KFDS_NR (KFDS_64BLOCK*8 > NR_OPEN ? NR_OPEN : KFDS_64BLOCK*8)
X typedef unsigned long kernel_fd_set[KFDS_NR/__NFDBITS];
-
-/*
- * XXX - still used by alpha osf and sparc32 compatiblity.
- */
-
-typedef struct {
-	kernel_fd_set in, out, ex;
-	kernel_fd_set res_in, res_out, res_ex;
-} fd_set_buffer;
X 
X /*
X  * Scaleable version of the fd_set.
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/swap.h linux/include/linux/swap.h
--- v2.2.0-pre8/linux/include/linux/swap.h	Wed Jan 13 15:00:44 1999
+++ linux/include/linux/swap.h	Wed Jan 20 16:21:45 1999
@@ -1,6 +1,8 @@
X #ifndef _LINUX_SWAP_H
X #define _LINUX_SWAP_H
X 
+#include <asm/page.h>
+
X #define SWAP_FLAG_PREFER	0x8000	/* set if swap priority specified */
X #define SWAP_FLAG_PRIO_MASK	0x7fff
X #define SWAP_FLAG_PRIO_SHIFT	0
@@ -25,6 +27,13 @@
X };
X 
X #ifdef __KERNEL__
+
+/*
+ * Max bad pages in the new format..
+ */
+#define __swapoffset(x) ((unsigned long)&((union swap_header *)0)->x)
+#define MAX_SWAP_BADPAGES \
+	((__swapoffset(magic.magic) - __swapoffset(info.badpages)) / sizeof(int))
X 
X #undef DEBUG_SWAP
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/linux/timex.h linux/include/linux/timex.h
--- v2.2.0-pre8/linux/include/linux/timex.h	Fri May  8 23:14:57 1998
+++ linux/include/linux/timex.h	Wed Jan 20 16:21:43 1999
@@ -45,6 +45,8 @@
X  *      Derived linux/timex.h
X  * 1995-08-13    Torsten Duwe
X  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
+ * 1997-08-30    Ulrich Windl
+ *      Added new constant NTP_PHASE_LIMIT
X  */
X #ifndef _LINUX_TIMEX_H
X #define _LINUX_TIMEX_H
@@ -102,6 +104,7 @@
X #define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */
X #define MINSEC 16L              /* min interval between updates (s) */
X #define MAXSEC 1200L            /* max interval between updates (s) */
+#define	NTP_PHASE_LIMIT	(MAXPHASE << 5)	/* beyond max. dispersion */
X 
X /*
X  * The following defines are used only if a pulse-per-second (PPS)
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/crc.h linux/include/net/irda/crc.h
--- v2.2.0-pre8/linux/include/net/irda/crc.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/crc.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Sat Dec 12 23:09:29 1998
+ * Modified at:   Tue Dec 15 22:18:53 1998
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  ********************************************************************/
@@ -20,7 +20,7 @@
X #define GOOD_FCS  0xf0b8   /* Good final FCS value */
X 
X /* Recompute the FCS with one more character appended. */
-#define IR_FCS(fcs, byte) (((fcs)>>8)^irda_crc16_table[((fcs)^(byte)) & 0xff])
+#define IR_FCS(fcs, c) (((fcs) >> 8) ^ irda_crc16_table[((fcs) ^ (c)) & 0xff])
X 
X /* Recompute the FCS with len bytes appended. */
X unsigned short crc_calc( __u16 fcs, __u8 const *buf, size_t len);
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irda.h linux/include/net/irda/irda.h
--- v2.2.0-pre8/linux/include/net/irda/irda.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irda.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Dec  9 21:13:12 1997
- * Modified at:   Mon Nov  2 14:49:11 1998
+ * Modified at:   Sat Jan 16 01:23:15 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -39,21 +39,22 @@
X #define PACK __attribute__((packed))
X 
X /* use 0 for production, 1 for verification, >2 for debug */
-#ifndef NET_DEBUG
-#define NET_DEBUG 3
-static unsigned int net_debug = NET_DEBUG;
+#ifdef CONFIG_IRDA_DEBUG
X 
-#define DEBUG(n, args...) if (net_debug >= (n)) printk( KERN_DEBUG args)
+extern __u32 irda_debug;
+
+#define IRDA_DEBUG 3
+
+#define DEBUG(n, args...) if (irda_debug >= (n)) printk( KERN_DEBUG args)
X #define ASSERT(expr, func) \
X if(!(expr)) { \
X         printk( "Assertion failed! %s,%s,%s,line=%d\n",\
X         #expr,__FILE__,__FUNCTION__,__LINE__); \
X         ##func}
X #else
-#error
X #define DEBUG(n, args...)
X #define ASSERT(expr, func)
-#endif /* NET_DEBUG */
+#endif /* CONFIG_IRDA_DEBUG */
X 
X #ifdef CHECK_SKB
X static unsigned int check_skb = CHECK_SKB;
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h
--- v2.2.0-pre8/linux/include/net/irda/irda_device.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irda_device.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Haris Zukanovic <ha...@stud.cs.uit.no>
X  * Created at:    Tue Apr 14 12:41:42 1998
- * Modified at:   Thu Dec 10 21:18:25 1998
+ * Modified at:   Mon Jan 18 10:52:10 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Haris Zukanovic, <ha...@stud.cs.uit.no>
@@ -85,8 +85,9 @@
X struct irda_device {
X 	QUEUE q; /* Must be first */
X 
-        int  magic;	/* our magic bullet */
-	char name[16];
+        int  magic;	       /* Our magic bullet */
+	char name[16];         /* Name of device "irda0" */
+	char description[32];  /* Something like "irda0 <-> ttyS0" */
X 
X 	struct irlap_cb *irlap; /* The link layer we are connected to  */
X 	struct device netdev;   /* Yes! we are some kind of netdevice */
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irlap_event.h linux/include/net/irda/irlap_event.h
--- v2.2.0-pre8/linux/include/net/irda/irlap_event.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irlap_event.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Dec 14 13:58:27 1998
+ * Modified at:   Thu Dec 17 11:58:10 1998
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
@@ -45,6 +45,7 @@
X 	LAP_NRM_S,       /* Normal response mode as secondary */
X 	LAP_XMIT_S,
X 	LAP_SCLOSE,
+	LAP_RESET_CHECK,
X } IRLAP_STATE;
X 
X /* IrLAP Events */
@@ -56,6 +57,7 @@
X 	DISCONNECT_REQUEST,
X 	DATA_REQUEST,
X 	RESET_REQUEST,
+	RESET_RESPONSE,
X 
X 	/* Send events */
X 	SEND_I_CMD,
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irlpt_cli.h linux/include/net/irda/irlpt_cli.h
--- v2.2.0-pre8/linux/include/net/irda/irlpt_cli.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlpt_cli.h	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,47 @@
+/*********************************************************************
+ *                
+ * Filename:      irlpt_client.h
+ * Version:       0.1
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <da...@cs.uit.no>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Mon Jan 11 15:58:16 1999
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>
+ *     Copyright (c) 1998, Dag Brattli, 
+ *     All Rights Reserved
+ *      
+ *     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.
+ *  
+ *     I, Thomas Davis, provide no warranty for any of this software. This
+ *     material is provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef IRLPT_CLIENT_H
+#define IRLPT_CLIENT_H
+
+/* Debug function */
+
+/* int  client_init( struct device *dev); */
+
+/*
+ * if it's static, it doesn't go in here.
+ */
+
+void irlpt_client_get_value_confirm(__u16 obj_id, 
+				    struct ias_value *value, void *priv);
+void irlpt_client_connect_indication( void *instance, void *sap, 
+				      struct qos_info *qos, 
+				      int max_seg_size,
+				      struct sk_buff *skb);
+void irlpt_client_connect_request( struct irlpt_cb *self);
+
+extern hashbin_t *irlpt_clients;
+
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irlpt_cli_fsm.h linux/include/net/irda/irlpt_cli_fsm.h
--- v2.2.0-pre8/linux/include/net/irda/irlpt_cli_fsm.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlpt_cli_fsm.h	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,34 @@
+/*********************************************************************
+ *                
+ * Filename:      irlpt_client_fsm.h
+ * Version:       0.1
+ * Sources:       irlan_event.h
+ * 
+ *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>, All Rights Reserved.
+ *     
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLPT_EVENT_H
+#define IRLPT_EVENT_H
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+extern void irlpt_client_do_event( struct irlpt_cb *self,  
+				   IRLPT_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct irlpt_info *info);
+extern void irlpt_client_next_state( struct irlpt_cb *self, 
+				     IRLPT_CLIENT_STATE state);
+
+#endif
+
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irlpt_common.h linux/include/net/irda/irlpt_common.h
--- v2.2.0-pre8/linux/include/net/irda/irlpt_common.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlpt_common.h	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,184 @@
+/*********************************************************************
+ *
+ * Filename:      irlpt.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Thomas Davis, <rat...@radiks.net>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Sun Mar  8 23:44:19 1998
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * Sources:	  irlan.c
+ *
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>,
+ *			   Dag Brattli,  <da...@cs.uit.no>
+ *     All Rights Reserved.
+ *
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLPT_COMMON_H
+#define IRLPT_COMMON_H
+
+#include <net/irda/qos.h>
+#include <net/irda/irmod.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/miscdevice.h>
+
+#include <linux/poll.h>
+
+extern char *irlpt_service_type[];
+extern char *irlpt_port_type[];
+extern char *irlpt_connected[];
+extern char *irlpt_reasons[];
+extern char *irlpt_client_fsm_state[];
+extern char *irlpt_server_fsm_state[];
+extern char *irlpt_fsm_event[];
+
+extern struct wait_queue *lpt_wait;
+
+extern struct irlpt_cb *irlpt_find_handle(unsigned int minor);
+extern void irlpt_flow_control(struct sk_buff *skb);
+
+extern ssize_t irlpt_read( struct file *file, char *buffer, 
+			   size_t count, loff_t *noidea);
+extern ssize_t irlpt_write(struct file *file, const char *buffer, 
+			   size_t count, loff_t *noidea);
+extern loff_t irlpt_seek(struct file *, loff_t, int);
+extern int irlpt_open(struct inode * inode, struct file *file);
+extern int irlpt_close(struct inode *inode, struct file *file);
+extern u_int irlpt_poll(struct file *file, poll_table *wait);
+
+/* FSM definitions */
+
+typedef enum {
+        IRLPT_CLIENT_IDLE,
+	IRLPT_CLIENT_QUERY,
+	IRLPT_CLIENT_READY,
+	IRLPT_CLIENT_WAITI,
+	IRLPT_CLIENT_WAITR,
+	IRLPT_CLIENT_CONN,
+} IRLPT_CLIENT_STATE;
+
+typedef enum {
+	IRLPT_SERVER_IDLE,
+	IRLPT_SERVER_CONN,
+} IRLPT_SERVER_STATE;
+    
+/* IrLPT Events */
+
+typedef enum {
+	QUERY_REMOTE_IAS,
+	IAS_PROVIDER_AVAIL,
+	IAS_PROVIDER_NOT_AVAIL,
+	LAP_DISCONNECT,
+	LMP_CONNECT,
+	LMP_DISCONNECT,
+	LMP_CONNECT_INDICATION,
+	LMP_DISCONNECT_INDICATION,
+#if 0
+	TTP_CONNECT_INDICATION,
+	TTP_DISCONNECT_INDICATION,
+#endif
+        IRLPT_DISCOVERY_INDICATION,
+	IRLPT_CONNECT_REQUEST,
+	IRLPT_DISCONNECT_REQUEST,
+	CLIENT_DATA_INDICATION,
+} IRLPT_EVENT;
+
+struct irlpt_info {
+	struct lsap_cb *lsap;
+	__u8 dlsap_sel;
+	__u32 daddr;
+};
+
+/* Command packet types */
+
+#define IRLPT_MAX_PACKET 1024
+#define IRLPT_MAX_HEADER LMP_MAX_HEADER
+#define IRLPT_MAX_DEVICES 3
+#define IRLPT_MAGIC 0x0755
+
+typedef enum {
+	IRLPT_DISCONNECTED,
+	IRLPT_WAITING,
+	IRLPT_CONNECTED,
+	IRLPT_FLUSHED,
+} IRLPT_SERVER_STATUS;
+
+#define IRLPT_LSAP      0x09
+
+#define PI_SERVICE_TYPE	0x00
+
+#define IRLPT_UNKNOWN         0x00            /* not defined yet. */
+#define IRLPT_THREE_WIRE_RAW  0x01		/* bit 0 */
+#define IRLPT_THREE_WIRE      0x02		/* bit 1 */
+#define IRLPT_NINE_WIRE	      0x04		/* bit 2 */
+#define IRLPT_CENTRONICS      0x08		/* bit 3 */
+#define IRLPT_SERVER_MODE     0xFF            /* our own flag */
+
+#define PI_PORT_TYPE	0x01
+
+#define IRLPT_SERIAL	0x01		/* bit 0 */
+#define IRLPT_PARALLEL	0x02		/* bit 1 */
+
+#define PI_PORT_NAME	0x02
+
+#define PI_CRITICAL	0x80
+
+struct irlpt_cb {
+	QUEUE queue;		/* must be first. */
+
+	int magic;		/* magic used to detect corruption of 
+				   the struct */
+	__u32 daddr;		/* my local address. */
+
+	struct timer_list retry_timer;
+	
+	int volatile state;	/* Current state of IrCOMM layer */
+	int open_retries;
+        int in_use;		/* flag to prevent re-use */
+        char ifname[16];		/* name of the allocated instance, 
+				   and registered device. */
+	struct lsap_cb *lsap;	/* lmp handle */
+
+	__u8 dlsap_sel;		/* remote LSAP selector address */
+	__u8 slsap_sel;		/* local LSAP selectoraddress */
+	__u8 servicetype;	/* Type of remote service, ie THREE_WIRE_RAW */
+	__u8 porttype;		/* type of remote port. */
+
+	struct miscdevice ir_dev; /* used to register the misc device. */
+
+	int count;                /* open count */
+	int irlap_data_size;	/* max frame size we can send */
+	int pkt_count;		/* how many packets are queued up */
+
+	struct wait_queue *read_wait;	/* wait queues */
+	struct wait_queue *write_wait;
+	struct wait_queue *ex_wait;
+
+	/* this is used by the server side of the system */
+
+        IRLPT_SERVER_STATE connected;
+
+	int eof;
+	int service_LSAP;
+
+	struct sk_buff_head rx_queue; /* read buffer queue */
+};
+
+/* Debug function */
+void irlpt_dump_buffer(struct sk_buff *);
+
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irlpt_server.h linux/include/net/irda/irlpt_server.h
--- v2.2.0-pre8/linux/include/net/irda/irlpt_server.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlpt_server.h	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,42 @@
+/*********************************************************************
+ *                
+ * Filename:      server.h
+ * Version:       0.1
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <da...@cs.uit.no>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Tue Sep 22 11:41:42 1998
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>
+ *     Copyright (c) 1998, Dag Brattli, 
+ *     All Rights Reserved
+ *      
+ *     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.
+ *  
+ *     I, Thomas Davis, provide no warranty for any of this software. This
+ *     material is provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef IRLPT_SERVER_H
+#define IRLPT_SERVER_H
+
+#include "qos.h"
+#include "irmod.h"
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/miscdevice.h>
+
+/* int  server_init( struct device *dev); */
+
+extern struct irlpt_cb *irlpt_server;
+
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irlpt_server_fsm.h linux/include/net/irda/irlpt_server_fsm.h
--- v2.2.0-pre8/linux/include/net/irda/irlpt_server_fsm.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/irlpt_server_fsm.h	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,30 @@
+/*********************************************************************
+ *                
+ * Filename:      server_fsm.h<2>
+ * Version:       0.1
+ * Sources:       irlan_event.h
+ * 
+ *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>, All Rights Reserved.
+ *     
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#ifndef IRLPT_EVENT_H
+#define IRLPT_EVENT_H
+
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+
+void irlpt_server_do_event( struct irlpt_cb *self,  IRLPT_EVENT event, 
+			    struct sk_buff *skb, struct irlpt_info *info);
+void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_SERVER_STATE state);
+
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irmod.h linux/include/net/irda/irmod.h
--- v2.2.0-pre8/linux/include/net/irda/irmod.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irmod.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Dec 15 13:58:52 1997
- * Modified at:   Mon Dec  7 01:40:35 1998
+ * Modified at:   Tue Jan 12 14:56:11 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X *
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -89,9 +89,11 @@
X /*
X  *  Main structure for the IrDA device (not much here :-)
X  */
-struct irda {
+struct irda_cb {
X 	struct miscdevice dev;	
X 	struct wait_queue *wait_queue;
+
+	int in_use;
X 
X 	QUEUE *event_queue; /* Events queued for the irmanager */
X 	QUEUE *todo_queue;  /* Todo list */
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irobex.h linux/include/net/irda/irobex.h
--- v2.2.0-pre8/linux/include/net/irda/irobex.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irobex.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Jul  4 22:43:57 1998
- * Modified at:   Mon Oct 19 12:32:33 1998
+ * Modified at:   Wed Jan 13 15:55:28 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -50,21 +50,29 @@
X #define IROBEX_IOCSDISCONNECT _IOW(IROBEX_IOC_MAGIC, 2, 4)
X #define IROBEX_IOC_MAXNR 2
X 
-
X #define IROBEX_MAX_HEADER (TTP_HEADER+LMP_HEADER+LAP_HEADER)
X 
+typedef enum {
+	OBEX_IDLE,       /* Doing nothing */
+	OBEX_DISCOVER,   /* Trying to discovery remote device */
+	OBEX_QUERY,      /* Querying remote LM-IAS */
+	OBEX_CONN,       /* Trying to connect to remote device */
+	OBEX_DATA,       /* Data transfer ready */
+} OBEX_STATE;
+
X struct irobex_cb {
X 	QUEUE queue;        /* Must be first! */
X 
X         int magic;          /* magic used to detect corruption of the struct */
X 
+	OBEX_STATE state;   /* Current state */
+
X 	__u32 saddr;        /* my local address */
X 	__u32 daddr;        /* peer address */
X 	unsigned long time_discovered;
X 
X         char devname[9];    /* name of the registered device */
X 	struct tsap_cb *tsap;
-	int connected;
X 	int eof;
X 
X 	__u8 dtsap_sel;         /* remote TSAP address */
@@ -81,11 +89,6 @@
X 	struct wait_queue *read_wait;
X 	struct wait_queue *write_wait;
X 
-	/* These wait queues are used for setting up a connections */
-	struct wait_queue *connect_wait;
-	struct wait_queue *discover_wait;
-	struct wait_queue *ias_wait;
-
X 	struct fasync_struct *async;
X 
X 	struct timer_list watchdog_timer;
@@ -121,13 +124,11 @@
X 
X void irobex_watchdog_timer_expired( unsigned long data);
X 
-inline void irobex_start_watchdog_timer( struct irobex_cb *self, 
-						int timeout) 
+inline void irobex_start_watchdog_timer( struct irobex_cb *self, int timeout) 
X {
X 	irda_start_timer( &self->watchdog_timer, timeout, (unsigned long) self,
X 			  irobex_watchdog_timer_expired);
X }
-
X 
X extern struct irobex_cb *irobex;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/irport.h linux/include/net/irda/irport.h
--- v2.2.0-pre8/linux/include/net/irda/irport.h	Tue Dec 22 14:16:58 1998
+++ linux/include/net/irda/irport.h	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug  3 13:49:59 1997
- * Modified at:   Wed Nov  4 15:10:41 1998
+ * Modified at:   Thu Jan  7 14:17:31 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1997, 1998 Dag Brattli <da...@cs.uit.no>
@@ -30,7 +30,7 @@
X #include <linux/skbuff.h>
X #include <linux/types.h>
X 
-#include <irda_device.h>
+#include <net/irda/irda_device.h>
X 
X #define SPEED_DEFAULT 9600
X #define SPEED_MAX     115200
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/irda/uircc.h linux/include/net/irda/uircc.h
--- v2.2.0-pre8/linux/include/net/irda/uircc.h	Wed Dec 31 16:00:00 1969
+++ linux/include/net/irda/uircc.h	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,121 @@
+/*********************************************************************
+ *                
+ * Filename:      uircc.h
+ * Version:       0.1
+ * Description:   Driver for the Sharp Universal Infrared 
+ *                Communications Controller (UIRCC)
+ * Status:        Experimental.
+ * Author:        Dag Brattli <da...@cs.uit.no>
+ * Created at:    Sat Dec 26 11:00:49 1998
+ * Modified at:   Tue Jan 19 23:52:46 1999
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
+ *      
+ *     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.
+ *  
+ *     Neither Dag Brattli nor University of Tromsø admit liability nor
+ *     provide warranty for any of this software. This material is 
+ *     provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#ifndef UIRCC_H
+#define UIRCC_H
+
+/* Control registers (write only) */
+#define UIRCC_CR0           0x00 /* Control register 0 */
+#define UIRCC_CR0_XMIT_RST  0x20 /* Transmit reset */
+#define UIRCC_CR0_RECV_RST  0x10 /* Receive reset */
+#define UIRCC_CR0_TMR_RST   0x08 /* Timer reset */
+#define UIRCC_CR0_SYS_RST   0x04 /* System reset */
+#define UIRCC_CR0_CARR_RST  0x02 /* Carrier latch reset */
+#define UIRCC_CR0_CNT_SWT   0x01 /* Transmit/receive length counter reset */
+
+#define UIRCC_CR1           0x01 /* Transmit/receive mode setting register */
+#define UIRCC_CR1_RX_DMA    0x80 /* Rx DMA mode */
+#define UIRCC_CR1_TX_DMA    0x20 /* Tx DMA mode */
+#define UIRCC_CR1_DMA_BRST  0x10 /* DMA burst mode */
+#define UIRCC_CR1_MUST_SET  0x0c /* Must be set */
+
+#define UIRCC_CR2           0x02 /* Interrupt mask register */
+#define UIRCC_CR2_RECV_OVR  0x40 /* Receive overrun error */
+#define UIRCC_CR2_RECV_FRM  0x20 /* Receive frame error */
+#define UIRCC_CR2_RECV_END  0x10 /* Receive end */
+#define UIRCC_CR2_TMR_OUT   0x08 /* Timer time-out */
+#define UIRCC_CR2_XMIT_UNR  0x04 /* Transmit under-run error */
+#define UIRCC_CR2_XMIT_END  0x01 /* Transmit end */
+#define UIRCC_CR2_RECV_MASK 0x70
+#define UIRCC_CR2_XMIT_MASK 0x05
+
+#define UIRCC_CR3           0x03 /* Transmit/receive control */
+#define UIRCC_CR3_XMIT_EN   0x80 /* Transmit enable */
+#define UIRCC_CR3_TX_CRC_EN 0x40 /* Transmit UIRCC_CRC enable */
+#define UIRCC_CR3_RECV_EN   0x20 /* Receive enable */
+#define UIRCC_CR3_RX_CRC_EN 0x10 /* Receive CRC enable */
+#define UIRCC_CR3_ADDR_CMP  0x08 /* Address comparison enable */
+#define UIRCC_CR3_MCAST_EN  0x04 /* Multicast enable */
+
+#define UIRCC_CR4           0x04 /* Transmit data length low byte */
+#define UIRCC_CR5           0x05 /* Transmit data length high byte */
+#define UIRCC_CR6           0x06 /* Transmit data writing low byte */
+#define UIRCC_CR7           0x07 /* Transmit data writing high byte */
+
+#define UIRCC_CR8           0x08 /* Self pole address */
+
+#define UIRCC_CR9           0x09 /* System control 1 */
+
+#define UIRCC_CR10          0x0a /* Modem selection */
+#define UIRCC_CR10_SIR      0x22 /* Set SIR mode */
+#define UIRCC_CR10_FIR      0x88 /* Set FIR mode */
+
+#define UIRCC_CR11          0x0b /* System control 2 (same as SR11) */
+#define UIRCC_CR11_TMR_EN   0x08
+
+#define UIRCC_CR12          0x0c /* Timer counter initial value (low byte) */
+#define UIRCC_CR13          0x0d /* Timer counter initial value (high byte) */
+
+/* Status registers (read only) */
+#define UIRCC_SR0           0x00 /* Transmit/receive status register */
+#define UIRCC_SR0_RX_RDY    0x80 /* Received data ready */
+#define UIRCC_SR0_RX_OVR    0x40 /* Receive overrun error */
+#define UIRCC_SR0_RX_CRCFRM 0x20 /* Receive CRC or framing error */
+
+#define UIRCC_SR2           0x02 /* Interrupt mask status */
+
+#define UIRCC_SR3           0x03 /* Interrupt factor register */
+#define UIRCC_SR3_RX_OVR_ER 0x40 /* Receive overrun error */
+#define UIRCC_SR3_RX_FRM_ER 0x20 /* Receive frameing error */
+#define UIRCC_SR3_RX_EOF    0x10 /* Receive end of frame */
+#define UIRCC_SR3_TMR_OUT   0x08 /* Timer timeout */
+#define UIRCC_SR3_TXUR      0x04 /* Transmit underrun */
+#define UIRCC_SR3_TX_DONE   0x01 /* Transmit all sent */
+
+#define UIRCC_SR4           0x04 /* TX/RX data length counter low byte */
+#define UIRCC_SR5           0x05 /* TX/RX data length counter high byte */
+
+#define UIRCC_SR8           0x08 /* Chip version */
+
+#define UIRCC_SR9           0x09 /* System status 1 */
+
+#define UIRCC_SR10          0x0a /* Modem select status */
+
+#define UIRCC_SR12          0x0c /* Timer counter status (low byte) */
+#define UIRCC_SR13          0x0d /* Timer counter status (high byte) */
+
+/* Private data for each instance */
+struct uircc_cb {
+	struct irda_device idev;
+	
+	__u8 cr3;                 /* Copy of register sr3 */
+};
+
+#define CR3_SET
+
+#endif
+
+
+
diff -u --recursive --new-file v2.2.0-pre8/linux/include/net/sock.h linux/include/net/sock.h
--- v2.2.0-pre8/linux/include/net/sock.h	Mon Dec 28 15:00:53 1998
+++ linux/include/net/sock.h	Wed Jan 20 16:23:35 1999
@@ -278,6 +278,7 @@
X 	char	saw_tstamp;	/* Saw TIMESTAMP on last packet		*/
X         __u8	snd_wscale;	/* Window scaling received from sender	*/
X         __u8	rcv_wscale;	/* Window scaling to send to receiver	*/
+	__u8	rexmt_done;	/* Retransmitted up to send head?	*/
X         __u32	rcv_tsval;	/* Time stamp value             	*/
X         __u32	rcv_tsecr;	/* Time stamp echo reply        	*/
X         __u32	ts_recent;	/* Time stamp to echo next		*/
@@ -910,7 +911,7 @@
X  *	Enable debug/info messages 
X  */
X 
-#if 0
+#if 1
X #define NETDEBUG(x)	do { } while (0)
X #else
X #define NETDEBUG(x)	do { x; } while (0)
diff -u --recursive --new-file v2.2.0-pre8/linux/include/video/font.h linux/include/video/font.h
--- v2.2.0-pre8/linux/include/video/font.h	Mon Oct  5 13:13:47 1998
+++ linux/include/video/font.h	Tue Jan 19 10:47:48 1999
@@ -11,19 +11,6 @@
X #ifndef _VIDEO_FONT_H
X #define _VIDEO_FONT_H
X 
-#ifdef __ASSEMBLY__
-
-#ifdef __mc68000__
-#define FBCON_FONT_DESC_idx	0
-#define FBCON_FONT_DESC_name	(FBCON_FONT_DESC_idx   +4)
-#define FBCON_FONT_DESC_width	(FBCON_FONT_DESC_name  +4)
-#define FBCON_FONT_DESC_height	(FBCON_FONT_DESC_width +4)
-#define FBCON_FONT_DESC_data	(FBCON_FONT_DESC_height+4)
-#define FBCON_FONT_DESC_pref	(FBCON_FONT_DESC_data  +4)
-#endif
-
-#else /* __ASSEMBLY__ */
-
X #include <linux/types.h>
X 
X struct fbcon_font_desc {
@@ -60,7 +47,5 @@
X 
X /* Max. length for the name of a predefined font */
X #define MAX_FONT_NAME	32
-
-#endif /* __ASSEMBLY__ */
X 
X #endif /* _VIDEO_FONT_H */
diff -u --recursive --new-file v2.2.0-pre8/linux/init/main.c linux/init/main.c
--- v2.2.0-pre8/linux/init/main.c	Mon Dec 28 15:00:53 1998
+++ linux/init/main.c	Wed Jan 20 10:18:53 1999
@@ -541,7 +541,7 @@
X #ifdef __SMP__
X 	{ "nosmp", smp_setup },
X 	{ "maxcpus=", smp_setup },
-#ifdef __i386__
+#ifdef CONFIG_X86_IO_APIC
X 	{ "noapic", ioapic_setup },
X 	{ "pirq=", ioapic_pirq_setup },
X #endif
diff -u --recursive --new-file v2.2.0-pre8/linux/kernel/ksyms.c linux/kernel/ksyms.c
--- v2.2.0-pre8/linux/kernel/ksyms.c	Tue Jan 19 11:32:53 1999
+++ linux/kernel/ksyms.c	Tue Jan 19 10:37:44 1999
@@ -36,6 +36,7 @@
X #include <linux/ctype.h>
X #include <linux/file.h>
X #include <linux/console.h>
+#include <linux/poll.h>
X 
X #if defined(CONFIG_PROC_FS)
X #include <linux/proc_fs.h>
@@ -178,6 +179,7 @@
X EXPORT_SYMBOL(vfs_rmdir);
X EXPORT_SYMBOL(vfs_unlink);
X EXPORT_SYMBOL(vfs_rename);
+EXPORT_SYMBOL(__pollwait);
X 
X #if !defined(CONFIG_NFSD) && defined(CONFIG_NFSD_MODULE)
X EXPORT_SYMBOL(do_nfsservctl);
diff -u --recursive --new-file v2.2.0-pre8/linux/kernel/sched.c linux/kernel/sched.c
--- v2.2.0-pre8/linux/kernel/sched.c	Tue Jan 19 11:32:53 1999
+++ linux/kernel/sched.c	Tue Jan 19 10:19:58 1999
@@ -7,6 +7,8 @@
X  *  1996-12-23  Modified by Dave Grothe to fix bugs in semaphores and
X  *              make semaphores SMP safe
X  *  1997-01-28  Modified by Finn Arne Gangstad to make timers scale better.
+ *  1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
X  *  1998-11-19	Implemented schedule_timeout() and related stuff
X  *		by Andrea Arcangeli
X  *  1998-12-24	Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
@@ -65,8 +67,8 @@
X long time_constant = 2;		/* pll time constant */
X long time_tolerance = MAXFREQ;	/* frequency tolerance (ppm) */
X long time_precision = 1;	/* clock precision (us) */
-long time_maxerror = MAXPHASE;	/* maximum error (us) */
-long time_esterror = MAXPHASE;	/* estimated error (us) */
+long time_maxerror = NTP_PHASE_LIMIT;	/* maximum error (us) */
+long time_esterror = NTP_PHASE_LIMIT;	/* estimated error (us) */
X long time_phase = 0;		/* phase offset (scaled us) */
X long time_freq = ((1000000 + HZ/2) % HZ - HZ/2) << SHIFT_USEC;	/* frequency offset (scaled ppm) */
X long time_adj = 0;		/* tick adjust (scaled 1 / HZ) */
@@ -1116,8 +1118,11 @@
X 
X     /* Bump the maxerror field */
X     time_maxerror += time_tolerance >> SHIFT_USEC;
-    if ( time_maxerror > MAXPHASE )
-        time_maxerror = MAXPHASE;
+    if ( time_maxerror > NTP_PHASE_LIMIT ) {
+        time_maxerror = NTP_PHASE_LIMIT;
+	time_state = TIME_ERROR;	/* p. 17, sect. 4.3, (b) */
+	time_status |= STA_UNSYNC;
+    }
X 
X     /*
X      * Leap second processing. If in leap-insert state at
@@ -1141,7 +1146,7 @@
X 	if (xtime.tv_sec % 86400 == 0) {
X 	    xtime.tv_sec--;
X 	    time_state = TIME_OOP;
-	    printk("Clock: inserting leap second 23:59:60 UTC\n");
+	    printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
X 	}
X 	break;
X 
@@ -1149,7 +1154,7 @@
X 	if ((xtime.tv_sec + 1) % 86400 == 0) {
X 	    xtime.tv_sec++;
X 	    time_state = TIME_WAIT;
-	    printk("Clock: deleting leap second 23:59:59 UTC\n");
+	    printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
X 	}
X 	break;
X 
@@ -1197,7 +1202,7 @@
X      * the pll and the PPS signal.
X      */
X     pps_valid++;
-    if (pps_valid == PPS_VALID) {
+    if (pps_valid == PPS_VALID) {	/* PPS signal lost */
X 	pps_jitter = MAXTIME;
X 	pps_stabil = MAXFREQ;
X 	time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
@@ -1212,17 +1217,38 @@
X 	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
X 
X #if HZ == 100
-    /* compensate for (HZ==100) != 128. Add 25% to get 125; => only 3% error */
+    /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
+     * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
+     */
X     if (time_adj < 0)
-	time_adj -= -time_adj >> 2;
+	time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
X     else
-	time_adj += time_adj >> 2;
+	time_adj += (time_adj >> 2) + (time_adj >> 5);
X #endif
X }
X 
X /* in the NTP reference this is called "hardclock()" */
X static void update_wall_time_one_tick(void)
X {
+	if ( (time_adjust_step = time_adjust) != 0 ) {
+	    /* We are doing an adjtime thing. 
+	     *
+	     * Prepare time_adjust_step to be within bounds.
+	     * Note that a positive time_adjust means we want the clock
+	     * to run faster.
+	     *
+	     * Limit the amount of the step to be in the range
+	     * -tickadj .. +tickadj
+	     */
+	     if (time_adjust > tickadj)
+		time_adjust_step = tickadj;
+	     else if (time_adjust < -tickadj)
+		time_adjust_step = -tickadj;
+	     
+	    /* Reduce by this step the amount of time left  */
+	    time_adjust -= time_adjust_step;
+	}
+	xtime.tv_usec += tick + time_adjust_step;
X 	/*
X 	 * Advance the phase, once it gets to one microsecond, then
X 	 * advance the tick more.
@@ -1231,37 +1257,13 @@
X 	if (time_phase <= -FINEUSEC) {
X 		long ltemp = -time_phase >> SHIFT_SCALE;
X 		time_phase += ltemp << SHIFT_SCALE;
-		xtime.tv_usec += tick + time_adjust_step - ltemp;
+		xtime.tv_usec -= ltemp;
X 	}
X 	else if (time_phase >= FINEUSEC) {
X 		long ltemp = time_phase >> SHIFT_SCALE;
X 		time_phase -= ltemp << SHIFT_SCALE;
-		xtime.tv_usec += tick + time_adjust_step + ltemp;
-	} else
-		xtime.tv_usec += tick + time_adjust_step;
-
-	if (time_adjust) {
-	    /* We are doing an adjtime thing. 
-	     *
-	     * Modify the value of the tick for next time.
-	     * Note that a positive delta means we want the clock
-	     * to run fast. This means that the tick should be bigger
-	     *
-	     * Limit the amount of the step for *next* tick to be
-	     * in the range -tickadj .. +tickadj
-	     */
-	     if (time_adjust > tickadj)
-		time_adjust_step = tickadj;
-	     else if (time_adjust < -tickadj)
-		time_adjust_step = -tickadj;
-	     else
-		time_adjust_step = time_adjust;
-	     
-	    /* Reduce by this step the amount of time left  */
-	    time_adjust -= time_adjust_step;
+		xtime.tv_usec += ltemp;
X 	}
-	else
-	    time_adjust_step = 0;
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre8/linux/kernel/time.c linux/kernel/time.c
--- v2.2.0-pre8/linux/kernel/time.c	Fri Nov 27 13:09:30 1998
+++ linux/kernel/time.c	Tue Jan 19 10:20:00 1999
@@ -16,6 +16,12 @@
X  *      adjtime interface update and CMOS clock write code
X  * 1995-08-13    Torsten Duwe
X  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
+ * 1999-01-16    Ulrich Windl
+ *	Introduced error checking for many cases in adjtimex().
+ *	Updated NTP code according to technical memorandum Jan '96
+ *	"A Kernel Model for Precision Timekeeping" by Dave Mills
+ *	Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
+ *	(Even though the technical memorandum forbids it)
X  */
X 
X #include <linux/mm.h>
@@ -88,9 +94,11 @@
X 	cli();
X 	xtime.tv_sec = value;
X 	xtime.tv_usec = 0;
-	time_state = TIME_ERROR;
-	time_maxerror = MAXPHASE;
-	time_esterror = MAXPHASE;
+	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;
X 	sti();
X 	return 0;
X }
@@ -213,6 +221,7 @@
X int do_adjtimex(struct timex *txc)
X {
X         long ltemp, mtemp, save_adjust;
+	int error = 0;
X 
X 	/* In order to modify anything, you gotta be super-user! */
X 	if (txc->modes && !capable(CAP_SYS_TIME))
@@ -235,109 +244,153 @@
X 	/* Save for later - semantics of adjtime is to return old value */
X 	save_adjust = time_adjust;
X 
+#if 0	/* STA_CLOCKERR is never set yet */
+	time_status &= ~STA_CLOCKERR;		/* reset STA_CLOCKERR */
+#endif
X 	/* If there are input parameters, then process them */
X 	if (txc->modes)
X 	{
-	    if (time_state == TIME_BAD)
-		time_state = TIME_OK;
-
-	    if (txc->modes & ADJ_STATUS)
-		time_status = txc->status;
+	    if (time_state == TIME_ERROR)
+		time_state = TIME_OK;		/* reset error -- why? */
X 
-	    if (txc->modes & ADJ_FREQUENCY)
-		time_freq = txc->freq;
+	    if (txc->modes & ADJ_STATUS)	/* only set allowed bits */
+		time_status =  (txc->status & ~STA_RONLY) |
+			      (time_status & STA_RONLY);
+
+	    if (txc->modes & ADJ_FREQUENCY) {	/* p. 22 */
+		if (txc->freq > MAXFREQ || txc->freq < -MAXFREQ) {
+		    error = -EINVAL;
+		    goto leave;
+		}
+		time_freq = txc->freq - pps_freq;
+	    }
X 
-	    if (txc->modes & ADJ_MAXERROR)
+	    if (txc->modes & ADJ_MAXERROR) {
+		if (txc->maxerror < 0 || txc->maxerror >= NTP_PHASE_LIMIT) {
+		    error = -EINVAL;
+		    goto leave;
+		}
X 		time_maxerror = txc->maxerror;
+	    }
X 
-	    if (txc->modes & ADJ_ESTERROR)
+	    if (txc->modes & ADJ_ESTERROR) {
+		if (txc->esterror < 0 || txc->esterror >= NTP_PHASE_LIMIT) {
+		    error = -EINVAL;
+		    goto leave;
+		}
X 		time_esterror = txc->esterror;
+	    }
X 
-	    if (txc->modes & ADJ_TIMECONST)
+	    if (txc->modes & ADJ_TIMECONST) {	/* p. 24 */
+		if (txc->constant < 0) {	/* NTP v4 uses values > 6 */
+		    error = -EINVAL;
+		    goto leave;
+		}
X 		time_constant = txc->constant;
+	    }
X 
-	    if (txc->modes & ADJ_OFFSET) {
-	      if ((txc->modes == ADJ_OFFSET_SINGLESHOT)
-		  || !(time_status & STA_PLL))
-		{
-		  time_adjust = txc->offset;
+	    if (txc->modes & ADJ_OFFSET) {	/* values checked earlier */
+		if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
+		    /* adjtime() is independent from ntp_adjtime() */
+		    time_adjust = txc->offset;
X 		}
-	      else if ((time_status & STA_PLL)||(time_status & STA_PPSTIME))
-		{
-		  ltemp = (time_status & STA_PPSTIME &&
-			   time_status & STA_PPSSIGNAL) ?
-		    pps_offset : txc->offset;
-
-		  /*
-		   * Scale the phase adjustment and
-		   * clamp to the operating range.
-		   */
-		  if (ltemp > MAXPHASE)
-		    time_offset = MAXPHASE << SHIFT_UPDATE;
-		  else if (ltemp < -MAXPHASE)
-		    time_offset = -(MAXPHASE << SHIFT_UPDATE);
-		  else
-		    time_offset = ltemp << SHIFT_UPDATE;
-
-		  /*
-		   * Select whether the frequency is to be controlled and in which
-		   * mode (PLL or FLL). Clamp to the operating range. Ugly
-		   * multiply/divide should be replaced someday.
-		   */
-
-		  if (time_status & STA_FREQHOLD || time_reftime == 0)
+		else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
+		    ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
+		            (STA_PPSTIME | STA_PPSSIGNAL) ?
+		            pps_offset : txc->offset;
+
+		    /*
+		     * Scale the phase adjustment and
+		     * clamp to the operating range.
+		     */
+		    if (ltemp > MAXPHASE)
+		        time_offset = MAXPHASE << SHIFT_UPDATE;
+		    else if (ltemp < -MAXPHASE)
+			time_offset = -(MAXPHASE << SHIFT_UPDATE);
+		    else
+		        time_offset = ltemp << SHIFT_UPDATE;
+
+		    /*
+		     * Select whether the frequency is to be controlled
+		     * and in which mode (PLL or FLL). Clamp to the operating
+		     * range. Ugly multiply/divide should be replaced someday.
+		     */
+
+		    if (time_status & STA_FREQHOLD || time_reftime == 0)
+		        time_reftime = xtime.tv_sec;
+		    mtemp = xtime.tv_sec - time_reftime;
X 		    time_reftime = xtime.tv_sec;
-		  mtemp = xtime.tv_sec - time_reftime;
-		  time_reftime = xtime.tv_sec;
-		  if (time_status & STA_FLL)
-		    {
-		      if (mtemp >= MINSEC)
-			{
-			  ltemp = ((time_offset / mtemp) << (SHIFT_USEC -
-							     SHIFT_UPDATE));
-			  if (ltemp < 0)
-			    time_freq -= -ltemp >> SHIFT_KH;
-			  else
-			    time_freq += ltemp >> SHIFT_KH;
-			}
-		    } 
-		  else 
-		    {
-		      if (mtemp < MAXSEC)
-			{
-			  ltemp *= mtemp;
-			  if (ltemp < 0)
-			    time_freq -= -ltemp >> (time_constant +
-						    time_constant + SHIFT_KF -
-						    SHIFT_USEC);
-			  else
-			    time_freq += ltemp >> (time_constant +
-						   time_constant + SHIFT_KF -
-						   SHIFT_USEC);
-			}
+		    if (time_status & STA_FLL) {
+		        if (mtemp >= MINSEC) {
+			    ltemp = (time_offset / mtemp) << (SHIFT_USEC -
+							      SHIFT_UPDATE);
+			    if (ltemp < 0)
+			        time_freq -= -ltemp >> SHIFT_KH;
+			    else
+			        time_freq += ltemp >> SHIFT_KH;
+			} else /* calibration interval too short (p. 12) */
+				time_state = TIME_ERROR;
+		    } else {	/* PLL mode */
+		        if (mtemp < MAXSEC) {
+			    ltemp *= mtemp;
+			    if (ltemp < 0)
+			        time_freq -= -ltemp >> (time_constant +
+							time_constant +
+							SHIFT_KF - SHIFT_USEC);
+			    else
+			        time_freq += ltemp >> (time_constant +
+						       time_constant +
+						       SHIFT_KF - SHIFT_USEC);
+			} else /* calibration interval too long (p. 12) */
+				time_state = TIME_ERROR;
X 		    }
-		  if (time_freq > time_tolerance)
-		    time_freq = time_tolerance;
-		  else if (time_freq < -time_tolerance)
-		    time_freq = -time_tolerance;
+		    if (time_freq > time_tolerance)
+		        time_freq = time_tolerance;
+		    else if (time_freq < -time_tolerance)
+		        time_freq = -time_tolerance;
X 		} /* STA_PLL || STA_PPSTIME */
+	    } /* txc->modes & ADJ_OFFSET */
+	    if (txc->modes & ADJ_TICK) {
+		/* if the quartz is off by more than 10% something is
+		   VERY wrong ! */
+		if (txc->tick < 900000/HZ || txc->tick > 1100000/HZ) {
+		    error = -EINVAL;
+		    goto leave;
+		}
+		tick = txc->tick;
X 	    }
-	    if (txc->modes & ADJ_TICK)
-	      tick = txc->tick;
-
+	} /* txc->modes */
+leave:	if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
+	    || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
+		&& (time_status & STA_PPSSIGNAL) == 0)
+	    /* p. 24, (b) */
+	    || ((time_status & (STA_PPSTIME|STA_PPSJITTER))
+		== (STA_PPSTIME|STA_PPSJITTER))
+	    /* p. 24, (c) */
+	    || ((time_status & STA_PPSFREQ) != 0
+		&& (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
+	    /* p. 24, (d) */
+		time_state = TIME_ERROR;
+	
+	if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
+	    txc->offset	   = save_adjust;
+	else {
+	    if (time_offset < 0)
+		txc->offset = -(-time_offset >> SHIFT_UPDATE);
+	    else
+		txc->offset = time_offset >> SHIFT_UPDATE;
X 	}
-	txc->offset	   = save_adjust;
-	txc->freq	   = time_freq;
+	txc->freq	   = time_freq + pps_freq;
X 	txc->maxerror	   = time_maxerror;
X 	txc->esterror	   = time_esterror;
X 	txc->status	   = time_status;
X 	txc->constant	   = time_constant;
X 	txc->precision	   = time_precision;
X 	txc->tolerance	   = time_tolerance;
-	txc->time	   = xtime;
+	do_gettimeofday(&txc->time);
X 	txc->tick	   = tick;
X 	txc->ppsfreq	   = pps_freq;
-	txc->jitter	   = pps_jitter;
+	txc->jitter	   = pps_jitter >> PPS_AVG;
X 	txc->shift	   = pps_shift;
X 	txc->stabil	   = pps_stabil;
X 	txc->jitcnt	   = pps_jitcnt;
@@ -346,7 +399,7 @@
X 	txc->stbcnt	   = pps_stbcnt;
X 
X 	sti();
-	return 0;
+	return(error < 0 ? error : time_state);
X }
X 
X asmlinkage int sys_adjtimex(struct timex *txc_p)
@@ -360,8 +413,6 @@
X 	 */
X 	if(copy_from_user(&txc, txc_p, sizeof(struct timex)))
X 		return -EFAULT;
-	if ((ret = do_adjtimex(&txc)))
-	  return ret;
-
-	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : time_state;
+	ret = do_adjtimex(&txc);
+	return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/mm/filemap.c linux/mm/filemap.c
--- v2.2.0-pre8/linux/mm/filemap.c	Tue Jan 19 11:32:53 1999
+++ linux/mm/filemap.c	Wed Jan 20 13:37:41 1999
@@ -144,7 +144,7 @@
X 		if (PageSkip(page)) {
X 			/* next_hash is overloaded for PageSkip */
X 			page = page->next_hash;
-			clock = page->map_nr;
+			clock = page - mem_map;
X 		}
X 		
X 		count--;
diff -u --recursive --new-file v2.2.0-pre8/linux/mm/page_alloc.c linux/mm/page_alloc.c
--- v2.2.0-pre8/linux/mm/page_alloc.c	Wed Jan 13 15:00:44 1999
+++ linux/mm/page_alloc.c	Wed Jan 20 13:40:00 1999
@@ -125,7 +125,7 @@
X 		if (PageSwapCache(page))
X 			panic ("Freeing swap cache page");
X 		page->flags &= ~(1 << PG_referenced);
-		free_pages_ok(page->map_nr, 0);
+		free_pages_ok(page - mem_map, 0);
X 		return;
X 	}
X }
@@ -163,7 +163,7 @@
X 			if (!dma || CAN_DMA(ret)) { \
X 				unsigned long map_nr; \
X 				(prev->next = ret->next)->prev = prev; \
-				map_nr = ret->map_nr; \
+				map_nr = ret - mem_map; \
X 				MARK_USED(map_nr, new_order, area); \
X 				nr_free_pages -= 1 << order; \
X 				EXPAND(ret, map_nr, order, new_order, area); \
@@ -189,6 +189,8 @@
X 	atomic_set(&map->count, 1); \
X } while (0)
X 
+int low_on_memory = 0;
+
X unsigned long __get_free_pages(int gfp_mask, unsigned long order)
X {
X 	unsigned long flags;
@@ -212,19 +214,18 @@
X 		 * further thought.
X 		 */
X 		if (!(current->flags & PF_MEMALLOC)) {
-			static int trashing = 0;
X 			int freed;
X 
X 			if (nr_free_pages > freepages.min) {
-				if (!trashing)
+				if (!low_on_memory)
X 					goto ok_to_allocate;
-				if (nr_free_pages > freepages.low) {
-					trashing = 0;
+				if (nr_free_pages >= freepages.high) {
+					low_on_memory = 0;
X 					goto ok_to_allocate;
X 				}
X 			}
X 
-			trashing = 1;
+			low_on_memory = 1;
X 			current->flags |= PF_MEMALLOC;
X 			freed = try_to_free_pages(gfp_mask);
X 			current->flags &= ~PF_MEMALLOC;
@@ -322,7 +323,6 @@
X 		--p;
X 		atomic_set(&p->count, 0);
X 		p->flags = (1 << PG_DMA) | (1 << PG_reserved);
-		p->map_nr = p - mem_map;
X 	} while (p > mem_map);
X 
X 	for (i = 0 ; i < NR_MEM_LISTS ; i++) {
diff -u --recursive --new-file v2.2.0-pre8/linux/mm/swapfile.c linux/mm/swapfile.c
--- v2.2.0-pre8/linux/mm/swapfile.c	Wed Jan 13 15:00:44 1999
+++ linux/mm/swapfile.c	Tue Jan 19 10:01:37 1999
@@ -627,11 +627,11 @@
X 		p->highest_bit = swap_header->info.last_page - 1;
X 		p->max	       = swap_header->info.last_page;
X 
-		if (p->max >= 0x7fffffffL/PAGE_SIZE ||
-		    (void *) &swap_header->info.badpages[(int) swap_header->info.nr_badpages-1] >= (void *) swap_header->magic.magic) {
-			error = -EINVAL;
+		error = -EINVAL;
+		if (swap_header->info.nr_badpages > MAX_SWAP_BADPAGES)
+			goto bad_swap;
+		if (p->max >= SWP_OFFSET(SWP_ENTRY(0,~0UL)))
X 			goto bad_swap;
-		}
X 		
X 		/* OK, set up the swap map and apply the bad block list */
X 		if (!(p->swap_map = vmalloc (p->max * sizeof(short)))) {
diff -u --recursive --new-file v2.2.0-pre8/linux/mm/vmscan.c linux/mm/vmscan.c
--- v2.2.0-pre8/linux/mm/vmscan.c	Tue Jan 19 11:32:53 1999
+++ linux/mm/vmscan.c	Wed Jan 20 16:27:39 1999
@@ -407,12 +407,7 @@
X 	current->session = 1;
X 	current->pgrp = 1;
X 	strcpy(current->comm, "kswapd");
-
-	/*
-	 * Hey, if somebody wants to kill us, be our guest. 
-	 * Don't come running to mama if things don't work.
-	 */
-	siginitsetinv(¤t->blocked, sigmask(SIGKILL));
+	sigfillset(¤t->blocked);
X 	
X 	/*
X 	 * Tell the memory management that we're a "memory allocator",
@@ -429,23 +424,29 @@
X 	current->flags |= PF_MEMALLOC;
X 
X 	while (1) {
-		if (signal_pending(current))
-			break;
-		current->state = TASK_INTERRUPTIBLE;
-		run_task_queue(&tq_disk);
-		schedule_timeout(HZ);
+		int tmo;
X 
X 		/*
-		 * kswapd isn't even meant to keep up with anything,
-		 * so just a few pages per second is plenty: the only
-		 * point is to make sure that the system doesn't stay
-		 * forever in a really bad memory squeeze.
+		 * Wake up once a second to see if we need to make
+		 * more memory available. When we get into a low
+		 * memory situation, we start waking up more often.
+		 *
+		 * We consider "freepages.low" to be low on memory,
+		 * but we also try to be aggressive if other processes
+		 * are low on memory and would otherwise block when
+		 * calling __get_free_page().
X 		 */
-		if (nr_free_pages < freepages.high)
-			try_to_free_pages(GFP_KSWAPD);
+		tmo = HZ;
+		if (nr_free_pages < freepages.high) {
+			if (nr_free_pages < freepages.low || low_on_memory) {
+				if (try_to_free_pages(GFP_KSWAPD))
+					tmo = (HZ+9)/10;
+			}
+		}
+		run_task_queue(&tq_disk);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(tmo);
X 	}
-
-	return 0;
X }
X 
X /*
@@ -475,11 +476,13 @@
X 		}
X 
X 		/* Try to get rid of some shared memory pages.. */
-		while (shm_swap(priority, gfp_mask)) {
-			if (!--count)
-				goto done;
+		if (gfp_mask & __GFP_IO) {
+			while (shm_swap(priority, gfp_mask)) {
+				if (!--count)
+					goto done;
+			}
X 		}
-	
+
X 		/* Then, try to page stuff out.. */
X 		while (swap_out(priority, gfp_mask)) {
X 			if (!--count)
diff -u --recursive --new-file v2.2.0-pre8/linux/net/ipv4/ip_output.c linux/net/ipv4/ip_output.c
--- v2.2.0-pre8/linux/net/ipv4/ip_output.c	Thu Jan  7 15:11:41 1999
+++ linux/net/ipv4/ip_output.c	Wed Jan 20 11:03:22 1999
@@ -35,6 +35,9 @@
X  *		Andi Kleen	:	Split fast and slow ip_build_xmit path 
X  *					for decreased register pressure on x86 
X  *					and more readibility. 
+ *		Marc Boucher	:	When call_out_firewall returns FW_QUEUE,
+ *					silently abort send instead of failing
+ *					with -EPERM.
X  */
X 
X #include <asm/uaccess.h>
@@ -128,8 +131,10 @@
X 
X 	dev = rt->u.dst.dev;
X 
+#ifdef CONFIG_FIREWALL
X 	if (call_out_firewall(PF_INET, dev, iph, NULL, &skb) < FW_ACCEPT)
X 		goto drop;
+#endif
X 
X 	ip_send_check(iph);
X 
@@ -137,8 +142,10 @@
X 	skb->dst->output(skb);
X 	return;
X 
+#ifdef CONFIG_FIREWALL
X drop:
X 	kfree_skb(skb);
+#endif
X }
X 
X int __ip_finish_output(struct sk_buff *skb)
@@ -284,8 +291,10 @@
X 
X 	dev = rt->u.dst.dev;
X 
+#ifdef CONFIG_FIREWALL
X 	if (call_out_firewall(PF_INET, dev, iph, NULL, &skb) < FW_ACCEPT) 
X 		goto drop;
+#endif
X 
X 	/* This can happen when the transport layer has segments queued
X 	 * with a cached route, and by the time we get here things are
@@ -546,9 +555,19 @@
X 		 *	Account for the fragment.
X 		 */
X 
-		if(!err &&
-		   call_out_firewall(PF_INET, rt->u.dst.dev, skb->nh.iph, NULL, &skb) < FW_ACCEPT)
-			err = -EPERM;
+#ifdef CONFIG_FIREWALL
+		if(!err) {
+			int fw_res;
+
+			fw_res = call_out_firewall(PF_INET, rt->u.dst.dev, skb->nh.iph, NULL, &skb);
+			if(fw_res == FW_QUEUE) {
+				kfree_skb(skb);
+				skb = NULL;
+			} else if(fw_res < FW_ACCEPT) {
+				err = -EPERM;
+			}
+		}
+#endif
X 
X 		if (err) { 
X 			ip_statistics.IpOutDiscards++;
@@ -564,7 +583,7 @@
X 		nfrags++;
X 
X 		err = 0; 
-		if (rt->u.dst.output(skb)) {
+		if (skb && rt->u.dst.output(skb)) {
X 			err = -ENETDOWN;
X 			ip_statistics.IpOutDiscards++;	
X 			break;
@@ -663,8 +682,20 @@
X 	if (err) 
X 		err = -EFAULT;
X 
-	if(!err && call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb) < FW_ACCEPT) 
-		err = -EPERM;
+#ifdef CONFIG_FIREWALL
+	if(!err) {
+		int fw_res;
+
+		fw_res = call_out_firewall(PF_INET, rt->u.dst.dev, iph, NULL, &skb);
+		if(fw_res == FW_QUEUE) {
+			/* re-queued elsewhere; silently abort this send */
+			kfree_skb(skb);
+			return 0;
+		}
+		if(fw_res < FW_ACCEPT)
+			err = -EPERM;
+	}
+#endif
X 
X 	if (err) { 
X 		kfree_skb(skb);
diff -u --recursive --new-file v2.2.0-pre8/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c
--- v2.2.0-pre8/linux/net/ipv4/tcp_input.c	Tue Jan 19 11:32:53 1999
+++ linux/net/ipv4/tcp_input.c	Wed Jan 20 10:11:21 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_input.c,v 1.150 1999/01/16 08:31:08 davem Exp $
+ * Version:	$Id: tcp_input.c,v 1.153 1999/01/20 07:20:03 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -100,8 +100,10 @@
X 		tp->lrcvtime = jiffies;
X 
X 		/* Help sender leave slow start quickly,
-		 * this sets our initial ato value.
+		 * and also makes sure we do not take this
+		 * branch ever again for this connection.
X 		 */
+		tp->ato = 1;
X 		tcp_enter_quickack_mode(tp);
X 	} else {
X 		int m = jiffies - tp->lrcvtime;
@@ -314,7 +316,8 @@
X 			if(!after(start_seq, TCP_SKB_CB(skb)->seq) &&
X 			   !before(end_seq, TCP_SKB_CB(skb)->end_seq)) {
X 				/* If this was a retransmitted frame, account for it. */
-				if(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS)
+				if((TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_RETRANS) &&
+				   tp->retrans_out)
X 					tp->retrans_out--;
X 				TCP_SKB_CB(skb)->sacked |= TCPCB_SACKED_ACKED;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/net/ipv4/tcp_output.c linux/net/ipv4/tcp_output.c
--- v2.2.0-pre8/linux/net/ipv4/tcp_output.c	Tue Jan 19 11:32:53 1999
+++ linux/net/ipv4/tcp_output.c	Wed Jan 20 10:11:21 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_output.c,v 1.100 1999/01/16 08:31:06 davem Exp $
+ * Version:	$Id: tcp_output.c,v 1.101 1999/01/20 07:20:14 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -544,8 +544,10 @@
X 	
X 	tp->retrans_head = tp->retrans_head->next;
X 	if((tp->retrans_head == tp->send_head) ||
-	   (tp->retrans_head == (struct sk_buff *) &sk->write_queue))
+	   (tp->retrans_head == (struct sk_buff *) &sk->write_queue)) {
X 		tp->retrans_head = NULL;
+		tp->rexmt_done = 1;
+	}
X }
X 
X /* This retransmits one SKB.  Policy decisions and retransmit queue
@@ -610,7 +612,8 @@
X 	struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
X 	struct sk_buff *skb;
X 
-	if (tp->retrans_head == NULL)
+	if (tp->retrans_head == NULL &&
+	    tp->rexmt_done == 0)
X 		tp->retrans_head = skb_peek(&sk->write_queue);
X 	if (tp->retrans_head == tp->send_head)
X 		tp->retrans_head = NULL;
diff -u --recursive --new-file v2.2.0-pre8/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c
--- v2.2.0-pre8/linux/net/ipv4/tcp_timer.c	Thu Dec 31 10:29:03 1998
+++ linux/net/ipv4/tcp_timer.c	Wed Jan 20 10:11:21 1999
@@ -5,7 +5,7 @@
X  *
X  *		Implementation of the Transmission Control Protocol(TCP).
X  *
- * Version:	$Id: tcp_timer.c,v 1.56 1998/11/30 15:18:12 davem Exp $
+ * Version:	$Id: tcp_timer.c,v 1.57 1999/01/20 07:20:21 davem Exp $
X  *
X  * Authors:	Ross Biro, <bi...@leland.Stanford.Edu>
X  *		Fred N. van Kempen, <wal...@uWalt.NL.Mugnet.ORG>
@@ -468,6 +468,7 @@
X 
X 	/* Retransmission. */
X 	tp->retrans_head = NULL;
+	tp->rexmt_done = 0;
X 	tp->fackets_out = 0;
X 	tp->retrans_out = 0;
X 	if (tp->retransmits == 0) {
diff -u --recursive --new-file v2.2.0-pre8/linux/net/ipv6/af_inet6.c linux/net/ipv6/af_inet6.c
--- v2.2.0-pre8/linux/net/ipv6/af_inet6.c	Tue Jan 19 11:32:53 1999
+++ linux/net/ipv6/af_inet6.c	Wed Jan 20 10:11:21 1999
@@ -7,7 +7,7 @@
X  *
X  *	Adapted from linux/net/ipv4/af_inet.c
X  *
- *	$Id: af_inet6.c,v 1.41 1999/01/02 16:51:50 davem Exp $
+ *	$Id: af_inet6.c,v 1.42 1999/01/19 08:20:06 davem Exp $
X  *
X  *	This program is free software; you can redistribute it and/or
X  *      modify it under the terms of the GNU General Public License
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/Config.in linux/net/irda/Config.in
--- v2.2.0-pre8/linux/net/irda/Config.in	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/Config.in	Wed Jan 20 11:05:33 1999
@@ -14,6 +14,7 @@
X       source net/irda/irlan/Config.in
X       source net/irda/irobex/Config.in
X       source net/irda/ircomm/Config.in
+      source net/irda/irlpt/Config.in
X 
X       bool 'IrDA protocol options' CONFIG_IRDA_OPTIONS
X       if [ "$CONFIG_IRDA_OPTIONS" != "n" ] ; then
@@ -21,6 +22,7 @@
X         bool '   Cache last LSAP' CONFIG_IRDA_CACHE_LAST_LSAP
X 	bool '   Fast RRs' CONFIG_IRDA_FAST_RR
X         bool '   Recycle RRs' CONFIG_IRDA_RECYCLE_RR
+	bool '   Debug information' CONFIG_IRDA_DEBUG
X       fi
X     fi
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/Makefile linux/net/irda/Makefile
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 10'
echo 'File patch-2.2.0-pre9 is continued in part 11'
echo 11 > _shar_seq_.tmp
#!/bin/sh
# this is part 11 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 11; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
--- v2.2.0-pre8/linux/net/irda/Makefile	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/Makefile	Wed Jan 20 11:05:33 1999
@@ -7,7 +7,7 @@
X #
X # Note 2! The CFLAGS definition is now in the main makefile...
X 
-ALL_SUB_DIRS := irlan ircomm compressors
+ALL_SUB_DIRS := irlan ircomm irlpt compressors
X SUB_DIRS :=
X MOD_SUB_DIRS :=
X 
@@ -36,6 +36,15 @@
X else
X   ifeq ($(CONFIG_IRLAN),m)
X   MOD_SUB_DIRS += irlan
+  endif
+endif
+
+ifeq ($(CONFIG_IRLPT),y)
+SUB_DIRS += irlpt
+O_OBJS += irlpt/irlpt.o
+else
+  ifeq ($(CONFIG_IRLPT),m)
+  MOD_IN_SUB_DIRS += irlpt
X   endif
X endif
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/af_irda.c linux/net/irda/af_irda.c
--- v2.2.0-pre8/linux/net/irda/af_irda.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/af_irda.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun May 31 10:12:43 1998
- * Modified at:   Mon Dec 14 10:39:45 1998
+ * Modified at:   Thu Jan 14 13:42:16 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       af_netroom.c, af_ax25.x
X  * 
@@ -703,7 +703,7 @@
X  */
X void irda_proto_init(struct net_proto *pro)
X {
-	DEBUG( 0, __FUNCTION__ "\n");
+	DEBUG( 4, __FUNCTION__ "\n");
X 
X 	/* sock_register( irda_proto_ops.family, &irda_proto_ops); */
X 	irda_packet_type.type = htons(ETH_P_IRDA);
@@ -723,7 +723,7 @@
X  */
X void irda_proto_cleanup(void)
X {
-	DEBUG( 0, __FUNCTION__ "\n");
+	DEBUG( 4, __FUNCTION__ "\n");
X 
X 	irda_packet_type.type = htons(ETH_P_IRDA);
X         dev_remove_pack(&irda_packet_type);
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irda_device.c linux/net/irda/irda_device.c
--- v2.2.0-pre8/linux/net/irda/irda_device.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irda_device.c	Wed Jan 20 11:05:33 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X  * Filename:      irda_device.c
- * Version:       
- * Description:   
+ * Version:       0.3
+ * Description:   Abstract device driver layer and helper functions
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Wed Sep  2 20:22:08 1998
- * Modified at:   Mon Dec 14 19:18:51 1998
+ * Modified at:   Mon Jan 18 11:05:59 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -122,8 +122,6 @@
X 	int result;
X 	int i=0;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n");     
-
X 	/* Check that a minimum of allocation flags are specified */
X 	ASSERT(( self->rx_buff.flags & (GFP_KERNEL|GFP_ATOMIC)) != 0, 
X 	       return -1;);
@@ -160,7 +158,6 @@
X 
X 	/* A pointer to the low level implementation */
X 	self->priv = priv;
-	strncpy( self->name, name, 16);
X 
X 	/* Initialize IrDA net device */
X 	do {
@@ -172,16 +169,25 @@
X 	self->netdev.next = NULL;
X 
X 	if (( result = register_netdev( &self->netdev)) != 0) {
-		DEBUG( 0, "IrDA Device, register_netdev() failed!\n");
+		DEBUG( 0, __FUNCTION__ "(), register_netdev() failed!\n");
X 		return -1;
X 	}
X 
+	/* 
+	 * Make the description for the device. self->netdev.name will get
+	 * a name like "irda0" and the self->descriptin will get a name
+	 * like "irda0 <-> irtty0" 
+	 */
+	strncpy( self->description, self->name, 4);
+	strcat( self->description, " <-> ");
+	strncat( self->description, name, 23);
+
X 	hashbin_insert( irda_device, (QUEUE *) self, (int) self, NULL);
X 
X 	/* Open network device */
X 	dev_open( &self->netdev);
X 
-	printk( "IrDA irda_device %s registered.\n", self->name);
+	printk( "IrDA device %s registered.\n", self->name);
X 
X 	irda_device_set_media_busy( self, FALSE);
X         
@@ -536,7 +542,7 @@
X  *
X  */
X int irda_device_proc_read( char *buf, char **start, off_t offset, int len, 
-		      int unused)
+			   int unused)
X {
X 	struct irda_device *self;
X 	unsigned long flags;
@@ -548,7 +554,11 @@
X 
X 	self = (struct irda_device *) hashbin_get_first( irda_device);
X 	while ( self != NULL) {
-		len += sprintf( buf+len, "Irda_Device name: %s\n", self->name);
+		len += sprintf( buf+len, "device name: %s\n", self->name);
+		len += sprintf( buf+len, "description: %s\n", 
+				self->description);
+		len += sprintf( buf+len, "  tbusy=%s\n", self->netdev.tbusy ? 
+				"TRUE" : "FALSE");
X 		len += sprintf( buf+len, "  bps\tmaxtt\tdsize\twinsize\taddbofs\tmintt\tldisc\n");
X 		
X 		len += sprintf( buf+len, "  %d\t", 
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/iriap.c linux/net/irda/iriap.c
--- v2.2.0-pre8/linux/net/irda/iriap.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/iriap.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Wed Dec  9 02:19:23 1998
+ * Modified at:   Tue Dec 15 16:00:35 1998
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
@@ -24,10 +24,12 @@
X  ********************************************************************/
X 
X #include <linux/config.h>
-#include <asm/byteorder.h>
X #include <linux/types.h>
X #include <linux/skbuff.h>
X #include <linux/string.h>
+#include <linux/init.h>
+
+#include <asm/byteorder.h>
X 
X #include <net/irda/irda.h>
X #include <net/irda/irttp.h>
@@ -50,7 +52,7 @@
X  *    Initializes the IrIAP layer, called by the module initialization code
X  *    in irmod.c 
X  */
-int iriap_init(void) 
+__initfunc(int iriap_init(void))
X {
X 	struct ias_object *obj;
X 
@@ -102,15 +104,11 @@
X  */
X void iriap_cleanup(void) 
X {
-	DEBUG( 4, "--> iriap_cleanup\n");
-
X 	irlmp_unregister_layer( S_COMPUTER, SERVER | CLIENT);
X 	irlmp_unregister_layer( S_PNP, SERVER);
X 	
X 	hashbin_delete( iriap, (FREE_FUNC) __iriap_close);
-	hashbin_delete( objects, (FREE_FUNC) __irias_delete_object);
-	
-	DEBUG( 4, "iriap_cleanup -->\n");
+	hashbin_delete( objects, (FREE_FUNC) __irias_delete_object);	
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irias_object.c linux/net/irda/irias_object.c
--- v2.2.0-pre8/linux/net/irda/irias_object.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irias_object.c	Wed Jan 20 11:05:33 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X  * Filename:      irias_object.c
- * Version:       0.1
+ * Version:       0.3
X  * Description:   IAS object database and functions
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Oct  1 22:50:04 1998
- * Modified at:   Sat Dec  5 13:54:39 1998
+ * Modified at:   Tue Dec 15 09:19:43 1998
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlan/irlan_cli.c linux/net/irda/irlan/irlan_cli.c
--- v2.2.0-pre8/linux/net/irda/irlan/irlan_cli.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_cli.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Dec 14 10:44:07 1998
+ * Modified at:   Mon Jan 18 13:24:26 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * Sources:       skeleton.c by Donald Becker <bec...@CESDIS.gsfc.nasa.gov>
X  *                slip.c by Laurence Culhane, <l...@holmes.demon.co.uk>
@@ -143,11 +143,9 @@
X  */
X void irlan_client_cleanup(void) 
X {
-	DEBUG( 0, "--> irlan_client_cleanup\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	irlmp_unregister_layer( S_LAN, CLIENT);
-
-	DEBUG( 4, "irlan_client_cleanup -->\n");
X }
X 
X /*
@@ -244,7 +242,7 @@
X       	if ( self != NULL) {
X 		ASSERT( self->magic == IRLAN_MAGIC, return;);
X 
-		DEBUG( 0, "Found instance!\n");
+		DEBUG( 4, __FUNCTION__ "(), Found instance!\n");
X 		if ( self->state == IRLAN_IDLE) {
X 			/* daddr may have changed! */
X 			self->daddr = daddr;
@@ -311,10 +309,10 @@
X 	DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
X 	
X 	if ( tsap == self->tsap_data) {
-		DEBUG( 0, "IrLAN, data channel disconnected by peer!\n");
+		DEBUG( 4, "IrLAN, data channel disconnected by peer!\n");
X 		self->connected = FALSE;
X 	} else if ( tsap == self->tsap_ctrl) {
-		DEBUG( 0, "IrLAN, control channel disconnected by peer!\n");
+		DEBUG( 4, "IrLAN, control channel disconnected by peer!\n");
X 	} else {
X 		DEBUG( 0, "Error, disconnect on unknown handle!\n");
X 	}
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
--- v2.2.0-pre8/linux/net/irda/irlan/irlan_common.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlan/irlan_common.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:37 1997
- * Modified at:   Mon Dec 14 10:43:05 1998
+ * Modified at:   Tue Jan 19 23:11:30 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
@@ -23,7 +23,7 @@
X  ********************************************************************/
X 
X #include <linux/config.h>
-#include <linux/module.h> 
+#include <linux/module.h>
X 
X #include <linux/kernel.h>
X #include <linux/string.h>
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlap.c linux/net/irda/irlap.c
--- v2.2.0-pre8/linux/net/irda/irlap.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlap.c	Wed Jan 20 11:05:33 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X  * Filename:      irlap.c
- * Version:       0.3
+ * Version:       0.8
X  * Description:   An IrDA LAP driver for Linux
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Mon Dec 14 11:54:42 1998
+ * Modified at:   Sat Jan 16 22:19:27 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
@@ -208,7 +208,7 @@
X  */
X void irlap_connect_indication( struct irlap_cb *self, struct sk_buff *skb) 
X {
-	DEBUG( 4, "irlap_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -257,7 +257,7 @@
X 	if ( self->state == LAP_NDM) {
X 		irlap_do_event( self, CONNECT_REQUEST, NULL, NULL);
X 	} else {
-		DEBUG( 0, "irlap_connect_request() Wrong state!\n");
+		DEBUG( 0, __FUNCTION__ "() Wrong state!\n");
X 		
X 		irlap_disconnect_indication( self, LAP_MEDIA_BUSY);
X 	}
@@ -295,8 +295,6 @@
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
X 
-	IS_SKB( skb, return;);
-
X 	/* Hide LAP header from IrLMP layer */
X 	skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
X 
@@ -321,14 +319,12 @@
X  */
X void irlap_unit_data_indication( struct irlap_cb *self, struct sk_buff *skb)
X {
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	DEBUG( 0, __FUNCTION__ "()\n"); 
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
X 
-	IS_SKB( skb, return;);
-
X 	/* Hide LAP header from IrLMP layer */
X 	skb_pull( skb, LAP_ADDR_HEADER+LAP_CTRL_HEADER);
X 
@@ -342,9 +338,7 @@
X 		}
X 	}
X #endif
-	
-	irlmp_link_data_indication( self->notify.instance, LAP_UNRELIABLE, 
-				    skb);
+	irlmp_link_data_indication(self->notify.instance, LAP_UNRELIABLE, skb);
X }
X 
X /*
@@ -362,8 +356,6 @@
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
X 
-	IS_SKB( skb, return;);
-
X 	DEBUG( 4, "irlap_data_request: tx_list=%d\n", 
X 		   skb_queue_len( &self->tx_list));
X 
@@ -392,8 +384,6 @@
X 		skb->data[1] = UI_FRAME;
X 	}
X 
-	IS_SKB( skb, return;);
-
X 	/* 
X 	 *  Send event if this frame only if we are in the right state 
X 	 *  FIXME: udata should be sent first! (skb_queue_head?)
@@ -408,7 +398,6 @@
X 			skb = skb_dequeue( &self->tx_list);
X 			
X 			ASSERT( skb != NULL, return;);
-			IS_SKB( skb, return;);
X 		}
X 		irlap_do_event( self, SEND_I_CMD, skb, NULL);
X 	} else
@@ -479,8 +468,6 @@
X {
X 	struct irlap_info info;
X 	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
-
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( discovery != NULL, return;);
@@ -506,26 +493,22 @@
X  	} 
X }
X 
-
X /*
X  * Function irlap_discovery_confirm (log)
X  *
X  *    A device has been discovered in front of this station, we
X  *    report directly to LMP.
X  */
-void irlap_discovery_confirm( struct irlap_cb *self, 
-			      hashbin_t *discovery_log) 
+void irlap_discovery_confirm( struct irlap_cb *self, hashbin_t *discovery_log) 
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
-
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	
X 	ASSERT( self->notify.instance != NULL, return;);
-
+	
X 	/* Inform IrLMP */
X 	irlmp_link_discovery_confirm( self->notify.instance, discovery_log);
-
+	
X 	/* 
X 	 *  IrLMP has now the responsibilities for the discovery_log 
X 	 */
@@ -538,8 +521,7 @@
X  *    Somebody is trying to discover us!
X  *
X  */
-inline void irlap_discovery_indication( struct irlap_cb *self, 
-					DISCOVERY *discovery) 
+void irlap_discovery_indication( struct irlap_cb *self, DISCOVERY *discovery) 
X {
X 	DEBUG( 4, __FUNCTION__ "()\n");
X 
@@ -587,7 +569,10 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	
-	irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+	if ( self->state == LAP_RESET_WAIT)
+		irlap_do_event( self, RESET_REQUEST, NULL, NULL);
+	else
+		irlap_do_event( self, RESET_RESPONSE, NULL, NULL);
X }
X 
X /*
@@ -598,7 +583,7 @@
X  */
X void irlap_reset_confirm(void)
X {
-	DEBUG( 0, __FUNCTION__ "() Not implemented!\n");	
+	DEBUG( 0, __FUNCTION__ "()\n");
X }
X 
X /*
@@ -616,8 +601,6 @@
X 
X 	slot = s + jiffies % (S-s);
X 	
-	DEBUG( 4, "S=%d, s=%d, rnd=%d\n", S, s, slot);
-
X 	ASSERT(( slot >= s) || ( slot < S), return 0;);
X 	
X 	return slot;
@@ -687,9 +670,7 @@
X 	ASSERT( self != NULL, return -ENODEV;);
X 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
X 
-	/* 
-	 *  ns as expected?
-	 */
+	/*  ns as expected?  */
X 	if ( ns == self->vr) {
X 		DEBUG( 4, "*** irlap_validate_ns_received: expected!\n");
X 		return NS_EXPECTED;
@@ -713,9 +694,7 @@
X 	ASSERT( self != NULL, return -ENODEV;);
X 	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
X 
-	/* 
-	 *  nr as expected?
-	 */
+	/*  nr as expected?  */
X 	if ( nr == self->vs) {
X 		DEBUG( 4, "*** irlap_validate_nr_received: expected!\n");
X 		return NR_EXPECTED;
@@ -726,24 +705,14 @@
X 	 *  ns numbers of the frames in the current window wrap.
X 	 */
X 	if ( self->va < self->vs) {
-		if (( nr >= self->va) && ( nr <= self->vs)) {
-			DEBUG( 4, "*** irlap_validate_nr_received:"
-			       " unexpected nr, no wrap\n");
+		if (( nr >= self->va) && ( nr <= self->vs))
X 			return NR_UNEXPECTED;
-		}
X 	} else {
-		if (( nr >= self->va) || ( nr <= self->vs)) {
-			DEBUG( 4, "*** irlap_validate_nr_received:"
-			       " unexpected nr, wrapped\n");
+		if (( nr >= self->va) || ( nr <= self->vs)) 
X 			return NR_UNEXPECTED;
-		}
-	}	
-
+	}
+	
X 	/* Invalid nr!  */
-	DEBUG( 4, "irlap_validate_nr_received: invalid nr!, "
-	       " vs=%d, vr=%d, va=%d, nr=%d\n",
-	       self->vs, self->vr, self->va, nr);
-
X 	return NR_INVALID;
X }
X 
@@ -760,9 +729,7 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 
-	/*
-	 * Next to send and next to receive
-	 */
+	/* Next to send and next to receive */
X 	self->vs = self->vr = 0;
X 
X 	/* Last frame which got acked (0 - 1) % 8 */
@@ -792,9 +759,7 @@
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( qos != NULL, return;);
X 
-	/*
-	 *  Get QoS values.
-	 */
+	/* Get QoS values.  */
X 	speed = qos->baud_rate.value;
X 	usecs = qos->min_turn_time.value;
X 
@@ -828,24 +793,23 @@
X {
X 	struct sk_buff* skb;
X 
-	DEBUG( 4, "irlap_flush_all_queues()\n");
-
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 
-	/*
-	 *  Free transmission queue
-	 */
-	while (( skb = skb_dequeue( &self->tx_list)) != NULL) {
+	/* Free transmission queue */
+	while (( skb = skb_dequeue( &self->tx_list)) != NULL)
X 		dev_kfree_skb( skb);
-	}
X 	
-	/*
-	 *  Free sliding window buffered packets
-	 */
-	while (( skb = skb_dequeue( &self->wx_list)) != NULL) {
+	/* Free sliding window buffered packets */
+	while (( skb = skb_dequeue( &self->wx_list)) != NULL)
X 		dev_kfree_skb( skb);
-	}
+
+#ifdef CONFIG_IRDA_RECYCLE_RR
+	if ( self->recycle_rr_skb) { 
+ 		dev_kfree_skb( self->recycle_rr_skb);
+ 		self->recycle_rr_skb = NULL;
+ 	}
+#endif
X }
X 
X /*
@@ -972,10 +936,14 @@
X 
X 	/* Use 500ms in IrLAP for now */
X 	self->qos_rx.max_turn_time.bits &= 0x03;
+	self->qos_rx.max_turn_time.bits &= 0x01;
X 
X 	/* Set data size */
X 	/* self->qos_rx.data_size.bits &= 0x03; */
X 
+	/* Set disconnect time */
+	self->qos_rx.link_disc_time.bits &= 0x07;
+
X 	irda_qos_bits_to_value( &self->qos_rx);
X }
X 
@@ -987,7 +955,7 @@
X  */
X void irlap_apply_default_connection_parameters( struct irlap_cb *self)
X {
-	DEBUG( 4, "irlap_apply_default_connection_parameters()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
@@ -1062,13 +1030,6 @@
X 	self->poll_timeout = qos->max_turn_time.value / 10;
X 	self->final_timeout = qos->max_turn_time.value / 10;
X 	self->wd_timeout = self->poll_timeout * 2;
-
-	DEBUG( 4, __FUNCTION__ "(), Setting poll timeout = %d\n", 
-	       self->poll_timeout);
-	DEBUG( 4, __FUNCTION__ "(), Setting final timeout = %d\n", 
-	       self->final_timeout);
-	DEBUG( 4, __FUNCTION__ "(), Setting wd timeout = %d\n", 
-	       self->wd_timeout);
X 
X #ifdef CONFIG_IRDA_COMPRESSION
X 	if ( qos->compression.value) {
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlap_event.c linux/net/irda/irlap_event.c
--- v2.2.0-pre8/linux/net/irda/irlap_event.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlap_event.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sat Aug 16 00:59:29 1997
- * Modified at:   Mon Dec 14 14:16:00 1998
+ * Modified at:   Tue Jan 19 22:58:45 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>,
@@ -68,6 +68,8 @@
X 				struct sk_buff *skb, struct irlap_info *info);
X static int irlap_state_sclose ( struct irlap_cb *self, IRLAP_EVENT event, 
X 				struct sk_buff *skb, struct irlap_info *info);
+static int irlap_state_reset_check( struct irlap_cb *, IRLAP_EVENT event, 
+				    struct sk_buff *, struct irlap_info *);
X 
X static char *irlap_event[] = {
X 	"DISCOVERY_REQUEST",
@@ -76,6 +78,7 @@
X 	"DISCONNECT_REQUEST",
X 	"DATA_REQUEST",
X 	"RESET_REQUEST",
+	"RESET_RESPONSE",
X 	"SEND_I_CMD",
X 	"RECV_DISCOVERY_XID_CMD",
X 	"RECV_DISCOVERY_XID_RSP",
@@ -115,6 +118,7 @@
X 	"LAP_NRM_S",
X 	"LAP_XMIT_S",
X 	"LAP_SCLOSE",
+	"LAP_RESET_CHECK",
X };
X 
X static int (*state[])( struct irlap_cb *self, IRLAP_EVENT event, 
@@ -134,6 +138,7 @@
X 	irlap_state_nrm_s,
X 	irlap_state_xmit_s,
X 	irlap_state_sclose,
+	irlap_state_reset_check,
X };
X 
X /*
@@ -146,8 +151,6 @@
X {
X 	struct irlap_cb *self = (struct irlap_cb *) data;
X 	
-	DEBUG( 4, "Poll timer expired!\n");
-	
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	
@@ -252,8 +255,7 @@
X  *
X  */
X void irlap_next_state( struct irlap_cb *self, IRLAP_STATE state) 
-{
-	
+{	
X 	if ( !self || self->magic != LAP_MAGIC) {
X 		DEBUG( 4, "irlap_next_state: I have lost myself!\n");
X 		return;
@@ -285,7 +287,7 @@
X 	DISCOVERY *discovery_rsp;
X 	int ret = 0;
X 	
-	DEBUG( 4, "irlap_state_ndm()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	ASSERT( self != NULL, return -1;);
X 	ASSERT( self->magic == LAP_MAGIC, return -1;);
@@ -404,7 +406,7 @@
X 		ASSERT( info != NULL, return -1;);
X 		ASSERT( info->discovery != NULL, return -1;);
X 
-		DEBUG( 4, "irlap_state_query(), daddr=%08x\n", 
+		DEBUG( 4, __FUNCTION__ "(), daddr=%08x\n", 
X 		       info->discovery->daddr);
X 
X 		hashbin_insert( self->discovery_log, 
@@ -443,7 +445,7 @@
X 		}
X 		break;
X 	default:
-		DEBUG( 4, "irlap_state_query: Unknown event %d, %s\n", event, 
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
X 		       irlap_event[event]);
X 
X 		if ( skb != NULL) {
@@ -468,14 +470,14 @@
X 	DISCOVERY *discovery_rsp;
X 	int ret=0;
X 
-	DEBUG( 4, "irlap_state_reply()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return -1;);
X 	ASSERT( self->magic == LAP_MAGIC, return -1;);
X 
X 	switch( event) {
X 	case QUERY_TIMER_EXPIRED:
-		DEBUG( 0, "irlap_state_reply: QUERY_TIMER_EXPIRED <%ld>\n",
+		DEBUG( 0, __FUNCTION__ "(), QUERY_TIMER_EXPIRED <%ld>\n",
X 		       jiffies);
X 		irlap_next_state( self, LAP_NDM);
X 		break;
@@ -532,7 +534,7 @@
X {
X 	int ret = 0;
X 
-	DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
+	DEBUG( 4, __FUNCTION__ "(), event=%s\n", irlap_event[ event]);
X 
X 	ASSERT( self != NULL, return -1;);
X 	ASSERT( self->magic == LAP_MAGIC, return -1;);
@@ -564,14 +566,14 @@
X 		break;
X 
X 	case RECV_SNRM_CMD:
-		DEBUG( 3, "irlap_state_conn: event RECV_SNRM_CMD!\n");
+		DEBUG( 3, __FUNCTION__ "(), event RECV_SNRM_CMD!\n");
X #if 0
X 		irlap_next_state( self, LAP_NDM);
X #endif
X 		break;
X 
X 	case RECV_DISCOVERY_XID_CMD:
-		DEBUG( 3, "irlap_state_conn: event RECV_DISCOVER_XID_CMD!\n");
+		DEBUG( 3, __FUNCTION__ "(), event RECV_DISCOVER_XID_CMD!\n");
X 		irlap_next_state( self, LAP_NDM);
X 		break;
X 
@@ -581,7 +583,7 @@
X 		break;
X 
X 	default:
-		DEBUG( 0, "irlap_state_conn: Unknown event %d, %s\n", event, 
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, %s\n", event, 
X 		       irlap_event[event]);
X 		ret = -1;
X 		break;
@@ -631,7 +633,7 @@
X 		break;
X 
X 	case RECV_SNRM_CMD:
-		DEBUG( 0, "irlap_state_setup: SNRM battle!\n");
+		DEBUG( 4, __FUNCTION__ "(), SNRM battle!\n");
X 
X 		ASSERT( skb != NULL, return 0;);
X 		ASSERT( info != NULL, return 0;);
@@ -672,7 +674,6 @@
X 		irlap_initiate_connection_state( self);
X 
X 		/* Negotiate connection parameters */
-		IS_SKB( skb, return -1;);
X 		ASSERT( skb->len > 10, return -1;);
X 		skb_pull( skb, 10);
X 
@@ -741,7 +742,7 @@
X 	switch( event) {
X 	case SEND_I_CMD:
X 		ASSERT( skb != NULL, return -1;);
-		DEBUG( 4, "irlap_state_xmit: Window=%d\n", self->window);
+		DEBUG( 4, __FUNCTION__ "(), Window=%d\n", self->window);
X 		
X 		/*
X 		 *  Only send frame if send-window > 0.
@@ -790,7 +791,7 @@
X 			self->fast_RR = FALSE;
X #endif
X 		} else {
-			DEBUG( 0, __FUNCTION__ 
+			DEBUG( 4, __FUNCTION__ 
X 			       "(), Unable to send! remote busy?\n");
X 			skb_queue_head( &self->tx_list, skb);
X 
@@ -869,7 +870,7 @@
X 		}
X 		break;
X 	default:
-		DEBUG( 0, "irlap_state_pclose: Unknown event %d\n", event);
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d\n", event);
X 		ret = -1;
X 		break;	
X 	}
@@ -897,7 +898,7 @@
X 
X 	switch( event) {
X 	case RECV_RR_RSP:
-		DEBUG( 4, "irlap_state_nrm_p: RECV_RR_FRAME: "
+		DEBUG( 4, __FUNCTION__ "(), RECV_RR_FRAME: "
X 		       "Retrans:%d, nr=%d, va=%d, vs=%d, vr=%d\n",
X 		       self->retry_count, info->nr, self->va, self->vs, 
X 		       self->vr);
@@ -1074,8 +1075,8 @@
X 				/* Keep state */
X 				irlap_next_state( self, LAP_NRM_P);
X 			} else {
-				DEBUG( 4, "*** irlap_state_nrm_p:"
-				       " missing or duplicate frame!\n");
+				DEBUG( 4, __FUNCTION__
+				       "(), missing or duplicate frame!\n");
X 				
X 				/* Update Nr received */
X 				irlap_update_nr_received( self, info->nr);
@@ -1321,7 +1322,7 @@
X 		irlap_next_state( self, LAP_PCLOSE);
X 		break;
X 	default:
-		DEBUG( 0, "irlap_state_reset_wait: Unknown event %s\n", 
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
X 		       irlap_event[event]);
X 		ret = -1;
X 		break;	
@@ -1402,7 +1403,7 @@
X 		break;
X 
X 	default:
-		DEBUG( 0, "irlap_state_reset: Unknown event %s\n", 
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %s\n", 
X 		       irlap_event[ event]);
X 		ret = -1;
X 		break;	
@@ -1429,9 +1430,6 @@
X 	
X 	switch( event) {
X 	case SEND_I_CMD:
-		ASSERT( skb != NULL, return -1;);
-		DEBUG( 4, "irlap_state_xmit: Window=%d\n", self->window);
-		
X 		/*
X 		 *  Send frame only if send window > 1
X 		 */ 
@@ -1463,16 +1461,16 @@
X 			if (( self->window > 1) && 
X 			    skb_queue_len( &self->tx_list) > 0) 
X 			{   
-				DEBUG( 4, "irlap_state_xmit: window > 1\n");
+				DEBUG( 4, __FUNCTION__ "(), window > 1\n");
X 				irlap_send_data_secondary( self, skb);
X 				irlap_next_state( self, LAP_XMIT_S);
X 			} else {
-				DEBUG( 4, "irlap_state_xmit: window <= 1\n");
+				DEBUG( 4, "(), window <= 1\n");
X 				irlap_send_data_secondary_final( self, skb);
X 				irlap_next_state( self, LAP_NRM_S);
X 			}
X 		} else {
-			DEBUG( 0, "Unable to send!\n");
+			DEBUG( 0, __FUNCTION__ "(), Unable to send!\n");
X 			skb_queue_head( &self->tx_list, skb);
X 			ret = -EPROTO;
X 		}
@@ -1545,7 +1543,7 @@
X 			/* Keep state */
X 			irlap_next_state( self, LAP_NRM_S); 
X 		} else {
-			DEBUG( 0, "irlap_state_nrm_s: **** "
+			DEBUG( 0, __FUNCTION__ "(), "
X 			       "invalid nr not implemented!\n");
X 		} 
X 		if ( skb)
@@ -1732,23 +1730,17 @@
X 		}
X 		break;
X 	case RECV_SNRM_CMD:
-#if 1
X 		del_timer( &self->wd_timer);
X 		DEBUG( 0, "irlap_state_nrm_s: received SNRM cmd\n");
-		irlap_next_state( self, LAP_RESET);
-#else
-		irlap_wait_min_turn_around( &self->qos_session);
-		irlap_send_ua_response_frame( &self->qos_session);
-		irda_start_timer( WD_TIMER, self->wd_timeout);
-		irlap_next_state( self, LAP_SCLOSE)
-		
-#endif
+		irlap_next_state( self, LAP_RESET_CHECK);
+
+		irlap_reset_indication( self);
X 		break;
X 	case WD_TIMER_EXPIRED:
X 		DEBUG( 4, "WD_TIMER_EXPIRED: %ld\n", jiffies);
X 	
X 		/*
-		 *  Wait until  retry_count * n matches negotiated threshold/
+		 *  Wait until retry_count * n matches negotiated threshold/
X 		 *  disconnect time (note 2 in IrLAP p. 82)
X 		 */
X 		DEBUG( 0, "retry_count = %d\n", self->retry_count);
@@ -1767,7 +1759,7 @@
X 			
X 			/* Always switch state before calling upper layers */
X 			irlap_next_state( self, LAP_NDM);
-			
+
X 			irlap_disconnect_indication( self, LAP_NO_RESPONSE);
X 		}
X 		break;
@@ -1808,7 +1800,7 @@
X 		break;
X 
X 	default:
-		DEBUG( 0, "irlap_state_nrm_s: Unknown event %d, (%s)\n", 
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
X 		       event, irlap_event[event]);
X 		ret = -1;
X 		break;
@@ -1829,3 +1821,42 @@
X 
X 	return -1;
X }
+
+static int irlap_state_reset_check( struct irlap_cb *self, IRLAP_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct irlap_info *info) 
+{
+	int ret = 0;
+
+	DEBUG( 0, __FUNCTION__ "(), event=%s\n", irlap_event[ event]); 
+
+	ASSERT( self != NULL, return -ENODEV;);
+	ASSERT( self->magic == LAP_MAGIC, return -EBADR;);
+	
+	switch( event) {
+	case RESET_RESPONSE:
+		irlap_send_ua_response_frame( self, &self->qos_rx);
+		irlap_initiate_connection_state( self);
+		irlap_start_wd_timer( self, WD_TIMEOUT);
+		irlap_flush_all_queues( self);
+		
+		irlap_next_state( self, LAP_NRM_S);
+		break;
+	case DISCONNECT_REQUEST:
+		irlap_wait_min_turn_around( self, &self->qos_tx);
+		/* irlap_send_rd_frame(self); */
+		irlap_start_wd_timer( self, WD_TIMEOUT);
+		break;
+	default:
+		DEBUG( 0, __FUNCTION__ "(), Unknown event %d, (%s)\n", 
+		       event, irlap_event[event]);
+		ret = -1;
+		break;
+	}
+
+	return ret;
+}
+
+
+
+
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlap_frame.c linux/net/irda/irlap_frame.c
--- v2.2.0-pre8/linux/net/irda/irlap_frame.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlap_frame.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Aug 19 10:27:26 1997
- * Modified at:   Mon Dec 14 14:24:05 1998
+ * Modified at:   Tue Jan 19 22:58:13 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, All Rights Resrved.
@@ -76,7 +76,7 @@
X }
X 
X /*
- * Function irlap_send_connect_snrm_cmd (void)
+ * Function irlap_send_snrm_cmd (void)
X  *
X  *    Transmits a connect SNRM command frame
X  */
@@ -564,7 +564,6 @@
X 	if ( self->recycle_rr_skb) {
X 		DEBUG( 4, __FUNCTION__ "(), recycling skb!\n");
X 		skb = self->recycle_rr_skb;
-		skb->stamp.tv_sec = 0;
X 		self->recycle_rr_skb = NULL;
X 	}
X #endif      
@@ -640,7 +639,7 @@
X 
X 		/*  
X 		 *  Set skb to NULL, so that the state machine will not 
-		 *  deallocate it.
+		 *  try to deallocate it.
X 		 */
X 		skb = NULL;  
X 	}
@@ -652,11 +651,6 @@
X 		irlap_do_event( self, RECV_RR_RSP, skb, info);
X }
X 
-/*
- * Function irlap_send_rr_frame ()
- *
- *    Build and transmit RR (Receive Ready) frame
- */
X void irlap_send_frmr_frame( struct irlap_cb *self, int command)
X {
X 	struct sk_buff *skb = NULL;
@@ -805,8 +799,6 @@
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
X 
-	IS_SKB( skb, return;);
-
X 	/* Initialize variables */
X 	tx_skb = NULL;
X 
@@ -888,8 +880,6 @@
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
X 
-	IS_SKB( skb,return;);
-
X 	/* Is this reliable or unreliable data? */
X 	if ( skb->data[1] == I_FRAME) {
X 
@@ -950,8 +940,6 @@
X 	ASSERT( self->magic == LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
X 
-	IS_SKB( skb, return;);
-
X 	/* Is this reliable or unreliable data? */
X 	if ( skb->data[1] == I_FRAME) {
X 		
@@ -1066,8 +1054,7 @@
X 
X 	while ( skb_queue_len( &self->tx_list) > 0) {
X 		
-		DEBUG( 0, "irlap_resend_rejected_frames: "
-		       "sending additional frames!\n");
+		DEBUG( 0, __FUNCTION__ "(), sending additional frames!\n");
X 		if (( skb_queue_len( &self->tx_list) > 0) && 
X 		    ( self->window > 0)) {
X 			skb = skb_dequeue( &self->tx_list); 
@@ -1141,8 +1128,7 @@
X 	
X 	/* Insert next to receive (Vr) */
X 	frame[1] |= (self->vr << 5);  /* insert nr */
-
-#if 0	
+#if 0
X 	{
X 		int vr, vs, pf;
X 		
@@ -1151,7 +1137,7 @@
X 		vs = (frame[1] >> 1) & 0x07;
X 		pf = (frame[1] >> 4) & 0x01;
X 		
-		DEBUG( 4, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
+		DEBUG( 0, __FUNCTION__ "(), vs=%d, vr=%d, p=%d, %ld\n", 
X 		       vs, vr, pf, jiffies);
X 	}
X #endif	
@@ -1351,7 +1337,7 @@
X 			self->stats.rx_packets++;
X 			break;
X 		case RNR:
-			DEBUG( 3, "*** RNR frame received! pf = %d ***\n", 
+			DEBUG( 4, "*** RNR frame received! pf = %d ***\n", 
X 			       info.pf >> 4);
X 			irlap_recv_rnr_frame( self, skb, &info);
X 			self->stats.rx_packets++;
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
--- v2.2.0-pre8/linux/net/irda/irlmp.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlmp.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 17 20:54:32 1997
- * Modified at:   Mon Dec 14 11:54:08 1998
+ * Modified at:   Sat Jan 16 22:13:20 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
@@ -373,8 +373,8 @@
X 	if ( userdata == NULL) {
X 		skb = dev_alloc_skb( 64);
X 		if (skb == NULL) {
-			DEBUG( 0, "irlmp_connect_request: "
-			       "Could not allocate an sk_buff of length %d\n",
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Could not allocate sk_buff of length %d\n",
X 			       64);
X 			return;
X 		}
@@ -596,7 +596,7 @@
X {
X 	struct lsap_cb *lsap;
X 
-	DEBUG( 4, "irlmp_disconnect_indication()\n");	
+	DEBUG( 4, __FUNCTION__ "()\n");	
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -625,10 +625,9 @@
X 
X 	/* FIXME: the reasons should be extracted somewhere else? */
X 	if ( userdata) {
-		DEBUG( 4, "irlmp_disconnect_indication: reason=%02x\n", 
-		       userdata->data[3]);
+		DEBUG( 4, __FUNCTION__ "(), reason=%02x\n", userdata->data[3]);
X 	}
-
+	
X 	/*
X 	 *  Inform service user
X 	 */
@@ -648,7 +647,7 @@
X {
X 	struct lap_cb *lap;
X 
-	DEBUG( 4, "irlmp_discovery_request()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( irlmp != NULL, return;);
X 
@@ -702,7 +701,6 @@
X 	printk( KERN_INFO "IrDA Discovered: %s\n", discovery->info);
X 	printk( KERN_INFO "    Services: ");
X 
-
X 	service = irlmp_hint_to_service( discovery->hint);
X 	if (service != NULL) {
X 		/*
@@ -746,22 +744,12 @@
X {
X 	DISCOVERY *discovery;
X 	
-	DEBUG( 4, "irlmp_discovery_confirm()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
X 
X 	/*
-	 *  If log is missing this means that IrLAP was unable to perform the
-	 *  discovery, so restart discovery again with just the half timeout
-	 *  of the normal one.
-	 */
-	if ( !log) {
-		irlmp_start_discovery_timer( irlmp, 150);
-		return;
-	}
-
-	/*
X 	 *  Now, check all discovered devices (if any)
X 	 */
X 	discovery = ( DISCOVERY *) hashbin_get_first( log);
@@ -798,8 +786,10 @@
X 	/*
X 	 *  Create a new discovery log if neccessary
X 	 */
-	if ( self->cachelog == NULL)
-		self->cachelog = hashbin_new( HB_LOCAL);
+	/* if ( self->cachelog == NULL) */
+/* 		self->cachelog = hashbin_new( HB_LOCAL); */
+	ASSERT( self->cachelog != NULL, return;);
+
X 	/*
X 	 *  Insert this discovery device into the discovery_log if its
X 	 *  not there already
@@ -932,7 +922,7 @@
X  */
X void irlmp_connectionless_data_request( struct sk_buff *skb)
X {
-	DEBUG( 0, __FUNCTION__ "()\n"); 
+	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented\n"); 
X }
X 
X /*
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlmp_event.c linux/net/irda/irlmp_event.c
--- v2.2.0-pre8/linux/net/irda/irlmp_event.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlmp_event.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Dec  9 01:48:48 1998
+ * Modified at:   Sat Jan 16 22:22:29 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
@@ -119,7 +119,7 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
X 
-	DEBUG( 4, "do_lsap_event: EVENT = %s, STATE = %s\n",
+	DEBUG( 4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
X 	       irlmp_event[ event], irlmp_state[ self->lsap_state]);
X 
X 	(*lsap_state[ self->lsap_state]) ( self, event, skb);
@@ -137,7 +137,7 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
X 	
-	DEBUG( 4, "do_lap_event: EVENT = %s, STATE = %s\n",
+	DEBUG( 4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
X 	       irlmp_event[event], 
X 	       irlmp_state[self->lap_state]);
X 
@@ -152,9 +152,7 @@
X 	
X 	irlmp_discovery_request( 8);
X 
-	/*
-	 *  Restart timer
-	 */
+	/* Restart timer */
X 	irlmp_start_discovery_timer( irlmp, 300);
X }
X 
@@ -185,7 +183,7 @@
X static void irlmp_state_standby( struct lap_cb *self, IRLMP_EVENT event, 
X 				 struct sk_buff *skb)
X {	
-	DEBUG( 4, "irlmp_state_standby()\n"); 
+	DEBUG( 4, __FUNCTION__ "()\n"); 
X 	ASSERT( self->irlap != NULL, return;);
X 	
X 	switch( event) {
@@ -241,7 +239,7 @@
X 	struct lsap_cb *lsap;
X 	struct lsap_cb *lsap_current;
X 	
-	DEBUG( 4, "irlmp_state_u_connect()\n"); 
+	DEBUG( 4, __FUNCTION__ "()\n"); 
X 
X 	switch( event) {
X 	case LM_LAP_CONNECT_CONFIRM:
@@ -250,14 +248,12 @@
X 
X 		lsap = ( struct lsap_cb *) hashbin_get_first( self->lsaps);
X 		while ( lsap != NULL) {
-			irlmp_do_lsap_event( lsap, 
-					     LM_LAP_CONNECT_CONFIRM,
-					     skb); 
+			irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, skb);
X 			lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
X 		}		
X 		break;
X 	case LM_LAP_DISCONNECT_INDICATION:
-		DEBUG( 0, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
+		DEBUG( 4, __FUNCTION__ "(), IRLAP_DISCONNECT_INDICATION\n");
X 	
X 		irlmp_next_lap_state( self, LAP_STANDBY);
X 
@@ -277,13 +273,15 @@
X 		}
X 		break;
X 	case LM_LAP_DISCONNECT_REQUEST:
-		DEBUG( 0, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
-		/* irlmp_next_lap_state( self, LAP_STANDBY); */
+		DEBUG( 4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
X 
+		irlmp_next_lap_state( self, LAP_STANDBY);
+
+		/* FIXME */
X /* 		irlap_disconnect_request( self->irlap); */
X 		break;
X 	default:
-		DEBUG( 4, "irlmp_state_u_connect: Unknown event\n");
+		DEBUG( 4, __FUNCTION__ "(), Unknown event\n");
X 		break;
X 	}	
X }
@@ -300,11 +298,11 @@
X 	struct lsap_cb *lsap;
X 	struct lsap_cb *lsap_current;
X 
-	DEBUG( 4, "irlmp_state_active()\n"); 
+	DEBUG( 4, __FUNCTION__ "()\n"); 
X 
X  	switch( event) {
X 	case LM_LAP_CONNECT_REQUEST:
-		DEBUG( 4, "irlmp_state_active(), LS_CONNECT_REQUEST\n");
+		DEBUG( 4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
X 
X 		/*
X 		 *  LAP connection allready active, just bounce back! Since we 
@@ -379,14 +377,14 @@
X {
X 	struct lsap_cb *lsap;
X 
-	DEBUG( 4, "irlmp_state_disconnected()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
X 
X 	switch( event) {
X 	case LM_CONNECT_REQUEST:
-		DEBUG( 4, "irlmp_state_disconnected: LM_CONNECT_REQUEST\n");
+		DEBUG( 4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
X 		irlmp_next_lsap_state( self, LSAP_SETUP_PEND);
X 
X 		irlmp_do_lap_event( self->lap, LM_LAP_CONNECT_REQUEST, NULL);
@@ -433,7 +431,7 @@
X 				 struct sk_buff *skb) 
X {
X 
-	DEBUG( 4, "irlmp_state_connect()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -464,7 +462,7 @@
X static void irlmp_state_connect_pend( struct lsap_cb *self, IRLMP_EVENT event,
X 				      struct sk_buff *skb) 
X {
-	DEBUG( 4, "irlmp_state_connect_pend()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -508,7 +506,7 @@
X {
X 	LM_REASON reason;
X 
- 	DEBUG( 4, "irlmp_state_dtr()\n");
+ 	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LSAP_MAGIC, return;);
@@ -584,7 +582,7 @@
X 
X 		break;
X 	default:
-		DEBUG( 4, "irlmp_state_dtr: Unknown event %d\n", event);
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
X 		break;	
X 	}	
X }
@@ -629,7 +627,7 @@
X 		irlmp_disconnect_indication( self, reason, skb);
X 		break;
X 	default:
-		DEBUG( 4, "irlmp_state_setup: Unknown event %d\n", event);
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
X 		break;	
X 	}
X }
@@ -664,23 +662,22 @@
X 		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
X 		break;
X 	case LM_WATCHDOG_TIMEOUT:
-		DEBUG( 0, "irlmp_state_setup_pend() WATCHDOG_TIMEOUT!\n");
+		DEBUG( 0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
X 
X 		/* FIXME: should we do a disconnect_indication? */
-		return;
X 		ASSERT( self->lap != NULL, return;);
X 		irlmp_do_lap_event( self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
X 		irlmp_next_lsap_state( self, LSAP_DISCONNECTED);
X 		break;
X 	default:
-		DEBUG( 4, "irlmp_state_setup_pend: Unknown event %d\n", event);
+		DEBUG( 4, __FUNCTION__ "(), Unknown event %d\n", event);
X 		break;	
X 	}
X }
X 
X void irlmp_next_lap_state( struct lap_cb *self, IRLMP_STATE state) 
X {
-	DEBUG( 4, "LMP LAP = %s\n", irlmp_state[state]);
+	DEBUG( 4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
X 	self->lap_state = state;
X }
X 
@@ -688,6 +685,6 @@
X {
X 	ASSERT( self != NULL, return;);
X 
-	DEBUG( 4, "LMP LSAP = %s\n", irlsap_state[state]);
+	DEBUG( 4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
X 	self->lsap_state = state;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlmp_frame.c linux/net/irda/irlmp_frame.c
--- v2.2.0-pre8/linux/net/irda/irlmp_frame.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irlmp_frame.c	Wed Jan 20 11:05:33 1999
@@ -1,15 +1,16 @@
X /*********************************************************************
X  *                
X  * Filename:      irlmp_frame.c
- * Version:       0.1
+ * Version:       0.8
X  * Description:   IrLMP frame implementation
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Aug 19 02:09:59 1997
- * Modified at:   Wed Dec  9 01:25:47 1998
+ * Modified at:   Sat Jan 16 22:14:04 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
- *     Copyright (c) 1997 Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>
+ *     All Rights Reserved.
X  *     
X  *     This program is free software; you can redistribute it and/or 
X  *     modify it under the terms of the GNU General Public License as 
@@ -28,19 +29,18 @@
X 
X #include <net/irda/irda.h>
X #include <net/irda/irlap.h>
+#include <net/irda/timer.h>
X #include <net/irda/irlmp.h>
X #include <net/irda/irlmp_frame.h>
X 
X static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap, 
-					__u8 slsap, int status);
+					__u8 slsap, int status, hashbin_t *);
X 
X inline void irlmp_send_data_pdu( struct lap_cb *self, __u8 dlsap, __u8 slsap,
X 				 int expedited, struct sk_buff *skb)
X {
X 	__u8 *frame;
X 
-	DEBUG( 4, __FUNCTION__ "()\n");
-
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
X 	ASSERT( skb != NULL, return;);
@@ -104,9 +104,6 @@
X 	__u8  slsap_sel;   /* Source (this) LSAP address */
X 	__u8  dlsap_sel;   /* Destination LSAP address */
X 	struct lsap_cb *lsap;
-
-	
-	DEBUG( 4, "irlmp_link_data_indication()\n");
X 	
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
@@ -119,12 +116,9 @@
X 	 *  The next statements may be confusing, but we do this so that 
X 	 *  destination LSAP of received frame is source LSAP in our view
X 	 */
-	slsap_sel = fp[0] & ~CONTROL_BIT; 
+	slsap_sel = fp[0] & LSAP_MASK; 
X 	dlsap_sel = fp[1];
X 	
-	DEBUG( 4, "slsap_sel = %02x, dlsap_sel = %02x\n", slsap_sel, 
-	       dlsap_sel);
-	
X 	/*
X 	 *  Check if this is an incoming connection, since we must deal with
X 	 *  it in a different way than other established connections.
@@ -132,11 +126,19 @@
X 	if (( fp[0] & CONTROL_BIT) && ( fp[2] == CONNECT_CMD)) {
X 		DEBUG( 4,"Incoming connection, source LSAP=%d, dest LSAP=%d\n",
X 		       slsap_sel, dlsap_sel);
+		
+		/* Try to find LSAP among the unconnected LSAPs */
X 		lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 
-					CONNECT_CMD);
+					CONNECT_CMD, irlmp->unconnected_lsaps);
+		
+		/* Maybe LSAP was already connected, so try one more time */
+		if ( !lsap)
+		     lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 0,
+					     self->lsaps);
X 	} else
-		lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 0);
-
+		lsap = irlmp_find_lsap( self, dlsap_sel, slsap_sel, 0, 
+					self->lsaps);
+	
X 	if ( lsap == NULL) {
X 		DEBUG( 0, "IrLMP, Sorry, no LSAP for received frame!\n");
X 		DEBUG( 0, __FUNCTION__ 
@@ -146,8 +148,7 @@
X 			DEBUG( 0, __FUNCTION__ 
X 			       "(), received control frame %02x\n", fp[2]);
X 		} else {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), received data frame\n");
+			DEBUG( 0, __FUNCTION__ "(), received data frame\n");
X 		}
X 		dev_kfree_skb( skb);
X 		return;
@@ -157,10 +158,8 @@
X 	 *  Check if we received a control frame? 
X 	 */
X 	if ( fp[0] & CONTROL_BIT) {
-		/* DEBUG( 0, "irlmp_input: Got control frame\n"); */
X 		switch( fp[2]) {
X 		case CONNECT_CMD:
-			DEBUG( 4, "irlmp_input: CONNECT_CMD\n");
X 			lsap->lap = self;
X 			irlmp_do_lsap_event( lsap, LM_CONNECT_INDICATION, skb);
X 			break;
@@ -168,7 +167,7 @@
X 			irlmp_do_lsap_event( lsap, LM_CONNECT_CONFIRM, skb);
X 			break;
X 		case DISCONNECT:
-			DEBUG( 4, "irlmp_input: Disconnect indication!\n");
+			DEBUG( 4, __FUNCTION__ "(), Disconnect indication!\n");
X 			irlmp_do_lsap_event( lsap, LM_DISCONNECT_INDICATION, 
X 					     skb);
X 			break;
@@ -179,8 +178,8 @@
X 			DEBUG( 0, "Access mode cnf not implemented!\n");
X 			break;
X 		default:
-			DEBUG( 0, "irlmp_input: Unknown control frame %02x\n",
-			       fp[2]);
+			DEBUG( 0, __FUNCTION__ 
+			       "(), Unknown control frame %02x\n", fp[2]);
X 			break;
X 		}
X 	} else if ( reliable == LAP_RELIABLE) {
@@ -202,7 +201,7 @@
X 				       LAP_REASON reason, 
X 				       struct sk_buff *userdata)
X {
-	DEBUG( 4, "irlmp_link_disconnect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( lap != NULL, return;);
X 	ASSERT( lap->magic == LMP_LAP_MAGIC, return;);
@@ -226,7 +225,7 @@
X void irlmp_link_connect_indication( struct lap_cb *self, struct qos_info *qos,
X 				    struct sk_buff *skb) 
X {
-	DEBUG( 4, "irlmp_link_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	/* Copy QoS settings for this session */
X 	self->qos = qos;
@@ -265,24 +264,53 @@
X  */
X void irlmp_link_discovery_confirm( struct lap_cb *self, hashbin_t *log)
X {
-	DEBUG( 4, "irlmp_link_connect_confirm()\n");
+/* 	DISCOVERY *discovery; */
+	hashbin_t *old_log;
+
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == LMP_LAP_MAGIC, return;);
X 
-	if ( self->cachelog)
-		hashbin_delete( self->cachelog, (FREE_FUNC) kfree);
+	ASSERT( self->cachelog != NULL, return;);
X 
+	/*
+	 *  If log is missing this means that IrLAP was unable to perform the
+	 *  discovery, so restart discovery again with just the half timeout
+	 *  of the normal one.
+	 */
+	if ( !log) {
+		irlmp_start_discovery_timer( irlmp, 150);
+		return;
+	}
+
+#if 0
+	discovery = hashbin_remove_first( log);
+	while ( discovery) {
+		DEBUG( 0, __FUNCTION__ "(), found %s\n", discovery->info);
+
+		/* Remove any old discovery of this device */
+		hashbin_remove( self->cachelog, discovery->daddr, NULL);
+
+		/* Insert the new one */
+		hashbin_insert( self->cachelog, (QUEUE *) discovery, 
+				discovery->daddr, NULL);
+
+		discovery = hashbin_remove_first( log);
+	}
+#endif
+	old_log = self->cachelog;
X 	self->cachelog = log;
+	hashbin_delete( old_log, (FREE_FUNC) kfree);
X       
X 	irlmp_do_lap_event( self, LM_LAP_DISCOVERY_CONFIRM, NULL);
+
+	DEBUG( 4, __FUNCTION__ "() -->\n");
X }
X 
X #ifdef CONFIG_IRDA_CACHE_LAST_LSAP
-void irlmp_update_cache( struct lsap_cb *self)
+__inline__ void irlmp_update_cache( struct lsap_cb *self)
X {
-	DEBUG( 4, __FUNCTION__ "()\n");
-
X 	/* Update cache entry */
X 	irlmp->cache.dlsap_sel = self->dlsap_sel;
X 	irlmp->cache.slsap_sel = self->slsap_sel;
@@ -292,28 +320,20 @@
X #endif
X 
X /*
- * Function irlmp_find_handle (dlsap, slsap)
+ * Function irlmp_find_handle (self, dlsap_sel, slsap_sel, status, queue)
X  *
X  *    Find handle assosiated with destination and source LSAP
X  *
X  */
X static struct lsap_cb *irlmp_find_lsap( struct lap_cb *self, __u8 dlsap_sel,
-					__u8 slsap_sel, int status) 
+					__u8 slsap_sel, int status,
+					hashbin_t *queue) 
X {
X 	struct lsap_cb *lsap;
-	hashbin_t *queue;
-	
-	DEBUG( 4, "irlmp_find_lsap: dlsap_sel=0x%02x, slsap_sel=0x%02x\n", 
-	       dlsap_sel, slsap_sel);
X 	
X 	ASSERT( self != NULL, return NULL;);
X 	ASSERT( self->magic == LMP_LAP_MAGIC, return NULL;);
X 
-	if ( status)
-		queue = irlmp->unconnected_lsaps;
-	else
-		queue = self->lsaps;
-
X 	/* 
X 	 *  Optimize for the common case. We assume that the last frame
X 	 *  received is in the same connection as the last one, so check in
@@ -333,14 +353,11 @@
X 	lsap = ( struct lsap_cb *) hashbin_get_first( queue);
X 	while ( lsap != NULL) {
X 		/* 
-		 *  Check if source LSAP (in our view!) match, and if
-		 *  dest LSAP is equal to LM_ANY, which is the case
-		 *  for incomming connections 
+		 *  If this is an incomming connection, then the destination 
+		 *  LSAP selector may have been specified as LM_ANY so that 
+		 *  any client can connect. In that case we only need to check
+		 *  if the source LSAP (in our view!) match!
X 		 */
-		DEBUG( 4, "irlmp_find_lsap: "
-		       "LSAP: lsap->dlsap=%d, lsap->slsap=%d\n", 
-		       lsap->dlsap_sel, lsap->slsap_sel);
-		
X 		if (( status == CONNECT_CMD) && 
X 		    ( lsap->slsap_sel == slsap_sel) &&      
X 		    ( lsap->dlsap_sel == LSAP_ANY)) 
@@ -371,3 +388,5 @@
X 	/* Sorry not found! */
X 	return NULL;
X }
+
+
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/Config.in linux/net/irda/irlpt/Config.in
--- v2.2.0-pre8/linux/net/irda/irlpt/Config.in	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/Config.in	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,7 @@
+
+dep_tristate 'IrLPT protocol' CONFIG_IRLPT $CONFIG_IRDA
+
+if [ "$CONFIG_IRLPT" != "n" ]; then
+  dep_tristate '   IrLPT client support' CONFIG_IRLPT_CLIENT $CONFIG_IRLPT
+  dep_tristate '   IrLPT server support' CONFIG_IRLPT_SERVER $CONFIG_IRLPT
+fi
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/Makefile linux/net/irda/irlpt/Makefile
--- v2.2.0-pre8/linux/net/irda/irlpt/Makefile	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/Makefile	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,48 @@
+#
+# Makefile for the Linux IrDA IrLPT protocol layer.
+#
+# 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...
+
+MOD_LIST_NAME := IRDA_MODULES
+O_TARGET := irlpt.o
+O_OBJS	 := irlpt_common.o
+M_OBJS   := $(O_TARGET)
+MI_OBJS  :=
+
+OX_OBJS  += 
+
+ifeq ($(CONFIG_IRLPT_CLIENT),y)
+O_OBJS += irlpt_cli.o irlpt_cli_fsm.o
+else
+  ifeq ($(CONFIG_IRLPT_CLIENT),m)
+  M_OBJS += irlpt_client.o
+  endif
+endif
+
+ifeq ($(CONFIG_IRLPT_SERVER),y)
+O_OBJS += irlpt_srvr.o irlpt_srvr_fsm.o
+else
+  ifeq ($(CONFIG_IRLPT_SERVER),m)
+  M_OBJS += irlpt_server.o
+  endif
+endif
+
+# Special rule to build the composite modules
+ifeq ($(CONFIG_IRLPT_CLIENT),m)
+irlpt_client.o: irlpt_cli.o irlpt_cli_fsm.o
+	$(LD) $(LD_RFLAG) -r -o $@ irlpt_cli.o irlpt_cli_fsm.o
+endif
+ifeq ($(CONFIG_IRLPT_SERVER),m)
+irlpt_server.o: irlpt_srvr.o irlpt_srvr_fsm.o
+	$(LD) $(LD_RFLAG) -r -o $@ irlpt_srvr.o irlpt_srvr_fsm.o
+endif
+
+include $(TOPDIR)/Rules.make
+
+tar:
+	tar -cvf /dev/f1 .
+
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/irlpt_cli.c linux/net/irda/irlpt/irlpt_cli.c
--- v2.2.0-pre8/linux/net/irda/irlpt/irlpt_cli.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/irlpt_cli.c	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,599 @@
+/*********************************************************************
+ *
+ * Filename:      irlpt.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Thomas Davis, <rat...@radiks.net>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Sun Mar  8 23:44:19 1998
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * Sources:	  irlan.c
+ *
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>,
+ * Copyright (c) 1998, Dag Brattli, <da...@cs.uit.no>
+ *     All Rights Reserved.
+ *
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <net/irda/irlap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irlpt_common.h>
+#include <net/irda/irlpt_cli.h>
+#include <net/irda/irlpt_cli_fsm.h>
+#include <net/irda/timer.h>
+#include <net/irda/irda.h>
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+
+int  irlpt_client_init(void);
+static void irlpt_client_cleanup(void);
+static void irlpt_client_close(struct irlpt_cb *self);
+
+static void irlpt_client_discovery_indication( DISCOVERY *);
+
+static void irlpt_client_connect_confirm( void *instance, void *sap, 
+					  struct qos_info *qos, 
+					  int max_seg_size, 
+					  struct sk_buff *skb);
+static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+						LM_REASON reason,
+						struct sk_buff *userdata);
+
+#if 0
+static char *rcsid = "$Id: irlpt_client.c,v 1.10 1998/11/10 22:50:57 dagb Exp $";
+#endif
+static char *version = "IrLPT, $Revision: 1.10 $/$Date: 1998/11/10 22:50:57 $ (Thomas Davis)";
+
+struct file_operations client_fops = {
+	irlpt_seek,    /* seek */
+	NULL,          /* read_irlpt (server) */
+	irlpt_write,   /* write */
+	NULL,	       /* readdir */
+	NULL,          /* poll */
+	NULL,	       /* ioctl */
+	NULL,	       /* mmap */
+	irlpt_open,    /* open */
+	NULL,          /* flush */
+	irlpt_close,   /* release */
+	NULL,          /* fsync */
+	NULL,          /* fasync */
+	NULL,          /* check_media_change */
+	NULL,          /* revalidate */
+	NULL,          /* lock */
+};
+
+int irlpt_client_debug = 4;
+
+extern char *irlptstate[];
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Function client_proc_read (buf, start, offset, len, unused)
+ *
+ */
+static int irlpt_client_proc_read( char *buf, char **start, off_t offset, 
+				   int len, int unused)
+{
+	struct irlpt_cb *self;
+	int index;
+
+	len = sprintf(buf, "%s\n\n", version);
+
+	self = (struct irlpt_cb *) hashbin_get_first( irlpt_clients);
+	while( self) {
+	        ASSERT( self != NULL, return len;);
+          	ASSERT( self->magic == IRLPT_MAGIC, return len;);
+
+		len += sprintf(buf+len, "ifname: %s\n", self->ifname);
+		len += sprintf(buf+len, "minor: %d\n", self->ir_dev.minor);
+
+		switch ( self->servicetype) {
+		case IRLPT_UNKNOWN:
+			index = 0;
+			break;
+		case IRLPT_THREE_WIRE_RAW:
+			index = 1;
+			break;
+		case IRLPT_THREE_WIRE:
+			index = 2;
+			break;
+		case IRLPT_NINE_WIRE:
+			index = 3;
+			break;
+		case IRLPT_CENTRONICS:
+			index = 4;
+			break;
+		case IRLPT_SERVER_MODE:
+			index = 5;
+			break;
+		default:
+			index = 0;
+			break;
+		}
+		
+		len += sprintf(buf+len, "service_type: %s\n", 
+			       irlpt_service_type[index]);
+		len += sprintf(buf+len, "port_type: %s\n", 
+			       irlpt_port_type[ self->porttype]);
+		len += sprintf(buf+len, "daddr: 0x%08x\n", self->daddr);
+		len += sprintf(buf+len, "fsm_state: %s\n", 
+			       irlpt_client_fsm_state[self->state]);
+		len += sprintf(buf+len, "retries: %d\n", self->open_retries);
+		len += sprintf(buf+len, "dlsap: %d\n", self->dlsap_sel);
+
+		len += sprintf(buf+len, "count: %d\n", self->count);
+		len += sprintf(buf+len, "rx_queue: %d\n", 
+			       skb_queue_len(&self->rx_queue));
+		len += sprintf(buf+len, "\n\n");
+		
+		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
+	}
+	
+	return len;
+}
+
+struct proc_dir_entry proc_irlpt_client = {
+	0, 12, "irlpt_client",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irlpt_client_proc_read /* get_info */,
+};
+
+extern struct proc_dir_entry proc_irda;
+
+#endif /* CONFIG_PROC_FS */
+
+/*
+ * Function irlpt_init (dev)
+ *
+ *   Initializes the irlpt control structure
+ *
+ */
+__initfunc(int irlpt_client_init(void))
+{
+	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
+
+	printk( KERN_INFO "%s\n", version);
+
+	irlpt_clients = hashbin_new( HB_LOCAL); 
+	if ( irlpt_clients == NULL) {
+		printk( KERN_WARNING "IrLPT: Can't allocate hashbin!\n");
+		return -ENOMEM;
+	}
+
+	irlmp_register_layer( S_PRINTER, CLIENT, TRUE, 
+			      irlpt_client_discovery_indication);
+
+#ifdef CONFIG_PROC_FS
+	proc_register( &proc_irda, &proc_irlpt_client);
+#endif /* CONFIG_PROC_FS */
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+
+#ifdef MODULE
+/*
+ * Function irlpt_cleanup (void)
+ *
+ *
+ *
+ */
+static void irlpt_client_cleanup(void)
+{
+	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
+
+	irlmp_unregister_layer( S_PRINTER, CLIENT);
+
+	/*
+	 *  Delete hashbin and close all irlan client instances in it
+	 */
+	hashbin_delete( irlpt_clients, (FREE_FUNC) irlpt_client_close);
+
+#ifdef CONFIG_PROC_FS
+	proc_unregister( &proc_irda, proc_irlpt_client.low_ino);
+#endif
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+#endif /* MODULE */
+
+
+/*
+ * Function irlpt_open (void)
+ *
+ *    This is the entry-point which starts all the fun! Currently this
+ *
+ */
+static struct irlpt_cb *irlpt_client_open( __u32 daddr)
+{
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_client_debug, "--> "__FUNCTION__ "\n");
+
+	self = kmalloc(sizeof(struct irlpt_cb), GFP_ATOMIC);
+	if (self == NULL)
+		return NULL;
+
+	memset(self, 0, sizeof(struct irlpt_cb));
+
+	ASSERT( self != NULL, return NULL;);
+
+ 	sprintf(self->ifname, "irlpt%d", hashbin_get_size(irlpt_clients));
+	self->ir_dev.minor = MISC_DYNAMIC_MINOR;
+	self->ir_dev.name = self->ifname;
+	self->ir_dev.fops = &client_fops;
+
+	misc_register(&self->ir_dev);
+
+	self->magic = IRLPT_MAGIC;
+	self->in_use = TRUE;
+	self->servicetype = IRLPT_THREE_WIRE_RAW;
+	self->porttype = IRLPT_SERIAL;
+
+	skb_queue_head_init(&self->rx_queue);
+
+	irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+
+	hashbin_insert( irlpt_clients, (QUEUE *) self, daddr, NULL);
+
+	/*	MOD_INC_USE_COUNT; */
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+
+	return self;
+}
+
+/*
+ * Function irlpt_client_close (self)
+ *
+ *    This function closes and marks the IrLPT instance as not in use.
+ */
+static void irlpt_client_close( struct irlpt_cb *self)
+{
+	struct sk_buff *skb;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 11'
echo 'File patch-2.2.0-pre9 is continued in part 12'
echo 12 > _shar_seq_.tmp
#!/bin/sh
# this is part 12 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 12; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
+
+	while (( skb = skb_dequeue(&self->rx_queue)) != NULL) {
+		DEBUG(3, "irlpt_client_close: freeing SKB\n");
+                dev_kfree_skb( skb);
+	}
+
+	misc_deregister(&self->ir_dev);
+
+	self->magic = ~IRLPT_MAGIC;
+
+	kfree( self);
+
+	/* MOD_DEC_USE_COUNT; */
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_discovery_indication (daddr)
+ *
+ *    Remote device discovered, try query the remote IAS to see which
+ *    device it is, and which services it has.
+ *
+ */
+static void irlpt_client_discovery_indication( DISCOVERY *discovery)
+{
+	struct irlpt_info info;
+	struct irlpt_cb *self;
+	__u32 daddr;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+	ASSERT( irlpt_clients != NULL, return;);
+	ASSERT( discovery != NULL, return;);
+
+	daddr = discovery->daddr;
+
+	/*
+	 *  Check if an instance is already dealing with this device
+	 *  (daddr)
+	 */
+	self = (struct irlpt_cb *) hashbin_find( irlpt_clients, daddr, NULL);
+      	if ( self != NULL) {
+		ASSERT( self->magic == IRLPT_MAGIC, return;);
+		if ( self->state == IRLPT_CLIENT_IDLE) {
+			irlpt_client_do_event( self, 
+					       IRLPT_DISCOVERY_INDICATION, 
+					       NULL, &info);
+		}
+		return;
+	}
+    
+
+	/*
+	 * We have no instance for daddr, so time to start a new instance.
+	 * First we must find a free entry in master array
+	 */
+	if (( self = irlpt_client_open( daddr)) == NULL) {
+		DEBUG(irlpt_client_debug, __FUNCTION__ 
+		      ":irlpt_client_open failed!\n");
+	}
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRLPT_MAGIC, return;);
+
+	self->daddr = info.daddr = daddr;
+	
+	if (self->state == IRLPT_CLIENT_IDLE) {
+		irlpt_client_do_event( self, IRLPT_DISCOVERY_INDICATION, 
+				       NULL, &info);
+	}
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_disconnect_indication (handle)
+ *
+ */
+static void irlpt_client_disconnect_indication( void *instance, void *sap, 
+						LM_REASON reason,
+						struct sk_buff *skb)
+{
+	struct irlpt_info info;
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+ self = ( struct irlpt_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	info.daddr = self->daddr;
+
+        DEBUG( irlpt_client_debug, __FUNCTION__ 
+	       ": reason=%d (%s), peersap=%d\n",
+	       reason, irlpt_reasons[reason], self->dlsap_sel);
+
+	self->connected = IRLPT_DISCONNECTED;
+	self->eof = reason;
+
+	wake_up_interruptible( &self->write_wait);
+
+	irlpt_client_do_event( self, LMP_DISCONNECT, NULL, NULL);
+
+	if (skb) {
+		dev_kfree_skb( skb);
+	}
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_connect_confirm (handle, qos, skb)
+ *
+ *    LSAP connection confirmed!
+ */
+static void irlpt_client_connect_confirm( void *instance, void *sap, 
+					  struct qos_info *qos, 
+					  int max_sdu_size,
+					  struct sk_buff *skb)
+{
+	struct irlpt_info info;
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+ self = ( struct irlpt_cb *) instance;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	info.daddr = self->daddr;
+
+	/*
+	 *  Check if we have got some QoS parameters back! This should be the
+	 *  negotiated QoS for the link.
+	 */
+	if ( qos) {
+		DEBUG( irlpt_client_debug, __FUNCTION__ ": Frame Size: %d\n",
+		       qos->data_size.value);
+	}
+
+	self->irlap_data_size = (qos->data_size.value - IRLPT_MAX_HEADER);
+	self->connected = TRUE;
+	
+	irlpt_client_do_event( self, LMP_CONNECT, NULL, NULL);
+
+	if (skb) {
+		dev_kfree_skb( skb);
+	}
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function client_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the data channel
+ *
+ */
+static void irlpt_client_data_indication( void *instance, void *sap, 
+					  struct sk_buff *skb) 
+{
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+	ASSERT( skb != NULL, return;);
+	DEBUG( irlpt_client_debug, __FUNCTION__ ": len=%d\n", (int) skb->len);
+
+	self = ( struct irlpt_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+#if 1
+	{
+		int i;
+
+		for(i=0;i<skb->len;i++)
+			if (skb->data[i] > 31 && skb->data[i] < 128) {
+				printk("%c", skb->data[i]);
+			} else {
+				if (skb->data[i] == 0x0d) {
+					printk("\n");
+				} else {
+					printk(".");
+				}
+			}
+
+		printk("\n");
+	}
+#endif
+	
+	skb_queue_tail(&self->rx_queue, skb);
+        wake_up_interruptible(&self->read_wait);
+
+/* 	if (skb) { */
+/* 		dev_kfree_skb( skb); */
+/* 	} */
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_get_value_confirm (obj_id, type, value_int, value_char, priv)
+ *
+ *    Fixed to match changes in iriap.h, DB.
+ *
+ */
+
+void irlpt_client_get_value_confirm(__u16 obj_id, struct ias_value *value, 
+				    void *priv)
+{
+	struct irlpt_info info;
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+	ASSERT( priv != NULL, return;);
+
+	self = (struct irlpt_cb *) priv;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	/* can't stop here..  if we get a bad obj, must tell the state
+	   machine that!
+	ASSERT( type == IAS_INTEGER, return;);
+	*/
+
+	if ( value->type == IAS_INTEGER && value->t.integer != -1) {
+	        info.dlsap_sel = value->t.integer;
+		self->dlsap_sel = value->t.integer;
+
+		DEBUG( irlpt_client_debug, __FUNCTION__ 
+		       ": obj_id = %d, value = %d\n", 
+		       obj_id, value->t.integer);
+
+		irlpt_client_do_event( self, IAS_PROVIDER_AVAIL, 
+				       NULL, &info);
+	} else
+		irlpt_client_do_event( self, IAS_PROVIDER_NOT_AVAIL, 
+				       NULL, &info);
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+void irlpt_client_connect_request( struct irlpt_cb *self) 
+{
+	struct notify_t lpt_notify;
+
+	DEBUG( irlpt_client_debug, "--> " __FUNCTION__ "\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	lpt_notify.connect_confirm = irlpt_client_connect_confirm;
+	lpt_notify.disconnect_indication = irlpt_client_disconnect_indication;
+	lpt_notify.data_indication = irlpt_client_data_indication;
+	lpt_notify.instance = self;
+
+	self->lsap = irlmp_open_lsap( LSAP_ANY, &lpt_notify);
+	DEBUG( irlpt_client_debug, __FUNCTION__ ": Dest LSAP sel= %d\n", 
+	       self->dlsap_sel);
+	
+	if (self->servicetype == IRLPT_THREE_WIRE_RAW) {
+	        DEBUG( irlpt_client_debug, __FUNCTION__ 
+		       ": issue THREE_WIRE_RAW connect\n");
+		irlmp_connect_request( self->lsap, self->dlsap_sel, 
+				       self->daddr, NULL, NULL);
+	}
+
+	DEBUG( irlpt_client_debug, __FUNCTION__ " -->\n");
+}
+
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Thomas Davis <rat...@radiks.net>");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize the IrLPT client module, this function is called by the
+ *    modprobe(1) program.
+ */
+int init_module(void)
+{
+
+        DEBUG( irlpt_client_debug, "--> irlpt client: init_module\n");
+
+        irlpt_client_init();
+
+        DEBUG( irlpt_client_debug, "irlpt client: init_module -->\n");
+
+        return 0;
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Remove the IrLPT server module, this function is called by the rmmod(1)
+ *    program
+ */
+void cleanup_module(void)
+{
+        DEBUG( irlpt_client_debug, "--> irlpt client: cleanup_module\n");
+        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+
+        /* Free some memory */
+        irlpt_client_cleanup();
+
+        DEBUG( irlpt_client_debug, "irlpt client: cleanup_module -->\n");
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/irlpt_cli_fsm.c linux/net/irda/irlpt/irlpt_cli_fsm.c
--- v2.2.0-pre8/linux/net/irda/irlpt/irlpt_cli_fsm.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/irlpt_cli_fsm.c	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,374 @@
+/*********************************************************************
+ *                
+ * Filename:      irlpt_cli_fsm.c
+ * Version:       0.1
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Dag Brattli <da...@cs.uit.no>
+ * Created at:    Tue Jan 12 11:06:00 1999
+ * Modified at:   Tue Jan 12 11:14:22 1999
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * 
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>
+ *     Copyright (c) 1998, Dag Brattli, <da...@cs.uit.no>
+ *     All Rights Reserved.
+ *      
+ *     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.
+ *  
+ *     I, Thomas Davis, provide no warranty for any of this software. This 
+ *     material is provided "AS-IS" and at no charge.
+ *     
+ ********************************************************************/
+
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlpt_common.h>
+#include <net/irda/irlpt_cli.h>
+#include <net/irda/irlpt_cli_fsm.h>
+#include <net/irda/irda.h>
+
+#if 0
+static char *rcsid = "$Id: irlpt_client_fsm.c,v 1.3 1998/10/05 05:46:44 ratbert Exp $";
+#endif
+
+static int irlpt_client_state_idle  ( struct irlpt_cb *self, IRLPT_EVENT event,
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+static int irlpt_client_state_query ( struct irlpt_cb *self, IRLPT_EVENT event,
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+static int irlpt_client_state_ready  ( struct irlpt_cb *self, 
+				       IRLPT_EVENT event, 
+				       struct sk_buff *skb, 
+				       struct irlpt_info *info);
+static int irlpt_client_state_waiti ( struct irlpt_cb *self, IRLPT_EVENT event,
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+static int irlpt_client_state_waitr ( struct irlpt_cb *self, IRLPT_EVENT event,
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+static int irlpt_client_state_conn  ( struct irlpt_cb *self, IRLPT_EVENT event,
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+
+int irlpt_client_fsm_debug = 3;
+
+int (*irlpt_client_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
+				    struct sk_buff *skb, 
+				    struct irlpt_info *info) = 
+{ 
+	irlpt_client_state_idle,
+	irlpt_client_state_query,
+	irlpt_client_state_ready,
+	irlpt_client_state_waiti,
+	irlpt_client_state_waitr,
+	irlpt_client_state_conn,
+};
+
+void irlpt_client_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
+				   struct sk_buff *skb, 
+				   struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ "\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
+	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
+
+	(*irlpt_client_state[ self->state]) ( self, event, skb, info);
+
+	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+}
+
+void irlpt_client_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
+	       irlpt_client_fsm_state[state]);
+
+	self->state = state;
+
+	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function client_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlpt_client_state_idle( struct irlpt_cb *self, IRLPT_EVENT event, 
+				    struct sk_buff *skb, 
+				    struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case IRLPT_DISCOVERY_INDICATION:
+		/* Get some values from peer IAS */
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": IRLPT_DISCOVERY_INDICATION, sending getvaluebyclass command..\n");
+		iriap_getvaluebyclass_request( info->daddr, 
+					"IrLPT", "IrDA:IrLMP:LsapSel",
+					irlpt_client_get_value_confirm,
+					(void *) self);
+		irlpt_client_next_state( self, IRLPT_CLIENT_QUERY);
+		break;
+
+	default:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d (%s)\n",
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if (skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function client_state_query
+ *
+ *    QUERY, We have queryed the remote IAS and is ready to connect
+ *    to provider, just waiting for the confirm.
+ *
+ */
+static int irlpt_client_state_query( struct irlpt_cb *self, IRLPT_EVENT event, 
+				     struct sk_buff *skb, 
+				     struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case IAS_PROVIDER_AVAIL:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": IAS_PROVIDER_AVAIL\n");
+		self->open_retries = 0;
+		irlpt_client_next_state( self, IRLPT_CLIENT_READY);
+		irlpt_client_do_event( self, IRLPT_CONNECT_REQUEST, NULL, NULL);
+		break;
+
+	case IAS_PROVIDER_NOT_AVAIL:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": IAS_PROVIDER_NOT_AVAIL\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		break;
+
+	default:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": Unknown event %d (%s)\n",
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if (skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function client_state_info 
+ *
+ *    INFO, We have issued a GetInfo command and is awaiting a reply.
+ */
+static int irlpt_client_state_ready( struct irlpt_cb *self, IRLPT_EVENT event,
+				     struct sk_buff *skb, 
+				     struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case IRLPT_CONNECT_REQUEST:
+	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": IRLPT_CONNECT_REQUEST\n");
+		irlpt_client_connect_request(self);
+		irlpt_client_next_state( self, IRLPT_CLIENT_WAITI);
+		break;
+	case LMP_DISCONNECT:
+	case LAP_DISCONNECT:
+	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": LMP_DISCONNECT or LAP_DISCONNECT\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		break;
+	default:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d (%s)\n", 
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if ( skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+
+/*
+ * Function client_state_waiti 
+ *
+ *
+ */
+static int irlpt_client_state_waiti( struct irlpt_cb *self, IRLPT_EVENT event, 
+				     struct sk_buff *skb, 
+				     struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case LMP_CONNECT:
+	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
+	        irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
+	        break;
+	case LAP_DISCONNECT:
+	case LMP_DISCONNECT:
+	        DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
+	        irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+	        break;
+
+	default:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d (%s)\n", 
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if ( skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function client_state_waitr 
+ *
+ *
+ */
+static int irlpt_client_state_waitr( struct irlpt_cb *self, IRLPT_EVENT event,
+				     struct sk_buff *skb, 
+				     struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case LMP_CONNECT:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_CONNECT\n");
+		irlpt_client_next_state(self, IRLPT_CLIENT_CONN);
+		break;
+
+	case LMP_DISCONNECT:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LMP_DISCONNECT\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		break;
+
+	case LAP_DISCONNECT:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ ": LAP_DISCONNECT\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		break;
+
+	default:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d, (%s)\n",
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if ( skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function client_state_conn (event, skb, info)
+ *
+ *    CONN, We have connected to a provider but has not issued any
+ *    commands yet.
+ *
+ */
+static int irlpt_client_state_conn( struct irlpt_cb *self, IRLPT_EVENT event, 
+				    struct sk_buff *skb, 
+				    struct irlpt_info *info) 
+{
+	DEBUG( irlpt_client_fsm_debug,"--> "  __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case CLIENT_DATA_INDICATION:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": CLIENT_DATA_INDICATION\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_CONN);
+		break;
+
+	case LMP_DISCONNECT:
+	case LAP_DISCONNECT:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
+		irlpt_client_next_state( self, IRLPT_CLIENT_IDLE);
+		break;
+
+	default:
+		DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d (%s)\n",
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if ( skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_client_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+void irlpt_client_print_event( IRLPT_EVENT event) 
+{
+	DEBUG( irlpt_client_fsm_debug, __FUNCTION__ 
+	       ": IRLPT_EVENT = %s\n", irlpt_fsm_event[event]);
+}
+
+
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
--- v2.2.0-pre8/linux/net/irda/irlpt/irlpt_common.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/irlpt_common.c	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,512 @@
+/*********************************************************************
+ *
+ * Filename:      irlpt_common.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Thomas Davis, <rat...@radiks.net>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Sun Mar  8 23:44:19 1998
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * Sources: irlpt.c
+ *
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>,
+ *     Copyright (c) 1998, Dag Brattli,  <da...@cs.uit.no>
+ *     All Rights Reserved.
+ *
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/config.h>
+#include <linux/module.h> 
+
+#include <asm/segment.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irttp.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlpt_common.h>
+/* #include "irlpt_client.h" */
+/* #include "irlpt_server.h" */
+
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/fs.h>
+
+char *irlpt_service_type[] = {
+	"IRLPT_UNKNOWN",
+	"IRLPT_THREE_WIRE_RAW",
+	"IRLPT_THREE_WIRE",
+	"IRLPT_NINE_WIRE",
+	"IRLPT_CENTRONICS",
+	"IRLPT_SERVER_MODE",
+};
+
+char *irlpt_port_type[] = {
+	"IRLPT_UNKNOWN",
+	"IRLPT_SERIAL",
+	"IRLPT_PARALLEL",
+};
+
+char *irlpt_connected[] = {
+	"IRLPT_DISCONNECTED",
+	"IRLPT_WAITING",
+	"IRLPT_CONNECTED",
+	"IRLPT_FLUSHED",
+};
+
+char *irlpt_reasons[] = {
+	"SERVICE_CLOSE",     /* Service has closed the connection */
+	"DISC_INDICATION",   /* Received a disconnect request from peer entity*/
+	"NO_RESPONSE",       /* To many retransmits without response */
+	"DEADLOCK_DETECTED", /* To many retransmits _with_ response */
+	"FOUND_NONE",        /* No devices were discovered */
+	"MEDIA_BUSY",
+
+};
+
+char *irlpt_client_fsm_state[] = {
+	"IRLPT_CLIENT_IDLE",
+	"IRLPT_CLIENT_QUERY",
+	"IRLPT_CLIENT_READY",
+	"IRLPT_CLIENT_WAITI",
+	"IRLPT_CLIENT_WAITR",
+	"IRLPT_CLIENT_CONN"
+};
+
+char *irlpt_server_fsm_state[] = {
+	"IRLPT_SERVER_IDLE",
+	"IRLPT_SERVER_CONN"
+};
+
+char *irlpt_fsm_event[] = {
+	"QUERY_REMOTE_IAS",
+	"IAS_PROVIDER_AVAIL",
+	"IAS_PROVIDER_NOT_AVAIL",
+	"LAP_DISCONNECT",
+	"LMP_CONNECT",
+	"LMP_DISCONNECT",
+	"LMP_CONNECT_INDICATION",
+	"LMP_DISCONNECT_INDICATION",
+        "IRLPT_DISCOVERY_INDICATION",
+	"IRLPT_CONNECT_REQUEST",
+	"IRLPT_DISCONNECT_REQUEST",
+	"CLIENT_DATA_INDICATION",
+};
+
+hashbin_t *irlpt_clients = NULL;
+struct irlpt_cb *irlpt_server = NULL;
+int irlpt_common_debug = 4;  /* want to change this? please don't! 
+				use irlpt_common_debug=3 on the command line! */
+
+static struct wait_queue *irlpt_wait;
+
+#if 0
+static char *rcsid = "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
+#endif
+
+struct irlpt_cb *irlpt_find_handle(unsigned int minor)
+{
+	struct irlpt_cb *self;
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+	
+	/* Check for server */
+	if (irlpt_server != NULL && irlpt_server->ir_dev.minor == minor) {
+		DEBUG(irlpt_common_debug, __FUNCTION__ 
+		      ": irlpt_server file handle!\n");
+		return irlpt_server;
+	}
+
+	/* Check the clients */
+	self = (struct irlpt_cb *) hashbin_get_first( irlpt_clients);
+	while ( self) {
+		ASSERT( self->magic == IRLPT_MAGIC, return NULL;);
+		
+		if ( minor == self->ir_dev.minor)
+			return self;
+
+		self = (struct irlpt_cb *) hashbin_get_next( irlpt_clients);
+	}
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+
+	return NULL;
+}
+
+ssize_t irlpt_read( struct file *file, char *buffer, size_t count, loff_t
+		    *noidea)
+{
+	int len=0;
+	char *ptr = buffer;
+	struct irlpt_cb *self;
+	struct sk_buff *skb = NULL;
+	struct wait_queue wait = { current, NULL };
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
+
+	ASSERT( self != NULL, return 0;);
+	ASSERT( self->magic == IRLPT_MAGIC, return 0;);
+
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ": count=%d, skb_len=%d, connected=%d (%s) eof=%d\n", 
+	       count, skb_queue_len(&self->rx_queue), self->connected, 
+	       irlpt_connected[self->connected], self->eof);
+
+	if (self->eof && !skb_queue_len(&self->rx_queue)) {
+		switch (self->eof) {
+		case LM_USER_REQUEST:
+			self->eof = FALSE;
+			DEBUG(3, "irlpt_read: returning 0\n");
+			return 0;
+		case LM_LAP_DISCONNECT:
+			self->eof = FALSE;
+			return -EIO;
+		case LM_LAP_RESET:
+			self->eof = FALSE;
+			return -ECONNRESET;
+		default:
+			self->eof = FALSE;
+			return -EIO;
+		}
+	}
+
+	while (len <= count) {
+		skb = skb_dequeue(&self->rx_queue);
+
+		if (skb != NULL) {
+			DEBUG(irlpt_common_debug, __FUNCTION__ 
+			      ": len=%d, skb->len=%d, count=%d\n", 
+			       len, (int) skb->len, count);
+
+			if ((skb->len + len) < count) {
+				copy_to_user(ptr, skb->data, skb->len);
+				len += skb->len;
+				ptr += skb->len;
+		
+				dev_kfree_skb( skb);
+			} else {
+				skb_queue_head(&self->rx_queue, skb);
+				break;
+			}
+		} else {
+			DEBUG( irlpt_common_debug, __FUNCTION__ 
+			       ": skb=NULL, len=%d, count=%d, eof=%d\n", 
+			       len, count, self->eof);
+
+			if (!signal_pending(current) && !self->eof) {
+			        add_wait_queue(&irlpt_wait, &wait);
+				current->state = TASK_INTERRUPTIBLE;
+				schedule();
+				current->state = TASK_RUNNING;
+				remove_wait_queue(&irlpt_wait, &wait);
+			} else
+				break;
+		}
+	}
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ ": len=%d\n", len);
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+	return len;
+}
+
+ssize_t irlpt_write(struct file *file, const char *buffer,
+		    size_t count, loff_t *noidea)
+{
+	struct irlpt_cb *self;
+	struct sk_buff *skb;
+	struct wait_queue wait = { current, NULL };
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
+
+	ASSERT( self != NULL, return 0;);
+	ASSERT( self->magic == IRLPT_MAGIC, return 0;);
+	
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ": count = %d\n", count);
+
+	if (self->state != IRLPT_CLIENT_CONN) {
+		DEBUG( irlpt_common_debug, __FUNCTION__ 
+		       ": state != IRLPT_CONN (possible link problems?)\n");
+		return -ENOLINK;
+	}
+
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ": pkt_count = %d\n", self->pkt_count);
+	if (self->pkt_count > 8) {
+		DEBUG( irlpt_common_debug, __FUNCTION__ 
+		       ": too many outstanding buffers, going to sleep\n");
+		add_wait_queue(&self->write_wait, &wait);
+		current->state = TASK_INTERRUPTIBLE;
+		schedule();
+		current->state = TASK_RUNNING;
+		remove_wait_queue(&self->write_wait, &wait);
+	}
+
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+		count, self->irlap_data_size, IRLPT_MAX_HEADER);
+
+ 	if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
+ 		count = (self->irlap_data_size - IRLPT_MAX_HEADER);
+ 		DEBUG(irlpt_common_debug, __FUNCTION__ 
+		      ": setting count to %d\n", count);
+ 	}
+
+	DEBUG( irlpt_common_debug, __FUNCTION__ ": count = %d\n", count);
+
+	skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
+	if ( skb == NULL) {
+		printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n");
+		return 0;
+	}
+
+	/*
+	 * we use the unused stamp field to hold the device minor
+	 * number, so we can look it up when the skb is destroyed.
+	 */
+	*((__u32 *) &skb->stamp) = MINOR( file->f_dentry->d_inode->i_rdev);
+
+	skb_reserve( skb, IRLPT_MAX_HEADER);
+	skb_put( skb, count);
+
+	skb->destructor = irlpt_flow_control;
+	self->pkt_count++;
+
+	copy_from_user( skb->data, buffer, count);
+
+	irlmp_data_request(self->lsap, skb);
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+
+	return(count);
+}
+
+loff_t irlpt_seek( struct file *file, loff_t offset, int count)
+{
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+	return -ESPIPE;
+}
+
+#if 0
+
+/*
+ * Function irlpt_select (inode, filp, mode, table)
+ *
+ *    Implementation for the select() call
+ *
+ */
+int irlpt_select( struct inode *inode, struct file *filp, int mode, 
+			 select_table *table)
+{
+	struct irlpt_cb *self;
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+	
+	self = irlpt_find_handle(MINOR( inode->i_rdev));
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch (mode) {
+	case SEL_IN:
+		if ( skb_queue_len( &self->rx_queue))
+			return 1; /* Readable */
+		select_wait( &self->read_wait, table);
+		break;
+	case SEL_OUT:
+		if ( self->connected)
+			return 1;
+		select_wait( &self->write_wait, table);
+		break;
+	case SEL_EX:
+		if ( self->connected)
+			return 1;
+		select_wait( &self->ex_wait, table);
+		break;
+	default:
+		break;
+	}
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+#else
+
+/*
+ * Function irobex_poll (file, wait)
+ *
+ *    
+ *
+ */
+static u_int irlpt_poll(struct file *file, poll_table *wait)
+{
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	/* check out /usr/src/pcmcia/modules/ds.c for an example */
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+	return 0;
+}
+
+#endif
+
+/*
+ * Function open_irlpt (inode, file)
+ *
+ *
+ *
+ */
+int irlpt_open(struct inode *inode, struct file *file)
+{
+	struct irlpt_cb *self;
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+#if 0
+	if (self->state == IRLPT_IDLE) {
+		DEBUG( irlpt_common_debug, __FUNCTION__ 
+		       ": state == IRLPT_IDLE! (no device found yet)\n");
+		return -ENODEV;
+	}
+
+	if (self->state == IRLPT_QUERY ||
+	    self->state == IRLPT_READY ||
+	    self->state == IRLPT_WAITI) {
+		DEBUG( irlpt_common_debug, __FUNCTION__ ": state == IRLPT_QUERY, " 
+		       "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
+		return -EBUSY;
+	}
+#endif
+
+	if (self->count++) {
+		DEBUG( irlpt_common_debug, __FUNCTION__ 
+		       ": count not zero; actual = %d\n", self->count);
+		self->count--;
+		return -EBUSY;
+	}
+
+ DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function close_irlpt (inode, file)
+ *
+ *
+ *
+ */
+int irlpt_close(struct inode *inode, struct file *file)
+{
+	struct irlpt_cb *self;
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	self = irlpt_find_handle(MINOR( file->f_dentry->d_inode->i_rdev));
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ ": have handle!\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ ": self->count=%d\n", self->count);
+	if (self->count > 0)
+		self->count--;
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+void irlpt_dump_buffer( struct sk_buff *skb) 
+{
+	int i;
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	for(i=0;i<skb->len;i++)
+		if (skb->data[i] > 31 && skb->data[i] < 128) {
+			printk("%c", skb->data[i]);
+		} else {
+			if (skb->data[i] == 0x0d) {
+				printk("\n");
+			} else {
+				printk(".");
+			}
+		}
+	
+	printk("\n");
+	
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+}
+
+void irlpt_flow_control(struct sk_buff *skb)
+{
+	struct irlpt_cb *self;
+
+	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
+
+	self = irlpt_find_handle( *((__u32 *) &skb->stamp));
+
+	self->pkt_count--;
+
+	ASSERT(self->pkt_count >= 0, return;);
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ 
+	      ": packet destroyed, count = %d\n", self->pkt_count);
+
+	wake_up_interruptible( &self->write_wait);
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+}
+
+#ifdef MODULE
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize the module, this function is called by the
+ *    modprobe(1) program.
+ */
+int init_module(void) 
+{
+	return 0;
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Remove the module, this function is called by the rmmod(1)
+ *    program
+ */
+void cleanup_module(void) 
+{
+
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/irlpt_srvr.c linux/net/irda/irlpt/irlpt_srvr.c
--- v2.2.0-pre8/linux/net/irda/irlpt/irlpt_srvr.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/irlpt_srvr.c	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,545 @@
+/*********************************************************************
+ *
+ * Filename:      irlpt.c
+ * Version:       
+ * Description:   
+ * Status:        Experimental.
+ * Author:        Thomas Davis, <rat...@radiks.net>
+ * Created at:    Sat Feb 21 18:54:38 1998
+ * Modified at:   Sun Mar  8 23:44:19 1998
+ * Modified by:   Dag Brattli <da...@cs.uit.no>
+ * Sources:	  irlan.c
+ *
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>,
+ * Dag Brattli, <da...@cs.uit.no>
+ *     All Rights Reserved.
+ *
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software.
+ *     This material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/module.h>
+
+#include <asm/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+
+#include <net/irda/irlap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/irias_object.h>
+#include <net/irda/timer.h>
+#include <net/irda/irda.h>
+#include <net/irda/irlpt_common.h>
+#include <net/irda/irlpt_server.h>
+#include <net/irda/irlpt_server_fsm.h>
+
+#ifdef CONFIG_PROC_FS
+static int irlpt_server_proc_read(char *buf, char **start, off_t offset, 
+				  int len, int unused);
+#endif /* CONFIG_PROC_FS */
+
+int irlpt_server_init(void);
+static void irlpt_server_cleanup(void);
+static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+						LM_REASON reason,
+						struct sk_buff *skb);
+static void irlpt_server_connect_confirm( void *instance, void *sap, 
+					  struct qos_info *qos,  
+					  int max_seg_size,
+					  struct sk_buff *skb);
+static void irlpt_server_connect_indication( void *instance, void *sap, 
+					     struct qos_info *qos, 
+					     int max_seg_size,
+					     struct sk_buff *skb);
+static void irlpt_server_data_indication( void *instance, void *sap, 
+					  struct sk_buff *skb);
+static void register_irlpt_server(void);
+static void deregister_irlpt_server(void);
+
+static struct wait_queue *irlpt_server_wait;
+
+int irlpt_server_lsap = LSAP_IRLPT;
+int irlpt_server_debug = 4;
+
+#if 0
+static char *rcsid = "$Id: irlpt_server.c,v 1.9 1998/10/22 12:02:22 dagb Exp $";
+#endif
+static char *version = "IrLPT server, $Revision: 1.9 $/$Date: 1998/10/22 12:02:22 $ (Thomas Davis)";
+
+struct file_operations irlpt_fops = {
+	irlpt_seek,	/* seek */
+	irlpt_read,     /* read */   
+	irlpt_write,
+	NULL,		/* readdir */
+	NULL,           /* poll */
+	NULL,		/* ioctl */
+	NULL,		/* mmap */
+	irlpt_open,     /* open */
+	NULL,           /* flush */
+	irlpt_close,    /* release */
+	NULL,           /* fsync */
+	NULL,           /* fasync */
+	NULL,           /* check_media_change */
+	NULL,           /* revalidate */
+        NULL,           /* lock */
+};
+
+#ifdef CONFIG_PROC_FS
+
+/*
+ * Function proc_irlpt_read (buf, start, offset, len, unused)
+ *
+ *
+ *
+ */
+static int irlpt_server_proc_read(char *buf, char **start, off_t offset, 
+				  int len, int unused)
+{
+	int index;
+
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	if (irlpt_server != NULL) {
+	        len = sprintf(buf, "%s\n\n", version);
+		len += sprintf(buf+len, "ifname: %s\n", irlpt_server->ifname);
+		len += sprintf(buf+len, "minor: %d\n", irlpt_server->ir_dev.minor);
+
+		switch (irlpt_server->servicetype) {
+		case IRLPT_UNKNOWN:
+			index = 0;
+			break;
+		case IRLPT_THREE_WIRE_RAW:
+			index = 1;
+			break;
+		case IRLPT_THREE_WIRE:
+			index = 2;
+			break;
+		case IRLPT_NINE_WIRE:
+			index = 3;
+			break;
+		case IRLPT_CENTRONICS:
+			index = 4;
+			break;
+		case IRLPT_SERVER_MODE:
+			index = 5;
+			break;
+		default:
+			index = 0;
+			break;
+		}
+
+		len += sprintf(buf+len, "servicetype: %s\n", 
+			       irlpt_service_type[index]);
+		len += sprintf(buf+len, "porttype: %s\n", 
+			       irlpt_port_type[irlpt_server->porttype]);
+		len += sprintf(buf+len, "daddr: %d\n", 
+			       irlpt_server->daddr);
+		len += sprintf(buf+len, "state: %s\n", 
+			       irlpt_server_fsm_state[irlpt_server->state]);
+		len += sprintf(buf+len, "retries: %d\n", 
+			       irlpt_server->open_retries);
+		len += sprintf(buf+len, "peersap: %d\n", 
+			       irlpt_server->dlsap_sel);
+		len += sprintf(buf+len, "count: %d\n", 
+ irlpt_server->count);
+		len += sprintf(buf+len, "rx_queue: %d\n", 
+			       skb_queue_len(&irlpt_server->rx_queue));
+		len += sprintf(buf+len, "\n");
+	}
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+
+	return len;
+}
+
+extern struct proc_dir_entry proc_irda;
+
+struct proc_dir_entry proc_irlpt_server = {
+	0, 12, "irlpt_server",
+	S_IFREG | S_IRUGO, 1, 0, 0,
+	0, NULL /* ops -- default to array */,
+	&irlpt_server_proc_read /* get_info */,
+};
+
+#endif /* CONFIG_PROC_FS */
+
+/*
+ * Function irlpt_init (dev)
+ *
+ *   Initializes the irlpt control structure
+ *
+ */
+
+/*int irlpt_init( struct device *dev) {*/
+__initfunc(int irlpt_server_init(void))
+{
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	printk( KERN_INFO "%s\n", version);
+
+	irlpt_server = (struct irlpt_cb *) kmalloc (sizeof(struct irlpt_cb), 
+						    GFP_KERNEL);
+
+	if ( irlpt_server == NULL) {
+		printk( KERN_WARNING "IrLPT server: Can't allocate" 
+			" irlpt_server control block!\n");
+		return -ENOMEM;
+	}
+
+	memset( irlpt_server, 0, sizeof(struct irlpt_cb));
+
+	sprintf(irlpt_server->ifname, "irlpt_server");
+	irlpt_server->ir_dev.minor = MISC_DYNAMIC_MINOR;
+	irlpt_server->ir_dev.name = irlpt_server->ifname;
+	irlpt_server->ir_dev.fops = &irlpt_fops;
+	misc_register(&irlpt_server->ir_dev);
+	irlpt_server->magic = IRLPT_MAGIC;
+	irlpt_server->in_use = TRUE;
+	irlpt_server->servicetype = IRLPT_THREE_WIRE_RAW;
+	irlpt_server->porttype = IRLPT_SERIAL;
+
+	skb_queue_head_init(&irlpt_server->rx_queue);
+
+	irlmp_register_layer( S_PRINTER, SERVER, FALSE, NULL);
+	
+	register_irlpt_server();
+
+#ifdef CONFIG_PROC_FS
+	proc_register( &proc_irda, &proc_irlpt_server);
+#endif /* CONFIG_PROC_FS */
+
+ DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function irlpt_cleanup (void)
+ *
+ *
+ *
+ */
+static void irlpt_server_cleanup(void)
+{
+	struct sk_buff *skb;
+
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	deregister_irlpt_server();
+
+	while (( skb = skb_dequeue(&irlpt_server->rx_queue)) != NULL) {
+		DEBUG(irlpt_server_debug, __FUNCTION__ ": freeing SKB\n");
+                IS_SKB( skb, return;);
+                FREE_SKB_MAGIC( skb);
+                dev_kfree_skb( skb);
+	}
+
+	misc_deregister(&irlpt_server->ir_dev);
+
+	kfree(irlpt_server);
+
+#ifdef CONFIG_PROC_FS
+	proc_unregister( &proc_irda, proc_irlpt_server.low_ino);
+#endif
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_disconnect_indication (handle)
+ *
+ */
+static void irlpt_server_disconnect_indication( void *instance, void *sap, 
+						LM_REASON reason,
+						struct sk_buff *userdata)
+{
+	struct irlpt_info info;
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	self = ( struct irlpt_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	info.daddr = self->daddr;
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ ": reason=%d (%s), dlsap_sel=%d\n",
+	       reason, irlpt_reasons[reason], self->dlsap_sel);
+
+	self->connected = IRLPT_DISCONNECTED;
+	self->eof = reason;
+
+        wake_up_interruptible(&irlpt_server_wait);
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ ": skb_queue_len=%d\n",
+	       skb_queue_len(&irlpt_server->rx_queue));
+
+	irlpt_server_do_event( self, LMP_DISCONNECT, NULL, NULL);
+
+	deregister_irlpt_server();
+	register_irlpt_server();
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_connect_confirm (handle, qos, skb)
+ *
+ *    LSAP connection confirmed!
+ */
+static void irlpt_server_connect_confirm( void *instance, void *sap, 
+					  struct qos_info *qos,
+					  int max_seg_size,
+					  struct sk_buff *skb)
+{
+	struct irlpt_info info;
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+	self = ( struct irlpt_cb *) instance;
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	info.daddr = self->daddr;
+
+	/*
+	 *  Check if we have got some QoS parameters back! This should be the
+	 *  negotiated QoS for the link.
+	 */
+	if ( qos) {
+		DEBUG( irlpt_server_debug, __FUNCTION__ 
+		       ": IrLPT Negotiated BAUD_RATE: %02x\n", 
+		       qos->baud_rate.bits);			
+		DEBUG( irlpt_server_debug, __FUNCTION__ 
+		       ": IrLPT Negotiated BAUD_RATE: %d bps.\n", 
+		       qos->baud_rate.value);
+	}
+
+	self->connected = TRUE;
+
+	irlpt_server_do_event( self, LMP_CONNECT, NULL, NULL);
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_connect_indication (handle)
+ *
+ */
+static void irlpt_server_connect_indication( void *instance, void *sap, 
+					     struct qos_info *qos, 
+					     int max_seg_size,
+					     struct sk_buff *skb)
+{
+	struct irlpt_cb *self;
+ struct irlpt_info info;
+	struct lsap_cb *lsap;
+
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	self = ( struct irlpt_cb *) instance;
+	lsap = (struct lsap_cb *) sap;
+	
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	self->connected = IRLPT_CONNECTED;
+	self->eof = FALSE;
+
+	info.lsap = lsap;
+
+	irlpt_server_do_event( self, LMP_CONNECT, NULL, &info);
+
+	if (skb) {
+		dev_kfree_skb( skb);
+	}
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function irlpt_data_indication (handle, skb)
+ *
+ *    This function gets the data that is received on the data channel
+ *
+ */
+static void irlpt_server_data_indication( void *instance, void *sap, 
+					  struct sk_buff *skb) 
+{
+
+	struct irlpt_cb *self;
+
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	self = ( struct irlpt_cb *) instance;
+	     
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	ASSERT( skb != NULL, return;);
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ ": len=%d\n", (int) skb->len);
+
+#if 0
+	dump_buffer(skb);
+#endif
+	
+	skb_queue_tail(&self->rx_queue, skb);
+        wake_up_interruptible(&irlpt_server_wait);
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function register_irlpt_server(void)
+ *
+ *    Register server support so we can accept incoming connections. We
+ *    must register both a TSAP for control and data
+ * 
+ */
+static void register_irlpt_server(void)
+{
+	struct notify_t notify;
+	struct ias_object *obj;
+	
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+	/*
+	 *  First register control TSAP
+	 */
+
+	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
+		DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
+		return;
+	}
+
+	irda_notify_init(¬ify);
+
+	notify.connect_confirm = irlpt_server_connect_confirm;
+	notify.connect_indication = irlpt_server_connect_indication;
+	notify.disconnect_indication = irlpt_server_disconnect_indication;
+	notify.data_indication = irlpt_server_data_indication;
+	notify.instance = irlpt_server;
+	strcpy(notify.name, "IrLPT");
+
+	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, ¬ify);
+
+	irlpt_server->connected = IRLPT_WAITING;
+	irlpt_server->service_LSAP = irlpt_server_lsap;
+
+	/* 
+	 *  Register with LM-IAS
+	 */
+
+	obj = irias_new_object("IrLPT", IAS_IRLPT_ID);
+	irias_add_integer_attrib(obj, "IrDA:IrLMP:LsapSel", irlpt_server_lsap);
+	irias_insert_object(obj);
+
+	DEBUG( irlpt_server_debug, __FUNCTION__ 
+	       ": Source LSAP sel=%d\n", irlpt_server->slsap_sel);
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function register_irlpt_server(void)
+ *
+ *    Register server support so we can accept incoming connections. We
+ *    must register both a TSAP for control and data
+ * 
+ */
+static void deregister_irlpt_server(void)
+{
+#if 0
+	struct notify_t notify;
+#endif
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+
+#if 0
+	/*
+	 *  First register control TSAP
+	 */
+
+	if ( !irlpt_server || irlpt_server->magic != IRLPT_MAGIC) {
+		DEBUG( 0, "irlpt_register_server:, unable to obtain handle!\n");
+		return;
+	}
+
+	irda_notify_init(¬ify);
+
+	notify.connect_confirm = irlpt_server_connect_confirm;
+	notify.connect_indication = irlpt_server_connect_indication;
+	notify.disconnect_indication = irlpt_server_disconnect_indication;
+	notify.data_indication = irlpt_server_data_indication;
+	notify.instance = irlpt_server;
+	strcpy(notify.name, "IrLPT");
+
+	irlpt_server->lsap = irlmp_open_lsap( irlpt_server_lsap, ¬ify);
+
+	irlpt_server->connected = IRLPT_WAITING;
+	irlpt_server->service_LSAP = irlpt_server_lsap;
+#endif
+
+	/* 
+	 *  de-Register with LM-IAS
+	 */
+	irias_delete_object( "IrLPT");
+
+	DEBUG( irlpt_server_debug, 
+	       __FUNCTION__ ": Source LSAP sel=%d\n", irlpt_server->slsap_sel);
+	DEBUG( irlpt_server_debug, __FUNCTION__ " -->\n");
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Thomas Davis <rat...@radiks.net>");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT protocol");
+
+/*
+ * Function init_module (void)
+ *
+ *    Initialize the IrLPT server module, this function is called by the
+ *    modprobe(1) program.
+ */
+int init_module(void)
+{
+
+        DEBUG( irlpt_server_debug, "--> irlpt server: init_module\n");
+
+        irlpt_server_init();
+
+        DEBUG( irlpt_server_debug, "irlpt server: init_module -->\n");
+
+        return 0;
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ *    Remove the IrLPT server module, this function is called by the rmmod(1)
+ *    program
+ */
+void cleanup_module(void)
+{
+	DEBUG( irlpt_server_debug, "--> " __FUNCTION__ "\n");
+        DEBUG( 3, "--> irlpt server: cleanup_module\n");
+        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+
+        /* Free some memory */
+        irlpt_server_cleanup();
+
+        DEBUG( irlpt_server_debug, "irlpt server: cleanup_module -->\n");
+}
+
+#endif /* MODULE */
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irlpt/irlpt_srvr_fsm.c linux/net/irda/irlpt/irlpt_srvr_fsm.c
--- v2.2.0-pre8/linux/net/irda/irlpt/irlpt_srvr_fsm.c	Wed Dec 31 16:00:00 1969
+++ linux/net/irda/irlpt/irlpt_srvr_fsm.c	Wed Jan 20 11:05:33 1999
@@ -0,0 +1,182 @@
+/*********************************************************************
+ *                
+ * Filename:      irlpt_srvr_fsm.c
+ * Version:       0.1
+ * Sources:       irlan_event.c
+ * 
+ *     Copyright (c) 1997, Dag Brattli <da...@cs.uit.no>, All Rights Reserved.
+ *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>, All Rights Reserved.
+ *     
+ *     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.
+ *
+ *     I, Thomas Davis, provide no warranty for any of this software. This 
+ *     material is provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/config.h>
+
+#include <net/irda/iriap.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlpt_common.h>
+#include <net/irda/irlpt_server.h>
+#include <net/irda/irlpt_server_fsm.h>
+#include <net/irda/irda.h>
+
+static int irlpt_server_state_idle  ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event,
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+static int irlpt_server_state_conn  ( struct irlpt_cb *self, 
+				      IRLPT_EVENT event, 
+				      struct sk_buff *skb, 
+				      struct irlpt_info *info);
+
+#if 0
+static char *rcsid = "$Id: irlpt_server_fsm.c,v 1.4 1998/10/05 05:46:45 ratbert Exp $";
+#endif
+
+int irlpt_server_fsm_debug = 3;
+
+static int (*irlpt_server_state[])( struct irlpt_cb *self, IRLPT_EVENT event, 
+				    struct sk_buff *skb,
+				    struct irlpt_info *info) = 
+{ 
+	irlpt_server_state_idle,
+	irlpt_server_state_conn,
+};
+
+void irlpt_server_do_event( struct irlpt_cb *self, IRLPT_EVENT event, 
+			    struct sk_buff *skb, struct irlpt_info *info) 
+{
+	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": STATE = %s, EVENT = %s\n", 
+	       irlpt_server_fsm_state[self->state], irlpt_fsm_event[event]);
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	(*irlpt_server_state[ self->state]) ( self, event, skb, info);
+
+	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
+}
+
+void irlpt_server_next_state( struct irlpt_cb *self, IRLPT_CLIENT_STATE state) 
+{
+
+	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ ": NEXT STATE = %s\n", 
+	       irlpt_server_fsm_state[state]);
+
+	ASSERT( self != NULL, return;);
+	ASSERT( self->magic == IRLPT_MAGIC, return;);
+
+	self->state = state;
+
+	DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
+}
+
+/*
+ * Function server_state_idle (event, skb, info)
+ *
+ *    IDLE, We are waiting for an indication that there is a provider
+ *    available.
+ */
+static int irlpt_server_state_idle( struct irlpt_cb *self, IRLPT_EVENT event, 
+				    struct sk_buff *skb, 
+				    struct irlpt_info *info) 
+{
+	struct sk_buff *r_skb;
+
+	DEBUG( irlpt_server_fsm_debug, "--> " __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case LMP_CONNECT:
+		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
+		       ": LM_CONNECT, remote lsap=%d\n", 
+		       info->dlsap_sel);
+
+		self->dlsap_sel = info->dlsap_sel;
+
+		r_skb = dev_alloc_skb(64);
+		if (r_skb == NULL) { 
+			printk( KERN_INFO __FUNCTION__ 
+				": can't allocate sk_buff of length 64\n");
+			return 0;
+		}
+		ALLOC_SKB_MAGIC(r_skb);
+		skb_reserve( r_skb, LMP_MAX_HEADER);
+		skb->len = 0;
+		irlmp_connect_response( self->lsap, r_skb);
+		irlpt_server_next_state( self, IRLPT_SERVER_CONN);
+
+		break;
+
+	default:
+		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d (%s)\n", 
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if (skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+/*
+ * Function server_state_conn (event, skb, info)
+ *
+ *    CONN, We have connected to a provider but has not issued any
+ *    commands yet.
+ *
+ */
+static int irlpt_server_state_conn( struct irlpt_cb *self, 
+				    IRLPT_EVENT event, 
+				    struct sk_buff *skb, 
+				    struct irlpt_info *info) 
+{
+	DEBUG( irlpt_server_fsm_debug, "--> " __FUNCTION__ ":\n");
+
+	ASSERT( self != NULL, return -1;);
+	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
+
+	switch( event) {
+	case LMP_DISCONNECT:
+	case LAP_DISCONNECT:
+		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
+		       ": LMP_DISCONNECT/LAP_DISCONNECT\n");
+		irlpt_server_next_state( self, IRLPT_SERVER_IDLE);
+		break;
+
+	default:
+		DEBUG( irlpt_server_fsm_debug, __FUNCTION__ 
+		       ": Unknown event %d (%s)\n", 
+		       event, irlpt_fsm_event[event]);
+		break;
+	}
+
+	if ( skb) {
+		dev_kfree_skb( skb);
+	}
+
+ DEBUG( irlpt_server_fsm_debug, __FUNCTION__ " -->\n");
+
+	return 0;
+}
+
+#if 0
+static void irlpt_server_print_event( IRLPT_EVENT event) 
+{
+	DEBUG( 0, "IRLPT_EVENT = %s\n", irlpt_fsm_event[event]);
+}
+#endif
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irmod.c linux/net/irda/irmod.c
--- v2.2.0-pre8/linux/net/irda/irmod.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irmod.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Dec 15 13:55:39 1997
- * Modified at:   Mon Dec 14 20:10:28 1998
+ * Modified at:   Tue Jan 19 23:34:18 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -33,7 +33,11 @@
X #include <net/irda/iriap.h>
X #include <net/irda/irttp.h>
X 
-struct irda irda; /* One global instance */
+struct irda_cb irda; /* One global instance */
+
+#ifdef CONFIG_IRDA_DEBUG
+__u32 irda_debug = IRDA_DEBUG;
+#endif
X 
X extern void irda_proc_register(void);
X extern void irda_proc_unregister(void);
@@ -50,6 +54,8 @@
X extern int irlan_server_init(void);
X extern int ircomm_init(void);
X extern int irvtd_init(void);
+extern int irlpt_client_init(void);
+extern int irlpt_server_init(void);
X 
X static int irda_open( struct inode * inode, struct file *file);
X static int irda_ioctl( struct inode *inode, struct file *filp, 
@@ -99,6 +105,8 @@
X 	
X 	misc_register( &irda.dev);
X 
+	irda.in_use = FALSE;
+
X 	/* 
X 	 * Initialize modules that got compiled into the kernel 
X 	 */
@@ -119,6 +127,14 @@
X 	irvtd_init();
X #endif
X 
+#ifdef CONFIG_IRLPT_CLIENT
+	irlpt_client_init();
+#endif
+
+#ifdef CONFIG_IRLPT_SERVER
+	irlpt_server_init();
+#endif
+
X 	return 0;
X }
X 
@@ -206,6 +222,12 @@
X 	struct irda_todo *new;
X 	struct irmanager_event event;
X 
+	/* Make sure irmanager is running */
+	if ( !irda.in_use) {
+		printk( KERN_ERR "irmanager is not running!\n");
+		return;
+	}
+
X 	/* Make new todo event */
X 	new = (struct irda_todo *) kmalloc( sizeof(struct irda_todo),
X 					    GFP_ATOMIC);
@@ -239,6 +261,12 @@
X 	
X 	DEBUG( 4, __FUNCTION__ "()\n");
X 
+	/* Make sure irmanager is running */
+	if ( !irda.in_use) {
+		printk( KERN_ERR "irmanager is not running!\n");
+		return;
+	}
+
X 	/* Make new IrDA Event */
X 	new = (struct irda_event *) kmalloc( sizeof(struct irda_event),
X 					     GFP_ATOMIC);
@@ -259,6 +287,12 @@
X {
X 	DEBUG( 4, __FUNCTION__ "()\n");
X 
+	if ( irda.in_use) {
+		DEBUG( 0, __FUNCTION__ "(), irmanager is already running!\n");
+		return -1;
+	}
+	irda.in_use = TRUE;
+		
X 	MOD_INC_USE_COUNT;
X 
X 	return 0;
@@ -312,6 +346,8 @@
X 	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	MOD_DEC_USE_COUNT;
+
+	irda.in_use = FALSE;
X 
X 	return 0;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irobex/irobex.c linux/net/irda/irobex/irobex.c
--- v2.2.0-pre8/linux/net/irda/irobex/irobex.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irobex/irobex.c	Wed Jan 20 11:05:33 1999
@@ -1,12 +1,12 @@
X /*********************************************************************
X  *                
X * Filename: irobex.c
- * Version:       0.1
+ * Version:       0.3
X * Description: Kernel side of the IrOBEX layer
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Thu Jun 25 21:21:07 1998
- * Modified at:   Mon Dec 14 11:56:26 1998
+ * Modified at:   Sat Jan 16 22:18:03 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli, All Rights Reserved.
@@ -46,6 +46,14 @@
X  */
X struct irobex_cb *irobex;
X 
+char *irobex_state[] = {
+	"OBEX_IDLE",
+	"OBEX_DISCOVER",
+	"OBEX_QUERY",
+	"OBEX_CONN",
+	"OBEX_DATA",
+};
+
X static int irobex_dev_open( struct inode * inode, struct file *file);
X static int irobex_ioctl( struct inode *inode, struct file *filp, 
X 			 unsigned int cmd, unsigned long arg);
@@ -99,14 +107,12 @@
X {
X 	struct irobex_cb *self;
X 
-	DEBUG( 4, "--> " __FUNCTION__ "()\n");	
-
X 	self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);
X 	if ( self == NULL)
X 		return -ENOMEM;
X 	
X 	memset( self, 0, sizeof(struct irobex_cb));
- 	sprintf( self->devname, "irobex%d", 1); /* Just one instance for now */
+ 	sprintf( self->devname, "irobex%d", 0); /* Just one instance for now */
X 	
X 	self->magic = IROBEX_MAGIC;
X 	self->rx_flow = self->tx_flow = FLOW_START;
@@ -121,8 +127,6 @@
X 	irobex = self;
X 	
X 	misc_register( &self->dev);
-	
-	irobex_register_server( self);
X 
X #ifdef CONFIG_PROC_FS
X 	proc_register( &proc_irda, &proc_irobex);
@@ -131,8 +135,6 @@
X 	irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, 
X 			      irobex_discovery_indication);
X 	
-	DEBUG( 4, "irobex_init -->\n");
-	
X 	return 0;
X }
X 
@@ -142,12 +144,13 @@
X  *     Removes the IrOBEX layer
X  *
X  */
+#ifdef MODULE
X void irobex_cleanup(void)
X {
X 	struct sk_buff *skb;
X 	struct irobex_cb *self;
X 	
-	DEBUG( 4, "-->" __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	self = irobex;
X 
@@ -170,9 +173,8 @@
X 	/*
X 	 *  Deallocate buffers
X 	 */
-	while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
+	while (( skb = skb_dequeue( &self->rx_queue)) != NULL)
X 		dev_kfree_skb( skb);
-	}
X 
X #ifdef CONFIG_PROC_FS
X 	proc_unregister( &proc_irda, proc_irobex.low_ino);
@@ -180,10 +182,9 @@
X 	
X 	misc_deregister( &self->dev);
X 	
-	kfree( self);
-	
-	DEBUG( 4, __FUNCTION__ "() -->\n");
+	kfree( self);	
X }
+#endif /* MODULE */
X 
X /*
X  * Function irobex_read (inode, file, buffer, count)
@@ -204,19 +205,24 @@
X 	ASSERT( self != NULL, return -EIO;);
X 	ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
X   
-	DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, conn.=%d, eof=%d\n", 
-	       count, skb_queue_len( &self->rx_queue), self->connected, 
+	DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, state=%s, eof=%d\n", 
+	       count, skb_queue_len( &self->rx_queue), 
+	       irobex_state[self->state], 
X 	       self->eof);
-	
+
+	if ( self->state != OBEX_DATA) {
+		DEBUG( 0, __FUNCTION__ "(), link not connected yet!\n");
+		return -EIO;
+	}
+
X 	/*
-	 *  Check if there is no data to return
+	 *  If there is data to return, then we return it. If not, then we 
+	 *  must check if we are still connected
X 	 */
X 	if ( skb_queue_len( &self->rx_queue) == 0) {
X 
-		/*
-		 *  Disconnected yet?
-		 */
-		if ( !self->connected) {
+		/* Still connected?  */
+		if ( self->state != OBEX_DATA) {
X 			switch ( self->eof) {
X 			case LM_USER_REQUEST:
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 12'
echo 'File patch-2.2.0-pre9 is continued in part 13'
echo 13 > _shar_seq_.tmp
#!/bin/sh
# this is part 13 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 13; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
X 				self->eof = FALSE;
@@ -243,7 +249,7 @@
X 		if ( file->f_flags & O_NONBLOCK)
X 			return -EAGAIN;
X 
-		/* * Go to sleep and wait for data!  */
+		/* Go to sleep and wait for data!  */
X 		interruptible_sleep_on( &self->read_wait);
X 
X 		/*
@@ -266,7 +272,7 @@
X 		 */
X 		if ( self->rx_flow == FLOW_STOP) {
X 			if ( skb_queue_len( &self->rx_queue) < LOW_THRESHOLD) {
-				DEBUG( 0, __FUNCTION__ "(), Starting IrTTP\n");
+				DEBUG( 4, __FUNCTION__ "(), Starting IrTTP\n");
X 				self->rx_flow = FLOW_START;
X 				irttp_flow_request( self->tsap, FLOW_START);
X 			}
@@ -279,7 +285,7 @@
X 		if ( count <  skb->len) {
X 			copy_to_user( buffer+len, skb->data, count);
X 			len += count;
-
+			
X 			/*
X 			 *  Remove copied data from skb and queue
X 			 *  it for next read
@@ -323,34 +329,36 @@
X 	/*
X 	 *  If we are not connected then we just give up!
X 	 */
-	if ( !self->connected) {
+	if ( self->state != OBEX_DATA) {
X 		DEBUG( 0, __FUNCTION__ "(): Not connected!\n");
-
+		
X 		return -ENOLINK;
X 	} 
-
+	
X 	/* Check if IrTTP is wants us to slow down */
X 	if ( self->tx_flow == FLOW_STOP) {
-		DEBUG( 0, __FUNCTION__ 
+		DEBUG( 4, __FUNCTION__ 
X 		       "(), IrTTP wants us to slow down, going to sleep\n");
X 		interruptible_sleep_on( &self->write_wait);
X 	}
X 	
X 	/* Send data to TTP layer possibly as muliple packets */
X 	while ( count) {
-
+		
X 		/*
X 		 *  Check if request is larger than what fits inside a TTP
-		 *  frame
+		 *  frame. In that case we must fragment the frame into 
+		 *  multiple TTP frames. IrOBEX should not care about message
+		 *  boundaries.
X 		 */
X 		if ( count < (self->irlap_data_size - IROBEX_MAX_HEADER))
X 			data_len = count;
X 		else 
X 		        data_len = self->irlap_data_size - IROBEX_MAX_HEADER;
-
+		
X 		DEBUG( 4, __FUNCTION__ "(), data_len=%d, header_len = %d\n", 
X 		       data_len, IROBEX_MAX_HEADER);
-
+		
X 		skb = dev_alloc_skb( data_len + IROBEX_MAX_HEADER);
X 		if ( skb == NULL) {
X 			DEBUG( 0, "irobex - couldn't allocate skbuff!\n");
@@ -363,10 +371,11 @@
X 		copy_from_user( skb->data, buffer+len, data_len);
X 		len += data_len;
X 		count -= data_len;
-
+		
X 		DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int) skb->len);
X 		ASSERT( skb->len <= (self->irlap_data_size-IROBEX_MAX_HEADER),
X 			return len;);
+		
X 		irttp_data_request( self->tsap, skb);
X 	}
X 	return (len);
@@ -433,7 +442,7 @@
X 	int err = 0;
X 	int size = _IOC_SIZE(cmd);
X 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	self = irobex;
X 	
@@ -454,73 +463,73 @@
X 
X 	switch ( cmd) {
X 	case IROBEX_IOCSCONNECT:
-		DEBUG( 0, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
+		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
X 		
X 		/* Already connected? */
-		if ( self->connected)
+		if ( self->state == OBEX_DATA) {
+			DEBUG( 0, __FUNCTION__ "(), already connected!\n");
X 			return 0;
+		}
X 		
+		/* Timeout after 15 secs. */
+		irobex_start_watchdog_timer( self, 1000);
+
X 		/*
-		 *  Wait until we have discovered a remote IrOBEX device
+		 * If we have discovered a remote device we
+		 * check if the discovery is still fresh. If not, we don't
+		 * trust the address.
X 		 */
-		if (( self->daddr == 0) || 
-		    (( jiffies - self->time_discovered) > 500)) {
-			
-			if ( self->daddr != 0) {
-				DEBUG( 0, __FUNCTION__ "(), daddr is old!\n");
-				self->daddr = 0;
-			}
+		if ( self->daddr && ((jiffies - self->time_discovered) > 500))
+			self->daddr = 0;
X 
+		/* 
+		 * Try to discover remote remote device if it has not been 
+		 * discovered yet. 
+		 */
+		if ( !self->daddr) {
+			self->state = OBEX_DISCOVER;
+			
X 			irlmp_discovery_request( 8);
-			DEBUG( 0, __FUNCTION__ 
-			       "(): Sleep until device discovered\n");
X 			
-			/* Timeout after 10 secs. */
-			irobex_start_watchdog_timer( self, 1000);
-			/*
-			 *  Wait for discovery to complete
-			 */
-			interruptible_sleep_on( &self->discover_wait);
-			/* del_timer( &self->watchdog_timer); */
+			/* Wait for discovery to complete */
+			interruptible_sleep_on( &self->write_wait);
+			del_timer( &self->watchdog_timer);
X 		}
X 		
X 		/* Give up if we are unable to discover any remote devices */
-		if ( self->daddr == 0) {
+		if ( !self->daddr) {
X 			DEBUG( 0, __FUNCTION__ 
X 			       "(), Unable to discover any devices!\n");
X 			return -ENOTTY;
X 		}
X 		
X 		/* Need to find remote destination TSAP selector? */
-		if ( self->dtsap_sel == 0) {
-			
+		if ( !self->dtsap_sel) {
X 			DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
X 			
+			self->state = OBEX_QUERY;
+			
X 			/* Timeout after 5 secs. */
X 			irobex_start_watchdog_timer( self, 500);
-			iriap_getvaluebyclass_request( self->daddr,
-						       "OBEX", 
-						       "IrDA:TinyTP:LsapSel",
-						       irobex_get_value_confirm,
-						       self);
+			iriap_getvaluebyclass_request( 
+				self->daddr,
+				"OBEX", 
+				"IrDA:TinyTP:LsapSel",
+				irobex_get_value_confirm,
+				self);
X 			
-			DEBUG( 0, __FUNCTION__ "(): Sleep until IAS answer\n");
-			interruptible_sleep_on( &self->ias_wait);
-			/* del_timer( &self->watchdog_timer); */
+			interruptible_sleep_on( &self->write_wait);
+			del_timer( &self->watchdog_timer);
X 		}	
X 		
-		if ( self->dtsap_sel == 0) {
+		if ( !self->dtsap_sel) {
X 			DEBUG( 0, __FUNCTION__ 
X 			       "(), Unable to query remote LM-IAS!\n");
X 			return -ENOTTY;
X 		}
X 
-
-		/*
-		 *  Try connect
-		 */
-		DEBUG( 0, __FUNCTION__ "(): Connecting ...\n");
-
+		self->state = OBEX_CONN;
+		
X 		/* Timeout after 5 secs. */
X 		irobex_start_watchdog_timer( self, 500);
X 
@@ -528,31 +537,28 @@
X 				       self->daddr, NULL, SAR_DISABLE, 
X 				       NULL);
X 		
-		/*
-		 *  Go to sleep and wait for connection!
-		 */
-		DEBUG( 0, __FUNCTION__ "(): Waiting for connection!\n");
-		interruptible_sleep_on( &self->connect_wait);
-
+		/* Go to sleep and wait for connection!  */
+		interruptible_sleep_on( &self->write_wait);
X 		del_timer( &self->watchdog_timer);
X 		
-		if ( !self->connected) {
+		if ( self->state != OBEX_DATA) {
X 			DEBUG( 0, __FUNCTION__ 
X 			       "(), Unable to connect to remote device!\n");
X 			return -ENOTTY;
X 		}
-
+		
X 		break;
X 	case IROBEX_IOCSDISCONNECT:
-		DEBUG( 0, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
-		if ( !self->connected)
+		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
+
+		if ( self->state != OBEX_DATA)
X 			return 0;
X 
X 		irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
X 
X 		/* Reset values for this instance */
-		self->connected = FALSE;
-		self->eof = 0;
+		self->state = OBEX_IDLE;
+		self->eof = LM_USER_REQUEST;
X 		self->daddr = 0;
X 		self->dtsap_sel = 0;
X 		self->rx_flow = FLOW_START;
@@ -569,14 +575,14 @@
X /*
X  * Function irobex_dev_open (inode, file)
X  *
- *    
+ *    Device opened by user process
X  *
X  */
X static int irobex_dev_open( struct inode * inode, struct file *file)
X {
X 	struct irobex_cb *self;
X 	
- DEBUG( 4, "open_irobex:\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	self = irobex;
X 
@@ -589,18 +595,28 @@
X 		self->count--;
X 		return -EBUSY;
X 	}
-	
+
+	irobex_register_server( self);
+
+	/* Reset values for this instance */
+	self->state = OBEX_IDLE;
+	self->eof = FALSE;
+	self->daddr = 0;
+	self->dtsap_sel = 0;
+	self->rx_flow = FLOW_START;
+	self->tx_flow = FLOW_START;
+
X 	MOD_INC_USE_COUNT;
X 	
X 	return 0;
X }
X 
-static int  irobex_dev_close( struct inode *inode, struct file *file)
+static int irobex_dev_close( struct inode *inode, struct file *file)
X {
X 	struct irobex_cb *self;
X 	struct sk_buff *skb;
X 	
- DEBUG( 4, "close_irobex()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	self = irobex;
X 
@@ -613,11 +629,17 @@
X 		dev_kfree_skb( skb);
X 	}
X 
-	/* if ( self->tsap) { */
-/* 		irttp_close_tsap( self->tsap); */
-/* 		self->tsap = NULL; */
-/* 		self->connected = FALSE; */
-/* 	} */
+	/* Close TSAP is its still there */
+	if ( self->tsap) {
+		irttp_close_tsap( self->tsap);
+		self->tsap = NULL;
+	}
+	self->state = OBEX_IDLE;
+	self->eof = FALSE;
+	self->daddr = 0;
+	self->dtsap_sel = 0;
+	self->rx_flow = FLOW_START;
+	self->tx_flow = FLOW_START;
X 
X 	/* Remove this filp from the asynchronously notified filp's */
X 	irobex_fasync( -1, file, 0);
@@ -647,16 +669,19 @@
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IROBEX_MAGIC, return;);
X 
+	/* Remember address and time if was discovered */
X 	self->daddr = discovery->daddr;
X 	self->time_discovered = jiffies;
X 	
-	wake_up_interruptible( &self->discover_wait);
+	/* Wake up process if its waiting for device to be discovered */
+	if ( self->state == OBEX_DISCOVER)
+		wake_up_interruptible( &self->write_wait);
X }
X 
X /*
X  * Function irobex_disconnect_indication (handle, reason, priv)
X  *
- *    
+ *    Link has been disconnected
X  *
X  */
X void irobex_disconnect_indication( void *instance, void *sap, 
@@ -664,35 +689,27 @@
X {
X 	struct irobex_cb *self;
X 	
-	DEBUG( 0, __FUNCTION__ "(), reason=%d\n", reason);
-
+	DEBUG( 4, __FUNCTION__ "(), reason=%d\n", reason);
+	
X 	self = ( struct irobex_cb *) instance;
-
+	
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IROBEX_MAGIC, return;);
-
-/* 	save_flags(flags); */
-/* 	cli(); */
X 	
-	self->connected = FALSE;
+	self->state = OBEX_IDLE;
X 	self->eof = reason;
X 	self->daddr = 0;
X 	self->dtsap_sel = 0;
X 	self->rx_flow = self->tx_flow = FLOW_START;
-	
-/* 	restore_flags(flags); */
X 
X 	wake_up_interruptible( &self->read_wait);
-	wake_up_interruptible( &self->connect_wait);
X 	wake_up_interruptible( &self->write_wait);
X 	
-	DEBUG( 4, "irobex_disconnect_indication: skb_queue_len=%d\n",
+	DEBUG( 4, __FUNCTION__ "(), skb_queue_len=%d\n",
X 	       skb_queue_len( &irobex->rx_queue));
X 	
-	if ( userdata) {
+	if ( userdata)
X 	        dev_kfree_skb( userdata);
-
-	}	
X }
X 
X /*
@@ -706,7 +723,7 @@
X {
X 	struct irobex_cb *self;
X 	
- DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	self = ( struct irobex_cb *) instance;
X 
@@ -714,18 +731,20 @@
X 	ASSERT( self->magic == IROBEX_MAGIC, return;);
X 	ASSERT( qos != NULL, return;);
X 
-	DEBUG( 0, __FUNCTION__ "(), IrLAP data size=%d\n", 
+	DEBUG( 4, __FUNCTION__ "(), IrLAP data size=%d\n", 
X 	       qos->data_size.value);
X 
X 	self->irlap_data_size = qos->data_size.value;
-	self->connected = TRUE;
X 
X 	/*
X 	 *  Wake up any blocked process wanting to write. Finally this process
X 	 *  can start writing since the connection is now open :-)
X 	 */
-	wake_up_interruptible( &self->connect_wait);
-
+	if (self->state == OBEX_CONN) {
+		self->state = OBEX_DATA;
+		wake_up_interruptible( &self->write_wait);
+	}
+	
X 	if ( userdata) {
X 	        dev_kfree_skb( userdata);
X 
@@ -743,18 +762,16 @@
X 	struct sk_buff *skb;
X /* 	__u8 *frame; */
X 
-	DEBUG( 4, "irobex_connect_response()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IROBEX_MAGIC, return;);	
X 
-	self->connected = TRUE;
+	self->state = OBEX_DATA;
X 
X 	skb = dev_alloc_skb( 64);
X 	if (skb == NULL) {
- DEBUG( 0,"irobex_connect_response: "
-		       "Could not allocate an sk_buff of length %d\n",
-		       64);
+		DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n");
X 		return;
X 	}
X 
@@ -777,7 +794,7 @@
X 	struct irmanager_event mgr_event;
X 	struct irobex_cb *self;
X 	
- DEBUG( 0, "irobex_connect_indication()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	self = ( struct irobex_cb *) instance;
X 
@@ -787,22 +804,23 @@
X 
X 	self->eof = FALSE;
X 
-	DEBUG( 0, "irobex_connect_indication, skb_len = %d\n", 
+	DEBUG( 4, __FUNCTION__ "(), skb_len = %d\n", 
X 	       (int) userdata->len);
X 
-	DEBUG( 0, __FUNCTION__ "(), IrLAP data size=%d\n", 
+	DEBUG( 4, __FUNCTION__ "(), IrLAP data size=%d\n", 
X 	       qos->data_size.value);
X 
X 	ASSERT( qos->data_size.value >= 64, return;);
X 
X 	self->irlap_data_size = qos->data_size.value;
X 
+	/* We just accept the connection */
X 	irobex_connect_response( self);
-
+#if 1
X 	mgr_event.event = EVENT_IROBEX_START;
X 	sprintf( mgr_event.devname, "%s", self->devname);
X 	irmanager_notify( &mgr_event);
-
+#endif
X 	wake_up_interruptible( &self->read_wait);
X 
X 	if ( userdata) {
@@ -862,7 +880,7 @@
X {
X 	struct irobex_cb *self;
X 
- DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	self = ( struct irobex_cb *) instance;
X 	
@@ -877,7 +895,7 @@
X 	case FLOW_START:
X 		self->tx_flow = flow;
X 		DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to start again\n");
-		wake_up_interruptible( &self->discover_wait);
+		wake_up_interruptible( &self->write_wait);
X 		break;
X 	default:
X 		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
@@ -895,7 +913,7 @@
X {
X 	struct irobex_cb *self;
X 	
- DEBUG( 4, "irobex_get_value_confirm()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( priv != NULL, return;);
X 	self = ( struct irobex_cb *) priv;
@@ -907,8 +925,7 @@
X 
X 	switch ( value->type) {
X 	case IAS_INTEGER:
-		DEBUG( 0, "irobex_get_value_confirm() int=%d\n", 
-		       value->t.integer);
+		DEBUG( 4, __FUNCTION__ "() int=%d\n", value->t.integer);
X 		
X 		if ( value->t.integer != -1) {
X 			self->dtsap_sel = value->t.integer;
@@ -920,24 +937,22 @@
X 			 *  process that wants to make a connection, so we
X 			 *  just let that process do the connect itself
X 			 */
-			wake_up_interruptible( &self->ias_wait);
+			if ( self->state == OBEX_QUERY)
+				wake_up_interruptible( &self->write_wait);
X 		} else 
X 			self->dtsap_sel = 0;
X 		break;
X 	case IAS_STRING:
-		DEBUG( 0, "irlan_get_value_confirm(), got string %s\n", 
-		       value->t.string);
+		DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string);
X 		break;
X 	case IAS_OCT_SEQ:
-		DEBUG( 0, "irobex_get_value_confirm(), "
-		       "OCT_SEQ not implemented\n");
+		DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n");
X 		break;
X 	case IAS_MISSING:
-		DEBUG( 0, "irobex_get_value_confirm(), "
-		       "MISSING not implemented\n");
+		DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n");
X 		break;
X 	default:
-		DEBUG( 0, "irobex_get_value_confirm(), unknown type!\n");
+		DEBUG( 0, __FUNCTION__ "(), unknown type!\n");
X 		break;
X 	}
X }
@@ -1004,8 +1019,7 @@
X 	self->tsap = irttp_open_tsap( TSAP_IROBEX, DEFAULT_INITIAL_CREDIT,
X 				      ¬ify);	
X 	if ( self->tsap == NULL) {
-		DEBUG( 0, "irobex_register_server(), "
-		       "Unable to allocate TSAP!\n");
+		DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
X 		return;
X 	}
X 
@@ -1015,23 +1029,26 @@
X 	obj = irias_new_object( "OBEX", 0x42343);
X 	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IROBEX);
X 	irias_insert_object( obj);
-
X }
X 
X void irobex_watchdog_timer_expired( unsigned long data)
X {
X 	struct irobex_cb *self = ( struct irobex_cb *) data;
X 	
-	DEBUG( 0, __FUNCTION__ "()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == IROBEX_MAGIC, return;);
X 
-	wake_up_interruptible( &self->discover_wait);
-	wake_up_interruptible( &self->ias_wait);
-	wake_up_interruptible( &self->connect_wait);
-
-	/* irlmp_do_lsap_event( self, LM_WATCHDOG_TIMEOUT, NULL); */
+	switch (self->state) {
+	case OBEX_CONN:      /* FALLTROUGH */
+	case OBEX_DISCOVER:  /* FALLTROUGH */
+	case OBEX_QUERY:     /* FALLTROUGH */
+		wake_up_interruptible( &self->write_wait);
+		break;
+	default:
+		break;
+	}
X }
X 
X #ifdef CONFIG_PROC_FS
@@ -1053,8 +1070,7 @@
X 	len = 0;
X 	
X 	len += sprintf( buf+len, "ifname: %s ",self->devname);
-	len += sprintf( buf+len, "connected: %s ", 
-			self->connected ? "TRUE": "FALSE");
+	len += sprintf( buf+len, "state: %s ", irobex_state[ self->state]);
X 	len += sprintf( buf+len, "EOF: %s\n", self->eof ? "TRUE": "FALSE");
X 	
X 	return len;
@@ -1075,12 +1091,8 @@
X  */
X int init_module(void) 
X {
-	DEBUG( 4, "--> irobex: init_module\n");
-	
X 	irobex_init();
X 	
-	DEBUG( 4, "irobex: init_module -->\n");	
-	
X 	return 0;
X }
X 
@@ -1092,15 +1104,12 @@
X  */
X void cleanup_module(void) 
X {
-	DEBUG( 4, "--> irobex, cleanup_module\n");
X 	/* 
X 	 *  No need to check MOD_IN_USE, as sys_delete_module() checks. 
X 	 */
X 	
X 	/* Free some memory */
-	irobex_cleanup();
-	
-	DEBUG( 4, "irobex, cleanup_module -->\n");
+	irobex_cleanup();	
X }
X 
X #endif /* MODULE */
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irproc.c linux/net/irda/irproc.c
--- v2.2.0-pre8/linux/net/irda/irproc.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irproc.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Thomas Davis, <rat...@radiks.net>
X  * Created at:    Sat Feb 21 21:33:24 1998
- * Modified at:   Wed Dec  9 02:26:45 1998
+ * Modified at:   Tue Dec 15 09:21:50 1998
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998, Thomas Davis, <rat...@radiks.net>, 
@@ -330,7 +330,6 @@
X 		return len;
X 
X 	len = sprintf(buf, "IrLMP: Discovery log:\n\n");	
-
X 
X 	save_flags(flags);
X 	cli();
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irqueue.c linux/net/irda/irqueue.c
--- v2.2.0-pre8/linux/net/irda/irqueue.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irqueue.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Tue Jun  9 13:29:31 1998
- * Modified at:   Mon Dec 14 20:11:07 1998
+ * Modified at:   Wed Jan 13 21:21:22 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (C) 1998, Aage Kvalnes <aa...@cs.uit.no>
@@ -49,7 +49,7 @@
X {
X 	hashbin_t* hashbin;
X 	
-	DEBUG( 4, "hashbin_create()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 	
X 	/*
X 	 * Allocate new hashbin
@@ -353,19 +353,19 @@
X }
X 
X 
-/*
- * Function hashbin_remove (hashbin, name)
+/* 
+ *  Function hashbin_remove (hashbin, hashv, name)
X  *
X  *    Remove entry with the given name
X  *
X  */
X void* hashbin_remove( hashbin_t* hashbin, __u32 hashv, char* name)
X {
-	int   bin, found = FALSE;
+	int bin, found = FALSE;
X 	unsigned long flags = 0;
X 	QUEUE* entry;
X 
-	DEBUG( 4, "hashbin_remove()\n");
+	DEBUG( 4, __FUNCTION__ "()\n");
X 
X 	ASSERT( hashbin != NULL, return NULL;);
X 	ASSERT( hashbin->magic == HB_MAGIC, return NULL;);
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irsysctl.c linux/net/irda/irsysctl.c
--- v2.2.0-pre8/linux/net/irda/irsysctl.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/irsysctl.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun May 24 22:12:06 1998
- * Modified at:   Wed Dec  9 01:29:22 1998
+ * Modified at:   Thu Jan  7 10:35:02 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1997 Dag Brattli, All Rights Reserved.
@@ -27,13 +27,19 @@
X #include <linux/sysctl.h>
X #include <asm/segment.h>
X 
+#include <net/irda/irda.h>
+
X #define NET_IRDA 412 /* Random number */
-enum { DISCOVERY=1, DEVNAME, COMPRESSION };
+enum { DISCOVERY=1, DEVNAME, COMPRESSION, DEBUG };
X 
X extern int sysctl_discovery;
X int sysctl_compression = 0;
X extern char sysctl_devname[];
X 
+#ifdef CONFIG_IRDA_DEBUG
+extern unsigned int irda_debug;
+#endif
+
X /* One file */
X static ctl_table irda_table[] = {
X 	{ DISCOVERY, "discovery", &sysctl_discovery,
@@ -42,6 +48,10 @@
X 	  65, 0644, NULL, &proc_dostring, &sysctl_string},
X 	{ COMPRESSION, "compression", &sysctl_compression,
X 	  sizeof(int), 0644, NULL, &proc_dointvec },
+#ifdef CONFIG_IRDA_DEBUG
+	{ DEBUG, "debug", &irda_debug,
+	  sizeof(int), 0644, NULL, &proc_dointvec },
+#endif
X 	{ 0 }
X };
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/irttp.c linux/net/irda/irttp.c
--- v2.2.0-pre8/linux/net/irda/irttp.c	Wed Jan 13 15:00:44 1999
+++ linux/net/irda/irttp.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Sun Aug 31 20:14:31 1997
- * Modified at:   Mon Dec 14 11:53:19 1998
+ * Modified at:   Tue Jan 19 23:56:58 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
@@ -290,8 +290,6 @@
X 	ASSERT( self->magic == TTP_TSAP_MAGIC, return -1;);
X 	ASSERT( skb != NULL, return -1;);
X 
-	IS_SKB( skb, return -1;);
-
X 	/* Check that nothing bad happens */
X 	if (( skb->len == 0) || ( !self->connected)) {
X 		DEBUG( 4, __FUNCTION__ "(), No data, or not connected\n");
@@ -1044,12 +1042,12 @@
X 	DEBUG( 4, "irttp_disconnect_indication()\n");
X 
X 	self = ( struct tsap_cb *) instance;
-
+	
X 	ASSERT( self != NULL, return;);
X 	ASSERT( self->magic == TTP_TSAP_MAGIC, return;);
-
+	
X 	self->connected = FALSE;
-
+	
X 	/* 
X 	 *  Use callback to notify layer above 
X 	 */
@@ -1207,7 +1205,6 @@
X {
X 	struct sk_buff *skb, *frag;
X 	int n = 0;  /* Fragment index */
-	int i = 1;  /* Fragment nr */
X 
X       	ASSERT( self != NULL, return NULL;);
X 	ASSERT( self->magic == TTP_TSAP_MAGIC, return NULL;);
@@ -1227,11 +1224,9 @@
X 	 *  Copy all fragments to a new buffer
X 	 */
X 	while (( frag = skb_dequeue( &self->rx_fragments)) != NULL) {
-		DEBUG( 4, __FUNCTION__ "(), copying fragment %d with len=%d\n",
-		       i++, (int) frag->len);
X 		memcpy( skb->data+n, frag->data, frag->len);
X 		n += frag->len;
-
+		
X 		dev_kfree_skb( frag);
X 	}
X 	DEBUG( 4, __FUNCTION__ "(), frame len=%d\n", n);
@@ -1256,7 +1251,6 @@
X {
X 	struct sk_buff *frag;
X 	__u8 *frame;
-	int i = 0;
X 
X 	DEBUG( 4, __FUNCTION__ "()\n");
X 
@@ -1306,10 +1300,6 @@
X 		/* Hide the copied data from the original skb */
X 		skb_pull( skb, self->max_seg_size);
X 		
-		/* Queue segment */
-		DEBUG( 4, __FUNCTION__ "(), queuing segment %d with len=%d\n", 
-		       i++, (int) frag->len);
-
X 		skb_queue_tail( &self->tx_queue, frag);
X 	}
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
--- v2.2.0-pre8/linux/net/irda/wrapper.c	Tue Dec 22 14:16:59 1998
+++ linux/net/irda/wrapper.c	Wed Jan 20 11:05:33 1999
@@ -6,7 +6,7 @@
X  * Status:        Experimental.
X  * Author:        Dag Brattli <da...@cs.uit.no>
X  * Created at:    Mon Aug  4 20:40:53 1997
- * Modified at:   Wed Dec  9 01:35:53 1998
+ * Modified at:   Sat Jan 16 22:05:45 1999
X  * Modified by:   Dag Brattli <da...@cs.uit.no>
X  * 
X  *     Copyright (c) 1998 Dag Brattli <da...@cs.uit.no>, 
@@ -110,18 +110,16 @@
X #endif
X 	tx_buff[n++] = EOF;
X 	
-	DEBUG( 6, "async_wrap() -->\n");
-	
X 	return n;
X }
X 
X /*
- * Function async_bump (irdev)
+ * Function async_bump (idev)
X  *
X  *    Got a frame, make a copy of it, and pass it up the stack!
X  *
X  */
-static __inline__ void async_bump( struct irda_device *irdev, __u8 *buf, 
+static __inline__ void async_bump( struct irda_device *idev, __u8 *buf, 
X 				   int len)
X {
X        	struct sk_buff *skb;
@@ -130,36 +128,31 @@
X 	if (skb == NULL)  {
X 		printk( KERN_INFO __FUNCTION__ "() memory squeeze, " 
X 			"dropping frame.\n");
-		irdev->stats.rx_dropped++;
+		idev->stats.rx_dropped++;
X 		return;
X 	}
X 
X 	/*  Align to 20 bytes */
X 	skb_reserve( skb, 1);
X 	
-	/* For finding out how much time we use to
-	   send a frame */
-	do_gettimeofday( &skb->stamp);
-
X 	ASSERT( len-2 > 0, return;);
X 
X         /* Copy data without CRC */
X 	skb_put( skb, len-2);
X 	memcpy( skb->data, buf, len-2); 
X 	
-	irdev->rx_buff.len = 0;
+	idev->rx_buff.len = 0;
X 	/* 
X 	 *  Feed it to IrLAP layer 
X 	 */
X 	/* memcpy(skb_put(skb,count), ax->rbuff, count); */
-	skb->dev = &irdev->netdev;
+	skb->dev = &idev->netdev;
X 	skb->mac.raw  = skb->data;
X 	skb->protocol = htons(ETH_P_IRDA);
X 
X 	netif_rx( skb);
-	irdev->stats.rx_packets++;
-	
-        /* irlap_input( skb, skb->dev, NULL); */
+	idev->stats.rx_packets++;
+	idev->stats.rx_bytes += skb->len;	
X }
X  
X /*
@@ -168,18 +161,16 @@
X  *    Parse and de-stuff frame received from the IR-port
X  *
X  */
-void async_unwrap_char( struct irda_device *irdev, __u8 byte) 
+void async_unwrap_char( struct irda_device *idev, __u8 byte) 
X {
-	DEBUG( 6, "async_unwrap()\n");
-
X 	/* State machine for receiving frames */	   
-	switch( irdev->rx_buff.state) {
+	switch( idev->rx_buff.state) {
X 	case OUTSIDE_FRAME:
X 		if ( byte == BOF) {
-			irdev->rx_buff.state = BEGIN_FRAME;
-			irdev->rx_buff.in_frame = TRUE;
+			idev->rx_buff.state = BEGIN_FRAME;
+			idev->rx_buff.in_frame = TRUE;
X 		} else if ( byte == EOF) {
-			irda_device_set_media_busy( irdev, TRUE);
+			irda_device_set_media_busy( idev, TRUE);
X 		}
X 		break;
X 	case BEGIN_FRAME:
@@ -189,20 +180,22 @@
X 			break;
X 		case CE:
X 			/* Stuffed byte */
-			irdev->rx_buff.state = LINK_ESCAPE;
+			idev->rx_buff.state = LINK_ESCAPE;
X 			break;
X 		case EOF:
X 			/* Abort frame */
-			DEBUG( 0, "Frame abort (1)\n");
-			irdev->rx_buff.state = OUTSIDE_FRAME;
+			idev->rx_buff.state = OUTSIDE_FRAME;
+
+			idev->stats.rx_errors++;
+			idev->stats.rx_frame_errors++;
X 			break;
X 		default:
X 			/* Got first byte of frame */
-			if ( irdev->rx_buff.len < irdev->rx_buff.truesize)  {
-				irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
+				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
X 			
-				irdev->rx_buff.fcs = IR_FCS ( INIT_FCS, byte);
-				irdev->rx_buff.state = INSIDE_FRAME;
+				idev->rx_buff.fcs = IR_FCS( INIT_FCS, byte);
+				idev->rx_buff.state = INSIDE_FRAME;
X 			} else 
X 				printk( "Rx buffer overflow\n");
X 			break;
@@ -213,9 +206,9 @@
X 		case BOF:
X 			/* New frame? */
X 			DEBUG( 4, "New frame?\n");
-			irdev->rx_buff.state = BEGIN_FRAME;
-			irdev->rx_buff.len = 0;
-			irda_device_set_media_busy( irdev, TRUE);
+			idev->rx_buff.state = BEGIN_FRAME;
+			idev->rx_buff.len = 0;
+			irda_device_set_media_busy( idev, TRUE);
X 			break;
X 		case CE:
X 			DEBUG( 4, "WARNING: State not defined\n");
@@ -223,8 +216,8 @@
X 		case EOF:
X 			/* Abort frame */
X 			DEBUG( 0, "Abort frame (2)\n");
-			irdev->rx_buff.state = OUTSIDE_FRAME;
-			irdev->rx_buff.len = 0;
+			idev->rx_buff.state = OUTSIDE_FRAME;
+			idev->rx_buff.len = 0;
X 			break;
X 		default:
X 			/* 
@@ -232,11 +225,11 @@
X 			 *  following CE, IrLAP p.114 
X 			 */
X 			byte ^= IR_TRANS;
-			if ( irdev->rx_buff.len < irdev->rx_buff.truesize)  {
-				irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
+				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
X 			
-				irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte);
-				irdev->rx_buff.state = INSIDE_FRAME;
+				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
+				idev->rx_buff.state = INSIDE_FRAME;
X 			} else 
X 				printk( "Rx buffer overflow\n");
X 			break;
@@ -246,41 +239,40 @@
X 		switch ( byte) {
X 		case BOF:
X 			/* New frame? */
-			DEBUG( 4, "New frame?\n");
-			irdev->rx_buff.state = BEGIN_FRAME;
-			irdev->rx_buff.len = 0;
-			irda_device_set_media_busy( irdev, TRUE);
+			idev->rx_buff.state = BEGIN_FRAME;
+			idev->rx_buff.len = 0;
+			irda_device_set_media_busy( idev, TRUE);
X 			break;
X 		case CE:
X 			/* Stuffed char */
-			irdev->rx_buff.state = LINK_ESCAPE;
+			idev->rx_buff.state = LINK_ESCAPE;
X 			break;
X 		case EOF:
X 			/* End of frame */
-			irdev->rx_buff.state = OUTSIDE_FRAME;
-			irdev->rx_buff.in_frame = FALSE;
+			idev->rx_buff.state = OUTSIDE_FRAME;
+			idev->rx_buff.in_frame = FALSE;
X 			
X 			/* 
X 			 *  Test FCS and deliver frame if it's good
X 			 */			
-			if ( irdev->rx_buff.fcs == GOOD_FCS) {
-				async_bump( irdev, irdev->rx_buff.data, 
-					    irdev->rx_buff.len);
+			if ( idev->rx_buff.fcs == GOOD_FCS) {
+				async_bump( idev, idev->rx_buff.data, 
+					    idev->rx_buff.len);
X 			} else {
-				/* 
-				 *  Wrong CRC, discard frame! 
-				 */
-				DEBUG( 0, "Received frame has wrong CRC\n");
-				irda_device_set_media_busy( irdev, TRUE); 
-				irdev->rx_buff.len = 0;
+				/* Wrong CRC, discard frame!  */
+				irda_device_set_media_busy( idev, TRUE); 
+				idev->rx_buff.len = 0;
+
+				idev->stats.rx_errors++;
+				idev->stats.rx_crc_errors++;
X 			}			
X 			break;
X 		default:
X 			/* Next byte of frame */
-			if ( irdev->rx_buff.len < irdev->rx_buff.truesize)  {
-				irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+			if ( idev->rx_buff.len < idev->rx_buff.truesize)  {
+				idev->rx_buff.data[ idev->rx_buff.len++] = byte;
X 				
-				irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte);
+				idev->rx_buff.fcs = IR_FCS( idev->rx_buff.fcs, byte);
X 			} else 
X 				printk( "Rx buffer overflow\n");
X 			break;
diff -u --recursive --new-file v2.2.0-pre8/linux/net/sunrpc/xprt.c linux/net/sunrpc/xprt.c
--- v2.2.0-pre8/linux/net/sunrpc/xprt.c	Tue Jan 19 11:32:53 1999
+++ linux/net/sunrpc/xprt.c	Wed Jan 20 13:44:53 1999
@@ -655,10 +655,7 @@
X 		reclen = ntohl(xprt->tcp_reclen);
X 		dprintk("RPC:      reclen %08x\n", reclen);
X 		xprt->tcp_more = (reclen & 0x80000000)? 0 : 1;
-		if (!(reclen &= 0x7fffffff)) {
-			printk(KERN_NOTICE "RPC:      empty TCP record.\n");
-			return -ENOTCONN;	/* break connection */
-		}
+		reclen &= 0x7fffffff;
X 		xprt->tcp_total += reclen;
X 		xprt->tcp_reclen = reclen;
X 
diff -u --recursive --new-file v2.2.0-pre8/linux/scripts/tkcond.c linux/scripts/tkcond.c
--- v2.2.0-pre8/linux/scripts/tkcond.c	Mon Jan  4 15:08:18 1999
+++ linux/scripts/tkcond.c	Wed Jan 20 10:05:49 1999
@@ -1,544 +1,359 @@
-/* parser config.in
- *
- * Version 1.0
- * Eric Youngdale
- * 10/95
- *
- * The general idea here is that we want to parse a config.in file and 
- * from this, we generate a wish script which gives us effectively the
- * same functionality that the original config.in script provided.
- *
- * This task is split roughly into 3 parts.  The first parse is the parse
- * of the input file itself.  The second part is where we analyze the 
- * #ifdef clauses, and attach a linked list of tokens to each of the
- * menu items.  In this way, each menu item has a complete list of
- * dependencies that are used to enable/disable the options.
- * The third part is to take the configuration database we have build,
- * and build the actual wish script.
- *
- * This file contains the code to further process the conditions from
- * the "ifdef" clauses.
+/*
+ * tkcond.c
X  *
- * The conditions are assumed to be one of the following formats
+ * Eric Youngdale was the original author of xconfig.
+ * Michael Elizabeth Chastain (m...@shout.net) is the current maintainer.
X  *
- * simple_condition:= "$VARIABLE" == y/n/m
- * simple_condition:= "$VARIABLE != y/n/m
+ * This file takes the tokenized statement list and transforms 'if ...'
+ * statements.  For each simple statement, I find all of the 'if' statements
+ * that enclose it, and attach the aggregate conditionals of those 'if'
+ * statements to the cond list of the simple statement.
X  *
- * simple_condition -a simple_condition
+ * 14 January 1999, Michael Elizabeth Chastain, <m...@shout.net>
+ * - Steam-clean this file.  I tested this by generating kconfig.tk for
+ *   every architecture and comparing it character-for-character against
+ *   the output of the old tkparse.
X  *
- * If the input condition contains '(' or ')' it would screw us up, but for now
- * this is not a problem.
+ * TO DO:
+ * - xconfig is at the end of its life cycle.  Contact <m...@shout.net> if
+ *   you are interested in working on the replacement.
X  */
-#include <stdlib.h>
+
X #include <stdio.h>
+#include <stdlib.h>
X #include <string.h>
-#include "tkparse.h"
-
-
-/*
- * Walk a condition chain and invert it so that the logical result is
- * inverted.
- */
-static void invert_condition(struct condition * cnd)
-{
-  /*
-   * This is simple.  Just walk through the list, and invert
-   * all of the operators.
-   */
-  for(;cnd; cnd = cnd->next)
-    {
-      switch(cnd->op)
-	{
-	case op_and:
-	  cnd->op = op_or;
-	  break;
-	case op_or:
-	  /*
-	   * This is not turned into op_and - we need to keep track
-	   * of what operators were used here since we have an optimization
-	   * later on to remove duplicate conditions, and having
-	   * inverted ors in there would make it harder if we did not
-	   * distinguish an inverted or from an and we inserted because
-	   * of nested ifs.
-	   */
-	  cnd->op = op_and1;
-	  break;
-	case op_neq:
-	  cnd->op = op_eq;
-	  break;
-	case op_eq:
-	  cnd->op = op_neq;
-	  break;
-	default:
-	  break;
-	}
-    }
-}
X 
-/*
- * Walk a condition chain, and free the memory associated with it.
- */
-static void free_condition(struct condition * cnd)
-{
-  struct condition * next;
-  for(;cnd; cnd = next)
-    {
-      next = cnd->next;
+#include "tkparse.h"
X 
-      if( cnd->variable.str != NULL )
-	free(cnd->variable.str);
X 
-      free(cnd);
-    }
-}
X 
X /*
- * Walk all of the conditions, and look for choice values.  Convert
- * the tokens into something more digestible.
+ * Transform op_variable to op_kvariable.
+ *
+ * This works, but it's gross, speed-wise.  It would benefit greatly
+ * from a simple hash table that maps names to cfg.
+ *
+ * Note well: this is actually better than the loop structure xconfig
+ * has been staggering along with for three years, which performs
+ * this whole procedure inside *another* loop on active conditionals.
X  */
-void fix_choice_cond(void)
+void transform_to_kvariable( struct kconfig * scfg )
X {
-  struct condition * cond;
-  struct condition * cond2;
-  struct kconfig * cfg;
-  char tmpbuf[255];
+    struct kconfig * cfg;
X 
-  for(cfg = config;cfg != NULL; cfg = cfg->next)
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      if( cfg->cond == NULL )
-	{
-	  continue;
-	}
+	struct condition * cond;
X 
-      for(cond = cfg->cond; cond != NULL; cond = cond->next)
+	for ( cond = cfg->cond; cond != NULL; cond = cond->next )
X 	{
-	  if( cond->op != op_kvariable )
-	    continue;
-
-	  if( cond->variable.cfg->tok != tok_choice )
-	    continue;
-
-	  /*
-	   * Look ahead for what we are comparing this to.  There should
-	   * be one operator in between.
-	   */
-	  cond2 = cond->next->next;
-	  strcpy(tmpbuf, cond->variable.cfg->label);
-
-	  if( strcmp(cond2->variable.str, "y") == 0 )
+	    if ( cond->op == op_variable )
X 	    {
-	      cond->variable.cfg = cond->variable.cfg->choice_label;
-	      cond2->variable.str = strdup(tmpbuf);
+		/* Here's where it gets DISGUSTING. */
+		struct kconfig * cfg1;
+
+		for ( cfg1 = scfg; cfg1 != NULL; cfg1 = cfg1->next )
+		{
+		    if ( cfg1->token == token_bool
+		    ||   cfg1->token == token_choice_item
+		    ||   cfg1->token == token_dep_tristate
+		    ||   cfg1->token == token_hex
+		    ||   cfg1->token == token_int
+		    ||   cfg1->token == token_string
+		    ||   cfg1->token == token_tristate )
+		    {
+			if ( strcmp( cond->str, cfg1->optionname ) == 0 )
+			{
+			    cond->op  = op_kvariable;
+			    cond->str = NULL;
+			    cond->cfg = cfg1;
+			    break;
+			}
+		    }
+		}
X 	    }
-	  else
+
+#if 0
+	    /*
+	     * Maybe someday this will be useful, but right now it
+	     * gives a lot of false positives on files like
+	     * drivers/video/Config.in that are meant for more
+	     * than one architecture.  Turn it on if you want to play
+	     * with it though; it does work.  -- mec
+	     */
+	    if ( cond->op == op_variable )
X 	    {
-	      fprintf(stderr,"tkparse can't handle this conditional\n");
-	      exit(1);
+		if ( strcmp( cond->str, "ARCH"       ) != 0
+		&&   strcmp( cond->str, "CONSTANT_Y" ) != 0
+		&&   strcmp( cond->str, "CONSTANT_M" ) != 0
+		&&   strcmp( cond->str, "CONSTANT_N" ) != 0 )
+		{
+		    fprintf( stderr, "warning: $%s used but not defined\n",
+			cond->str );
+		}
X 	    }
+#endif
X 	}
-
X     }
X }
X 
+
+
X /*
- * Walk the stack of conditions, and clone all of them with "&&" operators
- * gluing them together.  The conditions from each level of the stack
- * are wrapped in parenthesis so as to guarantee that the results
- * are logically correct.
+ * Make a new condition chain by joining the current condition stack with
+ * the "&&" operator for glue.
X  */
-struct condition * get_token_cond(struct condition ** cond, int depth)
+struct condition * join_condition_stack( struct condition * conditions [],
+    int depth )
X {
-  int i;
-  struct condition * newcond;
-  struct condition * tail;
-  struct condition * new;
-  struct condition * ocond;
-  struct kconfig * cfg;
+    struct condition * cond_list;
+    struct condition * cond_last;
+    int i;
X 
-  newcond = tail = NULL;
-  for(i=0; i<depth; i++, cond++)
+    cond_list = cond_last = NULL;
+    for ( i = 0; i < depth; i++ )
X     {
-      /*
-       * First insert the left parenthesis
-       */
-      new = (struct condition *) malloc(sizeof(struct condition));
-      memset(new, 0, sizeof(*new));
-      new->op = op_lparen;
-      if( tail == NULL )
-	{
-	  newcond = tail = new;
-	}
-      else
-	{
-	  tail->next = new;
-	  tail = new;
+	struct condition * cond;
+	struct condition * cnew;
+
+	/* add a '(' */
+	cnew = malloc( sizeof(*cnew) );
+	memset( cnew, 0, sizeof(*cnew) );
+	cnew->op = op_lparen;
+	if ( cond_last == NULL )
+	    { cond_list = cond_last = cnew; }
+	else
+	    { cond_last->next = cnew; cond_last = cnew; }
+
+	/* duplicate the chain */
+	for ( cond = conditions [i]; cond != NULL; cond = cond->next )
+	{
+	    cnew            = malloc( sizeof(*cnew) );
+	    cnew->next      = NULL;
+	    cnew->op        = cond->op;
+	    cnew->str       = cond->str ? strdup( cond->str ) : NULL;
+	    cnew->cfg       = cond->cfg;
+	    cond_last->next = cnew;
+	    cond_last       = cnew;
+	}
+
+	/* add a ')' */
+	cnew = malloc( sizeof(*cnew) );
+	memset( cnew, 0, sizeof(*cnew) );
+	cnew->op = op_rparen;
+	cond_last->next = cnew;
+	cond_last = cnew;
+
+	/* if i have another condition, add an '&&' operator */
+	if ( i < depth - 1 )
+	{
+	    cnew = malloc( sizeof(*cnew) );
+	    memset( cnew, 0, sizeof(*cnew) );
+	    cnew->op = op_and;
+	    cond_last->next = cnew;
+	    cond_last = cnew;
X 	}
+    }
X 
-      /*
-       * Now duplicate the chain.
-       */
-      ocond = *cond;
-      for(;ocond != NULL; ocond = ocond->next)
+    /*
+     * Remove duplicate conditions.
+     */
+    {
+	struct condition *cond1, *cond1b, *cond1c, *cond1d, *cond1e, *cond1f;
+
+	for ( cond1 = cond_list; cond1 != NULL; cond1 = cond1->next )
X 	{
-	  new = (struct condition *) malloc(sizeof(struct condition));
-	  memset(new, 0, sizeof(*new));
-	  new->op = ocond->op;
-	  if( ocond->variable.str != NULL )
+	    if ( cond1->op == op_lparen )
X 	    {
-	      if( ocond->op == op_variable )
+		cond1b = cond1 ->next; if ( cond1b == NULL ) break;
+		cond1c = cond1b->next; if ( cond1c == NULL ) break;
+		cond1d = cond1c->next; if ( cond1d == NULL ) break;
+		cond1e = cond1d->next; if ( cond1e == NULL ) break;
+		cond1f = cond1e->next; if ( cond1f == NULL ) break;
+
+		if ( cond1b->op == op_kvariable
+		&& ( cond1c->op == op_eq || cond1c->op == op_neq )
+		&&   cond1d->op == op_constant 
+		&&   cond1e->op == op_rparen )
X 		{
-		  /*
-		   * Search for structure to insert here.
-		   */
-		  for(cfg = config;cfg != NULL; cfg = cfg->next)
+		    struct condition *cond2, *cond2b, *cond2c, *cond2d, *cond2e, *cond2f;
+
+		    for ( cond2 = cond1f->next; cond2 != NULL; cond2 = cond2->next )
X 		    {
-		      if( cfg->tok != tok_bool
-		         && cfg->tok != tok_int
-		         && cfg->tok != tok_hex
-		         && cfg->tok != tok_string
-			 && cfg->tok != tok_tristate 
-			 && cfg->tok != tok_choice
-			 && cfg->tok != tok_dep_tristate)
+			if ( cond2->op == op_lparen )
X 			{
-			  continue;
+			    cond2b = cond2 ->next; if ( cond2b == NULL ) break;
+			    cond2c = cond2b->next; if ( cond2c == NULL ) break;
+			    cond2d = cond2c->next; if ( cond2d == NULL ) break;
+			    cond2e = cond2d->next; if ( cond2e == NULL ) break;
+			    cond2f = cond2e->next;
+
+			    /* look for match */
+			    if ( cond2b->op == op_kvariable
+			    &&   cond2b->cfg == cond1b->cfg
+			    &&   cond2c->op == cond1c->op
+			    &&   cond2d->op == op_constant
+			    &&   strcmp( cond2d->str, cond1d->str ) == 0
+			    &&   cond2e->op == op_rparen )
+			    {
+				/* one of these must be followed by && */
+				if ( cond1f->op == op_and
+				|| ( cond2f != NULL && cond2f->op == op_and ) )
+				{
+				    /* nuke the first duplicate */
+				    cond1 ->op = op_nuked;
+				    cond1b->op = op_nuked;
+				    cond1c->op = op_nuked;
+				    cond1d->op = op_nuked;
+				    cond1e->op = op_nuked;
+				    if ( cond1f->op == op_and )
+					cond1f->op = op_nuked;
+				    else
+					cond2f->op = op_nuked;
+				}
+			    }
X 			}
-		      if( strcmp(cfg->optionname, ocond->variable.str) == 0)
-			{
-			  new->variable.cfg = cfg;
-			  new->op = op_kvariable;
-			  break;
-			}
-		    }
-		  if( cfg == NULL )
-		    {
-		      new->variable.str = strdup(ocond->variable.str);
X 		    }
X 		}
-	      else
-		{
-		  new->variable.str = strdup(ocond->variable.str);
-		}
X 	    }
-	  tail->next = new;
-	  tail = new;
X 	}
-
-      /*
-       * Next insert the left parenthesis
-       */
-      new = (struct condition *) malloc(sizeof(struct condition));
-      memset(new, 0, sizeof(*new));
-      new->op = op_rparen;
-      tail->next = new;
-      tail = new;
-
-      /*
-       * Insert an and operator, if we have another condition.
-       */
-      if( i < depth - 1 )
-	{
-	  new = (struct condition *) malloc(sizeof(struct condition));
-	  memset(new, 0, sizeof(*new));
-	  new->op = op_and;
-	  tail->next = new;
-	  tail = new;
-	}
-
X     }
X 
-  return newcond;
+    return cond_list;
X }
X 
-/*
- * Walk a single chain of conditions and clone it.  These are assumed
- * to be created/processed by  get_token_cond in a previous pass.
- */
-struct condition * get_token_cond_frag(struct condition * cond, 
-				       struct condition ** last)
-{
-  struct condition * newcond;
-  struct condition * tail;
-  struct condition * new;
-  struct condition * ocond;
-
-  newcond = tail = NULL;
-
-  /*
-   * Now duplicate the chain.
-   */
-  for(ocond = cond;ocond != NULL; ocond = ocond->next)
-    {
-      new = (struct condition *) malloc(sizeof(struct condition));
-      memset(new, 0, sizeof(*new));
-      new->op = ocond->op;
-      new->variable.cfg = ocond->variable.cfg;
-      if( tail == NULL )
-	{
-	  newcond = tail = new;
-	}
-      else
-	{
-	  tail->next = new;
-	  tail = new;
-	}
-    }
X 
-  new = (struct condition *) malloc(sizeof(struct condition));
-  memset(new, 0, sizeof(*new));
-  new->op = op_and;
-  tail->next = new;
-  tail = new;
-  
-  *last = tail;
-  return newcond;
-}
X 
X /*
- * Walk through the if conditionals and maintain a chain.
+ * This is the main transformation function.
X  */
-void fix_conditionals(struct kconfig * scfg)
+void fix_conditionals( struct kconfig * scfg )
X {
-  int depth = 0;
-  int i;
-  struct kconfig * cfg;
-  struct kconfig * cfg1;
-  struct condition * conditions[25];
-  struct condition * cnd;
-  struct condition * cnd1;
-  struct condition * cnd2;
-  struct condition * cnd3;
-  struct condition * newcond;
-  struct condition * last;
-
-  /*
-   * Start by walking the chain.  Every time we see an ifdef, push
-   * the condition chain on the stack.  When we see an "else", we invert
-   * the condition at the top of the stack, and when we see an "endif"
-   * we free all of the memory for the condition at the top of the stack
-   * and remove the condition from the top of the stack.
-   *
-   * For any other type of token (i.e. a bool), we clone a new condition chain
-   * by anding together all of the conditions that are currently stored on
-   * the stack.  In this way, we have a correct representation of whatever
-   * conditions govern the usage of each option.
-   */
-  memset(conditions, 0, sizeof(conditions));
-  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
-    {
-      switch(cfg->tok)
-	{
-	case tok_if:
-	  /*
-	   * Push this condition on the stack, and nuke the token
-	   * representing the ifdef, since we no longer need it.
-	   */
-	  conditions[depth] = cfg->cond;
-	  depth++;
-	  cfg->tok = tok_nop;
-	  cfg->cond =  NULL;
-	  break;
-	case tok_else:
-	  /*
-	   * For an else, we just invert the condition at the top of
-	   * the stack.  This is done in place with no reallocation
-	   * of memory taking place.
-	   */
-	  invert_condition(conditions[depth-1]);
-	  cfg->tok = tok_nop;
-	  break;
-	case tok_fi:
-	  depth--;
-	  free_condition(conditions[depth]);
-	  conditions[depth] = NULL;
-	  cfg->tok = tok_nop;
-	  break;
-	case tok_comment:
-	case tok_define:
-	case tok_menuoption:
-	case tok_bool:
-	case tok_tristate:
-	case tok_int:
-	case tok_hex:
-	case tok_string:
-	case tok_choice:
-	  /*
-	   * We need to duplicate the chain of conditions and attach them to
-	   * this token.
-	   */
-	  cfg->cond = get_token_cond(&conditions[0], depth);
-	  break;
-	case tok_dep_tristate:
-	  /*
-	   * Same as tok_tristate et al except we have a temporary
-	   * conditional. (Sort of a hybrid tok_if, tok_tristate, tok_fi
-	   * option)
-	   */
-	  conditions[depth] = cfg->cond;
-	  depth++;
-	  cfg->cond = get_token_cond(&conditions[0], depth);
-	  depth--;
-	  free_condition(conditions[depth]);
-	  conditions[depth] = NULL;
-	default:
-	  break;
-	}
-    }
+    struct kconfig * cfg;
X 
-  /*
-   * Fix any conditions involving the "choice" operator.
-   */
-  fix_choice_cond();
-
-  /*
-   * Walk through and see if there are multiple options that control the
-   * same kvariable.  If there are we need to treat them a little bit
-   * special.
-   */
-  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+    /*
+     * Transform op_variable to op_kvariable.
+     */
+    transform_to_kvariable( scfg );
+
+    /*
+     * Transform conditions that use variables from "choice" statements.
+     * Choice values appear to the user as a collection of booleans, and the
+     * script can test the individual booleans.  But internally, all I have is
+     * the N-way value of an unnamed temporary for the whole statement.  So I
+     * have to tranform '"$CONFIG_M386" != "y"'
+     * into '"$tmpvar_N" != "CONFIG_M386"'.
+     */
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      switch(cfg->tok)
+	struct condition * cond;
+
+	for ( cond = cfg->cond; cond != NULL; cond = cond->next )
X 	{
-	case tok_bool:
-	case tok_tristate:
-	case tok_dep_tristate:
-	case tok_int:
-	case tok_hex:
-	case tok_string:
-	  for(cfg1=cfg;cfg1 != NULL; cfg1 = cfg1->next)
+	    if ( cond->op == op_kvariable && cond->cfg->token == token_choice_item )
X 	    {
-	      switch(cfg1->tok)
+		/*
+		 * Look two more tokens down for the comparison token.
+		 * It has to be "y" for this trick to work.
+		 *
+		 * If you get this error, don't even think about relaxing the
+		 * strcmp test.  You will produce incorrect TK code.  Instead,
+		 * look for the place in your Config.in script where you are
+		 * comparing a 'choice' variable to a value other than 'y',
+		 * and rewrite the comparison to be '= "y"' or '!= "y"'.
+		 */
+		struct condition * cond2 = cond->next->next;
+		const char * label;
+
+		if ( strcmp( cond2->str, "y" ) != 0 )
X 		{
-		case tok_define:
-		case tok_bool:
-		case tok_tristate:
-		case tok_dep_tristate:
-		case tok_int:
-		case tok_hex:
-		case tok_string:
-		  if( strcmp(cfg->optionname, cfg1->optionname) == 0)
-		    {
-		      cfg->flags |= CFG_DUP;
-		      cfg1->flags |= CFG_DUP;
-		    }
-		  break;
-		default:
-		  break;
+		    fprintf( stderr, "tkparse choked in fix_choice_cond\n" );
+		    exit( 1 );
X 		}
+
+		label = cond->cfg->label;
+		cond->cfg  = cond->cfg->cfg_parent;
+		cond2->str = strdup( label );
X 	    }
-	  break;
-	default:
-	  break;
X 	}
X     }
X 
-  /*
-   * Now go through the list, and every time we see a kvariable, check
-   * to see whether it also has some dependencies.  If so, then
-   * append it to our list.  The reason we do this is that we might have
-   * option CONFIG_FOO which is only used if CONFIG_BAR is set.  It may
-   * turn out that in config.in that the default value for CONFIG_BAR is
-   * set to "y", but that CONFIG_BAR is not enabled because CONFIG_XYZZY
-   * is not set.  The current condition chain does not reflect this, but
-   * we can fix this by searching for the tokens that this option depends
-   * upon and cloning the conditions and merging them with the list.
-   */
-  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
+    /*
+     * Walk the statement list, maintaining a stack of current conditions.
+     *   token_if      push its condition onto the stack.
+     *   token_else    invert the condition on the top of the stack.
+     *   token_endif   pop the stack.
+     *
+     * For a simple statement, create a condition chain by joining together
+     * all of the conditions on the stack.
+     */
X     {
-      /*
-       * Search for a token that has a condition list.
-       */
-      if(cfg->cond == NULL) continue;
-      for(cnd = cfg->cond; cnd; cnd=cnd->next)
-	{
-	  /*
-	   * Now search the condition list for a known configuration variable
-	   * that has conditions of its own.
-	   */
-	  if(cnd->op != op_kvariable) continue;
-	  if(cnd->variable.cfg->cond == NULL) continue;
-
-	  if(cnd->variable.cfg->flags & CFG_DUP) continue; 
-	  /*
-	   * OK, we have some conditions to append to cfg.  Make  a clone
-	   * of the conditions,
-	   */
-	  newcond = get_token_cond_frag(cnd->variable.cfg->cond, &last);
-
-	  /*
-	   * Finally, we splice it into our list.
-	   */
-	  last->next = cfg->cond;
-	  cfg->cond = newcond;
+	struct condition * cond_stack [32];
+	int depth = 0;
X 
-	}
-    }
-
-  /*
-   * There is a strong possibility that we have duplicate conditions
-   * in here.  It would make the script more efficient and readable to
-   * remove these.  Here is where we assume here that there are no
-   * parenthesis in the input script.
-   */
-  for(cfg=scfg;cfg != NULL; cfg = cfg->next)
-    {
-      /*
-       * Search for configuration options that have conditions.
-       */
-      if(cfg->cond == NULL) continue;
-      for(cnd = cfg->cond; cnd; cnd=cnd->next)
+	for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X 	{
-	  /*
-	   * Search for a left parenthesis.
-	   */
-	  if(cnd->op != op_lparen) continue;
-	  for(cnd1 = cnd->next; cnd1; cnd1=cnd1->next)
+	    switch ( cfg->token )
X 	    {
-	      /*
-	       * Search after the previous left parenthesis, and try
-	       * and find a second left parenthesis.
-	       */
-	      if(cnd1->op != op_lparen) continue;
-
-	      /*
-	       * Now compare the next 5 tokens to see if they are
-	       * identical.  We are looking for two chains that
-	       * are like: '(' $VARIABLE operator constant ')'.
-	       */
-	      cnd2 = cnd;
-	      cnd3 = cnd1;
-	      for(i=0; i<5; i++, cnd2=cnd2->next, cnd3=cnd3->next)
-		{
-		  if(!cnd2 || !cnd3) break;
-		  if(cnd2->op != cnd3->op) break;
-		  if(i == 1 && (cnd2->op != op_kvariable 
-		     || cnd2->variable.cfg != cnd3->variable.cfg) ) break;
-		  if(i==2 && cnd2->op != op_eq && cnd2->op != op_neq) break;
-		  if(i == 3 && cnd2->op != op_constant &&
-		     strcmp(cnd2->variable.str, cnd3->variable.str) != 0)
-		    break;
-		  if(i==4 && cnd2->op != op_rparen) break;
-		}
-	      /*
-	       * If these match, and there is an and gluing these together,
-	       * then we can nuke the second one.
-	       */
-	      if(i==5 && ((cnd3 && cnd3->op == op_and)
-			  ||(cnd2 && cnd2->op == op_and)))
+	    default:
+		break;
+
+	    case token_if:
+		cond_stack [depth++] = cfg->cond;
+		cfg->cond = NULL;
+		break;
+
+	    case token_else:
X 		{
-		  /*
-		   * We have a duplicate.  Nuke 5 ops.
-		   */
-		  cnd3 = cnd1;
-		  for(i=0; i<5; i++, cnd3=cnd3->next)
+		    /*
+		     * Invert the condition chain.
+		     *
+		     * Be careful to transfrom op_or to op_and1, not op_and.
+		     * I will need this later in the code that removes
+		     * duplicate conditions.
+		     */
+		    struct condition * cond;
+
+		    for ( cond  = cond_stack [depth-1];
+			  cond != NULL;
+			  cond  = cond->next )
X 		    {
-		      cnd3->op = op_nuked;
+			switch( cond->op )
+			{
+			default:     break;
+			case op_and: cond->op = op_or;   break;
+			case op_or:  cond->op = op_and1; break;
+			case op_neq: cond->op = op_eq;   break;
+			case op_eq:  cond->op = op_neq;  break;
+			}
X 		    }
-		  /*
-		   * Nuke the and that glues the conditions together.
-		   */
-		  if(cnd3 && cnd3->op == op_and) cnd3->op = op_nuked;
-		  else if(cnd2 && cnd2->op == op_and) cnd2->op = op_nuked;
X 		}
+		break;
+
+	    case token_fi:
+		--depth;
+		break;
+
+	    case token_bool:
+	    case token_choice_item:
+	    case token_comment:
+	    case token_define_bool:
+	    case token_hex:
+	    case token_int:
+	    case token_mainmenu_option:
+	    case token_string:
+	    case token_tristate:
+		cfg->cond = join_condition_stack( cond_stack, depth );
+		break;
+
+	    case token_dep_tristate:
+		/*
+		 * Same as the other simple statements, plus an additional
+		 * condition for the dependency.
+		 */
+		cond_stack [depth] = cfg->cond;
+		cfg->cond = join_condition_stack( cond_stack, depth+1 );
+		break;
X 	    }
X 	}
X     }
diff -u --recursive --new-file v2.2.0-pre8/linux/scripts/tkgen.c linux/scripts/tkgen.c
--- v2.2.0-pre8/linux/scripts/tkgen.c	Tue Jan 19 11:32:53 1999
+++ linux/scripts/tkgen.c	Wed Jan 20 10:05:49 1999
@@ -77,1095 +77,970 @@
X  * 8 January 1999, Michael Elizabeth Chastain <m...@shout.net>
X  * - Emit menus_per_column
X  *
- * 1999 01 04
- * Michael Elizabeth Chastain <m...@shout.net>
- * - Call clear_globalflags when writing out update_mainmenu.
- *   This fixes the missing global/vfix lines for ARCH=alpha on 2.2.0-pre4.
- *
- * TO DO:
- *   - clean up - there are useless ifdef's everywhere.
- *   - better comments throughout - C code generating tcl is really cryptic.
- *   - eliminate silly "update idletasks" hack to improve display speed and
- *     reduce flicker.  But how?
- *   - make canvas contents resize with the window (good luck).
- *   - some way to make submenus inside of submenus (ie. Main->Networking->IP)
- *           (perhaps a button where the description would be)
- *   - make the main menu use the same tcl code as the submenus.
- *   - make choice and int/hex input types line up vertically with
- *           bool/tristate.
- *   - general speedups - how?  The canvas seems to slow it down a lot.
- *   - clean up +/- 16 confusion for enabling/disabling variables; causes
- *           (theoretical, at the moment) problems with dependencies.
- *   
+ * 14 January 1999, Michael Elizabeth Chastain <m...@shout.net>
+ * - Steam-clean this file.  I tested this by generating kconfig.tk for every
+ *   architecture and comparing it character-for-character against the output
+ *   of the old tkparse.
+ * - Fix flattening of nested menus.  The old code simply assigned items to
+ *   the most recent token_mainmenu_option, without paying attention to scope.
+ *   For example: "menu-1 bool-a menu-2 bool-b endmenu bool-c bool-d endmenu".
+ *   The old code would put bool-a in menu-1, bool-b in menu-2, and bool-c
+ *   and bool-d in *menu-2*.  This hosed the nested submenus in
+ *   drives/net/Config.in and other places.
+ * - Fix menu line wraparound at 128 menus (some fool used a 'char' for
+ *   a counter).
X  */
+
X #include <stdio.h>
X #include <unistd.h>
X #include "tkparse.h"
X 
-#ifndef TRUE
-#define TRUE (1)
-#endif
X 
-#ifndef FALSE
-#define FALSE (0)
-#endif
X 
X /*
- * This is the total number of submenus that we have.
+ * Total number of menus.
X  */
-static int tot_menu_num =0;
+static int tot_menu_num = 0;
+
+
X 
X /*
X  * Generate portion of wish script for the beginning of a submenu.
X  * The guts get filled in with the various options.
X  */
-static void start_proc(char * label, int menu_num, int flag)
+static void start_proc( char * label, int menu_num, int flag )
X {
-  if( flag )
-    printf("menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label);
-  printf("proc menu%d {w title} {\n", menu_num);
-  printf("\tcatch {destroy $w}\n");
-  printf("\ttoplevel $w -class Dialog\n");
-  printf("\twm withdraw $w\n");
-  printf("\tmessage $w.m -width 400 -aspect 300 -text \\\n");
-  printf("\t\t\"%s\"  -relief raised\n",label);
-  printf("\tpack $w.m -pady 10 -side top -padx 10\n");
-  printf("\twm title $w \"%s\" \n\n", label);
-  
-  /*
-   * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
-   */
-  printf("\tset oldFocus [focus]\n");
-  printf("\tframe $w.f\n");
-  printf("\tbutton $w.f.back -text \"Main Menu\" \\\n"
-         "\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n");
-  printf("\tbutton $w.f.next -text \"Next\" \\\n"
-         "\t\t-width 15 -command \" destroy $w; focus $oldFocus;  menu%d .menu%d \\\"$title\\\"\"\n",
-         	menu_num+1, menu_num+1);
-  if (menu_num == tot_menu_num)
-  	printf("\t$w.f.next configure -state disabled\n");
-  printf("\tbutton $w.f.prev -text \"Prev\" \\\n"
-         "\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n",
-       		menu_num-1, menu_num-1);
-  if (1 == menu_num)
-  	printf("\t$w.f.prev configure -state disabled\n");
-  printf("\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n");
-  printf("\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n");
-
-  /*
-   * Lines between canvas and other areas of the window.
-   */
-  printf("\tframe $w.topline -relief ridge -borderwidth 2 -height 2\n");
-  printf("\tpack $w.topline -side top -fill x\n\n");
-  printf("\tframe $w.botline -relief ridge -borderwidth 2 -height 2\n");
-  printf("\tpack $w.botline -side bottom -fill x\n\n");
-  
-  /*
-   * The "config" frame contains the canvas and a scrollbar.
-   */
-  printf("\tframe $w.config\n");
-  printf("\tpack $w.config -fill y -expand on\n\n");
-  printf("\tscrollbar $w.config.vscroll -command \"$w.config.canvas yview\"\n");
-  printf("\tpack $w.config.vscroll -side right -fill y\n\n");
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 13'
echo 'File patch-2.2.0-pre9 is continued in part 14'
echo 14 > _shar_seq_.tmp
#!/bin/sh
# this is part 14 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 14; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
-  
-  /*
-   * The scrollable canvas itself, where the real work (and mess) gets done.
-   */
-  printf("\tcanvas $w.config.canvas -height 1\\\n"
-  	 "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n"
-  	 "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n");
-  printf("\tframe $w.config.f\n");
-  printf("\tpack $w.config.canvas -side right -fill y\n");
-  
-  printf("\n\n");
+    if ( flag )
+	printf( "menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label );
+    printf( "proc menu%d {w title} {\n", menu_num );
+    printf( "\tcatch {destroy $w}\n" );
+    printf( "\ttoplevel $w -class Dialog\n" );
+    printf( "\twm withdraw $w\n" );
+    printf( "\tmessage $w.m -width 400 -aspect 300 -text \\\n" );
+    printf( "\t\t\"%s\"  -relief raised\n", label );
+    printf( "\tpack $w.m -pady 10 -side top -padx 10\n" );
+    printf( "\twm title $w \"%s\" \n\n", label );
+
+    /*
+     * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
+     */
+    printf( "\tset oldFocus [focus]\n" );
+    printf( "\tframe $w.f\n" );
+    printf( "\tbutton $w.f.back -text \"Main Menu\" \\\n" );
+    printf( "\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n" );
+    printf( "\tbutton $w.f.next -text \"Next\" \\\n" );
+    printf( "\t\t-width 15 -command \" destroy $w; focus $oldFocus;  menu%d .menu%d \\\"$title\\\"\"\n", menu_num+1, menu_num+1 );
+    if ( menu_num == tot_menu_num )
+	printf( "\t$w.f.next configure -state disabled\n" );
+    printf( "\tbutton $w.f.prev -text \"Prev\" \\\n" );
+    printf( "\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n", menu_num-1, menu_num-1 );
+    if ( menu_num == 1 )
+	printf( "\t$w.f.prev configure -state disabled\n" );
+    printf( "\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n" );
+    printf( "\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n" );
+
+    /*
+     * Lines between canvas and other areas of the window.
+     */
+    printf( "\tframe $w.topline -relief ridge -borderwidth 2 -height 2\n" );
+    printf( "\tpack $w.topline -side top -fill x\n\n" );
+    printf( "\tframe $w.botline -relief ridge -borderwidth 2 -height 2\n" );
+    printf( "\tpack $w.botline -side bottom -fill x\n\n" );
+
+    /*
+     * The "config" frame contains the canvas and a scrollbar.
+     */
+    printf( "\tframe $w.config\n" );
+    printf( "\tpack $w.config -fill y -expand on\n\n" );
+    printf( "\tscrollbar $w.config.vscroll -command \"$w.config.canvas yview\"\n" );
+    printf( "\tpack $w.config.vscroll -side right -fill y\n\n" );
+
+    /*
+     * The scrollable canvas itself, where the real work (and mess) gets done.
+     */
+    printf( "\tcanvas $w.config.canvas -height 1\\\n" );
+    printf( "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n" );
+    printf( "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n" );
+    printf( "\tframe $w.config.f\n" );
+    printf( "\tpack $w.config.canvas -side right -fill y\n" );
+    printf("\n\n");
X }
X 
+
+
X /*
X  * Each proc we create needs a global declaration for any global variables we
X  * use.  To minimize the size of the file, we set a flag each time we output
X  * a global declaration so we know whether we need to insert one for a
X  * given function or not.
X  */
-void clear_globalflags(struct kconfig * cfg)
+void clear_globalflags( struct kconfig * scfg )
X {
-  for(; cfg != NULL; cfg = cfg->next)
-  {
-    cfg->flags &= ~GLOBAL_WRITTEN;
-  }
+    struct kconfig * cfg;
+
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+ cfg->global_written = 0;
X }
X 
+
+
X /*
X  * Output a "global" line for a given variable.  Also include the
X  * call to "vfix".  (If vfix is not needed, then it's fine to just printf
X  * a "global" line).
X  */
-void inline global(char *var)
+void global( const char *var )
X {
-  printf("\tglobal %s; vfix %s\n", var, var);
+    printf( "\tglobal %s; vfix %s\n", var, var );
X }
X 
+
+
X /*
- * This function walks the chain of conditions that we got from cond.c,
- * and creates a wish conditional to enable/disable a given widget.
+ * This function walks the chain of conditions that we got from cond.c
+ * and creates a TCL conditional to enable/disable a given widget.
X  */
-void generate_if(struct kconfig * item,
-	    struct condition * cond,
-	    int menu_num,
-	    int line_num)
+void generate_if( struct kconfig * cfg, struct condition * ocond,
+    int menu_num, int line_num )
X {
-  struct condition * ocond;
+    struct condition * cond;
X 
-  ocond = cond;
-
-  /*
-   * First write any global declarations we need for this conditional.
-   */
-  while(cond != NULL )
+    /*
+     * First write any global declarations we need for this conditional.
+     */
+    for ( cond = ocond; cond != NULL; cond = cond->next )
X     {
-      switch(cond->op){
-      case op_variable:
-      	global(cond->variable.str);
-	break;
-      case op_kvariable:
-	if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
-	cond->variable.cfg->flags |= GLOBAL_WRITTEN;
-	global(cond->variable.cfg->optionname);
-	break;
-      default:
-	break;
-      }
-      cond = cond->next;
+	switch ( cond->op )
+	{
+	default:
+	    break;
+
+	case op_variable:
+	    global( cond->str );
+	    break;
+
+	case op_kvariable:
+	    if ( ! cond->cfg->global_written )
+	    {
+		cond->cfg->global_written = 1;
+		global( cond->cfg->optionname );
+	    }
+	    break;
+	}
X     }
-  
-  /*
-   * Now write this option.
-   */
-  if(   (item->flags & GLOBAL_WRITTEN) == 0
-     && (item->optionname != NULL) )
+
+    /*
+     * Now write this option.
+     */
+    if ( ! cfg->global_written && cfg->optionname != NULL )
X     {
-      global(item->optionname);
-      item->flags |= GLOBAL_WRITTEN;
+	cfg->global_written = 1;
+	global( cfg->optionname );
X     }
-  /*
-   * Now generate the body of the conditional.
-   */
-  printf("\tif {");
-  cond = ocond;
-  while(cond != NULL )
+
+    /*
+     * Generate the body of the conditional.
+     */
+    printf( "\tif {" );
+    for ( cond = ocond; cond != NULL; cond = cond->next )
X     {
-      switch(cond->op){
-      case op_bang:
-	printf(" ! ");
-	break;
-      case op_eq:
- printf(" == ");
-	break;
-      case op_neq:
-	printf(" != ");
-	break;
-      case op_and:
-      case op_and1:
-	printf(" && ");
-	break;
-      case op_or:
-	printf(" || ");
-	break;
-      case op_lparen:
-	printf("(");
-	break;
-      case op_rparen:
-	printf(")");
-	break;
-      case op_variable:
-	printf("$%s", cond->variable.str);
-	break;
-      case op_kvariable:
-	printf("$%s", cond->variable.cfg->optionname);
-	break;
-      case op_shellcmd:
-	printf("[exec %s]", cond->variable.str);
-	break;
-      case op_constant:
-	if( strcmp(cond->variable.str, "y") == 0 )
-	  printf("1");
-	else if( strcmp(cond->variable.str, "n") == 0 )
-	  printf("0");
-	else if( strcmp(cond->variable.str, "m") == 0 )
-	  printf("2");
-	else
-	  printf("\"%s\"", cond->variable.str);
-	break;
-      default:
-        break;
-      }
-      cond = cond->next;
-    }
+	switch ( cond->op )
+	{
+	default:
+	    break;
X 
-  /*
-   * Now we generate what we do depending upon the value of the conditional.
-   * Depending upon what the token type is, there are different things
-   * we must do to enable/disable the given widget - this code needs to
-   * be closely coordinated with the widget creation procedures in header.tk.
-   */
-  switch(item->tok)
+	case op_bang:   printf( " ! "  ); break;
+	case op_eq:     printf( " == " ); break;
+	case op_neq:    printf( " != " ); break;
+	case op_and:    printf( " && " ); break;
+	case op_and1:   printf( " && " ); break;
+	case op_or:     printf( " || " ); break;
+	case op_lparen: printf( "("    ); break;
+	case op_rparen: printf( ")"    ); break;
+
+	case op_variable:
+	    printf( "$%s", cond->str );
+	    break;
+
+	case op_kvariable:
+	    printf( "$%s", cond->cfg->optionname );
+	    break;
+
+	case op_constant:
+	    if      ( strcmp( cond->str, "y" ) == 0 ) printf( "1" );
+	    else if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" );
+	    else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" );
+	    else
+		printf( "\"%s\"", cond->str );
+	    break;
+	}
+    }
+    printf( "} then { " );
+
+    /*
+     * Generate a procedure call to write the value.
+     * This code depends on procedures in header.tk.
+     */
+    switch ( cfg->token )
X     {
-    case tok_define:
-      printf("} then { set %s %s } \n",  item->optionname, item->value);
-      break;
-    case tok_menuoption:
-      printf("} then { .f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
-	     menu_num, menu_num);
-      break;
-    case tok_int:
-    case tok_hex:
-    case tok_string:
-      printf("} then { ");
-      printf(".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ", menu_num, line_num);
-      printf(".menu%d.config.f.x%d.l configure -state normal; ", menu_num, line_num);
-      printf("} else { ");
-      printf(".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ];", menu_num, line_num );
-      printf(".menu%d.config.f.x%d.l configure -state disabled;", menu_num, line_num );
-      printf("}\n");
-      break;
-    case tok_bool:
-#ifdef BOOL_IS_BUTTON
-      /*
-       * If a bool is just a button, then use this definition.
-       */
-      printf("} then { .menu%d.config.f.x%d configure -state normal } else { .menu%d.config.f.x%d configure -state disabled }\n",
-	     menu_num, line_num,
-	     menu_num, line_num );
-#else
-      /*
-       * If a bool is a radiobutton, then use this instead.
-       */
-      printf("} then { ");
-      printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
-      printf("set %s [expr $%s&15];", item->optionname, item->optionname);
-      printf("} else { ");
-      printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.n configure -state disabled;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.l configure -state disabled;",menu_num, line_num);
-      printf("set %s [expr $%s|16];", item->optionname, item->optionname);
-      printf("}\n");
-#endif
-      break;
-    case tok_tristate:
-    case tok_dep_tristate:
-      printf("} then { ");
-      if( item->tok == tok_dep_tristate )
-	{
-	  global(item->depend.str);
-	  printf("if { $%s != 1 && $%s != 0 } then {", 
-	  	item->depend.str,item->depend.str);
-	  printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
-	  printf("} else {");
-	  printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
-	  printf("}; ");
-	}
-      else
-	{
-	  printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
-	}
-      
-      printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
-      printf("global CONFIG_MODULES; if {($CONFIG_MODULES == 1)} then { .menu%d.config.f.x%d.m configure -state normal };",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
-      /*
-       * Or in a bit to the variable - this causes all of the radiobuttons
-       * to be deselected (i.e. not be red).
-       */
-      printf("set %s [expr $%s&15];", item->optionname, item->optionname);
-      printf("} else { ");
-      printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.n configure -state disabled;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.m configure -state disabled;",menu_num, line_num);
-      printf(".menu%d.config.f.x%d.l configure -state disabled;",menu_num, line_num);
-      /*
-       * Clear the disable bit - this causes the correct radiobutton
-       * to appear selected (i.e. turn red).
-       */
-      printf("set %s [expr $%s|16];", item->optionname, item->optionname);
-      printf("}\n");
-      break;
-    case tok_choose:
-    case tok_choice:
-      fprintf(stderr,"Fixme\n");
-      exit(0);
X     default:
-      break;
+	printf( " }\n" );
+	break;
+
+    case token_bool:
+	printf( ".menu%d.config.f.x%d.y configure -state normal;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.n configure -state normal;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.l configure -state normal;",
+	    menu_num, line_num );
+	printf( "set %s [expr $%s&15];",
+	    cfg->optionname, cfg->optionname );
+	printf( "} else { ");
+	printf( ".menu%d.config.f.x%d.y configure -state disabled;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.n configure -state disabled;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.l configure -state disabled;",
+	    menu_num, line_num );
+	printf( "set %s [expr $%s|16];}\n",
+	    cfg->optionname, cfg->optionname );
+	break;
+
+    case token_choice_header:
+	fprintf( stderr, "Internal error on token_choice_header\n" );
+	exit( 1 );
+
+    case token_choice_item:
+	fprintf( stderr, "Internal error on token_choice_item\n" );
+	exit( 1 );
+
+    case token_define_bool:
+	printf( "set %s %s } \n",
+	    cfg->optionname, cfg->value );
+	break;
+
+    case token_dep_tristate:
+    case token_tristate:
+	if ( cfg->token == token_dep_tristate )
+	{
+	    global( cfg->depend );
+	    printf( "if { $%s != 1 && $%s != 0 } then {",
+		cfg->depend, cfg->depend );
+	    printf( ".menu%d.config.f.x%d.y configure -state disabled;",
+		menu_num, line_num );
+	    printf( "} else {" );
+	    printf( ".menu%d.config.f.x%d.y configure -state normal;",
+		menu_num, line_num);
+	    printf( "}; " );
+	}
+	else
+	{
+	    printf( ".menu%d.config.f.x%d.y configure -state normal;",
+		menu_num, line_num );
+	}
+
+	printf( ".menu%d.config.f.x%d.n configure -state normal;",
+	    menu_num, line_num );
+	printf( "global CONFIG_MODULES; if {($CONFIG_MODULES == 1)} then { .menu%d.config.f.x%d.m configure -state normal };",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.l configure -state normal;",
+	    menu_num, line_num );
+
+	/*
+	 * Or in a bit to the variable - this causes all of the radiobuttons
+	 * to be deselected (i.e. not be red).
+	 */
+	printf( "set %s [expr $%s&15];",
+	    cfg->optionname, cfg->optionname );
+	printf( "} else { " );
+	printf( ".menu%d.config.f.x%d.y configure -state disabled;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.n configure -state disabled;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.m configure -state disabled;",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.l configure -state disabled;",
+	    menu_num, line_num );
+
+	/*
+	 * Clear the disable bit to enable the correct radiobutton.
+	 */
+	printf( "set %s [expr $%s|16];}\n",
+	    cfg->optionname, cfg->optionname );
+	break;
+
+    case token_hex:
+    case token_int:
+    case token_string:
+	printf( ".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ",
+	    menu_num, line_num);
+	printf( ".menu%d.config.f.x%d.l configure -state normal; ",
+	    menu_num, line_num);
+	printf( "} else { " );
+	printf( ".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ];",
+	    menu_num, line_num );
+	printf( ".menu%d.config.f.x%d.l configure -state disabled;}\n",
+	    menu_num, line_num );
+	break;
+
+    case token_mainmenu_option:
+	printf( ".f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
+	    menu_num, menu_num );
+	break;
X     }
X }
X 
+
+
X /*
- * Similar to generate_if, except we come here when generating an
- * output file.  Thus instead of enabling/disabling a widget, we
- * need to decide whether to write out a given configuration variable
- * to the output file.
+ * Generate a line that writes a variable to the output file.
X  */
-void generate_if_for_outfile(struct kconfig * item,
-	    struct condition * cond)
+void generate_writeconfig( struct kconfig * cfg )
X {
-  struct condition * ocond;
+    struct condition * cond;
X 
-  /*
-   * First write any global declarations we need for this conditional.
-   */
-  ocond = cond;
-  for(; cond != NULL; cond = cond->next )
+    /*
+     * Generate global declaration for this symbol.
+     */
+    if ( cfg->token != token_comment )
X     {
-      switch(cond->op){
-      case op_variable:
-        global(cond->variable.str);
-	break;
-      case op_kvariable:
-	if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
-	cond->variable.cfg->flags |= GLOBAL_WRITTEN;
-	global(cond->variable.cfg->optionname);
-	break;
-      default:
-	break;
-      }
+	if ( ! cfg->global_written )
+	{
+	    cfg->global_written = 1;
+	    printf( "\tglobal %s\n", cfg->optionname );
+	}
X     }
X 
-  /*
-   * Now generate the body of the conditional.
-   */
-  printf("\tif {");
-  cond = ocond;
-  while(cond != NULL )
+    /*
+     * Generate global declarations for the condition chain.
+     */
+    for ( cond = cfg->cond; cond != NULL; cond = cond->next )
X     {
-      switch(cond->op){
-      case op_bang:
-	printf(" ! ");
-	break;
-      case op_eq:
- printf(" == ");
-	break;
-      case op_neq:
-	printf(" != ");
-	break;
-      case op_and:
-      case op_and1:
-	printf(" && ");
-	break;
-      case op_or:
-	printf(" || ");
-	break;
-      case op_lparen:
-	printf("(");
-	break;
-      case op_rparen:
-	printf(")");
-	break;
-      case op_variable:
-	printf("$%s", cond->variable.str);
-	break;
-      case op_shellcmd:
-	printf("[exec %s]", cond->variable.str);
-	break;
-      case op_kvariable:
-	printf("$%s", cond->variable.cfg->optionname);
-	break;
-      case op_constant:
-	if( strcmp(cond->variable.str, "y") == 0 )
-	  printf("1");
-	else if( strcmp(cond->variable.str, "n") == 0 )
-	  printf("0");
-	else if( strcmp(cond->variable.str, "m") == 0 )
-	  printf("2");
-	else
-	  printf("\"%s\"", cond->variable.str);
-	break;
-      default:
-        break;
-      }
-      cond = cond->next;
-    }
+	switch( cond->op )
+	{
+	default:
+	    break;
X 
-  /*
-   * Now we generate what we do depending upon the value of the
-   * conditional.  Depending upon what the token type is, there are
-   * different things we must do write the value the given widget -
-   * this code needs to be closely coordinated with the widget
-   * creation procedures in header.tk.  
-   */
-  switch(item->tok)
-    {
-    case tok_define:
-      printf("} then {write_tristate $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
-      break;
-    case tok_comment:
- printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
-      break;
-    case tok_dep_tristate:
-      printf("} then { write_tristate $cfg $autocfg %s $%s $%s } \n", 
-	     item->optionname, item->optionname, item->depend.str);
-      break;
-    case tok_tristate:
-    case tok_bool:
-      printf("} then { write_tristate $cfg $autocfg %s $%s $notmod }\n", 
-	     item->optionname, item->optionname);
-      break;
-    case tok_int:
-      printf("} then { write_int $cfg $autocfg %s $%s $notmod }\n",
-             item->optionname, item->optionname);
-      break;
-    case tok_hex:
-      printf("} then { write_hex $cfg $autocfg %s $%s $notmod }\n",
-             item->optionname, item->optionname);
-      break;
-    case tok_string:
-      printf("} then { write_string $cfg $autocfg %s $%s $notmod }\n",
-             item->optionname, item->optionname);
-      break;
-    case tok_choose:
-    case tok_choice:
-      fprintf(stderr,"Fixme\n");
-      exit(0);
-    default:
-      break;
+	case op_variable:
+	    global( cond->str );
+	    break;
+
+	case op_kvariable:
+	    if ( ! cond->cfg->global_written )
+	    {
+		cond->cfg->global_written = 1;
+		global( cond->cfg->optionname );
+	    }
+	    break;
+	}
X     }
-}
X 
-/*
- * Generates a fragment of wish script that closes out a submenu procedure.
- */
-static void end_proc(int menu_num)
-{
-  struct kconfig * cfg;
+    /*
+     * Generate indentation.
+     */
+    if ( cfg->token != token_choice_header )
+	printf( "\t" );
X 
-  printf("\n\n\n");
-  printf("\tfocus $w\n");
-  printf("\tupdate_menu%d $w.config.f\n", menu_num);
-  printf("\tglobal winx; global winy\n");
-  printf("\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n");
-  printf("\twm geometry $w +$winx+$winy\n");
-  
-  /*
-   * Now that the whole window is in place, we need to wait for an "update"
-   * so we can tell the canvas what its virtual size should be.
-   *
-   * Unfortunately, this causes some ugly screen-flashing because the whole
-   * window is drawn, and then it is immediately resized.  It seems
-   * unavoidable, though, since "frame" objects won't tell us their size
-   * until after an update, and "canvas" objects can't automatically pack
-   * around frames.  Sigh.
-   */
-  printf("\tupdate idletasks\n");
-  printf("\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n");
-  printf("\t$w.config.canvas configure \\\n"
-  	 "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n"
-  	 "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n"
-  	 "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n");
-  	 
-  /*
-   * If the whole canvas will fit in 3/4 of the screen height, do it;
-   * otherwise, resize to around 1/2 the screen and let us scroll.
-   */
-  printf("\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n");
-  printf("\tset scry [expr [winfo screenh $w] / 2]\n");
-  printf("\tset maxy [expr [winfo screenh $w] * 3 / 4]\n");
-  printf("\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n");
-  printf("\tif [expr $winy + $canvtotal < $maxy] {\n"
-  	 "\t\t$w.config.canvas configure -height $canvtotal\n"
-  	 "\t} else {\n"
-  	 "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n"
-  	 "\t}\n");
-  
-  /*
-   * Limit the min/max window size.  Height can vary, but not width,
-   * because of the limitations of canvas and our laziness.
-   */
-  printf("\tupdate idletasks\n");
-  printf("\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n");
-  printf("\twm minsize $w [winfo width $w] 100\n\n");
-  printf("\twm deiconify $w\n");
-    
-  printf("}\n\n\n");
-
-  /*
-   * Now we generate the companion procedure for the menu we just
-   * generated.  This procedure contains all of the code to
-   * disable/enable widgets based upon the settings of the other
-   * widgets, and will be called first when the window is mapped,
-   * and each time one of the buttons in the window are clicked.
-   */
-  printf("proc update_menu%d {w}  {\n", menu_num);
-
-  printf("\tupdate_define\n");
-  clear_globalflags(config);
-  for(cfg = config;cfg != NULL; cfg = cfg->next)
+    /*
+     * Generate the conditional.
+     */
+    if ( cfg->cond != NULL )
X     {
-      /*
-       * Skip items not for this menu, or ones having no conditions.
-       */
-      if (cfg->menu_number != menu_num ) continue;
-      if (cfg->tok != tok_define) continue;
-      /*
-       * Clear all of the booleans that are defined in this menu.
-       */
-      if(   (cfg->flags & GLOBAL_WRITTEN) == 0
-	 && (cfg->optionname != NULL) )
-	{
-	  printf("\tglobal %s\n", cfg->optionname);
-	  cfg->flags |= GLOBAL_WRITTEN;
-	  printf("\tset %s 0\n", cfg->optionname);
-	}
+	printf( "if {" );
+	for ( cond = cfg->cond; cond != NULL; cond = cond->next )
+	{
+	    switch ( cond->op )
+	    {
+	    default:           break;
+	    case op_bang:      printf( " ! "  ); break;
+	    case op_eq:        printf( " == " ); break;
+	    case op_neq:       printf( " != " ); break;
+	    case op_and:       printf( " && " ); break;
+	    case op_and1:      printf( " && " ); break;
+	    case op_or:        printf( " || " ); break;
+	    case op_lparen:    printf( "("    ); break;
+	    case op_rparen:    printf( ")"    ); break;
X 
+	    case op_variable:
+		printf( "$%s", cond->str );
+		break;
+
+	    case op_kvariable:
+		printf( "$%s", cond->cfg->optionname );
+		break;
+
+	    case op_constant:
+		if      ( strcmp( cond->str, "n" ) == 0 ) printf( "0" );
+		else if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" );
+		else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" );
+		else
+		    printf( "\"%s\"", cond->str );
+		break;
+	    }
+	}
+	printf( "} then {" );
X     }
-  for(cfg = config;cfg != NULL; cfg = cfg->next)
+
+    /*
+     * Generate a procedure call to write the value.
+     * This code depends on the write_* procedures in header.tk.
+     */
+    switch ( cfg->token )
X     {
-      /*
-       * Skip items not for this menu, or ones having no conditions.
-       */
-      if (cfg->menu_number != menu_num ) continue;
-      if (cfg->tok == tok_menuoption) continue;
-      if (cfg->cond != NULL ) 
-	generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
-      else
-	{
-	  /*
-	   * If this token has no conditionals, check to see whether
-	   * it is a tristate - if so, then generate the conditional
-	   * to enable/disable the "y" button based upon the setting
-	   * of the option it depends upon.
-	   */
-	  if(cfg->tok == tok_dep_tristate)
+    default:
+	if ( cfg->cond != NULL )
+	    printf( " }" );
+	printf( "\n" );
+	break;
+
+    case token_bool:
+    case token_tristate:
+	if ( cfg->cond )
+	    printf( " " );
+	printf( "write_tristate $cfg $autocfg %s $%s $notmod", 
+	    cfg->optionname, cfg->optionname );
+	if ( cfg->cond != NULL )
+	    printf( " }" );
+	printf( "\n" );
+	break;
+
+    case token_choice_header:
+	/*
+	 * This is funky code -- it fails if there were any conditionals.
+	 * Fortunately all the conditionals got stripped off somewhere
+	 * else.
+	 */
+	{
+	    struct kconfig * cfg1;
+	    for ( cfg1  = cfg->next;
+		  cfg1 != NULL && cfg1->token == token_choice_item;
+		  cfg1  = cfg1->next )
X 	    {
-	      global(cfg->depend.str);
-	      printf("\tif {$%s != 1 && $%s != 0 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n",
-		     cfg->depend.str,cfg->depend.str,
-		     menu_num, cfg->menu_line,
-		     menu_num, cfg->menu_line);
+		printf("\tif { $%s == \"%s\" } then { write_tristate $cfg $autocfg %s 1 $notmod } else { write_tristate $cfg $autocfg %s 0 $notmod }\n",
+		    cfg->optionname, cfg1->label,
+		    cfg1->optionname,
+		    cfg1->optionname );
X 	    }
X 	}
+	break;
X 
-    }
+    case token_choice_item:
+	fprintf( stderr, "Internal error on token_choice_item\n" );
+	exit( 1 );
X 
+    case token_comment:
+	printf( "write_comment $cfg $autocfg \"%s\"",
+	    cfg->label );
+	if ( cfg->cond != NULL )
+	    printf( "}" );
+	printf( "\n" );
+	break;
+
+    case token_define_bool:
+	if ( cfg->cond == NULL )
+	{
+	    printf( "write_tristate $cfg $autocfg %s $%s $notmod\n",
+		cfg->optionname, cfg->optionname );
+	}
+	else
+	{
+	    printf( "write_tristate $cfg $autocfg %s %s $notmod }\n",
+		cfg->optionname, cfg->value );
+	}
+	break;
X 
-  printf("}\n\n\n");
+    case token_dep_tristate:
+	if ( cfg->cond )
+	    printf( " " );
+	printf( "write_tristate $cfg $autocfg %s $%s $%s",
+	    cfg->optionname, cfg->optionname, cfg->depend );
+	if ( cfg->cond != NULL )
+	    printf( " }" );
+	printf( " \n" );
+	break;
+
+    case token_hex:
+	if ( cfg->cond != NULL )
+	    printf( " " );
+	printf( "write_hex $cfg $autocfg %s $%s $notmod",
+	    cfg->optionname, cfg->optionname );
+	if ( cfg->cond != NULL )
+	    printf( " }" );
+	printf( "\n" );
+	break;
+
+    case token_int:
+	if ( cfg->cond != NULL )
+	    printf( " " );
+	printf( "write_int $cfg $autocfg %s $%s $notmod",
+	    cfg->optionname, cfg->optionname );
+	if ( cfg->cond != NULL )
+	    printf( " }" );
+	printf( "\n" );
+	break;
+
+    case token_string:
+	if ( cfg->cond != NULL )
+	    printf( " " );
+	printf( "write_string $cfg $autocfg %s $%s $notmod",
+	    cfg->optionname, cfg->optionname );
+	if ( cfg->cond != NULL )
+	    printf( " }" );
+	printf( "\n" );
+	break;
+    }
X }
X 
+
+
X /*
- * This function goes through and counts up the number of items in
- * each submenu. If there are too many options, we need to split it
- * into submenus.  This function just calculates how many submenus,
- * and how many items go in each submenu.
+ * Generates the end of a menu procedure.
X  */
-static void find_menu_size(struct kconfig *cfg,
-			  int *menu_max, 
-			  int *menu_maxlines)
-
+static void end_proc( struct kconfig * scfg, int menu_num )
X {
-  struct kconfig * pnt;
-  int tot;
-  
-  /*
-   * First count up the number of options in this menu.
-   */
-  tot = 0;
-  for(pnt = cfg->next; pnt; pnt = pnt->next)
-  {
-    if( pnt->tok == tok_menuoption) break;
-    switch (pnt->tok)
-      {
-      case tok_bool:
-      case tok_tristate:
-      case tok_dep_tristate:
-      case tok_int:
-      case tok_hex:
-      case tok_string:
-      case tok_choose:
-	tot++;
-	break;
-      case tok_choice:
-      default:
-	break;
-      }
-  }
+    struct kconfig * cfg;
X 
-  *menu_max = cfg->menu_number;
-  *menu_maxlines = tot;
+    printf( "\n\n\n" );
+    printf( "\tfocus $w\n" );
+    printf( "\tupdate_menu%d $w.config.f\n",
+	menu_num );
+    printf( "\tglobal winx; global winy\n" );
+    printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" );
+    printf( "\twm geometry $w +$winx+$winy\n" );
+
+    /*
+     * Now that the whole window is in place, we need to wait for an "update"
+     * so we can tell the canvas what its virtual size should be.
+     *
+     * Unfortunately, this causes some ugly screen-flashing because the whole
+     * window is drawn, and then it is immediately resized.  It seems
+     * unavoidable, though, since "frame" objects won't tell us their size
+     * until after an update, and "canvas" objects can't automatically pack
+     * around frames.  Sigh.
+     */
+    printf( "\tupdate idletasks\n" );
+    printf( "\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n" );
+    printf( "\t$w.config.canvas configure \\\n" );
+    printf( "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n" );
+    printf( "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n" );
+    printf( "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n" );
+	 
+    /*
+     * If the whole canvas will fit in 3/4 of the screen height, do it;
+     * otherwise, resize to around 1/2 the screen and let us scroll.
+     */
+    printf( "\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n" );
+    printf( "\tset scry [expr [winfo screenh $w] / 2]\n" );
+    printf( "\tset maxy [expr [winfo screenh $w] * 3 / 4]\n" );
+    printf( "\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n" );
+    printf( "\tif [expr $winy + $canvtotal < $maxy] {\n" );
+    printf( "\t\t$w.config.canvas configure -height $canvtotal\n" );
+    printf( "\t} else {\n" );
+    printf( "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n" );
+    printf( "\t}\n" );
+
+    /*
+     * Limit the min/max window size.  Height can vary, but not width,
+     * because of the limitations of canvas and our laziness.
+     */
+    printf( "\tupdate idletasks\n" );
+    printf( "\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n" );
+    printf( "\twm minsize $w [winfo width $w] 100\n\n" );
+    printf( "\twm deiconify $w\n" );
+    printf( "}\n\n\n" );
+
+    /*
+     * Now we generate the companion procedure for the menu we just
+     * generated.  This procedure contains all of the code to
+     * disable/enable widgets based upon the settings of the other
+     * widgets, and will be called first when the window is mapped,
+     * and each time one of the buttons in the window are clicked.
+     */
+    printf( "proc update_menu%d {w}  {\n", menu_num );
+    printf( "\tupdate_define\n" );
+
+    /*
+     * Clear all of the booleans that are defined in this menu.
+     */
+    clear_globalflags( scfg );
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+    {
+	if ( cfg->menu_number == menu_num && cfg->token == token_define_bool
+	&&   cfg->optionname  != NULL )
+	{
+	    if ( ! cfg->global_written )
+	    {
+		cfg->global_written = 1;
+		printf( "\tglobal %s\n", cfg->optionname );
+		printf( "\tset %s 0\n",  cfg->optionname );
+	    }
+	}
+    }
+
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+    {
+	if ( cfg->menu_number == menu_num
+	&&   cfg->token != token_mainmenu_option
+	&&   cfg->token != token_choice_item )
+	{
+	    if ( cfg->cond != NULL )
+		generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line );
+	    else
+	    {
+		/*
+		 * Treat tristate like conditional here.
+		 */
+		if ( cfg->token == token_dep_tristate )
+		{
+		    global( cfg->depend );
+		    printf( "\tif {$%s != 1 && $%s != 0 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n",
+			cfg->depend, cfg->depend,
+			menu_num, cfg->menu_line,
+			menu_num, cfg->menu_line );
+		}
+	    }
+	}
+    }
+
+    printf("}\n\n\n");
X }
X 
+
+
X /*
X  * This is the top level function for generating the tk script.
X  */
-void dump_tk_script(struct kconfig *scfg)
+void dump_tk_script( struct kconfig * scfg )
X {
-  int menu_num =0;
-  int menu_max =0;
-  int menu_min =0;
-  int menu_line = 0;
-  int menu_maxlines = 0;
-  struct kconfig * cfg;
-  struct kconfig * cfg1 = NULL;
-  char * menulabel = "tkgen error";
-
-  /*
-   * Start by assigning menu numbers, and submenu numbers.
-   */
-  for(cfg = scfg;cfg != NULL; cfg = cfg->next)
+    int menu_depth;
+    int menu_num [64];
+    struct kconfig * menu_first [256];
+    struct kconfig * menu_last  [256];
+    int imenu;
+    struct kconfig * cfg;
+    struct kconfig * cfg1 = NULL;
+    const char * name = "No Name";
+
+    /*
+    * Thread the menu pointers so I can walk each menu separately.
+    */
+    tot_menu_num = 0;
+    menu_depth   = 0;
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
- switch (cfg->tok)
+	switch ( cfg->token )
X 	{
-	case tok_menuname:
-	  break;
-	case tok_menuoption:
-	  /*
-	   * At the start of a new menu, calculate the number of items
-	   * we will put into each submenu so we know when to bump the
-	   * menu number. The submenus are really no different from a
-	   * normal menu, but the top level buttons only access the first
-	   * of the chain of menus, and the prev/next buttons are used
-	   * access the submenus.
-	   */
-	  cfg->menu_number = ++menu_num;
-	  find_menu_size(cfg, &menu_max, &menu_maxlines);
-	  cfg->submenu_start = menu_num;
-	  cfg->submenu_end = menu_max;
-	  menu_line = 0;
-	  break;
-	case tok_bool:
-	case tok_tristate:
-	case tok_dep_tristate:
-	case tok_int:
-	case tok_hex:
-	case tok_string:
-	case tok_choose:
-	  /*
-	   * If we have overfilled the menu, then go to the next one.
-	   */
-	  if( menu_line == menu_maxlines )
-	    {
-	      menu_line = 0;
-	      menu_num++;
-	    }
-	  cfg->menu_number = menu_num;
-	  cfg->submenu_start = menu_min;
-	  cfg->submenu_end = menu_max;
-	  cfg->menu_line = menu_line++;
-	  break;
-	case tok_define:
-	  cfg->menu_number = -1;
-	case tok_choice:
X 	default:
-	  break;
-	};
-    }
+	    break;
X 
-  /*
-   * Record this so we can set up the prev/next buttons correctly.
-   * Menus per column computation has extra button space as follows:
-   *   4 for the save/quit/load/store buttons,
-   *   1 for the blank space above save/quit/load/store
-   *   2 to make the rounding work
-   */
-  tot_menu_num = menu_num;
-  printf( "set menus_per_column %d\n\n", (tot_menu_num + 4 + 1 + 2) / 3 );
-
-  /*
-   * Now start generating the actual wish script that we will use.
-   * We need to keep track of the menu numbers of the min/max menu
-   * for a range of submenus so that we can correctly limit the
-   * prev and next buttons so that they don't go over into some other
-   * category.
-   */
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
-    {
-      switch (cfg->tok)
-	{
-	case tok_menuname:
-	  printf("mainmenu_name \"%s\"\n", cfg->label);
-	  break;
-	case tok_menuoption:
-	  /*
-	   * We are at the start of a new menu. If we had one that
-	   * we were working on before, close it out, and then generate
-	   * the script to start the new one.
-	   */
-	  if( cfg->menu_number > 1 )
-	    {
-	      end_proc(menu_num);
-	    }
-	  menulabel = cfg->label;
-	  start_proc(cfg->label, cfg->menu_number, TRUE);
-	  menu_num = cfg->menu_number;
-	  menu_max = cfg->submenu_end;
-	  menu_min = cfg->submenu_start;
-	  break;
-	case tok_bool:
-	  /*
-	   * If we reached the point where we need to switch over
-	   * to the next submenu, then bump the menu number and generate
-	   * the code to close out the old menu and start the new one.
-	   */
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\tbool $w.config.f %d %d \"%s\" %s\n",
-		 cfg->menu_number,
-		 cfg->menu_line,
-		 cfg->label,
-		 cfg->optionname);
-	  break;
-
-	case tok_choice:
-	  printf("\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value \"%s\" -command \"update_menu%d .menu%d.config.f\"\n",
-		 cfg1->menu_line,
-		 cfg->label,
-		 cfg1->optionname,
-		 cfg->label,
-		 cfg1->menu_number, cfg1->menu_number);
-	  break;
-	case tok_choose:
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\tglobal %s\n",cfg->optionname);
-	  printf("\tminimenu $w.config.f %d %d \"%s\" %s %s\n",
-	  	cfg->menu_number,
-	  	cfg->menu_line,
-	  	cfg->label,
-	  	cfg->optionname,
-	  	/*
-	  	 * We rely on the fact that the first tok_choice corresponding
-	  	 * to the current tok_choose is cfg->next (compare parse() in
-	  	 * tkparse.c).  We need its name to pick out the right help
-	  	 * text from Configure.help.
-	  	 */
-	  	cfg->next->optionname);
-	  printf("\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line);
-	  cfg1 = cfg;
-	  break;
-	case tok_tristate:
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\ttristate $w.config.f %d %d \"%s\" %s\n",
-		 cfg->menu_number,
-		 cfg->menu_line,
-		 cfg->label,
-		 cfg->optionname);
-	  break;
-	case tok_dep_tristate:
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\tdep_tristate $w.config.f %d %d \"%s\" %s %s\n",
-		 cfg->menu_number,
-		 cfg->menu_line,
-		 cfg->label,
-		 cfg->optionname,
-		 cfg->depend.str);
-	  break;
-	case tok_int:
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\tint $w.config.f %d %d \"%s\" %s\n",
-		 cfg->menu_number,
-		 cfg->menu_line,
-		 cfg->label,
-		 cfg->optionname);
-	  break;
-	case tok_hex:
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\thex $w.config.f %d %d \"%s\" %s\n",
-		 cfg->menu_number,
-		 cfg->menu_line,
-		 cfg->label,
-		 cfg->optionname);
-	  break;
-	case tok_string:
-	  if( cfg->menu_number != menu_num )
-	    {
-	      end_proc(menu_num);
-	      start_proc(menulabel, cfg->menu_number, FALSE);
-	      menu_num = cfg->menu_number;
-	    }
-	  printf("\tistring $w.config.f %d %d \"%s\" %s\n",
-		 cfg->menu_number,
-		 cfg->menu_line,
-		 cfg->label,
-		 cfg->optionname);
-	  break;
-	default:
-	  break;
-	}
+	case token_mainmenu_name:
+	    name = cfg->label;
+	    break;
+
+	case token_mainmenu_option:
+	    if ( ++menu_depth >= 64 )
+		{ fprintf( stderr, "menus too deep\n" ); exit( 1 ); }
+	    if ( ++tot_menu_num >= 256 )
+		{ fprintf( stderr, "too many menus\n" ); exit( 1 ); }
+	    menu_num   [menu_depth]   = tot_menu_num;
+	    menu_first [tot_menu_num] = cfg;
+	    menu_last  [tot_menu_num] = cfg;
+	    break;
+
+	case token_endmenu:
+#if ! defined(BUG_COMPATIBLE)
+	    /* flatten menus with proper scoping */
+	    if ( --menu_depth < 0 )
+		{ fprintf( stderr, "unmatched endmenu\n" ); exit( 1 ); }
+#endif
+	    break;
X 
+	case token_bool:
+	case token_choice_header:
+	case token_choice_item:
+	case token_dep_tristate:
+	case token_hex:
+	case token_int:
+	case token_string:
+	case token_tristate:
+	    if ( menu_depth == 0 )
+		{ fprintf( stderr, "statement not in menu\n" ); exit( 1 ); }
+	    menu_last [menu_num [menu_depth]]->menu_next = cfg;
+	    menu_last [menu_num [menu_depth]]            = cfg;
+	    cfg->menu_next                               = NULL;
+	    break;
+
+	case token_define_bool:
+	    break;
+	}
+    }
+
+    /*
+     * Generate menus per column setting.
+     * There are:
+     *   four extra buttons for save/quit/load/store;
+     *   one blank button
+     *   add two to round up for division
+     */
+    printf( "set menus_per_column %d\n\n", (tot_menu_num + 4 + 1 + 2) / 3 );
+
+    /*
+     * Generate the menus.
+     */
+    printf( "mainmenu_name \"%s\"\n", name );
+    for ( imenu = 1; imenu <= tot_menu_num; ++imenu )
+    {
+	int menu_line = 0;
+
+	clear_globalflags( scfg );
+	start_proc( menu_first[imenu]->label, imenu, 1 );
+
+	for ( cfg = menu_first[imenu]; cfg != NULL; cfg = cfg->menu_next )
+	{
+	    cfg->menu_number = imenu;
+
+	    switch ( cfg->token )
+ {
+	    default:
+		break;
+
+	    case token_bool:
+		cfg->menu_line = menu_line++;
+		printf( "\tbool $w.config.f %d %d \"%s\" %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname );
+		break;
+
+	    case token_choice_header:
+		/*
+		 * I need the first token_choice_item to pick out the right
+		 * help text from Documentation/Configure.help.
+		 */
+		cfg->menu_line = menu_line++;
+		printf( "\tglobal %s\n", cfg->optionname );
+		printf( "\tminimenu $w.config.f %d %d \"%s\" %s %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname, cfg->next->optionname );
+		printf( "\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line );
+		cfg1 = cfg;
+		break;
+
+	    case token_choice_item:
+		/* note: no menu line; uses choice header menu line */
+		printf( "\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value \"%s\" -command \"update_menu%d .menu%d.config.f\"\n",
+		    cfg1->menu_line, cfg->label, cfg1->optionname,
+		    cfg->label, cfg1->menu_number, cfg1->menu_number );
+		break;
+
+	    case token_dep_tristate:
+		cfg->menu_line = menu_line++;
+		printf( "\tdep_tristate $w.config.f %d %d \"%s\" %s %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname, cfg->depend );
+		break;
+
+	    case token_hex:
+		cfg->menu_line = menu_line++;
+		printf( "\thex $w.config.f %d %d \"%s\" %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname );
+		break;
+
+	    case token_int:
+		cfg->menu_line = menu_line++;
+		printf( "\tint $w.config.f %d %d \"%s\" %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname );
+		break;
+
+	    case token_string:
+		cfg->menu_line = menu_line++;
+		printf( "\tistring $w.config.f %d %d \"%s\" %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname );
+		break;
+
+	    case token_tristate:
+		cfg->menu_line = menu_line++;
+		printf( "\ttristate $w.config.f %d %d \"%s\" %s\n",
+		    cfg->menu_number, cfg->menu_line, cfg->label,
+		    cfg->optionname );
+		break;
+	    }
+	}
+
+	end_proc( scfg, imenu );
+    }
+
+    /*
+     * The top level menu also needs an update function.  When we exit a
+     * submenu, we may need to disable one or more of the submenus on
+     * the top level menu, and this procedure will ensure that things are
+     * correct.
+     */
+    clear_globalflags( scfg );
+    printf( "proc update_mainmenu {w}  {\n" );
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
+    {
+	if ( cfg->token == token_mainmenu_option && cfg->cond != NULL )
+	    generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line );
X     }
+    printf( "}\n\n\n" );
X 
-  /*
-   * Generate the code to close out the last menu.
-   */
-  end_proc(menu_num);
-  clear_globalflags(config);
-
-  /*
-   * The top level menu also needs an update function.  When we exit a
-   * submenu, we may need to disable one or more of the submenus on
-   * the top level menu, and this procedure will ensure that things are
-   * correct.
-   */
-  clear_globalflags(scfg);
-  printf("proc update_mainmenu {w}  {\n");
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+#if 0
+    /*
+     * Generate code to set the variables that are "defined".
+     */
+    for ( cfg = config; cfg != NULL; cfg = cfg->next )
X     {
-      switch (cfg->tok)
+	if ( cfg->token == token_define_bool )
X 	{
-	case tok_menuoption:
-	  if (cfg->cond != NULL ) 
-	    generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
-	  break;
-	default:
-	  break;
+	    if ( cfg->cond != NULL ) 
+		generate_if( cfg, cfg->cond, menu_num, cfg->menu_line );
+	    else
+		printf( "\twrite_define %s %s\n", cfg->optionname, cfg->value );
X 	}
X     }
+    #endif
X 
-  printf("}\n\n\n");
-
-#if 0
-  /*
-   * Generate some code to set the variables that are "defined".
-   */
-  for(cfg = config;cfg != NULL; cfg = cfg->next)
+    /*
+     * Generate code to load the default settings into the variables.
+     * The script in tail.tk will attempt to load .config,
+     * which may override these settings, but that's OK.
+     */
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      /*
-       * Skip items not for this menu, or ones having no conditions.
-       */
-      if( cfg->tok != tok_define) continue;
-      if (cfg->cond != NULL ) 
-	generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
-      else
+	switch ( cfg->token )
X 	{
-	  printf("\twrite_define %s %s\n", cfg->optionname, cfg->value);
-	}
+	default:
+	    break;
X 
+	case token_bool:
+	case token_choice_item:
+	case token_dep_tristate:
+	case token_tristate:
+	    printf( "set %s 0\n", cfg->optionname );
+	    break;
+
+	case token_choice_header:
+	    printf( "set %s \"(not set)\"\n", cfg->optionname );
+	    break;
+
+	case token_hex:
+	case token_int:
+	case token_string:
+	    printf( "set %s %s\n", cfg->optionname, cfg->value );
+	    break;
+	}
X     }
-#endif
X 
-  /*
-   * Now generate code to load the default settings into the variables.
-   * Note that the script in tail.tk will attempt to load .config,
-   * which may override these settings, but that's OK.
-   */
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    /*
+     * Generate a function to write all of the variables to a file.
+     */
+    printf( "proc writeconfig {file1 file2} {\n" );
+    printf( "\tset cfg [open $file1 w]\n" );
+    printf( "\tset autocfg [open $file2 w]\n" );
+    printf( "\tset notmod 1\n" );
+    printf( "\tset notset 0\n" );
+    printf( "\tputs $cfg \"#\"\n");
+    printf( "\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
+    printf( "\tputs $cfg \"#\"\n" );
+
+    printf( "\tputs $autocfg \"/*\"\n" );
+    printf( "\tputs $autocfg \" * Automatically generated C config: don't edit\"\n" );
+    printf( "\tputs $autocfg \" */\"\n" );
+    printf( "\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n" );
+
+    clear_globalflags( scfg );
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
- switch (cfg->tok)
+	switch ( cfg->token )
X 	{
-	case tok_bool:
-	case tok_tristate:
-	case tok_dep_tristate:
-	case tok_choice:
-	  printf("set %s 0\n", cfg->optionname);
-	  break;
-	case tok_int:
-	case tok_hex:
-	case tok_string:
-	  printf("set %s %s\n", cfg->optionname, cfg->value);
-	  break;
-	case tok_choose:
-	  printf("set %s \"(not set)\"\n",cfg->optionname);
X 	default:
-	  break;
+	    break;
+
+	case token_bool:
+ case token_choice_header:
+	case token_comment:
+	case token_define_bool:
+ case token_dep_tristate:
+	case token_hex:
+	case token_int:
+	case token_string:
+	case token_tristate:
+	    generate_writeconfig( cfg );
+	    break;
X 	}
X     }
+    printf( "\tclose $cfg\n" );
+    printf( "\tclose $autocfg\n" );
+    printf( "}\n\n\n" );
X 
-  /*
-   * Next generate a function that can be called from the main menu that will
-   * write all of the variables out.  This also serves double duty - we can
-   * save configuration to a file using this.
-   */
-  printf("proc writeconfig {file1 file2} {\n");
-  printf("\tset cfg [open $file1 w]\n");
-  printf("\tset autocfg [open $file2 w]\n");
-  printf("\tset notmod 1\n");
-  printf("\tset notset 0\n");
-  clear_globalflags(config);
-  printf("\tputs $cfg \"#\"\n");
-  printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
-  printf("\tputs $cfg \"#\"\n");
-
-  printf("\tputs $autocfg \"/*\"\n");
-  printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
-  printf("\tputs $autocfg \" */\"\n");
-  printf("\tputs $autocfg \"#define AUTOCONF_INCLUDED\"\n");
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    /*
+     * Generate a simple function that updates the master choice
+     * variable depending upon what values were loaded from a .config
+     * file.  
+     */
+    printf( "proc clear_choices { } {\n" );
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      switch (cfg->tok)
+	if ( cfg->token == token_choice_header )
X 	{
-	case tok_int:
-	case tok_hex:
-	case tok_string:
-	case tok_bool:
-	case tok_tristate:
-	case tok_dep_tristate:
-	case tok_define:
-	case tok_choose:
-	  if(!(cfg->flags & GLOBAL_WRITTEN))
+	    for ( cfg1  = cfg->next; 
+		  cfg1 != NULL && cfg1->token == token_choice_item;
+		  cfg1  = cfg1->next )
X 	    {
-	      cfg->flags |= GLOBAL_WRITTEN;
-	      printf("\tglobal %s\n", cfg->optionname);
+		printf( "\tglobal %s; set %s 0\n",
+		    cfg1->optionname, cfg1->optionname );
X 	    }
-	  /* fall through */
-	case tok_comment:
-	  if (cfg->cond != NULL ) 
-	    generate_if_for_outfile(cfg, cfg->cond);
-	  else
-	    {
-	      if(cfg->tok == tok_dep_tristate)
-		{
-		  printf("\tif {$%s == 0 } then {\n"
-		  	 "\t\twrite_tristate $cfg $autocfg %s $notset $notmod\n"
-		  	 "\t} else {\n"
-		  	 "\t\twrite_tristate $cfg $autocfg %s $%s $%s\n"
-		  	 "\t}\n",
-		  	 cfg->depend.str,
-			 cfg->optionname,
-			 cfg->optionname,
-			 cfg->optionname,
-			 cfg->depend.str);
-		}
-	      else if(cfg->tok == tok_comment)
-		{
-		  printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
-		}
-#if 0
-	      else if(cfg->tok == tok_define)
-		{
-		  printf("\twrite_define %s %s\n", cfg->optionname,
-			 cfg->value);
-		}
-#endif
-	      else if (cfg->tok == tok_choose )
-		{
-		  for(cfg1 = cfg->next; 
-		      cfg1 != NULL && cfg1->tok == tok_choice;
-		      cfg1 = cfg1->next)
-		    {
-		      printf("\tif { $%s == \"%s\" } then { write_tristate $cfg $autocfg %s 1 $notmod } else { write_tristate $cfg $autocfg %s 0 $notmod }\n",
-			     cfg->optionname,
-			     cfg1->label,
-			     cfg1->optionname,
-			     cfg1->optionname);
-		    }
-		}
-	      else if (cfg->tok == tok_int )
-	        {
-		  printf("\twrite_int $cfg $autocfg %s $%s $notmod\n",
-			 cfg->optionname,
-			 cfg->optionname);
-	        }
-	      else if (cfg->tok == tok_hex )
-	        {
-		  printf("\twrite_hex $cfg $autocfg %s $%s $notmod\n",
-			 cfg->optionname,
-			 cfg->optionname);
-	        }
-	      else if (cfg->tok == tok_string )
-	        {
-		  printf("\twrite_string $cfg $autocfg %s $%s $notmod\n",
-			 cfg->optionname,
-			 cfg->optionname);
-	        }
-	      else
-		{
-		  printf("\twrite_tristate $cfg $autocfg %s $%s $notmod\n",
-			 cfg->optionname,
-			 cfg->optionname);
-		}
-	    }
-	  break;
-	default:
-	  break;
X 	}
X     }
-  printf("\tclose $cfg\n");
-  printf("\tclose $autocfg\n");
-  printf("}\n\n\n");
-
-  /*
-   * Finally write a simple function that updates the master choice
-   * variable depending upon what values were loaded from a .config
-   * file.  
-   */
-  printf("proc clear_choices { } {\n");
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    printf( "}\n\n\n" );
+
+    printf( "proc update_choices { } {\n" );
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      if( cfg->tok != tok_choose ) continue;
-      for(cfg1 = cfg->next; 
-	  cfg1 != NULL && cfg1->tok == tok_choice;
-	  cfg1 = cfg1->next)
+	if ( cfg->token == token_choice_header )
X 	{
-	  printf("\tglobal %s; set %s 0\n",cfg1->optionname,cfg1->optionname);
+	    printf( "\tglobal %s\n", cfg->optionname );
+	    for ( cfg1  = cfg->next; 
+		  cfg1 != NULL && cfg1->token == token_choice_item;
+		  cfg1  = cfg1->next )
+	    {
+		printf( "\tglobal %s\n", cfg1->optionname );
+		printf( "\tif { $%s == 1 } then { set %s \"%s\" }\n",
+		    cfg1->optionname, cfg->optionname, cfg1->label );
+	    }
X 	}
X     }
-  printf("}\n\n\n");
+    printf( "}\n\n\n" );
X 
-  printf("proc update_choices { } {\n");
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    printf( "proc update_define { } {\n" );
+    clear_globalflags( scfg );
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      if( cfg->tok != tok_choose ) continue;
-      printf("\tglobal %s\n", cfg->optionname);
-      for(cfg1 = cfg->next; 
-	  cfg1 != NULL && cfg1->tok == tok_choice;
-	  cfg1 = cfg1->next)
-	{
-	  printf("\tglobal %s\n", cfg1->optionname);
-	  printf("\tif { $%s == 1 } then { set %s \"%s\" }\n",
-		 cfg1->optionname,
-		 cfg->optionname,
-		 cfg1->label);
+	if ( cfg->token == token_define_bool )
+	{
+	    cfg->global_written = 1;
+	    printf( "\tglobal %s\n", cfg->optionname );
X 	}
X     }
-  printf("}\n\n\n");
X 
-  printf("proc update_define { } {\n");
-  clear_globalflags(config);
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
+    for ( cfg = scfg; cfg != NULL; cfg = cfg->next )
X     {
-      if( cfg->tok != tok_define ) continue;
-      printf("\tglobal %s\n",  cfg->optionname);
-      cfg->flags |= GLOBAL_WRITTEN;
-    }
-  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
-    {
-      if( cfg->tok != tok_define ) continue;
-      if (cfg->cond != NULL ) 
-	generate_if(cfg, cfg->cond, -1, 0);
-      else
+	if( cfg->token == token_define_bool )
X 	{
-	  printf("\tset %s %s\n",
-		 cfg->optionname, cfg->value);
+	    if ( cfg->cond == NULL )
+		printf( "\tset %s %s\n", cfg->optionname, cfg->value );
+	    else
+		generate_if( cfg, cfg->cond, -1, 0 );
X 	}
X     }
-  printf("}\n\n\n");
-  /*
-   * That's it.  We are done.  The output of this file will have header.tk
-   * prepended and tail.tk appended to create an executable wish script.
-   */
+    printf( "}\n\n\n" );
+
+    /*
+     * That's it.  We are done.  The output of this file will have header.tk
+     * prepended and tail.tk appended to create an executable wish script.
+     */
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/scripts/tkparse.c linux/scripts/tkparse.c
--- v2.2.0-pre8/linux/scripts/tkparse.c	Tue Jan 19 11:32:53 1999
+++ linux/scripts/tkparse.c	Wed Jan 20 10:05:49 1999
@@ -1,777 +1,622 @@
-/* parser config.in
- *
- * Version 1.0
- * Eric Youngdale
- * 10/95
+/*
+ * tkparse.c
X  *
- * The general idea here is that we want to parse a config.in file and 
- * from this, we generate a wish script which gives us effectively the
- * same functionality that the original config.in script provided.
+ * Eric Youngdale was the original author of xconfig.
+ * Michael Elizabeth Chastain (m...@shout.net) is the current maintainer.
X  *
- * This task is split roughly into 3 parts.  The first parse is the parse
- * of the input file itself.  The second part is where we analyze the 
- * #ifdef clauses, and attach a linked list of tokens to each of the
- * menu items.  In this way, each menu item has a complete list of
- * dependencies that are used to enable/disable the options.
- * The third part is to take the configuration database we have build,
- * and build the actual wish script.
+ * Parse a config.in file and translate it to a wish script.
+ * This task has three parts:
X  *
- * This file contains the code to do the first parse of config.in.
+ *   tkparse.c	tokenize the input
+ *   tkcond.c   transform 'if ...' statements
+ *   tkgen.c    generate output
X  *
X  * Change History
X  *
- * 7 January 1999, Michael Elizabeth Chastain, <mailto:m...@shout.net>
- * Teach dep_tristate about a few literals, such as:
- *   dep_tristate 'foo' CONFIG_FOO m
- * Also have it print an error message and exit on some parse failures.
+ * 7 January 1999, Michael Elizabeth Chastain, <m...@shout.net>
+ * - Teach dep_tristate about a few literals, such as:
+ *     dep_tristate 'foo' CONFIG_FOO m
+ *   Also have it print an error message and exit on some parse failures.
+ *
+ * 14 January 1999, Michael Elizabeth Chastain, <m...@shout.net>
+ * - Don't fclose stdin.  Thanks to Tony Hoyle for nailing this one.
+ *
+ * 14 January 1999, Michael Elizabeth Chastain, <m...@shout.net>
+ * - Steam-clean this file.  I tested this by generating kconfig.tk for
+ *   every architecture and comparing it character-for-character against
+ *   the output of the old tkparse.
X  *
- * 14 January 1999, Michael Elizabeth Chastain, <mailto:m...@shout.net>
- * Don't fclose stdin.  Thanks to Tony Hoyle for nailing this one.
+ * TO DO:
+ * - xconfig is at the end of its life cycle.  Contact <m...@shout.net> if
+ *   you are interested in working on the replacement.
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
fi
echo 'End of  part 14'
echo 'File patch-2.2.0-pre9 is continued in part 15'
echo 15 > _shar_seq_.tmp
#!/bin/sh
# this is part 15 of a 15 - part archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file patch-2.2.0-pre9 continued
if test ! -r _shar_seq_.tmp; then
        echo 'Please unpack part 1 first!'
        exit 1
fi
(read Scheck
if test "$Scheck" != 15; then
        echo Please unpack part "$Scheck" next!
        exit 1
 else
        exit 0
 fi
) < _shar_seq_.tmp || exit 1
if test ! -f _shar_wnt_.tmp; then
echo 'x - still skipping patch-2.2.0-pre9'
else
echo 'x - continuing with patch-2.2.0-pre9'
sed 's/^X//' << 'SHAR_EOF' >> 'patch-2.2.0-pre9' &&
X  */
X 
-#include <stdlib.h>
X #include <stdio.h>
+#include <stdlib.h>
X #include <string.h>
+
X #include "tkparse.h"
X 
-struct kconfig * config = NULL;
-struct kconfig * clast = NULL;
-struct kconfig * koption = NULL;
+static struct kconfig * config_list = NULL;
+static struct kconfig * config_last = NULL;
+static const char * current_file = "<unknown file>";
X static int lineno = 0;
-static int menus_seen = 0;
-static char * current_file = NULL;
-static int do_source(char * filename);
-static char * get_string(char *pnt, char ** labl);
-static int choose_number = 0;
+
+static void do_source( const char * );
+
+#undef strcmp
+int my_strcmp( const char * s1, const char * s2 ) { return strcmp( s1, s2 ); }
+#define strcmp my_strcmp
+
X 
X 
X /*
- * Simple function just to skip over spaces and tabs in config.in.
+ * Report a syntax error.
X  */
-static char * skip_whitespace(char * pnt)
+static void syntax_error( const char * msg )
X {
-  while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
-  return pnt;
+    fprintf( stderr, "%s: %d: %s\n", current_file, lineno, msg );
+    exit( 1 );
X }
X 
+
+
X /*
- * This function parses a conditional from a config.in (i.e. from an ifdef)
- * and generates a linked list of tokens that describes the conditional.
+ * Get a string.
X  */
-static struct condition * parse_if(char * pnt)
+static const char * get_string( const char * pnt, char ** label )
X {
-  char * opnt;
-  struct condition *list;
-  struct condition *last;
-  struct condition *cpnt;
-  char varname[64];
-  char * pnt1;
-
-  opnt = pnt;
-
-  /*
-   * We need to find the various tokens, and build the linked list.
-   */
-  pnt = skip_whitespace(pnt);
-  if( *pnt != '[' ) return NULL;
-  pnt++;
-  pnt = skip_whitespace(pnt);
-
-  list = last = NULL;
-  while(*pnt && *pnt != ']') {
+    const char * word;
X 
-    pnt = skip_whitespace(pnt);
-    if(*pnt== '\0' || *pnt == ']') break;
-
-    /*
-     * Allocate memory for the token we are about to parse, and insert
-     * it in the linked list.
-     */
-    cpnt = (struct condition *) malloc(sizeof(struct condition));
-    memset(cpnt, 0, sizeof(struct condition));
-    if( last == NULL )
-      {
-	list = last = cpnt;
-      }
-    else
-      {
-	last->next = cpnt;
-	last = cpnt;
-      }
+    word = pnt;
+    for ( ; ; )
+    {
+	if ( *pnt == '\0' || *pnt == ' ' || *pnt == '\t' )
+	    break;
+	pnt++;
+    }
X 
-    /*
-     * Determine what type of operation this token represents.
-     */
-    if( *pnt == '-' && pnt[1] == 'a' )
-      {
-	cpnt->op = op_and;
-	pnt += 2;
-	continue;
-      }
-
-    if( *pnt == '-' && pnt[1] == 'o' )
-      {
-	cpnt->op = op_or;
-	pnt += 2;
-	continue;
-      }
-
-    if( *pnt == '!' && pnt[1] == '=' )
-      {
-	cpnt->op = op_neq;
-	pnt += 2;
-	continue;
-      }
-
-    if( *pnt == '=')
-      {
-	cpnt->op = op_eq;
-	pnt += 1;
-	continue;
-      }
-
-    if( *pnt == '!')
-      {
-	cpnt->op = op_bang;
-	pnt += 1;
-	continue;
-      }
+    *label = malloc( pnt - word + 1 );
+    memcpy( *label, word, pnt - word );
+    (*label)[pnt - word] = '\0';
X 
-    if( *pnt != '"' ) goto error;  /* This cannot be right. */
-    pnt++;
-    if( *pnt == '`' )
-      {
-	cpnt->op = op_shellcmd;
-	pnt1 = varname;
-	pnt++;
-	while(*pnt && *pnt != '`') *pnt1++ = *pnt++;
-	*pnt1++ = '\0';
-	cpnt->variable.str = strdup(varname);
-	if( *pnt == '`' ) pnt++;
-	if( *pnt == '"' ) pnt++;
-	continue;
-      }
-    if( *pnt == '$' )
-      {
-	cpnt->op = op_variable;
-	pnt1 = varname;
+    if ( *pnt != '\0' )
X 	pnt++;
-	while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
-	*pnt1++ = '\0';
-	cpnt->variable.str = strdup(varname);
-	if( *pnt == '"' ) pnt++;
-	continue;
-      }
-
-    cpnt->op = op_constant;
-    pnt1 = varname;
-    while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
-    *pnt1++ = '\0';
-    cpnt->variable.str = strdup(varname);
-    if( *pnt == '"' ) pnt++;
-    continue;
-  }
-
-  return list;
-
- error:
-  if(current_file != NULL) 
-    fprintf(stderr, 
-	    "Bad if clause at line %d(%s):%s\n", lineno, current_file, opnt);
-  else
-    fprintf(stderr,
-	    "Bad if clause at line %d:%s\n", lineno, opnt);
-  return NULL;
+    return pnt;
X }
X 
+
+
X /*
- * This function looks for a quoted string, from the input buffer, and
- * returns a pointer to a copy of this string.  Any characters in
- * the string that need to be "quoted" have a '\' character inserted
- * in front - this way we can directly write these strings into
- * wish scripts.
+ * Get a quoted string.
+ * Insert a '\' before any characters that need quoting.
X  */
-static char * get_qstring(char *pnt, char ** labl)
+static const char * get_qstring( const char * pnt, char ** label )
X {
-  char quotechar;
-  char newlabel[1024];
-  char * pnt1;
-  char * pnt2;
-
-  while( *pnt && *pnt != '"' && *pnt != '\'') pnt++;
-  if (*pnt == '\0') return pnt;
-
-  quotechar = *pnt++;
-  pnt1 = newlabel;
-  while(*pnt && *pnt != quotechar && pnt[-1] != '\\')
-    {
-      /*
-       * Quote the character if we need to.
-       */
-      if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']')
-	*pnt1++ = '\\';
-
-      *pnt1++ = *pnt++;
-    }
-  *pnt1++ = '\0';
-
-  pnt2 = (char *) malloc(strlen(newlabel) + 1);
-  strcpy(pnt2, newlabel);
-  *labl = pnt2;
-
-  /*
-   * Skip over last quote, and whitespace.
-   */
-  pnt++;
-  pnt = skip_whitespace(pnt);
-  return pnt;
-}
+    char quote_char;
+    char newlabel [1024];
+    char * pnt1;
X 
-static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
-{
-  struct kconfig * kcfg;
-  int index = 1;
+    /* advance to the open quote */
+    for ( ; ; )
+    {
+	if ( *pnt == '\0' )
+	    return pnt;
+	quote_char = *pnt++;
+	if ( quote_char == '"' || quote_char == '\'' )
+	    break;
+    }
X 
-  /*
-   * Choices appear in pairs of strings.  The parse is fairly trivial.
-   */
-  while(1)
-    {
-      pnt = skip_whitespace(pnt);
-      if(*pnt == '\0') break;
-
-      kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
-      memset(kcfg, 0, sizeof(struct kconfig));
-      kcfg->tok = tok_choice;
-      if( clast != NULL )
-	{
-	  clast->next = kcfg;
-	  clast = kcfg;
-	}
-      else
-	{
-	  clast = config = kcfg;
-	}
+    /* copy into an intermediate buffer */
+    pnt1 = newlabel;
+    for ( ; ; )
+    {
+	if ( *pnt == '\0' )
+	    syntax_error( "unterminated quoted string" );
+	if ( *pnt == quote_char && pnt[-1] != '\\' )
+	    break;
X 
-      pnt = get_string(pnt, &kcfg->label);
-      pnt = skip_whitespace(pnt);
-      pnt = get_string(pnt, &kcfg->optionname);
-      kcfg->choice_label = choice_kcfg;
-      kcfg->choice_value = index++;
-      if( strcmp(kcfg->label, choice_kcfg->value) == 0 )
-	choice_kcfg->choice_value = kcfg->choice_value;
+	/* copy the character, quoting if needed */
+	if ( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']' )
+	    *pnt1++ = '\\';
+	*pnt1++ = *pnt++;
X     }
-    
+
+    /* copy the label into a permanent location */
+    *pnt1++ = '\0';
+    *label = (char *) malloc( pnt1 - newlabel );
+    memcpy( *label, newlabel, pnt1 - newlabel );
+
+    /* skip over last quote and next whitespace */
+    pnt++;
+    while ( *pnt == ' ' || *pnt == '\t' )
+	pnt++;
X     return pnt;
X }
X 
X 
X /*
- * This function grabs one text token from the input buffer
- * and returns a pointer to a copy of just the identifier.
- * This can be either a variable name (i.e. CONFIG_NET),
- * or it could be the default value for the option.
+ * Tokenize an 'if' statement condition.
X  */
-static char * get_string(char *pnt, char ** labl)
+static struct condition * tokenize_if( const char * pnt )
X {
-  char newlabel[1024];
-  char * pnt1;
-  char * pnt2;
+    struct condition * list;
+    struct condition * last;
X 
-  if (*pnt == '\0') return pnt;
+    /* eat the open bracket */
+    while ( *pnt == ' ' || *pnt == '\t' )
+	pnt++;
+    if ( *pnt != '[' )
+	syntax_error( "bad 'if' condition" );
+    pnt++;
X 
-  pnt1 = newlabel;
-  while(*pnt && *pnt != ' ' && *pnt != '\t')
+    list = last = NULL;
+    for ( ; ; )
X     {
-      *pnt1++ = *pnt++;
+	struct condition * cond;
+
+	/* advance to the next token */
+	while ( *pnt == ' ' || *pnt == '\t' )
+	    pnt++;
+	if ( *pnt == '\0' )
+	    syntax_error( "unterminated 'if' condition" );
+	if ( *pnt == ']' )
+	    return list;
+
+	/* allocate a new token */
+	cond = malloc( sizeof(*cond) );
+	memset( cond, 0, sizeof(*cond) );
+	if ( last == NULL )
+	    { list = last = cond; }
+	else
+	    { last->next = cond; last = cond; }
+
+	/* determine the token value */
+	if ( *pnt == '-' && pnt[1] == 'a' )
+	    { cond->op = op_and;  pnt += 2; continue; }
+
+	if ( *pnt == '-' && pnt[1] == 'o' )
+	    { cond->op = op_or;   pnt += 2; continue; }
+
+	if ( *pnt == '!' && pnt[1] == '=' )
+	    { cond->op = op_neq;  pnt += 2; continue; }
+
+	if ( *pnt == '=' )
+	    { cond->op = op_eq;   pnt += 1; continue; }
+
+	if ( *pnt == '!' )
+	    { cond->op = op_bang; pnt += 1; continue; }
+
+	if ( *pnt == '"' )
+	{
+	    const char * word;
+
+	    /* advance to the word */
+	    pnt++;
+	    if ( *pnt == '$' )
+		{ cond->op = op_variable; pnt++; }
+	    else
+		{ cond->op = op_constant; }
+
+	    /* find the end of the word */
+	    word = pnt;
+	    for ( ; ; )
+	    {
+		if ( *pnt == '\0' )
+		    syntax_error( "unterminated double quote" );
+		if ( *pnt == '"' )
+		    break;
+		pnt++;
+	    }
+
+	    /* store a copy of this word */
+	    {
+		char * str = malloc( pnt - word + 1 );
+		memcpy( str, word, pnt - word );
+		str [pnt - word] = '\0';
+		cond->str = str;
+	    }
+
+	    pnt++;
+	    continue;
+	}
+
+	/* unknown token */
+	syntax_error( "bad if condition" );
X     }
-  *pnt1++ = '\0';
+}
+
X 
-  pnt2 = (char *) malloc(strlen(newlabel) + 1);
-  strcpy(pnt2, newlabel);
-  *labl = pnt2;
X 
-  if( *pnt ) pnt++;
-  return pnt;
+/*
+ * Tokenize a choice list.  Choices appear as pairs of strings;
+ * note that I am parsing *inside* the double quotes.  Ugh.
+ */
+static const char * tokenize_choices( struct kconfig * cfg_choose,
+    const char * pnt )
+{
+    for ( ; ; )
+    {
+	struct kconfig * cfg;
+
+	/* skip whitespace */
+	while ( *pnt == ' ' || *pnt == '\t' )
+	    pnt++;
+	if ( *pnt == '\0' )
+	    return pnt;
+
+	/* allocate a new kconfig line */
+	cfg = malloc( sizeof(*cfg) );
+	memset( cfg, 0, sizeof(*cfg) );
+	if ( config_last == NULL )
+	    { config_last = config_list = cfg; }
+	else
+	    { config_last->next = cfg; config_last = cfg; }
+
+	/* fill out the line */
+	cfg->token      = token_choice_item;
+	cfg->cfg_parent = cfg_choose;
+	pnt = get_string( pnt, &cfg->label );
+	while ( *pnt == ' ' || *pnt == '\t' )
+	    pnt++;
+	pnt = get_string( pnt, &cfg->optionname );
+    }
+
+    return pnt;
X }
X 
X 
+
+
+
X /*
- * Top level parse function.  Input pointer is one complete line from config.in
- * and the result is that we create a token that describes this line
- * and insert it into our linked list.
+ * Tokenize one line.
X  */
-void parse(char * pnt) {
-  enum token tok;
-  struct kconfig * kcfg;
-  char tmpbuf[24],fake_if[1024];
+static void tokenize_line( const char * pnt )
+{
+    static struct kconfig * last_menuoption = NULL;
+    enum e_token token;
+    struct kconfig * cfg;
X 
-  /*
-   * Ignore comments and leading whitespace.
-   */
+    /* skip white space */
+    while ( *pnt == ' ' || *pnt == '\t' )
+	pnt++;
X 
-  pnt = skip_whitespace(pnt);
-  while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
-  if(! *pnt ) return;
-  if( *pnt == '#' ) return;
+    /*
+     * categorize the next token
+     */
X 
-  /*
-   * Now categorize the next token.
-   */
-  tok = tok_unknown;
-  if      (strncmp(pnt, "mainmenu_name", 13) == 0) 
-    {
-      tok = tok_menuname;
-      pnt += 13;
-    }
-  else if      (strncmp(pnt, "source", 6) == 0) 
-    {
-      pnt += 7;
-      pnt = skip_whitespace(pnt);
-      do_source(pnt);
-      return;
-    }
-  else if (strncmp(pnt, "mainmenu_option", 15) == 0) 
-    {
-      menus_seen++;
-      tok = tok_menuoption;
-      pnt += 15;
-    }
-  else if (strncmp(pnt, "comment", 7) == 0) 
-    {
-      tok = tok_comment;
-      pnt += 7;
-    }
-  else if (strncmp(pnt, "choice", 6) == 0) 
-    {
-      tok = tok_choose;
-      pnt += 6;
-    }
-  else if (strncmp(pnt, "define_bool", 11) == 0) 
-    {
-      tok = tok_define;
-      pnt += 11;
-    }
-  else if (strncmp(pnt, "bool", 4) == 0) 
-    {
-      tok = tok_bool;
-      pnt += 4;
-    }
-  else if (strncmp(pnt, "tristate", 8) == 0) 
-    {
-      tok = tok_tristate;
-      pnt += 8;
-    }
-  else if (strncmp(pnt, "dep_tristate", 12) == 0) 
-    {
-      tok = tok_dep_tristate;
-      pnt += 12;
-    }
-  else if (strncmp(pnt, "int", 3) == 0) 
-    {
-      tok = tok_int;
-      pnt += 3;
-    }
-  else if (strncmp(pnt, "hex", 3) == 0) 
-    {
-      tok = tok_hex;
-      pnt += 3;
-    }
-  else if (strncmp(pnt, "string", 6) == 0) 
-    {
-      tok = tok_string;
-      pnt += 6;
-    }
-  else if (strncmp(pnt, "if", 2) == 0) 
-    {
-      tok = tok_if;
-      pnt += 2;
-    }
-  else if (strncmp(pnt, "else", 4) == 0) 
-    {
-      tok = tok_else;
-      pnt += 4;
-    }
-  else if (strncmp(pnt, "fi", 2) == 0) 
-    {
-      tok = tok_fi;
-      pnt += 2;
-    }
-  else if (strncmp(pnt, "endmenu", 7) == 0) 
+#define match_token(t, s) \
+    if (strncmp(pnt, s, strlen(s)) == 0) { token = t; pnt += strlen(s); break; }
+
+    token = token_UNKNOWN;
+    switch ( *pnt )
X     {
-      tok = tok_endmenu;
-      pnt += 7;
+    default:
+	break;
+
+    case '#':
+    case '\0':
+	return;
+
+    case 'b':
+	match_token( token_bool, "bool" );
+	break;
+
+    case 'c':
+	match_token( token_choice_header, "choice"  );
+	match_token( token_comment, "comment" );
+	break;
+
+    case 'd':
+	match_token( token_define_bool, "define_bool" );
+	match_token( token_dep_tristate, "dep_tristate" );
+	break;
+
+    case 'e':
+	match_token( token_else, "else" );
+	match_token( token_endmenu, "endmenu" );
+	break;
+
+    case 'f':
+	match_token( token_fi, "fi" );
+	break;
+
+    case 'h':
+	match_token( token_hex, "hex" );
+	break;
+
+    case 'i':
+	match_token( token_if, "if" );
+	match_token( token_int, "int" );
+	break;
+
+    case 'm':
+	match_token( token_mainmenu_name, "mainmenu_name" );
+	match_token( token_mainmenu_option, "mainmenu_option" );
+	break;
+
+    case 's':
+	match_token( token_source, "source" );
+	match_token( token_string, "string" );
+	break;
+
+    case 't':
+	match_token( token_then, "then" );
+	match_token( token_tristate, "tristate" );
+	break;
+
+    case 'u':
+	match_token( token_unset, "unset" );
+	break;
X     }
X 
-  if( tok == tok_unknown)
+#undef match_token
+
+    if ( token == token_source )
X     {
-      if( clast != NULL && clast->tok == tok_if 
-	  && strcmp(pnt,"then") == 0) return;
-      if( current_file != NULL )
-	fprintf(stderr, "unknown command=%s(%s %d)\n", pnt,
-		current_file, lineno);
-      else
-	fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno);
-      return;
+	while ( *pnt == ' ' || *pnt == '\t' )
+	    pnt++;
+	do_source( pnt );
+	return;
X     }
X 
-  /*
-   * Allocate memory for this item, and attach it to the end of the linked
-   * list.
-   */
-  kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
-  memset(kcfg, 0, sizeof(struct kconfig));
-  kcfg->tok = tok;
-  if( clast != NULL )
+    if ( token == token_then )
X     {
-      clast->next = kcfg;
-      clast = kcfg;
+	if ( config_last != NULL && config_last->token == token_if )
+	    return;
+	syntax_error( "bogus 'then'" );
X     }
-  else
+
+    if ( token == token_unset )
X     {
-      clast = config = kcfg;
+	fprintf( stderr, "Ignoring 'unset' command\n" );
+	return;
X     }
X 
-  pnt = skip_whitespace(pnt);
+    if ( token == token_UNKNOWN )
+	syntax_error( "unknown command" );
X 
-  /*
-   * Now parse the remaining parts of the option, and attach the results
-   * to the structure.
-   */
-  switch (tok)
-    {
-    case tok_choose:
-      pnt = get_qstring(pnt, &kcfg->label);
-      pnt = get_qstring(pnt, &kcfg->optionname);
-      pnt = get_string(pnt, &kcfg->value);
-      /*
-       * Now we need to break apart the individual options into their
-       * own configuration structures.
-       */
-      parse_choices(kcfg, kcfg->optionname);
-      free(kcfg->optionname);
-      sprintf(tmpbuf, "tmpvar_%d", choose_number++);
-      kcfg->optionname = strdup(tmpbuf);
-      break;
-    case tok_define:
-      pnt = get_string(pnt, &kcfg->optionname);
-      if(*pnt == 'y' || *pnt == 'Y' ) kcfg->value = "1";
-      if(*pnt == 'n' || *pnt == 'N' ) kcfg->value = "0";
-      if(*pnt == 'm' || *pnt == 'M' ) kcfg->value = "2";
-      break;
-    case tok_menuname:
-      pnt = get_qstring(pnt, &kcfg->label);
-      break;
-    case tok_bool:
-    case tok_tristate:
-      pnt = get_qstring(pnt, &kcfg->label);
-      pnt = get_string(pnt, &kcfg->optionname);
-      break;
-    case tok_int:
-    case tok_hex:
-    case tok_string:
-      pnt = get_qstring(pnt, &kcfg->label);
-      pnt = get_string(pnt, &kcfg->optionname);
-      pnt = get_string(pnt, &kcfg->value);
-      break;
-    case tok_dep_tristate:
-      pnt = get_qstring(pnt, &kcfg->label);
-      pnt = get_string(pnt, &kcfg->optionname);
-      pnt = skip_whitespace(pnt);
+    /*
+     * Allocate an item.
+     */
+    cfg = malloc( sizeof(*cfg) );
+    memset( cfg, 0, sizeof(*cfg) );
+    if ( config_last == NULL )
+	{ config_last = config_list = cfg; }
+    else
+	{ config_last->next = cfg; config_last = cfg; }
X 
-      if ( ( pnt[0] == 'y'  || pnt[0] == 'm' || pnt[0] == 'n'  )
-      &&   ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) ) {
-	if      ( pnt[0] == 'y' ) kcfg->depend.str = strdup( "CONSTANT_Y" );
-	else if ( pnt[0] == 'm' ) kcfg->depend.str = strdup( "CONSTANT_M" );
-	else                      kcfg->depend.str = strdup( "CONSTANT_N" );
-	pnt++;
-      } else if ( *pnt == '$' ) {
+    /*
+     * Tokenize the arguments.
+     */
+    while ( *pnt == ' ' || *pnt == '\t' )
X 	pnt++;
-	pnt = get_string(pnt, &kcfg->depend.str);
-      } else {
-	fprintf( stderr, "Can't handle dep_tristate condition\n" );
-	exit( 1 );
-      }
-
-      /*
-       * Create a conditional for this object's dependency.
-       *
-       * We can't use "!= n" because this is internally converted to "!= 0"
-       * and if UMSDOS depends on MSDOS which depends on FAT, then when FAT
-       * is disabled MSDOS has 16 added to its value, making UMSDOS fully
-       * available.  Whew.
-       *
-       * This is more of a hack than a fix.  Nested "if" conditionals are
-       * probably affected too - that +/- 16 affects things in too many
-       * places.  But this should do for now.
-       */
-      sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
-	      	kcfg->depend.str,kcfg->depend.str);
-      kcfg->cond = parse_if(fake_if);
-      if(kcfg->cond == NULL )
+
+    cfg->token = token;
+    switch ( token )
+    {
+    default:
+	syntax_error( "unknown token" );
+
+    case token_bool:
+    case token_tristate:
+	pnt = get_qstring ( pnt, &cfg->label      );
+	pnt = get_string  ( pnt, &cfg->optionname );
+	break;
+
+    case token_choice_header:
X 	{
-	  exit(1);
+	    static int choose_number = 0;
+	    char * choice_list;
+
+	    pnt = get_qstring ( pnt, &cfg->label  );
+	    pnt = get_qstring ( pnt, &choice_list );
+	    pnt = get_string  ( pnt, &cfg->value  );
+
+	    cfg->optionname = malloc( 32 );
+	    sprintf( cfg->optionname, "tmpvar_%d", choose_number++ );
+
+	    tokenize_choices( cfg, choice_list );
+	    free( choice_list );
X 	}
-      break;
-    case tok_comment:
-      pnt = get_qstring(pnt, &kcfg->label);
-      if( koption != NULL )
-	{
-	  pnt = get_qstring(pnt, &kcfg->label);
-	  koption->label = kcfg->label;
-	  koption = NULL;
+	break;
+
+    case token_comment:
+	pnt = get_qstring(pnt, &cfg->label);
+	if ( last_menuoption != NULL )
+	{
+	    pnt = get_qstring(pnt, &cfg->label);
+	    last_menuoption->label = cfg->label;
+	    last_menuoption = NULL;
+	}
+	break;
+
+    case token_define_bool:
+	pnt = get_string( pnt, &cfg->optionname );
+#if ! defined(BUG_COMPATIBLE)
+	while ( *pnt == ' ' || *pnt == '\t' )
+	    pnt++;
+#endif
+	if      ( *pnt == 'n' || *pnt == 'N' ) cfg->value = "0";
+	else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = "1";
+	else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = "2";
+	else
+	{
+#if ! defined(BUG_COMPATIBLE)
+	    syntax_error( "unknown define_bool value" );
+#else
+	    /*
+	     * This ought to give the same output as printf'ing
+	     * through the null pointer ... I don't want to be
+	     * SIGSEGV compatible!
+	     */
+	    cfg->value = "(null)";
+#endif
X 	}
-      break;
-    case tok_menuoption:
- if( strncmp(pnt, "next_comment", 12) == 0)
+	break;
+
+    case token_dep_tristate:
+	pnt = get_qstring ( pnt, &cfg->label      );
+	pnt = get_string  ( pnt, &cfg->optionname );
+
+	while ( *pnt == ' ' || *pnt == '\t' )
+	    pnt++;
+
+	if ( ( pnt[0] == 'Y'  || pnt[0] == 'M' || pnt[0] == 'N'
+	||     pnt[0] == 'y'  || pnt[0] == 'm' || pnt[0] == 'n'  )
+	&&   ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) )
X 	{
-	  koption = kcfg;
+	    /* dep_tristate 'foo' CONFIG_FOO m */
+	    if      ( pnt[0] == 'Y' || pnt[0] == 'y' )
+		cfg->depend = strdup( "CONSTANT_Y" );
+	    else if ( pnt[0] == 'M' || pnt[0] == 'm' )
+		cfg->depend = strdup( "CONSTANT_M" );
+	    else
+		cfg->depend = strdup( "CONSTANT_N" );
+	    pnt++;
X 	}
-      else
+	else if ( *pnt == '$' )
X 	{
-	  pnt = get_qstring(pnt, &kcfg->label);
+	    pnt++;
+	    pnt = get_string( pnt, &cfg->depend );
X 	}
-      break;
-    case tok_else:
-    case tok_fi:
-    case tok_endmenu:
-      break;
-    case tok_if:
-      /*
-       * Conditionals are different.  For the first level parse, only
-       * tok_if and tok_dep_tristate items have a ->cond chain attached.
-       */
-      kcfg->cond = parse_if(pnt);
-      if(kcfg->cond == NULL )
+	else
X 	{
-	  exit(1);
+	    syntax_error( "can't handle dep_tristate condition" );
X 	}
-      break;
-    default:
-      exit(0);
-    }
-    
-    return;
-}
X 
-/*
- * Simple function to dump to the screen what the condition chain looks like.
- */
-void dump_if(struct condition * cond)
-{
-  printf(" ");
-  while(cond != NULL )
-    {
-      switch(cond->op){
-      case op_eq:
-	printf(" = ");
-	break;
-      case op_bang:
-	printf(" ! ");
-	break;
-      case op_neq:
-	printf(" != ");
+	/*
+	 * Create a conditional for this object's dependency.
+	 */
+	{
+	    char fake_if [1024];
+	    sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
+		cfg->depend, cfg->depend );
+	    cfg->cond = tokenize_if( fake_if );
+	}
X 	break;
-      case op_and:
-	printf(" -a ");
+
+    case token_else:
+    case token_endmenu:
+    case token_fi:
X 	break;
-      case op_lparen:
-	printf("(");
+
+    case token_hex:
+    case token_int:
+    case token_string:
+	pnt = get_qstring ( pnt, &cfg->label      );
+	pnt = get_string  ( pnt, &cfg->optionname );
+	pnt = get_string  ( pnt, &cfg->value      );
X 	break;
-      case op_rparen:
-	printf(")");
+
+    case token_if:
+	cfg->cond = tokenize_if( pnt );
X 	break;
-      case op_variable:
-	printf("$%s", cond->variable.str);
+
+    case token_mainmenu_name:
+	pnt = get_qstring( pnt, &cfg->label );
X 	break;
-      case op_constant:
-	printf("'%s'", cond->variable.str);
+
+    case token_mainmenu_option:
+	if ( strncmp( pnt, "next_comment", 12 ) == 0 )
+	    last_menuoption = cfg;
+	else
+	    pnt = get_qstring( pnt, &cfg->label );
X 	break;
-      default:
-        break;
-      }
-      cond = cond->next;
X     }
X 
-  printf("\n");
+    return;
X }
X 
-static int do_source(char * filename)
+
+
+/*
+ * Implement the "source" command.
+ */
+static void do_source( const char * filename )
X {
-  char buffer[1024];
-  int  offset;
-  int old_lineno;
-  char * old_file = 0;		/* superfluous, just for gcc */
-  char * pnt;
-  FILE * infile;
-
-  if( strcmp(filename, "-") == 0 )
-    infile = stdin;
-  else
-    infile = fopen(filename,"r");
-
-  /*
-   * If our cwd was in the scripts directory, we might have to go up one
-   * to find the sourced file.
-   */
-  if(!infile) {
-    strcpy (buffer, "../");
-    strcat (buffer, filename);
-    infile = fopen(buffer,"r");
-  }
-
-  if(!infile) {
-    fprintf(stderr,"Unable to open file %s\n", filename);
-    return 1;
-  }
-  old_lineno = lineno;
-  lineno = 0;
-  if( infile != stdin ) {
-    old_file = current_file;
-    current_file = filename;
-  }
-  offset = 0;
-  while(1)
-    {
-      fgets(&buffer[offset], sizeof(buffer) - offset, infile);
-      if(feof(infile)) break;
-
-      /*
-       * Strip the trailing return character.
-       */
-      pnt = buffer + strlen(buffer) - 1;
-      if( *pnt == '\n') *pnt-- = 0;
-      lineno++;
-      if( *pnt == '\\' )
-	{
-	  offset = pnt - buffer;
-	}
-      else
-	{
-	  parse(buffer);
-	  offset = 0;
-	}
+    char buffer [1024];
+    FILE * infile;
+    const char * old_file;
+    int old_lineno;
+    int offset;
+
+    /* open the file */
+    if ( strcmp( filename, "-" ) == 0 )
+	infile = stdin;
+    else
+	infile = fopen( filename, "r" );
+
+    /* if that failed, try ../filename */
+    if ( infile == NULL )
+    {
+	sprintf( buffer, "../%s", filename );
+	infile = fopen( buffer, "r" );
X     }
-  if( infile != stdin ) {
-    fclose(infile);
-    current_file = old_file;
-  }
-  lineno = old_lineno;
-  return 0;
-}
X 
-int main(int argc, char * argv[])
-{
-#if 0
-  char buffer[1024];
-  char * pnt;
-  struct kconfig * cfg;
-  int    i;
+    if ( infile == NULL )
+    {
+	sprintf( buffer, "unable to open %s", filename );
+#if defined(BUG_COMPATIBLE)
+	fprintf( stderr, "%s\n", buffer );
+	return;
+#else
+	syntax_error( buffer );
X #endif
+    }
+
+    /* push the new file name and line number */
+    old_file     = current_file;
+    old_lineno   = lineno;
+    current_file = filename;
+    lineno       = 0;
X 
-  /*
-   * Read stdin to get the top level script.
-   */
-  do_source("-");
-
-  if( menus_seen == 0 )
-    {
-      fprintf(stderr,"The config.in file for this platform does not support\n");
-      fprintf(stderr,"menus.\n");
-      exit(1);
-    }
-  /*
-   * Input file is now parsed.  Next we need to go through and attach
-   * the correct conditions to each of the actual menu items and kill
-   * the if/else/endif tokens from the list.  We also flag the menu items
-   * that have other things that depend upon its setting.
-   */
-  fix_conditionals(config);
-
-  /*
-   * Finally, we generate the wish script.
-   */
-  dump_tk_script(config);
-
-#if 0
-  /*
-   * Now dump what we have so far.  This is only for debugging so that
-   * we can display what we think we have in the list.
-   */
-  for(cfg = config; cfg; cfg = cfg->next)
+    /* read and process lines */
+    for ( offset = 0; ; )
X     {
+	char * pnt;
X 
-      if(cfg->cond != NULL && cfg->tok != tok_if)
-	dump_if(cfg->cond);
+	/* read a line */
+	fgets( buffer + offset, sizeof(buffer) - offset, infile );
+	if ( feof( infile ) )
+	    break;
+	lineno++;
X 
-      switch(cfg->tok)
-	{
-	case tok_menuname:
-	  printf("main_menuname ");
-	  break;
-	case tok_bool:
-	  printf("bool ");
-	  break;
-	case tok_tristate:
-	  printf("tristate ");
-	  break;
-	case tok_dep_tristate:
-	  printf("dep_tristate ");
-	  break;
-	case tok_int:
-	  printf("int ");
-	  break;
-	case tok_hex:
-	  printf("hex ");
-	  break;
-	case tok_string:
-	  printf("istring ");
-	  break;
-	case tok_comment:
-	  printf("comment ");
-	  break;
-	case tok_menuoption:
-	  printf("menuoption ");
-	  break;
-	case tok_else:
-	  printf("else");
-	  break;
-	case tok_fi:
-	  printf("fi");
-	  break;
-	case tok_if:
-	  printf("if");
-	  break;
-	default:
-	}
+	/* strip the trailing return character */
+	pnt = buffer + strlen(buffer) - 1;
+	if ( *pnt == '\n' )
+	    *pnt-- = '\0';
X 
-      switch(cfg->tok)
+	/* eat \ NL pairs */
+	if ( *pnt == '\\' )
X 	{
-	case tok_menuoption:
-	case tok_comment:
-	case tok_menuname:
-	  printf("%s\n", cfg->label);
-	  break;
-	case tok_bool:
-	case tok_tristate:
-	case tok_dep_tristate:
-	case tok_int:
-	case tok_hex:
-	case tok_string:
-	  printf("%s %s\n", cfg->label, cfg->optionname);
-	  break;
-	case tok_if:
-	  dump_if(cfg->cond);
-	  break;
-	case tok_nop:
-	case tok_endmenu:
-	  break;
-	default:
-	  printf("\n");
+	    offset = pnt - buffer;
+	    continue;
X 	}
+
+	/* tokenize this line */
+	tokenize_line( buffer );
+	offset = 0;
X     }
-#endif
X 
-  return 0;
+    /* that's all, folks */
+    if ( infile != stdin )
+	fclose( infile );
+    current_file = old_file;
+    lineno       = old_lineno;
+    return;
+}
+
+
X 
+/*
+ * Main program.
+ */
+int main( int argc, const char * argv [] )
+{
+    do_source        ( "-"         );
+    fix_conditionals ( config_list );
+    dump_tk_script   ( config_list );
+    return 0;
X }
diff -u --recursive --new-file v2.2.0-pre8/linux/scripts/tkparse.h linux/scripts/tkparse.h
--- v2.2.0-pre8/linux/scripts/tkparse.h	Tue Jan 19 11:32:54 1999
+++ linux/scripts/tkparse.h	Wed Jan 20 10:05:49 1999
@@ -1,82 +1,112 @@
+/*
+ * tkparse.h
+ */
X 
-enum token {
-  tok_menuname, 
-  tok_menuoption, 
-  tok_comment, 
-  tok_bool, 
-  tok_tristate, 
-  tok_dep_tristate,
-  tok_nop,
-  tok_if, 
-  tok_else, 
-  tok_fi, 
-  tok_int,
-  tok_hex,
-  tok_string,
-  tok_define,
-  tok_choose,
-  tok_choice,
-  tok_endmenu,
-  tok_unknown
-};
+/*
+ * Define this symbol to generate exactly the same output, byte for byte,
+ * as the previous version of xconfig.  I need to do this to make sure I
+ * I don't break anything in my moby edit. -- mec
+ */
X 
-enum operator {
-  op_eq,
-  op_neq,
-  op_and,
-  op_and1,
-  op_or,
-  op_bang,
-  op_lparen,
-  op_rparen,
-  op_variable,
-  op_kvariable,
-  op_shellcmd,
-  op_constant,
-  op_nuked
+#define BUG_COMPATIBLE
+
+/*
+ * Token types (mostly statement types).
+ */
+
+enum e_token
+{
+    token_UNKNOWN,
+    token_bool, 
+    token_choice_header,
+    token_choice_item,
+    token_comment, 
+    token_define_bool,
+    token_dep_tristate,
+    token_else, 
+    token_endmenu,
+    token_fi, 
+    token_hex,
+    token_if, 
+    token_int,
+    token_mainmenu_name, 
+    token_mainmenu_option, 
+    token_source,
+    token_string,
+    token_then,
+    token_tristate, 
+    token_unset,
X };
X 
-union var
+/*
+ * Operator types for conditionals.
+ */
+
+enum operator
X {
-  char * str;
-  struct kconfig * cfg;
+    op_eq,
+    op_neq,
+    op_and,
+    op_and1,
+    op_or,
+    op_bang,
+    op_lparen,
+    op_rparen,
+    op_constant,
+    op_variable,
+    op_kvariable,
+    op_nuked
X };
X 
+/*
+ * Conditions come in linked lists.
+ * Some operators take strings:
+ *
+ *   op_constant   "foo"
+ *   op_variable   "$ARCH", "$CONFIG_PMAC"
+ *   op_kvariable  "$CONFIG_EXPERIMENTAL"
+ *
+ * Most "$..." constructs refer to a variable which is defined somewhere
+ * in the script, so they become op_kvariable's instead.  Note that it
+ * is legal to test variables which are never defined, such as variables
+ * that are meaningful only on other architectures.
+ */
+
X struct condition
X {
-  struct condition * next;
-  enum operator op;
-  union var variable;
+    struct condition * next;
+    enum operator op;
+    const char * str;		/* op_constant, op_variable */
+    struct kconfig * cfg;	/* op_kvariable */
X };
X 
-#define GLOBAL_WRITTEN  1
-#define CFG_DUP 	2
-#define UNSAFE		4
+/*
+ * A statement from a config.in file
+ */
X 
X struct kconfig
X {
-  struct kconfig 	* next;
-  int 			  flags;
-  enum 			  token tok;
-  int   		  menu_number;
-  int   		  menu_line;
-  int   		  submenu_start;
-  int   		  submenu_end;
-  char 			* optionname;
-  char 			* label;
-  char 			* value;
-  int   		  choice_value;
-  struct kconfig        * choice_label;
-  union var 		  depend;
-  struct condition 	* cond;
+    struct kconfig *	next;
+    enum e_token	token;
+    char *		optionname;
+    char *		label;
+    char *		value;
+    struct condition *	cond;
+    char *		depend;		/* token_dep_tristate */
+    struct kconfig *	cfg_parent;	/* token_choice_item */
+
+    /* used only in tkgen.c */
+    char		global_written;
+    int			menu_number;
+    int			menu_line;
+    struct kconfig *	menu_next;
X };
X 
-extern struct kconfig * config;
-extern struct kconfig * clast;
-extern struct kconfig * koption;
+
X 
X /*
X  * Prototypes
X  */
-void fix_conditionals(struct kconfig * scfg);	/* tkcond.c */
-void dump_tk_script(struct kconfig *scfg);	/* tkgen.c  */
+
+extern void fix_conditionals ( struct kconfig * scfg );		/* tkcond.c */
+extern void dump_tk_script   ( struct kconfig * scfg );		/* tkgen.c  */
SHAR_EOF
true || echo 'restore of patch-2.2.0-pre9 failed'
echo 'File patch-2.2.0-pre9 is complete' &&
chmod 644 patch-2.2.0-pre9 ||
echo 'restore of patch-2.2.0-pre9 failed'
Cksum="`cksum < 'patch-2.2.0-pre9'`"
if ! test " 778691712   838284" = "$Cksum"
then
	echo 'patch-2.2.0-pre9: original Checksum  778691712   838284, current one' "$Cksum" 
	rm -f _shar_wnt_.tmp
	rm -f _shar_seq_.tmp
	exit 1
fi
rm -f _shar_wnt_.tmp
fi
rm -f _shar_seq_.tmp
echo 'You have unpacked the last part.'